diff --git a/core/java/android/hardware/biometrics/BiometricAuthenticator.java b/core/java/android/hardware/biometrics/BiometricAuthenticator.java index a0027077e1a35..60a365835e2ec 100644 --- a/core/java/android/hardware/biometrics/BiometricAuthenticator.java +++ b/core/java/android/hardware/biometrics/BiometricAuthenticator.java @@ -63,6 +63,11 @@ public interface BiometricAuthenticator { */ int TYPE_FACE = 1 << 3; + /** + * @hide + */ + int TYPE_ANY_BIOMETRIC = TYPE_FINGERPRINT | TYPE_IRIS | TYPE_FACE; + @IntDef(flag = true, value = { TYPE_NONE, TYPE_CREDENTIAL, diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index c22224dd0da2a..7edd6e6597b28 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -1321,6 +1321,24 @@ public class UserManager { public static final String DISALLOW_CAMERA_TOGGLE = "disallow_camera_toggle"; + /** + * This is really not a user restriction in the normal sense. This can't be set to a user, + * via UserManager nor via DevicePolicyManager. This is not even set in UserSettingsUtils. + * This is defined here purely for convenience within the settings app. + * + * TODO(b/191306258): Refactor the Settings app to remove the need for this field, and delete it + * + * Specifies whether biometrics are available to the user. This is used internally only, + * as a means of communications between biometric settings and + * {@link com.android.settingslib.enterprise.ActionDisabledByAdminControllerFactory}. + * + * @see {@link android.hardware.biometrics.ParentalControlsUtilsInternal} + * @see {@link com.android.settings.biometrics.ParentalControlsUtils} + * + * @hide + */ + public static final String DISALLOW_BIOMETRIC = "disallow_biometric"; + /** * Application restriction key that is used to indicate the pending arrival * of real restrictions for the app. @@ -1415,6 +1433,7 @@ public class UserManager { DISALLOW_MICROPHONE_TOGGLE, DISALLOW_CAMERA_TOGGLE, KEY_RESTRICTIONS_PENDING, + DISALLOW_BIOMETRIC, }) @Retention(RetentionPolicy.SOURCE) public @interface UserRestrictionKey {} diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminController.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminController.java index a5373944474c2..37eab132772ad 100644 --- a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminController.java +++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminController.java @@ -18,6 +18,7 @@ package com.android.settingslib.enterprise; import android.annotation.UserIdInt; import android.content.Context; +import android.content.DialogInterface; import androidx.annotation.Nullable; @@ -54,4 +55,12 @@ public interface ActionDisabledByAdminController { * Updates the enforced admin */ void updateEnforcedAdmin(RestrictedLockUtils.EnforcedAdmin admin, @UserIdInt int adminUserId); + + /** + * Returns a listener for handling positive button clicks + */ + @Nullable + default DialogInterface.OnClickListener getPositiveButtonListener() { + return null; + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java index da42e330b8b4e..44cafb17e1d8e 100644 --- a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java +++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java @@ -20,6 +20,11 @@ import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED; import android.app.admin.DevicePolicyManager; import android.content.Context; +import android.hardware.biometrics.BiometricAuthenticator; +import android.hardware.biometrics.ParentalControlsUtilsInternal; +import android.os.UserHandle; +import android.os.UserManager; +import android.text.TextUtils; /** * A factory that returns the relevant instance of {@link ActionDisabledByAdminController}. @@ -30,10 +35,28 @@ public final class ActionDisabledByAdminControllerFactory { * Returns the relevant instance of {@link ActionDisabledByAdminController}. */ public static ActionDisabledByAdminController createInstance(Context context, - DeviceAdminStringProvider stringProvider) { - return isFinancedDevice(context) - ? new FinancedDeviceActionDisabledByAdminController(stringProvider) - : new ManagedDeviceActionDisabledByAdminController(stringProvider); + String restriction, DeviceAdminStringProvider stringProvider) { + if (doesBiometricRequireParentalConsent(context, restriction)) { + return new BiometricActionDisabledByAdminController(stringProvider); + } else if (isFinancedDevice(context)) { + return new FinancedDeviceActionDisabledByAdminController(stringProvider); + } else { + return new ManagedDeviceActionDisabledByAdminController(stringProvider); + } + } + + /** + * @return true if the restriction == UserManager.DISALLOW_BIOMETRIC and parental consent + * is required. + */ + private static boolean doesBiometricRequireParentalConsent(Context context, + String restriction) { + if (!TextUtils.equals(UserManager.DISALLOW_BIOMETRIC, restriction)) { + return false; + } + DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); + return ParentalControlsUtilsInternal.parentConsentRequired(context, dpm, + BiometricAuthenticator.TYPE_ANY_BIOMETRIC, new UserHandle(UserHandle.myUserId())); } private static boolean isFinancedDevice(Context context) { diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminController.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminController.java new file mode 100644 index 0000000000000..48ac208383a5d --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminController.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.enterprise; + +import android.content.Context; +import android.content.DialogInterface; +import android.util.Log; + +import androidx.annotation.Nullable; + +public class BiometricActionDisabledByAdminController extends BaseActionDisabledByAdminController { + + private static final String TAG = "BiometricActionDisabledByAdminController"; + + BiometricActionDisabledByAdminController( + DeviceAdminStringProvider stringProvider) { + super(stringProvider); + } + + @Override + public void setupLearnMoreButton(Context context) { + + } + + @Override + public String getAdminSupportTitle(@Nullable String restriction) { + return mStringProvider.getDisabledBiometricsParentConsentTitle(); + } + + @Override + public CharSequence getAdminSupportContentString(Context context, + @Nullable CharSequence supportMessage) { + return mStringProvider.getDisabledBiometricsParentConsentContent(); + } + + @Override + public DialogInterface.OnClickListener getPositiveButtonListener() { + return (dialog, which) -> { + Log.d(TAG, "Positive button clicked"); + // TODO(b/188847063) Launch appropriate intent + }; + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/DeviceAdminStringProvider.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/DeviceAdminStringProvider.java index c47d789a514d2..b83837e6caf64 100644 --- a/packages/SettingsLib/src/com/android/settingslib/enterprise/DeviceAdminStringProvider.java +++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/DeviceAdminStringProvider.java @@ -72,4 +72,14 @@ public interface DeviceAdminStringProvider { * a financed device. */ String getDisabledByPolicyTitleForFinancedDevice(); + + /** + * Returns the dialog title for when biometrics require parental consent. + */ + String getDisabledBiometricsParentConsentTitle(); + + /** + * Returns the dialog contents for when biometrics require parental consent. + */ + String getDisabledBiometricsParentConsentContent(); } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FakeDeviceAdminStringProvider.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FakeDeviceAdminStringProvider.java index be3e9fcf45ea2..99e13c3254724 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FakeDeviceAdminStringProvider.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FakeDeviceAdminStringProvider.java @@ -30,6 +30,8 @@ class FakeDeviceAdminStringProvider implements DeviceAdminStringProvider { static final String DEFAULT_DISABLED_BY_POLICY_CONTENT = "default_disabled_by_policy_content"; static final String DEFAULT_DISABLED_BY_POLICY_TITLE_FINANCED_DEVICE = "default_disabled_by_policy_title_financed_device"; + static final String DEFAULT_BIOMETRIC_TITLE = "biometric_title"; + static final String DEFAULT_BIOMETRIC_CONTENTS = "biometric_contents"; static final DeviceAdminStringProvider DEFAULT_DEVICE_ADMIN_STRING_PROVIDER = new FakeDeviceAdminStringProvider(/* url = */ null); @@ -88,4 +90,15 @@ class FakeDeviceAdminStringProvider implements DeviceAdminStringProvider { public String getDisabledByPolicyTitleForFinancedDevice() { return DEFAULT_DISABLED_BY_POLICY_TITLE_FINANCED_DEVICE; } + + @Override + public String getDisabledBiometricsParentConsentTitle() { + return DEFAULT_BIOMETRIC_TITLE; + } + + @Override + public String getDisabledBiometricsParentConsentContent() { + return DEFAULT_BIOMETRIC_CONTENTS; + } + }