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

Commit 26850bb5 authored by Joshua Mccloskey's avatar Joshua Mccloskey Committed by Android (Google) Code Review
Browse files

Merge "Add FaceShell command to sync virtual enrollments."

parents 405e17b8 fa11942a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -5614,6 +5614,10 @@
    <permission android:name="android.permission.MANAGE_FINGERPRINT"
        android:protectionLevel="signature|privileged" />

    <!-- Allows managing (adding, removing) face templates. Reserved for the system. @hide -->
    <permission android:name="android.permission.MANAGE_FACE"
        android:protectionLevel="signature|privileged" />

    <!-- Allows an app to reset fingerprint attempt counter. Reserved for the system. @hide -->
    <permission android:name="android.permission.RESET_FINGERPRINT_LOCKOUT"
        android:protectionLevel="signature" />
+28 −0
Original line number Diff line number Diff line
@@ -18,11 +18,13 @@ package com.android.server.biometrics.sensors.face;

import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.MANAGE_BIOMETRIC;
import static android.Manifest.permission.MANAGE_FACE;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricsProtoEnums;
@@ -45,7 +47,9 @@ import android.os.IBinder;
import android.os.NativeHandle;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.UserHandle;
import android.util.Pair;
import android.util.Slog;
@@ -444,6 +448,15 @@ public class FaceService extends SystemService {
            mLockoutResetDispatcher.addCallback(callback, opPackageName);
        }

        @Override // Binder call
        public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
                @Nullable FileDescriptor err, @NonNull String[] args,
                @Nullable ShellCallback callback, @NonNull ResultReceiver resultReceiver)
                throws RemoteException {
            (new FaceShellCommand(FaceService.this))
                    .exec(this, in, out, err, args, callback, resultReceiver);
        }

        @Override // Binder call
        protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, String[] args) {
            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) {
@@ -732,4 +745,19 @@ public class FaceService extends SystemService {
     * @param handle a handle that was obtained from {@link #acquireSurfaceHandle(Surface)}.
     */
    public static native void releaseSurfaceHandle(@NonNull NativeHandle handle);


    void syncEnrollmentsNow() {
        Utils.checkPermissionOrShell(getContext(), MANAGE_FACE);
        if (Utils.isVirtualEnabled(getContext())) {
            Slog.i(TAG, "Sync virtual enrollments");
            final int userId = ActivityManager.getCurrentUser();
            for (ServiceProvider provider : mServiceProviders) {
                for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
                    provider.scheduleInternalCleanup(props.sensorId, userId, null /* callback */,
                            true /* favorHalEnrollments */);
                }
            }
        }
    }
}
+73 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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;

import android.os.ShellCommand;

import java.io.PrintWriter;

/** Handles shell commands for {@link FaceService}. */
public class FaceShellCommand extends ShellCommand {

    private final FaceService mService;

    public FaceShellCommand(FaceService service) {
        mService = service;
    }

    @Override
    public int onCommand(String cmd) {
        if (cmd == null) {
            onHelp();
            return 1;
        }

        try {
            switch (cmd) {
                case "help":
                    return doHelp();
                case "sync":
                    return doSync();
                default:
                    getOutPrintWriter().println("Unrecognized command: " + cmd);
            }
        } catch (Exception e) {
            getOutPrintWriter().println("Exception: " + e);
        }
        return -1;
    }

    @Override
    public void onHelp() {
        PrintWriter pw = getOutPrintWriter();
        pw.println("Face Service commands:");
        pw.println("  help");
        pw.println("      Print this help text.");
        pw.println("  sync");
        pw.println("      Sync enrollments now (virtualized sensors only).");
    }

    private int doHelp() {
        onHelp();
        return 0;
    }

    private int doSync() {
        mService.syncEnrollmentsNow();
        return 0;
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -139,6 +139,9 @@ public interface ServiceProvider {
    void scheduleInternalCleanup(int sensorId, int userId,
            @Nullable ClientMonitorCallback callback);

    void scheduleInternalCleanup(int sensorId, int userId,
            @Nullable ClientMonitorCallback callback, boolean favorHalEnrollments);

    void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto,
            boolean clearSchedulerBuffer);

+9 −0
Original line number Diff line number Diff line
@@ -540,6 +540,12 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
    @Override
    public void scheduleInternalCleanup(int sensorId, int userId,
            @Nullable ClientMonitorCallback callback) {
        scheduleInternalCleanup(sensorId, userId, callback, false /* favorHalEnrollments */);
    }

    @Override
    public void scheduleInternalCleanup(int sensorId, int userId,
            @Nullable ClientMonitorCallback callback, boolean favorHalEnrollments) {
        mHandler.post(() -> {
            final List<Face> enrolledList = getEnrolledFaces(sensorId, userId);
            final FaceInternalCleanupClient client =
@@ -551,6 +557,9 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
                            mBiometricContext, enrolledList,
                            FaceUtils.getInstance(sensorId),
                            mSensors.get(sensorId).getAuthenticatorIds());
            if (favorHalEnrollments) {
                client.setFavorHalEnrollments();
            }
            scheduleForSensor(sensorId, client, callback);
        });
    }
Loading