UI modifications for user picker
Test: tested on Mojave
bug: 75023449

Change-Id: Ia991ca9ed9424d0008ca2328f28c0900e8d5653a
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
index 23d3ebbb..24b5a34 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
@@ -29,7 +29,6 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.qs.QSFooter;
 import com.android.systemui.qs.QSPanel;
-import com.android.systemui.statusbar.car.UserGridView;
 import com.android.systemui.statusbar.phone.MultiUserSwitch;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.UserInfoController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
index 0ee6d1f..da21aa5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
@@ -20,21 +20,20 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.app.Fragment;
+import android.content.Context;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
+import android.support.v7.widget.GridLayoutManager;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.qs.QSFooter;
-import com.android.systemui.statusbar.car.PageIndicator;
-import com.android.systemui.statusbar.car.UserGridView;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.car.UserGridRecyclerView;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -45,14 +44,12 @@
  * status bar, and a static row with access to the user switcher and settings.
  */
 public class CarQSFragment extends Fragment implements QS {
-    private ViewGroup mPanel;
     private View mHeader;
     private View mUserSwitcherContainer;
     private CarQSFooter mFooter;
     private View mFooterUserName;
     private View mFooterExpandIcon;
-    private UserGridView mUserGridView;
-    private PageIndicator mPageIndicator;
+    private UserGridRecyclerView mUserGridView;
     private AnimatorSet mAnimatorSet;
     private UserSwitchCallback mUserSwitchCallback;
 
@@ -65,7 +62,6 @@
     @Override
     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
-        mPanel = (ViewGroup) view;
         mHeader = view.findViewById(R.id.header);
         mFooter = view.findViewById(R.id.qs_footer);
         mFooterUserName = mFooter.findViewById(R.id.user_name);
@@ -75,16 +71,15 @@
 
         updateUserSwitcherHeight(0);
 
-        mUserGridView = view.findViewById(R.id.user_grid);
-        mUserGridView.init(null, Dependency.get(UserSwitcherController.class),
-                false /* overrideAlpha */);
-
-        mPageIndicator = view.findViewById(R.id.user_switcher_page_indicator);
-        mPageIndicator.setupWithViewPager(mUserGridView);
+        Context context = getContext();
+        mUserGridView = mUserSwitcherContainer.findViewById(R.id.user_grid);
+        GridLayoutManager layoutManager = new GridLayoutManager(context,
+                context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col));
+        mUserGridView.setLayoutManager(layoutManager);
+        mUserGridView.buildAdapter();
 
         mUserSwitchCallback = new UserSwitchCallback();
         mFooter.setUserSwitchCallback(mUserSwitchCallback);
-        mUserGridView.setUserSwitchCallback(mUserSwitchCallback);
     }
 
     @Override
@@ -111,13 +106,11 @@
     @Override
     public void setHeaderListening(boolean listening) {
         mFooter.setListening(listening);
-        mUserGridView.setListening(listening);
     }
 
     @Override
     public void setListening(boolean listening) {
         mFooter.setListening(listening);
-        mUserGridView.setListening(listening);
     }
 
     @Override
@@ -219,24 +212,6 @@
             mShowing = false;
             animateHeightChange(false /* opening */);
         }
-
-        public void resetShowing() {
-            if (mShowing) {
-                for (int i = 0; i < mUserGridView.getChildCount(); i++) {
-                    ViewGroup podContainer = (ViewGroup) mUserGridView.getChildAt(i);
-                    // Need to bring the last child to the front to maintain the order in the pod
-                    // container. Why? ¯\_(ツ)_/¯
-                    if (podContainer.getChildCount() > 0) {
-                        podContainer.getChildAt(podContainer.getChildCount() - 1).bringToFront();
-                    }
-                    // The alpha values are default to 0, so if the pods have been refreshed, they
-                    // need to be set to 1 when showing.
-                    for (int j = 0; j < podContainer.getChildCount(); j++) {
-                        podContainer.getChildAt(j).setAlpha(1f);
-                    }
-                }
-            }
-        }
     }
 
     private void updateUserSwitcherHeight(int height) {
@@ -260,27 +235,6 @@
         });
         allAnimators.add(heightAnimator);
 
-        // The user grid contains pod containers that each contain a number of pods.  Animate
-        // all pods to avoid any discrepancy/race conditions with possible changes during the
-        // animation.
-        int cascadeDelay = getResources().getInteger(
-                R.integer.car_user_switcher_anim_cascade_delay_ms);
-        for (int i = 0; i < mUserGridView.getChildCount(); i++) {
-            ViewGroup podContainer = (ViewGroup) mUserGridView.getChildAt(i);
-            for (int j = 0; j < podContainer.getChildCount(); j++) {
-                View pod = podContainer.getChildAt(j);
-                Animator podAnimator = AnimatorInflater.loadAnimator(getContext(),
-                        opening ? R.anim.car_user_switcher_open_pod_animation
-                                : R.anim.car_user_switcher_close_pod_animation);
-                // Add the cascading delay between pods
-                if (opening) {
-                    podAnimator.setStartDelay(podAnimator.getStartDelay() + j * cascadeDelay);
-                }
-                podAnimator.setTarget(pod);
-                allAnimators.add(podAnimator);
-            }
-        }
-
         Animator nameAnimator = AnimatorInflater.loadAnimator(getContext(),
                 opening ? R.anim.car_user_switcher_open_name_animation
                         : R.anim.car_user_switcher_close_name_animation);
@@ -293,12 +247,6 @@
         iconAnimator.setTarget(mFooterExpandIcon);
         allAnimators.add(iconAnimator);
 
-        Animator pageAnimator = AnimatorInflater.loadAnimator(getContext(),
-                opening ? R.anim.car_user_switcher_open_pages_animation
-                        : R.anim.car_user_switcher_close_pages_animation);
-        pageAnimator.setTarget(mPageIndicator);
-        allAnimators.add(pageAnimator);
-
         mAnimatorSet = new AnimatorSet();
         mAnimatorSet.addListener(new AnimatorListenerAdapter() {
             @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 3fb1137..008794c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -418,8 +418,7 @@
                 Dependency.get(UserSwitcherController.class);
         if (userSwitcherController.useFullscreenUserSwitcher()) {
             mFullscreenUserSwitcher = new FullscreenUserSwitcher(this,
-                    userSwitcherController,
-                    mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub));
+                    mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub), mContext);
         } else {
             super.createUserSwitcher();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index bc353f2..fb525f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -18,14 +18,15 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.content.res.Resources;
+import android.content.Context;
 import android.view.View;
 import android.view.ViewStub;
 import android.widget.ProgressBar;
 
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
 
 /**
  * Manages the fullscreen user switcher.
@@ -33,36 +34,25 @@
 public class FullscreenUserSwitcher {
     private final View mContainer;
     private final View mParent;
-    private final UserGridView mUserGridView;
-    private final UserSwitcherController mUserSwitcherController;
+    private final UserGridRecyclerView mUserGridView;
     private final ProgressBar mSwitchingUsers;
     private final int mShortAnimDuration;
 
     private boolean mShowing;
 
-    public FullscreenUserSwitcher(StatusBar statusBar,
-            UserSwitcherController userSwitcherController,
-            ViewStub containerStub) {
-        mUserSwitcherController = userSwitcherController;
+    public FullscreenUserSwitcher(StatusBar statusBar, ViewStub containerStub, Context context) {
         mParent = containerStub.inflate();
         mContainer = mParent.findViewById(R.id.container);
         mUserGridView = mContainer.findViewById(R.id.user_grid);
-        mUserGridView.init(statusBar, mUserSwitcherController, true /* overrideAlpha */);
-        mUserGridView.setUserSelectionListener(record -> {
-            if (!record.isCurrent) {
-                toggleSwitchInProgress(true);
-            }
-        });
+        mUserGridView.setStatusBar(statusBar);
+        GridLayoutManager layoutManager = new GridLayoutManager(context,
+                context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col));
+        mUserGridView.setLayoutManager(layoutManager);
+        mUserGridView.buildAdapter();
+        mUserGridView.setUserSelectionListener(record -> toggleSwitchInProgress(true));
 
-        PageIndicator pageIndicator = mContainer.findViewById(R.id.user_switcher_page_indicator);
-        pageIndicator.setupWithViewPager(mUserGridView);
-
-        Resources res = mContainer.getResources();
-        mShortAnimDuration = res.getInteger(android.R.integer.config_shortAnimTime);
-
-        mContainer.findViewById(R.id.start_driving).setOnClickListener(v -> {
-            automaticallySelectUser();
-        });
+        mShortAnimDuration = mContainer.getResources()
+            .getInteger(android.R.integer.config_shortAnimTime);
 
         mSwitchingUsers = mParent.findViewById(R.id.switching_users);
     }
@@ -115,10 +105,4 @@
         toggleSwitchInProgress(false);
         mParent.setVisibility(View.GONE);
     }
-
-    private void automaticallySelectUser() {
-        // TODO: Switch according to some policy. This implementation just tries to drop the
-        //       keyguard for the current user.
-        mUserGridView.showOfflineAuthUi();
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
new file mode 100644
index 0000000..e09a360
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2018 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.car;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.drawable.GradientDrawable;
+import android.os.AsyncTask;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.settingslib.users.UserManagerHelper;
+import com.android.systemui.R;
+import com.android.systemui.qs.car.CarQSFragment;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Displays a GridLayout with icons for the users in the system to allow switching between users.
+ * One of the uses of this is for the lock screen in auto.
+ */
+public class UserGridRecyclerView extends RecyclerView implements
+        UserManagerHelper.OnUsersUpdateListener {
+
+    private StatusBar mStatusBar;
+    private UserSelectionListener mUserSelectionListener;
+    private UserAdapter mAdapter;
+    private UserManagerHelper mUserManagerHelper;
+    private Context mContext;
+
+    public UserGridRecyclerView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        super.setHasFixedSize(true);
+        mContext = context;
+        mUserManagerHelper = new UserManagerHelper(mContext);
+    }
+
+    /**
+     * Register listener for any update to the users
+     */
+    @Override
+    public void onFinishInflate() {
+        mUserManagerHelper.registerOnUsersUpdateListener(this);
+    }
+
+    /**
+     * Unregisters listener checking for any change to the users
+     */
+    @Override
+    public void onDetachedFromWindow() {
+        mUserManagerHelper.unregisterOnUsersUpdateListener();
+    }
+
+    /**
+     * Initializes the adapter that populates the grid layout
+     *
+     * @return the adapter
+     */
+    public void buildAdapter() {
+        List<UserRecord> userRecords = createUserRecords(mUserManagerHelper
+                .getAllUsers());
+        mAdapter = new UserAdapter(mContext, userRecords);
+        super.setAdapter(mAdapter);
+    }
+
+    public void setStatusBar(@Nullable StatusBar statusBar) {
+        mStatusBar = statusBar;
+    }
+
+    private List<UserRecord> createUserRecords(List<UserInfo> userInfoList) {
+        List<UserRecord> userRecords = new ArrayList<>();
+        for (UserInfo userInfo : userInfoList) {
+            boolean isCurrent = false;
+            if (ActivityManager.getCurrentUser() == userInfo.id) {
+                isCurrent = true;
+            }
+            UserRecord record = new UserRecord(userInfo, false /* isGuest */,
+                    false /* isAddUser */, isCurrent);
+            userRecords.add(record);
+        }
+
+        // Add guest user record if the current user is not a guest
+        if (!mUserManagerHelper.isGuestUser()) {
+            userRecords.add(addGuestUserRecord());
+        }
+
+        // Add add user record if the current user can add users
+        if (mUserManagerHelper.canAddUsers()) {
+            userRecords.add(addUserRecord());
+        }
+
+        return userRecords;
+    }
+
+    /**
+     * Create guest user record
+     */
+    private UserRecord addGuestUserRecord() {
+        UserInfo userInfo = new UserInfo();
+        userInfo.name = mContext.getString(R.string.car_guest);
+        return new UserRecord(userInfo, true /* isGuest */,
+                false /* isAddUser */, false /* isCurrent */);
+    }
+
+    /**
+     * Create add user record
+     */
+    private UserRecord addUserRecord() {
+        UserInfo userInfo = new UserInfo();
+        userInfo.name = mContext.getString(R.string.car_add_user);
+        return new UserRecord(userInfo, false /* isGuest */,
+                true /* isAddUser */, false /* isCurrent */);
+    }
+
+    public void onUserSwitched(int newUserId) {
+        // Bring up security view after user switch is completed.
+        post(this::showOfflineAuthUi);
+    }
+
+    public void setUserSelectionListener(UserSelectionListener userSelectionListener) {
+        mUserSelectionListener = userSelectionListener;
+    }
+
+    void showOfflineAuthUi() {
+        // TODO: Show keyguard UI in-place.
+        if (mStatusBar != null) {
+            mStatusBar.executeRunnableDismissingKeyguard(null/* runnable */, null /* cancelAction */,
+                    true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */);
+        }
+    }
+
+    @Override
+    public void onUsersUpdate() {
+        mAdapter.clearUsers();
+        mAdapter.updateUsers(createUserRecords(mUserManagerHelper.getAllUsers()));
+        mAdapter.notifyDataSetChanged();
+    }
+
+    /**
+     * Adapter to populate the grid layout with the available user profiles
+     */
+    public final class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserAdapterViewHolder> {
+
+        private final Context mContext;
+        private List<UserRecord> mUsers;
+        private final int mPodImageAvatarWidth;
+        private final int mPodImageAvatarHeight;
+        private final Resources mRes;
+        private final String mGuestName;
+        private final String mNewUserName;
+
+        public UserAdapter(Context context, List<UserRecord> users) {
+            mRes = context.getResources();
+            mContext = context;
+            updateUsers(users);
+            mPodImageAvatarWidth = mRes.getDimensionPixelSize(
+                    R.dimen.car_fullscreen_user_pod_image_avatar_width);
+            mPodImageAvatarHeight = mRes.getDimensionPixelSize(
+                    R.dimen.car_fullscreen_user_pod_image_avatar_height);
+            mGuestName = mRes.getString(R.string.car_guest);
+            mNewUserName = mRes.getString(R.string.car_new_user);
+        }
+
+        public void clearUsers() {
+            mUsers.clear();
+        }
+
+        public void updateUsers(List<UserRecord> users) {
+            mUsers = users;
+        }
+
+        @Override
+        public UserAdapterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+            View view = LayoutInflater.from(mContext)
+                    .inflate(R.layout.car_fullscreen_user_pod, parent, false);
+            view.setAlpha(1f);
+            view.bringToFront();
+            return new UserAdapterViewHolder(view);
+        }
+
+        @Override
+        public void onBindViewHolder(UserAdapterViewHolder holder, int position) {
+            UserRecord userRecord = mUsers.get(position);
+            holder.mUserAvatarImageView.setImageBitmap(getDefaultUserIcon(userRecord));
+            holder.mUserNameTextView.setText(userRecord.mInfo.name);
+            holder.mView.setOnClickListener(v -> {
+                if (userRecord == null) {
+                    return;
+                }
+
+                // Notify the listener which user was selected
+                if (mUserSelectionListener != null) {
+                    mUserSelectionListener.onUserSelected(userRecord);
+                }
+
+                // If the user selects Guest, switch to Guest profile
+                if (userRecord.mIsGuest) {
+                    mUserManagerHelper.switchToGuest(mGuestName);
+                    return;
+                }
+
+                // If the user wants to add a user, start task to add new user
+                if (userRecord.mIsAddUser) {
+                    new AddNewUserTask().execute(mNewUserName);
+                    return;
+                }
+
+                // If the user doesn't want to be a guest or add a user, switch to the user selected
+                mUserManagerHelper.switchToUser(userRecord.mInfo);
+            });
+
+        }
+
+        private class AddNewUserTask extends AsyncTask<String, Void, UserInfo> {
+
+            @Override
+            protected UserInfo doInBackground(String... userNames) {
+                return mUserManagerHelper.createNewUser(userNames[0]);
+            }
+
+            @Override
+            protected void onPreExecute() {
+            }
+
+            @Override
+            protected void onPostExecute(UserInfo user) {
+                if (user != null) {
+                    mUserManagerHelper.switchToUser(user);
+                }
+            }
+        }
+
+        @Override
+        public int getItemCount() {
+            return mUsers.size();
+        }
+
+        /**
+         * Returns the default user icon.  This icon is a circle with a letter in it.  The letter is
+         * the first character in the username.
+         *
+         * @param record the profile of the user for which the icon should be created
+         */
+        private Bitmap getDefaultUserIcon(UserRecord record) {
+            CharSequence displayText;
+            boolean isAddUserText = false;
+            if (record.mIsAddUser) {
+                displayText = "+";
+                isAddUserText = true;
+            } else {
+                displayText = record.mInfo.name.subSequence(0, 1);
+            }
+            Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight,
+                    Bitmap.Config.ARGB_8888);
+            Canvas canvas = new Canvas(out);
+
+            // Draw the circle background.
+            GradientDrawable shape = new GradientDrawable();
+            shape.setShape(GradientDrawable.RADIAL_GRADIENT);
+            shape.setGradientRadius(1.0f);
+            shape.setColor(mContext.getColor(R.color.car_user_switcher_no_user_image_bgcolor));
+            shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
+            shape.draw(canvas);
+
+            // Draw the letter in the center.
+            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            paint.setColor(mContext.getColor(R.color.car_user_switcher_no_user_image_fgcolor));
+            paint.setTextAlign(Align.CENTER);
+            if (isAddUserText) {
+                paint.setTextSize(mRes.getDimensionPixelSize(
+                        R.dimen.car_touch_target_size));
+            } else {
+                paint.setTextSize(mRes.getDimensionPixelSize(
+                        R.dimen.car_fullscreen_user_pod_icon_text_size));
+            }
+
+            Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
+            // The Y coordinate is measured by taking half the height of the pod, but that would
+            // draw the character putting the bottom of the font in the middle of the pod.  To
+            // correct this, half the difference between the top and bottom distance metrics of the
+            // font gives the offset of the font.  Bottom is a positive value, top is negative, so
+            // the different is actually a sum.  The "half" operation is then factored out.
+            canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2,
+                    (mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint);
+
+            return out;
+        }
+
+        public class UserAdapterViewHolder extends RecyclerView.ViewHolder {
+
+            public ImageView mUserAvatarImageView;
+            public TextView mUserNameTextView;
+            public View mView;
+
+            public UserAdapterViewHolder(View view) {
+                super(view);
+                mView = view;
+                mUserAvatarImageView = (ImageView) view.findViewById(R.id.user_avatar);
+                mUserNameTextView = (TextView) view.findViewById(R.id.user_name);
+            }
+        }
+    }
+
+    /**
+     * Object wrapper class for the userInfo.  Use it to distinguish if a profile is a
+     * guest profile, add user profile, or a current user.
+     */
+    public static final class UserRecord {
+
+        public final UserInfo mInfo;
+        public final boolean mIsGuest;
+        public final boolean mIsAddUser;
+        public final boolean mIsCurrent;
+
+        public UserRecord(UserInfo userInfo, boolean isGuest, boolean isAddUser,
+                boolean isCurrent) {
+            mInfo = userInfo;
+            mIsGuest = isGuest;
+            mIsAddUser = isAddUser;
+            mIsCurrent = isCurrent;
+        }
+    }
+
+    /**
+     * Listener used to notify when a user has been selected
+     */
+    interface UserSelectionListener {
+
+        void onUserSelected(UserRecord record);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
deleted file mode 100644
index 1bd820d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (C) 2015 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.car;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.qs.car.CarQSFragment;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Vector;
-
-/**
- * Displays a ViewPager with icons for the users in the system to allow switching between users.
- * One of the uses of this is for the lock screen in auto.
- */
-public class UserGridView extends ViewPager implements
-        UserInfoController.OnUserInfoChangedListener {
-    private StatusBar mStatusBar;
-    private UserSwitcherController mUserSwitcherController;
-    private Adapter mAdapter;
-    private UserSelectionListener mUserSelectionListener;
-    private UserInfoController mUserInfoController;
-    private Vector mUserContainers;
-    private int mContainerWidth;
-    private boolean mOverrideAlpha;
-    private CarQSFragment.UserSwitchCallback mUserSwitchCallback;
-
-    public UserGridView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public void init(StatusBar statusBar, UserSwitcherController userSwitcherController,
-            boolean overrideAlpha) {
-        mStatusBar = statusBar;
-        mUserSwitcherController = userSwitcherController;
-        mAdapter = new Adapter(mUserSwitcherController);
-        mUserInfoController = Dependency.get(UserInfoController.class);
-        mOverrideAlpha = overrideAlpha;
-        // Whenever the container width changes, the containers must be refreshed. Instead of
-        // doing an initial refreshContainers() to populate the containers, this listener will
-        // refresh them on layout change because that affects how the users are split into
-        // containers. Furthermore, at this point, the container width is unknown, so
-        // refreshContainers() cannot populate any containers.
-        addOnLayoutChangeListener(
-                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
-                    int newWidth = Math.max(left - right, right - left);
-                    if (mContainerWidth != newWidth) {
-                        mContainerWidth = newWidth;
-                        refreshContainers();
-                    }
-                });
-    }
-
-    private void refreshContainers() {
-        mUserContainers = new Vector();
-
-        Context context = getContext();
-        LayoutInflater inflater = LayoutInflater.from(context);
-
-        for (int i = 0; i < mAdapter.getCount(); i++) {
-            ViewGroup pods = (ViewGroup) inflater.inflate(
-                    R.layout.car_fullscreen_user_pod_container, null);
-
-            int iconsPerPage = mAdapter.getIconsPerPage();
-            int limit = Math.min(mUserSwitcherController.getUsers().size(), (i + 1) * iconsPerPage);
-            for (int j = i * iconsPerPage; j < limit; j++) {
-                View v = mAdapter.makeUserPod(inflater, context, j, pods);
-                if (mOverrideAlpha) {
-                    v.setAlpha(1f);
-                }
-                pods.addView(v);
-                // This is hacky, but the dividers on the pod container LinearLayout don't seem
-                // to work for whatever reason.  Instead, set a right margin on the pod if it's not
-                // the right-most pod and there is more than one pod in the container.
-                if (i < limit - 1 && limit > 1) {
-                    ViewGroup.MarginLayoutParams params =
-                            (ViewGroup.MarginLayoutParams) v.getLayoutParams();
-                    params.setMargins(0, 0, getResources().getDimensionPixelSize(
-                            R.dimen.car_fullscreen_user_pod_margin_between), 0);
-                    v.setLayoutParams(params);
-                }
-            }
-            mUserContainers.add(pods);
-        }
-
-        mAdapter = new Adapter(mUserSwitcherController);
-        setAdapter(mAdapter);
-    }
-
-    @Override
-    public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
-        refreshContainers();
-    }
-
-    public void setUserSwitchCallback(CarQSFragment.UserSwitchCallback callback) {
-        mUserSwitchCallback = callback;
-    }
-
-    public void onUserSwitched(int newUserId) {
-        // Bring up security view after user switch is completed.
-        post(this::showOfflineAuthUi);
-    }
-
-    public void setUserSelectionListener(UserSelectionListener userSelectionListener) {
-        mUserSelectionListener = userSelectionListener;
-    }
-
-    public void setListening(boolean listening) {
-        if (listening) {
-            mUserInfoController.addCallback(this);
-        } else {
-            mUserInfoController.removeCallback(this);
-        }
-    }
-
-    void showOfflineAuthUi() {
-        // TODO: Show keyguard UI in-place.
-        mStatusBar.executeRunnableDismissingKeyguard(null, null, true, true, true);
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        // Wrap content doesn't work in ViewPagers, so simulate the behavior in code.
-        int height = 0;
-        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
-            height = MeasureSpec.getSize(heightMeasureSpec);
-        } else {
-            for (int i = 0; i < getChildCount(); i++) {
-                View child = getChildAt(i);
-                child.measure(widthMeasureSpec,
-                        MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
-                height = Math.max(child.getMeasuredHeight(), height);
-            }
-
-            // Respect the AT_MOST request from parent.
-            if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
-                height = Math.min(MeasureSpec.getSize(heightMeasureSpec), height);
-            }
-        }
-        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
-
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-    }
-
-    /**
-     * This is a ViewPager.PagerAdapter which deletegates the work to a
-     * UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have
-     * to use composition instead to achieve the same goal since both the base classes are abstract
-     * classes and not interfaces.
-     */
-    private final class Adapter extends PagerAdapter {
-        private final int mPodWidth;
-        private final int mPodMarginBetween;
-        private final int mPodImageAvatarWidth;
-        private final int mPodImageAvatarHeight;
-
-        private final WrappedBaseUserAdapter mUserAdapter;
-
-        public Adapter(UserSwitcherController controller) {
-            super();
-            mUserAdapter = new WrappedBaseUserAdapter(controller, this);
-
-            Resources res = getResources();
-            mPodWidth = res.getDimensionPixelSize(R.dimen.car_fullscreen_user_pod_width);
-            mPodMarginBetween = res.getDimensionPixelSize(
-                    R.dimen.car_fullscreen_user_pod_margin_between);
-            mPodImageAvatarWidth = res.getDimensionPixelSize(
-                    R.dimen.car_fullscreen_user_pod_image_avatar_width);
-            mPodImageAvatarHeight = res.getDimensionPixelSize(
-                    R.dimen.car_fullscreen_user_pod_image_avatar_height);
-        }
-
-        @Override
-        public void destroyItem(ViewGroup container, int position, Object object) {
-            container.removeView((View) object);
-        }
-
-        private int getIconsPerPage() {
-            // We need to know how many pods we need in this page. Each pod has its own width and
-            // a margin between them. We can then divide the measured width of the parent by the
-            // sum of pod width and margin to get the number of pods that will completely fit.
-            // There is one less margin than the number of pods (eg. for 5 pods, there are 4
-            // margins), so need to add the margin to the measured width to account for that.
-            return (mContainerWidth + mPodMarginBetween) /
-                    (mPodWidth + mPodMarginBetween);
-        }
-
-        @Override
-        public void finishUpdate(ViewGroup container) {
-            if (mUserSwitchCallback != null) {
-                mUserSwitchCallback.resetShowing();
-            }
-        }
-
-        @Override
-        public Object instantiateItem(ViewGroup container, int position) {
-            if (position < mUserContainers.size()) {
-                container.addView((View) mUserContainers.get(position));
-                return mUserContainers.get(position);
-            } else {
-                return null;
-            }
-        }
-
-        /**
-         * Returns the default user icon.  This icon is a circle with a letter in it.  The letter is
-         * the first character in the username.
-         *
-         * @param userName the username of the user for which the icon is to be created
-         */
-        private Bitmap getDefaultUserIcon(CharSequence userName) {
-            CharSequence displayText = userName.subSequence(0, 1);
-            Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight,
-                    Bitmap.Config.ARGB_8888);
-            Canvas canvas = new Canvas(out);
-
-            // Draw the circle background.
-            GradientDrawable shape = new GradientDrawable();
-            shape.setShape(GradientDrawable.RADIAL_GRADIENT);
-            shape.setGradientRadius(1.0f);
-            shape.setColor(getContext().getColor(R.color.car_user_switcher_no_user_image_bgcolor));
-            shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
-            shape.draw(canvas);
-
-            // Draw the letter in the center.
-            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
-            paint.setColor(getContext().getColor(R.color.car_user_switcher_no_user_image_fgcolor));
-            paint.setTextAlign(Align.CENTER);
-            paint.setTextSize(getResources().getDimensionPixelSize(
-                    R.dimen.car_fullscreen_user_pod_icon_text_size));
-            Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
-            // The Y coordinate is measured by taking half the height of the pod, but that would
-            // draw the character putting the bottom of the font in the middle of the pod.  To
-            // correct this, half the difference between the top and bottom distance metrics of the
-            // font gives the offset of the font.  Bottom is a positive value, top is negative, so
-            // the different is actually a sum.  The "half" operation is then factored out.
-            canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2,
-                    (mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint);
-
-            return out;
-        }
-
-        private View makeUserPod(LayoutInflater inflater, Context context,
-                int position, ViewGroup parent) {
-            final UserSwitcherController.UserRecord record = mUserAdapter.getItem(position);
-            View view = inflater.inflate(R.layout.car_fullscreen_user_pod, parent, false);
-
-            TextView nameView = view.findViewById(R.id.user_name);
-            if (record != null) {
-                nameView.setText(mUserAdapter.getName(context, record));
-                view.setActivated(record.isCurrent);
-            } else {
-                nameView.setText(context.getString(R.string.unknown_user_label));
-            }
-
-            ImageView iconView = (ImageView) view.findViewById(R.id.user_avatar);
-            if (record == null || (record.picture == null && !record.isAddUser)) {
-                iconView.setImageBitmap(getDefaultUserIcon(nameView.getText()));
-            } else if (record.isAddUser) {
-                Drawable icon = context.getDrawable(R.drawable.ic_add_circle_qs);
-                icon.setTint(context.getColor(R.color.car_user_switcher_no_user_image_bgcolor));
-                iconView.setImageDrawable(icon);
-            } else {
-                iconView.setImageBitmap(record.picture);
-            }
-
-            iconView.setOnClickListener(v -> {
-                if (record == null) {
-                    return;
-                }
-
-                if (mUserSelectionListener != null) {
-                    mUserSelectionListener.onUserSelected(record);
-                }
-
-                if (record.isCurrent) {
-                    showOfflineAuthUi();
-                } else {
-                    mUserSwitcherController.switchTo(record);
-                }
-            });
-
-            return view;
-        }
-
-        @Override
-        public int getCount() {
-            int iconsPerPage = getIconsPerPage();
-            if (iconsPerPage == 0) {
-                return 0;
-            }
-            return (int) Math.ceil((double) mUserAdapter.getCount() / getIconsPerPage());
-        }
-
-        public void refresh() {
-            mUserAdapter.refresh();
-        }
-
-        @Override
-        public boolean isViewFromObject(View view, Object object) {
-            return view == object;
-        }
-    }
-
-    private final class WrappedBaseUserAdapter extends UserSwitcherController.BaseUserAdapter {
-        private final Adapter mContainer;
-
-        public WrappedBaseUserAdapter(UserSwitcherController controller, Adapter container) {
-            super(controller);
-            mContainer = container;
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            throw new UnsupportedOperationException("unused");
-        }
-
-        @Override
-        public void notifyDataSetChanged() {
-            super.notifyDataSetChanged();
-            mContainer.notifyDataSetChanged();
-        }
-    }
-
-    interface UserSelectionListener {
-        void onUserSelected(UserSwitcherController.UserRecord record);
-    };
-}