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