From cbd9d418263c646800083a83917a1b2bc2453239 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Wed, 10 Feb 2021 17:25:04 -0800 Subject: [PATCH 1/2] Update biometric test paths 1) Test HALs should always respond to enumerate with no enrollments. CTS tests use this path to consciously remove (framework) enrollments when cleaning up. 2) Removes unnecessary TestSession classes from AIDL providers. These are redundant with the existing sessions returned from the TestHals themselves. We just need the framework to retrieve a new HAL session (from either the real HAL or the test HAL) whenever changing between test and non-test modes Test: atest CtsBiometricsTestCases Test: atest com.android.server.biometrics Fixes: 179949545 Fixes: 179856730 Change-Id: I1bbf0b77c69a36c9065193d10be32e942af8db70 --- .../biometrics/sensors/face/aidl/Sensor.java | 12 +- .../biometrics/sensors/face/aidl/TestHal.java | 52 ++++++-- .../sensors/face/aidl/TestSession.java | 117 ----------------- .../biometrics/sensors/face/hidl/TestHal.java | 5 +- .../sensors/fingerprint/aidl/Sensor.java | 14 +-- .../sensors/fingerprint/aidl/TestHal.java | 46 +++++-- .../sensors/fingerprint/aidl/TestSession.java | 119 ------------------ .../sensors/fingerprint/hidl/TestHal.java | 6 +- 8 files changed, 96 insertions(+), 275 deletions(-) delete mode 100644 services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java delete mode 100644 services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java index a204c6c20c0fe..90aa4ad556133 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java @@ -436,13 +436,7 @@ public class Sensor implements IBinder.DeathRecipient { mScheduler = new BiometricScheduler(tag, null /* gestureAvailabilityDispatcher */); mLockoutCache = new LockoutCache(); mAuthenticatorIds = new HashMap<>(); - mLazySession = () -> { - if (mTestHalEnabled) { - return new TestSession(mCurrentSession.mHalSessionCallback); - } else { - return mCurrentSession != null ? mCurrentSession.mSession : null; - } - }; + mLazySession = () -> mCurrentSession != null ? mCurrentSession.mSession : null; } @NonNull HalClientMonitor.LazyDaemon getLazySession() { @@ -499,6 +493,10 @@ public class Sensor implements IBinder.DeathRecipient { void setTestHalEnabled(boolean enabled) { Slog.w(mTag, "setTestHalEnabled: " + enabled); + if (enabled != mTestHalEnabled) { + // The framework should retrieve a new session from the HAL. + mCurrentSession = null; + } mTestHalEnabled = enabled; } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java index a38da3ad70b3c..ff65c931dd783 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java @@ -17,12 +17,14 @@ package com.android.server.biometrics.sensors.face.aidl; import android.hardware.biometrics.common.ICancellationSignal; +import android.hardware.biometrics.face.Error; import android.hardware.biometrics.face.IFace; import android.hardware.biometrics.face.ISession; import android.hardware.biometrics.face.ISessionCallback; import android.hardware.biometrics.face.SensorProps; import android.hardware.common.NativeHandle; import android.hardware.keymaster.HardwareAuthToken; +import android.os.RemoteException; import android.util.Slog; /** @@ -38,70 +40,96 @@ public class TestHal extends IFace.Stub { @Override public ISession createSession(int sensorId, int userId, ISessionCallback cb) { + Slog.w(TAG, "createSession, sensorId: " + sensorId + " userId: " + userId); + return new ISession.Stub() { @Override - public void generateChallenge(int cookie, int timeoutSec) { + public void generateChallenge(int cookie, int timeoutSec) throws RemoteException { Slog.w(TAG, "generateChallenge, cookie: " + cookie); + cb.onChallengeGenerated(0L); } @Override - public void revokeChallenge(int cookie, long challenge) { + public void revokeChallenge(int cookie, long challenge) throws RemoteException { Slog.w(TAG, "revokeChallenge: " + challenge + ", cookie: " + cookie); + cb.onChallengeRevoked(challenge); } @Override public ICancellationSignal enroll(int cookie, HardwareAuthToken hat, byte enrollmentType, byte[] features, NativeHandle previewSurface) { Slog.w(TAG, "enroll, cookie: " + cookie); - return null; + return new ICancellationSignal.Stub() { + @Override + public void cancel() throws RemoteException { + cb.onError(Error.CANCELED, 0 /* vendorCode */); + } + }; } @Override public ICancellationSignal authenticate(int cookie, long operationId) { Slog.w(TAG, "authenticate, cookie: " + cookie); - return null; + return new ICancellationSignal.Stub() { + @Override + public void cancel() throws RemoteException { + cb.onError(Error.CANCELED, 0 /* vendorCode */); + } + }; } @Override public ICancellationSignal detectInteraction(int cookie) { Slog.w(TAG, "detectInteraction, cookie: " + cookie); - return null; + return new ICancellationSignal.Stub() { + @Override + public void cancel() throws RemoteException { + cb.onError(Error.CANCELED, 0 /* vendorCode */); + } + }; } @Override - public void enumerateEnrollments(int cookie) { + public void enumerateEnrollments(int cookie) throws RemoteException { Slog.w(TAG, "enumerateEnrollments, cookie: " + cookie); + cb.onEnrollmentsEnumerated(new int[0]); } @Override - public void removeEnrollments(int cookie, int[] enrollmentIds) { + public void removeEnrollments(int cookie, int[] enrollmentIds) throws RemoteException { Slog.w(TAG, "removeEnrollments, cookie: " + cookie); + cb.onEnrollmentsRemoved(enrollmentIds); } @Override - public void getFeatures(int cookie, int enrollmentId) { + public void getFeatures(int cookie, int enrollmentId) throws RemoteException { Slog.w(TAG, "getFeatures, cookie: " + cookie); + cb.onFeaturesRetrieved(new byte[0], enrollmentId); } @Override public void setFeature(int cookie, HardwareAuthToken hat, int enrollmentId, - byte feature, boolean enabled) { + byte feature, boolean enabled) throws RemoteException { Slog.w(TAG, "setFeature, cookie: " + cookie); + cb.onFeatureSet(enrollmentId, feature); } @Override - public void getAuthenticatorId(int cookie) { + public void getAuthenticatorId(int cookie) throws RemoteException { Slog.w(TAG, "getAuthenticatorId, cookie: " + cookie); + cb.onAuthenticatorIdRetrieved(0L); } @Override - public void invalidateAuthenticatorId(int cookie) { + public void invalidateAuthenticatorId(int cookie) throws RemoteException { Slog.w(TAG, "invalidateAuthenticatorId, cookie: " + cookie); + cb.onAuthenticatorIdInvalidated(0L); } @Override - public void resetLockout(int cookie, HardwareAuthToken hat) { + public void resetLockout(int cookie, HardwareAuthToken hat) throws RemoteException { Slog.w(TAG, "resetLockout, cookie: " + cookie); + cb.onLockoutCleared(); } }; } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java deleted file mode 100644 index 23e69885841a4..0000000000000 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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.sensors.face.aidl; - -import android.annotation.NonNull; -import android.hardware.biometrics.common.ICancellationSignal; -import android.hardware.biometrics.face.Error; -import android.hardware.biometrics.face.ISession; -import android.hardware.common.NativeHandle; -import android.hardware.keymaster.HardwareAuthToken; -import android.os.Binder; -import android.os.IBinder; -import android.util.Slog; - -/** - * Test session that provides mostly no-ops. - */ -public class TestSession extends ISession.Stub { - private static final String TAG = "FaceTestSession"; - - @NonNull - private final Sensor.HalSessionCallback mHalSessionCallback; - - TestSession(@NonNull Sensor.HalSessionCallback halSessionCallback) { - mHalSessionCallback = halSessionCallback; - } - - @Override - public void generateChallenge(int cookie, int timeoutSec) { - mHalSessionCallback.onChallengeGenerated(0 /* challenge */); - } - - @Override - public void revokeChallenge(int cookie, long challenge) { - mHalSessionCallback.onChallengeRevoked(challenge); - } - - @Override - public ICancellationSignal enroll(int cookie, HardwareAuthToken hat, byte enrollmentType, - byte[] features, NativeHandle previewSurface) { - return null; - } - - @Override - public ICancellationSignal authenticate(int cookie, long operationId) { - return new ICancellationSignal() { - @Override - public void cancel() { - mHalSessionCallback.onError(Error.CANCELED, 0 /* vendorCode */); - } - - @Override - public IBinder asBinder() { - return new Binder(); - } - }; - } - - @Override - public ICancellationSignal detectInteraction(int cookie) { - return null; - } - - @Override - public void enumerateEnrollments(int cookie) { - - } - - @Override - public void removeEnrollments(int cookie, int[] enrollmentIds) { - - } - - @Override - public void getFeatures(int cookie, int enrollmentId) { - - } - - @Override - public void setFeature(int cookie, HardwareAuthToken hat, int enrollmentId, byte feature, - boolean enabled) { - - } - - @Override - public void getAuthenticatorId(int cookie) { - Slog.d(TAG, "getAuthenticatorId"); - // Immediately return a value so the framework can continue with subsequent requests. - mHalSessionCallback.onAuthenticatorIdRetrieved(0); - } - - @Override - public void invalidateAuthenticatorId(int cookie) { - Slog.d(TAG, "invalidateAuthenticatorId"); - // Immediately return a value so the framework can continue with subsequent requests. - mHalSessionCallback.onAuthenticatorIdInvalidated(0); - } - - @Override - public void resetLockout(int cookie, HardwareAuthToken hat) { - mHalSessionCallback.onLockoutCleared(); - } -} diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java index 00ca8025564df..13bd1c27d8c84 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java @@ -98,8 +98,11 @@ public class TestHal extends IBiometricsFace.Stub { } @Override - public int enumerate() { + public int enumerate() throws RemoteException { Slog.w(TAG, "enumerate"); + if (mCallback != null) { + mCallback.onEnumerate(0 /* deviceId */, new ArrayList<>(), 0 /* userId */); + } return 0; } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java index 6e1d7d6027567..a4dcac794d35c 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java @@ -416,13 +416,7 @@ class Sensor implements IBinder.DeathRecipient { mScheduler = new BiometricScheduler(tag, gestureAvailabilityDispatcher); mLockoutCache = new LockoutCache(); mAuthenticatorIds = new HashMap<>(); - mLazySession = () -> { - if (mTestHalEnabled) { - return new TestSession(mCurrentSession.mHalSessionCallback); - } else { - return mCurrentSession != null ? mCurrentSession.mSession : null; - } - }; + mLazySession = () -> mCurrentSession != null ? mCurrentSession.mSession : null; } @NonNull HalClientMonitor.LazyDaemon getLazySession() { @@ -478,7 +472,11 @@ class Sensor implements IBinder.DeathRecipient { } void setTestHalEnabled(boolean enabled) { - Slog.w(mTag, "setTestHalEnabled, enabled"); + Slog.w(mTag, "setTestHalEnabled: " + enabled); + if (enabled != mTestHalEnabled) { + // The framework should retrieve a new session from the HAL. + mCurrentSession = null; + } mTestHalEnabled = enabled; } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestHal.java index 66b68eeb335b9..8ed24b6f9d48e 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestHal.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestHal.java @@ -17,11 +17,13 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; import android.hardware.biometrics.common.ICancellationSignal; +import android.hardware.biometrics.fingerprint.Error; import android.hardware.biometrics.fingerprint.IFingerprint; import android.hardware.biometrics.fingerprint.ISession; import android.hardware.biometrics.fingerprint.ISessionCallback; import android.hardware.biometrics.fingerprint.SensorProps; import android.hardware.keymaster.HardwareAuthToken; +import android.os.RemoteException; import android.util.Slog; /** @@ -38,58 +40,82 @@ public class TestHal extends IFingerprint.Stub { @Override public ISession createSession(int sensorId, int userId, ISessionCallback cb) { + Slog.w(TAG, "createSession, sensorId: " + sensorId + " userId: " + userId); + return new ISession.Stub() { @Override - public void generateChallenge(int cookie, int timeoutSec) { + public void generateChallenge(int cookie, int timeoutSec) throws RemoteException { Slog.w(TAG, "generateChallenge, cookie: " + cookie); + cb.onChallengeGenerated(0L); } @Override - public void revokeChallenge(int cookie, long challenge) { + public void revokeChallenge(int cookie, long challenge) throws RemoteException { Slog.w(TAG, "revokeChallenge: " + challenge + ", cookie: " + cookie); + cb.onChallengeRevoked(challenge); } @Override public ICancellationSignal enroll(int cookie, HardwareAuthToken hat) { Slog.w(TAG, "enroll, cookie: " + cookie); - return null; + return new ICancellationSignal.Stub() { + @Override + public void cancel() throws RemoteException { + cb.onError(Error.CANCELED, 0 /* vendorCode */); + } + }; } @Override public ICancellationSignal authenticate(int cookie, long operationId) { Slog.w(TAG, "authenticate, cookie: " + cookie); - return null; + return new ICancellationSignal.Stub() { + @Override + public void cancel() throws RemoteException { + cb.onError(Error.CANCELED, 0 /* vendorCode */); + } + }; } @Override public ICancellationSignal detectInteraction(int cookie) { Slog.w(TAG, "detectInteraction, cookie: " + cookie); - return null; + return new ICancellationSignal.Stub() { + @Override + public void cancel() throws RemoteException { + cb.onError(Error.CANCELED, 0 /* vendorCode */); + } + }; } @Override - public void enumerateEnrollments(int cookie) { + public void enumerateEnrollments(int cookie) throws RemoteException { Slog.w(TAG, "enumerateEnrollments, cookie: " + cookie); + cb.onEnrollmentsEnumerated(new int[0]); } @Override - public void removeEnrollments(int cookie, int[] enrollmentIds) { + public void removeEnrollments(int cookie, int[] enrollmentIds) throws RemoteException { Slog.w(TAG, "removeEnrollments, cookie: " + cookie); + cb.onEnrollmentsRemoved(enrollmentIds); } @Override - public void getAuthenticatorId(int cookie) { + public void getAuthenticatorId(int cookie) throws RemoteException { Slog.w(TAG, "getAuthenticatorId, cookie: " + cookie); + cb.onAuthenticatorIdRetrieved(0L); } @Override - public void invalidateAuthenticatorId(int cookie) { + public void invalidateAuthenticatorId(int cookie) throws RemoteException { Slog.w(TAG, "invalidateAuthenticatorId, cookie: " + cookie); + cb.onAuthenticatorIdInvalidated(0L); } @Override - public void resetLockout(int cookie, HardwareAuthToken hat) { + public void resetLockout(int cookie, HardwareAuthToken hat) throws RemoteException { Slog.w(TAG, "resetLockout, cookie: " + cookie); + cb.onLockoutCleared(); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java deleted file mode 100644 index ac4f6651613d9..0000000000000 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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.sensors.fingerprint.aidl; - -import android.annotation.NonNull; -import android.hardware.biometrics.common.ICancellationSignal; -import android.hardware.biometrics.face.Error; -import android.hardware.biometrics.fingerprint.ISession; -import android.hardware.keymaster.HardwareAuthToken; -import android.os.Binder; -import android.os.IBinder; -import android.util.Slog; - -/** - * Test session that provides mostly no-ops. - */ -class TestSession extends ISession.Stub { - - private static final String TAG = "FingerprintTestSession"; - - @NonNull private final Sensor.HalSessionCallback mHalSessionCallback; - - TestSession(@NonNull Sensor.HalSessionCallback halSessionCallback) { - mHalSessionCallback = halSessionCallback; - } - - @Override - public void generateChallenge(int cookie, int timeoutSec) { - mHalSessionCallback.onChallengeGenerated(0 /* challenge */); - } - - @Override - public void revokeChallenge(int cookie, long challenge) { - mHalSessionCallback.onChallengeRevoked(challenge); - } - - @Override - public ICancellationSignal enroll(int cookie, HardwareAuthToken hat) { - return null; - } - - @Override - public ICancellationSignal authenticate(int cookie, long operationId) { - return new ICancellationSignal() { - @Override - public void cancel() { - mHalSessionCallback.onError(Error.CANCELED, 0 /* vendorCode */); - } - - @Override - public IBinder asBinder() { - return new Binder(); - } - }; - } - - @Override - public ICancellationSignal detectInteraction(int cookie) { - return null; - } - - @Override - public void enumerateEnrollments(int cookie) { - Slog.d(TAG, "enumerate"); - } - - @Override - public void removeEnrollments(int cookie, int[] enrollmentIds) { - Slog.d(TAG, "remove"); - } - - @Override - public void getAuthenticatorId(int cookie) { - Slog.d(TAG, "getAuthenticatorId"); - // Immediately return a value so the framework can continue with subsequent requests. - mHalSessionCallback.onAuthenticatorIdRetrieved(0); - } - - @Override - public void invalidateAuthenticatorId(int cookie) { - Slog.d(TAG, "invalidateAuthenticatorId"); - // Immediately return a value so the framework can continue with subsequent requests. - mHalSessionCallback.onAuthenticatorIdInvalidated(0); - } - - @Override - public void resetLockout(int cookie, HardwareAuthToken hat) { - mHalSessionCallback.onLockoutCleared(); - } - - @Override - public void onPointerDown(int pointerId, int x, int y, float minor, float major) { - - } - - @Override - public void onPointerUp(int pointerId) { - - } - - @Override - public void onUiReady() { - - } -} diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java index 57447f3a8cf79..14fdb507b0b17 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java @@ -83,8 +83,12 @@ public class TestHal extends IBiometricsFingerprint.Stub { } @Override - public int enumerate() { + public int enumerate() throws RemoteException { Slog.w(TAG, "Enumerate"); + if (mCallback != null) { + mCallback.onEnumerate(0 /* deviceId */, 0 /* fingerId */, 0 /* groupId */, + 0 /* remaining */); + } return 0; } From a5ae7ebb95e446f48f0480341eff5134489a820b Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Wed, 10 Feb 2021 18:39:29 -0800 Subject: [PATCH 2/2] Go to STATE_AUTH_STARTED_UI_SHOWING if UI was already showing This can happen if the retry button was pressed Bug: 179955752 Test: atest CtsBiometricsTestCases Test: atest com.android.server.biometrics Change-Id: Id632da3c13c81f8eee905cf0f00e7cb8cfaabaf3 --- .../java/com/android/server/biometrics/AuthSession.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java index c9560437799e2..f37fbf59af39e 100644 --- a/services/core/java/com/android/server/biometrics/AuthSession.java +++ b/services/core/java/com/android/server/biometrics/AuthSession.java @@ -257,11 +257,15 @@ public final class AuthSession implements IBinder.DeathRecipient { mUserId, mOpPackageName, mOperationId); + mState = STATE_AUTH_STARTED; } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); } + } else { + // The UI was already showing :) + mState = STATE_AUTH_STARTED_UI_SHOWING; } - mState = STATE_AUTH_STARTED; + } }