1 /*
2  * Copyright (C) 2021 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 package com.android.settings.biometrics.combination;
17 
18 import android.content.Context;
19 
20 import androidx.annotation.Nullable;
21 import androidx.lifecycle.Lifecycle;
22 import androidx.lifecycle.LifecycleObserver;
23 import androidx.lifecycle.OnLifecycleEvent;
24 import androidx.preference.Preference;
25 import androidx.preference.PreferenceScreen;
26 
27 import com.android.internal.annotations.VisibleForTesting;
28 import com.android.settings.Utils;
29 import com.android.settings.biometrics.BiometricStatusPreferenceController;
30 import com.android.settingslib.RestrictedLockUtils;
31 import com.android.settingslib.RestrictedPreference;
32 
33 /**
34  * Preference controller for biometrics settings page controlling the ability to unlock the phone
35  * with face and fingerprint.
36  */
37 public class CombinedBiometricStatusPreferenceController extends
38         BiometricStatusPreferenceController implements LifecycleObserver {
39     public static final String KEY_BIOMETRIC_SETTINGS = "biometric_settings";
40 
41     @VisibleForTesting
42     RestrictedPreference mPreference;
43     protected final CombinedBiometricStatusUtils mCombinedBiometricStatusUtils;
44     private PreferenceScreen mPreferenceScreen;
45 
CombinedBiometricStatusPreferenceController(Context context)46     public CombinedBiometricStatusPreferenceController(Context context) {
47         this(context, KEY_BIOMETRIC_SETTINGS, null /* lifecycle */);
48     }
49 
CombinedBiometricStatusPreferenceController(Context context, String key)50     public CombinedBiometricStatusPreferenceController(Context context, String key) {
51         this(context, key, null /* lifecycle */);
52     }
53 
CombinedBiometricStatusPreferenceController(Context context, Lifecycle lifecycle)54     public CombinedBiometricStatusPreferenceController(Context context, Lifecycle lifecycle) {
55         this(context, KEY_BIOMETRIC_SETTINGS, lifecycle);
56     }
57 
CombinedBiometricStatusPreferenceController( Context context, String key, Lifecycle lifecycle)58     public CombinedBiometricStatusPreferenceController(
59             Context context, String key, Lifecycle lifecycle) {
60         super(context, key);
61         mCombinedBiometricStatusUtils = new CombinedBiometricStatusUtils(context, getUserId());
62 
63         if (lifecycle != null) {
64             lifecycle.addObserver(this);
65         }
66     }
67 
68     @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
onResume()69     public void onResume() {
70         updateStateInternal();
71         if (mPreferenceScreen != null) {
72             displayPreference(mPreferenceScreen);
73         }
74     }
75 
76     @Override
displayPreference(PreferenceScreen screen)77     public void displayPreference(PreferenceScreen screen) {
78         super.displayPreference(screen);
79         mPreferenceScreen = screen;
80         mPreference = screen.findPreference(mPreferenceKey);
81     }
82 
83     @Override
isDeviceSupported()84     protected boolean isDeviceSupported() {
85         return mCombinedBiometricStatusUtils.isAvailable();
86     }
87 
88     @Override
isHardwareSupported()89     protected boolean isHardwareSupported() {
90         return Utils.hasFaceHardware(mContext) || Utils.hasFingerprintHardware(mContext);
91     }
92 
93     @Override
updateState(Preference preference)94     public void updateState(Preference preference) {
95         super.updateState(preference);
96         updateStateInternal();
97     }
98 
updateStateInternal()99     private void updateStateInternal() {
100         final RestrictedLockUtils.EnforcedAdmin admin =
101                 mCombinedBiometricStatusUtils.getDisablingAdmin();
102 
103         updateStateInternal(admin);
104     }
105 
106     /**
107      *   Disables the preference and shows the consent flow only if consent is required for all
108      *   modalities.
109      *
110      *   <p>Otherwise, users will not be able to enter and modify settings for modalities which have
111      *   already been consented. In any case, the controllers for the modalities which have not yet
112      *   been consented will be disabled in the combined page anyway - users can go through the
113      *   consent+enrollment flow from there.
114      */
115     @VisibleForTesting
updateStateInternal(@ullable RestrictedLockUtils.EnforcedAdmin enforcedAdmin)116     void updateStateInternal(@Nullable RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
117         if (mPreference != null) {
118             mPreference.setDisabledByAdmin(enforcedAdmin);
119         }
120     }
121 
122     @Override
getSummaryText()123     protected String getSummaryText() {
124         return mCombinedBiometricStatusUtils.getSummary();
125     }
126 
127     @Override
getSettingsClassName()128     protected String getSettingsClassName() {
129         return mCombinedBiometricStatusUtils.getSettingsClassName();
130     }
131 
setPreferenceScreen(PreferenceScreen preferenceScreen)132     public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
133         mPreferenceScreen = preferenceScreen;
134     }
135 }
136