Merge "Wait for keyguard to be shown before completing the user switch." into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
df14a8f71f
@@ -151,6 +151,8 @@ import java.util.Arrays;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@@ -1707,7 +1709,8 @@ class UserController implements Handler.Callback {
|
|||||||
mInjector.getWindowManager().setSwitchingUser(true);
|
mInjector.getWindowManager().setSwitchingUser(true);
|
||||||
// Only lock if the user has a secure keyguard PIN/Pattern/Pwd
|
// Only lock if the user has a secure keyguard PIN/Pattern/Pwd
|
||||||
if (mInjector.getKeyguardManager().isDeviceSecure(userId)) {
|
if (mInjector.getKeyguardManager().isDeviceSecure(userId)) {
|
||||||
mInjector.getWindowManager().lockNow(null);
|
// Make sure the device is locked before moving on with the user switch
|
||||||
|
mInjector.lockDeviceNowAndWaitForKeyguardShown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3444,6 +3447,11 @@ class UserController implements Handler.Callback {
|
|||||||
WindowManagerService getWindowManager() {
|
WindowManagerService getWindowManager() {
|
||||||
return mService.mWindowManager;
|
return mService.mWindowManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ActivityTaskManagerInternal getActivityTaskManagerInternal() {
|
||||||
|
return mService.mAtmInternal;
|
||||||
|
}
|
||||||
|
|
||||||
void activityManagerOnUserStopped(@UserIdInt int userId) {
|
void activityManagerOnUserStopped(@UserIdInt int userId) {
|
||||||
LocalServices.getService(ActivityTaskManagerInternal.class).onUserStopped(userId);
|
LocalServices.getService(ActivityTaskManagerInternal.class).onUserStopped(userId);
|
||||||
}
|
}
|
||||||
@@ -3667,5 +3675,43 @@ class UserController implements Handler.Callback {
|
|||||||
void onSystemUserVisibilityChanged(boolean visible) {
|
void onSystemUserVisibilityChanged(boolean visible) {
|
||||||
getUserManagerInternal().onSystemUserVisibilityChanged(visible);
|
getUserManagerInternal().onSystemUserVisibilityChanged(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lockDeviceNowAndWaitForKeyguardShown() {
|
||||||
|
if (getWindowManager().isKeyguardLocked()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
|
||||||
|
t.traceBegin("lockDeviceNowAndWaitForKeyguardShown");
|
||||||
|
|
||||||
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
ActivityTaskManagerInternal.ScreenObserver screenObserver =
|
||||||
|
new ActivityTaskManagerInternal.ScreenObserver() {
|
||||||
|
@Override
|
||||||
|
public void onAwakeStateChanged(boolean isAwake) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onKeyguardStateChanged(boolean isShowing) {
|
||||||
|
if (isShowing) {
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
getActivityTaskManagerInternal().registerScreenObserver(screenObserver);
|
||||||
|
getWindowManager().lockDeviceNow();
|
||||||
|
try {
|
||||||
|
if (!latch.await(20, TimeUnit.SECONDS)) {
|
||||||
|
throw new RuntimeException("Keyguard is not shown in 20 seconds");
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
getActivityTaskManagerInternal().unregisterScreenObserver(screenObserver);
|
||||||
|
t.traceEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -262,8 +262,16 @@ public abstract class ActivityTaskManagerInternal {
|
|||||||
*/
|
*/
|
||||||
public abstract void setVr2dDisplayId(int vr2dDisplayId);
|
public abstract void setVr2dDisplayId(int vr2dDisplayId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a {@link ScreenObserver}.
|
||||||
|
*/
|
||||||
public abstract void registerScreenObserver(ScreenObserver observer);
|
public abstract void registerScreenObserver(ScreenObserver observer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters the given {@link ScreenObserver}.
|
||||||
|
*/
|
||||||
|
public abstract void unregisterScreenObserver(ScreenObserver observer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns is the caller has the same uid as the Recents component
|
* Returns is the caller has the same uid as the Recents component
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -296,6 +296,7 @@ import java.text.DateFormat;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -652,7 +653,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
*/
|
*/
|
||||||
float mMinPercentageMultiWindowSupportWidth;
|
float mMinPercentageMultiWindowSupportWidth;
|
||||||
|
|
||||||
final List<ActivityTaskManagerInternal.ScreenObserver> mScreenObservers = new ArrayList<>();
|
final List<ActivityTaskManagerInternal.ScreenObserver> mScreenObservers =
|
||||||
|
Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
// VR Vr2d Display Id.
|
// VR Vr2d Display Id.
|
||||||
int mVr2dDisplayId = INVALID_DISPLAY;
|
int mVr2dDisplayId = INVALID_DISPLAY;
|
||||||
@@ -5868,6 +5870,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
mScreenObservers.add(observer);
|
mScreenObservers.add(observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterScreenObserver(ScreenObserver observer) {
|
||||||
|
mScreenObservers.remove(observer);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCallerRecents(int callingUid) {
|
public boolean isCallerRecents(int callingUid) {
|
||||||
return ActivityTaskManagerService.this.isCallerRecents(callingUid);
|
return ActivityTaskManagerService.this.isCallerRecents(callingUid);
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ import static org.mockito.Matchers.anyBoolean;
|
|||||||
import static org.mockito.Matchers.anyInt;
|
import static org.mockito.Matchers.anyInt;
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
import static org.mockito.Mockito.doAnswer;
|
import static org.mockito.Mockito.doAnswer;
|
||||||
|
import static org.mockito.Mockito.doCallRealMethod;
|
||||||
import static org.mockito.Mockito.doNothing;
|
import static org.mockito.Mockito.doNothing;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
@@ -103,11 +104,13 @@ import com.android.server.am.UserState.KeyEvictedCallback;
|
|||||||
import com.android.server.pm.UserJourneyLogger;
|
import com.android.server.pm.UserJourneyLogger;
|
||||||
import com.android.server.pm.UserManagerInternal;
|
import com.android.server.pm.UserManagerInternal;
|
||||||
import com.android.server.pm.UserManagerService;
|
import com.android.server.pm.UserManagerService;
|
||||||
|
import com.android.server.wm.ActivityTaskManagerInternal;
|
||||||
import com.android.server.wm.WindowManagerService;
|
import com.android.server.wm.WindowManagerService;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -187,6 +190,7 @@ public class UserControllerTest {
|
|||||||
doNothing().when(mInjector).activityManagerOnUserStopped(anyInt());
|
doNothing().when(mInjector).activityManagerOnUserStopped(anyInt());
|
||||||
doNothing().when(mInjector).clearBroadcastQueueForUser(anyInt());
|
doNothing().when(mInjector).clearBroadcastQueueForUser(anyInt());
|
||||||
doNothing().when(mInjector).taskSupervisorRemoveUser(anyInt());
|
doNothing().when(mInjector).taskSupervisorRemoveUser(anyInt());
|
||||||
|
doNothing().when(mInjector).lockDeviceNowAndWaitForKeyguardShown();
|
||||||
mockIsUsersOnSecondaryDisplaysEnabled(false);
|
mockIsUsersOnSecondaryDisplaysEnabled(false);
|
||||||
// All UserController params are set to default.
|
// All UserController params are set to default.
|
||||||
|
|
||||||
@@ -951,6 +955,45 @@ public class UserControllerTest {
|
|||||||
.systemServiceManagerOnUserCompletedEvent(eq(user2), eq(event2a));
|
.systemServiceManagerOnUserCompletedEvent(eq(user2), eq(event2a));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStallUserSwitchUntilTheKeyguardIsShown() throws Exception {
|
||||||
|
// enable user switch ui, because keyguard is only shown then
|
||||||
|
mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
|
||||||
|
/* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
|
||||||
|
|
||||||
|
// mock the device to be secure in order to expect the keyguard to be shown
|
||||||
|
when(mInjector.mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(true);
|
||||||
|
|
||||||
|
// call real lockDeviceNowAndWaitForKeyguardShown method for this test
|
||||||
|
doCallRealMethod().when(mInjector).lockDeviceNowAndWaitForKeyguardShown();
|
||||||
|
|
||||||
|
// call startUser on a thread because we're expecting it to be blocked
|
||||||
|
Thread threadStartUser = new Thread(()-> {
|
||||||
|
mUserController.startUser(TEST_USER_ID, USER_START_MODE_FOREGROUND);
|
||||||
|
});
|
||||||
|
threadStartUser.start();
|
||||||
|
|
||||||
|
// make sure the switch is stalled...
|
||||||
|
Thread.sleep(2000);
|
||||||
|
// by checking REPORT_USER_SWITCH_MSG is not sent yet
|
||||||
|
assertNull(mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG));
|
||||||
|
// and the thread is still alive
|
||||||
|
assertTrue(threadStartUser.isAlive());
|
||||||
|
|
||||||
|
// mock send the keyguard shown event
|
||||||
|
ArgumentCaptor<ActivityTaskManagerInternal.ScreenObserver> captor = ArgumentCaptor.forClass(
|
||||||
|
ActivityTaskManagerInternal.ScreenObserver.class);
|
||||||
|
verify(mInjector.mActivityTaskManagerInternal).registerScreenObserver(captor.capture());
|
||||||
|
captor.getValue().onKeyguardStateChanged(true);
|
||||||
|
|
||||||
|
// verify the switch now moves on...
|
||||||
|
Thread.sleep(1000);
|
||||||
|
// by checking REPORT_USER_SWITCH_MSG is sent
|
||||||
|
assertNotNull(mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG));
|
||||||
|
// and the thread is finished
|
||||||
|
assertFalse(threadStartUser.isAlive());
|
||||||
|
}
|
||||||
|
|
||||||
private void setUpAndStartUserInBackground(int userId) throws Exception {
|
private void setUpAndStartUserInBackground(int userId) throws Exception {
|
||||||
setUpUser(userId, 0);
|
setUpUser(userId, 0);
|
||||||
mUserController.startUser(userId, USER_START_MODE_BACKGROUND);
|
mUserController.startUser(userId, USER_START_MODE_BACKGROUND);
|
||||||
@@ -1092,6 +1135,7 @@ public class UserControllerTest {
|
|||||||
private final IStorageManager mStorageManagerMock;
|
private final IStorageManager mStorageManagerMock;
|
||||||
private final UserManagerInternal mUserManagerInternalMock;
|
private final UserManagerInternal mUserManagerInternalMock;
|
||||||
private final WindowManagerService mWindowManagerMock;
|
private final WindowManagerService mWindowManagerMock;
|
||||||
|
private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
|
||||||
private final KeyguardManager mKeyguardManagerMock;
|
private final KeyguardManager mKeyguardManagerMock;
|
||||||
private final LockPatternUtils mLockPatternUtilsMock;
|
private final LockPatternUtils mLockPatternUtilsMock;
|
||||||
|
|
||||||
@@ -1111,6 +1155,7 @@ public class UserControllerTest {
|
|||||||
mUserManagerMock = mock(UserManagerService.class);
|
mUserManagerMock = mock(UserManagerService.class);
|
||||||
mUserManagerInternalMock = mock(UserManagerInternal.class);
|
mUserManagerInternalMock = mock(UserManagerInternal.class);
|
||||||
mWindowManagerMock = mock(WindowManagerService.class);
|
mWindowManagerMock = mock(WindowManagerService.class);
|
||||||
|
mActivityTaskManagerInternal = mock(ActivityTaskManagerInternal.class);
|
||||||
mStorageManagerMock = mock(IStorageManager.class);
|
mStorageManagerMock = mock(IStorageManager.class);
|
||||||
mKeyguardManagerMock = mock(KeyguardManager.class);
|
mKeyguardManagerMock = mock(KeyguardManager.class);
|
||||||
when(mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(true);
|
when(mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(true);
|
||||||
@@ -1171,6 +1216,11 @@ public class UserControllerTest {
|
|||||||
return mWindowManagerMock;
|
return mWindowManagerMock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
ActivityTaskManagerInternal getActivityTaskManagerInternal() {
|
||||||
|
return mActivityTaskManagerInternal;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
KeyguardManager getKeyguardManager() {
|
KeyguardManager getKeyguardManager() {
|
||||||
return mKeyguardManagerMock;
|
return mKeyguardManagerMock;
|
||||||
|
|||||||
Reference in New Issue
Block a user