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 
25 import android.annotation.Nullable;
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.VisibleForTesting;
38 
39 import com.android.internal.widget.LockPatternUtils;
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 or the calling user is not allowed to set
72         // separate profile challenge, it is the current user to set new password. Otherwise,
73         // it is the user who starts this activity setting new password.
74         int userId = ActivityManager.getCurrentUser();
75         if (ACTION_SET_NEW_PASSWORD.equals(intent.getAction())) {
76             final int callingUserId = Utils.getSecureTargetUser(activityToken,
77                     UserManager.get(context), null, intent.getExtras()).getIdentifier();
78             final LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
79             if (lockPatternUtils.isSeparateProfileChallengeAllowed(callingUserId)) {
80                 userId = callingUserId;
81             }
82         }
83         // Create a wrapper of FingerprintManager for testing, see IFingerPrintManager for details.
84         final FingerprintManager fingerprintManager = Utils.getFingerprintManagerOrNull(context);
85         final FaceManager faceManager = Utils.getFaceManagerOrNull(context);
86         return new SetNewPasswordController(userId,
87                 context.getPackageManager(),
88                 fingerprintManager, faceManager,
89                 (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE), ui);
90     }
91 
92     @VisibleForTesting
SetNewPasswordController( int targetUserId, PackageManager packageManager, FingerprintManager fingerprintManager, FaceManager faceManager, DevicePolicyManager devicePolicyManager, Ui ui)93     SetNewPasswordController(
94             int targetUserId,
95             PackageManager packageManager,
96             FingerprintManager fingerprintManager,
97             FaceManager faceManager,
98             DevicePolicyManager devicePolicyManager,
99             Ui ui) {
100         mTargetUserId = targetUserId;
101         mPackageManager = checkNotNull(packageManager);
102         mFingerprintManager = fingerprintManager;
103         mFaceManager = faceManager;
104         mDevicePolicyManager = checkNotNull(devicePolicyManager);
105         mUi = checkNotNull(ui);
106     }
107 
108     /**
109      * Dispatches the set new password intent to the correct activity that handles it.
110      */
dispatchSetNewPasswordIntent()111     public void dispatchSetNewPasswordIntent() {
112         final Bundle extras;
113 
114         final boolean hasFeatureFingerprint = mPackageManager
115                 .hasSystemFeature(PackageManager.FEATURE_FINGERPRINT);
116         final boolean hasFeatureFace = mPackageManager
117                 .hasSystemFeature(PackageManager.FEATURE_FACE);
118 
119         final boolean shouldShowFingerprintEnroll = mFingerprintManager != null
120                 && mFingerprintManager.isHardwareDetected()
121                 && !mFingerprintManager.hasEnrolledFingerprints(mTargetUserId)
122                 && !isFingerprintDisabledByAdmin();
123         final boolean shouldShowFaceEnroll = mFaceManager != null
124                 && mFaceManager.isHardwareDetected()
125                 && !mFaceManager.hasEnrolledTemplates(mTargetUserId)
126                 && !isFaceDisabledByAdmin();
127 
128         if (hasFeatureFace && shouldShowFaceEnroll
129                 && hasFeatureFingerprint && shouldShowFingerprintEnroll) {
130             extras = getBiometricChooseLockExtras();
131         } else if (hasFeatureFace && shouldShowFaceEnroll) {
132             extras = getFaceChooseLockExtras();
133         } else if (hasFeatureFingerprint && shouldShowFingerprintEnroll) {
134             extras = getFingerprintChooseLockExtras();
135         } else {
136             extras = new Bundle();
137         }
138 
139         // No matter we show fingerprint options or not, we should tell the next activity which
140         // user is setting new password.
141         extras.putInt(Intent.EXTRA_USER_ID, mTargetUserId);
142         mUi.launchChooseLock(extras);
143     }
144 
getBiometricChooseLockExtras()145     private Bundle getBiometricChooseLockExtras() {
146         Bundle chooseLockExtras = new Bundle();
147         chooseLockExtras.putBoolean(
148                 ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS, true);
149         chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
150         chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, true);
151         return chooseLockExtras;
152     }
153 
getFingerprintChooseLockExtras()154     private Bundle getFingerprintChooseLockExtras() {
155         Bundle chooseLockExtras = new Bundle();
156         chooseLockExtras.putBoolean(
157                 ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS, true);
158         chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
159         chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
160         return chooseLockExtras;
161     }
162 
getFaceChooseLockExtras()163     private Bundle getFaceChooseLockExtras() {
164         Bundle chooseLockExtras = new Bundle();
165         chooseLockExtras.putBoolean(
166                 ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS, true);
167         chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
168         chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, true);
169         return chooseLockExtras;
170     }
171 
isFingerprintDisabledByAdmin()172     private boolean isFingerprintDisabledByAdmin() {
173         int disabledFeatures =
174                 mDevicePolicyManager.getKeyguardDisabledFeatures(null, mTargetUserId);
175         return (disabledFeatures & KEYGUARD_DISABLE_FINGERPRINT) != 0;
176     }
177 
isFaceDisabledByAdmin()178     private boolean isFaceDisabledByAdmin() {
179         int disabledFeatures =
180                 mDevicePolicyManager.getKeyguardDisabledFeatures(null, mTargetUserId);
181         return (disabledFeatures & KEYGUARD_DISABLE_FACE) != 0;
182     }
183 }
184