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);
}
- 进入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);
}
}