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

Commit 2619951a authored by Curtis Belmonte's avatar Curtis Belmonte Committed by Automerger Merge Worker
Browse files

Merge changes I7dcdef58,Ibba26a57 into rvc-dev am: f1ef159a am: e8f7daa8 am: a834a267

Change-Id: I9b877cead14cfa76f1506557e2963f2ef124a27b
parents 11f2e89b a834a267
Loading
Loading
Loading
Loading
+49 −31
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.biometrics;
package com.android.server.biometrics;


import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;


import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager;
@@ -43,6 +44,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder;
import android.os.IHwBinder;
import android.os.IHwBinder;
import android.os.IRemoteCallback;
import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.PowerManager;
import android.os.PowerManager;
import android.os.Process;
import android.os.Process;
import android.os.RemoteException;
import android.os.RemoteException;
@@ -52,6 +54,8 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManager;
import android.util.Slog;
import android.util.Slog;


import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.FrameworkStatsLog;
@@ -93,7 +97,22 @@ public abstract class BiometricServiceBase extends SystemService
    protected final Map<Integer, Long> mAuthenticatorIds =
    protected final Map<Integer, Long> mAuthenticatorIds =
            Collections.synchronizedMap(new HashMap<>());
            Collections.synchronizedMap(new HashMap<>());
    protected final AppOpsManager mAppOps;
    protected final AppOpsManager mAppOps;
    protected final H mHandler = new H();

    /**
     * Handler which all subclasses should post events to.
     */
    protected final Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case MSG_USER_SWITCHING:
                    handleUserSwitching(msg.arg1);
                    break;
                default:
                    Slog.w(getTag(), "Unknown message:" + msg.what);
            }
        }
    };


    private final IBinder mToken = new Binder(); // Used for internal enumeration
    private final IBinder mToken = new Binder(); // Used for internal enumeration
    private final ArrayList<UserTemplate> mUnknownHALTemplates = new ArrayList<>();
    private final ArrayList<UserTemplate> mUnknownHALTemplates = new ArrayList<>();
@@ -483,23 +502,6 @@ public abstract class BiometricServiceBase extends SystemService
        void resetLockout(byte[] token) throws RemoteException;
        void resetLockout(byte[] token) throws RemoteException;
    }
    }


    /**
     * Handler which all subclasses should post events to.
     */
    protected final class H extends Handler {
        @Override
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case MSG_USER_SWITCHING:
                    handleUserSwitching(msg.arg1);
                    break;

                default:
                    Slog.w(getTag(), "Unknown message:" + msg.what);
            }
        }
    }

    private final Runnable mOnTaskStackChangedRunnable = new Runnable() {
    private final Runnable mOnTaskStackChangedRunnable = new Runnable() {
        @Override
        @Override
        public void run() {
        public void run() {
@@ -647,8 +649,9 @@ public abstract class BiometricServiceBase extends SystemService
        mContext = context;
        mContext = context;
        mStatusBarService = IStatusBarService.Stub.asInterface(
        mStatusBarService = IStatusBarService.Stub.asInterface(
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
        mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString(
        final ComponentName keyguardComponent = ComponentName.unflattenFromString(
                com.android.internal.R.string.config_keyguardComponent)).getPackageName();
                context.getResources().getString(R.string.config_keyguardComponent));
        mKeyguardPackage = keyguardComponent != null ? keyguardComponent.getPackageName() : null;
        mAppOps = context.getSystemService(AppOpsManager.class);
        mAppOps = context.getSystemService(AppOpsManager.class);
        mActivityTaskManager = ((ActivityTaskManager) context.getSystemService(
        mActivityTaskManager = ((ActivityTaskManager) context.getSystemService(
                Context.ACTIVITY_TASK_SERVICE)).getService();
                Context.ACTIVITY_TASK_SERVICE)).getService();
@@ -671,8 +674,8 @@ public abstract class BiometricServiceBase extends SystemService


        // All client lifecycle must be managed on the handler.
        // All client lifecycle must be managed on the handler.
        mHandler.post(() -> {
        mHandler.post(() -> {
            handleError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
            Slog.e(getTag(), "Sending BIOMETRIC_ERROR_HW_UNAVAILABLE after HAL crash");
                    0 /*vendorCode */);
            handleError(getHalDeviceId(), BIOMETRIC_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
        });
        });


        FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
        FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
@@ -798,9 +801,10 @@ public abstract class BiometricServiceBase extends SystemService
    }
    }


    protected void handleEnumerate(BiometricAuthenticator.Identifier identifier, int remaining) {
    protected void handleEnumerate(BiometricAuthenticator.Identifier identifier, int remaining) {
        ClientMonitor client = getCurrentClient();
        ClientMonitor client = mCurrentClient;

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


        // All templates in the HAL for this user were enumerated
        // All templates in the HAL for this user were enumerated
        if (remaining == 0) {
        if (remaining == 0) {
@@ -818,7 +822,7 @@ public abstract class BiometricServiceBase extends SystemService
                }
                }
                removeClient(client);
                removeClient(client);
                startCleanupUnknownHALTemplates();
                startCleanupUnknownHALTemplates();
            } else {
            } else if (client != null) {
                removeClient(client);
                removeClient(client);
            }
            }
        }
        }
@@ -898,12 +902,16 @@ public abstract class BiometricServiceBase extends SystemService


    protected void cancelAuthenticationInternal(final IBinder token, final String opPackageName,
    protected void cancelAuthenticationInternal(final IBinder token, final String opPackageName,
            int callingUid, int callingPid, int callingUserId, boolean fromClient) {
            int callingUid, int callingPid, int callingUserId, boolean fromClient) {

        if (DEBUG) Slog.v(getTag(), "cancelAuthentication(" + opPackageName + ")");
        if (fromClient) {
        if (fromClient) {
            // Only check this if cancel was called from the client (app). If cancel was called
            // Only check this if cancel was called from the client (app). If cancel was called
            // from BiometricService, it means the dialog was dismissed due to user interaction.
            // from BiometricService, it means the dialog was dismissed due to user interaction.
            if (!canUseBiometric(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
            if (!canUseBiometric(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
                    callingUserId)) {
                    callingUserId)) {
                if (DEBUG) Slog.v(getTag(), "cancelAuthentication(): reject " + opPackageName);
                if (DEBUG) {
                    Slog.v(getTag(), "cancelAuthentication(): reject " + opPackageName);
                }
                return;
                return;
            }
            }
        }
        }
@@ -1059,7 +1067,8 @@ public abstract class BiometricServiceBase extends SystemService
     * @param newClient the new client that wants to connect
     * @param newClient the new client that wants to connect
     * @param initiatedByClient true for authenticate, remove and enroll
     * @param initiatedByClient true for authenticate, remove and enroll
     */
     */
    private void startClient(ClientMonitor newClient, boolean initiatedByClient) {
    @VisibleForTesting
    void startClient(ClientMonitor newClient, boolean initiatedByClient) {
        ClientMonitor currentClient = mCurrentClient;
        ClientMonitor currentClient = mCurrentClient;
        if (currentClient != null) {
        if (currentClient != null) {
            if (DEBUG) Slog.v(getTag(), "request stop current client " +
            if (DEBUG) Slog.v(getTag(), "request stop current client " +
@@ -1122,18 +1131,27 @@ public abstract class BiometricServiceBase extends SystemService
            Slog.e(getTag(), "Trying to start null client!");
            Slog.e(getTag(), "Trying to start null client!");
            return;
            return;
        }
        }

        if (DEBUG) Slog.v(getTag(), "starting client "
        if (DEBUG) Slog.v(getTag(), "starting client "
                + mCurrentClient.getClass().getSuperclass().getSimpleName()
                + mCurrentClient.getClass().getSuperclass().getSimpleName()
                + "(" + mCurrentClient.getOwnerString() + ")"
                + "(" + mCurrentClient.getOwnerString() + ")"
                + " targetUserId: " + mCurrentClient.getTargetUserId()
                + " targetUserId: " + mCurrentClient.getTargetUserId()
                + " currentUserId: " + mCurrentUserId
                + " currentUserId: " + mCurrentUserId
                + " cookie: " + cookie + "/" + mCurrentClient.getCookie());
                + " cookie: " + cookie + "/" + mCurrentClient.getCookie());

        if (cookie != mCurrentClient.getCookie()) {
        if (cookie != mCurrentClient.getCookie()) {
            Slog.e(getTag(), "Mismatched cookie");
            Slog.e(getTag(), "Mismatched cookie");
            return;
            return;
        }
        }

        int status = mCurrentClient.start();
        if (status == 0) {
            notifyClientActiveCallbacks(true);
            notifyClientActiveCallbacks(true);
        mCurrentClient.start();
        } else {
            mCurrentClient.onError(getHalDeviceId(), BIOMETRIC_ERROR_HW_UNAVAILABLE,
                    0 /* vendorCode */);
            removeClient(mCurrentClient);
        }
    }
    }


    protected void removeClient(ClientMonitor client) {
    protected void removeClient(ClientMonitor client) {
@@ -1145,7 +1163,7 @@ public abstract class BiometricServiceBase extends SystemService
            }
            }
        }
        }
        if (mCurrentClient != null) {
        if (mCurrentClient != null) {
            if (DEBUG) Slog.v(getTag(), "Done with client: " + client.getOwnerString());
            if (DEBUG) Slog.v(getTag(), "Done with client: " + mCurrentClient.getOwnerString());
            mCurrentClient = null;
            mCurrentClient = null;
        }
        }
        if (mPendingClient == null) {
        if (mPendingClient == null) {
+162 −0
Original line number Original line 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;

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.content.res.Resources;
import android.hardware.biometrics.BiometricAuthenticator;

import androidx.test.filters.SmallTest;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.List;

@SmallTest
public class BiometricServiceBaseTest {
    private static class TestableBiometricServiceBase extends BiometricServiceBase {
        TestableBiometricServiceBase(Context context) {
            super(context);
        }

        @Override
        protected String getTag() {
            return null;
        }

        @Override
        protected DaemonWrapper getDaemonWrapper() {
            return null;
        }

        @Override
        protected BiometricUtils getBiometricUtils() {
            return null;
        }

        @Override
        protected Constants getConstants() {
            return null;
        }

        @Override
        protected boolean hasReachedEnrollmentLimit(int userId) {
            return false;
        }

        @Override
        protected void updateActiveGroup(int userId, String clientPackage) {
        }

        @Override
        protected String getLockoutResetIntent() {
            return null;
        }

        @Override
        protected String getLockoutBroadcastPermission() {
            return null;
        }

        @Override
        protected long getHalDeviceId() {
            return 0;
        }

        @Override
        protected boolean hasEnrolledBiometrics(int userId) {
            return false;
        }

        @Override
        protected String getManageBiometricPermission() {
            return null;
        }

        @Override
        protected void checkUseBiometricPermission() {
        }

        @Override
        protected boolean checkAppOps(int uid, String opPackageName) {
            return false;
        }

        @Override
        protected List<? extends BiometricAuthenticator.Identifier> getEnrolledTemplates(
                int userId) {
            return null;
        }

        @Override
        protected int statsModality() {
            return 0;
        }

        @Override
        protected int getLockoutMode() {
            return 0;
        }
    }

    private static final int CLIENT_COOKIE = 0xc00c1e;

    private BiometricServiceBase mBiometricServiceBase;

    @Mock
    private Context mContext;
    @Mock
    private Resources mResources;
    @Mock
    private BiometricAuthenticator.Identifier mIdentifier;
    @Mock
    private ClientMonitor mClient;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);

        when(mContext.getResources()).thenReturn(mResources);
        when(mResources.getString(anyInt())).thenReturn("");
        when(mClient.getCookie()).thenReturn(CLIENT_COOKIE);

        mBiometricServiceBase = new TestableBiometricServiceBase(mContext);
    }

    @Test
    public void testHandleEnumerate_doesNotCrash_withNullClient() {
        mBiometricServiceBase.handleEnumerate(mIdentifier, 0 /* remaining */);
    }

    @Test
    public void testStartClient_sendsErrorAndRemovesClient_onNonzeroErrorCode() {
        when(mClient.start()).thenReturn(1);

        mBiometricServiceBase.startClient(mClient, false /* initiatedByClient */);

        verify(mClient).onError(anyLong(), anyInt(), anyInt());
        verify(mClient).destroy();
    }
}