Merge "Update framework together with HIDL for accessibility"
diff --git a/core/java/android/hardware/biometrics/BiometricFaceConstants.java b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
index 1d9330d..9d37d99 100644
--- a/core/java/android/hardware/biometrics/BiometricFaceConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
@@ -28,6 +28,21 @@
  */
 public interface BiometricFaceConstants {
     //
+    // Accessibility constants
+    //
+    /**
+     * Require the user to look at the device during enrollment and
+     * authentication. Note this is to accommodate people who have limited
+     * vision.
+     */
+    public static final int FEATURE_REQUIRE_ATTENTION = 1;
+    /**
+     * Require a diverse set of poses during enrollment. Note this is to
+     * accommodate people with limited mobility.
+     */
+    public static final int FEATURE_REQUIRE_REQUIRE_DIVERSITY = 2;
+
+    //
     // Error messages from face authentication hardware during initialization, enrollment,
     // authentication or removal. Must agree with the list in HAL h file
     //
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 322863a..bac23b3 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -207,11 +207,8 @@
      * @hide
      */
     @RequiresPermission(MANAGE_BIOMETRIC)
-    public void enroll(byte[] token, CancellationSignal cancel, int flags,
-            int userId, EnrollmentCallback callback) {
-        if (userId == UserHandle.USER_CURRENT) {
-            userId = getCurrentUserId();
-        }
+    public void enroll(byte[] token, CancellationSignal cancel,
+            EnrollmentCallback callback, int[] disabledFeatures) {
         if (callback == null) {
             throw new IllegalArgumentException("Must supply an enrollment callback");
         }
@@ -228,8 +225,8 @@
         if (mService != null) {
             try {
                 mEnrollmentCallback = callback;
-                mService.enroll(mToken, token, userId, mServiceReceiver, flags,
-                        mContext.getOpPackageName());
+                mService.enroll(mToken, token, mServiceReceiver,
+                        mContext.getOpPackageName(), disabledFeatures);
             } catch (RemoteException e) {
                 Log.w(TAG, "Remote exception in enroll: ", e);
                 if (callback != null) {
@@ -284,10 +281,10 @@
      * @hide
      */
     @RequiresPermission(MANAGE_BIOMETRIC)
-    public void setRequireAttention(boolean requireAttention, byte[] token) {
+    public void setFeature(int feature, boolean enabled, byte[] token) {
         if (mService != null) {
             try {
-                mService.setRequireAttention(requireAttention, token);
+                mService.setFeature(feature, enabled, token);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -298,11 +295,11 @@
      * @hide
      */
     @RequiresPermission(MANAGE_BIOMETRIC)
-    public boolean getRequireAttention(byte[] token) {
+    public boolean getFeature(int feature) {
         boolean result = true;
         if (mService != null) {
             try {
-                mService.getRequireAttention(token);
+                result = mService.getFeature(feature);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index a15dcec..a1c88f8 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -50,8 +50,8 @@
             int callingUid, int callingPid, int callingUserId, boolean fromClient);
 
     // Start face enrollment
-    void enroll(IBinder token, in byte [] cryptoToken, int userId, IFaceServiceReceiver receiver,
-                int flags, String opPackageName);
+    void enroll(IBinder token, in byte [] cryptoToken, IFaceServiceReceiver receiver,
+                String opPackageName, in int [] disabledFeatures);
 
     // Cancel enrollment in progress
     void cancelEnrollment(IBinder token);
@@ -98,9 +98,9 @@
     // Enumerate all faces
     void enumerate(IBinder token, int userId, IFaceServiceReceiver receiver);
 
-    int setRequireAttention(boolean requireAttention, in byte [] token);
+    int setFeature(int feature, boolean enabled, in byte [] token);
 
-    boolean getRequireAttention(in byte [] token);
+    boolean getFeature(int feature);
 
     void userActivity();
 }
diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
index 9649ccd..32219aa 100644
--- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
+++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
@@ -282,9 +282,11 @@
 
         public EnrollClientImpl(Context context, DaemonWrapper daemon, long halDeviceId,
                 IBinder token, ServiceListener listener, int userId, int groupId,
-                byte[] cryptoToken, boolean restricted, String owner) {
+                byte[] cryptoToken, boolean restricted, String owner,
+                final int[] disabledFeatures) {
             super(context, getMetrics(), daemon, halDeviceId, token, listener,
-                    userId, groupId, cryptoToken, restricted, owner, getBiometricUtils());
+                    userId, groupId, cryptoToken, restricted, owner, getBiometricUtils(),
+                    disabledFeatures);
         }
 
         @Override
@@ -408,7 +410,8 @@
         int cancel() throws RemoteException;
         int remove(int groupId, int biometricId) throws RemoteException;
         int enumerate() throws RemoteException;
-        int enroll(byte[] cryptoToken, int groupId, int timeout) throws RemoteException;
+        int enroll(byte[] cryptoToken, int groupId, int timeout,
+                ArrayList<Integer> disabledFeatures) throws RemoteException;
     }
 
     /**
diff --git a/services/core/java/com/android/server/biometrics/EnrollClient.java b/services/core/java/com/android/server/biometrics/EnrollClient.java
index f858ef5..8a0f085 100644
--- a/services/core/java/com/android/server/biometrics/EnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/EnrollClient.java
@@ -34,15 +34,18 @@
     private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute
     private final byte[] mCryptoToken;
     private final BiometricUtils mBiometricUtils;
+    private final int[] mDisabledFeatures;
 
     public EnrollClient(Context context, Metrics metrics,
             BiometricServiceBase.DaemonWrapper daemon, long halDeviceId, IBinder token,
             BiometricServiceBase.ServiceListener listener, int userId, int groupId,
-            byte[] cryptoToken, boolean restricted, String owner, BiometricUtils utils) {
+            byte[] cryptoToken, boolean restricted, String owner, BiometricUtils utils,
+            final int[] disabledFeatures) {
         super(context, metrics, daemon, halDeviceId, token, listener, userId, groupId, restricted,
                 owner, 0 /* cookie */);
         mBiometricUtils = utils;
         mCryptoToken = Arrays.copyOf(cryptoToken, cryptoToken.length);
+        mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length);
     }
 
     @Override
@@ -74,7 +77,13 @@
     public int start() {
         final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
         try {
-            final int result = getDaemonWrapper().enroll(mCryptoToken, getGroupId(), timeout);
+            final ArrayList<Integer> disabledFeatures = new ArrayList<>();
+            for (int i = 0; i < mDisabledFeatures.length; i++) {
+                disabledFeatures.add(mDisabledFeatures[i]);
+            }
+
+            final int result = getDaemonWrapper().enroll(mCryptoToken, getGroupId(), timeout,
+                    disabledFeatures);
             if (result != 0) {
                 Slog.w(getLogTag(), "startEnroll failed, result=" + result);
                 mMetricsLogger.histogram(mMetrics.tagEnrollStartError(), result);
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index 557af04..72f73f6 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -113,17 +113,17 @@
         }
 
         @Override // Binder call
-        public void enroll(final IBinder token, final byte[] cryptoToken, final int userId,
-                final IFaceServiceReceiver receiver, final int flags,
-                final String opPackageName) {
+        public void enroll(final IBinder token, final byte[] cryptoToken,
+                final IFaceServiceReceiver receiver, final String opPackageName,
+                final int[] disabledFeatures) {
             checkPermission(MANAGE_BIOMETRIC);
 
             final boolean restricted = isRestricted();
             final EnrollClientImpl client = new EnrollClientImpl(getContext(), mDaemonWrapper,
                     mHalDeviceId, token, new ServiceListenerImpl(receiver), mCurrentUserId,
-                    0 /* groupId */, cryptoToken, restricted, opPackageName);
+                    0 /* groupId */, cryptoToken, restricted, opPackageName, disabledFeatures);
 
-            enrollInternal(client, userId);
+            enrollInternal(client, UserHandle.getCallingUserId());
         }
 
         @Override // Binder call
@@ -333,7 +333,7 @@
         }
 
         @Override
-        public int setRequireAttention(boolean requireAttention, final byte[] token) {
+        public int setFeature(int feature, boolean enabled, final byte[] token) {
             checkPermission(MANAGE_BIOMETRIC);
 
             final ArrayList<Byte> byteToken = new ArrayList<>();
@@ -343,10 +343,11 @@
 
             int result;
             try {
-                result = mDaemon != null ? mDaemon.setRequireAttention(requireAttention, byteToken)
+                result = mDaemon != null ? mDaemon.setFeature(feature, enabled, byteToken)
                         : Status.INTERNAL_ERROR;
             } catch (RemoteException e) {
-                Slog.e(getTag(), "Unable to setRequireAttention to " + requireAttention, e);
+                Slog.e(getTag(), "Unable to set feature: " + feature + " to enabled:" + enabled,
+                        e);
                 result = Status.INTERNAL_ERROR;
             }
 
@@ -354,17 +355,12 @@
         }
 
         @Override
-        public boolean getRequireAttention(final byte[] token) {
+        public boolean getFeature(int feature) {
             checkPermission(MANAGE_BIOMETRIC);
 
-            final ArrayList<Byte> byteToken = new ArrayList<>();
-            for (int i = 0; i < token.length; i++) {
-                byteToken.add(token[i]);
-            }
-
             boolean result = true;
             try {
-                result = mDaemon != null ? mDaemon.getRequireAttention(byteToken).value : true;
+                result = mDaemon != null ? mDaemon.getFeature(feature) : true;
             } catch (RemoteException e) {
                 Slog.e(getTag(), "Unable to getRequireAttention", e);
             }
@@ -612,7 +608,8 @@
         }
 
         @Override
-        public int enroll(byte[] cryptoToken, int groupId, int timeout) throws RemoteException {
+        public int enroll(byte[] cryptoToken, int groupId, int timeout,
+                ArrayList<Integer> disabledFeatures) throws RemoteException {
             IBiometricsFace daemon = getFaceDaemon();
             if (daemon == null) {
                 Slog.w(TAG, "enroll(): no face HAL!");
@@ -623,7 +620,7 @@
                 token.add(cryptoToken[i]);
             }
             // TODO: plumb requireAttention down from framework
-            return daemon.enroll(token, timeout, true /* requireAttention */);
+            return daemon.enroll(token, timeout, disabledFeatures);
         }
     };
 
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
index 6a5bc61..3895ef7 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -144,7 +144,7 @@
             final int groupId = userId; // default group for fingerprint enrollment
             final EnrollClientImpl client = new EnrollClientImpl(getContext(), mDaemonWrapper,
                     mHalDeviceId, token, new ServiceListenerImpl(receiver), mCurrentUserId, groupId,
-                    cryptoToken, restricted, opPackageName);
+                    cryptoToken, restricted, opPackageName, new int[0] /* disabledFeatures */);
 
             enrollInternal(client, userId);
         }
@@ -716,7 +716,8 @@
         }
 
         @Override
-        public int enroll(byte[] cryptoToken, int groupId, int timeout) throws RemoteException {
+        public int enroll(byte[] cryptoToken, int groupId, int timeout,
+                ArrayList<Integer> disabledFeatures) throws RemoteException {
             IBiometricsFingerprint daemon = getFingerprintDaemon();
             if (daemon == null) {
                 Slog.w(TAG, "enroll(): no fingerprint HAL!");