Merge "Wrap start and stop user clients in an operation." into sc-dev

This commit is contained in:
Joe Bolinger
2021-06-28 23:04:55 +00:00
committed by Android (Google) Code Review
3 changed files with 84 additions and 23 deletions

View File

@@ -110,11 +110,21 @@ public class BiometricScheduler {
@Nullable final BaseClientMonitor.Callback mClientCallback; @Nullable final BaseClientMonitor.Callback mClientCallback;
@OperationState int mState; @OperationState int mState;
Operation(@NonNull BaseClientMonitor clientMonitor, Operation(
@Nullable BaseClientMonitor.Callback callback) { @NonNull BaseClientMonitor clientMonitor,
this.mClientMonitor = clientMonitor; @Nullable BaseClientMonitor.Callback callback
this.mClientCallback = callback; ) {
mState = STATE_WAITING_IN_QUEUE; this(clientMonitor, callback, STATE_WAITING_IN_QUEUE);
}
protected Operation(
@NonNull BaseClientMonitor clientMonitor,
@Nullable BaseClientMonitor.Callback callback,
@OperationState int state
) {
mClientMonitor = clientMonitor;
mClientCallback = callback;
mState = state;
} }
public boolean isHalOperation() { public boolean isHalOperation() {

View File

@@ -50,16 +50,26 @@ public class UserAwareBiometricScheduler extends BiometricScheduler {
@NonNull private final CurrentUserRetriever mCurrentUserRetriever; @NonNull private final CurrentUserRetriever mCurrentUserRetriever;
@NonNull private final UserSwitchCallback mUserSwitchCallback; @NonNull private final UserSwitchCallback mUserSwitchCallback;
@NonNull @VisibleForTesting final ClientFinishedCallback mClientFinishedCallback;
@Nullable private StopUserClient<?> mStopUserClient; @Nullable private StopUserClient<?> mStopUserClient;
@VisibleForTesting private class ClientFinishedCallback implements BaseClientMonitor.Callback {
class ClientFinishedCallback implements BaseClientMonitor.Callback { private final BaseClientMonitor mOwner;
ClientFinishedCallback(BaseClientMonitor owner) {
mOwner = owner;
}
@Override @Override
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) { public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) {
mHandler.post(() -> { mHandler.post(() -> {
Slog.d(getTag(), "[Client finished] " + clientMonitor + ", success: " + success); if (mOwner == clientMonitor && mOwner == mCurrentOperation.mClientMonitor) {
Slog.d(getTag(), "[Client finished] "
+ clientMonitor + ", success: " + success);
mCurrentOperation = null;
} else {
Slog.e(getTag(), "[Client finished, but not current operation], actual: "
+ mCurrentOperation + ", expected: " + mOwner);
}
startNextOperationIfIdle(); startNextOperationIfIdle();
}); });
@@ -76,7 +86,6 @@ public class UserAwareBiometricScheduler extends BiometricScheduler {
mCurrentUserRetriever = currentUserRetriever; mCurrentUserRetriever = currentUserRetriever;
mUserSwitchCallback = userSwitchCallback; mUserSwitchCallback = userSwitchCallback;
mClientFinishedCallback = new ClientFinishedCallback();
} }
public UserAwareBiometricScheduler(@NonNull String tag, public UserAwareBiometricScheduler(@NonNull String tag,
@@ -112,17 +121,27 @@ public class UserAwareBiometricScheduler extends BiometricScheduler {
} else if (currentUserId == UserHandle.USER_NULL) { } else if (currentUserId == UserHandle.USER_NULL) {
final BaseClientMonitor startClient = final BaseClientMonitor startClient =
mUserSwitchCallback.getStartUserClient(nextUserId); mUserSwitchCallback.getStartUserClient(nextUserId);
final ClientFinishedCallback finishedCallback =
new ClientFinishedCallback(startClient);
Slog.d(getTag(), "[Starting User] " + startClient); Slog.d(getTag(), "[Starting User] " + startClient);
startClient.start(mClientFinishedCallback); startClient.start(finishedCallback);
mCurrentOperation = new Operation(
startClient, finishedCallback, Operation.STATE_STARTED);
} else { } else {
if (mStopUserClient != null) { if (mStopUserClient != null) {
Slog.d(getTag(), "[Waiting for StopUser] " + mStopUserClient); Slog.d(getTag(), "[Waiting for StopUser] " + mStopUserClient);
} else { } else {
mStopUserClient = mUserSwitchCallback mStopUserClient = mUserSwitchCallback
.getStopUserClient(currentUserId); .getStopUserClient(currentUserId);
final ClientFinishedCallback finishedCallback =
new ClientFinishedCallback(mStopUserClient);
Slog.d(getTag(), "[Stopping User] current: " + currentUserId Slog.d(getTag(), "[Stopping User] current: " + currentUserId
+ ", next: " + nextUserId + ". " + mStopUserClient); + ", next: " + nextUserId + ". " + mStopUserClient);
mStopUserClient.start(mClientFinishedCallback); mStopUserClient.start(finishedCallback);
mCurrentOperation = new Operation(
mStopUserClient, finishedCallback, Operation.STATE_STARTED);
} }
} }
} }

View File

@@ -19,6 +19,7 @@ package com.android.server.biometrics.sensors;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -57,12 +58,16 @@ public class UserAwareBiometricSchedulerTest {
private TestUserStartedCallback mUserStartedCallback; private TestUserStartedCallback mUserStartedCallback;
private TestUserStoppedCallback mUserStoppedCallback; private TestUserStoppedCallback mUserStoppedCallback;
private int mCurrentUserId = UserHandle.USER_NULL; private int mCurrentUserId = UserHandle.USER_NULL;
private boolean mStartOperationsFinish;
private int mStartUserClientCount;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mToken = new Binder(); mToken = new Binder();
mStartOperationsFinish = true;
mStartUserClientCount = 0;
mUserStartedCallback = new TestUserStartedCallback(); mUserStartedCallback = new TestUserStartedCallback();
mUserStoppedCallback = new TestUserStoppedCallback(); mUserStoppedCallback = new TestUserStoppedCallback();
@@ -81,8 +86,9 @@ public class UserAwareBiometricSchedulerTest {
@NonNull @NonNull
@Override @Override
public StartUserClient<?, ?> getStartUserClient(int newUserId) { public StartUserClient<?, ?> getStartUserClient(int newUserId) {
mStartUserClientCount++;
return new TestStartUserClient(mContext, Object::new, mToken, newUserId, return new TestStartUserClient(mContext, Object::new, mToken, newUserId,
TEST_SENSOR_ID, mUserStartedCallback); TEST_SENSOR_ID, mUserStartedCallback, mStartOperationsFinish);
} }
}); });
} }
@@ -91,20 +97,41 @@ public class UserAwareBiometricSchedulerTest {
public void testScheduleOperation_whenNoUser() { public void testScheduleOperation_whenNoUser() {
mCurrentUserId = UserHandle.USER_NULL; mCurrentUserId = UserHandle.USER_NULL;
final int nextUserId = 0; final BaseClientMonitor nextClient = mock(BaseClientMonitor.class);
when(nextClient.getTargetUserId()).thenReturn(0);
BaseClientMonitor nextClient = mock(BaseClientMonitor.class);
when(nextClient.getTargetUserId()).thenReturn(nextUserId);
mScheduler.scheduleClientMonitor(nextClient); mScheduler.scheduleClientMonitor(nextClient);
waitForIdle();
assertEquals(0, mUserStoppedCallback.numInvocations); assertEquals(0, mUserStoppedCallback.numInvocations);
assertEquals(1, mUserStartedCallback.numInvocations); assertEquals(1, mUserStartedCallback.numInvocations);
waitForIdle();
verify(nextClient).start(any()); verify(nextClient).start(any());
} }
@Test
public void testScheduleOperation_whenNoUser_notStarted() {
mCurrentUserId = UserHandle.USER_NULL;
mStartOperationsFinish = false;
final BaseClientMonitor[] nextClients = new BaseClientMonitor[] {
mock(BaseClientMonitor.class),
mock(BaseClientMonitor.class),
mock(BaseClientMonitor.class)
};
for (BaseClientMonitor client : nextClients) {
when(client.getTargetUserId()).thenReturn(5);
mScheduler.scheduleClientMonitor(client);
waitForIdle();
}
assertEquals(0, mUserStoppedCallback.numInvocations);
assertEquals(0, mUserStartedCallback.numInvocations);
assertEquals(1, mStartUserClientCount);
for (BaseClientMonitor client : nextClients) {
verify(client, never()).start(any());
}
}
@Test @Test
public void testScheduleOperation_whenSameUser() { public void testScheduleOperation_whenSameUser() {
mCurrentUserId = 10; mCurrentUserId = 10;
@@ -192,10 +219,13 @@ public class UserAwareBiometricSchedulerTest {
} }
private static class TestStartUserClient extends StartUserClient<Object, Object> { private static class TestStartUserClient extends StartUserClient<Object, Object> {
private final boolean mShouldFinish;
public TestStartUserClient(@NonNull Context context, public TestStartUserClient(@NonNull Context context,
@NonNull LazyDaemon<Object> lazyDaemon, @Nullable IBinder token, int userId, @NonNull LazyDaemon<Object> lazyDaemon, @Nullable IBinder token, int userId,
int sensorId, @NonNull UserStartedCallback<Object> callback) { int sensorId, @NonNull UserStartedCallback<Object> callback, boolean shouldFinish) {
super(context, lazyDaemon, token, userId, sensorId, callback); super(context, lazyDaemon, token, userId, sensorId, callback);
mShouldFinish = shouldFinish;
} }
@Override @Override
@@ -206,8 +236,10 @@ public class UserAwareBiometricSchedulerTest {
@Override @Override
public void start(@NonNull Callback callback) { public void start(@NonNull Callback callback) {
super.start(callback); super.start(callback);
mUserStartedCallback.onUserStarted(getTargetUserId(), new Object()); if (mShouldFinish) {
callback.onClientFinished(this, true /* success */); mUserStartedCallback.onUserStarted(getTargetUserId(), new Object());
callback.onClientFinished(this, true /* success */);
}
} }
@Override @Override