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

Commit 943b19ec authored by Kevin Chyn's avatar Kevin Chyn Committed by Android (Google) Code Review
Browse files

Merge "Revert "finished implementation of fingerprintservice enumerate"" into oc-dev

parents dd83c200 32a12e9a
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ public abstract class EnumerateClient extends ClientMonitor {
    public int stop(boolean initiatedByClient) {
        IBiometricsFingerprint daemon = getFingerprintDaemon();
        if (daemon == null) {
            Slog.w(TAG, "stopEnumeration: no fingerprint HAL!");
            Slog.w(TAG, "stopAuthentication: no fingerprint HAL!");
            return ERROR_ESRCH;
        }
        try {
@@ -102,12 +102,12 @@ public abstract class EnumerateClient extends ClientMonitor {
    @Override
    public boolean onEnrollResult(int fingerId, int groupId, int rem) {
        if (DEBUG) Slog.w(TAG, "onEnrollResult() called for enumerate!");
        return true; // Invalid for Enumerate.
        return true; // Invalid for Remove
    }

    @Override
    public boolean onRemoved(int fingerId, int groupId, int remaining) {
        if (DEBUG) Slog.w(TAG, "onRemoved() called for enumerate!");
        return true; // Invalid for Enumerate.
        return true; // Invalid for Authenticate
    }
}
+33 −165
Original line number Diff line number Diff line
@@ -85,7 +85,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.LinkedList;

/**
 * A service to manage multiple clients that want to access the fingerprint HAL API.
@@ -135,20 +134,6 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
    private ClientMonitor mPendingClient;
    private PerformanceStats mPerformanceStats;


    private IBinder mToken = new Binder(); // used for internal FingerprintService enumeration
    private LinkedList<Integer> mEnumeratingUserIds = new LinkedList<>();
    private ArrayList<UserFingerprint> mUnknownFingerprints = new ArrayList<>(); // hw finterprints

    private class UserFingerprint {
        Fingerprint f;
        int userId;
        public UserFingerprint(Fingerprint f, int userId) {
            this.f = f;
            this.userId = userId;
        }
    }

    // Normal fingerprint authentications are tracked by mPerformanceMap.
    private HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>();

@@ -272,12 +257,10 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
        // This operation can be expensive, so keep track of the elapsed time. Might need to move to
        // background if it takes too long.
        long t = System.currentTimeMillis();

        mAuthenticatorIds.clear();
        mEnumeratingUserIds.clear();
        mUnknownFingerprints.clear();
        for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) {
            int userId = getUserOrWorkProfileId(null, user.id);
            mEnumeratingUserIds.add(userId);
            if (!mAuthenticatorIds.containsKey(userId)) {
                updateActiveGroup(userId, null);
            }
@@ -287,70 +270,12 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
        if (t > 1000) {
            Slog.w(TAG, "loadAuthenticatorIds() taking too long: " + t + "ms");
        }

        if (!mEnumeratingUserIds.isEmpty()) {
            enumerateNextUser();
        }
    }

    private void enumerateNextUser() {
        int nextUser = mEnumeratingUserIds.getFirst();
        updateActiveGroup(nextUser, null);
        boolean restricted = !hasPermission(MANAGE_FINGERPRINT);

        if (DEBUG) Slog.v(TAG, "Enumerating user id " + nextUser + " of "
                + mEnumeratingUserIds.size() + " remaining users");

        startEnumerate(mToken, nextUser, null, restricted, true /* internal */);
    }

    // Remove unknown fingerprints from hardware
    private void cleanupUnknownFingerprints() {
        if (!mUnknownFingerprints.isEmpty()) {
            Slog.w(TAG, "unknown fingerprint size: " + mUnknownFingerprints.size());
            UserFingerprint uf = mUnknownFingerprints.get(0);
            mUnknownFingerprints.remove(uf);
            boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
            updateActiveGroup(uf.userId, null);
            startRemove(mToken, uf.f.getFingerId(), uf.f.getGroupId(), uf.userId, null,
                    restricted, true /* internal */);
        }
    }

    protected void handleEnumerate(long deviceId, int fingerId, int groupId, int remaining) {
        if (DEBUG) Slog.w(TAG, "Enumerate: fid=" + fingerId
                + ", gid=" + groupId
                + ", dev=" + deviceId
                + ", rem=" + remaining);

        ClientMonitor client = mCurrentClient;

        if (client != null) {
            client.onEnumerationResult(fingerId, groupId, remaining);
        }

        // All fingerprints in hardware for this user were enumerated
        if (remaining == 0) {
            mEnumeratingUserIds.poll();

            if (client instanceof InternalEnumerateClient) {
                List<Fingerprint> enrolled = ((InternalEnumerateClient) client).getEnumeratedList();
                Slog.w(TAG, "Added " + enrolled.size() + " enumerated fingerprints for deletion");
                for (Fingerprint f : enrolled) {
                    mUnknownFingerprints.add(new UserFingerprint(f, client.getTargetUserId()));
                }
            }

            removeClient(client);

            if (!mEnumeratingUserIds.isEmpty()) {
                enumerateNextUser();
            } else if (client instanceof InternalEnumerateClient) {
                if (DEBUG) Slog.v(TAG, "Finished enumerating all users");
                // This will start a chain of InternalRemovalClients
                cleanupUnknownFingerprints();
            }
        }
        if (DEBUG) Slog.w(TAG, "Enumerate: fid=" + fingerId + ", gid="
                + groupId + "rem=" + remaining);
        // TODO: coordinate names with framework
    }

    protected void handleError(long deviceId, int error, int vendorCode) {
@@ -379,18 +304,10 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
    }

    protected void handleRemoved(long deviceId, int fingerId, int groupId, int remaining) {
        if (DEBUG) Slog.w(TAG, "Removed: fid=" + fingerId
                + ", gid=" + groupId
                + ", dev=" + deviceId
                + ", rem=" + remaining);

        ClientMonitor client = mCurrentClient;
        if (client != null && client.onRemoved(fingerId, groupId, remaining)) {
            removeClient(client);
        }
        if (client instanceof InternalRemovalClient && !mUnknownFingerprints.isEmpty()) {
            cleanupUnknownFingerprints();
        }
    }

    protected void handleAuthenticated(long deviceId, int fingerId, int groupId,
@@ -517,15 +434,7 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
        ClientMonitor currentClient = mCurrentClient;
        if (currentClient != null) {
            if (DEBUG) Slog.v(TAG, "request stop current client " + currentClient.getOwnerString());
            if (currentClient instanceof InternalEnumerateClient ||
                    currentClient instanceof InternalRemovalClient) {
                // This condition means we're currently running internal diagnostics to
                // remove extra fingerprints in the hardware and/or the software
                // TODO: design an escape hatch in case client never finishes
            }
            else {
            currentClient.stop(initiatedByClient);
            }
            mPendingClient = newClient;
            mHandler.removeCallbacks(mResetClientState);
            mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
@@ -542,30 +451,12 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
    }

    void startRemove(IBinder token, int fingerId, int groupId, int userId,
            IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
            IFingerprintServiceReceiver receiver, boolean restricted) {
        IBiometricsFingerprint daemon = getFingerprintDaemon();
        if (daemon == null) {
            Slog.w(TAG, "startRemove: no fingerprint HAL!");
            return;
        }

        if (internal) {
            Context context = getContext();
            InternalRemovalClient client = new InternalRemovalClient(context, mHalDeviceId,
                    token, receiver, fingerId, groupId, userId, restricted,
                    context.getOpPackageName()) {
                @Override
                public void notifyUserActivity() {

                }
                @Override
                public IBiometricsFingerprint getFingerprintDaemon() {
                    return FingerprintService.this.getFingerprintDaemon();
                }
            };
            startClient(client, true);
        }
        else {
        RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token,
                receiver, fingerId, groupId, userId, restricted, token.toString()) {
            @Override
@@ -580,34 +471,14 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
        };
        startClient(client, true);
    }
    }

    void startEnumerate(IBinder token, int userId,
        IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
        IFingerprintServiceReceiver receiver, boolean restricted) {
        IBiometricsFingerprint daemon = getFingerprintDaemon();
        if (daemon == null) {
            Slog.w(TAG, "startEnumerate: no fingerprint HAL!");
            return;
        }
        if (internal) {
            List<Fingerprint> enrolledList = getEnrolledFingerprints(userId);
            Context context = getContext();
            InternalEnumerateClient client = new InternalEnumerateClient(context, mHalDeviceId,
                    token, receiver, userId, userId, restricted, context.getOpPackageName(),
                    enrolledList) {
                @Override
                public void notifyUserActivity() {

                }

                @Override
                public IBiometricsFingerprint getFingerprintDaemon() {
                    return FingerprintService.this.getFingerprintDaemon();
                }
            };
            startClient(client, true);
        }
        else {
        EnumerateClient client = new EnumerateClient(getContext(), mHalDeviceId, token,
            receiver, userId, userId, restricted, token.toString()) {
            @Override
@@ -622,7 +493,6 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
        };
        startClient(client, true);
    }
    }

    public List<Fingerprint> getEnrolledFingerprints(int userId) {
        return mFingerprintUtils.getFingerprintsForUser(mContext, userId);
@@ -1108,14 +978,12 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    startRemove(token, fingerId, groupId, userId, receiver,
                            restricted, false /* internal */);
                    startRemove(token, fingerId, groupId, userId, receiver, restricted);
                }
            });

        }

        @Override // Binder call
        public void enumerate(final IBinder token, final int userId,
            final IFingerprintServiceReceiver receiver) {
            checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
@@ -1123,7 +991,7 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    startEnumerate(token, userId, receiver, restricted, false /* internal */);
                    startEnumerate(token, userId, receiver, restricted);
                }
            });

+0 −94
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.fingerprint;

import android.content.Context;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
import android.os.IBinder;
import android.util.Slog;
import java.util.ArrayList;
import java.util.List;

/**
 * An internal class to help clean up unknown fingerprints in the hardware and software
 */
public abstract class InternalEnumerateClient extends EnumerateClient {

    private List<Fingerprint> mEnrolledList;
    private List<Fingerprint> mEnumeratedList = new ArrayList<>(); // list of fp to delete

    public InternalEnumerateClient(Context context, long halDeviceId, IBinder token,
            IFingerprintServiceReceiver receiver, int groupId, int userId,
            boolean restricted, String owner, List<Fingerprint> enrolledList) {

        super(context, halDeviceId, token, receiver, userId, groupId, restricted, owner);
        mEnrolledList = enrolledList;
    }

    private void handleEnumeratedFingerprint(int fingerId, int groupId, int remaining) {

        boolean matched = false;
        for (int i=0; i<mEnrolledList.size(); i++) {
            if (mEnrolledList.get(i).getFingerId() == fingerId) {
                mEnrolledList.remove(i);
                matched = true;
                Slog.e(TAG, "Matched fingerprint fid=" + fingerId);
                break;
            }
        }

        // fingerId 0 means no fingerprints are in hardware
        if (!matched && fingerId != 0) {
            Fingerprint fingerprint = new Fingerprint("", groupId, fingerId, getHalDeviceId());
            mEnumeratedList.add(fingerprint);
        }
    }

    private void doFingerprintCleanup() {

        if (mEnrolledList == null) {
            return;
        }

        for (Fingerprint f : mEnrolledList) {
            Slog.e(TAG, "Internal Enumerate: Removing dangling enrolled fingerprint: "
                    + f.getName() + " " + f.getFingerId() + " " + f.getGroupId()
                    + " " + f.getDeviceId());

            FingerprintUtils.getInstance().removeFingerprintIdForUser(getContext(),
                    f.getFingerId(), getTargetUserId());
        }
        mEnrolledList.clear();
    }

    public List<Fingerprint> getEnumeratedList() {
        return mEnumeratedList;
    }

    @Override
    public boolean onEnumerationResult(int fingerId, int groupId, int remaining) {

        handleEnumeratedFingerprint(fingerId, groupId, remaining);
        if (remaining == 0) {
            doFingerprintCleanup();
        }

        return fingerId == 0; // done when id hits 0
    }

}
+0 −33
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.fingerprint;

import android.content.Context;
import android.os.IBinder;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
import com.android.server.fingerprint.RemovalClient;

public abstract class InternalRemovalClient extends RemovalClient {

    public InternalRemovalClient(Context context, long halDeviceId, IBinder token,
            IFingerprintServiceReceiver receiver, int fingerId, int groupId, int userId,
            boolean restricted, String owner) {

        super(context, halDeviceId, token, receiver, fingerId, groupId, userId, restricted, owner);

    }
}