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.ChooseLockGeneric;
38 import com.android.settings.ChooseLockSettingsHelper;
39 import 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  */
48 final class SetNewPasswordController {
49 
50     interface Ui {
51         /** Starts the {@link ChooseLockGeneric} activity with the given extras. */
launchChooseLock(Bundle chooseLockFingerprintExtras)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 
create(Context context, Ui ui, Intent intent, IBinder activityToken)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 = Utils.getFingerprintManagerOrNull(context);
81         final IFingerprintManager fingerprintManagerWrapper =
82                 fingerprintManager == null
83                         ? null
84                         : new FingerprintManagerWrapper(fingerprintManager);
85         return new SetNewPasswordController(userId,
86                 context.getPackageManager(),
87                 fingerprintManagerWrapper,
88                 (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE), ui);
89     }
90 
91     @VisibleForTesting
SetNewPasswordController( int targetUserId, PackageManager packageManager, IFingerprintManager fingerprintManager, DevicePolicyManager devicePolicyManager, Ui ui)92     SetNewPasswordController(
93             int targetUserId,
94             PackageManager packageManager,
95             IFingerprintManager fingerprintManager,
96             DevicePolicyManager devicePolicyManager,
97             Ui ui) {
98         mTargetUserId = targetUserId;
99         mPackageManager = checkNotNull(packageManager);
100         mFingerprintManager = fingerprintManager;
101         mDevicePolicyManager = checkNotNull(devicePolicyManager);
102         mUi = checkNotNull(ui);
103     }
104 
105     /**
106      * Dispatches the set new password intent to the correct activity that handles it.
107      */
dispatchSetNewPasswordIntent()108     public void dispatchSetNewPasswordIntent() {
109         final Bundle extras;
110         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
111                 && mFingerprintManager != null
112                 && mFingerprintManager.isHardwareDetected()
113                 && !mFingerprintManager.hasEnrolledFingerprints(mTargetUserId)
114                 && !isFingerprintDisabledByAdmin()) {
115             extras = getFingerprintChooseLockExtras();
116         } else {
117             extras = new Bundle();
118         }
119         // No matter we show fingerprint options or not, we should tell the next activity which
120         // user is setting new password.
121         extras.putInt(Intent.EXTRA_USER_ID, mTargetUserId);
122         mUi.launchChooseLock(extras);
123     }
124 
getFingerprintChooseLockExtras()125     private Bundle getFingerprintChooseLockExtras() {
126         Bundle chooseLockExtras = new Bundle();
127         long challenge = mFingerprintManager.preEnroll();
128         chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
129                 PASSWORD_QUALITY_SOMETHING);
130         chooseLockExtras.putBoolean(
131                 ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
132         chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
133         chooseLockExtras.putLong(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
134         chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
135         return chooseLockExtras;
136     }
137 
isFingerprintDisabledByAdmin()138     private boolean isFingerprintDisabledByAdmin() {
139         int disabledFeatures =
140                 mDevicePolicyManager.getKeyguardDisabledFeatures(null, mTargetUserId);
141         return (disabledFeatures & KEYGUARD_DISABLE_FINGERPRINT) != 0;
142     }
143 }
144