Merge "Dismiss keyguard when target user has no password"

This commit is contained in:
Amith Yamasani
2021-11-17 15:59:47 +00:00
committed by Android (Google) Code Review
2 changed files with 112 additions and 11 deletions

View File

@@ -103,6 +103,7 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.widget.LockPatternUtils;
@@ -162,6 +163,7 @@ class UserController implements Handler.Callback {
static final int USER_UNLOCKED_MSG = 105;
static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 110;
static final int START_USER_SWITCH_FG_MSG = 120;
static final int COMPLETE_USER_SWITCH_MSG = 130;
// Message constant to clear {@link UserJourneySession} from {@link mUserIdToUserJourneyMap} if
// the user journey, defined in the UserLifecycleJourneyReported atom for statsd, is not
@@ -385,6 +387,7 @@ class UserController implements Handler.Callback {
@VisibleForTesting
UserController(Injector injector) {
mInjector = injector;
// This should be called early to avoid a null mHandler inside the injector
mHandler = mInjector.getHandler(this);
mUiHandler = mInjector.getUiHandler(this);
// User 0 is the first and only user that runs at boot.
@@ -1535,7 +1538,10 @@ class UserController implements Handler.Callback {
// with the option to show the user switcher on the keyguard.
if (userSwitchUiEnabled) {
mInjector.getWindowManager().setSwitchingUser(true);
mInjector.getWindowManager().lockNow(null);
// Only lock if the user has a secure keyguard PIN/Pattern/Pwd
if (mInjector.getKeyguardManager().isDeviceSecure(userId)) {
mInjector.getWindowManager().lockNow(null);
}
}
} else {
final Integer currentUserIdInt = mCurrentUserId;
@@ -1967,11 +1973,10 @@ class UserController implements Handler.Callback {
EventLog.writeEvent(EventLogTags.UC_CONTINUE_USER_SWITCH, oldUserId, newUserId);
if (isUserSwitchUiEnabled()) {
t.traceBegin("stopFreezingScreen");
mInjector.getWindowManager().stopFreezingScreen();
t.traceEnd();
}
// Do the keyguard dismiss and unfreeze later
mHandler.removeMessages(COMPLETE_USER_SWITCH_MSG);
mHandler.sendMessage(mHandler.obtainMessage(COMPLETE_USER_SWITCH_MSG, newUserId, 0));
uss.switching = false;
mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG);
mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_COMPLETE_MSG, newUserId, 0));
@@ -1981,6 +1986,34 @@ class UserController implements Handler.Callback {
t.traceEnd(); // end continueUserSwitch
}
@VisibleForTesting
void completeUserSwitch(int newUserId) {
if (isUserSwitchUiEnabled()) {
// If there is no challenge set, dismiss the keyguard right away
if (!mInjector.getKeyguardManager().isDeviceSecure(newUserId)) {
// Wait until the keyguard is dismissed to unfreeze
mInjector.dismissKeyguard(
new Runnable() {
public void run() {
unfreezeScreen();
}
},
"User Switch");
return;
} else {
unfreezeScreen();
}
}
}
@VisibleForTesting
void unfreezeScreen() {
TimingsTraceAndSlog t = new TimingsTraceAndSlog();
t.traceBegin("stopFreezingScreen");
mInjector.getWindowManager().stopFreezingScreen();
t.traceEnd();
}
private void moveUserToForeground(UserState uss, int oldUserId, int newUserId) {
boolean homeInFront = mInjector.taskSupervisorSwitchUser(newUserId, uss);
if (homeInFront) {
@@ -2772,6 +2805,9 @@ class UserController implements Handler.Callback {
case CLEAR_USER_JOURNEY_SESSION_MSG:
logAndClearSessionId(msg.arg1);
break;
case COMPLETE_USER_SWITCH_MSG:
completeUserSwitch(msg.arg1);
break;
}
return false;
}
@@ -2961,13 +2997,14 @@ class UserController implements Handler.Callback {
private final ActivityManagerService mService;
private UserManagerService mUserManager;
private UserManagerInternal mUserManagerInternal;
private Handler mHandler;
Injector(ActivityManagerService service) {
mService = service;
}
protected Handler getHandler(Handler.Callback callback) {
return new Handler(mService.mHandlerThread.getLooper(), callback);
return mHandler = new Handler(mService.mHandlerThread.getLooper(), callback);
}
protected Handler getUiHandler(Handler.Callback callback) {
@@ -3165,5 +3202,24 @@ class UserController implements Handler.Callback {
protected IStorageManager getStorageManager() {
return IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
}
protected void dismissKeyguard(Runnable runnable, String reason) {
getWindowManager().dismissKeyguard(new IKeyguardDismissCallback.Stub() {
@Override
public void onDismissError() throws RemoteException {
mHandler.post(runnable);
}
@Override
public void onDismissSucceeded() throws RemoteException {
mHandler.post(runnable);
}
@Override
public void onDismissCancelled() throws RemoteException {
mHandler.post(runnable);
}
}, reason);
}
}
}

View File

@@ -21,6 +21,7 @@ import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareC
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.server.am.UserController.COMPLETE_USER_SWITCH_MSG;
import static com.android.server.am.UserController.CONTINUE_USER_SWITCH_MSG;
import static com.android.server.am.UserController.REPORT_LOCKED_BOOT_COMPLETE_MSG;
import static com.android.server.am.UserController.REPORT_USER_SWITCH_COMPLETE_MSG;
@@ -59,6 +60,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.IUserSwitchObserver;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.Intent;
@@ -325,8 +327,16 @@ public class UserControllerTest {
assertWithMessage("No messages should be sent").that(actualCodes).isEmpty();
}
private void continueAndCompleteUserSwitch(UserState userState, int oldUserId, int newUserId) {
mUserController.continueUserSwitch(userState, oldUserId, newUserId);
mInjector.mHandler.removeMessages(UserController.COMPLETE_USER_SWITCH_MSG);
mUserController.completeUserSwitch(newUserId);
}
@Test
public void testContinueUserSwitch() throws RemoteException {
mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
/* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
// Start user -- this will update state of mUserController
mUserController.startUser(TEST_USER_ID, true);
Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
@@ -336,7 +346,28 @@ public class UserControllerTest {
int newUserId = reportMsg.arg2;
mInjector.mHandler.clearAllRecordedMessages();
// Verify that continueUserSwitch worked as expected
mUserController.continueUserSwitch(userState, oldUserId, newUserId);
continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
verify(mInjector, times(0)).dismissKeyguard(any(), anyString());
verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
continueUserSwitchAssertions(TEST_USER_ID, false);
}
@Test
public void testContinueUserSwitchDismissKeyguard() throws RemoteException {
when(mInjector.mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(false);
mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
/* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
// Start user -- this will update state of mUserController
mUserController.startUser(TEST_USER_ID, true);
Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
assertNotNull(reportMsg);
UserState userState = (UserState) reportMsg.obj;
int oldUserId = reportMsg.arg1;
int newUserId = reportMsg.arg2;
mInjector.mHandler.clearAllRecordedMessages();
// Verify that continueUserSwitch worked as expected
continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
verify(mInjector, times(1)).dismissKeyguard(any(), anyString());
verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
continueUserSwitchAssertions(TEST_USER_ID, false);
}
@@ -355,7 +386,7 @@ public class UserControllerTest {
int newUserId = reportMsg.arg2;
mInjector.mHandler.clearAllRecordedMessages();
// Verify that continueUserSwitch worked as expected
mUserController.continueUserSwitch(userState, oldUserId, newUserId);
continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
verify(mInjector.getWindowManager(), never()).stopFreezingScreen();
continueUserSwitchAssertions(TEST_USER_ID, false);
}
@@ -363,6 +394,7 @@ public class UserControllerTest {
private void continueUserSwitchAssertions(int expectedUserId, boolean backgroundUserStopping)
throws RemoteException {
Set<Integer> expectedCodes = new LinkedHashSet<>();
expectedCodes.add(COMPLETE_USER_SWITCH_MSG);
expectedCodes.add(REPORT_USER_SWITCH_COMPLETE_MSG);
if (backgroundUserStopping) {
expectedCodes.add(0); // this is for directly posting in stopping.
@@ -397,7 +429,7 @@ public class UserControllerTest {
}
@Test
public void testExplicitSystenUserStartInBackground() {
public void testExplicitSystemUserStartInBackground() {
setUpUser(UserHandle.USER_SYSTEM, 0);
assertFalse(mUserController.isSystemUserStarted());
assertTrue(mUserController.startUser(UserHandle.USER_SYSTEM, false, null));
@@ -646,7 +678,7 @@ public class UserControllerTest {
mUserStates.put(newUserId, userState);
mInjector.mHandler.clearAllRecordedMessages();
// Verify that continueUserSwitch worked as expected
mUserController.continueUserSwitch(userState, oldUserId, newUserId);
continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
verify(mInjector.getWindowManager(), times(expectedNumberOfCalls))
.stopFreezingScreen();
continueUserSwitchAssertions(newUserId, expectOldUserStopping);
@@ -701,6 +733,7 @@ public class UserControllerTest {
private final IStorageManager mStorageManagerMock;
private final UserManagerInternal mUserManagerInternalMock;
private final WindowManagerService mWindowManagerMock;
private final KeyguardManager mKeyguardManagerMock;
private final Context mCtx;
@@ -715,6 +748,8 @@ public class UserControllerTest {
mUserManagerInternalMock = mock(UserManagerInternal.class);
mWindowManagerMock = mock(WindowManagerService.class);
mStorageManagerMock = mock(IStorageManager.class);
mKeyguardManagerMock = mock(KeyguardManager.class);
when(mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(true);
}
@Override
@@ -753,6 +788,11 @@ public class UserControllerTest {
return mWindowManagerMock;
}
@Override
KeyguardManager getKeyguardManager() {
return mKeyguardManagerMock;
}
@Override
void updateUserConfiguration() {
Log.i(TAG, "updateUserConfiguration");
@@ -787,6 +827,11 @@ public class UserControllerTest {
protected IStorageManager getStorageManager() {
return mStorageManagerMock;
}
@Override
protected void dismissKeyguard(Runnable runnable, String reason) {
runnable.run();
}
}
private static class TestHandler extends Handler {