From 7c060b29511367f80b20edaf3b569c10aeafa2c9 Mon Sep 17 00:00:00 2001 From: Peter Kalauskas Date: Mon, 22 Mar 2021 20:26:10 -0700 Subject: [PATCH] Add tests for guest user metrics Test: statsd_testdrive -terse 90 Test: atest SystemUITests:com.android.systemui.qs.tiles.UserDetailViewAdapterTest Test: atest SystemUITests:com.android.systemui.statusbar.policy.UserSwitcherControllerTest Bug: 169783558 Bug: 194441567 Change-Id: I009fc0eba32e34cb62f2cc15f9337bce9b81c89d Merged-In: I009fc0eba32e34cb62f2cc15f9337bce9b81c89d --- .../systemui/GuestResumeSessionReceiver.java | 55 ++-- .../policy/UserSwitcherController.java | 72 ++--- .../policy/UserSwitcherControllerTest.kt | 248 ++++++++++++++++++ 3 files changed, 320 insertions(+), 55 deletions(-) create mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java b/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java index 0ae89bc102902..b5b6b1340108b 100644 --- a/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java +++ b/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java @@ -16,25 +16,24 @@ package com.android.systemui; -import android.app.ActivityManager; -import android.app.Dialog; +import android.app.AlertDialog; import android.content.BroadcastReceiver; -import android.content.ContentResolver; import android.content.Context; 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.provider.Settings; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEventLogger; 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; /** * Manages notification when a guest session is resumed. @@ -43,16 +42,23 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver { private static final String TAG = "GuestResumeSessionReceiver"; - private static final String SETTING_GUEST_HAS_LOGGED_IN = "systemui.guest_has_logged_in"; + @VisibleForTesting + public static final String SETTING_GUEST_HAS_LOGGED_IN = "systemui.guest_has_logged_in"; - private Dialog mNewSessionDialog; + @VisibleForTesting + public AlertDialog mNewSessionDialog; + private final UserTracker mUserTracker; private final UserSwitcherController mUserSwitcherController; private final UiEventLogger mUiEventLogger; + private final SecureSettings mSecureSettings; public GuestResumeSessionReceiver(UserSwitcherController userSwitcherController, - UiEventLogger uiEventLogger) { + UserTracker userTracker, UiEventLogger uiEventLogger, + SecureSettings secureSettings) { mUserSwitcherController = userSwitcherController; + mUserTracker = userTracker; mUiEventLogger = uiEventLogger; + mSecureSettings = secureSettings; } /** @@ -78,26 +84,19 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver { return; } - UserInfo currentUser; - try { - currentUser = ActivityManager.getService().getCurrentUser(); - } catch (RemoteException e) { - return; - } + UserInfo currentUser = mUserTracker.getUserInfo(); if (!currentUser.isGuest()) { return; } - ContentResolver cr = context.getContentResolver(); - int notFirstLogin = Settings.System.getIntForUser( - cr, SETTING_GUEST_HAS_LOGGED_IN, 0, userId); + int notFirstLogin = mSecureSettings.getIntForUser( + SETTING_GUEST_HAS_LOGGED_IN, 0, userId); if (notFirstLogin != 0) { mNewSessionDialog = new ResetSessionDialog(context, mUserSwitcherController, mUiEventLogger, userId); mNewSessionDialog.show(); } else { - Settings.System.putIntForUser( - cr, SETTING_GUEST_HAS_LOGGED_IN, 1, userId); + mSecureSettings.putIntForUser(SETTING_GUEST_HAS_LOGGED_IN, 1, userId); } } } @@ -109,18 +108,26 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver { } } - private static class ResetSessionDialog extends SystemUIDialog implements + /** + * Dialog shown when user when asking for confirmation before deleting guest user. + */ + @VisibleForTesting + public static class ResetSessionDialog extends SystemUIDialog implements DialogInterface.OnClickListener { - private static final int BUTTON_WIPE = BUTTON_NEGATIVE; - private static final int BUTTON_DONTWIPE = BUTTON_POSITIVE; + @VisibleForTesting + public static final int BUTTON_WIPE = BUTTON_NEGATIVE; + @VisibleForTesting + public static final int BUTTON_DONTWIPE = BUTTON_POSITIVE; private final UserSwitcherController mUserSwitcherController; private final UiEventLogger mUiEventLogger; private final int mUserId; - ResetSessionDialog(Context context, UserSwitcherController userSwitcherController, - UiEventLogger uiEventLogger, int userId) { + ResetSessionDialog(Context context, + UserSwitcherController userSwitcherController, + UiEventLogger uiEventLogger, + int userId) { super(context); setTitle(context.getString(R.string.guest_wipe_session_title)); 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 f10f4fef52924..ae73f7327defb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -23,6 +23,7 @@ import static com.android.systemui.DejankUtils.whitelistIpcs; import android.annotation.UserIdInt; import android.app.ActivityManager; +import android.app.AlertDialog; import android.app.Dialog; import android.app.IActivityTaskManager; import android.content.BroadcastReceiver; @@ -71,9 +72,11 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.qs.QSUserSwitcherEvent; import com.android.systemui.qs.tiles.UserDetailView; +import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.telephony.TelephonyListenerManager; import com.android.systemui.user.CreateUserActivity; +import com.android.systemui.util.settings.SecureSettings; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -104,9 +107,12 @@ public class UserSwitcherController implements Dumpable { private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF"; protected final Context mContext; + protected final UserTracker mUserTracker; protected final UserManager mUserManager; + private final ContentObserver mSettingsObserver; private final ArrayList> mAdapters = new ArrayList<>(); - private final GuestResumeSessionReceiver mGuestResumeSessionReceiver; + @VisibleForTesting + final GuestResumeSessionReceiver mGuestResumeSessionReceiver; private final KeyguardStateController mKeyguardStateController; protected final Handler mHandler; private final ActivityStarter mActivityStarter; @@ -115,15 +121,18 @@ public class UserSwitcherController implements Dumpable { private final IActivityTaskManager mActivityTaskManager; private ArrayList mUsers = new ArrayList<>(); - private Dialog mExitGuestDialog; - private Dialog mAddUserDialog; + @VisibleForTesting + AlertDialog mExitGuestDialog; + @VisibleForTesting + Dialog mAddUserDialog; private int mLastNonGuestUser = UserHandle.USER_SYSTEM; private boolean mResumeUserOnGuestLogout = true; private boolean mSimpleUserSwitcher; // 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); @@ -137,6 +146,8 @@ public class UserSwitcherController implements Dumpable { @Inject public UserSwitcherController(Context context, + UserManager userManager, + UserTracker userTracker, KeyguardStateController keyguardStateController, @Main Handler handler, ActivityStarter activityStarter, @@ -146,14 +157,17 @@ public class UserSwitcherController implements Dumpable { TelephonyListenerManager telephonyListenerManager, IActivityTaskManager activityTaskManager, UserDetailAdapter userDetailAdapter, + SecureSettings secureSettings, @UiBackground Executor uiBgExecutor) { mContext = context; + mUserTracker = userTracker; mBroadcastDispatcher = broadcastDispatcher; mTelephonyListenerManager = telephonyListenerManager; mActivityTaskManager = activityTaskManager; mUiEventLogger = uiEventLogger; mFalsingManager = falsingManager; - mGuestResumeSessionReceiver = new GuestResumeSessionReceiver(this, mUiEventLogger); + mGuestResumeSessionReceiver = new GuestResumeSessionReceiver( + this, mUserTracker, mUiEventLogger, secureSettings); mUserDetailAdapter = userDetailAdapter; mUiBgExecutor = uiBgExecutor; if (!UserManager.isGuestUserEphemeral()) { @@ -166,7 +180,7 @@ public class UserSwitcherController implements Dumpable { mKeyguardStateController = keyguardStateController; mHandler = handler; mActivityStarter = activityStarter; - mUserManager = UserManager.get(context); + mUserManager = userManager; IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_USER_ADDED); filter.addAction(Intent.ACTION_USER_REMOVED); @@ -185,6 +199,15 @@ public class UserSwitcherController implements Dumpable { mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter, PERMISSION_SELF, null /* scheduler */); + mSettingsObserver = new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange) { + mSimpleUserSwitcher = shouldUseSimpleUserSwitcher(); + mAddUsersFromLockScreen = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0; + refreshUsers(UserHandle.USER_NULL); + }; + }; mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(SIMPLE_USER_SWITCHER_GLOBAL_SETTING), true, mSettingsObserver); @@ -246,11 +269,11 @@ public class UserSwitcherController implements Dumpable { return null; } ArrayList records = new ArrayList<>(infos.size()); - int currentId = ActivityManager.getCurrentUser(); + int currentId = mUserTracker.getUserId(); // Check user switchability of the foreground user since SystemUI is running in // User 0 boolean canSwitchUsers = mUserManager.getUserSwitchability( - UserHandle.of(ActivityManager.getCurrentUser())) == SWITCHABILITY_STATUS_OK; + UserHandle.of(mUserTracker.getUserId())) == SWITCHABILITY_STATUS_OK; UserInfo currentUserInfo = null; UserRecord guestRecord = null; @@ -391,7 +414,7 @@ public class UserSwitcherController implements Dumpable { } public void logoutCurrentUser() { - int currentUser = ActivityManager.getCurrentUser(); + int currentUser = mUserTracker.getUserId(); if (currentUser != UserHandle.USER_SYSTEM) { pauseRefreshUsers(); ActivityManager.logoutCurrentUser(); @@ -403,7 +426,7 @@ public class UserSwitcherController implements Dumpable { Log.w(TAG, "User " + userId + " could not removed."); return; } - if (ActivityManager.getCurrentUser() == userId) { + if (mUserTracker.getUserId() == userId) { switchToUserId(UserHandle.USER_SYSTEM); } if (mUserManager.removeUser(userId)) { @@ -411,7 +434,8 @@ public class UserSwitcherController implements Dumpable { } } - private void onUserListItemClicked(UserRecord record) { + @VisibleForTesting + void onUserListItemClicked(UserRecord record) { int id; if (record.isGuest && record.info == null) { // No guest user. Create one. @@ -429,7 +453,7 @@ public class UserSwitcherController implements Dumpable { id = record.info.id; } - int currUserId = ActivityManager.getCurrentUser(); + int currUserId = mUserTracker.getUserId(); if (currUserId == id) { if (record.isGuest) { showExitGuestDialog(id); @@ -587,15 +611,6 @@ public class UserSwitcherController implements Dumpable { } }; - private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) { - public void onChange(boolean selfChange) { - mSimpleUserSwitcher = shouldUseSimpleUserSwitcher(); - mAddUsersFromLockScreen = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0; - refreshUsers(UserHandle.USER_NULL); - }; - }; - @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("UserSwitcherController state:"); @@ -654,13 +669,7 @@ public class UserSwitcherController implements Dumpable { * UserHandle.USER_NULL}, then switch immediately to the newly created guest user. */ public void removeGuestUser(@UserIdInt int guestUserId, @UserIdInt int targetUserId) { - UserInfo currentUser; - try { - currentUser = ActivityManager.getService().getCurrentUser(); - } catch (RemoteException e) { - Log.e(TAG, "Couldn't remove guest because ActivityManager is dead"); - return; - } + 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 + ")"); @@ -874,9 +883,9 @@ public class UserSwitcherController implements Dumpable { private void checkIfAddUserDisallowedByAdminOnly(UserRecord record) { EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(mContext, - UserManager.DISALLOW_ADD_USER, ActivityManager.getCurrentUser()); + UserManager.DISALLOW_ADD_USER, mUserTracker.getUserId()); if (admin != null && !RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext, - UserManager.DISALLOW_ADD_USER, ActivityManager.getCurrentUser())) { + UserManager.DISALLOW_ADD_USER, mUserTracker.getUserId())) { record.isDisabledByAdmin = true; record.enforcedAdmin = admin; } else { @@ -1088,7 +1097,8 @@ public class UserSwitcherController implements Dumpable { } } - private final class AddUserDialog extends SystemUIDialog implements + @VisibleForTesting + final class AddUserDialog extends SystemUIDialog implements DialogInterface.OnClickListener { public AddUserDialog(Context context) { 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 new file mode 100644 index 0000000000000..c345f71fa8514 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt @@ -0,0 +1,248 @@ +/* + * 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.systemui.statusbar.policy + +import android.app.IActivityTaskManager +import android.content.DialogInterface +import android.content.Intent +import android.content.pm.UserInfo +import android.graphics.Bitmap +import android.os.Handler +import android.os.UserHandle +import android.os.UserManager +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import androidx.test.filters.SmallTest +import com.android.internal.logging.testing.UiEventLoggerFake +import com.android.internal.util.UserIcons +import com.android.systemui.GuestResumeSessionReceiver +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.plugins.FalsingManager +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 +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mock +import org.mockito.Mockito.any +import org.mockito.Mockito.anyString +import org.mockito.Mockito.`when` +import org.mockito.MockitoAnnotations + +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +@SmallTest +class UserSwitcherControllerTest : SysuiTestCase() { + @Mock private lateinit var keyguardStateController: KeyguardStateController + @Mock private lateinit var handler: Handler + @Mock private lateinit var userTracker: UserTracker + @Mock private lateinit var userManager: UserManager + @Mock private lateinit var activityStarter: ActivityStarter + @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher + @Mock private lateinit var activityTaskManager: IActivityTaskManager + @Mock private lateinit var userDetailAdapter: UserSwitcherController.UserDetailAdapter + @Mock private lateinit var telephonyListenerManager: TelephonyListenerManager + @Mock private lateinit var secureSettings: SecureSettings + @Mock private lateinit var falsingManager: FalsingManager + private lateinit var testableLooper: TestableLooper + 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) + + `when`(userManager.canAddMoreUsers()).thenReturn(true) + + userSwitcherController = UserSwitcherController(context, + userManager, + userTracker, + keyguardStateController, + handler, + activityStarter, + broadcastDispatcher, + uiEventLogger, + falsingManager, + telephonyListenerManager, + activityTaskManager, + userDetailAdapter, + secureSettings, + uiBgExecutor) + userSwitcherController.mPauseRefreshUsers = true + + picture = UserIcons.convertToBitmap(context.getDrawable(R.drawable.ic_avatar_user)) + } + + @Test + fun testAddGuest_okButtonPressed_isLogged() { + val emptyGuestUserRecord = UserSwitcherController.UserRecord( + null, + null, + true /* guest */, + false /* current */, + false /* isAddUser */, + false /* isRestricted */, + true /* isSwitchToEnabled */) + `when`(userTracker.userId).thenReturn(ownerId) + `when`(userTracker.userInfo).thenReturn(ownerInfo) + + `when`(userManager.createGuest(any(), anyString())).thenReturn(guestInfo) + + userSwitcherController.onUserListItemClicked(emptyGuestUserRecord) + assertEquals(1, uiEventLogger.numLogs()) + assertEquals(QSUserSwitcherEvent.QS_USER_GUEST_ADD.id, uiEventLogger.eventId(0)) + } + + @Test + fun testRemoveGuest_removeButtonPressed_isLogged() { + val currentGuestUserRecord = UserSwitcherController.UserRecord( + 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) + userSwitcherController.mExitGuestDialog + .getButton(DialogInterface.BUTTON_POSITIVE).performClick() + testableLooper.processAllMessages() + assertEquals(1, uiEventLogger.numLogs()) + assertEquals(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE.id, uiEventLogger.eventId(0)) + } + + @Test + fun testRemoveGuest_cancelButtonPressed_isNotLogged() { + val currentGuestUserRecord = UserSwitcherController.UserRecord( + 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) + userSwitcherController.mExitGuestDialog + .getButton(DialogInterface.BUTTON_NEGATIVE).performClick() + testableLooper.processAllMessages() + assertEquals(0, uiEventLogger.numLogs()) + } + + @Test + fun testWipeGuest_startOverButtonPressed_isLogged() { + val currentGuestUserRecord = UserSwitcherController.UserRecord( + guestInfo, + picture, + true /* guest */, + false /* current */, + 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( + eq(GuestResumeSessionReceiver.SETTING_GUEST_HAS_LOGGED_IN), anyInt(), anyInt())) + .thenReturn(1) + + userSwitcherController.onUserListItemClicked(currentGuestUserRecord) + + // Simulate a user switch event + val intent = Intent(Intent.ACTION_USER_SWITCHED).putExtra(Intent.EXTRA_USER_HANDLE, guestId) + + assertNotNull(userSwitcherController.mGuestResumeSessionReceiver) + userSwitcherController.mGuestResumeSessionReceiver.onReceive(context, intent) + + assertNotNull(userSwitcherController.mGuestResumeSessionReceiver.mNewSessionDialog) + userSwitcherController.mGuestResumeSessionReceiver.mNewSessionDialog + .getButton(GuestResumeSessionReceiver.ResetSessionDialog.BUTTON_WIPE).performClick() + testableLooper.processAllMessages() + assertEquals(1, uiEventLogger.numLogs()) + assertEquals(QSUserSwitcherEvent.QS_USER_GUEST_WIPE.id, uiEventLogger.eventId(0)) + } + + @Test + fun testWipeGuest_continueButtonPressed_isLogged() { + val currentGuestUserRecord = UserSwitcherController.UserRecord( + guestInfo, + picture, + true /* guest */, + false /* current */, + 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( + eq(GuestResumeSessionReceiver.SETTING_GUEST_HAS_LOGGED_IN), anyInt(), anyInt())) + .thenReturn(1) + + userSwitcherController.onUserListItemClicked(currentGuestUserRecord) + + // Simulate a user switch event + val intent = Intent(Intent.ACTION_USER_SWITCHED).putExtra(Intent.EXTRA_USER_HANDLE, guestId) + + assertNotNull(userSwitcherController.mGuestResumeSessionReceiver) + userSwitcherController.mGuestResumeSessionReceiver.onReceive(context, intent) + + assertNotNull(userSwitcherController.mGuestResumeSessionReceiver.mNewSessionDialog) + userSwitcherController.mGuestResumeSessionReceiver.mNewSessionDialog + .getButton(GuestResumeSessionReceiver.ResetSessionDialog.BUTTON_DONTWIPE) + .performClick() + testableLooper.processAllMessages() + assertEquals(1, uiEventLogger.numLogs()) + assertEquals(QSUserSwitcherEvent.QS_USER_GUEST_CONTINUE.id, uiEventLogger.eventId(0)) + } +}