Merge "Introduce config for auto-created guest users" into sc-dev
This commit is contained in:
@@ -3529,6 +3529,12 @@
|
||||
<!-- If true, all guest users created on the device will be ephemeral. -->
|
||||
<bool name="config_guestUserEphemeral">false</bool>
|
||||
|
||||
<!-- Whether device should always have a guest user available. If true, guest user will be
|
||||
created on boot, and a new guest user will be created in the background anytime the current
|
||||
guest user is removed. Instead of showing "Add guest" and "Remove guest", the UI will show
|
||||
"Guest" and "Reset guest". -->
|
||||
<bool name="config_guestUserAutoCreated">false</bool>
|
||||
|
||||
<!-- Enforce strong auth on boot. Setting this to false represents a security risk and should
|
||||
not be ordinarily done. The only case in which this might be permissible is in a car head
|
||||
unit where there are hardware mechanisms to protect the device (physical keys) and not
|
||||
|
||||
@@ -402,6 +402,7 @@
|
||||
<java-symbol type="bool" name="config_supportsSystemDecorsOnSecondaryDisplays" />
|
||||
<java-symbol type="bool" name="config_supportsInsecureLockScreen" />
|
||||
<java-symbol type="bool" name="config_guestUserEphemeral" />
|
||||
<java-symbol type="bool" name="config_guestUserAutoCreated" />
|
||||
<java-symbol type="bool" name="config_localDisplaysMirrorContent" />
|
||||
<java-symbol type="array" name="config_localPrivateDisplayPorts" />
|
||||
<java-symbol type="integer" name="config_defaultDisplayDefaultColorMode" />
|
||||
|
||||
@@ -1422,6 +1422,8 @@
|
||||
<string name="guest_new_guest">Add guest</string>
|
||||
<!-- Label for exiting and removing the guest session in the user switcher [CHAR LIMIT=35] -->
|
||||
<string name="guest_exit_guest">Remove guest</string>
|
||||
<!-- Label for resetting guest session in the user switcher, which will remove all data from the current guest session [CHAR LIMIT=35] -->
|
||||
<string name="guest_reset_guest">Reset guest</string>
|
||||
<!-- Name for the guest user [CHAR LIMIT=35] -->
|
||||
<string name="guest_nickname">Guest</string>
|
||||
|
||||
|
||||
@@ -1148,12 +1148,18 @@
|
||||
<!-- Title of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
|
||||
<string name="guest_exit_guest_dialog_title">Remove guest?</string>
|
||||
|
||||
<!-- Title of the confirmation dialog when resetting guest session [CHAR LIMIT=NONE] -->
|
||||
<string name="guest_reset_guest_dialog_title">Reset guest?</string>
|
||||
|
||||
<!-- Message of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
|
||||
<string name="guest_exit_guest_dialog_message">All apps and data in this session will be deleted.</string>
|
||||
|
||||
<!-- Label for button in confirmation dialog when exiting guest session [CHAR LIMIT=35] -->
|
||||
<string name="guest_exit_guest_dialog_remove">Remove</string>
|
||||
|
||||
<!-- Label for button in confirmation dialog when resetting guest session [CHAR LIMIT=35] -->
|
||||
<string name="guest_reset_guest_dialog_remove">Reset</string>
|
||||
|
||||
<!-- Title of the notification when resuming an existing guest session [CHAR LIMIT=NONE] -->
|
||||
<string name="guest_wipe_session_title">Welcome back, guest!</string>
|
||||
|
||||
|
||||
@@ -27,15 +27,14 @@ import android.content.IntentFilter;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.WindowManagerGlobal;
|
||||
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.qs.QSUserSwitcherEvent;
|
||||
import com.android.systemui.statusbar.phone.SystemUIDialog;
|
||||
import com.android.systemui.statusbar.policy.UserSwitcherController;
|
||||
|
||||
/**
|
||||
* Manages notification when a guest session is resumed.
|
||||
@@ -47,9 +46,12 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver {
|
||||
private static final String SETTING_GUEST_HAS_LOGGED_IN = "systemui.guest_has_logged_in";
|
||||
|
||||
private Dialog mNewSessionDialog;
|
||||
private final UserSwitcherController mUserSwitcherController;
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
|
||||
public GuestResumeSessionReceiver(UiEventLogger uiEventLogger) {
|
||||
public GuestResumeSessionReceiver(UserSwitcherController userSwitcherController,
|
||||
UiEventLogger uiEventLogger) {
|
||||
mUserSwitcherController = userSwitcherController;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
}
|
||||
|
||||
@@ -90,7 +92,8 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver {
|
||||
int notFirstLogin = Settings.System.getIntForUser(
|
||||
cr, SETTING_GUEST_HAS_LOGGED_IN, 0, userId);
|
||||
if (notFirstLogin != 0) {
|
||||
mNewSessionDialog = new ResetSessionDialog(context, mUiEventLogger, userId);
|
||||
mNewSessionDialog = new ResetSessionDialog(context, mUserSwitcherController,
|
||||
mUiEventLogger, userId);
|
||||
mNewSessionDialog.show();
|
||||
} else {
|
||||
Settings.System.putIntForUser(
|
||||
@@ -99,54 +102,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, int userId) {
|
||||
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||
UserInfo currentUser;
|
||||
try {
|
||||
currentUser = ActivityManager.getService().getCurrentUser();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Couldn't wipe session because ActivityManager is dead");
|
||||
return;
|
||||
}
|
||||
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();
|
||||
@@ -160,10 +115,12 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver {
|
||||
private static final int BUTTON_WIPE = BUTTON_NEGATIVE;
|
||||
private static final int BUTTON_DONTWIPE = BUTTON_POSITIVE;
|
||||
|
||||
private final UserSwitcherController mUserSwitcherController;
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
private final int mUserId;
|
||||
|
||||
ResetSessionDialog(Context context, UiEventLogger uiEventLogger, int userId) {
|
||||
ResetSessionDialog(Context context, UserSwitcherController userSwitcherController,
|
||||
UiEventLogger uiEventLogger, int userId) {
|
||||
super(context);
|
||||
|
||||
setTitle(context.getString(R.string.guest_wipe_session_title));
|
||||
@@ -175,6 +132,7 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver {
|
||||
setButton(BUTTON_DONTWIPE,
|
||||
context.getString(R.string.guest_wipe_session_dontwipe), this);
|
||||
|
||||
mUserSwitcherController = userSwitcherController;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
mUserId = userId;
|
||||
}
|
||||
@@ -183,7 +141,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(), mUserId);
|
||||
mUserSwitcherController.removeGuestUser(mUserId, UserHandle.USER_NULL);
|
||||
dismiss();
|
||||
} else if (which == BUTTON_DONTWIPE) {
|
||||
mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_CONTINUE);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.Dialog;
|
||||
import android.app.IActivityTaskManager;
|
||||
@@ -48,6 +49,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;
|
||||
@@ -63,6 +65,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;
|
||||
@@ -76,6 +79,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;
|
||||
@@ -123,23 +128,35 @@ public class UserSwitcherController implements Dumpable {
|
||||
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, KeyguardStateController keyguardStateController,
|
||||
@Main Handler handler, ActivityStarter activityStarter,
|
||||
BroadcastDispatcher broadcastDispatcher, UiEventLogger uiEventLogger,
|
||||
public UserSwitcherController(Context context,
|
||||
KeyguardStateController keyguardStateController,
|
||||
@Main Handler handler,
|
||||
ActivityStarter activityStarter,
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
UiEventLogger uiEventLogger,
|
||||
TelephonyListenerManager telephonyListenerManager,
|
||||
IActivityTaskManager activityTaskManager, UserDetailAdapter userDetailAdapter) {
|
||||
IActivityTaskManager activityTaskManager,
|
||||
UserDetailAdapter userDetailAdapter,
|
||||
@UiBackground Executor uiBgExecutor) {
|
||||
mContext = context;
|
||||
mBroadcastDispatcher = broadcastDispatcher;
|
||||
mTelephonyListenerManager = telephonyListenerManager;
|
||||
mActivityTaskManager = activityTaskManager;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
mGuestResumeSessionReceiver = new GuestResumeSessionReceiver(mUiEventLogger);
|
||||
mGuestResumeSessionReceiver = new GuestResumeSessionReceiver(this, mUiEventLogger);
|
||||
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;
|
||||
@@ -379,21 +396,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;
|
||||
@@ -457,11 +466,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);
|
||||
}
|
||||
@@ -576,6 +580,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. */
|
||||
@@ -602,6 +607,126 @@ 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}.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>If {@code targetUserId} is specified, then remove the guest in the background while
|
||||
* switching to {@code targetUserId}.
|
||||
*
|
||||
* <p>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;
|
||||
try {
|
||||
currentUser = ActivityManager.getService().getCurrentUser();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Couldn't remove guest because ActivityManager is dead");
|
||||
return;
|
||||
}
|
||||
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;
|
||||
@@ -662,10 +787,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) {
|
||||
@@ -882,12 +1012,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;
|
||||
@@ -901,7 +1034,7 @@ public class UserSwitcherController implements Dumpable {
|
||||
} else {
|
||||
mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE);
|
||||
dismiss();
|
||||
exitGuest(mGuestId, mTargetId);
|
||||
removeGuestUser(mGuestId, mTargetId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user