diff options
9 files changed, 313 insertions, 20 deletions
diff --git a/api/current.txt b/api/current.txt index bfb193428d73..4595cf8520d0 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6398,6 +6398,7 @@ package android.app.admin { method public java.util.List<java.lang.String> getDelegatePackages(android.content.ComponentName, java.lang.String); method public java.util.List<java.lang.String> getDelegatedScopes(android.content.ComponentName, java.lang.String); method public java.lang.CharSequence getDeviceOwnerLockScreenInfo(); + method public java.lang.CharSequence getEndUserSessionMessage(android.content.ComponentName); method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName); method public java.util.List<java.lang.String> getKeepUninstalledPackages(android.content.ComponentName); method public int getKeyguardDisabledFeatures(android.content.ComponentName); @@ -6433,6 +6434,7 @@ package android.app.admin { method public boolean getScreenCaptureDisabled(android.content.ComponentName); method public java.util.List<android.os.UserHandle> getSecondaryUsers(android.content.ComponentName); method public java.lang.CharSequence getShortSupportMessage(android.content.ComponentName); + method public java.lang.CharSequence getStartUserSessionMessage(android.content.ComponentName); method public boolean getStorageEncryption(android.content.ComponentName); method public int getStorageEncryptionStatus(); method public android.app.admin.SystemUpdatePolicy getSystemUpdatePolicy(); @@ -6495,6 +6497,7 @@ package android.app.admin { method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean); method public void setDelegatedScopes(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>); method public void setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.CharSequence); + method public void setEndUserSessionMessage(android.content.ComponentName, java.lang.CharSequence); method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String); method public void setKeepUninstalledPackages(android.content.ComponentName, java.util.List<java.lang.String>); method public boolean setKeyPairCertificate(android.content.ComponentName, java.lang.String, java.util.List<java.security.cert.Certificate>, boolean); @@ -6538,6 +6541,7 @@ package android.app.admin { method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String); method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean); method public void setShortSupportMessage(android.content.ComponentName, java.lang.CharSequence); + method public void setStartUserSessionMessage(android.content.ComponentName, java.lang.CharSequence); method public boolean setStatusBarDisabled(android.content.ComponentName, boolean); method public int setStorageEncryption(android.content.ComponentName, boolean); method public void setSystemSetting(android.content.ComponentName, java.lang.String, java.lang.String); diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 972ffcbf527f..db12c37f2c2d 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -324,4 +324,14 @@ public abstract class ActivityManagerInternal { * Returns if more users can be started without stopping currently running users. */ public abstract boolean canStartMoreUsers(); + + /** + * Sets the user switcher message for switching from {@link android.os.UserHandle#SYSTEM}. + */ + public abstract void setSwitchingFromSystemUserMessage(String switchingFromSystemUserMessage); + + /** + * Sets the user switcher message for switching to {@link android.os.UserHandle#SYSTEM}. + */ + public abstract void setSwitchingToSystemUserMessage(String switchingToSystemUserMessage); } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index cc4d29e3807a..9329d56a8de9 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -9117,4 +9117,84 @@ public class DevicePolicyManager { throw re.rethrowFromSystemServer(); } } + + /** + * Called by a device owner to specify the user session start message. This may be displayed + * during a user switch. + * <p> + * The message should be limited to a short statement or it may be truncated. + * <p> + * If the message needs to be localized, it is the responsibility of the + * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast + * and set a new version of this message accordingly. + * + * @param admin which {@link DeviceAdminReceiver} this request is associated with. + * @param startUserSessionMessage message for starting user session, or {@code null} to use + * system default message. + * @throws SecurityException if {@code admin} is not a device owner. + */ + public void setStartUserSessionMessage( + @NonNull ComponentName admin, @Nullable CharSequence startUserSessionMessage) { + throwIfParentInstance("setStartUserSessionMessage"); + try { + mService.setStartUserSessionMessage(admin, startUserSessionMessage); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * Called by a device owner to specify the user session end message. This may be displayed + * during a user switch. + * <p> + * The message should be limited to a short statement or it may be truncated. + * <p> + * If the message needs to be localized, it is the responsibility of the + * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast + * and set a new version of this message accordingly. + * + * @param admin which {@link DeviceAdminReceiver} this request is associated with. + * @param endUserSessionMessage message for ending user session, or {@code null} to use system + * default message. + * @throws SecurityException if {@code admin} is not a device owner. + */ + public void setEndUserSessionMessage( + @NonNull ComponentName admin, @Nullable CharSequence endUserSessionMessage) { + throwIfParentInstance("setEndUserSessionMessage"); + try { + mService.setEndUserSessionMessage(admin, endUserSessionMessage); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * Returns the user session start message. + * + * @param admin which {@link DeviceAdminReceiver} this request is associated with. + * @throws SecurityException if {@code admin} is not a device owner. + */ + public CharSequence getStartUserSessionMessage(@NonNull ComponentName admin) { + throwIfParentInstance("getStartUserSessionMessage"); + try { + return mService.getStartUserSessionMessage(admin); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * Returns the user session end message. + * + * @param admin which {@link DeviceAdminReceiver} this request is associated with. + * @throws SecurityException if {@code admin} is not a device owner. + */ + public CharSequence getEndUserSessionMessage(@NonNull ComponentName admin) { + throwIfParentInstance("getEndUserSessionMessage"); + try { + return mService.getEndUserSessionMessage(admin); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 9cdd1f836d45..eac7f7ed4b3e 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -391,4 +391,9 @@ interface IDevicePolicyManager { List<String> getDisallowedSystemApps(in ComponentName admin, int userId, String provisioningAction); void transferOwnership(in ComponentName admin, in ComponentName target, in PersistableBundle bundle); + + void setStartUserSessionMessage(in ComponentName admin, in CharSequence startUserSessionMessage); + void setEndUserSessionMessage(in ComponentName admin, in CharSequence endUserSessionMessage); + CharSequence getStartUserSessionMessage(in ComponentName admin); + CharSequence getEndUserSessionMessage(in ComponentName admin); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 8cff20ce73c9..a16dd3d0477d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -25130,6 +25130,16 @@ public class ActivityManagerService extends IActivityManager.Stub public boolean canStartMoreUsers() { return mUserController.canStartMoreUsers(); } + + @Override + public void setSwitchingFromSystemUserMessage(String switchingFromSystemUserMessage) { + mUserController.setSwitchingFromSystemUserMessage(switchingFromSystemUserMessage); + } + + @Override + public void setSwitchingToSystemUserMessage(String switchingToSystemUserMessage) { + mUserController.setSwitchingToSystemUserMessage(switchingToSystemUserMessage); + } } /** diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index a327a018bc25..c7210a835767 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -217,6 +217,18 @@ class UserController implements Handler.Callback { private volatile ArraySet<String> mCurWaitingUserSwitchCallbacks; /** + * Messages for for switching from {@link android.os.UserHandle#SYSTEM}. + */ + @GuardedBy("mLock") + private String mSwitchingFromSystemUserMessage; + + /** + * Messages for for switching to {@link android.os.UserHandle#SYSTEM}. + */ + @GuardedBy("mLock") + private String mSwitchingToSystemUserMessage; + + /** * Callbacks that are still active after {@link #USER_SWITCH_TIMEOUT_MS} */ @GuardedBy("mLock") @@ -1189,7 +1201,8 @@ class UserController implements Handler.Callback { private void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) { // The dialog will show and then initiate the user switch by calling startUserInForeground - mInjector.showUserSwitchingDialog(fromToUserPair.first, fromToUserPair.second); + mInjector.showUserSwitchingDialog(fromToUserPair.first, fromToUserPair.second, + getSwitchingFromSystemUserMessage(), getSwitchingToSystemUserMessage()); } private void dispatchForegroundProfileChanged(int userId) { @@ -1799,6 +1812,30 @@ class UserController implements Handler.Callback { return mLockPatternUtils.isLockScreenDisabled(userId); } + void setSwitchingFromSystemUserMessage(String switchingFromSystemUserMessage) { + synchronized (mLock) { + mSwitchingFromSystemUserMessage = switchingFromSystemUserMessage; + } + } + + void setSwitchingToSystemUserMessage(String switchingToSystemUserMessage) { + synchronized (mLock) { + mSwitchingToSystemUserMessage = switchingToSystemUserMessage; + } + } + + private String getSwitchingFromSystemUserMessage() { + synchronized (mLock) { + return mSwitchingFromSystemUserMessage; + } + } + + private String getSwitchingToSystemUserMessage() { + synchronized (mLock) { + return mSwitchingToSystemUserMessage; + } + } + void dump(PrintWriter pw, boolean dumpAll) { synchronized (mLock) { pw.println(" mStartedUsers:"); @@ -2079,9 +2116,11 @@ class UserController implements Handler.Callback { mService.installEncryptionUnawareProviders(userId); } - void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser) { + void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser, + String switchingFromSystemUserMessage, String switchingToSystemUserMessage) { Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromUser, toUser, - true /* above system */); + true /* above system */, switchingFromSystemUserMessage, + switchingToSystemUserMessage); d.show(); } diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java index 3e6934f67e4e..afcba3bfe330 100644 --- a/services/core/java/com/android/server/am/UserSwitchingDialog.java +++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java @@ -53,7 +53,8 @@ final class UserSwitchingDialog extends AlertDialog private boolean mStartedUser; public UserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser, - UserInfo newUser, boolean aboveSystem) { + UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage, + String switchingToSystemUserMessage) { super(context); mService = service; @@ -65,7 +66,7 @@ final class UserSwitchingDialog extends AlertDialog // Custom view due to alignment and font size requirements View view = LayoutInflater.from(getContext()).inflate(R.layout.user_switching_dialog, null); - String viewMessage; + String viewMessage = null; if (UserManager.isSplitSystemUser() && newUser.id == UserHandle.USER_SYSTEM) { viewMessage = res.getString(R.string.user_logging_out_message, oldUser.name); } else if (UserManager.isDeviceInDemoMode(context)) { @@ -75,7 +76,17 @@ final class UserSwitchingDialog extends AlertDialog viewMessage = res.getString(R.string.demo_starting_message); } } else { - viewMessage = res.getString(R.string.user_switching_message, newUser.name); + if (oldUser.id == UserHandle.USER_SYSTEM) { + viewMessage = switchingFromSystemUserMessage; + } else if (newUser.id == UserHandle.USER_SYSTEM) { + viewMessage = switchingToSystemUserMessage; + } + + // If switchingFromSystemUserMessage or switchingToSystemUserMessage is null, fallback + // to system message. + if (viewMessage == null) { + viewMessage = res.getString(R.string.user_switching_message, newUser.name); + } } ((TextView) view.findViewById(R.id.message)).setText(viewMessage); setView(view); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java index 36de3d12a743..384b416b0201 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java @@ -109,4 +109,21 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { public boolean startUserInBackground(ComponentName who, UserHandle userHandle) { return false; } + + @Override + public void setStartUserSessionMessage( + ComponentName admin, CharSequence startUserSessionMessage) {} + + @Override + public void setEndUserSessionMessage(ComponentName admin, CharSequence endUserSessionMessage) {} + + @Override + public String getStartUserSessionMessage(ComponentName admin) { + return null; + } + + @Override + public String getEndUserSessionMessage(ComponentName admin) { + return null; + } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 4e29935d7638..cb4f5c1177df 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -200,6 +200,7 @@ import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo; import com.android.server.pm.UserRestrictionsUtils; + import com.google.android.collect.Sets; import org.xmlpull.v1.XmlPullParser; @@ -792,6 +793,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications"; private static final String TAG_IS_LOGOUT_ENABLED = "is_logout_enabled"; private static final String TAG_MANDATORY_BACKUP_TRANSPORT = "mandatory_backup_transport"; + private static final String TAG_START_USER_SESSION_MESSAGE = "start_user_session_message"; + private static final String TAG_END_USER_SESSION_MESSAGE = "end_user_session_message"; DeviceAdminInfo info; @@ -912,6 +915,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // or null if backups are not mandatory. ComponentName mandatoryBackupTransport = null; + // Message for user switcher + String startUserSessionMessage = null; + String endUserSessionMessage = null; + ActiveAdmin(DeviceAdminInfo _info, boolean parent) { info = _info; isParent = parent; @@ -1180,6 +1187,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { out.attribute(null, ATTR_VALUE, mandatoryBackupTransport.flattenToString()); out.endTag(null, TAG_MANDATORY_BACKUP_TRANSPORT); } + if (startUserSessionMessage != null) { + out.startTag(null, TAG_START_USER_SESSION_MESSAGE); + out.text(startUserSessionMessage); + out.endTag(null, TAG_START_USER_SESSION_MESSAGE); + } + if (endUserSessionMessage != null) { + out.startTag(null, TAG_END_USER_SESSION_MESSAGE); + out.text(endUserSessionMessage); + out.endTag(null, TAG_END_USER_SESSION_MESSAGE); + } } void writePackageListToXml(XmlSerializer out, String outerTag, @@ -1361,6 +1378,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } else if (TAG_MANDATORY_BACKUP_TRANSPORT.equals(tag)) { mandatoryBackupTransport = ComponentName.unflattenFromString( parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_START_USER_SESSION_MESSAGE.equals(tag)) { + type = parser.next(); + if (type == XmlPullParser.TEXT) { + startUserSessionMessage = parser.getText(); + } else { + Log.w(LOG_TAG, "Missing text when loading start session message"); + } + } else if (TAG_END_USER_SESSION_MESSAGE.equals(tag)) { + type = parser.next(); + if (type == XmlPullParser.TEXT) { + endUserSessionMessage = parser.getText(); + } else { + Log.w(LOG_TAG, "Missing text when loading end session message"); + } } else { Slog.w(LOG_TAG, "Unknown admin tag: " + tag); XmlUtils.skipCurrentTag(parser); @@ -3215,10 +3246,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } synchronized (this) { - // push the force-ephemeral-users policy to the user manager. ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); if (deviceOwner != null) { + // Push the force-ephemeral-users policy to the user manager. mUserManagerInternal.setForceEphemeralUsers(deviceOwner.forceEphemeralUsers); + + // Update user switcher message to activity manager. + ActivityManagerInternal activityManagerInternal = + mInjector.getActivityManagerInternal(); + activityManagerInternal.setSwitchingFromSystemUserMessage( + deviceOwner.startUserSessionMessage); + activityManagerInternal.setSwitchingToSystemUserMessage( + deviceOwner.endUserSessionMessage); } } } @@ -12034,15 +12073,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } Preconditions.checkNotNull(admin); - getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); - if (enabled == isLogoutEnabledInternalLocked()) { - // already in the requested state - return; + synchronized (this) { + ActiveAdmin deviceOwner = + getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + + if (deviceOwner.isLogoutEnabled == enabled) { + // already in the requested state + return; + } + deviceOwner.isLogoutEnabled = enabled; + saveSettingsLocked(mInjector.userHandleGetCallingUserId()); } - ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); - deviceOwner.isLogoutEnabled = enabled; - saveSettingsLocked(mInjector.userHandleGetCallingUserId()); } @Override @@ -12051,15 +12093,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } synchronized (this) { - return isLogoutEnabledInternalLocked(); + ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); + return (deviceOwner != null) && deviceOwner.isLogoutEnabled; } } - private boolean isLogoutEnabledInternalLocked() { - ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); - return (deviceOwner != null) && deviceOwner.isLogoutEnabled; - } - @Override public List<String> getDisallowedSystemApps(ComponentName admin, int userId, String provisioningAction) throws RemoteException { @@ -12157,4 +12195,83 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } return extras; } + + @Override + public void setStartUserSessionMessage( + ComponentName admin, CharSequence startUserSessionMessage) { + if (!mHasFeature) { + return; + } + Preconditions.checkNotNull(admin); + + final String startUserSessionMessageString = + startUserSessionMessage != null ? startUserSessionMessage.toString() : null; + + synchronized (this) { + final ActiveAdmin deviceOwner = + getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + + if (TextUtils.equals(deviceOwner.startUserSessionMessage, startUserSessionMessage)) { + return; + } + deviceOwner.startUserSessionMessage = startUserSessionMessageString; + saveSettingsLocked(mInjector.userHandleGetCallingUserId()); + } + + mInjector.getActivityManagerInternal() + .setSwitchingFromSystemUserMessage(startUserSessionMessageString); + } + + @Override + public void setEndUserSessionMessage(ComponentName admin, CharSequence endUserSessionMessage) { + if (!mHasFeature) { + return; + } + Preconditions.checkNotNull(admin); + + final String endUserSessionMessageString = + endUserSessionMessage != null ? endUserSessionMessage.toString() : null; + + synchronized (this) { + final ActiveAdmin deviceOwner = + getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + + if (TextUtils.equals(deviceOwner.endUserSessionMessage, endUserSessionMessage)) { + return; + } + deviceOwner.endUserSessionMessage = endUserSessionMessageString; + saveSettingsLocked(mInjector.userHandleGetCallingUserId()); + } + + mInjector.getActivityManagerInternal() + .setSwitchingToSystemUserMessage(endUserSessionMessageString); + } + + @Override + public String getStartUserSessionMessage(ComponentName admin) { + if (!mHasFeature) { + return null; + } + Preconditions.checkNotNull(admin); + + synchronized (this) { + final ActiveAdmin deviceOwner = + getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + return deviceOwner.startUserSessionMessage; + } + } + + @Override + public String getEndUserSessionMessage(ComponentName admin) { + if (!mHasFeature) { + return null; + } + Preconditions.checkNotNull(admin); + + synchronized (this) { + final ActiveAdmin deviceOwner = + getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + return deviceOwner.endUserSessionMessage; + } + } } |