UserDetailsSettings.java revision b810a0ddf9dd93a08789aff38901eeab9bfaf812
1/*
2 * Copyright (C) 2012 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.settings.users;
18
19import android.app.AlertDialog;
20import android.app.Dialog;
21import android.content.DialogInterface;
22import android.content.Intent;
23import android.content.pm.ApplicationInfo;
24import android.content.pm.IPackageManager;
25import android.content.pm.PackageInfo;
26import android.content.pm.PackageManager;
27import android.content.pm.ResolveInfo;
28import android.content.pm.UserInfo;
29import android.graphics.drawable.Drawable;
30import android.net.Uri;
31import android.os.Bundle;
32import android.os.RemoteException;
33import android.os.ServiceManager;
34import android.os.SystemProperties;
35import android.preference.CheckBoxPreference;
36import android.preference.EditTextPreference;
37import android.preference.Preference;
38import android.preference.PreferenceGroup;
39import android.text.TextUtils;
40import android.util.Log;
41import android.view.Menu;
42import android.view.MenuInflater;
43import android.view.MenuItem;
44
45import com.android.settings.DialogCreatable;
46import com.android.settings.R;
47import com.android.settings.SettingsPreferenceFragment;
48
49import java.util.HashMap;
50import java.util.List;
51
52public class UserDetailsSettings extends SettingsPreferenceFragment
53        implements Preference.OnPreferenceChangeListener, DialogCreatable {
54
55    private static final String TAG = "UserDetailsSettings";
56
57    private static final int MENU_REMOVE_USER = Menu.FIRST;
58    private static final int DIALOG_CONFIRM_REMOVE = 1;
59
60    private static final String KEY_USER_NAME = "user_name";
61    private static final String KEY_INSTALLED_APPS = "market_apps_category";
62    private static final String KEY_SYSTEM_APPS = "system_apps_category";
63    public static final String EXTRA_USER_ID = "user_id";
64
65    private static final String[] SYSTEM_APPS = {
66            "com.google.android.browser",
67            "com.google.android.gm",
68            "com.google.android.youtube"
69    };
70
71    static class AppState {
72        boolean dirty;
73        boolean enabled;
74
75        AppState(boolean enabled) {
76            this.enabled = enabled;
77        }
78    }
79
80    private HashMap<String, AppState> mAppStates = new HashMap<String, AppState>();
81    private PreferenceGroup mSystemAppGroup;
82    private PreferenceGroup mInstalledAppGroup;
83    private EditTextPreference mNamePref;
84
85    private IPackageManager mIPm;
86    private PackageManager mPm;
87    private int mUserId;
88    private boolean mNewUser;
89
90    @Override
91    public void onCreate(Bundle icicle) {
92        super.onCreate(icicle);
93        addPreferencesFromResource(R.xml.user_details);
94        Bundle args = getArguments();
95        mNewUser = args == null || args.getInt(EXTRA_USER_ID, -1) == -1;
96        mUserId = mNewUser ? -1 : args.getInt(EXTRA_USER_ID, -1);
97        mIPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
98
99        if (mUserId == -1) {
100            try {
101                mUserId = mIPm.createUser(getString(R.string.user_new_user_name), 0).id;
102            } catch (RemoteException re) {
103            }
104        }
105        mSystemAppGroup = (PreferenceGroup) findPreference(KEY_SYSTEM_APPS);
106        mInstalledAppGroup = (PreferenceGroup) findPreference(KEY_INSTALLED_APPS);
107        mNamePref = (EditTextPreference) findPreference(KEY_USER_NAME);
108        mNamePref.setOnPreferenceChangeListener(this);
109
110        setHasOptionsMenu(true);
111    }
112
113    @Override
114    public void onResume() {
115        super.onResume();
116        mPm = getActivity().getPackageManager();
117        if (mUserId > 0) {
118            initExistingUser();
119        } else {
120            initNewUser();
121        }
122        refreshApps();
123    }
124
125    @Override
126    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
127        MenuItem addAccountItem = menu.add(0, MENU_REMOVE_USER, 0,
128                mNewUser ? R.string.user_discard_user_menu : R.string.user_remove_user_menu);
129        addAccountItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
130                | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
131    }
132
133    @Override
134    public boolean onOptionsItemSelected(MenuItem item) {
135        final int itemId = item.getItemId();
136        if (itemId == MENU_REMOVE_USER) {
137            onRemoveUserClicked();
138            return true;
139        } else {
140            return super.onOptionsItemSelected(item);
141        }
142    }
143
144    private void initExistingUser() {
145        List<UserInfo> users = mPm.getUsers();
146        UserInfo foundUser = null;
147        for (UserInfo user : users) {
148            if (user.id == mUserId) {
149                foundUser = user;
150                break;
151            }
152        }
153        if (foundUser != null) {
154            mNamePref.setSummary(foundUser.name);
155            mNamePref.setText(foundUser.name);
156        }
157    }
158
159    private void initNewUser() {
160        // TODO: Check if there's already a "New user" and localize
161        mNamePref.setText(getString(R.string.user_new_user_name));
162        mNamePref.setSummary(getString(R.string.user_new_user_name));
163    }
164
165    private void onRemoveUserClicked() {
166        if (mNewUser) {
167            removeUserNow();
168        } else {
169            showDialog(DIALOG_CONFIRM_REMOVE);
170        }
171    }
172
173    private void removeUserNow() {
174        try {
175            mIPm.removeUser(mUserId);
176        } catch (RemoteException re) {
177            // Couldn't remove user. Shouldn't happen
178            Log.e(TAG, "Couldn't remove user " + mUserId + "\n" + re);
179        }
180        finish();
181    }
182
183    private void insertAppInfo(PreferenceGroup group, HashMap<String, AppState> appStateMap,
184            PackageInfo info, boolean defaultState) {
185        if (info != null) {
186            String pkgName = info.packageName;
187            String name = info.applicationInfo.loadLabel(mPm).toString();
188            Drawable icon = info.applicationInfo.loadIcon(mPm);
189            AppState appState = appStateMap.get(info.packageName);
190            boolean enabled = appState == null ? defaultState : appState.enabled;
191            CheckBoxPreference appPref = new CheckBoxPreference(getActivity());
192            appPref.setTitle(name != null ? name : pkgName);
193            appPref.setIcon(icon);
194            appPref.setChecked(enabled);
195            appPref.setKey(pkgName);
196            appPref.setPersistent(false);
197            appPref.setOnPreferenceChangeListener(this);
198            group.addPreference(appPref);
199        }
200    }
201
202    private void refreshApps() {
203        mSystemAppGroup.removeAll();
204        mInstalledAppGroup.removeAll();
205
206        boolean firstTime = mAppStates.isEmpty();
207
208        final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
209        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
210        List<ResolveInfo> apps = mPm.queryIntentActivities(mainIntent, 0);
211
212        for (ResolveInfo resolveInfo : apps) {
213            PackageInfo info;
214            try {
215                info = mIPm.getPackageInfo(resolveInfo.activityInfo.packageName,
216                        0 /* flags */,
217                    mUserId < 0 ? 0 : mUserId);
218            } catch (RemoteException re) {
219                continue;
220            }
221            if (firstTime) {
222                mAppStates.put(resolveInfo.activityInfo.packageName,
223                        new AppState(info.applicationInfo.enabled));
224            }
225            if ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
226                if (mSystemAppGroup.findPreference(info.packageName) != null) {
227                    continue;
228                }
229                insertAppInfo(mSystemAppGroup, mAppStates, info, false);
230            } else {
231                if (mInstalledAppGroup.findPreference(info.packageName) != null) {
232                    continue;
233                }
234                insertAppInfo(mInstalledAppGroup, mAppStates, info, false);
235            }
236        }
237    }
238
239    @Override
240    public boolean onPreferenceChange(Preference preference, Object newValue) {
241        if (preference instanceof CheckBoxPreference) {
242            String packageName = preference.getKey();
243            int newState = ((Boolean) newValue) ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
244                    : PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
245            try {
246                mIPm.setApplicationEnabledSetting(packageName, newState, 0, mUserId);
247            } catch (RemoteException re) {
248                Log.e(TAG, "Unable to change enabled state of package " + packageName
249                        + " for user " + mUserId);
250            }
251        } else if (preference == mNamePref) {
252            String name = (String) newValue;
253            if (TextUtils.isEmpty(name)) {
254                return false;
255            }
256            try {
257                mIPm.updateUserName(mUserId, (String) newValue);
258                mNamePref.setSummary((String) newValue);
259            } catch (RemoteException re) {
260                return false;
261            }
262        }
263        return true;
264    }
265
266    @Override
267    public Dialog onCreateDialog(int dialogId) {
268        switch (dialogId) {
269            case DIALOG_CONFIRM_REMOVE:
270                return new AlertDialog.Builder(getActivity())
271                    .setTitle(R.string.user_confirm_remove_title)
272                    .setMessage(R.string.user_confirm_remove_message)
273                    .setPositiveButton(android.R.string.ok,
274                        new DialogInterface.OnClickListener() {
275                            public void onClick(DialogInterface dialog, int which) {
276                                removeUserNow();
277                            }
278                    })
279                    .setNegativeButton(android.R.string.cancel, null)
280                    .create();
281            default:
282                return null;
283        }
284    }
285}
286