LockSettingsService的setLockCredentialInternal函数详解

快速链接:
.
???????????? 个人博客笔记导读目录(全部) ????????????


相关推荐:
Android Gatekeeper流程深度解剖
Android手机使用命令行增加/删除/修改密码(password/pin/pattern)
android密码解锁/指纹解锁返回的authToken深度解剖


说明: 在无特别的说明下,本文讲述得是android10.0 !

本文旨在讲解LockSettingsService的应用,先上一张系统框图,看下LockSettingsService处于什么有样子的位置
LockSettingsService的setLockCredentialInternal函数详解

在android系统中的设置密码、清除密码、修改密码,都是调用到LockSettingsService.java的setLockCredential函数进行的,而setLockCredential又调用了setLockCredentialInternal,接下来我们来分析这个函数的流程

setLockCredentialInternal完成的功能有:

  • 1、如果是清除密码,即credential.isNone()==true, 则走另外一套流程;
  • 2、根据userId,读取存储的密码(其实是个hash): currentHandle = mStorage.readCredentialHash(userId)
  • 3、调用底层的enroll,将密码转换成enrolledHandle,如果enrolledHandle则说明底层出错了,则返回失败;
  • 4、将enrolledHandle转换成hash,并保存起来
  • 5、验证verifyChallenge
  • 6、setUserKeyProtection:添加一个userkey,vold使用d
  • 7、fixateNewestUserKeyAuth,也是调用到vold,fscrypt_fixate_newest_user_key_auth
  • 8、doVerifyCredential 做一次verify验证
  • 9、synchronizeUnifiedWorkChallengeForProfiles
  • 10、sendCredentialsOnChangeIfRequired
private boolean setLockCredentialInternal(LockscreenCredential credential,
        LockscreenCredential savedCredential, int userId, boolean isLockTiedToParent) {
    Objects.requireNonNull(credential);
    Objects.requireNonNull(savedCredential);
    synchronized (mSpManager) {  --------------------------------------------------//暂不介绍mSpManager机制
        if (isSyntheticPasswordBasedCredentialLocked(userId)) {
            return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId,
                    isLockTiedToParent);
        }
    }

    if (credential.isNone()) {  --------------------------------------------------//,其实就是密码类型选择了None,可以理解为,这是清除密码的流程
        clearUserKeyProtection(userId, null);
        gateKeeperClearSecureUserId(userId);
        mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId);
        // Still update PASSWORD_TYPE_KEY if we are running in pre-synthetic password code path,
        // since it forms part of the state that determines the credential type
        // @see getCredentialTypeInternal
        setKeyguardStoredQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
        setKeystorePassword(null, userId);
        fixateNewestUserKeyAuth(userId);
        synchronizeUnifiedWorkChallengeForProfiles(userId, null);
        setUserPasswordMetrics(LockscreenCredential.createNone(), userId);
        sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
        return true;
    }

    CredentialHash currentHandle = mStorage.readCredentialHash(userId);--------------------// 读取原来的密码
    if (isManagedProfileWithUnifiedLock(userId)) {
        // get credential from keystore when managed profile has unified lock
        if (savedCredential.isNone()) {
            try {
                //TODO: remove as part of b/80170828
                savedCredential = getDecryptedPasswordForTiedProfile(userId);
            } catch (FileNotFoundException e) {
                Slog.i(TAG, "Child profile key not found");
            } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
                    | NoSuchAlgorithmException | NoSuchPaddingException
                    | InvalidAlgorithmParameterException | IllegalBlockSizeException
                    | BadPaddingException | CertificateException | IOException e) {
                Slog.e(TAG, "Failed to decrypt child profile key", e);
            }
        }
    } else {
        if (currentHandle.hash == null) {
            if (!savedCredential.isNone()) {
                Slog.w(TAG, "Saved credential provided, but none stored");
            }
            savedCredential.close();
            savedCredential = LockscreenCredential.createNone();
        }
    }
    synchronized (mSpManager) {
        if (shouldMigrateToSyntheticPasswordLocked(userId)) {
            initializeSyntheticPasswordLocked(currentHandle.hash, savedCredential, userId);
            return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId,
                    isLockTiedToParent);
        }
    }
    if (DEBUG) Slog.d(TAG, "setLockCredentialInternal: user=" + userId);
    byte[] enrolledHandle = enrollCredential(currentHandle.hash, --------------------------------// 调用底层,完成enroll
            savedCredential.getCredential(), credential.getCredential(), userId);
    if (enrolledHandle == null) {
        Slog.w(TAG, String.format("Failed to enroll %s: incorrect credential",-------------------------------// 如果底层enroll错误了,则返回failed
                credential.isPattern() ? "pattern" : "password"));
        return false;
    }
    CredentialHash willStore = CredentialHash.create(enrolledHandle, credential.getType());-----------------------------//创建hash
    mStorage.writeCredentialHash(willStore, userId);    -----------------------------//保存hash
    // Still update PASSWORD_TYPE_KEY if we are running in pre-synthetic password code path,
    // since it forms part of the state that determines the credential type
    // @see getCredentialTypeInternal
    setKeyguardStoredQuality(
            LockPatternUtils.credentialTypeToPasswordQuality(credential.getType()), userId);
    // push new secret and auth token to vold
    GateKeeperResponse gkResponse;
    try {
        gkResponse = getGateKeeperService().verifyChallenge(userId, 0, willStore.hash, -----------------------------//验证challenge
                credential.getCredential());
    } catch (RemoteException e) {
        throw new IllegalStateException("Failed to verify current credential", e);
    }
    setUserKeyProtection(userId, credential, convertResponse(gkResponse));
    fixateNewestUserKeyAuth(userId);
    // Refresh the auth token
    doVerifyCredential(credential, CHALLENGE_FROM_CALLER, 0, userId, -----------------------------//再做一次verify
            null /* progressCallback */);
    synchronizeUnifiedWorkChallengeForProfiles(userId, null);
    sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
    return true;
}

流程图
LockSettingsService的setLockCredentialInternal函数详解

上一篇:循环结构(习题精选)


下一篇:微信模板消息400001:invalid credential, access_token is invalid or not latest