Merge "Implement keyguard user switcher"

This commit is contained in:
Adrian Roos
2014-06-19 23:52:23 +00:00
committed by Android (Google) Code Review
15 changed files with 559 additions and 3 deletions

View File

@@ -22,7 +22,13 @@ Copyright (C) 2014 The Android Open Source Project
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:fill="#FFFFFFFF"
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>

View File

@@ -0,0 +1,25 @@
<?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
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/keyguard_user_switcher"
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:gravity="end"
android:visibility="gone"
android:paddingTop="4dp">
</LinearLayout>

View File

@@ -0,0 +1,40 @@
<?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
-->
<LinearLayout 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"
android:padding="8dp"
android:layout_marginEnd="8dp"
android:gravity="center_vertical"
android:clickable="true"
android:background="@drawable/ripple_drawable">
<TextView android:id="@+id/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"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription="@null"
sysui:frameWidth="@dimen/keyguard_user_switcher_border_thickness"
sysui:activeFrameColor="@color/current_user_border_color" />
</LinearLayout>

View File

@@ -24,6 +24,7 @@
android:id="@+id/notification_panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
>
<include
@@ -91,6 +92,14 @@
<include layout="@layout/status_bar_expanded_header" />
<ViewStub
android:id="@+id/keyguard_user_switcher"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginTop="@dimen/status_bar_header_height_keyguard"
android:layout_gravity="end"
android:layout="@layout/keyguard_user_switcher" />
<include
layout="@layout/keyguard_bottom_area"
android:visibility="gone" />

View File

@@ -73,9 +73,9 @@
android:layout_width="wrap_content"
android:layout_height="@dimen/status_bar_header_height"
android:layout_toStartOf="@id/multi_user_switch"
android:layout_marginEnd="2dp"
android:layout_alignWithParentIfMissing="true"
android:layout_marginStart="16dp"
/>
android:paddingEnd="2dp" />
<TextView
android:id="@+id/header_charging_info"

View File

@@ -32,4 +32,7 @@
<!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
card. -->
<integer name="keyguard_max_notification_count">5</integer>
<!-- Set to true to enable the user switcher on the keyguard. -->
<bool name="config_keyguardUserSwitcher">true</bool>
</resources>

View File

@@ -54,5 +54,10 @@
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr>
<declare-styleable name="UserAvatarView">
<attr name="frameWidth" format="dimension" />
<attr name="activeFrameColor" format="color" />
<attr name="frameColor" />
</declare-styleable>
</resources>

View File

@@ -60,6 +60,9 @@
<color name="keyguard_affordance">#ffffffff</color>
<!-- The color of the circle around the primary user in the user switcher -->
<color name="current_user_border_color">@color/primary_color</color>
<!-- Our material color palette (deep teal) -->
<color name="primary_color">#ff7fcac3</color>
<color name="background_color_1">#ff384248</color>

View File

@@ -154,5 +154,8 @@
Notification.tickerText across the status bar for what seems like an
eternity. -->
<bool name="enable_ticker">false</bool>
<!-- Set to true to enable the user switcher on the keyguard. -->
<bool name="config_keyguardUserSwitcher">false</bool>
</resources>

View File

@@ -332,4 +332,11 @@
<!-- end margin for multi user switch in expanded quick settings -->
<dimen name="multi_user_switch_expanded_margin">8dp</dimen>
<!-- end margin for system icons if multi user switch is hidden -->
<dimen name="system_icons_switcher_hidden_expanded_margin">16dp</dimen>
<!-- The thickness of the colored border around the current user. -->
<dimen name="keyguard_user_switcher_border_thickness">2dp</dimen>
</resources>

View File

@@ -100,6 +100,13 @@
<style name="TextAppearance.StatusBar.Expanded.Network.EmergencyOnly">
</style>
<style name="TextAppearance.StatusBar.Expanded.UserSwitcher">
<item name="android:textSize">16sp</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">#ffffff</item>
</style>
<style name="TextAppearance.StatusBar.Expanded.UserSwitcher.UserName" />
<style name="TextAppearance" />
<style name="TextAppearance.QuickSettings" />

View File

@@ -123,6 +123,7 @@ import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
import com.android.systemui.statusbar.policy.CastControllerImpl;
import com.android.systemui.statusbar.policy.DateView;
import com.android.systemui.statusbar.policy.HeadsUpNotificationView;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.LocationControllerImpl;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
@@ -211,6 +212,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
ZenModeController mZenModeController;
CastControllerImpl mCastController;
VolumeComponent mVolumeComponent;
KeyguardUserSwitcher mKeyguardUserSwitcher;
int mNaturalBarHeight = -1;
int mIconSize = -1;
@@ -713,6 +715,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
final SignalClusterView signalCluster =
(SignalClusterView)mStatusBarView.findViewById(R.id.signal_cluster);
mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext,
(ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher), mHeader);
mNetworkController.addSignalCluster(signalCluster);
signalCluster.setNetworkController(mNetworkController);
@@ -2913,9 +2917,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardStatusView.setVisibility(View.VISIBLE);
mKeyguardIndicationController.setVisible(true);
mNotificationPanel.resetViews();
mKeyguardUserSwitcher.setKeyguard(true);
} else {
mKeyguardStatusView.setVisibility(View.GONE);
mKeyguardIndicationController.setVisible(false);
mKeyguardUserSwitcher.setKeyguard(false);
}
if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
mKeyguardBottomArea.setVisibility(View.VISIBLE);

View File

@@ -63,6 +63,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private boolean mShowEmergencyCallsOnly;
private boolean mShowChargingInfo;
private boolean mKeyguardUserSwitcherShowing;
private int mCollapsedHeight;
private int mExpandedHeight;
@@ -72,6 +73,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private int mNormalWidth;
private int mPadding;
private int mMultiUserExpandedMargin;
private int mSystemIconsSwitcherHiddenExpandedMargin;
private ActivityStarter mActivityStarter;
private BrightnessController mBrightnessController;
@@ -125,7 +127,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mPadding = getResources().getDimensionPixelSize(R.dimen.notification_side_padding);
mMultiUserExpandedMargin =
getResources().getDimensionPixelSize(R.dimen.multi_user_switch_expanded_margin);
mSystemIconsSwitcherHiddenExpandedMargin = getResources().getDimensionPixelSize(
R.dimen.system_icons_switcher_hidden_expanded_margin);
}
public void setActivityStarter(ActivityStarter activityStarter) {
@@ -216,12 +219,15 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
? VISIBLE : GONE);
mChargingInfo.setVisibility(mExpanded && !mOverscrolled && mShowChargingInfo
&& !mShowEmergencyCallsOnly ? VISIBLE : GONE);
mMultiUserSwitch.setVisibility(mExpanded || !mKeyguardUserSwitcherShowing
? VISIBLE : GONE);
}
private void updateSystemIconsLayoutParams() {
RelativeLayout.LayoutParams lp = (LayoutParams) mSystemIconsContainer.getLayoutParams();
boolean systemIconsAboveClock = mExpanded && !mOverscrolled
&& mShowChargingInfo && !mShowEmergencyCallsOnly;
lp.setMarginEnd(0);
if (systemIconsAboveClock) {
lp.addRule(ALIGN_PARENT_START);
lp.removeRule(START_OF);
@@ -230,7 +236,11 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
? mSettingsButton.getId()
: mMultiUserSwitch.getId());
lp.removeRule(ALIGN_PARENT_START);
if (mMultiUserSwitch.getVisibility() == GONE) {
lp.setMarginEnd(mSystemIconsSwitcherHiddenExpandedMargin);
}
}
mSystemIconsContainer.setLayoutParams(lp);
RelativeLayout.LayoutParams clockLp = (LayoutParams) mDateTime.getLayoutParams();
if (systemIconsAboveClock) {
@@ -238,6 +248,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
} else {
clockLp.addRule(BELOW, mEmergencyCallsOnly.getId());
}
mDateTime.setLayoutParams(clockLp);
}
private void updateBrightnessControllerState() {
@@ -385,4 +396,11 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
public void setChargingInfo(CharSequence chargingInfo) {
mChargingInfo.setText(chargingInfo);
}
public void setKeyguardUserSwitcherShowing(boolean showing) {
// STOPSHIP: NOT CALLED PROPERLY WHEN GOING TO FULL SHADE AND RETURNING!?!
mKeyguardUserSwitcherShowing = showing;
updateVisibilities();
updateSystemIconsLayoutParams();
}
}

View File

@@ -0,0 +1,215 @@
/*
* 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
*/
package com.android.systemui.statusbar.phone;
import com.android.systemui.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
/**
* A view that displays a user image cropped to a circle with a frame.
*/
public class UserAvatarView extends View {
private int mActiveFrameColor;
private int mFrameColor;
private float mFrameWidth;
private Bitmap mBitmap;
private Drawable mDrawable;
private final Paint mFramePaint = new Paint();
private final Paint mBitmapPaint = new Paint();
private final Matrix mDrawMatrix = new Matrix();
private float mScale = 1;
public UserAvatarView(Context context, AttributeSet attrs,
int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.UserAvatarView, defStyleAttr, defStyleRes);
final int N = a.getIndexCount();
for (int i = 0; i < N; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.UserAvatarView_frameWidth:
setFrameWidth(a.getDimension(attr, 0));
break;
case R.styleable.UserAvatarView_activeFrameColor:
setActiveFrameColor(a.getColor(attr, 0));
break;
case R.styleable.UserAvatarView_frameColor:
setFrameColor(a.getColor(attr, 0));
break;
}
}
a.recycle();
mFramePaint.setAntiAlias(true);
mFramePaint.setStyle(Paint.Style.STROKE);
mBitmapPaint.setAntiAlias(true);
}
public UserAvatarView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public UserAvatarView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public UserAvatarView(Context context) {
this(context, null);
}
public void setBitmap(Bitmap bitmap) {
setDrawable(null);
mBitmap = bitmap;
mBitmapPaint.setShader(new BitmapShader(
bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
configureBounds();
invalidate();
}
public void setFrameColor(int frameColor) {
mFrameColor = frameColor;
invalidate();
}
public void setActiveFrameColor(int activeFrameColor) {
mActiveFrameColor = activeFrameColor;
invalidate();
}
public void setFrameWidth(float frameWidth) {
mFrameWidth = frameWidth;
invalidate();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
configureBounds();
}
public void configureBounds() {
int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
int vheight = getHeight() - mPaddingTop - mPaddingBottom;
int dwidth;
int dheight;
if (mBitmap != null) {
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);
} else {
return;
}
float scale;
float dx;
float dy;
scale = Math.min((float) vwidth / (float) dwidth,
(float) vheight / (float) dheight);
dx = (int) ((vwidth - dwidth * scale) * 0.5f + 0.5f);
dy = (int) ((vheight - dheight * scale) * 0.5f + 0.5f);
mDrawMatrix.setScale(scale, scale);
mDrawMatrix.postTranslate(dx, dy);
mScale = scale;
}
@Override
protected void onDraw(Canvas canvas) {
int frameColor = isActivated() ? mActiveFrameColor : mFrameColor;
float halfW = getWidth() / 2f;
float halfH = getHeight() / 2f;
float halfSW = Math.min(halfH, halfW);
if (mBitmap != null && mScale > 0) {
int saveCount = canvas.getSaveCount();
canvas.save();
canvas.translate(mPaddingLeft, mPaddingTop);
canvas.concat(mDrawMatrix);
float halfBW = mBitmap.getWidth() / 2f;
float halfBH = mBitmap.getHeight() / 2f;
float halfBSW = Math.min(halfBH, halfBW);
canvas.drawCircle(halfBW, halfBH, halfBSW - mFrameWidth / mScale + 1, mBitmapPaint);
canvas.restoreToCount(saveCount);
} else if (mDrawable != null && mScale > 0) {
int saveCount = canvas.getSaveCount();
canvas.save();
canvas.translate(mPaddingLeft, mPaddingTop);
canvas.translate(mFrameWidth - 1, mFrameWidth - 1);
canvas.concat(mDrawMatrix);
mDrawable.draw(canvas);
canvas.restoreToCount(saveCount);
}
if (frameColor != 0) {
mFramePaint.setColor(frameColor);
mFramePaint.setStrokeWidth(mFrameWidth);
canvas.drawCircle(halfW, halfH, halfSW - mFrameWidth / 2f, mFramePaint);
}
}
public void setDrawable(Drawable d) {
if (mDrawable != null) {
mDrawable.setCallback(null);
unscheduleDrawable(mDrawable);
}
mDrawable = d;
if (d != null) {
d.setCallback(this);
if (d.isStateful()) {
d.setState(getDrawableState());
}
d.setLayoutDirection(getLayoutDirection());
configureBounds();
}
if (d != null) {
mBitmap = null;
}
configureBounds();
invalidate();
}
@Override
public void invalidateDrawable(Drawable dr) {
if (dr == mDrawable) {
invalidate();
} else {
super.invalidateDrawable(dr);
}
}
}

View File

@@ -0,0 +1,209 @@
/*
* 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
*/
package com.android.systemui.statusbar.policy;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.StatusBarHeaderView;
import com.android.systemui.statusbar.phone.UserAvatarView;
import android.app.ActivityManagerNative;
import android.content.Context;
import android.content.pm.UserInfo;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.RemoteException;
import android.os.UserManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.WindowManagerGlobal;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* Manages the user switcher on the Keyguard.
*/
public class KeyguardUserSwitcher implements View.OnClickListener {
private static final String TAG = "KeyguardUserSwitcher";
private final Context mContext;
private final ViewGroup mUserSwitcher;
private final UserManager mUserManager;
private final StatusBarHeaderView mHeader;
public KeyguardUserSwitcher(Context context, ViewStub userSwitcher,
StatusBarHeaderView header) {
mContext = context;
if (context.getResources().getBoolean(R.bool.config_keyguardUserSwitcher)) {
mUserSwitcher = (ViewGroup) userSwitcher.inflate();
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mHeader = header;
refresh();
} else {
mUserSwitcher = null;
mUserManager = null;
mHeader = null;
}
}
public void setKeyguard(boolean keyguard) {
if (mUserSwitcher != null) {
// TODO: Cache showUserSwitcherOnKeyguard().
if (keyguard && showUserSwitcherOnKeyguard()) {
show();
refresh();
} else {
hide();
}
}
}
/**
* @return true if the user switcher should be shown on the lock screen.
* @see android.os.UserManager#isUserSwitcherEnabled()
*/
private boolean showUserSwitcherOnKeyguard() {
// TODO: Set isEdu. The edu provisioning process can add settings to Settings.Global.
boolean isEdu = false;
if (isEdu) {
return true;
}
List<UserInfo> users = mUserManager.getUsers(true /* excludeDying */);
int N = users.size();
int switchableUsers = 0;
for (int i = 0; i < N; i++) {
if (users.get(i).supportsSwitchTo()) {
switchableUsers++;
}
}
return switchableUsers > 1;
}
public void show() {
if (mUserSwitcher != null) {
// TODO: animate
mUserSwitcher.setVisibility(View.VISIBLE);
mHeader.setKeyguardUserSwitcherShowing(true);
}
}
private void hide() {
if (mUserSwitcher != null) {
// TODO: animate
mUserSwitcher.setVisibility(View.GONE);
mHeader.setKeyguardUserSwitcherShowing(false);
}
}
private void refresh() {
if (mUserSwitcher != null) {
new AsyncTask<Void, Void, ArrayList<UserData>>() {
@Override
protected ArrayList<UserData> doInBackground(Void... params) {
return loadUsers();
}
@Override
protected void onPostExecute(ArrayList<UserData> userInfos) {
bind(userInfos);
}
}.execute((Void[]) null);
}
}
private void bind(ArrayList<UserData> userList) {
mUserSwitcher.removeAllViews();
int N = userList.size();
for (int i = 0; i < N; i++) {
mUserSwitcher.addView(inflateUser(userList.get(i)));
}
// TODO: add Guest
// TODO: add (+) button
}
private View inflateUser(UserData user) {
View v = LayoutInflater.from(mUserSwitcher.getContext()).inflate(
R.layout.keyguard_user_switcher_item, mUserSwitcher, false);
TextView name = (TextView) v.findViewById(R.id.name);
UserAvatarView picture = (UserAvatarView) v.findViewById(R.id.picture);
name.setText(user.userInfo.name);
picture.setActivated(user.isCurrent);
if (user.userInfo.isGuest()) {
picture.setDrawable(mContext.getResources().getDrawable(R.drawable.ic_account_circle));
} else {
picture.setBitmap(user.userIcon);
}
v.setOnClickListener(this);
v.setTag(user.userInfo);
// TODO: mark which user is current for accessibility.
return v;
}
@Override
public void onClick(View v) {
switchUser(((UserInfo)v.getTag()).id);
}
// TODO: Factor out logic below and share with QS implementation.
private ArrayList<UserData> loadUsers() {
ArrayList<UserInfo> users = (ArrayList<UserInfo>) mUserManager
.getUsers(true /* excludeDying */);
int N = users.size();
ArrayList<UserData> result = new ArrayList<>(N);
int currentUser = -1;
try {
currentUser = ActivityManagerNative.getDefault().getCurrentUser().id;
} catch (RemoteException e) {
Log.e(TAG, "Couln't get current user.", e);
}
for (int i = 0; i < N; i++) {
UserInfo user = users.get(i);
if (user.supportsSwitchTo()) {
boolean isCurrent = user.id == currentUser;
result.add(new UserData(user, mUserManager.getUserIcon(user.id), isCurrent));
}
}
return result;
}
private void switchUser(int userId) {
try {
WindowManagerGlobal.getWindowManagerService().lockNow(null);
ActivityManagerNative.getDefault().switchUser(userId);
} catch (RemoteException e) {
Log.e(TAG, "Couldn't switch user.", e);
}
}
private static class UserData {
final UserInfo userInfo;
final Bitmap userIcon;
final boolean isCurrent;
UserData(UserInfo userInfo, Bitmap userIcon, boolean isCurrent) {
this.userInfo = userInfo;
this.userIcon = userIcon;
this.isCurrent = isCurrent;
}
}
}