diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 66aa828ef8c3b..8b406c141fac9 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3529,6 +3529,12 @@
false
+
+ false
+
Remove guest
+
+ Reset guest
Guest
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7d5144f9cc570..24acba5a3adff 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1148,12 +1148,18 @@
Remove guest?
+
+ Reset guest?
+
All apps and data in this session will be deleted.
Remove
+
+ Reset
+
Welcome back, guest!
diff --git a/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java b/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java
index 95c68255db837..1d355f22edd5e 100644
--- a/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java
@@ -16,7 +16,6 @@
package com.android.systemui;
-import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -24,11 +23,8 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
-import android.os.RemoteException;
import android.os.UserHandle;
-import android.os.UserManager;
import android.util.Log;
-import android.view.WindowManagerGlobal;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.UiEventLogger;
@@ -36,6 +32,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.qs.QSUserSwitcherEvent;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.settings.SecureSettings;
/**
@@ -51,11 +48,14 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver {
@VisibleForTesting
public AlertDialog mNewSessionDialog;
private final UserTracker mUserTracker;
+ private final UserSwitcherController mUserSwitcherController;
private final UiEventLogger mUiEventLogger;
private final SecureSettings mSecureSettings;
- public GuestResumeSessionReceiver(UserTracker userTracker, UiEventLogger uiEventLogger,
+ public GuestResumeSessionReceiver(UserSwitcherController userSwitcherController,
+ UserTracker userTracker, UiEventLogger uiEventLogger,
SecureSettings secureSettings) {
+ mUserSwitcherController = userSwitcherController;
mUserTracker = userTracker;
mUiEventLogger = uiEventLogger;
mSecureSettings = secureSettings;
@@ -92,8 +92,8 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver {
int notFirstLogin = mSecureSettings.getIntForUser(
SETTING_GUEST_HAS_LOGGED_IN, 0, userId);
if (notFirstLogin != 0) {
- mNewSessionDialog = new ResetSessionDialog(context, mUserTracker, mUiEventLogger,
- userId);
+ mNewSessionDialog = new ResetSessionDialog(context, mUserSwitcherController,
+ mUserTracker, mUiEventLogger, userId);
mNewSessionDialog.show();
} else {
mSecureSettings.putIntForUser(SETTING_GUEST_HAS_LOGGED_IN, 1, userId);
@@ -101,48 +101,6 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver {
}
}
- /**
- * Wipes the guest session.
- *
- * The guest must be the current user and its id must be {@param userId}.
- */
- private static void wipeGuestSession(Context context, UserTracker userTracker, int userId) {
- UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- UserInfo currentUser = userTracker.getUserInfo();
- if (currentUser.id != userId) {
- Log.w(TAG, "User requesting to start a new session (" + userId + ")"
- + " is not current user (" + currentUser.id + ")");
- return;
- }
- if (!currentUser.isGuest()) {
- Log.w(TAG, "User requesting to start a new session (" + userId + ")"
- + " is not a guest");
- return;
- }
-
- boolean marked = userManager.markGuestForDeletion(currentUser.id);
- if (!marked) {
- Log.w(TAG, "Couldn't mark the guest for deletion for user " + userId);
- return;
- }
- UserInfo newGuest = userManager.createGuest(context, currentUser.name);
-
- try {
- if (newGuest == null) {
- Log.e(TAG, "Could not create new guest, switching back to system user");
- ActivityManager.getService().switchUser(UserHandle.USER_SYSTEM);
- userManager.removeUser(currentUser.id);
- WindowManagerGlobal.getWindowManagerService().lockNow(null /* options */);
- return;
- }
- ActivityManager.getService().switchUser(newGuest.id);
- userManager.removeUser(currentUser.id);
- } catch (RemoteException e) {
- Log.e(TAG, "Couldn't wipe session because ActivityManager or WindowManager is dead");
- return;
- }
- }
-
private void cancelDialog() {
if (mNewSessionDialog != null && mNewSessionDialog.isShowing()) {
mNewSessionDialog.cancel();
@@ -162,11 +120,14 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver {
@VisibleForTesting
public static final int BUTTON_DONTWIPE = BUTTON_POSITIVE;
- private final UserTracker mUserTracker;
+ private final UserSwitcherController mUserSwitcherController;
private final UiEventLogger mUiEventLogger;
private final int mUserId;
- ResetSessionDialog(Context context, UserTracker userTracker, UiEventLogger uiEventLogger,
+ ResetSessionDialog(Context context,
+ UserSwitcherController userSwitcherController,
+ UserTracker userTracker,
+ UiEventLogger uiEventLogger,
int userId) {
super(context);
@@ -179,7 +140,7 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver {
setButton(BUTTON_DONTWIPE,
context.getString(R.string.guest_wipe_session_dontwipe), this);
- mUserTracker = userTracker;
+ mUserSwitcherController = userSwitcherController;
mUiEventLogger = uiEventLogger;
mUserId = userId;
}
@@ -188,7 +149,7 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver {
public void onClick(DialogInterface dialog, int which) {
if (which == BUTTON_WIPE) {
mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_WIPE);
- wipeGuestSession(getContext(), mUserTracker, mUserId);
+ mUserSwitcherController.removeGuestUser(mUserId, UserHandle.USER_NULL);
dismiss();
} else if (which == BUTTON_DONTWIPE) {
mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_CONTINUE);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 327698392ac73..88e9f69620ed0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -119,6 +119,7 @@ import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.DeviceConfigProxy;
import java.io.FileDescriptor;
@@ -257,6 +258,9 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable,
/** TrustManager for letting it know when we change visibility */
private final TrustManager mTrustManager;
+ /** UserSwitcherController for creating guest user on boot complete */
+ private final UserSwitcherController mUserSwitcherController;
+
/**
* Used to keep the device awake while to ensure the keyguard finishes opening before
* we sleep.
@@ -805,6 +809,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable,
KeyguardUpdateMonitor keyguardUpdateMonitor, DumpManager dumpManager,
@UiBackground Executor uiBgExecutor, PowerManager powerManager,
TrustManager trustManager,
+ UserSwitcherController userSwitcherController,
DeviceConfigProxy deviceConfig,
NavigationModeController navigationModeController,
KeyguardDisplayManager keyguardDisplayManager,
@@ -825,6 +830,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable,
mUpdateMonitor = keyguardUpdateMonitor;
mPM = powerManager;
mTrustManager = trustManager;
+ mUserSwitcherController = userSwitcherController;
mKeyguardDisplayManager = keyguardDisplayManager;
dumpManager.registerDumpable(getClass().getName(), this);
mDeviceConfig = deviceConfig;
@@ -2558,6 +2564,11 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable,
@Override
public void onBootCompleted() {
synchronized (this) {
+ if (mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_guestUserAutoCreated)) {
+ // TODO(b/191067027): Move post-boot guest creation to system_server
+ mUserSwitcherController.guaranteeGuestPresent();
+ }
mBootCompleted = true;
adjustStatusBarLocked(false, true);
if (mBootSendUserPresent) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 05d1361c3ab83..8a383b974d77b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -54,6 +54,7 @@ import com.android.systemui.statusbar.phone.KeyguardLiftController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.sensors.AsyncSensorManager;
import com.android.systemui.util.settings.GlobalSettings;
@@ -92,6 +93,7 @@ public class KeyguardModule {
DumpManager dumpManager,
PowerManager powerManager,
TrustManager trustManager,
+ UserSwitcherController userSwitcherController,
@UiBackground Executor uiBgExecutor,
DeviceConfigProxy deviceConfig,
NavigationModeController navigationModeController,
@@ -114,6 +116,7 @@ public class KeyguardModule {
uiBgExecutor,
powerManager,
trustManager,
+ userSwitcherController,
deviceConfig,
navigationModeController,
keyguardDisplayManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index e2129bdc9a057..fae4423a4277b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -21,6 +21,7 @@ import static android.os.UserManager.SWITCHABILITY_STATUS_OK;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import static com.android.systemui.DejankUtils.whitelistIpcs;
+import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -49,6 +50,7 @@ import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManagerGlobal;
import android.widget.BaseAdapter;
import com.android.internal.annotations.VisibleForTesting;
@@ -64,6 +66,7 @@ import com.android.systemui.SystemUISecondaryUserService;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.QSUserSwitcherEvent;
@@ -79,6 +82,8 @@ import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
import javax.inject.Inject;
import javax.inject.Provider;
@@ -125,21 +130,31 @@ public class UserSwitcherController implements Dumpable {
// When false, there won't be any visual affordance to add a new user from the keyguard even if
// the user is unlocked
private boolean mAddUsersFromLockScreen;
- private boolean mPauseRefreshUsers;
+ @VisibleForTesting
+ boolean mPauseRefreshUsers;
private int mSecondaryUser = UserHandle.USER_NULL;
private Intent mSecondaryUserServiceIntent;
private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
private final UiEventLogger mUiEventLogger;
public final DetailAdapter mUserDetailAdapter;
+ private final Executor mUiBgExecutor;
+ private final boolean mGuestUserAutoCreated;
+ private final AtomicBoolean mGuestCreationScheduled;
@Inject
- public UserSwitcherController(Context context, UserManager userManager, UserTracker userTracker,
+ public UserSwitcherController(Context context,
+ UserManager userManager,
+ UserTracker userTracker,
KeyguardStateController keyguardStateController,
- @Main Handler handler, ActivityStarter activityStarter,
- BroadcastDispatcher broadcastDispatcher, UiEventLogger uiEventLogger,
+ @Main Handler handler,
+ ActivityStarter activityStarter,
+ BroadcastDispatcher broadcastDispatcher,
+ UiEventLogger uiEventLogger,
TelephonyListenerManager telephonyListenerManager,
- IActivityTaskManager activityTaskManager, UserDetailAdapter userDetailAdapter,
- SecureSettings secureSettings) {
+ IActivityTaskManager activityTaskManager,
+ UserDetailAdapter userDetailAdapter,
+ SecureSettings secureSettings,
+ @UiBackground Executor uiBgExecutor) {
mContext = context;
mUserTracker = userTracker;
mBroadcastDispatcher = broadcastDispatcher;
@@ -147,11 +162,15 @@ public class UserSwitcherController implements Dumpable {
mActivityTaskManager = activityTaskManager;
mUiEventLogger = uiEventLogger;
mGuestResumeSessionReceiver = new GuestResumeSessionReceiver(
- mUserTracker, mUiEventLogger, secureSettings);
+ this, mUserTracker, mUiEventLogger, secureSettings);
mUserDetailAdapter = userDetailAdapter;
+ mUiBgExecutor = uiBgExecutor;
if (!UserManager.isGuestUserEphemeral()) {
mGuestResumeSessionReceiver.register(mBroadcastDispatcher);
}
+ mGuestUserAutoCreated = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_guestUserAutoCreated);
+ mGuestCreationScheduled = new AtomicBoolean();
mKeyguardStateController = keyguardStateController;
mHandler = handler;
mActivityStarter = activityStarter;
@@ -400,21 +419,13 @@ public class UserSwitcherController implements Dumpable {
int id;
if (record.isGuest && record.info == null) {
// No guest user. Create one.
- UserInfo guest;
- try {
- guest = mUserManager.createGuest(mContext,
- mContext.getString(com.android.settingslib.R.string.guest_nickname));
- } catch (UserManager.UserOperationException e) {
- Log.e(TAG, "Couldn't create guest user", e);
- return;
- }
- if (guest == null) {
- // Couldn't create guest, most likely because there already exists one, we just
- // haven't reloaded the user list yet.
+ int guestId = createGuest();
+ if (guestId == UserHandle.USER_NULL) {
+ // This may happen if we haven't reloaded the user list yet.
return;
}
mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_ADD);
- id = guest.id;
+ id = guestId;
} else if (record.isAddUser) {
showAddUserDialog();
return;
@@ -478,11 +489,6 @@ public class UserSwitcherController implements Dumpable {
mAddUserDialog.show();
}
- protected void exitGuest(int id, int targetId) {
- switchToUserId(targetId);
- mUserManager.removeUser(id);
- }
-
private void listenForCallState() {
mTelephonyListenerManager.addCallStateListener(mPhoneStateListener);
}
@@ -588,6 +594,7 @@ public class UserSwitcherController implements Dumpable {
pw.print(" "); pw.println(u.toString());
}
pw.println("mSimpleUserSwitcher=" + mSimpleUserSwitcher);
+ pw.println("mGuestUserAutoCreated=" + mGuestUserAutoCreated);
}
/** Returns the name of the current user of the phone. */
@@ -614,6 +621,120 @@ public class UserSwitcherController implements Dumpable {
return mUsers;
}
+ /**
+ * Removes guest user and switches to target user. The guest must be the current user and its id
+ * must be {@code guestUserId}.
+ *
+ *
If {@code targetUserId} is {@link UserHandle.USER_NULL}, then create a new guest user in
+ * the foreground, and immediately switch to it. This is used for wiping the current guest and
+ * replacing it with a new one.
+ *
+ *
If {@code targetUserId} is specified, then remove the guest in the background while
+ * switching to {@code targetUserId}.
+ *
+ *
If device is configured with {@link
+ * com.android.internal.R.bool.config_guestUserAutoCreated}, then after guest user is removed, a
+ * new one is created in the background. This has no effect if {@code targetUserId} is {@link
+ * UserHandle.USER_NULL}.
+ *
+ * @param guestUserId id of the guest user to remove
+ * @param targetUserId id of the user to switch to after guest is removed. If {@link
+ * UserHandle.USER_NULL}, then switch immediately to the newly created guest user.
+ */
+ public void removeGuestUser(@UserIdInt int guestUserId, @UserIdInt int targetUserId) {
+ UserInfo currentUser = mUserTracker.getUserInfo();
+ if (currentUser.id != guestUserId) {
+ Log.w(TAG, "User requesting to start a new session (" + guestUserId + ")"
+ + " is not current user (" + currentUser.id + ")");
+ return;
+ }
+ if (!currentUser.isGuest()) {
+ Log.w(TAG, "User requesting to start a new session (" + guestUserId + ")"
+ + " is not a guest");
+ return;
+ }
+
+ boolean marked = mUserManager.markGuestForDeletion(currentUser.id);
+ if (!marked) {
+ Log.w(TAG, "Couldn't mark the guest for deletion for user " + guestUserId);
+ return;
+ }
+
+ try {
+ if (targetUserId == UserHandle.USER_NULL) {
+ // Create a new guest in the foreground, and then immediately switch to it
+ int newGuestId = createGuest();
+ if (newGuestId == UserHandle.USER_NULL) {
+ Log.e(TAG, "Could not create new guest, switching back to system user");
+ switchToUserId(UserHandle.USER_SYSTEM);
+ mUserManager.removeUser(currentUser.id);
+ WindowManagerGlobal.getWindowManagerService().lockNow(/* options= */ null);
+ return;
+ }
+ switchToUserId(newGuestId);
+ mUserManager.removeUser(currentUser.id);
+ } else {
+ if (mGuestUserAutoCreated) {
+ // TODO(b/191067027): Move guest recreation to system_server
+ scheduleGuestCreation();
+ }
+ switchToUserId(targetUserId);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't remove guest because ActivityManager or WindowManager is dead");
+ return;
+ }
+ }
+
+ private void scheduleGuestCreation() {
+ if (!mGuestCreationScheduled.compareAndSet(false, true)) {
+ return;
+ }
+
+ mUiBgExecutor.execute(() -> {
+ int newGuestId = createGuest();
+ if (newGuestId == UserHandle.USER_NULL) {
+ Log.w(TAG, "Could not create new guest while exiting existing guest");
+ }
+ mGuestCreationScheduled.set(false);
+ });
+
+ }
+
+ /**
+ * If there is no guest on the device, schedule creation of a new guest user in the background.
+ */
+ public void guaranteeGuestPresent() {
+ if (mUserManager.findCurrentGuestUser() == null) {
+ scheduleGuestCreation();
+ }
+ }
+
+ /**
+ * Creates a guest user and return its multi-user user ID.
+ *
+ * This method does not check if a guest already exists before it makes a call to
+ * {@link UserManager} to create a new one.
+ *
+ * @return The multi-user user ID of the newly created guest user, or
+ * {@link UserHandle.USER_NULL} if the guest couldn't be created.
+ */
+ public @UserIdInt int createGuest() {
+ UserInfo guest;
+ try {
+ guest = mUserManager.createGuest(mContext,
+ mContext.getString(com.android.settingslib.R.string.guest_nickname));
+ } catch (UserManager.UserOperationException e) {
+ Log.e(TAG, "Couldn't create guest user", e);
+ return UserHandle.USER_NULL;
+ }
+ if (guest == null) {
+ Log.e(TAG, "Couldn't create guest, most likely because there already exists one");
+ return UserHandle.USER_NULL;
+ }
+ return guest.id;
+ }
+
public static abstract class BaseUserAdapter extends BaseAdapter {
final UserSwitcherController mController;
@@ -674,10 +795,15 @@ public class UserSwitcherController implements Dumpable {
public String getName(Context context, UserRecord item) {
if (item.isGuest) {
if (item.isCurrent) {
- return context.getString(com.android.settingslib.R.string.guest_exit_guest);
+ return context.getString(mController.mGuestUserAutoCreated
+ ? com.android.settingslib.R.string.guest_reset_guest
+ : com.android.settingslib.R.string.guest_exit_guest);
} else {
+ // If config_guestUserAutoCreated, always show guest nickname instead of "Add
+ // guest" to make it seem as though the device always has a guest ready for use
return context.getString(
- item.info == null ? com.android.settingslib.R.string.guest_new_guest
+ item.info == null && !mController.mGuestUserAutoCreated
+ ? com.android.settingslib.R.string.guest_new_guest
: com.android.settingslib.R.string.guest_nickname);
}
} else if (item.isAddUser) {
@@ -894,12 +1020,15 @@ public class UserSwitcherController implements Dumpable {
public ExitGuestDialog(Context context, int guestId, int targetId) {
super(context);
- setTitle(R.string.guest_exit_guest_dialog_title);
+ setTitle(mGuestUserAutoCreated ? R.string.guest_reset_guest_dialog_title
+ : R.string.guest_exit_guest_dialog_title);
setMessage(context.getString(R.string.guest_exit_guest_dialog_message));
setButton(DialogInterface.BUTTON_NEGATIVE,
context.getString(android.R.string.cancel), this);
setButton(DialogInterface.BUTTON_POSITIVE,
- context.getString(R.string.guest_exit_guest_dialog_remove), this);
+ context.getString(
+ mGuestUserAutoCreated ? R.string.guest_reset_guest_dialog_remove
+ : R.string.guest_exit_guest_dialog_remove), this);
SystemUIDialog.setWindowOnTop(this);
setCanceledOnTouchOutside(false);
mGuestId = guestId;
@@ -913,7 +1042,7 @@ public class UserSwitcherController implements Dumpable {
} else {
mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE);
dismiss();
- exitGuest(mGuestId, mTargetId);
+ removeGuestUser(mGuestId, mTargetId);
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index d9b56a49f12a8..1dacc6245d841 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -52,6 +52,7 @@ import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.DeviceConfigProxyFake;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -78,6 +79,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
private @Mock DumpManager mDumpManager;
private @Mock PowerManager mPowerManager;
private @Mock TrustManager mTrustManager;
+ private @Mock UserSwitcherController mUserSwitcherController;
private @Mock NavigationModeController mNavigationModeController;
private @Mock KeyguardDisplayManager mKeyguardDisplayManager;
private @Mock DozeParameters mDozeParameters;
@@ -100,13 +102,27 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
when(mPowerManager.newWakeLock(anyInt(), any())).thenReturn(mock(WakeLock.class));
mViewMediator = new KeyguardViewMediator(
- mContext, mFalsingCollector, mLockPatternUtils, mBroadcastDispatcher,
+ mContext,
+ mFalsingCollector,
+ mLockPatternUtils,
+ mBroadcastDispatcher,
() -> mStatusBarKeyguardViewManager,
- mDismissCallbackRegistry, mUpdateMonitor, mDumpManager, mUiBgExecutor,
- mPowerManager, mTrustManager, mDeviceConfig, mNavigationModeController,
- mKeyguardDisplayManager, mDozeParameters, mStatusBarStateController,
- mKeyguardStateController, () -> mKeyguardUnlockAnimationController,
- mUnlockedScreenOffAnimationController, () -> mNotificationShadeDepthController);
+ mDismissCallbackRegistry,
+ mUpdateMonitor,
+ mDumpManager,
+ mUiBgExecutor,
+ mPowerManager,
+ mTrustManager,
+ mUserSwitcherController,
+ mDeviceConfig,
+ mNavigationModeController,
+ mKeyguardDisplayManager,
+ mDozeParameters,
+ mStatusBarStateController,
+ mKeyguardStateController,
+ () -> mKeyguardUnlockAnimationController,
+ mUnlockedScreenOffAnimationController,
+ () -> mNotificationShadeDepthController);
mViewMediator.start();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
index e0f395d494463..019bd8d6320e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
@@ -25,6 +25,7 @@ import android.graphics.Bitmap
import android.hardware.face.FaceManager
import android.hardware.fingerprint.FingerprintManager
import android.os.Handler
+import android.os.UserHandle
import android.os.UserManager
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
@@ -39,7 +40,9 @@ import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.qs.QSUserSwitcherEvent
import com.android.systemui.settings.UserTracker
import com.android.systemui.telephony.TelephonyListenerManager
+import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.settings.SecureSettings
+import com.android.systemui.util.time.FakeSystemClock
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Before
@@ -67,24 +70,37 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Mock private lateinit var activityTaskManager: IActivityTaskManager
@Mock private lateinit var userDetailAdapter: UserSwitcherController.UserDetailAdapter
@Mock private lateinit var telephonyListenerManager: TelephonyListenerManager
- @Mock private lateinit var userInfo: UserInfo
@Mock private lateinit var secureSettings: SecureSettings
private lateinit var testableLooper: TestableLooper
- private lateinit var userSwitcherController: UserSwitcherController
+ private lateinit var uiBgExecutor: FakeExecutor
private lateinit var uiEventLogger: UiEventLoggerFake
+ private lateinit var userSwitcherController: UserSwitcherController
private lateinit var picture: Bitmap
+ private val ownerId = UserHandle.USER_SYSTEM
+ private val ownerInfo = UserInfo(ownerId, "Owner", null,
+ UserInfo.FLAG_ADMIN or UserInfo.FLAG_FULL or UserInfo.FLAG_INITIALIZED or
+ UserInfo.FLAG_PRIMARY or UserInfo.FLAG_SYSTEM,
+ UserManager.USER_TYPE_FULL_SYSTEM)
private val guestId = 1234
+ private val guestInfo = UserInfo(guestId, "Guest", null,
+ UserInfo.FLAG_FULL or UserInfo.FLAG_GUEST, UserManager.USER_TYPE_FULL_GUEST)
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
testableLooper = TestableLooper.get(this)
+ uiBgExecutor = FakeExecutor(FakeSystemClock())
uiEventLogger = UiEventLoggerFake()
+ context.orCreateTestableResources.addOverride(
+ com.android.internal.R.bool.config_guestUserAutoCreated, false)
+
mContext.addMockSystemService(Context.FACE_SERVICE, mock(FaceManager::class.java))
mContext.addMockSystemService(Context.FINGERPRINT_SERVICE,
mock(FingerprintManager::class.java))
+ `when`(userManager.canAddMoreUsers()).thenReturn(true)
+
userSwitcherController = UserSwitcherController(context,
userManager,
userTracker,
@@ -96,7 +112,10 @@ class UserSwitcherControllerTest : SysuiTestCase() {
telephonyListenerManager,
activityTaskManager,
userDetailAdapter,
- secureSettings)
+ secureSettings,
+ uiBgExecutor)
+ userSwitcherController.mPauseRefreshUsers = true
+
picture = UserIcons.convertToBitmap(context.getDrawable(R.drawable.ic_avatar_user))
}
@@ -110,8 +129,10 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */)
+ `when`(userTracker.userId).thenReturn(ownerId)
+ `when`(userTracker.userInfo).thenReturn(ownerInfo)
- `when`(userManager.createGuest(any(), anyString())).thenReturn(userInfo)
+ `when`(userManager.createGuest(any(), anyString())).thenReturn(guestInfo)
userSwitcherController.onUserListItemClicked(emptyGuestUserRecord)
testableLooper.processAllMessages()
@@ -122,13 +143,15 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun testRemoveGuest_removeButtonPressed_isLogged() {
val currentGuestUserRecord = UserSwitcherController.UserRecord(
- userInfo,
+ guestInfo,
picture,
true /* guest */,
true /* current */,
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */)
+ `when`(userTracker.userId).thenReturn(guestInfo.id)
+ `when`(userTracker.userInfo).thenReturn(guestInfo)
userSwitcherController.onUserListItemClicked(currentGuestUserRecord)
assertNotNull(userSwitcherController.mExitGuestDialog)
@@ -142,13 +165,15 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun testRemoveGuest_cancelButtonPressed_isNotLogged() {
val currentGuestUserRecord = UserSwitcherController.UserRecord(
- userInfo,
+ guestInfo,
picture,
true /* guest */,
true /* current */,
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */)
+ `when`(userTracker.userId).thenReturn(guestId)
+ `when`(userTracker.userInfo).thenReturn(guestInfo)
userSwitcherController.onUserListItemClicked(currentGuestUserRecord)
assertNotNull(userSwitcherController.mExitGuestDialog)
@@ -160,7 +185,6 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun testWipeGuest_startOverButtonPressed_isLogged() {
- val guestInfo = UserInfo(guestId, null, null, 0, UserManager.USER_TYPE_FULL_GUEST)
val currentGuestUserRecord = UserSwitcherController.UserRecord(
guestInfo,
picture,
@@ -169,6 +193,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */)
+ `when`(userTracker.userId).thenReturn(guestId)
+ `when`(userTracker.userInfo).thenReturn(guestInfo)
// Simulate that guest user has already logged in
`when`(secureSettings.getIntForUser(
@@ -179,7 +205,6 @@ class UserSwitcherControllerTest : SysuiTestCase() {
// Simulate a user switch event
val intent = Intent(Intent.ACTION_USER_SWITCHED).putExtra(Intent.EXTRA_USER_HANDLE, guestId)
- `when`(userTracker.userInfo).thenReturn(guestInfo)
assertNotNull(userSwitcherController.mGuestResumeSessionReceiver)
userSwitcherController.mGuestResumeSessionReceiver.onReceive(context, intent)
@@ -194,7 +219,6 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun testWipeGuest_continueButtonPressed_isLogged() {
- val guestInfo = UserInfo(guestId, null, null, 0, UserManager.USER_TYPE_FULL_GUEST)
val currentGuestUserRecord = UserSwitcherController.UserRecord(
guestInfo,
picture,
@@ -203,6 +227,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */)
+ `when`(userTracker.userId).thenReturn(guestId)
+ `when`(userTracker.userInfo).thenReturn(guestInfo)
// Simulate that guest user has already logged in
`when`(secureSettings.getIntForUser(
@@ -213,7 +239,6 @@ class UserSwitcherControllerTest : SysuiTestCase() {
// Simulate a user switch event
val intent = Intent(Intent.ACTION_USER_SWITCHED).putExtra(Intent.EXTRA_USER_HANDLE, guestId)
- `when`(userTracker.userInfo).thenReturn(guestInfo)
assertNotNull(userSwitcherController.mGuestResumeSessionReceiver)
userSwitcherController.mGuestResumeSessionReceiver.onReceive(context, intent)