1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settingslib.drawer;
18
19import android.app.ActivityManager;
20
21import android.content.Context;
22import android.content.pm.UserInfo;
23import android.database.DataSetObserver;
24import android.graphics.drawable.BitmapDrawable;
25import android.graphics.drawable.Drawable;
26import android.os.UserHandle;
27import android.os.UserManager;
28import android.view.LayoutInflater;
29import android.view.View;
30import android.view.ViewGroup;
31import android.widget.ImageView;
32import android.widget.ListAdapter;
33import android.widget.SpinnerAdapter;
34import android.widget.TextView;
35import com.android.internal.util.UserIcons;
36import com.android.settingslib.drawable.UserIconDrawable;
37
38import com.android.settingslib.R;
39
40import java.util.ArrayList;
41import java.util.List;
42
43/**
44 * Adapter for a spinner that shows a list of users.
45 */
46public class UserAdapter implements SpinnerAdapter, ListAdapter {
47    /** Holder for user details */
48    public static class UserDetails {
49        private final UserHandle mUserHandle;
50        private final String mName;
51        private final Drawable mIcon;
52
53        public UserDetails(UserHandle userHandle, UserManager um, Context context) {
54            mUserHandle = userHandle;
55            UserInfo userInfo = um.getUserInfo(mUserHandle.getIdentifier());
56            Drawable icon;
57            if (userInfo.isManagedProfile()) {
58                mName = context.getString(R.string.managed_user_title);
59                icon = context.getDrawable(
60                    com.android.internal.R.drawable.ic_corp_icon);
61            } else {
62                mName = userInfo.name;
63                final int userId = userInfo.id;
64                if (um.getUserIcon(userId) != null) {
65                    icon = new BitmapDrawable(context.getResources(), um.getUserIcon(userId));
66                } else {
67                    icon = UserIcons.getDefaultUserIcon(userId, /* light= */ false);
68                }
69            }
70            this.mIcon = encircle(context, icon);
71        }
72
73        private static Drawable encircle(Context context, Drawable icon) {
74            return new UserIconDrawable(UserIconDrawable.getSizeForList(context))
75                    .setIconDrawable(icon).bake();
76        }
77    }
78    private ArrayList<UserDetails> data;
79    private final LayoutInflater mInflater;
80
81    public UserAdapter(Context context, ArrayList<UserDetails> users) {
82        if (users == null) {
83            throw new IllegalArgumentException("A list of user details must be provided");
84        }
85        this.data = users;
86        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
87    }
88
89    public UserHandle getUserHandle(int position) {
90        if (position < 0 || position >= data.size()) {
91            return null;
92        }
93        return data.get(position).mUserHandle;
94    }
95
96    @Override
97    public View getDropDownView(int position, View convertView, ViewGroup parent) {
98        final View row = convertView != null ? convertView : createUser(parent);
99
100        UserDetails user = data.get(position);
101        ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(user.mIcon);
102        ((TextView) row.findViewById(android.R.id.title)).setText(getTitle(user));
103        return row;
104    }
105
106    private int getTitle(UserDetails user) {
107        int userHandle = user.mUserHandle.getIdentifier();
108        if (userHandle == UserHandle.USER_CURRENT
109                || userHandle == ActivityManager.getCurrentUser()) {
110            return R.string.category_personal;
111        } else {
112            return R.string.category_work;
113        }
114    }
115
116    private View createUser(ViewGroup parent) {
117        return mInflater.inflate(R.layout.user_preference, parent, false);
118    }
119
120    @Override
121    public void registerDataSetObserver(DataSetObserver observer) {
122        // We don't support observers
123    }
124
125    @Override
126    public void unregisterDataSetObserver(DataSetObserver observer) {
127        // We don't support observers
128    }
129
130    @Override
131    public int getCount() {
132        return data.size();
133    }
134
135    @Override
136    public UserDetails getItem(int position) {
137        return data.get(position);
138    }
139
140    @Override
141    public long getItemId(int position) {
142        return data.get(position).mUserHandle.getIdentifier();
143    }
144
145    @Override
146    public boolean hasStableIds() {
147        return false;
148    }
149
150    @Override
151    public View getView(int position, View convertView, ViewGroup parent) {
152        return getDropDownView(position, convertView, parent);
153    }
154
155    @Override
156    public int getItemViewType(int position) {
157        return 0;
158    }
159
160    @Override
161    public int getViewTypeCount() {
162        return 1;
163    }
164
165    @Override
166    public boolean isEmpty() {
167        return data.isEmpty();
168    }
169
170    @Override
171    public boolean areAllItemsEnabled() {
172        return true;
173    }
174
175    @Override
176    public boolean isEnabled(int position) {
177        return true;
178    }
179
180    /**
181     * Creates a {@link UserAdapter} if there is more than one profile on the device.
182     *
183     * <p> The adapter can be used to populate a spinner that switches between the Settings
184     * app on the different profiles.
185     *
186     * @return a {@link UserAdapter} or null if there is only one profile.
187     */
188    public static UserAdapter createUserSpinnerAdapter(UserManager userManager,
189            Context context) {
190        List<UserHandle> userProfiles = userManager.getUserProfiles();
191        if (userProfiles.size() < 2) {
192            return null;
193        }
194
195        UserHandle myUserHandle = new UserHandle(UserHandle.myUserId());
196        // The first option should be the current profile
197        userProfiles.remove(myUserHandle);
198        userProfiles.add(0, myUserHandle);
199
200        return createUserAdapter(userManager, context, userProfiles);
201    }
202
203    public static UserAdapter createUserAdapter(UserManager userManager,
204            Context context, List<UserHandle> userProfiles) {
205        ArrayList<UserDetails> userDetails = new ArrayList<UserDetails>(userProfiles.size());
206        final int count = userProfiles.size();
207        for (int i = 0; i < count; i++) {
208            userDetails.add(new UserDetails(userProfiles.get(i), userManager, context));
209        }
210        return new UserAdapter(context, userDetails);
211    }
212}
213