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 
23 import static com.android.internal.util.Preconditions.checkNotNull;
24 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FINGERPRINT_ENROLLMENT_ONLY;
25 
26 import android.app.ActivityManager;
27 import android.app.admin.DevicePolicyManager;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.pm.PackageManager;
31 import android.hardware.face.FaceManager;
32 import android.hardware.fingerprint.FingerprintManager;
33 import android.os.Bundle;
34 import android.os.IBinder;
35 import android.os.UserManager;
36 
37 import androidx.annotation.Nullable;
38 import androidx.annotation.VisibleForTesting;
39 
40 import com.android.settings.Utils;
41 
42 /**
43  * Business logic for {@link SetNewPasswordActivity}.
44  *
45  * <p>On devices that supports fingerprint, this controller directs the user to configure
46  * fingerprint + a backup password if the device admin allows fingerprint for keyguard and
47  * the user has never configured a fingerprint before.
48  */
49 final class SetNewPasswordController {
50 
51     interface Ui {
52         /** Starts the {@link ChooseLockGeneric} activity with the given extras. */
launchChooseLock(Bundle chooseLockFingerprintExtras)53         void launchChooseLock(Bundle chooseLockFingerprintExtras);
54     }
55 
56     /**
57      * Which user is setting new password.
58      */
59     private final int mTargetUserId;
60     private final PackageManager mPackageManager;
61     @Nullable
62     private final FingerprintManager mFingerprintManager;
63     @Nullable
64     private final FaceManager mFaceManager;
65     private final DevicePolicyManager mDevicePolicyManager;
66     private final Ui mUi;
67 
create(Context context, Ui ui, Intent intent, IBinder activityToken)68     public static SetNewPasswordController create(Context context, Ui ui, Intent intent,
69             IBinder activityToken) {
70         // Trying to figure out which user is setting new password. If it is
71         // ACTION_SET_NEW_PARENT_PROFILE_PASSWORD, it is the current user to set
72         // new password. Otherwise, it is the user who starts this activity
73         // setting new password.
74         final int userId;
75         if (ACTION_SET_NEW_PASSWORD.equals(intent.getAction())) {
76             userId = Utils.getSecureTargetUser(activityToken,
77                     UserManager.get(context), null, intent.getExtras()).getIdentifier();
78         } else {
79             userId = ActivityManager.getCurrentUser();
80         }
81         // Create a wrapper of FingerprintManager for testing, see IFingerPrintManager for details.
82         final FingerprintManager fingerprintManager = Utils.getFingerprintManagerOrNull(context);
83         final FaceManager faceManager =
84                 !intent.getBooleanExtra(EXTRA_KEY_FINGERPRINT_ENROLLMENT_ONLY, false)
85                         ? Utils.getFaceManagerOrNull(context)
86                         : null;
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 
115         final boolean hasFeatureFingerprint = mPackageManager
116                 .hasSystemFeature(PackageManager.FEATURE_FINGERPRINT);
117         final boolean hasFeatureFace = mPackageManager
118                 .hasSystemFeature(PackageManager.FEATURE_FACE);
119 
120         final boolean shouldShowFingerprintEnroll = mFingerprintManager != null
121                 && mFingerprintManager.isHardwareDetected()
122                 && !mFingerprintManager.hasEnrolledFingerprints(mTargetUserId)
123                 && !isFingerprintDisabledByAdmin();
124         final boolean shouldShowFaceEnroll = mFaceManager != null
125                 && mFaceManager.isHardwareDetected()
126                 && !mFaceManager.hasEnrolledTemplates(mTargetUserId)
127                 && !isFaceDisabledByAdmin();
128 
129         if (hasFeatureFace && shouldShowFaceEnroll
130                 && hasFeatureFingerprint && shouldShowFingerprintEnroll) {
131             extras = getBiometricChooseLockExtras();
132         } else if (hasFeatureFace && shouldShowFaceEnroll) {
133             extras = getFaceChooseLockExtras();
134         } else if (hasFeatureFingerprint && shouldShowFingerprintEnroll) {
135             extras = getFingerprintChooseLockExtras();
136         } else {
137             extras = new Bundle();
138         }
139 
140         // No matter we show fingerprint options or not, we should tell the next activity which
141         // user is setting new password.
142         extras.putInt(Intent.EXTRA_USER_ID, mTargetUserId);
143         mUi.launchChooseLock(extras);
144     }
145 
getBiometricChooseLockExtras()146     private Bundle getBiometricChooseLockExtras() {
147         Bundle chooseLockExtras = new Bundle();
148         chooseLockExtras.putBoolean(
149                 ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS, true);
150         chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
151         chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, true);
152         return chooseLockExtras;
153     }
154 
getFingerprintChooseLockExtras()155     private Bundle getFingerprintChooseLockExtras() {
156         Bundle chooseLockExtras = new Bundle();
157         chooseLockExtras.putBoolean(
158                 ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS, true);
159         chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
160         chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
161         return chooseLockExtras;
162     }
163 
getFaceChooseLockExtras()164     private Bundle getFaceChooseLockExtras() {
165         Bundle chooseLockExtras = new Bundle();
166         chooseLockExtras.putBoolean(
167                 ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS, true);
168         chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
169         chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, true);
170         return chooseLockExtras;
171     }
172 
isFingerprintDisabledByAdmin()173     private boolean isFingerprintDisabledByAdmin() {
174         int disabledFeatures =
175                 mDevicePolicyManager.getKeyguardDisabledFeatures(null, mTargetUserId);
176         return (disabledFeatures & KEYGUARD_DISABLE_FINGERPRINT) != 0;
177     }
178 
isFaceDisabledByAdmin()179     private boolean isFaceDisabledByAdmin() {
180         int disabledFeatures =
181                 mDevicePolicyManager.getKeyguardDisabledFeatures(null, mTargetUserId);
182         return (disabledFeatures & KEYGUARD_DISABLE_FACE) != 0;
183     }
184 }
185