• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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