Loading core/java/android/app/KeyguardManager.java +32 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,16 @@ public class KeyguardManager { */ public static final int RESULT_ALTERNATE = 1; /** * * If this is set, check device policy for allowed biometrics when the user is authenticating. * This should only be used in the context of managed profiles. * * @hide */ public static final String EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS = "check_dpm"; /** * Get an intent to prompt the user to confirm credentials (pin, pattern, password or biometrics * if enrolled) for the current user of the device. The caller is expected to launch this Loading Loading @@ -164,6 +174,28 @@ public class KeyguardManager { return intent; } /** * Get an intent to prompt the user to confirm credentials (pin, pattern or password) * for the given user. The caller is expected to launch this activity using * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge. * * @param disallowBiometricsIfPolicyExists If true check if the Device Policy Manager has * disabled biometrics on the device. If biometrics are disabled, fall back to PIN/pattern/pass. * * @return the intent for launching the activity or null if no password is required. * * @hide */ public Intent createConfirmDeviceCredentialIntent( CharSequence title, CharSequence description, int userId, boolean disallowBiometricsIfPolicyExists) { Intent intent = this.createConfirmDeviceCredentialIntent(title, description, userId); intent.putExtra(EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, disallowBiometricsIfPolicyExists); return intent; } /** * Get an intent to prompt the user to confirm credentials (pin, pattern or password) * for the previous owner of the device. The caller is expected to launch this activity using Loading core/java/android/hardware/biometrics/BiometricPrompt.java +19 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,11 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan * @hide */ public static final String KEY_AUTHENTICATORS_ALLOWED = "authenticators_allowed"; /** * If this is set, check the Device Policy Manager for allowed biometrics. * @hide */ public static final String EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS = "check_dpm"; /** * Error/help message will show for this amount of time. Loading Loading @@ -325,6 +330,20 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan return this; } /** * If set check the Device Policy Manager for disabled biometrics. * * @param checkDevicePolicyManager * @return This builder. * @hide */ @NonNull public Builder setDisallowBiometricsIfPolicyExists(boolean checkDevicePolicyManager) { mBundle.putBoolean(EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, checkDevicePolicyManager); return this; } /** * Creates a {@link BiometricPrompt}. * Loading packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java +2 −8 Original line number Diff line number Diff line Loading @@ -51,12 +51,6 @@ import javax.inject.Inject; public class WorkLockActivity extends Activity { private static final String TAG = "WorkLockActivity"; /** * Add additional extra {@link com.android.settings.password.ConfirmDeviceCredentialActivity} to * enable device policy management enforcement from systemui. */ public static final String EXTRA_FROM_WORK_LOCK_ACTIVITY = "from_work_lock_activity"; /** * Contains a {@link TaskDescription} for the activity being covered. */ Loading Loading @@ -156,7 +150,8 @@ public class WorkLockActivity extends Activity { } final Intent credential = getKeyguardManager() .createConfirmDeviceCredentialIntent(null, null, getTargetUserId()); .createConfirmDeviceCredentialIntent(null, null, getTargetUserId(), true /* disallowBiometricsIfPolicyExists */); if (credential == null) { return; } Loading @@ -172,7 +167,6 @@ public class WorkLockActivity extends Activity { if (target != null) { credential.putExtra(Intent.EXTRA_INTENT, target.getIntentSender()); credential.putExtra(EXTRA_FROM_WORK_LOCK_ACTIVITY, true); } final ActivityOptions launchOptions = ActivityOptions.makeBasic(); Loading services/core/java/com/android/server/biometrics/BiometricService.java +56 −4 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static android.hardware.biometrics.BiometricManager.Authenticators; import android.app.ActivityManager; import android.app.IActivityManager; import android.app.UserSwitchObserver; import android.app.admin.DevicePolicyManager; import android.app.trust.ITrustManager; import android.content.ContentResolver; import android.content.Context; Loading Loading @@ -210,6 +211,7 @@ public class BiometricService extends SystemService { } private final Injector mInjector; private final DevicePolicyManager mDevicePolicyManager; @VisibleForTesting final IBiometricService.Stub mImpl; @VisibleForTesting Loading Loading @@ -648,6 +650,10 @@ public class BiometricService extends SystemService { throw new SecurityException("Invalid authenticator configuration"); } if (bundle.getBoolean(BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS)) { checkInternalPermission(); } Utils.combineAuthenticatorBundles(bundle); // Check the usage of this in system server. Need to remove this check if it becomes a Loading Loading @@ -712,8 +718,8 @@ public class BiometricService extends SystemService { int biometricConstantsResult = BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE; final long ident = Binder.clearCallingIdentity(); try { biometricConstantsResult = checkAndGetAuthenticators(userId, bundle, opPackageName).second; biometricConstantsResult = checkAndGetAuthenticators(userId, bundle, opPackageName, false /* checkDevicePolicyManager */).second; if (biometricConstantsResult != BiometricConstants.BIOMETRIC_SUCCESS && Utils.isDeviceCredentialAllowed(bundle)) { // If there's an issue with biometrics, but device credential is allowed and Loading Loading @@ -947,6 +953,8 @@ public class BiometricService extends SystemService { super(context); mInjector = injector; mDevicePolicyManager = (DevicePolicyManager) context .getSystemService(context.DEVICE_POLICY_SERVICE); mImpl = new BiometricServiceWrapper(); mEnabledOnKeyguardCallbacks = new ArrayList<>(); mSettingObserver = mInjector.getSettingObserver(context, mHandler, Loading Loading @@ -977,6 +985,42 @@ public class BiometricService extends SystemService { mBiometricStrengthController.startListening(); } /** * @param modality one of {@link BiometricAuthenticator#TYPE_FINGERPRINT}, * {@link BiometricAuthenticator#TYPE_IRIS} or {@link BiometricAuthenticator#TYPE_FACE} * @return */ private int mapModalityToDevicePolicyType(int modality) { switch (modality) { case TYPE_FINGERPRINT: return DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT; case TYPE_IRIS: return DevicePolicyManager.KEYGUARD_DISABLE_IRIS; case TYPE_FACE: return DevicePolicyManager.KEYGUARD_DISABLE_FACE; default: Slog.e(TAG, "Error modality=" + modality); return DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE; } } // TODO(joshmccloskey): Update this to throw an error if a new modality is added and this // logic is not updated. private boolean isBiometricDisabledByDevicePolicy(int modality, int effectiveUserId) { final int biometricToCheck = mapModalityToDevicePolicyType(modality); if (biometricToCheck == DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE) { Slog.e(TAG, "Allowing unknown modality " + modality + " to pass Device Policy check"); return false; } final int devicePolicyDisabledFeatures = mDevicePolicyManager.getKeyguardDisabledFeatures(null, effectiveUserId); final boolean isBiometricDisabled = (biometricToCheck & devicePolicyDisabledFeatures) != 0; Slog.w(TAG, "isBiometricDisabledByDevicePolicy(" + modality + "," + effectiveUserId + ")=" + isBiometricDisabled); return isBiometricDisabled; } /** * Checks if there are any available biometrics, and returns the modality. This method also * returns errors through the callback (no biometric feature, hardware not detected, no Loading @@ -996,7 +1040,7 @@ public class BiometricService extends SystemService { * TODO(kchyn): Update this to handle DEVICE_CREDENTIAL better, reduce duplicate code in callers */ private Pair<Integer, Integer> checkAndGetAuthenticators(int userId, Bundle bundle, String opPackageName) throws RemoteException { String opPackageName, boolean checkDevicePolicyManager) throws RemoteException { if (!Utils.isBiometricAllowed(bundle) && Utils.isDeviceCredentialAllowed(bundle) && !mTrustManager.isDeviceSecure(userId)) { Loading Loading @@ -1033,6 +1077,11 @@ public class BiometricService extends SystemService { } if (authenticator.impl.hasEnrolledTemplates(userId, opPackageName)) { hasTemplatesEnrolled = true; // If the device policy manager disables a specific biometric, skip it. if (checkDevicePolicyManager && isBiometricDisabledByDevicePolicy(modality, userId)) { continue; } if (isEnabledForApp(modality, userId)) { enabledForApps = true; break; Loading @@ -1043,6 +1092,7 @@ public class BiometricService extends SystemService { } Slog.d(TAG, "checkAndGetAuthenticators: user=" + userId + " checkDevicePolicyManager=" + checkDevicePolicyManager + " isHardwareDetected=" + isHardwareDetected + " hasTemplatesEnrolled=" + hasTemplatesEnrolled + " enabledForApps=" + enabledForApps); Loading Loading @@ -1502,8 +1552,10 @@ public class BiometricService extends SystemService { int result; try { final boolean checkDevicePolicyManager = bundle.getBoolean( BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, false); final Pair<Integer, Integer> pair = checkAndGetAuthenticators(userId, bundle, opPackageName); opPackageName, checkDevicePolicyManager); modality = pair.first; result = pair.second; } catch (RemoteException e) { Loading services/core/java/com/android/server/wm/ActivityStartInterceptor.java +2 −1 Original line number Diff line number Diff line Loading @@ -301,7 +301,8 @@ class ActivityStartInterceptor { FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT | FLAG_IMMUTABLE); final KeyguardManager km = (KeyguardManager) mServiceContext .getSystemService(KEYGUARD_SERVICE); final Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, userId); final Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, userId, true /* disallowBiometricsIfPolicyExists */); if (newIntent == null) { return null; } Loading Loading
core/java/android/app/KeyguardManager.java +32 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,16 @@ public class KeyguardManager { */ public static final int RESULT_ALTERNATE = 1; /** * * If this is set, check device policy for allowed biometrics when the user is authenticating. * This should only be used in the context of managed profiles. * * @hide */ public static final String EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS = "check_dpm"; /** * Get an intent to prompt the user to confirm credentials (pin, pattern, password or biometrics * if enrolled) for the current user of the device. The caller is expected to launch this Loading Loading @@ -164,6 +174,28 @@ public class KeyguardManager { return intent; } /** * Get an intent to prompt the user to confirm credentials (pin, pattern or password) * for the given user. The caller is expected to launch this activity using * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge. * * @param disallowBiometricsIfPolicyExists If true check if the Device Policy Manager has * disabled biometrics on the device. If biometrics are disabled, fall back to PIN/pattern/pass. * * @return the intent for launching the activity or null if no password is required. * * @hide */ public Intent createConfirmDeviceCredentialIntent( CharSequence title, CharSequence description, int userId, boolean disallowBiometricsIfPolicyExists) { Intent intent = this.createConfirmDeviceCredentialIntent(title, description, userId); intent.putExtra(EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, disallowBiometricsIfPolicyExists); return intent; } /** * Get an intent to prompt the user to confirm credentials (pin, pattern or password) * for the previous owner of the device. The caller is expected to launch this activity using Loading
core/java/android/hardware/biometrics/BiometricPrompt.java +19 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,11 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan * @hide */ public static final String KEY_AUTHENTICATORS_ALLOWED = "authenticators_allowed"; /** * If this is set, check the Device Policy Manager for allowed biometrics. * @hide */ public static final String EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS = "check_dpm"; /** * Error/help message will show for this amount of time. Loading Loading @@ -325,6 +330,20 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan return this; } /** * If set check the Device Policy Manager for disabled biometrics. * * @param checkDevicePolicyManager * @return This builder. * @hide */ @NonNull public Builder setDisallowBiometricsIfPolicyExists(boolean checkDevicePolicyManager) { mBundle.putBoolean(EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, checkDevicePolicyManager); return this; } /** * Creates a {@link BiometricPrompt}. * Loading
packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java +2 −8 Original line number Diff line number Diff line Loading @@ -51,12 +51,6 @@ import javax.inject.Inject; public class WorkLockActivity extends Activity { private static final String TAG = "WorkLockActivity"; /** * Add additional extra {@link com.android.settings.password.ConfirmDeviceCredentialActivity} to * enable device policy management enforcement from systemui. */ public static final String EXTRA_FROM_WORK_LOCK_ACTIVITY = "from_work_lock_activity"; /** * Contains a {@link TaskDescription} for the activity being covered. */ Loading Loading @@ -156,7 +150,8 @@ public class WorkLockActivity extends Activity { } final Intent credential = getKeyguardManager() .createConfirmDeviceCredentialIntent(null, null, getTargetUserId()); .createConfirmDeviceCredentialIntent(null, null, getTargetUserId(), true /* disallowBiometricsIfPolicyExists */); if (credential == null) { return; } Loading @@ -172,7 +167,6 @@ public class WorkLockActivity extends Activity { if (target != null) { credential.putExtra(Intent.EXTRA_INTENT, target.getIntentSender()); credential.putExtra(EXTRA_FROM_WORK_LOCK_ACTIVITY, true); } final ActivityOptions launchOptions = ActivityOptions.makeBasic(); Loading
services/core/java/com/android/server/biometrics/BiometricService.java +56 −4 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static android.hardware.biometrics.BiometricManager.Authenticators; import android.app.ActivityManager; import android.app.IActivityManager; import android.app.UserSwitchObserver; import android.app.admin.DevicePolicyManager; import android.app.trust.ITrustManager; import android.content.ContentResolver; import android.content.Context; Loading Loading @@ -210,6 +211,7 @@ public class BiometricService extends SystemService { } private final Injector mInjector; private final DevicePolicyManager mDevicePolicyManager; @VisibleForTesting final IBiometricService.Stub mImpl; @VisibleForTesting Loading Loading @@ -648,6 +650,10 @@ public class BiometricService extends SystemService { throw new SecurityException("Invalid authenticator configuration"); } if (bundle.getBoolean(BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS)) { checkInternalPermission(); } Utils.combineAuthenticatorBundles(bundle); // Check the usage of this in system server. Need to remove this check if it becomes a Loading Loading @@ -712,8 +718,8 @@ public class BiometricService extends SystemService { int biometricConstantsResult = BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE; final long ident = Binder.clearCallingIdentity(); try { biometricConstantsResult = checkAndGetAuthenticators(userId, bundle, opPackageName).second; biometricConstantsResult = checkAndGetAuthenticators(userId, bundle, opPackageName, false /* checkDevicePolicyManager */).second; if (biometricConstantsResult != BiometricConstants.BIOMETRIC_SUCCESS && Utils.isDeviceCredentialAllowed(bundle)) { // If there's an issue with biometrics, but device credential is allowed and Loading Loading @@ -947,6 +953,8 @@ public class BiometricService extends SystemService { super(context); mInjector = injector; mDevicePolicyManager = (DevicePolicyManager) context .getSystemService(context.DEVICE_POLICY_SERVICE); mImpl = new BiometricServiceWrapper(); mEnabledOnKeyguardCallbacks = new ArrayList<>(); mSettingObserver = mInjector.getSettingObserver(context, mHandler, Loading Loading @@ -977,6 +985,42 @@ public class BiometricService extends SystemService { mBiometricStrengthController.startListening(); } /** * @param modality one of {@link BiometricAuthenticator#TYPE_FINGERPRINT}, * {@link BiometricAuthenticator#TYPE_IRIS} or {@link BiometricAuthenticator#TYPE_FACE} * @return */ private int mapModalityToDevicePolicyType(int modality) { switch (modality) { case TYPE_FINGERPRINT: return DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT; case TYPE_IRIS: return DevicePolicyManager.KEYGUARD_DISABLE_IRIS; case TYPE_FACE: return DevicePolicyManager.KEYGUARD_DISABLE_FACE; default: Slog.e(TAG, "Error modality=" + modality); return DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE; } } // TODO(joshmccloskey): Update this to throw an error if a new modality is added and this // logic is not updated. private boolean isBiometricDisabledByDevicePolicy(int modality, int effectiveUserId) { final int biometricToCheck = mapModalityToDevicePolicyType(modality); if (biometricToCheck == DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE) { Slog.e(TAG, "Allowing unknown modality " + modality + " to pass Device Policy check"); return false; } final int devicePolicyDisabledFeatures = mDevicePolicyManager.getKeyguardDisabledFeatures(null, effectiveUserId); final boolean isBiometricDisabled = (biometricToCheck & devicePolicyDisabledFeatures) != 0; Slog.w(TAG, "isBiometricDisabledByDevicePolicy(" + modality + "," + effectiveUserId + ")=" + isBiometricDisabled); return isBiometricDisabled; } /** * Checks if there are any available biometrics, and returns the modality. This method also * returns errors through the callback (no biometric feature, hardware not detected, no Loading @@ -996,7 +1040,7 @@ public class BiometricService extends SystemService { * TODO(kchyn): Update this to handle DEVICE_CREDENTIAL better, reduce duplicate code in callers */ private Pair<Integer, Integer> checkAndGetAuthenticators(int userId, Bundle bundle, String opPackageName) throws RemoteException { String opPackageName, boolean checkDevicePolicyManager) throws RemoteException { if (!Utils.isBiometricAllowed(bundle) && Utils.isDeviceCredentialAllowed(bundle) && !mTrustManager.isDeviceSecure(userId)) { Loading Loading @@ -1033,6 +1077,11 @@ public class BiometricService extends SystemService { } if (authenticator.impl.hasEnrolledTemplates(userId, opPackageName)) { hasTemplatesEnrolled = true; // If the device policy manager disables a specific biometric, skip it. if (checkDevicePolicyManager && isBiometricDisabledByDevicePolicy(modality, userId)) { continue; } if (isEnabledForApp(modality, userId)) { enabledForApps = true; break; Loading @@ -1043,6 +1092,7 @@ public class BiometricService extends SystemService { } Slog.d(TAG, "checkAndGetAuthenticators: user=" + userId + " checkDevicePolicyManager=" + checkDevicePolicyManager + " isHardwareDetected=" + isHardwareDetected + " hasTemplatesEnrolled=" + hasTemplatesEnrolled + " enabledForApps=" + enabledForApps); Loading Loading @@ -1502,8 +1552,10 @@ public class BiometricService extends SystemService { int result; try { final boolean checkDevicePolicyManager = bundle.getBoolean( BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, false); final Pair<Integer, Integer> pair = checkAndGetAuthenticators(userId, bundle, opPackageName); opPackageName, checkDevicePolicyManager); modality = pair.first; result = pair.second; } catch (RemoteException e) { Loading
services/core/java/com/android/server/wm/ActivityStartInterceptor.java +2 −1 Original line number Diff line number Diff line Loading @@ -301,7 +301,8 @@ class ActivityStartInterceptor { FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT | FLAG_IMMUTABLE); final KeyguardManager km = (KeyguardManager) mServiceContext .getSystemService(KEYGUARD_SERVICE); final Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, userId); final Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, userId, true /* disallowBiometricsIfPolicyExists */); if (newIntent == null) { return null; } Loading