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

Commit 811e7f2f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Finish TestSession implementation for FaceProvider"

parents 07c1877d 0a60a1ce
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -564,6 +564,11 @@ public class BiometricScheduler {

    public void dump(PrintWriter pw) {
        pw.println("Dump of BiometricScheduler " + getTag());
        pw.println("Current operation: " + mCurrentOperation);
        pw.println("Pending operations: " + mPendingOperations.size());
        for (Operation operation : mPendingOperations) {
            pw.println("Pending operation: " + operation);
        }
        for (CrashState crashState : mCrashStates) {
            pw.println("Crash State " + crashState);
        }
+205 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.server.biometrics.sensors.face.aidl;

import static android.Manifest.permission.TEST_BIOMETRIC;

import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.ITestSession;
import android.hardware.face.Face;
import android.hardware.face.IFaceServiceReceiver;
import android.os.Binder;
import android.util.Slog;

import com.android.server.biometrics.HardwareAuthTokenUtils;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.face.FaceUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;

/**
 * A test session implementation for {@link FaceProvider}. See
 * {@link android.hardware.biometrics.BiometricTestSession}.
 */
public class BiometricTestSessionImpl extends ITestSession.Stub {

    private static final String TAG = "BiometricTestSessionImpl";

    @NonNull private final Context mContext;
    private final int mSensorId;
    @NonNull private final FaceProvider mProvider;
    @NonNull private final Sensor mSensor;
    @NonNull private final Set<Integer> mEnrollmentIds;
    @NonNull private final Random mRandom;

    /**
     * Internal receiver currently only used for enroll. Results do not need to be forwarded to the
     * test, since enrollment is a platform-only API. The authentication path is tested through
     * the public BiometricPrompt APIs and does not use this receiver.
     */
    private final IFaceServiceReceiver mReceiver = new IFaceServiceReceiver.Stub() {
        @Override
        public void onEnrollResult(Face face, int remaining) {

        }

        @Override
        public void onAcquired(int acquireInfo, int vendorCode) {

        }

        @Override
        public void onAuthenticationSucceeded(Face face, int userId, boolean isStrongBiometric) {

        }

        @Override
        public void onFaceDetected(int sensorId, int userId, boolean isStrongBiometric) {

        }

        @Override
        public void onAuthenticationFailed() {

        }

        @Override
        public void onError(int error, int vendorCode) {

        }

        @Override
        public void onRemoved(Face face, int remaining) {

        }

        @Override
        public void onFeatureSet(boolean success, int feature) {

        }

        @Override
        public void onFeatureGet(boolean success, int feature, boolean value) {

        }

        @Override
        public void onChallengeGenerated(int sensorId, long challenge) {

        }

        @Override
        public void onChallengeInterrupted(int sensorId) {

        }

        @Override
        public void onChallengeInterruptFinished(int sensorId) {

        }
    };

    BiometricTestSessionImpl(@NonNull Context context, int sensorId,
            @NonNull FaceProvider provider, @NonNull Sensor sensor) {
        mContext = context;
        mSensorId = sensorId;
        mProvider = provider;
        mSensor = sensor;
        mEnrollmentIds = new HashSet<>();
        mRandom = new Random();
    }

    @Override
    public void setTestHalEnabled(boolean enabled) {
        Utils.checkPermission(mContext, TEST_BIOMETRIC);

        mProvider.setTestHalEnabled(enabled);
        mSensor.setTestHalEnabled(enabled);
    }

    @Override
    public void startEnroll(int userId) {
        Utils.checkPermission(mContext, TEST_BIOMETRIC);

        mProvider.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver,
                mContext.getOpPackageName(), new int[0] /* disabledFeatures */, null /* surface */);
    }

    @Override
    public void finishEnroll(int userId) {
        Utils.checkPermission(mContext, TEST_BIOMETRIC);

        int nextRandomId = mRandom.nextInt();
        while (mEnrollmentIds.contains(nextRandomId)) {
            nextRandomId = mRandom.nextInt();
        }

        mEnrollmentIds.add(nextRandomId);
        mSensor.getSessionForUser(userId).mHalSessionCallback
                .onEnrollmentProgress(nextRandomId, 0 /* remaining */);
    }

    @Override
    public void acceptAuthentication(int userId)  {
        Utils.checkPermission(mContext, TEST_BIOMETRIC);

        // Fake authentication with any of the existing faces
        List<Face> faces = FaceUtils.getInstance(mSensorId)
                .getBiometricsForUser(mContext, userId);
        if (faces.isEmpty()) {
            Slog.w(TAG, "No faces, returning");
            return;
        }
        final int fid = faces.get(0).getBiometricId();
        mSensor.getSessionForUser(userId).mHalSessionCallback.onAuthenticationSucceeded(fid,
                HardwareAuthTokenUtils.toHardwareAuthToken(new byte[69]));
    }

    @Override
    public void rejectAuthentication(int userId)  {
        Utils.checkPermission(mContext, TEST_BIOMETRIC);

        mSensor.getSessionForUser(userId).mHalSessionCallback.onAuthenticationFailed();
    }

    @Override
    public void notifyAcquired(int userId, int acquireInfo)  {
        Utils.checkPermission(mContext, TEST_BIOMETRIC);

        mSensor.getSessionForUser(userId).mHalSessionCallback
                .onAcquired((byte) acquireInfo, 0 /* vendorCode */);
    }

    @Override
    public void notifyError(int userId, int errorCode)  {
        Utils.checkPermission(mContext, TEST_BIOMETRIC);

        mSensor.getSessionForUser(userId).mHalSessionCallback.onError((byte) errorCode,
                0 /* vendorCode */);
    }

    @Override
    public void cleanupInternalState(int userId)  {
        Utils.checkPermission(mContext, TEST_BIOMETRIC);

        mProvider.scheduleInternalCleanup(mSensorId, userId);
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -47,6 +47,11 @@ class FaceGetAuthenticatorIdClient extends ClientMonitor<ISession> {
        // Nothing to do here
    }

    public void start(@NonNull Callback callback) {
        super.start(callback);
        startHalOperation();
    }

    @Override
    protected void startHalOperation() {
        try {
+14 −2
Original line number Diff line number Diff line
@@ -67,6 +67,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
    private static final String TAG = "FaceProvider";
    private static final int ENROLL_TIMEOUT_SEC = 75;

    private boolean mTestHalEnabled;

    @NonNull private final Context mContext;
    @NonNull private final String mHalInstanceName;
    @NonNull private final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
@@ -150,6 +152,10 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {

    @Nullable
    private synchronized IFace getHalInstance() {
        if (mTestHalEnabled) {
            return new TestHal();
        }

        if (mDaemon != null) {
            return mDaemon;
        }
@@ -525,7 +531,9 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {

    @Override
    public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto) {

        if (mSensors.contains(sensorId)) {
            mSensors.get(sensorId).dumpProtoState(sensorId, proto);
        }
    }

    @Override
@@ -576,7 +584,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
    @NonNull
    @Override
    public ITestSession createTestSession(int sensorId, @NonNull String opPackageName) {
        return null; // TODO
        return mSensors.get(sensorId).createTestSession();
    }

    @Override
@@ -593,4 +601,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
            }
        });
    }

    void setTestHalEnabled(boolean enabled) {
        mTestHalEnabled = enabled;
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -61,6 +61,11 @@ public class FaceResetLockoutClient extends ClientMonitor<ISession> {
        // Nothing to do here
    }

    public void start(@NonNull Callback callback) {
        super.start(callback);
        startHalOperation();
    }

    @Override
    protected void startHalOperation() {
        try {
Loading