Home | History | Annotate | Download | only in users
      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 
     17 package com.android.settings.users;
     18 
     19 import android.app.AlertDialog;
     20 import android.app.Dialog;
     21 import android.content.DialogInterface;
     22 import android.content.Intent;
     23 import android.content.pm.ApplicationInfo;
     24 import android.content.pm.IPackageManager;
     25 import android.content.pm.PackageInfo;
     26 import android.content.pm.PackageManager;
     27 import android.content.pm.ResolveInfo;
     28 import android.content.pm.UserInfo;
     29 import android.graphics.drawable.Drawable;
     30 import android.net.Uri;
     31 import android.os.Bundle;
     32 import android.os.RemoteException;
     33 import android.os.ServiceManager;
     34 import android.os.SystemProperties;
     35 import android.preference.CheckBoxPreference;
     36 import android.preference.EditTextPreference;
     37 import android.preference.Preference;
     38 import android.preference.PreferenceGroup;
     39 import android.text.TextUtils;
     40 import android.util.Log;
     41 import android.view.Menu;
     42 import android.view.MenuInflater;
     43 import android.view.MenuItem;
     44 
     45 import com.android.settings.DialogCreatable;
     46 import com.android.settings.R;
     47 import com.android.settings.SettingsPreferenceFragment;
     48 
     49 import java.util.HashMap;
     50 import java.util.List;
     51 
     52 public 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