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 
17 package android.hardware.biometrics;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.app.admin.DevicePolicyManager;
22 import android.content.ComponentName;
23 import android.content.Context;
24 import android.os.Build;
25 import android.os.UserHandle;
26 import android.provider.Settings;
27 
28 /**
29  * "Base" functionality. For settings-specific functionality (which may rely on this base
30  * functionality), see {@link com.android.settings.biometrics.ParentalControlsUtils}
31  * @hide
32  */
33 public class ParentalControlsUtilsInternal {
34 
35     private static final String TEST_ALWAYS_REQUIRE_CONSENT_PACKAGE =
36             "android.hardware.biometrics.ParentalControlsUtilsInternal.require_consent_package";
37     private static final String TEST_ALWAYS_REQUIRE_CONSENT_CLASS =
38             "android.hardware.biometrics.ParentalControlsUtilsInternal.require_consent_class";
39 
40     /**
41      * ComponentName of Parent Consent activity for testing Biometric authentication disabled by
42      * Parental Controls.
43      *
44      * <p>Component could be defined by values of {@link #TEST_ALWAYS_REQUIRE_CONSENT_PACKAGE} and
45      * {@link #TEST_ALWAYS_REQUIRE_CONSENT_CLASS} Secure settings.
46      */
getTestComponentName(@onNull Context context, int userId)47     public static ComponentName getTestComponentName(@NonNull Context context, int userId) {
48         if (Build.IS_USERDEBUG || Build.IS_ENG) {
49             final String pkg = Settings.Secure.getStringForUser(context.getContentResolver(),
50                     TEST_ALWAYS_REQUIRE_CONSENT_PACKAGE, userId);
51             final String cls = Settings.Secure.getStringForUser(context.getContentResolver(),
52                     TEST_ALWAYS_REQUIRE_CONSENT_CLASS, userId);
53             return pkg != null && cls != null ? new ComponentName(pkg, cls) : null;
54         }
55         return null;
56     }
57 
parentConsentRequired(@onNull Context context, @NonNull DevicePolicyManager dpm, @BiometricAuthenticator.Modality int modality, @NonNull UserHandle userHandle)58     public static boolean parentConsentRequired(@NonNull Context context,
59             @NonNull DevicePolicyManager dpm, @BiometricAuthenticator.Modality int modality,
60             @NonNull UserHandle userHandle) {
61         if (getTestComponentName(context, userHandle.getIdentifier()) != null) {
62             return true;
63         }
64 
65         return parentConsentRequired(dpm, modality, userHandle);
66     }
67 
68     /**
69      * @return true if parental consent is required in order for biometric sensors to be used.
70      */
parentConsentRequired(@onNull DevicePolicyManager dpm, @BiometricAuthenticator.Modality int modality, @NonNull UserHandle userHandle)71     public static boolean parentConsentRequired(@NonNull DevicePolicyManager dpm,
72             @BiometricAuthenticator.Modality int modality, @NonNull UserHandle userHandle) {
73         final ComponentName cn = getSupervisionComponentName(dpm, userHandle);
74         if (cn == null) {
75             return false;
76         }
77 
78         final int keyguardDisabledFeatures = dpm.getKeyguardDisabledFeatures(cn);
79         final boolean dpmFpDisabled = containsFlag(keyguardDisabledFeatures,
80                 DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
81         final boolean dpmFaceDisabled = containsFlag(keyguardDisabledFeatures,
82                 DevicePolicyManager.KEYGUARD_DISABLE_FACE);
83         final boolean dpmIrisDisabled = containsFlag(keyguardDisabledFeatures,
84                 DevicePolicyManager.KEYGUARD_DISABLE_IRIS);
85 
86         final boolean consentRequired;
87         if (containsFlag(modality, BiometricAuthenticator.TYPE_FINGERPRINT) && dpmFpDisabled) {
88             consentRequired = true;
89         } else if (containsFlag(modality, BiometricAuthenticator.TYPE_FACE) && dpmFaceDisabled) {
90             consentRequired = true;
91         } else if (containsFlag(modality, BiometricAuthenticator.TYPE_IRIS) && dpmIrisDisabled) {
92             consentRequired = true;
93         } else {
94             consentRequired = false;
95         }
96 
97         return consentRequired;
98     }
99 
100     @Nullable
getSupervisionComponentName(@onNull DevicePolicyManager dpm, @NonNull UserHandle userHandle)101     public static ComponentName getSupervisionComponentName(@NonNull DevicePolicyManager dpm,
102             @NonNull UserHandle userHandle) {
103         return dpm.getProfileOwnerOrDeviceOwnerSupervisionComponent(userHandle);
104     }
105 
containsFlag(int haystack, int needle)106     private static boolean containsFlag(int haystack, int needle) {
107         return (haystack & needle) != 0;
108     }
109 }
110