Loading services/core/java/com/android/server/biometrics/sensors/LockoutResetDispatcher.java +10 −4 Original line number Diff line number Diff line Loading @@ -25,7 +25,11 @@ import android.os.PowerManager; import android.os.RemoteException; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Allows clients (such as keyguard) to register for notifications on when biometric lockout Loading @@ -37,7 +41,8 @@ public class LockoutResetDispatcher implements IBinder.DeathRecipient { private static final String TAG = "LockoutResetTracker"; private final Context mContext; private final ArrayList<ClientCallback> mClientCallbacks; @VisibleForTesting final List<ClientCallback> mClientCallbacks = new ArrayList<>(); private static class ClientCallback { private static final long WAKELOCK_TIMEOUT_MS = 2000; Loading Loading @@ -81,7 +86,6 @@ public class LockoutResetDispatcher implements IBinder.DeathRecipient { public LockoutResetDispatcher(Context context) { mContext = context; mClientCallbacks = new ArrayList<>(); } public void addCallback(IBiometricServiceLockoutResetCallback callback, String opPackageName) { Loading @@ -106,11 +110,13 @@ public class LockoutResetDispatcher implements IBinder.DeathRecipient { @Override public void binderDied(IBinder who) { Slog.e(TAG, "Callback binder died: " + who); for (ClientCallback callback : mClientCallbacks) { final Iterator<ClientCallback> iterator = mClientCallbacks.iterator(); while (iterator.hasNext()) { final ClientCallback callback = iterator.next(); if (callback.mCallback.asBinder().equals(who)) { Slog.e(TAG, "Removing dead callback for: " + callback.mOpPackageName); callback.releaseWakelock(); mClientCallbacks.remove(callback); iterator.remove(); } } } Loading services/tests/servicestests/src/com/android/server/biometrics/sensors/LockoutResetDispatcherTest.java 0 → 100644 +105 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; import android.os.Bundle; import android.os.IBinder; import android.os.IRemoteCallback; import android.platform.test.annotations.Presubmit; import android.testing.TestableContext; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @Presubmit @SmallTest public class LockoutResetDispatcherTest { @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @Rule public final TestableContext mContext = new TestableContext( InstrumentationRegistry.getInstrumentation().getTargetContext(), null); @Mock private IBinder mBinder; @Mock private IBiometricServiceLockoutResetCallback mCallback; private LockoutResetDispatcher mDispatcher; @Before public void setup() { when(mCallback.asBinder()).thenReturn(mBinder); mDispatcher = new LockoutResetDispatcher(mContext); } @Test public void linksToDeath() throws Exception { mDispatcher.addCallback(mCallback, "package"); verify(mBinder).linkToDeath(eq(mDispatcher), anyInt()); } @Test public void notifyLockoutReset() throws Exception { final int sensorId = 24; mDispatcher.addCallback(mCallback, "some.package"); mDispatcher.notifyLockoutResetCallbacks(sensorId); final ArgumentCaptor<IRemoteCallback> captor = ArgumentCaptor.forClass(IRemoteCallback.class); verify(mCallback).onLockoutReset(eq(sensorId), captor.capture()); captor.getValue().sendResult(new Bundle()); } @Test public void releaseWakeLockOnDeath() { mDispatcher.addCallback(mCallback, "a.b.cee"); mDispatcher.binderDied(mBinder); // would be better to check the wake lock // but this project lacks the extended mockito support to do it assertThat(mDispatcher.mClientCallbacks).isEmpty(); } @Test public void releaseCorrectWakeLockOnDeath() { mDispatcher.addCallback(mCallback, "a.b"); mDispatcher.binderDied(mock(IBinder.class)); assertThat(mDispatcher.mClientCallbacks).hasSize(1); } } Loading
services/core/java/com/android/server/biometrics/sensors/LockoutResetDispatcher.java +10 −4 Original line number Diff line number Diff line Loading @@ -25,7 +25,11 @@ import android.os.PowerManager; import android.os.RemoteException; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Allows clients (such as keyguard) to register for notifications on when biometric lockout Loading @@ -37,7 +41,8 @@ public class LockoutResetDispatcher implements IBinder.DeathRecipient { private static final String TAG = "LockoutResetTracker"; private final Context mContext; private final ArrayList<ClientCallback> mClientCallbacks; @VisibleForTesting final List<ClientCallback> mClientCallbacks = new ArrayList<>(); private static class ClientCallback { private static final long WAKELOCK_TIMEOUT_MS = 2000; Loading Loading @@ -81,7 +86,6 @@ public class LockoutResetDispatcher implements IBinder.DeathRecipient { public LockoutResetDispatcher(Context context) { mContext = context; mClientCallbacks = new ArrayList<>(); } public void addCallback(IBiometricServiceLockoutResetCallback callback, String opPackageName) { Loading @@ -106,11 +110,13 @@ public class LockoutResetDispatcher implements IBinder.DeathRecipient { @Override public void binderDied(IBinder who) { Slog.e(TAG, "Callback binder died: " + who); for (ClientCallback callback : mClientCallbacks) { final Iterator<ClientCallback> iterator = mClientCallbacks.iterator(); while (iterator.hasNext()) { final ClientCallback callback = iterator.next(); if (callback.mCallback.asBinder().equals(who)) { Slog.e(TAG, "Removing dead callback for: " + callback.mOpPackageName); callback.releaseWakelock(); mClientCallbacks.remove(callback); iterator.remove(); } } } Loading
services/tests/servicestests/src/com/android/server/biometrics/sensors/LockoutResetDispatcherTest.java 0 → 100644 +105 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; import android.os.Bundle; import android.os.IBinder; import android.os.IRemoteCallback; import android.platform.test.annotations.Presubmit; import android.testing.TestableContext; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @Presubmit @SmallTest public class LockoutResetDispatcherTest { @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @Rule public final TestableContext mContext = new TestableContext( InstrumentationRegistry.getInstrumentation().getTargetContext(), null); @Mock private IBinder mBinder; @Mock private IBiometricServiceLockoutResetCallback mCallback; private LockoutResetDispatcher mDispatcher; @Before public void setup() { when(mCallback.asBinder()).thenReturn(mBinder); mDispatcher = new LockoutResetDispatcher(mContext); } @Test public void linksToDeath() throws Exception { mDispatcher.addCallback(mCallback, "package"); verify(mBinder).linkToDeath(eq(mDispatcher), anyInt()); } @Test public void notifyLockoutReset() throws Exception { final int sensorId = 24; mDispatcher.addCallback(mCallback, "some.package"); mDispatcher.notifyLockoutResetCallbacks(sensorId); final ArgumentCaptor<IRemoteCallback> captor = ArgumentCaptor.forClass(IRemoteCallback.class); verify(mCallback).onLockoutReset(eq(sensorId), captor.capture()); captor.getValue().sendResult(new Bundle()); } @Test public void releaseWakeLockOnDeath() { mDispatcher.addCallback(mCallback, "a.b.cee"); mDispatcher.binderDied(mBinder); // would be better to check the wake lock // but this project lacks the extended mockito support to do it assertThat(mDispatcher.mClientCallbacks).isEmpty(); } @Test public void releaseCorrectWakeLockOnDeath() { mDispatcher.addCallback(mCallback, "a.b"); mDispatcher.binderDied(mock(IBinder.class)); assertThat(mDispatcher.mClientCallbacks).hasSize(1); } }