Introduce logout button and DevicePolicyManager API to enable it
Bug: 67843538
Test: Manual test with CloudDpc that logout button can be controlled by DevicePolicyManager API and only enabled in shared userse
Test: Logout button can actually exit the user and ActivityManager log shows that user is stopped
Test: CTS is tracked in b/67843605
Change-Id: I9f27050654958ce55f574dd05ff80609255ffeb4
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 00e8b1a..3b54e11 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -19,6 +19,7 @@
import android.app.ActivityManager;
import android.app.Dialog;
import android.app.WallpaperManager;
+import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -112,11 +113,13 @@
private static final String GLOBAL_ACTION_KEY_VOICEASSIST = "voiceassist";
private static final String GLOBAL_ACTION_KEY_ASSIST = "assist";
private static final String GLOBAL_ACTION_KEY_RESTART = "restart";
+ private static final String GLOBAL_ACTION_KEY_LOGOUT = "logout";
private final Context mContext;
private final GlobalActionsManager mWindowManagerFuncs;
private final AudioManager mAudioManager;
private final IDreamManager mDreamManager;
+ private final DevicePolicyManager mDevicePolicyManager;
private ArrayList<Action> mItems;
private ActionsDialog mDialog;
@@ -132,6 +135,7 @@
private boolean mIsWaitingForEcmExit = false;
private boolean mHasTelephony;
private boolean mHasVibrator;
+ private boolean mHasLogoutButton;
private final boolean mShowSilentToggle;
private final EmergencyAffordanceManager mEmergencyAffordanceManager;
@@ -144,6 +148,8 @@
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
mDreamManager = IDreamManager.Stub.asInterface(
ServiceManager.getService(DreamService.DREAM_SERVICE));
+ mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
// receive broadcasts
IntentFilter filter = new IntentFilter();
@@ -289,6 +295,7 @@
R.array.config_globalActionsList);
ArraySet<String> addedKeys = new ArraySet<String>();
+ mHasLogoutButton = false;
for (int i = 0; i < defaultActions.length; i++) {
String actionKey = defaultActions[i];
if (addedKeys.contains(actionKey)) {
@@ -325,6 +332,12 @@
mItems.add(getAssistAction());
} else if (GLOBAL_ACTION_KEY_RESTART.equals(actionKey)) {
mItems.add(new RestartAction());
+ } else if (GLOBAL_ACTION_KEY_LOGOUT.equals(actionKey)) {
+ if (mDevicePolicyManager.isLogoutButtonEnabled()
+ && getCurrentUser().id != UserHandle.USER_SYSTEM) {
+ mItems.add(new LogoutAction());
+ mHasLogoutButton = true;
+ }
} else {
Log.e(TAG, "Invalid global action key " + actionKey);
}
@@ -490,6 +503,37 @@
}
}
+ private final class LogoutAction extends SinglePressAction {
+ private LogoutAction() {
+ super(R.drawable.ic_logout, R.string.global_action_logout);
+ }
+
+ @Override
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ @Override
+ public boolean showBeforeProvisioning() {
+ return false;
+ }
+
+ @Override
+ public void onPress() {
+ // Add a little delay before executing, to give the dialog a chance to go away before
+ // switching user
+ mHandler.postDelayed(() -> {
+ try {
+ ActivityManager.getService().switchUser(UserHandle.USER_SYSTEM);
+ ActivityManager.getService().stopUser(getCurrentUser().id, true /*force*/,
+ null);
+ } catch (RemoteException re) {
+ Log.e(TAG, "Couldn't logout user " + re);
+ }
+ }, 500);
+ }
+ }
+
private Action getSettingsAction() {
return new SinglePressAction(R.drawable.ic_settings,
R.string.global_action_settings) {
@@ -764,7 +808,10 @@
public View getView(int position, View convertView, ViewGroup parent) {
Action action = getItem(position);
View view = action.create(mContext, convertView, parent, LayoutInflater.from(mContext));
- if (position == 2) {
+ // When there is no logout button, only power off and restart should be in white
+ // background, thus setting division view at third item; with logout button being the
+ // third item, set the division view at fourth item instead.
+ if (position == (mHasLogoutButton ? 3 : 2)) {
HardwareUiLayout.get(parent).setDivisionView(view);
}
return view;