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

Commit 9e34dce8 authored by Kevin Chyn's avatar Kevin Chyn
Browse files

6/n: Move logging into AuthSession

The logging is state-dependent and as such can be moved into
AuthSession. Access to member variables can be restricted further.

Bug: 149067920

Test: atest com.android.server.biometrics
Change-Id: Ic42f95f9d879bb5791ce98c4bae5918e0d1d84cf
parent f6c1ae32
Loading
Loading
Loading
Loading
+81 −5
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricSensorReceiver;
import android.hardware.biometrics.IBiometricServiceReceiver;
import android.hardware.biometrics.IBiometricSysuiReceiver;
@@ -36,6 +37,7 @@ import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.FrameworkStatsLog;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -124,6 +126,7 @@ final class AuthSession {
    private final int mCallingUid;
    private final int mCallingPid;
    private final int mCallingUserId;
    private final boolean mDebugEnabled;

    // The current state, which can be either idle, called, or started
    private @SessionState int mState = STATE_AUTH_IDLE;
@@ -135,15 +138,15 @@ final class AuthSession {
    private int mVendorCodeEscrow;

    // Timestamp when authentication started
    long mStartTimeMs;
    private long mStartTimeMs;
    // Timestamp when hardware authentication occurred
    long mAuthenticatedTimeMs;
    private long mAuthenticatedTimeMs;

    AuthSession(IStatusBarService statusBarService, IBiometricSysuiReceiver sysuiReceiver,
            KeyStore keystore, Random random, PreAuthInfo preAuthInfo,
            IBinder token, long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
            IBiometricServiceReceiver clientReceiver, String opPackageName, Bundle bundle,
            int callingUid, int callingPid, int callingUserId) {
            int callingUid, int callingPid, int callingUserId, boolean debugEnabled) {
        mStatusBarService = statusBarService;
        mSysuiReceiver = sysuiReceiver;
        mKeyStore = keystore;
@@ -159,6 +162,7 @@ final class AuthSession {
        mCallingUid = callingUid;
        mCallingPid = callingPid;
        mCallingUserId = callingUserId;
        mDebugEnabled = debugEnabled;

        setSensorsToStateUnknown();
    }
@@ -484,8 +488,66 @@ final class AuthSession {
        mState = STATE_SHOWING_DEVICE_CREDENTIAL;
    }

    private void logOnDialogDismissed(@BiometricPrompt.DismissedReason int reason) {
        if (reason == BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED) {
            // Explicit auth, authentication confirmed.
            // Latency in this case is authenticated -> confirmed. <Biometric>Service
            // should have the first half (first acquired -> authenticated).
            final long latency = System.currentTimeMillis() - mAuthenticatedTimeMs;

            if (LoggableMonitor.DEBUG) {
                Slog.v(LoggableMonitor.TAG, "Confirmed! Modality: " + statsModality()
                        + ", User: " + mUserId
                        + ", IsCrypto: " + isCrypto()
                        + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT
                        + ", RequireConfirmation: " + mPreAuthInfo.confirmationRequested
                        + ", State: " + FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED
                        + ", Latency: " + latency);
            }

            FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED,
                    statsModality(),
                    mUserId,
                    isCrypto(),
                    BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
                    mPreAuthInfo.confirmationRequested,
                    FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED,
                    latency,
                    mDebugEnabled);
        } else {
            final long latency = System.currentTimeMillis() - mStartTimeMs;

            int error = reason == BiometricPrompt.DISMISSED_REASON_NEGATIVE
                    ? BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON
                    : reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL
                            ? BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED
                            : 0;
            if (LoggableMonitor.DEBUG) {
                Slog.v(LoggableMonitor.TAG, "Dismissed! Modality: " + statsModality()
                        + ", User: " + mUserId
                        + ", IsCrypto: " + isCrypto()
                        + ", Action: " + BiometricsProtoEnums.ACTION_AUTHENTICATE
                        + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT
                        + ", Error: " + error
                        + ", Latency: " + latency);
            }
            // Auth canceled
            FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED,
                    statsModality(),
                    mUserId,
                    isCrypto(),
                    BiometricsProtoEnums.ACTION_AUTHENTICATE,
                    BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
                    error,
                    0 /* vendorCode */,
                    mDebugEnabled,
                    latency);
        }
    }

    void onDialogDismissed(@BiometricPrompt.DismissedReason int reason,
            @Nullable byte[] credentialAttestation) {
        logOnDialogDismissed(reason);
        try {
            switch (reason) {
                case BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED:
@@ -609,8 +671,22 @@ final class AuthSession {
        return mState;
    }

    int getUserId() {
        return mUserId;
    private int statsModality() {
        int modality = 0;

        for (BiometricSensor sensor : mPreAuthInfo.eligibleSensors) {
            if ((sensor.modality & BiometricAuthenticator.TYPE_FINGERPRINT) != 0) {
                modality |= BiometricsProtoEnums.MODALITY_FINGERPRINT;
            }
            if ((sensor.modality & BiometricAuthenticator.TYPE_IRIS) != 0) {
                modality |= BiometricsProtoEnums.MODALITY_IRIS;
            }
            if ((sensor.modality & BiometricAuthenticator.TYPE_FACE) != 0) {
                modality |= BiometricsProtoEnums.MODALITY_FACE;
            }
        }

        return modality;
    }

    @Override
+2 −85
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@ import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricAuthenticator;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.IBiometricSensorReceiver;
@@ -61,7 +60,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.SystemService;

import java.io.FileDescriptor;
@@ -842,87 +840,6 @@ public class BiometricService extends SystemService {
        return false;
    }

    private void logDialogDismissed(int reason) {
        if (reason == BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED) {
            // Explicit auth, authentication confirmed.
            // Latency in this case is authenticated -> confirmed. <Biometric>Service
            // should have the first half (first acquired -> authenticated).
            final long latency = System.currentTimeMillis()
                    - mCurrentAuthSession.mAuthenticatedTimeMs;

            if (LoggableMonitor.DEBUG) {
                Slog.v(LoggableMonitor.TAG, "Confirmed! Modality: " + statsModality()
                        + ", User: " + mCurrentAuthSession.getUserId()
                        + ", IsCrypto: " + mCurrentAuthSession.isCrypto()
                        + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT
                        + ", RequireConfirmation: "
                        + mCurrentAuthSession.mPreAuthInfo.confirmationRequested
                        + ", State: " + FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED
                        + ", Latency: " + latency);
            }

            FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED,
                    statsModality(),
                    mCurrentAuthSession.getUserId(),
                    mCurrentAuthSession.isCrypto(),
                    BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
                    mCurrentAuthSession.mPreAuthInfo.confirmationRequested,
                    FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED,
                    latency,
                    mInjector.isDebugEnabled(getContext(), mCurrentAuthSession.getUserId()));
        } else {
            final long latency = System.currentTimeMillis() - mCurrentAuthSession.mStartTimeMs;

            int error = reason == BiometricPrompt.DISMISSED_REASON_NEGATIVE
                    ? BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON
                    : reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL
                            ? BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED
                            : 0;
            if (LoggableMonitor.DEBUG) {
                Slog.v(LoggableMonitor.TAG, "Dismissed! Modality: " + statsModality()
                        + ", User: " + mCurrentAuthSession.getUserId()
                        + ", IsCrypto: " + mCurrentAuthSession.isCrypto()
                        + ", Action: " + BiometricsProtoEnums.ACTION_AUTHENTICATE
                        + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT
                        + ", Error: " + error
                        + ", Latency: " + latency);
            }
            // Auth canceled
            FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED,
                    statsModality(),
                    mCurrentAuthSession.getUserId(),
                    mCurrentAuthSession.isCrypto(),
                    BiometricsProtoEnums.ACTION_AUTHENTICATE,
                    BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
                    error,
                    0 /* vendorCode */,
                    mInjector.isDebugEnabled(getContext(), mCurrentAuthSession.getUserId()),
                    latency);
        }
    }

    private int statsModality() {
        int modality = 0;
        if (mCurrentAuthSession == null) {
            return BiometricsProtoEnums.MODALITY_UNKNOWN;
        }

        for (BiometricSensor sensor :
                mCurrentAuthSession.mPreAuthInfo.eligibleSensors) {
            if ((sensor.modality & BiometricAuthenticator.TYPE_FINGERPRINT) != 0) {
                modality |= BiometricsProtoEnums.MODALITY_FINGERPRINT;
            }
            if ((sensor.modality & BiometricAuthenticator.TYPE_IRIS) != 0) {
                modality |= BiometricsProtoEnums.MODALITY_IRIS;
            }
            if ((sensor.modality & BiometricAuthenticator.TYPE_FACE) != 0) {
                modality |= BiometricsProtoEnums.MODALITY_FACE;
            }
        }

        return modality;
    }

    private void handleAuthenticationSucceeded(int sensorId, byte[] token) {
        Slog.v(TAG, "handleAuthenticationSucceeded(), sensorId: " + sensorId);
        // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
@@ -1001,7 +918,6 @@ public class BiometricService extends SystemService {
            return;
        }

        logDialogDismissed(reason);
        mCurrentAuthSession.onDialogDismissed(reason, credentialAttestation);
        mCurrentAuthSession = null;
    }
@@ -1122,9 +1038,10 @@ public class BiometricService extends SystemService {
            mCurrentAuthSession = null;
        }

        final boolean debugEnabled = mInjector.isDebugEnabled(getContext(), userId);
        mCurrentAuthSession = new AuthSession(mStatusBarService, mSysuiReceiver, mKeyStore, mRandom,
                preAuthInfo, token, operationId, userId, mBiometricSensorReceiver, receiver,
                opPackageName, bundle, callingUid, callingPid, callingUserId);
                opPackageName, bundle, callingUid, callingPid, callingUserId, debugEnabled);
        try {
            mCurrentAuthSession.goToInitialState();
        } catch (RemoteException e) {
+1 −1
Original line number Diff line number Diff line
@@ -198,7 +198,7 @@ public class AuthSessionTest {
        return new AuthSession(mStatusBarService, mSysuiReceiver, mKeyStore,
                mRandom, preAuthInfo, mToken, operationId, userId, mSensorReceiver,
                mClientReceiver, TEST_PACKAGE, bundle, callingUid,
                callingPid, callingUserId);
                callingPid, callingUserId, false /* debugEnabled */);
    }

    private Bundle createBiometricPromptBundle(@Authenticators.Types int authenticators) {