summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Roos <roosa@google.com>2014-08-07 12:47:22 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-08-07 09:28:12 +0000
commit04e5f72cdb7bbe494e4b330b393388d1e0b18f74 (patch)
treefae8148a4dd4018a72498c3e712ec904d9a04c03
parent2e7cf64842aadcf198ee97d137ccbb02ee2115fd (diff)
parentccdff62159b41ab130a8f90d30edb9b9542d8c72 (diff)
downloadframeworks_base-04e5f72cdb7bbe494e4b330b393388d1e0b18f74.zip
frameworks_base-04e5f72cdb7bbe494e4b330b393388d1e0b18f74.tar.gz
frameworks_base-04e5f72cdb7bbe494e4b330b393388d1e0b18f74.tar.bz2
Merge "Update User switcher to new spec, implement adding users" into lmp-dev
-rw-r--r--packages/SystemUI/res/color/qs_user_detail_name.xml2
-rw-r--r--packages/SystemUI/res/drawable/ic_account_circle_qs.xml20
-rw-r--r--packages/SystemUI/res/drawable/ic_account_circle_qs_muted.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_add_circle_qs.xml30
-rw-r--r--packages/SystemUI/res/layout/keyguard_user_switcher_item.xml16
-rw-r--r--packages/SystemUI/res/layout/qs_user_detail_item.xml6
-rw-r--r--packages/SystemUI/res/values/attrs.xml5
-rw-r--r--packages/SystemUI/res/values/strings.xml7
-rw-r--r--packages/SystemUI/res/values/styles.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java131
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 {