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_FINGERPRINT; 21 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 22 import static com.android.internal.util.Preconditions.checkNotNull; 23 24 import android.annotation.Nullable; 25 import android.app.ActivityManager; 26 import android.app.admin.DevicePolicyManager; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.pm.PackageManager; 30 import android.hardware.fingerprint.FingerprintManager; 31 import android.os.Bundle; 32 import android.os.IBinder; 33 import android.os.UserManager; 34 35 import com.android.internal.annotations.VisibleForTesting; 36 import com.android.internal.widget.LockPatternUtils; 37 import com.android.settings.Utils; 38 39 /** 40 * Business logic for {@link SetNewPasswordActivity}. 41 * 42 * <p>On devices that supports fingerprint, this controller directs the user to configure 43 * fingerprint + a backup password if the device admin allows fingerprint for keyguard and 44 * the user has never configured a fingerprint before. 45 */ 46 final class SetNewPasswordController { 47 48 interface Ui { 49 /** Starts the {@link ChooseLockGeneric} activity with the given extras. */ launchChooseLock(Bundle chooseLockFingerprintExtras)50 void launchChooseLock(Bundle chooseLockFingerprintExtras); 51 } 52 53 /** 54 * Which user is setting new password. 55 */ 56 private final int mTargetUserId; 57 private final PackageManager mPackageManager; 58 @Nullable 59 private final FingerprintManager mFingerprintManager; 60 private final DevicePolicyManager mDevicePolicyManager; 61 private final Ui mUi; 62 create(Context context, Ui ui, Intent intent, IBinder activityToken)63 public static SetNewPasswordController create(Context context, Ui ui, Intent intent, 64 IBinder activityToken) { 65 // Trying to figure out which user is setting new password. If it is 66 // ACTION_SET_NEW_PARENT_PROFILE_PASSWORD or the calling user is not allowed to set 67 // separate profile challenge, it is the current user to set new password. Otherwise, 68 // it is the user who starts this activity setting new password. 69 int userId = ActivityManager.getCurrentUser(); 70 if (ACTION_SET_NEW_PASSWORD.equals(intent.getAction())) { 71 final int callingUserId = Utils.getSecureTargetUser(activityToken, 72 UserManager.get(context), null, intent.getExtras()).getIdentifier(); 73 final LockPatternUtils lockPatternUtils = new LockPatternUtils(context); 74 if (lockPatternUtils.isSeparateProfileChallengeAllowed(callingUserId)) { 75 userId = callingUserId; 76 } 77 } 78 // Create a wrapper of FingerprintManager for testing, see IFingerPrintManager for details. 79 final FingerprintManager fingerprintManager = Utils.getFingerprintManagerOrNull(context); 80 return new SetNewPasswordController(userId, 81 context.getPackageManager(), 82 fingerprintManager, 83 (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE), ui); 84 } 85 86 @VisibleForTesting SetNewPasswordController( int targetUserId, PackageManager packageManager, FingerprintManager fingerprintManager, DevicePolicyManager devicePolicyManager, Ui ui)87 SetNewPasswordController( 88 int targetUserId, 89 PackageManager packageManager, 90 FingerprintManager fingerprintManager, 91 DevicePolicyManager devicePolicyManager, 92 Ui ui) { 93 mTargetUserId = targetUserId; 94 mPackageManager = checkNotNull(packageManager); 95 mFingerprintManager = fingerprintManager; 96 mDevicePolicyManager = checkNotNull(devicePolicyManager); 97 mUi = checkNotNull(ui); 98 } 99 100 /** 101 * Dispatches the set new password intent to the correct activity that handles it. 102 */ dispatchSetNewPasswordIntent()103 public void dispatchSetNewPasswordIntent() { 104 final Bundle extras; 105 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT) 106 && mFingerprintManager != null 107 && mFingerprintManager.isHardwareDetected() 108 && !mFingerprintManager.hasEnrolledFingerprints(mTargetUserId) 109 && !isFingerprintDisabledByAdmin()) { 110 extras = getFingerprintChooseLockExtras(); 111 } else { 112 extras = new Bundle(); 113 } 114 // No matter we show fingerprint options or not, we should tell the next activity which 115 // user is setting new password. 116 extras.putInt(Intent.EXTRA_USER_ID, mTargetUserId); 117 mUi.launchChooseLock(extras); 118 } 119 getFingerprintChooseLockExtras()120 private Bundle getFingerprintChooseLockExtras() { 121 Bundle chooseLockExtras = new Bundle(); 122 long challenge = mFingerprintManager.preEnroll(); 123 chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY, 124 PASSWORD_QUALITY_SOMETHING); 125 chooseLockExtras.putBoolean( 126 ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true); 127 chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true); 128 chooseLockExtras.putLong(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); 129 chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true); 130 return chooseLockExtras; 131 } 132 isFingerprintDisabledByAdmin()133 private boolean isFingerprintDisabledByAdmin() { 134 int disabledFeatures = 135 mDevicePolicyManager.getKeyguardDisabledFeatures(null, mTargetUserId); 136 return (disabledFeatures & KEYGUARD_DISABLE_FINGERPRINT) != 0; 137 } 138 } 139