Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 901b3363 authored by Tian Xie's avatar Tian Xie
Browse files

Revert "Expose `FaceManager` APIs as `@SystemApi`."

Revert submission 25750009-facemanager_20240110

Reason for revert: Project cancelled.

Reverted changes: /q/submissionid:25750009-facemanager_20240110

Bug: 329561487

Test: Local
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5fe554bfd9f28b7b15677dfb74c756f827074ebc)
Merged-In: I7e329f311b3eb599195f415cf39dc28bb11139a1
Change-Id: I7e329f311b3eb599195f415cf39dc28bb11139a1
Revert FaceManager changes.
parent 70ad7a40
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -403,7 +403,6 @@ package android {
    field @Deprecated public static final String UPDATE_TIME_ZONE_RULES = "android.permission.UPDATE_TIME_ZONE_RULES";
    field public static final String UPGRADE_RUNTIME_PERMISSIONS = "android.permission.UPGRADE_RUNTIME_PERMISSIONS";
    field public static final String USER_ACTIVITY = "android.permission.USER_ACTIVITY";
    field @FlaggedApi("android.hardware.biometrics.face_background_authentication") public static final String USE_BACKGROUND_FACE_AUTHENTICATION = "android.permission.USE_BACKGROUND_FACE_AUTHENTICATION";
    field public static final String USE_COLORIZED_NOTIFICATIONS = "android.permission.USE_COLORIZED_NOTIFICATIONS";
    field @FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence") public static final String USE_ON_DEVICE_INTELLIGENCE = "android.permission.USE_ON_DEVICE_INTELLIGENCE";
    field public static final String USE_RESERVED_DISK = "android.permission.USE_RESERVED_DISK";
@@ -3759,7 +3758,6 @@ package android.content {
    field @FlaggedApi("android.permission.flags.enhanced_confirmation_mode_apis_enabled") public static final String ECM_ENHANCED_CONFIRMATION_SERVICE = "ecm_enhanced_confirmation";
    field public static final String ETHERNET_SERVICE = "ethernet";
    field public static final String EUICC_CARD_SERVICE = "euicc_card";
    field @FlaggedApi("android.hardware.biometrics.face_background_authentication") public static final String FACE_SERVICE = "face";
    field public static final String FONT_SERVICE = "font";
    field public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
    field public static final String MEDIA_TRANSCODING_SERVICE = "media_transcoding";
@@ -5131,15 +5129,6 @@ package android.hardware.display {
}
package android.hardware.face {
  @FlaggedApi("android.hardware.biometrics.face_background_authentication") public class FaceManager {
    method @FlaggedApi("android.hardware.biometrics.face_background_authentication") @RequiresPermission(android.Manifest.permission.USE_BACKGROUND_FACE_AUTHENTICATION) public void authenticateInBackground(@Nullable java.util.concurrent.Executor, @Nullable android.hardware.biometrics.BiometricPrompt.CryptoObject, @Nullable android.os.CancellationSignal, @NonNull android.hardware.biometrics.BiometricPrompt.AuthenticationCallback);
    method @FlaggedApi("android.hardware.biometrics.face_background_authentication") @RequiresPermission(anyOf={"android.permission.USE_BIOMETRIC_INTERNAL", android.Manifest.permission.USE_BACKGROUND_FACE_AUTHENTICATION}) public boolean hasEnrolledTemplates();
  }
}
package android.hardware.hdmi {
  public abstract class HdmiClient {
+0 −2
Original line number Diff line number Diff line
@@ -5081,8 +5081,6 @@ public abstract class Context {
     * @see #getSystemService
     * @see android.hardware.face.FaceManager
     */
    @FlaggedApi(android.hardware.biometrics.Flags.FLAG_FACE_BACKGROUND_AUTHENTICATION)
    @SystemApi
    public static final String FACE_SERVICE = "face";

    /**
+0 −7
Original line number Diff line number Diff line
@@ -28,10 +28,3 @@ flag {
  bug: "302735104"
}
flag {
  name: "face_background_authentication"
  namespace: "biometrics_framework"
  description: "Feature flag for allowing face background authentication with USE_BACKGROUND_FACE_AUTHENTICATION."
  bug: "318584190"
}
+111 −129
Original line number Diff line number Diff line
@@ -18,23 +18,18 @@ package android.hardware.face;

import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.MANAGE_BIOMETRIC;
import static android.Manifest.permission.USE_BACKGROUND_FACE_AUTHENTICATION;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
import static android.hardware.biometrics.Flags.FLAG_FACE_BACKGROUND_AUTHENTICATION;

import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricStateListener;
import android.hardware.biometrics.CryptoObject;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
@@ -42,9 +37,9 @@ import android.os.Binder;
import android.os.CancellationSignal;
import android.os.CancellationSignal.OnCancelListener;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.Trace;
@@ -54,21 +49,15 @@ import android.util.Slog;
import android.view.Surface;

import com.android.internal.R;
import com.android.internal.os.SomeArgs;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * A class that coordinates access to the face authentication hardware.
 *
 * <p>Please use {@link BiometricPrompt} for face authentication unless the experience must be
 * customized for unique system-level utilities, like the lock screen or ambient background usage.
 *
 * @hide
 */
@FlaggedApi(FLAG_FACE_BACKGROUND_AUTHENTICATION)
@SystemApi
@SystemService(Context.FACE_SERVICE)
public class FaceManager implements BiometricAuthenticator, BiometricFaceConstants {

@@ -99,76 +88,81 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
    @Nullable private GenerateChallengeCallback mGenerateChallengeCallback;
    private CryptoObject mCryptoObject;
    private Face mRemovalFace;
    private Executor mExecutor;
    private Handler mHandler;
    private List<FaceSensorPropertiesInternal> mProps = new ArrayList<>();

    private final IFaceServiceReceiver mServiceReceiver = new IFaceServiceReceiver.Stub() {

        @Override // binder call
        public void onEnrollResult(Face face, int remaining) {
            mExecutor.execute(() -> sendEnrollResult(face, remaining));
            mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0, face).sendToTarget();
        }

        @Override // binder call
        public void onAcquired(int acquireInfo, int vendorCode) {
            mExecutor.execute(() -> sendAcquiredResult(acquireInfo, vendorCode));
            mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, vendorCode).sendToTarget();
        }

        @Override // binder call
        public void onAuthenticationSucceeded(Face face, int userId, boolean isStrongBiometric) {
            mExecutor.execute(() -> sendAuthenticatedSucceeded(face, userId, isStrongBiometric));
            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId,
                    isStrongBiometric ? 1 : 0, face).sendToTarget();
        }

        @Override // binder call
        public void onFaceDetected(int sensorId, int userId, boolean isStrongBiometric) {
            mExecutor.execute(() -> sendFaceDetected(sensorId, userId, isStrongBiometric));
            mHandler.obtainMessage(MSG_FACE_DETECTED, sensorId, userId, isStrongBiometric)
                    .sendToTarget();
        }

        @Override // binder call
        public void onAuthenticationFailed() {
            mExecutor.execute(() -> sendAuthenticatedFailed());
            mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();
        }

        @Override // binder call
        public void onError(int error, int vendorCode) {
            mExecutor.execute(() -> sendErrorResult(error, vendorCode));
            mHandler.obtainMessage(MSG_ERROR, error, vendorCode).sendToTarget();
        }

        @Override // binder call
        public void onRemoved(Face face, int remaining) {
            mExecutor.execute(() -> {
                sendRemovedResult(face, remaining);
            mHandler.obtainMessage(MSG_REMOVED, remaining, 0, face).sendToTarget();
            if (remaining == 0) {
                Settings.Secure.putIntForUser(mContext.getContentResolver(),
                        Settings.Secure.FACE_UNLOCK_RE_ENROLL, 0,
                        UserHandle.USER_CURRENT);
            }
            });
        }

        @Override
        public void onFeatureSet(boolean success, int feature) {
            mExecutor.execute(() -> sendSetFeatureCompleted(success, feature));
            mHandler.obtainMessage(MSG_SET_FEATURE_COMPLETED, feature, 0, success).sendToTarget();
        }

        @Override
        public void onFeatureGet(boolean success, int[] features, boolean[] featureState) {
            mExecutor.execute(() -> sendGetFeatureCompleted(success, features, featureState));
            SomeArgs args = SomeArgs.obtain();
            args.arg1 = success;
            args.arg2 = features;
            args.arg3 = featureState;
            mHandler.obtainMessage(MSG_GET_FEATURE_COMPLETED, args).sendToTarget();
        }

        @Override
        public void onChallengeGenerated(int sensorId, int userId, long challenge) {
            mExecutor.execute(() -> sendChallengeGenerated(sensorId, userId, challenge));
            mHandler.obtainMessage(MSG_CHALLENGE_GENERATED, sensorId, userId, challenge)
                    .sendToTarget();
        }

        @Override
        public void onAuthenticationFrame(FaceAuthenticationFrame frame) {
            mExecutor.execute(() -> sendAuthenticationFrame(frame));
            mHandler.obtainMessage(MSG_AUTHENTICATION_FRAME, frame).sendToTarget();
        }

        @Override
        public void onEnrollmentFrame(FaceEnrollFrame frame) {
            mExecutor.execute(() -> sendEnrollmentFrame(frame));
            mHandler.obtainMessage(MSG_ENROLLMENT_FRAME, frame).sendToTarget();
        }
    };

@@ -181,7 +175,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
        if (mService == null) {
            Slog.v(TAG, "FaceAuthenticationManagerService was null");
        }
        mExecutor = context.getMainExecutor();
        mHandler = new MyHandler(context);
        if (context.checkCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL)
                == PackageManager.PERMISSION_GRANTED) {
            addAuthenticatorsRegisteredCallback(new IFaceAuthenticatorsRegisteredCallback.Stub() {
@@ -195,16 +189,18 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
    }

    /**
     * Returns an {@link Executor} for the given {@link Handler} or the main {@link Executor} if
     * {@code handler} is {@code null}.
     * Use the provided handler thread for events.
     */
    private @NonNull Executor createExecutorForHandlerIfNeeded(@Nullable Handler handler) {
        return handler != null ? new HandlerExecutor(handler) : mContext.getMainExecutor();
    private void useHandler(Handler handler) {
        if (handler != null) {
            mHandler = new MyHandler(handler.getLooper());
        } else if (mHandler.getLooper() != mContext.getMainLooper()) {
            mHandler = new MyHandler(mContext.getMainLooper());
        }
    }

    /**
     * @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FaceAuthenticateOptions)}.
     * @hide
     */
    @Deprecated
    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
@@ -216,22 +212,17 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
    }

    /**
     * Request authentication.
     *
     * <p>This call operates the face recognition hardware and starts capturing images.
     * Request authentication. This call operates the face recognition hardware and starts capturing images.
     * It terminates when
     * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
     * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at
     * which point the object is no longer valid. The operation can be canceled by using the
     * provided {@code cancel} object.
     * provided cancel object.
     *
     * @param crypto   the cryptographic operations to use for authentication or {@code null} if
     *                 none required
     * @param cancel   an object that can be used to cancel authentication or {@code null} if not
     *                 needed
     * @param crypto   object associated with the call or null if none required
     * @param cancel   an object that can be used to cancel authentication
     * @param callback an object to receive authentication events
     * @param handler  an optional handler to handle callback events or {@code null} to obtain main
     *                 {@link Executor} from {@link Context}
     * @param handler  an optional handler to handle callback events
     * @param options  additional options to customize this request
     * @throws IllegalArgumentException if the crypto operation is not supported or is not backed
     *                                  by
@@ -244,14 +235,6 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
    public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
            @NonNull AuthenticationCallback callback, @Nullable Handler handler,
            @NonNull FaceAuthenticateOptions options) {
        authenticate(crypto, cancel, callback, createExecutorForHandlerIfNeeded(handler),
                options, false /* allowBackgroundAuthentication */);
    }

    @RequiresPermission(anyOf = {USE_BIOMETRIC_INTERNAL, USE_BACKGROUND_FACE_AUTHENTICATION})
    private void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
            @NonNull AuthenticationCallback callback, @NonNull Executor executor,
            @NonNull FaceAuthenticateOptions options, boolean allowBackgroundAuthentication) {
        if (callback == null) {
            throw new IllegalArgumentException("Must supply an authentication callback");
        }
@@ -266,15 +249,13 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan

        if (mService != null) {
            try {
                mExecutor = executor;
                useHandler(handler);
                mAuthenticationCallback = callback;
                mCryptoObject = crypto;
                final long operationId = crypto != null ? crypto.getOpId() : 0;
                Trace.beginSection("FaceManager#authenticate");
                final long authId = allowBackgroundAuthentication
                        ? mService.authenticateInBackground(
                                mToken, operationId, mServiceReceiver, options)
                        : mService.authenticate(mToken, operationId, mServiceReceiver, options);
                final long authId = mService.authenticate(
                        mToken, operationId, mServiceReceiver, options);
                if (cancel != null) {
                    cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
                }
@@ -291,67 +272,6 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
        }
    }

    /**
     * Request background face authentication.
     *
     * <p>This call operates the face recognition hardware and starts capturing images.
     * It terminates when
     * {@link BiometricPrompt.AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
     * {@link BiometricPrompt.AuthenticationCallback#onAuthenticationSucceeded(
     * BiometricPrompt.AuthenticationResult)} is called, at which point the object is no longer
     * valid. The operation can be canceled by using the provided cancel object.
     *
     * <p>See {@link BiometricPrompt#authenticate} for more details. Please use
     * {@link BiometricPrompt} for face authentication unless the experience must be customized for
     * unique system-level utilities, like the lock screen or ambient background usage.
     *
     * @param executor the specified {@link Executor} to handle callback events; if {@code null},
     *                 the callback will be executed on the main {@link Executor}.
     * @param crypto   the cryptographic operations to use for authentication or {@code null} if
     *                 none required.
     * @param cancel   an object that can be used to cancel authentication or {@code null} if not
     *                 needed.
     * @param callback an object to receive authentication events.
     * @throws IllegalArgumentException if the crypto operation is not supported or is not backed
     *                                  by
     *                                  <a href="{@docRoot}training/articles/keystore.html">Android
     *                                  Keystore facility</a>.
     * @hide
     */
    @RequiresPermission(USE_BACKGROUND_FACE_AUTHENTICATION)
    @FlaggedApi(FLAG_FACE_BACKGROUND_AUTHENTICATION)
    @SystemApi
    public void authenticateInBackground(@Nullable Executor executor,
            @Nullable BiometricPrompt.CryptoObject crypto, @Nullable CancellationSignal cancel,
            @NonNull BiometricPrompt.AuthenticationCallback callback) {
        authenticate(crypto, cancel, new AuthenticationCallback() {
                    @Override
                    public void onAuthenticationError(int errorCode, CharSequence errString) {
                        callback.onAuthenticationError(errorCode, errString);
                    }

                    @Override
                    public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
                        callback.onAuthenticationHelp(helpCode, helpString);
                    }

                    @Override
                    public void onAuthenticationSucceeded(AuthenticationResult result) {
                        callback.onAuthenticationSucceeded(
                                new BiometricPrompt.AuthenticationResult(
                                        crypto,
                                        BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC));
                    }

                    @Override
                    public void onAuthenticationFailed() {
                        callback.onAuthenticationFailed();
                    }
                }, executor == null ? mContext.getMainExecutor() : executor,
                new FaceAuthenticateOptions.Builder().build(),
                true /* allowBackgroundAuthentication */);
    }

    /**
     * Uses the face hardware to detect for the presence of a face, without giving details about
     * accept/reject/lockout.
@@ -710,14 +630,12 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
    }

    /**
     * Determine if there are enrolled {@link Face} templates.
     * Determine if there is a face enrolled.
     *
     * @return {@code true} if there are enrolled {@link Face} templates, {@code false} otherwise
     * @return true if a face is enrolled, false otherwise
     * @hide
     */
    @RequiresPermission(anyOf = {USE_BIOMETRIC_INTERNAL, USE_BACKGROUND_FACE_AUTHENTICATION})
    @FlaggedApi(FLAG_FACE_BACKGROUND_AUTHENTICATION)
    @SystemApi
    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
    public boolean hasEnrolledTemplates() {
        return hasEnrolledTemplates(UserHandle.myUserId());
    }
@@ -882,7 +800,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
                                            PowerManager.PARTIAL_WAKE_LOCK,
                                            "faceLockoutResetCallback");
                                    wakeLock.acquire();
                                    mExecutor.execute(() -> {
                                    mHandler.post(() -> {
                                        try {
                                            callback.onLockoutReset(sensorId);
                                        } finally {
@@ -1352,6 +1270,70 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
        }
    }

    private class MyHandler extends Handler {
        private MyHandler(Context context) {
            super(context.getMainLooper());
        }

        private MyHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(android.os.Message msg) {
            Trace.beginSection("FaceManager#handleMessage: " + Integer.toString(msg.what));
            switch (msg.what) {
                case MSG_ENROLL_RESULT:
                    sendEnrollResult((Face) msg.obj, msg.arg1 /* remaining */);
                    break;
                case MSG_ACQUIRED:
                    sendAcquiredResult(msg.arg1 /* acquire info */, msg.arg2 /* vendorCode */);
                    break;
                case MSG_AUTHENTICATION_SUCCEEDED:
                    sendAuthenticatedSucceeded((Face) msg.obj, msg.arg1 /* userId */,
                            msg.arg2 == 1 /* isStrongBiometric */);
                    break;
                case MSG_AUTHENTICATION_FAILED:
                    sendAuthenticatedFailed();
                    break;
                case MSG_ERROR:
                    sendErrorResult(msg.arg1 /* errMsgId */, msg.arg2 /* vendorCode */);
                    break;
                case MSG_REMOVED:
                    sendRemovedResult((Face) msg.obj, msg.arg1 /* remaining */);
                    break;
                case MSG_SET_FEATURE_COMPLETED:
                    sendSetFeatureCompleted((boolean) msg.obj /* success */,
                            msg.arg1 /* feature */);
                    break;
                case MSG_GET_FEATURE_COMPLETED:
                    SomeArgs args = (SomeArgs) msg.obj;
                    sendGetFeatureCompleted((boolean) args.arg1 /* success */,
                            (int[]) args.arg2 /* features */,
                            (boolean[]) args.arg3 /* featureState */);
                    args.recycle();
                    break;
                case MSG_CHALLENGE_GENERATED:
                    sendChallengeGenerated(msg.arg1 /* sensorId */, msg.arg2 /* userId */,
                            (long) msg.obj /* challenge */);
                    break;
                case MSG_FACE_DETECTED:
                    sendFaceDetected(msg.arg1 /* sensorId */, msg.arg2 /* userId */,
                            (boolean) msg.obj /* isStrongBiometric */);
                    break;
                case MSG_AUTHENTICATION_FRAME:
                    sendAuthenticationFrame((FaceAuthenticationFrame) msg.obj /* frame */);
                    break;
                case MSG_ENROLLMENT_FRAME:
                    sendEnrollmentFrame((FaceEnrollFrame) msg.obj /* frame */);
                    break;
                default:
                    Slog.w(TAG, "Unknown message: " + msg.what);
            }
            Trace.endSection();
        }
    }

    private void sendSetFeatureCompleted(boolean success, int feature) {
        if (mSetFeatureCallback == null) {
            return;
+2 −7
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ interface IFaceService {
    byte[] dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer);

    // Retrieve static sensor properties for all face sensors
    @EnforcePermission(anyOf = {"USE_BIOMETRIC_INTERNAL", "USE_BACKGROUND_FACE_AUTHENTICATION"})
    @EnforcePermission("USE_BIOMETRIC_INTERNAL")
    List<FaceSensorPropertiesInternal> getSensorPropertiesInternal(String opPackageName);

    // Retrieve static sensor properties for the specified sensor
@@ -59,11 +59,6 @@ interface IFaceService {
    long authenticate(IBinder token, long operationId, IFaceServiceReceiver receiver,
            in FaceAuthenticateOptions options);

    // Authenticate with a face. A requestId is returned that can be used to cancel this operation.
    @EnforcePermission("USE_BACKGROUND_FACE_AUTHENTICATION")
    long authenticateInBackground(IBinder token, long operationId, IFaceServiceReceiver receiver,
            in FaceAuthenticateOptions options);

    // Uses the face hardware to detect for the presence of a face, without giving details
    // about accept/reject/lockout. A requestId is returned that can be used to cancel this
    // operation.
@@ -138,7 +133,7 @@ interface IFaceService {
    void revokeChallenge(IBinder token, int sensorId, int userId, String opPackageName, long challenge);

    // Determine if a user has at least one enrolled face
    @EnforcePermission(anyOf = {"USE_BIOMETRIC_INTERNAL", "USE_BACKGROUND_FACE_AUTHENTICATION"})
    @EnforcePermission("USE_BIOMETRIC_INTERNAL")
    boolean hasEnrolledFaces(int sensorId, int userId, String opPackageName);

    // Return the LockoutTracker status for the specified user
Loading