Android逆向--Android11 密码锁屏源码分析

1.打开应用的密码锁屏页面
执行
adb shell
dumpsys window | grep mFoc
得到当前的页面对应的java文件是位于AOSP源码下的vendor\mediatek\proprietary\packages\apps\MtkSettings\src\com\android\settings\password\ChooseLockPassword.java文件
两次输入密码后点击(确认/comfirm)按钮时会触发点击事件ChooseLockPassword子类ChooseLockPasswordFragment中的handleNext()方法

public void handleNext() {
        if (mSaveAndFinishWorker != null) return;
        // TODO(b/120484642): This is a point of entry for passwords from the UI
        final Editable passwordText = mPasswordEntry.getText();
        if (TextUtils.isEmpty(passwordText)) {
            return;
        }
        mChosenPassword = mIsAlphaMode ? LockscreenCredential.createPassword(passwordText)
                : LockscreenCredential.createPin(passwordText);
        if (mUiStage == ChooseLockPassword.ChooseLockPasswordFragment.Stage.Introduction) {
            if (validatePassword(mChosenPassword)) {
                mFirstPassword = mChosenPassword;
                mPasswordEntry.setText("");
                updateStage(ChooseLockPassword.ChooseLockPasswordFragment.Stage.NeedToConfirm);
            } else {
                mChosenPassword.zeroize();
            }
        } else if (mUiStage == ChooseLockPassword.ChooseLockPasswordFragment.Stage.NeedToConfirm) {
            //确认两次密码是否一致,开始调用startSaveAndFinish方法
            if (mChosenPassword.equals(mFirstPassword)) {
                startSaveAndFinish();
            } else {
                CharSequence tmp = mPasswordEntry.getText();
                if (tmp != null) {
                    Selection.setSelection((Spannable) tmp, 0, tmp.length());
                }
                updateStage(ChooseLockPassword.ChooseLockPasswordFragment.Stage.ConfirmWrong);
                mChosenPassword.zeroize();
            }
        }
    }

2.startSaveAndFinish()

    private void startSaveAndFinish() {
        if (mSaveAndFinishWorker != null) {
            Log.w(TAG, "startSaveAndFinish with an existing SaveAndFinishWorker.");
            return;
        }

        mPasswordEntryInputDisabler.setInputEnabled(false);
        setNextEnabled(false);

        mSaveAndFinishWorker = new ChooseLockPassword.SaveAndFinishWorker();
        mSaveAndFinishWorker.setListener(this);

        getFragmentManager().beginTransaction().add(mSaveAndFinishWorker,
                FRAGMENT_TAG_SAVE_AND_FINISH).commit();
        getFragmentManager().executePendingTransactions();

        final Intent intent = getActivity().getIntent();
        final boolean required = intent.getBooleanExtra(
                EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
        if (mUnificationProfileId != UserHandle.USER_NULL) {
            try (LockscreenCredential profileCredential = (LockscreenCredential)
                    intent.getParcelableExtra(EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL)) {
                mSaveAndFinishWorker.setProfileToUnify(mUnificationProfileId,
                        profileCredential);
            }
        }
        //继续下一步
        mSaveAndFinishWorker.start(mLockPatternUtils, required, mHasChallenge, mChallenge,
                mChosenPassword, mCurrentCredential, mUserId);
    }
  1. 进入SaveAndFinishWorker查看start()方法,这个内部类继承了SaveChosenLockWorkerBase类,代码里的start()是在SaveChosenLockWorkerBase中执行
 public void start(LockPatternUtils utils, boolean required,
                boolean hasChallenge, long challenge,
                LockscreenCredential chosenPassword, LockscreenCredential currentCredential,
                int userId) {
            prepare(utils, required, hasChallenge, challenge, userId);

            mChosenPassword = chosenPassword;
            mCurrentCredential = currentCredential != null ? currentCredential
                    : LockscreenCredential.createNone();
            mUserId = userId;
            //继续下一步
            start();
        }

4.SaveChosenLockWorkerBase.start()方法

 protected void start() {
        if (mBlocking) {
            //继续下一步  saveAndVerifyInBackground 看方法名就知道了,开始保存锁屏密码的操作了
            finish(saveAndVerifyInBackground().second);
        } else {
            new Task().execute();
        }
    }

5.SaveAndFinishWorker.saveAndVerifyInBackground()方法

 @Override
        protected Pair<Boolean, Intent> saveAndVerifyInBackground() {
            final boolean success = mUtils.setLockCredential(
                    mChosenPassword, mCurrentCredential, mUserId);
            if (success) {
                unifyProfileCredentialIfRequested();
            }
            Intent result = null;
            if (success && mHasChallenge) {
                byte[] token;
                try {
                    //mChosenPassword是新密码  mChallenge是原密码  mUserId通常是0
                    //mUtils是继承类SaveChosenLockWorkerBase里的参数,类名是LockPatternUtils
                    token = mUtils.verifyCredential(mChosenPassword, mChallenge, mUserId);
                } catch (RequestThrottledException e) {
                    token = null;
                }

                if (token == null) {
                    Log.e(TAG, "critical: no token returned for known good password.");
                }

                result = new Intent();
                result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
            }
            return Pair.create(success, result);
        }

6.setLockCredential()方法
位于源码中的frameworks/base/core/java/com/android/internal/widget/LockPatternUtils.java文件里

 public boolean setLockCredential(@NonNull LockscreenCredential newCredential,
            @NonNull LockscreenCredential savedCredential, int userHandle) {
        if (!hasSecureLockScreen() && newCredential.getType() != CREDENTIAL_TYPE_NONE) {
            throw new UnsupportedOperationException(
                    "This operation requires the lock screen feature.");
        }

        try {
            //通过LockSettingsService设置密码
            if (!getLockSettings().setLockCredential(newCredential, savedCredential, userHandle)) {
                return false;
            }
        } catch (RemoteException e) {
            throw new RuntimeException("Unable to save lock password", e);
        }
        return true;
    }

7.setLockCredential()方法
位于源码中的frameworks/base/services/core/java/com/android/server/locksettings/LockSettingsService.java文件里,后面就没关注过了

 @Override
    public boolean setLockCredential(LockscreenCredential credential,
            LockscreenCredential savedCredential, int userId) {

        if (!mHasSecureLockScreen
                && credential != null && credential.getType() != CREDENTIAL_TYPE_NONE) {
            throw new UnsupportedOperationException(
                    "This operation requires secure lock screen feature");
        }
        if (!hasPermission(PERMISSION) && !hasPermission(SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS)) {
            if (hasPermission(SET_INITIAL_LOCK) && savedCredential.isNone()) {
                // SET_INITIAL_LOCK can only be used if credential is not set.
            } else {
                throw new SecurityException(
                        "setLockCredential requires SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS or "
                                + PERMISSION);
            }
        }
        credential.validateBasicRequirements();

        final long identity = Binder.clearCallingIdentity();
        try {
            enforceFrpResolved();
            // When changing credential for profiles with unified challenge, some callers
            // will pass in empty credential while others will pass in the credential of
            // the parent user. setLockCredentialInternal() handles the formal case (empty
            // credential) correctly but not the latter. As a stopgap fix, convert the latter
            // case to the formal. The long-term fix would be fixing LSS such that it should
            // accept only the parent user credential on its public API interfaces, swap it
            // with the profile's random credential at that API boundary (i.e. here) and make
            // sure LSS internally does not special case profile with unififed challenge: b/80170828
            if (!savedCredential.isNone() && isProfileWithUnifiedLock(userId)) {
                // Verify the parent credential again, to make sure we have a fresh enough
                // auth token such that getDecryptedPasswordForTiedProfile() inside
                // setLockCredentialInternal() can function correctly.
                verifyCredential(savedCredential, mUserManager.getProfileParent(userId).id,
                        0 /* flags */);
                savedCredential.zeroize();
                savedCredential = LockscreenCredential.createNone();
            }
            synchronized (mSeparateChallengeLock) {
                if (!setLockCredentialInternal(credential, savedCredential,
                        userId, /* isLockTiedToParent= */ false)) {
                    scheduleGc();
                    return false;
                }
                setSeparateProfileChallengeEnabledLocked(userId, true, /* unused */ null);
                notifyPasswordChanged(credential, userId);
            }
            if (isCredentialSharableWithParent(userId)) {
                // Make sure the profile doesn't get locked straight after setting challenge.
                setDeviceUnlockedForUser(userId);
            }
            notifySeparateProfileChallengeChanged(userId);
            onPostPasswordChanged(credential, userId);
            scheduleGc();
            return true;
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值