Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 723632ea authored by Adrian Roos's avatar Adrian Roos
Browse files

Update KeyguardUserSwitcher to use UserSwitcherController

Also wires up the button to expand the keyguard user switcher.
Also respects the EDU simple switcher setting.

Bug: 16043126
Change-Id: I58871ec3323b2cafcacbc747fec5f20c56172969
parent baa23274
Loading
Loading
Loading
Loading
+19 −3
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ import android.view.View;
import android.widget.FrameLayout;

import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.tiles.UserDetailView;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;

/**
 * Container for image of the multi user switcher (tappable).
@@ -34,6 +34,8 @@ import com.android.systemui.qs.tiles.UserDetailView;
public class MultiUserSwitch extends FrameLayout implements View.OnClickListener {

    private QSPanel mQsPanel;
    private KeyguardUserSwitcher mKeyguardUserSwitcher;
    private boolean mKeyguardMode;

    public MultiUserSwitch(Context context, AttributeSet attrs) {
        super(context, attrs);
@@ -49,12 +51,26 @@ public class MultiUserSwitch extends FrameLayout implements View.OnClickListener
        mQsPanel = qsPanel;
    }

    public void setKeyguardUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) {
        mKeyguardUserSwitcher = keyguardUserSwitcher;
    }

    public void setKeyguardMode(boolean keyguardShowing) {
        mKeyguardMode = keyguardShowing;
    }

    @Override
    public void onClick(View v) {
        final UserManager um = UserManager.get(getContext());
        if (um.isUserSwitcherEnabled()) {
            if (mKeyguardMode) {
                if (mKeyguardUserSwitcher != null) {
                    mKeyguardUserSwitcher.show();
                }
            } else {
                mQsPanel.showDetailAdapter(true,
                        mQsPanel.getHost().getUserSwitcherController().userDetailAdapter);
            }
        } else {
            Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
                    getContext(), v, ContactsContract.Profile.CONTENT_URI,
+5 −3
Original line number Diff line number Diff line
@@ -737,9 +737,6 @@ 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);
        final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
@@ -775,6 +772,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        mUserSwitcherController = new UserSwitcherController(mContext);
        mKeyguardMonitor = new KeyguardMonitor();

        mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext,
                (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher), mHeader,
                mUserSwitcherController);


        // Set up the quick settings tile panel
        mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
        if (mQSPanel != null) {
+12 −2
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.systemui.R;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.UserInfoController;

/**
@@ -97,6 +98,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
    private ActivityStarter mActivityStarter;
    private BatteryController mBatteryController;
    private QSPanel mQSPanel;
    private boolean mHasKeyguardUserSwitcher;

    private final Rect mClipBounds = new Rect();
    private final StatusIconClipper mStatusIconClipper = new StatusIconClipper();
@@ -373,7 +375,11 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
    private void updateClickTargets() {
        setClickable(!mKeyguardShowing || mExpanded);
        mDateTime.setClickable(mExpanded);
        mMultiUserSwitch.setClickable(mExpanded);

        boolean keyguardSwitcherAvailable =
                mHasKeyguardUserSwitcher && mKeyguardShowing && !mExpanded;
        mMultiUserSwitch.setClickable(mExpanded || keyguardSwitcherAvailable);
        mMultiUserSwitch.setKeyguardMode(keyguardSwitcherAvailable);
        mSystemIconsSuperContainer.setClickable(mExpanded);
    }

@@ -509,6 +515,11 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
        mMultiUserSwitch.setQsPanel(qsp);
    }

    public void setKeyguarUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) {
        mHasKeyguardUserSwitcher = true;
        mMultiUserSwitch.setKeyguardUserSwitcher(keyguardUserSwitcher);
    }

    @Override
    public boolean shouldDelayChildPressedState() {
        return true;
@@ -522,7 +533,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
    }

    public void setKeyguardUserSwitcherShowing(boolean showing) {
        // STOPSHIP: NOT CALLED PROPERLY WHEN GOING TO FULL SHADE AND RETURNING!?!
        mKeyguardUserSwitcherShowing = showing;
        updateVisibilities();
        updateSystemIconsLayoutParams();
+77 −120
Original line number Diff line number Diff line
@@ -16,62 +16,56 @@

package com.android.systemui.statusbar.policy;

import com.android.systemui.BitmapHelper;
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.database.DataSetObserver;
import android.provider.Settings;
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 {
public class KeyguardUserSwitcher {

    private static final String TAG = "KeyguardUserSwitcher";
    private static final boolean ALWAYS_ON = false;
    private static final String SIMPLE_USER_SWITCHER_GLOBAL_SETTING =
            "lockscreenSimpleUserSwitcher";

    private final Context mContext;
    private final ViewGroup mUserSwitcher;
    private final UserManager mUserManager;
    private final StatusBarHeaderView mHeader;
    private final Adapter mAdapter;
    private final boolean mSimpleUserSwitcher;

    public KeyguardUserSwitcher(Context context, ViewStub userSwitcher,
            StatusBarHeaderView header) {
        mContext = context;
        if (context.getResources().getBoolean(R.bool.config_keyguardUserSwitcher)) {
            StatusBarHeaderView header, UserSwitcherController userSwitcherController) {
        if (context.getResources().getBoolean(R.bool.config_keyguardUserSwitcher) || ALWAYS_ON) {
            mUserSwitcher = (ViewGroup) userSwitcher.inflate();
            mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
            mHeader = header;
            refresh();
            mHeader.setKeyguarUserSwitcher(this);
            mAdapter = new Adapter(context, userSwitcherController);
            mAdapter.registerDataSetObserver(mDataSetObserver);
            mSimpleUserSwitcher = Settings.Global.getInt(context.getContentResolver(),
                    SIMPLE_USER_SWITCHER_GLOBAL_SETTING, 0) != 0;
        } else {
            mUserSwitcher = null;
            mUserManager = null;
            mHeader = null;
            mAdapter = null;
            mSimpleUserSwitcher = false;
        }
    }

    public void setKeyguard(boolean keyguard) {
        if (mUserSwitcher != null) {
            // TODO: Cache showUserSwitcherOnKeyguard().
            if (keyguard && showUserSwitcherOnKeyguard()) {
            if (keyguard && shouldExpandByDefault()) {
                show();
                refresh();
            } else {
                hide();
            }
@@ -79,24 +73,11 @@ public class KeyguardUserSwitcher implements View.OnClickListener {
    }

    /**
     * @return true if the user switcher should be shown on the lock screen.
     * @return true if the user switcher should be expanded by default 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;
    private boolean shouldExpandByDefault() {
        return mSimpleUserSwitcher || mAdapter.getSwitchableUsers() > 1;
    }

    public void show() {
@@ -116,100 +97,76 @@ public class KeyguardUserSwitcher implements View.OnClickListener {
    }

    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();
        final int childCount = mUserSwitcher.getChildCount();
        final int adapterCount = mAdapter.getCount();
        final int N = Math.max(childCount, adapterCount);
        for (int i = 0; i < N; i++) {
            mUserSwitcher.addView(inflateUser(userList.get(i)));
        }
        // TODO: add Guest
        // TODO: add (+) button
            if (i < adapterCount) {
                View oldView = null;
                if (i < childCount) {
                    oldView = mUserSwitcher.getChildAt(i);
                }
                View newView = mAdapter.getView(i, oldView, mUserSwitcher);
                if (oldView == null) {
                    // We ran out of existing views. Add it at the end.
                    mUserSwitcher.addView(newView);
                } else if (oldView != newView) {
                    // We couldn't rebind the view. Replace it.
                    mUserSwitcher.removeViewAt(i);
                    mUserSwitcher.addView(newView, i);
                }

    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);
                int lastIndex = mUserSwitcher.getChildCount() - 1;
                mUserSwitcher.removeViewAt(lastIndex);
            }
        }
        v.setOnClickListener(this);
        v.setTag(user.userInfo);
        // TODO: mark which user is current for accessibility.
        return v;
    }

    public final DataSetObserver mDataSetObserver = new DataSetObserver() {
        @Override
    public void onClick(View v) {
        switchUser(((UserInfo)v.getTag()).id);
        public void onChanged() {
            refresh();
        }
    };

    // TODO: Factor out logic below and share with QS implementation.
    public static class Adapter extends UserSwitcherController.BaseUserAdapter implements
            View.OnClickListener {

    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);
        }
        final int avatarSize
                = mContext.getResources().getDimensionPixelSize(R.dimen.max_avatar_size);
        for (int i = 0; i < N; i++) {
            UserInfo user = users.get(i);
            if (user.supportsSwitchTo()) {
                boolean isCurrent = user.id == currentUser;
                final Bitmap picture = BitmapHelper.createCircularClip(
                        mUserManager.getUserIcon(user.id),
                        avatarSize, avatarSize);
                result.add(new UserData(user, picture, isCurrent));
            }
        private Context mContext;

        public Adapter(Context context, UserSwitcherController controller) {
            super(controller);
            mContext = context;
        }
        return result;

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            UserSwitcherController.UserRecord item = getItem(position);

            if (convertView == null
                    || !(convertView.getTag() instanceof UserSwitcherController.UserRecord)) {
                convertView = LayoutInflater.from(mContext).inflate(
                        R.layout.keyguard_user_switcher_item, parent, false);
                convertView.setOnClickListener(this);
            }

    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);
            TextView nameView = (TextView) convertView.findViewById(R.id.name);
            UserAvatarView pictureView = (UserAvatarView) convertView.findViewById(R.id.picture);

            nameView.setText(getName(mContext, item));
            if (item.picture == null) {
                pictureView.setDrawable(mContext.getDrawable(R.drawable.ic_account_circle_qs));
            } else {
                pictureView.setBitmap(item.picture);
            }
            convertView.setActivated(item.isCurrent);
            convertView.setTag(item);
            return convertView;
        }

    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;
        @Override
        public void onClick(View v) {
            switchTo(((UserSwitcherController.UserRecord)v.getTag()));
        }
    }
}
+13 −1
Original line number Diff line number Diff line
@@ -123,7 +123,7 @@ public class UserSwitcherController {
                    if (info.isGuest()) {
                        guestRecord = new UserRecord(info, null /* picture */,
                                true /* isGuest */, isCurrent);
                    } else if (!info.isManagedProfile()) {
                    } else if (info.supportsSwitchTo()) {
                        Bitmap picture = bitmaps.get(info.id);
                        if (picture == null) {
                            picture = mUserManager.getUserIcon(info.id);
@@ -303,6 +303,18 @@ public class UserSwitcherController {
                return item.info.name;
            }
        }

        public int getSwitchableUsers() {
            int result = 0;
            ArrayList<UserRecord> users = mController.mUsers;
            int N = users.size();
            for (int i = 0; i < N; i++) {
                if (users.get(i).info != null) {
                    result++;
                }
            }
            return result;
        }
    }

    public static final class UserRecord {