1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.password; 18 19 import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD; 20 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FACE; 21 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT; 22 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 23 24 import static com.android.internal.util.Preconditions.checkNotNull; 25 26 import android.annotation.Nullable; 27 import android.app.ActivityManager; 28 import android.app.admin.DevicePolicyManager; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.content.pm.PackageManager; 32 import android.hardware.face.FaceManager; 33 import android.hardware.fingerprint.FingerprintManager; 34 import android.os.Bundle; 35 import android.os.IBinder; 36 import android.os.UserManager; 37 38 import androidx.annotation.VisibleForTesting; 39 40 import com.android.internal.widget.LockPatternUtils; 41 import com.android.settings.Utils; 42 43 /** 44 * Business logic for {@link SetNewPasswordActivity}. 45 * 46 * <p>On devices that supports fingerprint, this controller directs the user to configure 47 * fingerprint + a backup password if the device admin allows fingerprint for keyguard and 48 * the user has never configured a fingerprint before. 49 */ 50 final class SetNewPasswordController { 51 52 interface Ui { 53 /** Starts the {@link ChooseLockGeneric} activity with the given extras. */ launchChooseLock(Bundle chooseLockFingerprintExtras)54 void launchChooseLock(Bundle chooseLockFingerprintExtras); 55 } 56 57 /** 58 * Which user is setting new password. 59 */ 60 private final int mTargetUserId; 61 private final PackageManager mPackageManager; 62 @Nullable 63 private final FingerprintManager mFingerprintManager; 64 @Nullable 65 private final FaceManager mFaceManager; 66 private final DevicePolicyManager mDevicePolicyManager; 67 private final Ui mUi; 68 create(Context context, Ui ui, Intent intent, IBinder activityToken)69 public static SetNewPasswordController create(Context context, Ui ui, Intent intent, 70 IBinder activityToken) { 71 // Trying to figure out which user is setting new password. If it is 72 // ACTION_SET_NEW_PARENT_PROFILE_PASSWORD or the calling user is not allowed to set 73 // separate profile challenge, it is the current user to set new password. Otherwise, 74 // it is the user who starts this activity setting new password. 75 int userId = ActivityManager.getCurrentUser(); 76 if (ACTION_SET_NEW_PASSWORD.equals(intent.getAction())) { 77 final int callingUserId = Utils.getSecureTargetUser(activityToken, 78 UserManager.get(context), null, intent.getExtras()).getIdentifier(); 79 final LockPatternUtils lockPatternUtils = new LockPatternUtils(context); 80 if (lockPatternUtils.isSeparateProfileChallengeAllowed(callingUserId)) { 81 userId = callingUserId; 82 } 83 } 84 // Create a wrapper of FingerprintManager for testing, see IFingerPrintManager for details. 85 final FingerprintManager fingerprintManager = Utils.getFingerprintManagerOrNull(context); 86 final FaceManager faceManager = Utils.getFaceManagerOrNull(context); 87 return new SetNewPasswordController(userId, 88 context.getPackageManager(), 89 fingerprintManager, faceManager, 90 (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE), ui); 91 } 92 93 @VisibleForTesting SetNewPasswordController( int targetUserId, PackageManager packageManager, FingerprintManager fingerprintManager, FaceManager faceManager, DevicePolicyManager devicePolicyManager, Ui ui)94 SetNewPasswordController( 95 int targetUserId, 96 PackageManager packageManager, 97 FingerprintManager fingerprintManager, 98 FaceManager faceManager, 99 DevicePolicyManager devicePolicyManager, 100 Ui ui) { 101 mTargetUserId = targetUserId; 102 mPackageManager = checkNotNull(packageManager); 103 mFingerprintManager = fingerprintManager; 104 mFaceManager = faceManager; 105 mDevicePolicyManager = checkNotNull(devicePolicyManager); 106 mUi = checkNotNull(ui); 107 } 108 109 /** 110 * Dispatches the set new password intent to the correct activity that handles it. 111 */ dispatchSetNewPasswordIntent()112 public void dispatchSetNewPasswordIntent() { 113 final Bundle extras; 114 // TODO: handle the case with multiple biometrics, perhaps take an arg for biometric type? 115 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE) 116 && mFaceManager != null 117 && mFaceManager.isHardwareDetected() 118 && !mFaceManager.hasEnrolledTemplates(mTargetUserId) 119 && !isFaceDisabledByAdmin()) { 120 extras = getFaceChooseLockExtras(); 121 } else if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT) 122 && mFingerprintManager != null 123 && mFingerprintManager.isHardwareDetected() 124 && !mFingerprintManager.hasEnrolledFingerprints(mTargetUserId) 125 && !isFingerprintDisabledByAdmin()) { 126 extras = getFingerprintChooseLockExtras(); 127 } else { 128 extras = new Bundle(); 129 } 130 // No matter we show fingerprint options or not, we should tell the next activity which 131 // user is setting new password. 132 extras.putInt(Intent.EXTRA_USER_ID, mTargetUserId); 133 mUi.launchChooseLock(extras); 134 } 135 getFingerprintChooseLockExtras()136 private Bundle getFingerprintChooseLockExtras() { 137 Bundle chooseLockExtras = new Bundle(); 138 long challenge = mFingerprintManager.preEnroll(); 139 chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY, 140 PASSWORD_QUALITY_SOMETHING); 141 chooseLockExtras.putBoolean( 142 ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true); 143 chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true); 144 chooseLockExtras.putLong(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); 145 chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true); 146 return chooseLockExtras; 147 } 148 getFaceChooseLockExtras()149 private Bundle getFaceChooseLockExtras() { 150 Bundle chooseLockExtras = new Bundle(); 151 long challenge = mFaceManager.generateChallenge(); 152 chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY, 153 PASSWORD_QUALITY_SOMETHING); 154 chooseLockExtras.putBoolean( 155 ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true); 156 chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true); 157 chooseLockExtras.putLong(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); 158 chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, true); 159 return chooseLockExtras; 160 } 161 isFingerprintDisabledByAdmin()162 private boolean isFingerprintDisabledByAdmin() { 163 int disabledFeatures = 164 mDevicePolicyManager.getKeyguardDisabledFeatures(null, mTargetUserId); 165 return (disabledFeatures & KEYGUARD_DISABLE_FINGERPRINT) != 0; 166 } 167 isFaceDisabledByAdmin()168 private boolean isFaceDisabledByAdmin() { 169 int disabledFeatures = 170 mDevicePolicyManager.getKeyguardDisabledFeatures(null, mTargetUserId); 171 return (disabledFeatures & KEYGUARD_DISABLE_FACE) != 0; 172 } 173 } 174