本文以安卓5.1为例分析锁屏密码设置的流程。
由设置界面中设置密码可以看到以下文件。
packages/apps/Settings/src/com/android/settings/ChooseLockPassword.java
428 if (mUiStage == Stage.Introduction) {
429 errorMsg = validatePassword(pin);
430 if (errorMsg == null) {
431 mFirstPin = pin;
432 mPasswordEntry.setText("");
433 updateStage(Stage.NeedToConfirm);
434 }
435 } else if (mUiStage == Stage.NeedToConfirm) {
436 if (mFirstPin.equals(pin)) {
437 final boolean isFallback =
getActivity().getIntent().getBooleanExtra(
438 LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,false);
439 boolean wasSecureBefore = mLockPatternUtils.isSecure();
440 mLockPatternUtils.clearLock(isFallback);
441 final boolean required = getActivity().getIntent().getBooleanExtra(
442 EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
443 mLockPatternUtils.setCredentialRequiredToDecrypt(required);
//此处调用保存密码。进而查看mLockPatternUtils
444 mLockPatternUtils.saveLockPassword(pin, mRequestedQuality, isFallback);
445 getActivity().setResult(RESULT_FINISHED);
该文件中存在许多saveLockPassword的重载。我们看一下最终逻辑实现的重载函数
frameworks/base/core/java/com/android/internal/widget/LockPatternUtils.java
817 public void saveLockPassword(String password, int quality, boolean isFallback, int
userHandle) {
818 try {
819 DevicePolicyManager dpm = getDevicePolicyManager();
820 if (!TextUtils.isEmpty(password)) {
//此处进而设置setLockPassword 转而查看getLockSettings所实现的方法
821 getLockSettings().setLockPassword(password, userHandle);
822 int computedQuality = computePasswordQuality(password);
823
824 // Update the device encryption password.
825 if (userHandle == UserHandle.USER_OWNER
826 && LockPatternUtils.isDeviceEncryptionEnabled()) {
827 if (!isCredentialRequiredToDecrypt(true)) {
828 clearEncryptionPassword();
829 } else {
830 boolean numeric = computedQuality
831 == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
832 boolean numericComplex = computedQuality
833 == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLE
X;
834 int type = numeric || numericComplex ? StorageManager.CRYPT_TY
PE_PIN
getLockSettings(),与实际上是获取一个aidl的服务类型,我们应该看看该服务实现方法
frameworks/base/services/core/java/com/android/server/LockSettingsService.java
304 @Override
305 public void setLockPassword(String password, int userId) throws RemoteException {
306 checkWritePermission(userId);
307
308 maybeUpdateKeystore(password, userId);
309 //mStorage的writePasswordHash以及passwordToHash这两个方法具体实现我们来瞧一瞧
310 mStorage.writePasswordHash(mLockPatternUtils.passwordToHash(password, userId),
userId);
311 }
先看passwordToHash这个方法在
frameworks/base/core/java/com/android/internal/widget/LockPatternUtils.java
1086 public byte[] passwordToHash(String password, int userId) {
1087 if (password == null) {
1088 return null;
1089 }
1090 String algo = null;
1091 byte[] hashed = null;
1092 try {
//获取一个随机数并和密码明文相加,具体实现在同一个文件下自行查看
1093 byte[] saltedPassword = (password + getSalt(userId)).getBytes();
//计算sha1
1094 byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword);
//计算md5
1095 byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword
);
//最终形成hash值返回给mStorage.writePasswordHash
1096 hashed = (toHex(sha1) + toHex(md5)).getBytes();
1097 } catch (NoSuchAlgorithmException e) {
1098 Log.w(TAG, "Failed to encode string because of missing algorithm: " + algo
);
1099 }
1100 return hashed;
1101 }
再看mStorage.writePasswordHash
frameworks/base/services/core/java/com/android/server/LockSettingsStorage.java
243 public void writePasswordHash(byte[] hash, int userId) {
//获取路径写入hash值
244 writeFile(getLockPasswordFilename(userId), hash);
245 }
253 @VisibleForTesting
//获取路径还包了一层 LOCK_PASSWORD_FILE实际上是"password.key"
254 String getLockPasswordFilename(int userId) {
255 return getLockCredentialFilePathForUser(userId, LOCK_PASSWORD_FILE);
256 }
257
//最终获取路径在这个位置。实际上就是"/data/system/" + "password.key"
258 private String getLockCredentialFilePathForUser(int userId, String basename) {
259 userId = getUserParentOrSelfId(userId);
260 String dataSystemDirectory =
261 android.os.Environment.getDataDirectory().getAbsolutePath() +
262 SYSTEM_DIRECTORY;
263 if (userId == 0) {
264 // Leave it in the same place for user 0
265 return dataSystemDirectory + basename;
266 } else {
267 return new File(Environment.getUserSystemDirectory(userId), basename).getAbsolutePath();
268 }
269 }
手势密码的保存类同,可以自行研读。