Loading core/java/android/security/authenticationpolicy/AuthenticationPolicyManager.java +63 −10 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.os.Handler; import android.os.RemoteException; import android.proximity.IProximityResultCallback; import android.util.Log; import android.util.Slog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; Loading Loading @@ -511,15 +512,67 @@ public final class AuthenticationPolicyManager { */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) @FlaggedApi(FLAG_IDENTITY_CHECK_WATCH) public void startWatchRangingForIdentityCheck( @NonNull IProximityResultCallback resultCallback, Handler handler) { //TODO (b/397954948) : Update callback results to trigger in the handler handler.post(() -> { public void startWatchRangingForIdentityCheck(long authenticationRequestId, @NonNull IProximityResultCallback resultCallback, @NonNull Handler handler) { try { mAuthenticationPolicyService.startWatchRangingForIdentityCheck(resultCallback); mAuthenticationPolicyService.startWatchRangingForIdentityCheck( authenticationRequestId, new ProximityResultCallbackWrapper( handler, resultCallback)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) @FlaggedApi(FLAG_IDENTITY_CHECK_WATCH) public void cancelWatchRangingForRequestId(long authenticationRequestId) { try { mAuthenticationPolicyService.cancelWatchRangingForRequestId(authenticationRequestId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } private static final class ProximityResultCallbackWrapper extends IProximityResultCallback.Stub { private final Handler mHandler; private final IProximityResultCallback mProximityResultCallback; ProximityResultCallbackWrapper(Handler handler, IProximityResultCallback proximityResultCallback) { mHandler = handler; mProximityResultCallback = proximityResultCallback; } @Override public void onError(int error) { mHandler.post(() -> { final long id = Binder.clearCallingIdentity(); try { mProximityResultCallback.onError(error); } catch (RemoteException e) { Slog.e(TAG, "Remote exception thrown when proximity callback invoked " + e); } finally { Binder.restoreCallingIdentity(id); } }); } @Override public void onSuccess(int result) { mHandler.post(() -> { final long id = Binder.clearCallingIdentity(); try { mProximityResultCallback.onSuccess(result); } catch (RemoteException e) { Slog.e(TAG, "Remote exception thrown when proximity callback invoked " + e); } finally { Binder.restoreCallingIdentity(id); } }); } } } core/java/android/security/authenticationpolicy/IAuthenticationPolicyService.aidl +4 −1 Original line number Diff line number Diff line Loading @@ -47,5 +47,8 @@ interface IAuthenticationPolicyService { void unregisterSecureLockDeviceStatusListener(in ISecureLockDeviceStatusListener listener); @EnforcePermission("USE_BIOMETRIC_INTERNAL") void startWatchRangingForIdentityCheck(in IProximityResultCallback resultCallback); void startWatchRangingForIdentityCheck(in long authenticationRequestId, in IProximityResultCallback resultCallback); @EnforcePermission("USE_BIOMETRIC_INTERNAL") void cancelWatchRangingForRequestId(in long authenticationRequestId); } No newline at end of file core/res/res/values/config.xml +5 −0 Original line number Diff line number Diff line Loading @@ -7600,4 +7600,9 @@ <!-- Whether the system package installer supports the material design. --> <bool name="config_enableMaterialDesignInPackageInstaller">true</bool> <!-- Package and class info to bind to ProximityProviderService --> <string name="proximity_provider_service_package_name" translatable="false"></string> <string name="proximity_provider_service_class_name" translatable="false"></string> </resources> core/res/res/values/symbols.xml +4 −0 Original line number Diff line number Diff line Loading @@ -6240,4 +6240,8 @@ <!-- Verification service provider --> <java-symbol type="string" name="config_verificationServiceProviderPackageName" /> <!-- Package and class info to bind to ProximityProviderService --> <java-symbol type="string" name="proximity_provider_service_package_name" /> <java-symbol type="string" name="proximity_provider_service_class_name" /> </resources> services/core/java/com/android/server/biometrics/AuthSession.java +38 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.biometrics; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE; Loading @@ -40,6 +41,7 @@ import static com.android.server.biometrics.BiometricServiceStateProto.STATE_SHO import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricAuthenticator.Modality; Loading @@ -47,6 +49,7 @@ import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.Flags; import android.hardware.biometrics.IBiometricSensorReceiver; import android.hardware.biometrics.IBiometricServiceReceiver; import android.hardware.biometrics.IBiometricSysuiReceiver; Loading @@ -54,9 +57,11 @@ import android.hardware.biometrics.PromptInfo; import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.security.KeyStoreAuthorization; import android.security.authenticationpolicy.AuthenticationPolicyManager; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; Loading @@ -81,6 +86,7 @@ public final class AuthSession implements IBinder.DeathRecipient { private static final String TAG = "BiometricService/AuthSession"; private static final boolean DEBUG = true; /* * Defined in biometrics.proto */ Loading Loading @@ -154,6 +160,8 @@ public final class AuthSession implements IBinder.DeathRecipient { @NonNull private final OperationContextExt mOperationContext; @NonNull private final WatchRangingHelper mWatchRangingHelper; AuthSession(@NonNull Context context, Loading @@ -173,11 +181,14 @@ public final class AuthSession implements IBinder.DeathRecipient { @NonNull String opPackageName, @NonNull PromptInfo promptInfo, boolean debugEnabled, @NonNull List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties) { @NonNull List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties, @NonNull AuthenticationPolicyManager authenticationPolicyManager, @NonNull Handler handler) { this(context, biometricContext, statusBarService, sysuiReceiver, keyStoreAuthorization, random, clientDeathReceiver, preAuthInfo, token, requestId, operationId, userId, sensorReceiver, clientReceiver, opPackageName, promptInfo, debugEnabled, fingerprintSensorProperties, BiometricFrameworkStatsLogger.getInstance()); fingerprintSensorProperties, BiometricFrameworkStatsLogger.getInstance(), authenticationPolicyManager, handler); } @VisibleForTesting Loading @@ -199,7 +210,9 @@ public final class AuthSession implements IBinder.DeathRecipient { @NonNull PromptInfo promptInfo, boolean debugEnabled, @NonNull List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties, @NonNull BiometricFrameworkStatsLogger logger) { @NonNull BiometricFrameworkStatsLogger logger, @NonNull AuthenticationPolicyManager authenticationPolicyManager, @NonNull Handler handler) { Slog.d(TAG, "Creating AuthSession with: " + preAuthInfo); mContext = context; mBiometricContext = biometricContext; Loading Loading @@ -228,6 +241,8 @@ public final class AuthSession implements IBinder.DeathRecipient { mSfpsSensorIds = mFingerprintSensorProperties.stream().filter( FingerprintSensorPropertiesInternal::isAnySidefpsType).map( prop -> prop.sensorId).toList(); mWatchRangingHelper = new WatchRangingHelper(requestId, authenticationPolicyManager, handler); try { mClientReceiver.asBinder().linkToDeath(this, 0 /* flags */); Loading @@ -244,6 +259,13 @@ public final class AuthSession implements IBinder.DeathRecipient { mClientDeathReceiver.onClientDied(); } /** * Returns current state of watch ranging. */ public @WatchRangingHelper.WatchRangingState int getWatchRangingState() { return mWatchRangingHelper.getWatchRangingState(); } /** * @return bitmask representing the modalities that are running or could be running for the * current session. Loading Loading @@ -292,6 +314,10 @@ public final class AuthSession implements IBinder.DeathRecipient { } void goToInitialState() throws RemoteException { if (Flags.identityCheckWatch() && mPromptInfo.isIdentityCheckActive() && mPromptInfo.isDeviceCredentialAllowed()) { mWatchRangingHelper.startWatchRanging(); } if (mPreAuthInfo.credentialAvailable && mPreAuthInfo.eligibleSensors.isEmpty()) { // Only device credential should be shown. In this case, we don't need to wait, // since LockSettingsService/Gatekeeper is always ready to check for credential. Loading Loading @@ -838,6 +864,7 @@ public final class AuthSession implements IBinder.DeathRecipient { } } @RequiresPermission(USE_BIOMETRIC_INTERNAL) void onDialogDismissed(@BiometricPrompt.DismissedReason int reason, @Nullable byte[] credentialAttestation) { logOnDialogDismissed(reason); Loading Loading @@ -914,6 +941,9 @@ public final class AuthSession implements IBinder.DeathRecipient { mContext.getOpPackageName(), mAuthenticatedSensorId, mUserId, byteToken); } if (Flags.identityCheckWatch()) { mWatchRangingHelper.cancelWatchRanging(); } // ensure everything is cleaned up when dismissed cancelAllSensors(); Loading @@ -927,12 +957,17 @@ public final class AuthSession implements IBinder.DeathRecipient { * @param force if true, will immediately dismiss the dialog and send onError to the client * @return true if this AuthSession is finished, e.g. should be set to null */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) boolean onCancelAuthSession(boolean force) { if (hasAuthenticatedAndConfirmed()) { Slog.d(TAG, "onCancelAuthSession after successful auth"); return true; } if (Flags.identityCheckWatch()) { mWatchRangingHelper.cancelWatchRanging(); } mCancelled = true; final boolean authStarted = mState == STATE_AUTH_CALLED Loading Loading
core/java/android/security/authenticationpolicy/AuthenticationPolicyManager.java +63 −10 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.os.Handler; import android.os.RemoteException; import android.proximity.IProximityResultCallback; import android.util.Log; import android.util.Slog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; Loading Loading @@ -511,15 +512,67 @@ public final class AuthenticationPolicyManager { */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) @FlaggedApi(FLAG_IDENTITY_CHECK_WATCH) public void startWatchRangingForIdentityCheck( @NonNull IProximityResultCallback resultCallback, Handler handler) { //TODO (b/397954948) : Update callback results to trigger in the handler handler.post(() -> { public void startWatchRangingForIdentityCheck(long authenticationRequestId, @NonNull IProximityResultCallback resultCallback, @NonNull Handler handler) { try { mAuthenticationPolicyService.startWatchRangingForIdentityCheck(resultCallback); mAuthenticationPolicyService.startWatchRangingForIdentityCheck( authenticationRequestId, new ProximityResultCallbackWrapper( handler, resultCallback)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) @FlaggedApi(FLAG_IDENTITY_CHECK_WATCH) public void cancelWatchRangingForRequestId(long authenticationRequestId) { try { mAuthenticationPolicyService.cancelWatchRangingForRequestId(authenticationRequestId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } private static final class ProximityResultCallbackWrapper extends IProximityResultCallback.Stub { private final Handler mHandler; private final IProximityResultCallback mProximityResultCallback; ProximityResultCallbackWrapper(Handler handler, IProximityResultCallback proximityResultCallback) { mHandler = handler; mProximityResultCallback = proximityResultCallback; } @Override public void onError(int error) { mHandler.post(() -> { final long id = Binder.clearCallingIdentity(); try { mProximityResultCallback.onError(error); } catch (RemoteException e) { Slog.e(TAG, "Remote exception thrown when proximity callback invoked " + e); } finally { Binder.restoreCallingIdentity(id); } }); } @Override public void onSuccess(int result) { mHandler.post(() -> { final long id = Binder.clearCallingIdentity(); try { mProximityResultCallback.onSuccess(result); } catch (RemoteException e) { Slog.e(TAG, "Remote exception thrown when proximity callback invoked " + e); } finally { Binder.restoreCallingIdentity(id); } }); } } }
core/java/android/security/authenticationpolicy/IAuthenticationPolicyService.aidl +4 −1 Original line number Diff line number Diff line Loading @@ -47,5 +47,8 @@ interface IAuthenticationPolicyService { void unregisterSecureLockDeviceStatusListener(in ISecureLockDeviceStatusListener listener); @EnforcePermission("USE_BIOMETRIC_INTERNAL") void startWatchRangingForIdentityCheck(in IProximityResultCallback resultCallback); void startWatchRangingForIdentityCheck(in long authenticationRequestId, in IProximityResultCallback resultCallback); @EnforcePermission("USE_BIOMETRIC_INTERNAL") void cancelWatchRangingForRequestId(in long authenticationRequestId); } No newline at end of file
core/res/res/values/config.xml +5 −0 Original line number Diff line number Diff line Loading @@ -7600,4 +7600,9 @@ <!-- Whether the system package installer supports the material design. --> <bool name="config_enableMaterialDesignInPackageInstaller">true</bool> <!-- Package and class info to bind to ProximityProviderService --> <string name="proximity_provider_service_package_name" translatable="false"></string> <string name="proximity_provider_service_class_name" translatable="false"></string> </resources>
core/res/res/values/symbols.xml +4 −0 Original line number Diff line number Diff line Loading @@ -6240,4 +6240,8 @@ <!-- Verification service provider --> <java-symbol type="string" name="config_verificationServiceProviderPackageName" /> <!-- Package and class info to bind to ProximityProviderService --> <java-symbol type="string" name="proximity_provider_service_package_name" /> <java-symbol type="string" name="proximity_provider_service_class_name" /> </resources>
services/core/java/com/android/server/biometrics/AuthSession.java +38 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.biometrics; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE; Loading @@ -40,6 +41,7 @@ import static com.android.server.biometrics.BiometricServiceStateProto.STATE_SHO import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricAuthenticator.Modality; Loading @@ -47,6 +49,7 @@ import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.Flags; import android.hardware.biometrics.IBiometricSensorReceiver; import android.hardware.biometrics.IBiometricServiceReceiver; import android.hardware.biometrics.IBiometricSysuiReceiver; Loading @@ -54,9 +57,11 @@ import android.hardware.biometrics.PromptInfo; import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.security.KeyStoreAuthorization; import android.security.authenticationpolicy.AuthenticationPolicyManager; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; Loading @@ -81,6 +86,7 @@ public final class AuthSession implements IBinder.DeathRecipient { private static final String TAG = "BiometricService/AuthSession"; private static final boolean DEBUG = true; /* * Defined in biometrics.proto */ Loading Loading @@ -154,6 +160,8 @@ public final class AuthSession implements IBinder.DeathRecipient { @NonNull private final OperationContextExt mOperationContext; @NonNull private final WatchRangingHelper mWatchRangingHelper; AuthSession(@NonNull Context context, Loading @@ -173,11 +181,14 @@ public final class AuthSession implements IBinder.DeathRecipient { @NonNull String opPackageName, @NonNull PromptInfo promptInfo, boolean debugEnabled, @NonNull List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties) { @NonNull List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties, @NonNull AuthenticationPolicyManager authenticationPolicyManager, @NonNull Handler handler) { this(context, biometricContext, statusBarService, sysuiReceiver, keyStoreAuthorization, random, clientDeathReceiver, preAuthInfo, token, requestId, operationId, userId, sensorReceiver, clientReceiver, opPackageName, promptInfo, debugEnabled, fingerprintSensorProperties, BiometricFrameworkStatsLogger.getInstance()); fingerprintSensorProperties, BiometricFrameworkStatsLogger.getInstance(), authenticationPolicyManager, handler); } @VisibleForTesting Loading @@ -199,7 +210,9 @@ public final class AuthSession implements IBinder.DeathRecipient { @NonNull PromptInfo promptInfo, boolean debugEnabled, @NonNull List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties, @NonNull BiometricFrameworkStatsLogger logger) { @NonNull BiometricFrameworkStatsLogger logger, @NonNull AuthenticationPolicyManager authenticationPolicyManager, @NonNull Handler handler) { Slog.d(TAG, "Creating AuthSession with: " + preAuthInfo); mContext = context; mBiometricContext = biometricContext; Loading Loading @@ -228,6 +241,8 @@ public final class AuthSession implements IBinder.DeathRecipient { mSfpsSensorIds = mFingerprintSensorProperties.stream().filter( FingerprintSensorPropertiesInternal::isAnySidefpsType).map( prop -> prop.sensorId).toList(); mWatchRangingHelper = new WatchRangingHelper(requestId, authenticationPolicyManager, handler); try { mClientReceiver.asBinder().linkToDeath(this, 0 /* flags */); Loading @@ -244,6 +259,13 @@ public final class AuthSession implements IBinder.DeathRecipient { mClientDeathReceiver.onClientDied(); } /** * Returns current state of watch ranging. */ public @WatchRangingHelper.WatchRangingState int getWatchRangingState() { return mWatchRangingHelper.getWatchRangingState(); } /** * @return bitmask representing the modalities that are running or could be running for the * current session. Loading Loading @@ -292,6 +314,10 @@ public final class AuthSession implements IBinder.DeathRecipient { } void goToInitialState() throws RemoteException { if (Flags.identityCheckWatch() && mPromptInfo.isIdentityCheckActive() && mPromptInfo.isDeviceCredentialAllowed()) { mWatchRangingHelper.startWatchRanging(); } if (mPreAuthInfo.credentialAvailable && mPreAuthInfo.eligibleSensors.isEmpty()) { // Only device credential should be shown. In this case, we don't need to wait, // since LockSettingsService/Gatekeeper is always ready to check for credential. Loading Loading @@ -838,6 +864,7 @@ public final class AuthSession implements IBinder.DeathRecipient { } } @RequiresPermission(USE_BIOMETRIC_INTERNAL) void onDialogDismissed(@BiometricPrompt.DismissedReason int reason, @Nullable byte[] credentialAttestation) { logOnDialogDismissed(reason); Loading Loading @@ -914,6 +941,9 @@ public final class AuthSession implements IBinder.DeathRecipient { mContext.getOpPackageName(), mAuthenticatedSensorId, mUserId, byteToken); } if (Flags.identityCheckWatch()) { mWatchRangingHelper.cancelWatchRanging(); } // ensure everything is cleaned up when dismissed cancelAllSensors(); Loading @@ -927,12 +957,17 @@ public final class AuthSession implements IBinder.DeathRecipient { * @param force if true, will immediately dismiss the dialog and send onError to the client * @return true if this AuthSession is finished, e.g. should be set to null */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) boolean onCancelAuthSession(boolean force) { if (hasAuthenticatedAndConfirmed()) { Slog.d(TAG, "onCancelAuthSession after successful auth"); return true; } if (Flags.identityCheckWatch()) { mWatchRangingHelper.cancelWatchRanging(); } mCancelled = true; final boolean authStarted = mState == STATE_AUTH_CALLED Loading