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

Commit 6e0f14e7 authored by Adrian Roos's avatar Adrian Roos Committed by Android (Google) Code Review
Browse files

Merge "Add a temporary user switcher to quick settings" into master-lockscreen-dev

parents cf1b3b47 5a46cd37
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
<?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
  -->

<!-- FrameLayout -->
<com.android.systemui.settings.UserSwitcherHostView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#dd000000">
    <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@*android:dimen/volume_panel_top"
            android:background="@*android:drawable/dialog_full_holo_dark">
        <ListView android:id="@android:id/list"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                tools:listitem="@layout/user_switcher_item"/>
    </FrameLayout>
</com.android.systemui.settings.UserSwitcherHostView>
 No newline at end of file
+40 −0
Original line number Diff line number Diff line
<?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:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="64dp"
        android:orientation="horizontal"
        tools:context=".settings.UserSwitcherDialog">
    <ImageView
            android:layout_width="64dp"
            android:layout_height="match_parent"
            android:id="@+id/user_picture"
            tools:src="@drawable/dessert_zombiegingerbread"/>
    <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:id="@+id/user_name"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:padding="8dp"
            android:gravity="center_vertical"
            tools:text="Hiroshi Lockheimer"
            />
</LinearLayout>
+172 −0
Original line number Diff line number Diff line
/*
 * 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.settings;

import com.android.systemui.R;

import android.app.ActivityManagerNative;
import android.content.Context;
import android.content.pm.UserInfo;
import android.os.RemoteException;
import android.os.UserManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManagerGlobal;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;

/**
 * A quick and dirty view to show a user switcher.
 */
public class UserSwitcherHostView extends FrameLayout implements ListView.OnItemClickListener {

    private static final String TAG = "UserSwitcherDialog";

    private ArrayList<UserInfo> mUserInfo = new ArrayList<UserInfo>();
    private Adapter mAdapter = new Adapter();
    private UserManager mUserManager;
    private Runnable mFinishRunnable;
    private ListView mListView;

    public UserSwitcherHostView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        if (isInEditMode()) {
            return;
        }
        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
    }

    public UserSwitcherHostView(Context context, AttributeSet attrs) {
        this(context, attrs, com.android.internal.R.attr.listViewStyle);
    }

    public UserSwitcherHostView(Context context) {
        this(context, null);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mListView = (ListView) findViewById(android.R.id.list);
        mListView.setAdapter(mAdapter);
        mListView.setOnItemClickListener(this);
    }

    @Override
    public void onItemClick(AdapterView<?> l, View v, int position, long id) {
        int userId = mAdapter.getItem(position).id;
        try {
            WindowManagerGlobal.getWindowManagerService().lockNow(null);
            ActivityManagerNative.getDefault().switchUser(userId);
            finish();
        } catch (RemoteException e) {
            Log.e(TAG, "Couldn't switch user.", e);
        }
    }

    private void finish() {
        if (mFinishRunnable != null) {
            mFinishRunnable.run();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            finish();
        }
        return true;
    }

    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        // A gross hack to get rid of the switcher when the shade is collapsed.
        if (visibility != VISIBLE) {
            finish();
        }
    }

    public void setFinishRunnable(Runnable finishRunnable) {
        mFinishRunnable = finishRunnable;
    }

    public void refreshUsers() {
        mUserInfo.clear();
        mUserInfo.addAll(mUserManager.getUsers(true));
        mAdapter.notifyDataSetChanged();
    }

    private class Adapter extends BaseAdapter {

        @Override
        public int getCount() {
            return mUserInfo.size();
        }

        @Override
        public UserInfo getItem(int position) {
            return mUserInfo.get(position);
        }

        @Override
        public long getItemId(int position) {
            return getItem(position).serialNumber;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null || (!(convertView.getTag() instanceof ViewHolder))) {
                convertView = createView(parent);
            }
            ViewHolder h = (ViewHolder) convertView.getTag();
            bindView(h, getItem(position));
            return convertView;
        }

        private View createView(ViewGroup parent) {
            View v = LayoutInflater.from(getContext()).inflate(
                    R.layout.user_switcher_item, parent, false);
            ViewHolder h = new ViewHolder();
            h.name = (TextView) v.findViewById(R.id.user_name);
            h.picture = (ImageView) v.findViewById(R.id.user_picture);
            v.setTag(h);
            return v;
        }

        private void bindView(ViewHolder h, UserInfo item) {
            h.name.setText(item.name);
            h.picture.setImageBitmap(mUserManager.getUserIcon(item.id));
        }

        class ViewHolder {
            TextView name;
            ImageView picture;
        }
    }
}
+15 −0
Original line number Diff line number Diff line
@@ -2825,4 +2825,19 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
        mExpandedVisible = true;
        mNotificationPanel.setExpandedFraction(1);
    }

    /**
     * @return a ViewGroup that spans the entire panel which contains the quick settings
     */
    public ViewGroup getQuickSettingsOverlayParent() {
        if (mHasSettingsPanel) {
            if (mHasFlipSettings) {
                return mNotificationPanel;
            } else {
                return mSettingsPanel;
            }
        } else {
            return null;
        }
    }
}
+12 −13
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ import android.widget.TextView;

import com.android.internal.app.MediaRouteDialogPresenter;
import com.android.systemui.R;
import com.android.systemui.settings.UserSwitcherHostView;
import com.android.systemui.statusbar.phone.QuickSettingsModel.ActivityState;
import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState;
import com.android.systemui.statusbar.phone.QuickSettingsModel.RSSIState;
@@ -310,30 +311,28 @@ class QuickSettings {
        collapsePanels();
    }

    private void addUserTiles(ViewGroup parent, LayoutInflater inflater) {
    private void addUserTiles(final ViewGroup parent, final LayoutInflater inflater) {
        QuickSettingsTileView userTile = (QuickSettingsTileView)
                inflater.inflate(R.layout.quick_settings_tile, parent, false);
        userTile.setContent(R.layout.quick_settings_tile_user, inflater);
        userTile.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                collapsePanels();
                final UserManager um = UserManager.get(mContext);
                if (um.isUserSwitcherEnabled()) {
                    // Since keyguard and systemui were merged into the same process to save
                    // memory, they share the same Looper and graphics context.  As a result,
                    // there's no way to allow concurrent animation while keyguard inflates.
                    // The workaround is to add a slight delay to allow the animation to finish.
                    mHandler.postDelayed(new Runnable() {
                    final ViewGroup switcherParent = getService().getQuickSettingsOverlayParent();
                    final UserSwitcherHostView switcher = (UserSwitcherHostView) inflater.inflate(
                            R.layout.user_switcher_host, switcherParent, false);
                    switcher.setFinishRunnable(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                WindowManagerGlobal.getWindowManagerService().lockNow(null);
                            } catch (RemoteException e) {
                                Log.e(TAG, "Couldn't show user switcher", e);
                            }
                            switcherParent.removeView(switcher);
                        }
                    }, 400); // TODO: ideally this would be tied to the collapse of the panel
                    });
                    switcher.refreshUsers();
                    switcherParent.addView(switcher);
                } else {
                    collapsePanels();
                    Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
                            mContext, v, ContactsContract.Profile.CONTENT_URI,
                            ContactsContract.QuickContact.MODE_LARGE, null);