diff options
15 files changed, 240 insertions, 85 deletions
diff --git a/packages/SystemUI/res/color/qs_user_detail_name.xml b/packages/SystemUI/res/color/qs_user_detail_name.xml index 8ddb9be..57f7e65 100644 --- a/packages/SystemUI/res/color/qs_user_detail_name.xml +++ b/packages/SystemUI/res/color/qs_user_detail_name.xml @@ -17,6 +17,6 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_activated="true" android:color="#ffffffff" /> + <item android:state_activated="true" android:color="@color/current_user_border_color" /> <item android:color="#66ffffff" /> <!-- 40% white --> </selector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_account_circle_qs.xml b/packages/SystemUI/res/drawable/ic_account_circle_qs.xml index 0d5cd2e..d10a96d 100644 --- a/packages/SystemUI/res/drawable/ic_account_circle_qs.xml +++ b/packages/SystemUI/res/drawable/ic_account_circle_qs.xml @@ -16,7 +16,19 @@ ~ limitations under the License --> -<selector xmlns:android="http://schemas.android.com/apk/res/android" > - <item android:state_activated="true" android:drawable="@drawable/ic_account_circle" /> - <item android:drawable="@drawable/ic_account_circle_qs_muted" /> -</selector> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + + <group + android:scaleX="1.2" + android:scaleY="1.2" + android:pivotX="12.0" + android:pivotY="12.0"> + <path + android:fillColor="@color/qs_user_detail_icon_muted" + android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM12.0,5.0c1.7,0.0 3.0,1.3 3.0,3.0c0.0,1.7 -1.3,3.0 -3.0,3.0c-1.7,0.0 -3.0,-1.3 -3.0,-3.0C9.0,6.3 10.3,5.0 12.0,5.0zM12.0,19.2c-2.5,0.0 -4.7,-1.3 -6.0,-3.2c0.0,-2.0 4.0,-3.1 6.0,-3.1c2.0,0.0 6.0,1.1 6.0,3.1C16.7,17.9 14.5,19.2 12.0,19.2z"/> + </group> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_account_circle_qs_muted.xml b/packages/SystemUI/res/drawable/ic_account_circle_qs_muted.xml deleted file mode 100644 index 7b8b89f..0000000 --- a/packages/SystemUI/res/drawable/ic_account_circle_qs_muted.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<!-- - ~ Copyright (C) 2014 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 - --> - -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - - <group - android:scaleX="1.2" - android:scaleY="1.2" - android:pivotX="12.0" - android:pivotY="12.0"> - <path - android:fillColor="@color/qs_user_detail_icon_muted" - android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM12.0,5.0c1.7,0.0 3.0,1.3 3.0,3.0c0.0,1.7 -1.3,3.0 -3.0,3.0c-1.7,0.0 -3.0,-1.3 -3.0,-3.0C9.0,6.3 10.3,5.0 12.0,5.0zM12.0,19.2c-2.5,0.0 -4.7,-1.3 -6.0,-3.2c0.0,-2.0 4.0,-3.1 6.0,-3.1c2.0,0.0 6.0,1.1 6.0,3.1C16.7,17.9 14.5,19.2 12.0,19.2z"/> - </group> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_add_circle_qs.xml b/packages/SystemUI/res/drawable/ic_add_circle_qs.xml new file mode 100644 index 0000000..f296076 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_add_circle_qs.xml @@ -0,0 +1,30 @@ +<!-- +Copyright (C) 2014 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="48.0dp" + android:height="48.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <group + android:scaleX="1.2" + android:scaleY="1.2" + android:pivotX="12.0" + android:pivotY="12.0"> + <path + android:fillColor="@color/qs_user_detail_icon_muted" + android:pathData="M12.000000,2.000000C6.500000,2.000000 2.000000,6.500000 2.000000,12.000000s4.500000,10.000000 10.000000,10.000000c5.500000,0.000000 10.000000,-4.500000 10.000000,-10.000000S17.500000,2.000000 12.000000,2.000000zM17.000000,13.000000l-4.000000,0.000000l0.000000,4.000000l-2.000000,0.000000l0.000000,-4.000000L7.000000,13.000000l0.000000,-2.000000l4.000000,0.000000L11.000000,7.000000l2.000000,0.000000l0.000000,4.000000l4.000000,0.000000L17.000000,13.000000z"/> + </group> +</vector> diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml index d17390e..2e67376 100644 --- a/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml +++ b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml @@ -16,7 +16,9 @@ ~ limitations under the License --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<!-- LinearLayout --> +<com.android.systemui.qs.tiles.UserDetailItemView + xmlns:android="http://schemas.android.com/apk/res/android" xmlns:sysui="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -24,17 +26,21 @@ android:layout_marginEnd="8dp" android:gravity="center_vertical" android:clickable="true" - android:background="@drawable/ripple_drawable"> - <TextView android:id="@+id/name" + android:background="@drawable/ripple_drawable" + android:clipChildren="false" + android:clipToPadding="false" + sysui:activatedFontFamily="sans-serif-medium"> + <TextView android:id="@+id/user_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="16dp" android:textAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher.UserName" /> - <com.android.systemui.statusbar.phone.UserAvatarView android:id="@+id/picture" + <com.android.systemui.statusbar.phone.UserAvatarView android:id="@+id/user_picture" android:layout_width="@dimen/max_avatar_size" android:layout_height="@dimen/max_avatar_size" android:contentDescription="@null" sysui:frameWidth="@dimen/keyguard_user_switcher_border_thickness" + sysui:framePadding="6dp" sysui:activeFrameColor="@color/current_user_border_color" /> -</LinearLayout>
\ No newline at end of file +</com.android.systemui.qs.tiles.UserDetailItemView>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml index 403860c..5ceed84 100644 --- a/packages/SystemUI/res/layout/qs_user_detail_item.xml +++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml @@ -25,7 +25,10 @@ android:orientation="vertical" android:gravity="top|center_horizontal" android:paddingTop="16dp" - android:paddingBottom="20dp"> + android:paddingBottom="20dp" + android:clipChildren="false" + android:clipToPadding="false" + systemui:activatedFontFamily="sans-serif-medium"> <com.android.systemui.statusbar.phone.UserAvatarView android:id="@+id/user_picture" @@ -33,6 +36,7 @@ android:layout_height="@dimen/max_avatar_size" android:layout_marginBottom="12dp" systemui:frameWidth="2dp" + systemui:framePadding="6dp" systemui:activeFrameColor="@color/current_user_border_color"/> <TextView diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml index d8d170d..8bd3c39 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -56,9 +56,14 @@ </attr> <declare-styleable name="UserAvatarView"> <attr name="frameWidth" format="dimension" /> + <attr name="framePadding" format="dimension" /> <attr name="activeFrameColor" format="color" /> <attr name="frameColor" /> </declare-styleable> + <declare-styleable name="UserDetailItemView"> + <attr name="regularFontFamily" format="string" /> + <attr name="activatedFontFamily" format="string" /> + </declare-styleable> <declare-styleable name="DateView"> <attr name="datePattern" format="string" /> </declare-styleable> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 83a9a81..601a77b 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -672,6 +672,13 @@ <string name="keyguard_indication_charging_time">Charging (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%s</xliff:g> until full)</string> <!-- Related to user switcher --><skip/> + + <!-- Label for the adding a new user in the user switcher [CHAR LIMIT=35] --> + <string name="user_add_user">Add user</string> + + <!-- Name for a freshly added user [CHAR LIMIT=30] --> + <string name="user_new_user_name">New user</string> + <!-- Name for the guest user [CHAR LIMIT=35] --> <string name="guest_nickname">Guest</string> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index fc66730..5db6912 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -103,7 +103,7 @@ <style name="TextAppearance.StatusBar.Expanded.UserSwitcher"> <item name="android:textSize">16sp</item> <item name="android:textStyle">normal</item> - <item name="android:textColor">#ffffff</item> + <item name="android:textColor">@color/qs_user_detail_name</item> </style> <style name="TextAppearance.StatusBar.Expanded.UserSwitcher.UserName" /> 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 d765aab..759d540 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java @@ -16,11 +16,14 @@ package com.android.systemui.qs.tiles; +import com.android.internal.util.ArrayUtils; import com.android.systemui.R; import com.android.systemui.statusbar.phone.UserAvatarView; import android.content.Context; +import android.content.res.TypedArray; import android.graphics.Bitmap; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.LayoutInflater; @@ -36,6 +39,8 @@ public class UserDetailItemView extends LinearLayout { private UserAvatarView mAvatar; private TextView mName; + private Typeface mRegularTypeface; + private Typeface mActivatedTypeface; public UserDetailItemView(Context context) { this(context, null); @@ -52,6 +57,21 @@ public class UserDetailItemView extends LinearLayout { public UserDetailItemView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); + final TypedArray a = context.obtainStyledAttributes( + attrs, R.styleable.UserDetailItemView, defStyleAttr, defStyleRes); + final int N = a.getIndexCount(); + for (int i = 0; i < N; i++) { + int attr = a.getIndex(i); + switch (attr) { + case R.styleable.UserDetailItemView_regularFontFamily: + mRegularTypeface = Typeface.create(a.getString(attr), 0 /* style */); + break; + case R.styleable.UserDetailItemView_activatedFontFamily: + mActivatedTypeface = Typeface.create(a.getString(attr), 0 /* style */); + break; + } + } + a.recycle(); } public static UserDetailItemView convertOrInflate(Context context, View convertView, @@ -77,6 +97,23 @@ public class UserDetailItemView extends LinearLayout { protected void onFinishInflate() { mAvatar = (UserAvatarView) findViewById(R.id.user_picture); mName = (TextView) findViewById(R.id.user_name); + if (mRegularTypeface == null) { + mRegularTypeface = mName.getTypeface(); + } + if (mActivatedTypeface == null) { + mActivatedTypeface = mName.getTypeface(); + } + updateTypeface(); } + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + updateTypeface(); + } + + private void updateTypeface() { + boolean activated = ArrayUtils.contains(getDrawableState(), android.R.attr.state_activated); + mName.setTypeface(activated ? mActivatedTypeface : mRegularTypeface); + } } 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 67eef56..8cff81a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java @@ -83,7 +83,7 @@ public class UserDetailView extends GridView { mContext, convertView, parent); String name = getName(mContext, item); if (item.picture == null) { - v.bind(name, mContext.getDrawable(R.drawable.ic_account_circle_qs)); + v.bind(name, getDrawable(mContext, item)); } else { v.bind(name, item.picture); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 015a21d..e8b167c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -799,9 +799,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mFlashlightController = new FlashlightController(mContext); mKeyguardBottomArea.setFlashlightController(mFlashlightController); - mUserSwitcherController = new UserSwitcherController(mContext); mNextAlarmController = new NextAlarmController(mContext); mKeyguardMonitor = new KeyguardMonitor(); + mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor); mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext, (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher), diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java index 93561aa..101a5f3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java @@ -38,6 +38,7 @@ public class UserAvatarView extends View { private int mActiveFrameColor; private int mFrameColor; private float mFrameWidth; + private float mFramePadding; private Bitmap mBitmap; private Drawable mDrawable; @@ -60,6 +61,9 @@ public class UserAvatarView extends View { case R.styleable.UserAvatarView_frameWidth: setFrameWidth(a.getDimension(attr, 0)); break; + case R.styleable.UserAvatarView_framePadding: + setFramePadding(a.getDimension(attr, 0)); + break; case R.styleable.UserAvatarView_activeFrameColor: setActiveFrameColor(a.getColor(attr, 0)); break; @@ -115,6 +119,11 @@ public class UserAvatarView extends View { invalidate(); } + public void setFramePadding(float framePadding) { + mFramePadding = framePadding; + invalidate(); + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); @@ -131,11 +140,11 @@ public class UserAvatarView extends View { dwidth = mBitmap.getWidth(); dheight = mBitmap.getHeight(); } else if (mDrawable != null) { - dwidth = mDrawable.getIntrinsicWidth(); - dheight = mDrawable.getIntrinsicHeight(); - mDrawable.setBounds(0, 0, dwidth, dheight); vwidth -= 2 * (mFrameWidth - 1); vheight -= 2 * (mFrameWidth - 1); + dwidth = vwidth; + dheight = vheight; + mDrawable.setBounds(0, 0, dwidth, dheight); } else { return; } @@ -183,7 +192,8 @@ public class UserAvatarView extends View { if (frameColor != 0) { mFramePaint.setColor(frameColor); mFramePaint.setStrokeWidth(mFrameWidth); - canvas.drawCircle(halfW, halfH, halfSW - mFrameWidth / 2f, mFramePaint); + canvas.drawCircle(halfW, halfH, halfSW + (mFramePadding - mFrameWidth) / 2f, + mFramePaint); } } 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 a0312bc..ffc6898 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java @@ -26,6 +26,7 @@ import android.view.ViewStub; import android.widget.TextView; import com.android.systemui.R; +import com.android.systemui.qs.tiles.UserDetailItemView; import com.android.systemui.statusbar.phone.KeyguardStatusBarView; import com.android.systemui.statusbar.phone.UserAvatarView; @@ -140,21 +141,19 @@ public class KeyguardUserSwitcher { public View getView(int position, View convertView, ViewGroup parent) { UserSwitcherController.UserRecord item = getItem(position); - if (convertView == null + if (!(convertView instanceof UserDetailItemView) || !(convertView.getTag() instanceof UserSwitcherController.UserRecord)) { convertView = LayoutInflater.from(mContext).inflate( R.layout.keyguard_user_switcher_item, parent, false); convertView.setOnClickListener(this); } + UserDetailItemView v = (UserDetailItemView) convertView; - TextView nameView = (TextView) convertView.findViewById(R.id.name); - UserAvatarView pictureView = (UserAvatarView) convertView.findViewById(R.id.picture); - - nameView.setText(getName(mContext, item)); + String name = getName(mContext, item); if (item.picture == null) { - pictureView.setDrawable(mContext.getDrawable(R.drawable.ic_account_circle_qs)); + v.bind(name, getDrawable(mContext, item)); } else { - pictureView.setBitmap(item.picture); + v.bind(name, item.picture); } convertView.setActivated(item.isCurrent); convertView.setTag(item); 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 6e3656d..c48f3f5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -34,6 +34,7 @@ import android.content.IntentFilter; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Handler; import android.os.RemoteException; @@ -68,15 +69,18 @@ public class UserSwitcherController { private final ArrayList<WeakReference<BaseUserAdapter>> mAdapters = new ArrayList<>(); private final GuestResumeSessionReceiver mGuestResumeSessionReceiver = new GuestResumeSessionReceiver(); - private boolean mSimpleUserSwitcher; + private final KeyguardMonitor mKeyguardMonitor; private ArrayList<UserRecord> mUsers = new ArrayList<>(); private Dialog mExitGuestDialog; private int mLastNonGuestUser = UserHandle.USER_OWNER; + private boolean mSimpleUserSwitcher; + private boolean mAddUsersWhenLocked; - public UserSwitcherController(Context context) { + public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor) { mContext = context; mGuestResumeSessionReceiver.register(context); + mKeyguardMonitor = keyguardMonitor; mUserManager = UserManager.get(context); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_USER_ADDED); @@ -87,11 +91,17 @@ public class UserSwitcherController { mContext.registerReceiverAsUser(mReceiver, UserHandle.OWNER, filter, null /* permission */, null /* scheduler */); - mSimpleUserSwitcher = Settings.Global.getInt(context.getContentResolver(), - SIMPLE_USER_SWITCHER_GLOBAL_SETTING, 0) != 0; + mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(SIMPLE_USER_SWITCHER_GLOBAL_SETTING), true, - mSimpleUserSwitcherObserver); + mSettingsObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Global.getUriFor(Settings.Global.ADD_USERS_WHEN_LOCKED), true, + mSettingsObserver); + // Fetch initial values. + mSettingsObserver.onChange(false); + + keyguardMonitor.addCallback(mCallback); refreshUsers(UserHandle.USER_NULL); } @@ -116,6 +126,7 @@ public class UserSwitcherController { bitmaps.put(r.info.id, r.picture); } + final boolean addUsersWhenLocked = mAddUsersWhenLocked; new AsyncTask<SparseArray<Bitmap>, Void, ArrayList<UserRecord>>() { @SuppressWarnings("unchecked") @Override @@ -135,7 +146,8 @@ public class UserSwitcherController { boolean isCurrent = currentId == info.id; if (info.isGuest()) { guestRecord = new UserRecord(info, null /* picture */, - true /* isGuest */, isCurrent); + true /* isGuest */, isCurrent, false /* isAddUser */, + false /* isRestricted */); } else if (info.supportsSwitchTo()) { Bitmap picture = bitmaps.get(info.id); if (picture == null) { @@ -145,19 +157,40 @@ public class UserSwitcherController { picture = BitmapHelper.createCircularClip( picture, avatarSize, avatarSize); } - records.add(new UserRecord(info, picture, false /* isGuest */, isCurrent)); + records.add(new UserRecord(info, picture, false /* isGuest */, isCurrent, + false /* isAddUser */, false /* isRestricted */)); } } + boolean ownerCanCreateUsers = !mUserManager.hasUserRestriction( + UserManager.DISALLOW_ADD_USER, UserHandle.OWNER); + boolean currentUserCanCreateUsers = + (currentId == UserHandle.USER_OWNER) && ownerCanCreateUsers; + boolean anyoneCanCreateUsers = ownerCanCreateUsers && addUsersWhenLocked; + boolean canCreateGuest = (currentUserCanCreateUsers || anyoneCanCreateUsers) + && guestRecord == null; + boolean canCreateUser = (currentUserCanCreateUsers || anyoneCanCreateUsers) + && records.size() < UserManager.getMaxSupportedUsers(); + boolean createIsRestricted = !addUsersWhenLocked; + if (!mSimpleUserSwitcher) { if (guestRecord == null) { - records.add(new UserRecord(null /* info */, null /* picture */, - true /* isGuest */, false /* isCurrent */)); + if (canCreateGuest) { + records.add(new UserRecord(null /* info */, null /* picture */, + true /* isGuest */, false /* isCurrent */, + false /* isAddUser */, createIsRestricted)); + } } else { records.add(guestRecord); } } + if (canCreateUser) { + records.add(new UserRecord(null /* info */, null /* picture */, + false /* isGuest */, false /* isCurrent */, true /* isAddUser */, + createIsRestricted)); + } + return records; } @@ -168,7 +201,7 @@ public class UserSwitcherController { notifyAdapters(); } } - }.execute((SparseArray)bitmaps); + }.execute((SparseArray) bitmaps); } private void notifyAdapters() { @@ -190,8 +223,10 @@ public class UserSwitcherController { int id; if (record.isGuest && record.info == null) { // No guest user. Create one. - id = mUserManager.createGuest(mContext, - mContext.getResources().getString(R.string.guest_nickname)).id; + id = mUserManager.createGuest(mContext, mContext.getString(R.string.guest_nickname)).id; + } else if (record.isAddUser) { + id = mUserManager.createUser( + mContext.getString(R.string.user_new_user_name), 0 /* flags */).id; } else { id = record.info.id; } @@ -260,6 +295,11 @@ public class UserSwitcherController { if (shouldBeCurrent && !record.isGuest) { mLastNonGuestUser = record.info.id; } + if (currentId != UserHandle.USER_OWNER && record.isRestricted) { + // Immediately remove restricted records in case the AsyncTask is too slow. + mUsers.remove(i); + i--; + } } notifyAdapters(); } @@ -272,10 +312,12 @@ public class UserSwitcherController { } }; - private final ContentObserver mSimpleUserSwitcherObserver = new ContentObserver(new Handler()) { + private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) { public void onChange(boolean selfChange) { mSimpleUserSwitcher = Settings.Global.getInt(mContext.getContentResolver(), SIMPLE_USER_SWITCHER_GLOBAL_SETTING, 0) != 0; + mAddUsersWhenLocked = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0; refreshUsers(UserHandle.USER_NULL); }; }; @@ -301,7 +343,22 @@ public class UserSwitcherController { @Override public int getCount() { - return mController.mUsers.size(); + boolean secureKeyguardShowing = mController.mKeyguardMonitor.isShowing() + && mController.mKeyguardMonitor.isSecure(); + if (!secureKeyguardShowing) { + return mController.mUsers.size(); + } + // The lock screen is secure and showing. Filter out restricted records. + final int N = mController.mUsers.size(); + int count = 0; + for (int i = 0; i < N; i++) { + if (mController.mUsers.get(i).isRestricted) { + break; + } else { + count++; + } + } + return count; } @Override @@ -326,6 +383,8 @@ public class UserSwitcherController { return context.getString( item.info == null ? R.string.guest_new_guest : R.string.guest_nickname); } + } else if (item.isAddUser) { + return context.getString(R.string.user_add_user); } else { return item.info.name; } @@ -342,6 +401,13 @@ public class UserSwitcherController { } return result; } + + public Drawable getDrawable(Context context, UserRecord item) { + if (item.isAddUser) { + return context.getDrawable(R.drawable.ic_add_circle_qs); + } + return context.getDrawable(R.drawable.ic_account_circle_qs); + } } public static final class UserRecord { @@ -349,16 +415,22 @@ public class UserSwitcherController { public final Bitmap picture; public final boolean isGuest; public final boolean isCurrent; + public final boolean isAddUser; + /** If true, the record is only visible to the owner and only when unlocked. */ + public final boolean isRestricted; - public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent) { + public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent, + boolean isAddUser, boolean isRestricted) { this.info = info; this.picture = picture; this.isGuest = isGuest; this.isCurrent = isCurrent; + this.isAddUser = isAddUser; + this.isRestricted = isRestricted; } public UserRecord copyWithIsCurrent(boolean _isCurrent) { - return new UserRecord(info, picture, isGuest, _isCurrent); + return new UserRecord(info, picture, isGuest, _isCurrent, isAddUser, isRestricted); } public String toString() { @@ -367,17 +439,17 @@ public class UserSwitcherController { if (info != null) { sb.append("name=\"" + info.name + "\" id=" + info.id); } else { - sb.append("<add guest placeholder>"); - } - if (isGuest) { - sb.append(" <isGuest>"); - } - if (isCurrent) { - sb.append(" <isCurrent>"); - } - if (picture != null) { - sb.append(" <hasPicture>"); + if (isGuest) { + sb.append("<add guest placeholder>"); + } else if (isAddUser) { + sb.append("<add user placeholder>"); + } } + if (isGuest) sb.append(" <isGuest>"); + if (isAddUser) sb.append(" <isAddUser>"); + if (isCurrent) sb.append(" <isCurrent>"); + if (picture != null) sb.append(" <hasPicture>"); + if (isRestricted) sb.append(" <isRestricted>"); sb.append(')'); return sb.toString(); } @@ -418,6 +490,13 @@ public class UserSwitcherController { } }; + private final KeyguardMonitor.Callback mCallback = new KeyguardMonitor.Callback() { + @Override + public void onKeyguardChanged() { + notifyAdapters(); + } + }; + private final class ExitGuestDialog extends SystemUIDialog implements DialogInterface.OnClickListener { |