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

Commit 9928fdd7 authored by Curtis Belmonte's avatar Curtis Belmonte
Browse files

Fix BiometricServiceBase crash in handleEnumerate

Test: atest BiometricServiceBaseTest

Bug: 152135554
Change-Id: Ibba26a571f5e15bf50935a727ce3ce44aad127a7
parent aa9d95ed
Loading
Loading
Loading
Loading
+27 −25
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.IHwBinder;
import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
@@ -52,6 +53,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.util.Slog;

import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.FrameworkStatsLog;
@@ -93,7 +95,22 @@ public abstract class BiometricServiceBase extends SystemService
    protected final Map<Integer, Long> mAuthenticatorIds =
            Collections.synchronizedMap(new HashMap<>());
    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 ArrayList<UserTemplate> mUnknownHALTemplates = new ArrayList<>();
@@ -483,23 +500,6 @@ public abstract class BiometricServiceBase extends SystemService
        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() {
        @Override
        public void run() {
@@ -647,8 +647,9 @@ public abstract class BiometricServiceBase extends SystemService
        mContext = context;
        mStatusBarService = IStatusBarService.Stub.asInterface(
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
        mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString(
                com.android.internal.R.string.config_keyguardComponent)).getPackageName();
        final ComponentName keyguardComponent = ComponentName.unflattenFromString(
                context.getResources().getString(R.string.config_keyguardComponent));
        mKeyguardPackage = keyguardComponent != null ? keyguardComponent.getPackageName() : null;
        mAppOps = context.getSystemService(AppOpsManager.class);
        mActivityTaskManager = ((ActivityTaskManager) context.getSystemService(
                Context.ACTIVITY_TASK_SERVICE)).getService();
@@ -798,9 +799,10 @@ public abstract class BiometricServiceBase extends SystemService
    }

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

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

        // All templates in the HAL for this user were enumerated
        if (remaining == 0) {
@@ -818,7 +820,7 @@ public abstract class BiometricServiceBase extends SystemService
                }
                removeClient(client);
                startCleanupUnknownHALTemplates();
            } else {
            } else if (client != null) {
                removeClient(client);
            }
        }
@@ -1145,7 +1147,7 @@ public abstract class BiometricServiceBase extends SystemService
            }
        }
        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;
        }
        if (mPendingClient == null) {
+145 −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;

import static org.mockito.ArgumentMatchers.anyInt;
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 BiometricServiceBase mBiometricServiceBase;

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

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        when(mContext.getResources()).thenReturn(mResources);
        when(mResources.getString(anyInt())).thenReturn("");
        mBiometricServiceBase = new TestableBiometricServiceBase(mContext);
    }

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