Disable switching users until user 0 is unlocked

Switching with user0 locked can be re-enabled by setting
allow_user_switching_when_system_user_locked flag to a non-zero value

Bug: 26933989
Change-Id: I0958058f1cc8a059db9c20930e07183c14c8460a
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 770cde7..64fb9ca 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8140,6 +8140,15 @@
                 "uninstalled_ephemeral_app_cache_duration_millis";
 
         /**
+         * Allows switching users when system user is locked.
+         * <p>
+         * Type: int
+         * @hide
+         */
+        public static final String ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED =
+                "allow_user_switching_when_system_user_locked";
+
+        /**
          * Settings to backup. This is here so that it's in the same place as the settings
          * keys and easy to update.
          *
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
index 33befd0..fcf758b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
@@ -103,6 +103,11 @@
         mAvatar.setDisabled(disabled);
     }
 
+    public void setEnabled(boolean enabled) {
+        mName.setEnabled(enabled);
+        mAvatar.setDisabled(!enabled);
+    }
+
     @Override
     protected void onFinishInflate() {
         mAvatar = (UserAvatarView) findViewById(R.id.user_picture);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index 2c8a478..da98762 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -82,6 +82,9 @@
             }
             v.setActivated(item.isCurrent);
             v.setDisabledByAdmin(item.isDisabledByAdmin);
+            if (!item.isSwitchToEnabled) {
+                v.setEnabled(false);
+            }
             v.setTag(item);
             return v;
         }
@@ -94,7 +97,7 @@
                 final Intent intent = RestrictedLockUtils.getShowAdminSupportDetailsIntent(
                         mContext, tag.enforcedAdmin);
                 mController.startActivity(intent);
-            } else {
+            } else if (tag.isSwitchToEnabled) {
                 MetricsLogger.action(mContext, MetricsEvent.QS_SWITCH_USER);
                 switchTo(tag);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
index 867a8a3..fb310a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
@@ -21,6 +21,8 @@
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.database.DataSetObserver;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -242,7 +244,6 @@
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
             UserSwitcherController.UserRecord item = getItem(position);
-
             if (!(convertView instanceof UserDetailItemView)
                     || !(convertView.getTag() instanceof UserSwitcherController.UserRecord)) {
                 convertView = LayoutInflater.from(mContext).inflate(
@@ -252,11 +253,17 @@
             UserDetailItemView v = (UserDetailItemView) convertView;
 
             String name = getName(mContext, item);
+            Drawable drawable;
             if (item.picture == null) {
-                v.bind(name, getDrawable(mContext, item));
+                drawable = getDrawable(mContext, item).mutate();
             } else {
-                v.bind(name, item.picture);
+                drawable = new BitmapDrawable(mContext.getResources(), item.picture);
             }
+            // Disable the icon if switching is disabled
+            if (!item.isSwitchToEnabled) {
+                drawable.setTint(mContext.getColor(R.color.qs_tile_disabled_color));
+            }
+            v.bind(name, drawable);
             convertView.setActivated(item.isCurrent);
             convertView.setTag(item);
             return convertView;
@@ -269,7 +276,7 @@
                 // Close the switcher if tapping the current user. Guest is excluded because
                 // tapping the guest user while it's current clears the session.
                 mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */);
-            } else {
+            } else if (user.isSwitchToEnabled) {
                 switchTo(user);
             }
         }
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 13369f2..4c67010 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -99,6 +99,7 @@
     private boolean mSimpleUserSwitcher;
     private boolean mAddUsersWhenLocked;
     private boolean mPauseRefreshUsers;
+    private boolean mAllowUserSwitchingWhenSystemUserLocked;
     private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
 
     public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor,
@@ -115,6 +116,7 @@
         filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
         filter.addAction(Intent.ACTION_USER_SWITCHED);
         filter.addAction(Intent.ACTION_USER_STOPPING);
+        filter.addAction(Intent.ACTION_USER_UNLOCKED);
         mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
                 null /* permission */, null /* scheduler */);
 
@@ -130,6 +132,10 @@
         mContext.getContentResolver().registerContentObserver(
                 Settings.Global.getUriFor(Settings.Global.ADD_USERS_WHEN_LOCKED), true,
                 mSettingsObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(
+                        Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED),
+                true, mSettingsObserver);
         // Fetch initial values.
         mSettingsObserver.onChange(false);
 
@@ -180,6 +186,8 @@
                 }
                 ArrayList<UserRecord> records = new ArrayList<>(infos.size());
                 int currentId = ActivityManager.getCurrentUser();
+                boolean allowUserSwitching = mAllowUserSwitchingWhenSystemUserLocked
+                        || mUserManager.isUserUnlocked(UserHandle.SYSTEM);
                 UserInfo currentUserInfo = null;
                 UserRecord guestRecord = null;
                 int avatarSize = mContext.getResources()
@@ -190,10 +198,11 @@
                     if (isCurrent) {
                         currentUserInfo = info;
                     }
+                    boolean switchToEnabled = allowUserSwitching || isCurrent;
                     if (info.isGuest()) {
                         guestRecord = new UserRecord(info, null /* picture */,
                                 true /* isGuest */, isCurrent, false /* isAddUser */,
-                                false /* isRestricted */);
+                                false /* isRestricted */, switchToEnabled);
                     } else if (info.isEnabled() && info.supportsSwitchToByUser()) {
                         Bitmap picture = bitmaps.get(info.id);
                         if (picture == null) {
@@ -206,7 +215,8 @@
                         }
                         int index = isCurrent ? 0 : records.size();
                         records.add(index, new UserRecord(info, picture, false /* isGuest */,
-                                isCurrent, false /* isAddUser */, false /* isRestricted */));
+                                isCurrent, false /* isAddUser */, false /* isRestricted */,
+                                switchToEnabled));
                     }
                 }
 
@@ -228,7 +238,7 @@
                         if (canCreateGuest) {
                             guestRecord = new UserRecord(null /* info */, null /* picture */,
                                     true /* isGuest */, false /* isCurrent */,
-                                    false /* isAddUser */, createIsRestricted);
+                                    false /* isAddUser */, createIsRestricted, allowUserSwitching);
                             checkIfAddUserDisallowedByAdminOnly(guestRecord);
                             records.add(guestRecord);
                         }
@@ -241,7 +251,7 @@
                 if (!mSimpleUserSwitcher && canCreateUser) {
                     UserRecord addUserRecord = new UserRecord(null /* info */, null /* picture */,
                             false /* isGuest */, false /* isCurrent */, true /* isAddUser */,
-                            createIsRestricted);
+                            createIsRestricted, allowUserSwitching);
                     checkIfAddUserDisallowedByAdminOnly(addUserRecord);
                     records.add(addUserRecord);
                 }
@@ -463,6 +473,12 @@
             } else if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) {
                 forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
                         UserHandle.USER_NULL);
+            } else if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
+                // Unlocking the system user may require a refresh
+                int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+                if (userId != UserHandle.USER_SYSTEM) {
+                    return;
+                }
             }
             refreshUsers(forcePictureLoadForId);
             if (unpauseRefreshUsers) {
@@ -525,6 +541,9 @@
                     SIMPLE_USER_SWITCHER_GLOBAL_SETTING, 0) != 0;
             mAddUsersWhenLocked = Settings.Global.getInt(mContext.getContentResolver(),
                     Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0;
+            mAllowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
+                    mContext.getContentResolver(),
+                    Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, 0) != 0;
             refreshUsers(UserHandle.USER_NULL);
         };
     };
@@ -646,26 +665,29 @@
         public final boolean isRestricted;
         public boolean isDisabledByAdmin;
         public EnforcedAdmin enforcedAdmin;
+        public boolean isSwitchToEnabled;
 
         public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent,
-                boolean isAddUser, boolean isRestricted) {
+                boolean isAddUser, boolean isRestricted, boolean isSwitchToEnabled) {
             this.info = info;
             this.picture = picture;
             this.isGuest = isGuest;
             this.isCurrent = isCurrent;
             this.isAddUser = isAddUser;
             this.isRestricted = isRestricted;
+            this.isSwitchToEnabled = isSwitchToEnabled;
         }
 
         public UserRecord copyWithIsCurrent(boolean _isCurrent) {
-            return new UserRecord(info, picture, isGuest, _isCurrent, isAddUser, isRestricted);
+            return new UserRecord(info, picture, isGuest, _isCurrent, isAddUser, isRestricted,
+                    isSwitchToEnabled);
         }
 
         public String toString() {
             StringBuilder sb = new StringBuilder();
             sb.append("UserRecord(");
             if (info != null) {
-                sb.append("name=\"" + info.name + "\" id=" + info.id);
+                sb.append("name=\"").append(info.name).append("\" id=").append(info.id);
             } else {
                 if (isGuest) {
                     sb.append("<add guest placeholder>");
@@ -680,7 +702,10 @@
             if (isRestricted) sb.append(" <isRestricted>");
             if (isDisabledByAdmin) {
                 sb.append(" <isDisabledByAdmin>");
-                sb.append(" enforcedAdmin=" + enforcedAdmin);
+                sb.append(" enforcedAdmin=").append(enforcedAdmin);
+            }
+            if (isSwitchToEnabled) {
+                sb.append(" <isSwitchToEnabled>");
             }
             sb.append(')');
             return sb.toString();