Files
app_Settings/src/com/android/settings/users/UserSettings.java
Amith Yamasani ae47ef43fa More user management ui work
Show setup dialog after adding user.
Write user profile to nickname on setup.
Remove self.
Correct dialog text for user creation.

Bug: 7104261
Bug: 7174751
Bug: 7174685

Change-Id: I0ecd688f3edaef61332f974012454ceb87762e9f
2012-09-16 23:15:42 -07:00

482 lines
17 KiB
Java

/*
* Copyright (C) 2012 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.settings.users;
import android.app.ActivityManagerNative;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceGroup;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Profile;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.text.InputType;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;
import com.android.internal.telephony.MccTable;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class UserSettings extends SettingsPreferenceFragment
implements OnPreferenceClickListener, OnClickListener, DialogInterface.OnDismissListener,
Preference.OnPreferenceChangeListener {
private static final String TAG = "UserSettings";
private static final String KEY_USER_NICKNAME = "user_nickname";
private static final String KEY_USER_LIST = "user_list";
private static final String KEY_USER_ME = "user_me";
private static final int MENU_ADD_USER = Menu.FIRST;
private static final int MENU_REMOVE_USER = Menu.FIRST+1;
private static final int DIALOG_CONFIRM_REMOVE = 1;
private static final int DIALOG_ADD_USER = 2;
private static final int DIALOG_SETUP_USER = 3;
private static final int MESSAGE_UPDATE_LIST = 1;
private static final int MESSAGE_SETUP_USER = 2;
private static final int[] USER_DRAWABLES = {
R.drawable.ic_user,
R.drawable.ic_user_cyan,
R.drawable.ic_user_green,
R.drawable.ic_user_purple,
R.drawable.ic_user_red,
R.drawable.ic_user_yellow
};
private static final String[] CONTACT_PROJECTION = new String[] {
Phone._ID, // 0
Phone.DISPLAY_NAME, // 1
};
private PreferenceGroup mUserListCategory;
private Preference mMePreference;
private EditTextPreference mNicknamePreference;
private int mRemovingUserId = -1;
private int mAddedUserId = 0;
private boolean mAddingUser;
private boolean mProfileExists;
private final Object mUserLock = new Object();
private UserManager mUserManager;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_UPDATE_LIST:
updateUserList();
break;
case MESSAGE_SETUP_USER:
onUserCreated(msg.arg1);
break;
}
}
};
private BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
}
};
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mUserManager = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
addPreferencesFromResource(R.xml.user_settings);
mUserListCategory = (PreferenceGroup) findPreference(KEY_USER_LIST);
mMePreference = (Preference) findPreference(KEY_USER_ME);
mMePreference.setOnPreferenceClickListener(this);
if (UserHandle.myUserId() != UserHandle.USER_OWNER) {
mMePreference.setSummary(null);
}
mNicknamePreference = (EditTextPreference) findPreference(KEY_USER_NICKNAME);
mNicknamePreference.setOnPreferenceChangeListener(this);
mNicknamePreference.getEditText().setInputType(
InputType.TYPE_TEXT_VARIATION_NORMAL | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
loadProfile();
setHasOptionsMenu(true);
getActivity().registerReceiver(mUserChangeReceiver,
new IntentFilter(Intent.ACTION_USER_REMOVED));
}
@Override
public void onResume() {
super.onResume();
loadProfile();
updateUserList();
}
@Override
public void onDestroy() {
super.onDestroy();
getActivity().unregisterReceiver(mUserChangeReceiver);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (UserHandle.myUserId() == UserHandle.USER_OWNER) {
if (mUserManager.getMaxSupportedUsers() > mUserManager.getUsers().size()) {
MenuItem addUserItem = menu.add(0, MENU_ADD_USER, 0, R.string.user_add_user_menu);
addUserItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
| MenuItem.SHOW_AS_ACTION_WITH_TEXT);
}
} else {
MenuItem removeThisUser = menu.add(0, MENU_REMOVE_USER, 0, R.string.user_remove_user_menu);
removeThisUser.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
| MenuItem.SHOW_AS_ACTION_WITH_TEXT);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
final int itemId = item.getItemId();
if (itemId == MENU_ADD_USER) {
onAddUserClicked();
return true;
} else if (itemId == MENU_REMOVE_USER) {
onRemoveUserClicked(UserHandle.myUserId());
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
private void loadProfile() {
mProfileExists = false;
new AsyncTask<Void, Void, String>() {
@Override
protected void onPostExecute(String result) {
finishLoadProfile(result);
}
@Override
protected String doInBackground(Void... values) {
UserInfo user = mUserManager.getUserInfo(UserHandle.myUserId());
if (user.iconPath == null || user.iconPath.equals("")) {
assignProfilePhoto(user);
}
String profileName = getProfileName();
return profileName;
}
}.execute();
}
private void finishLoadProfile(String profileName) {
mMePreference.setTitle(profileName);
setPhotoId(mMePreference, mUserManager.getUserInfo(UserHandle.myUserId()));
}
private void onAddUserClicked() {
synchronized (mUserLock) {
if (mRemovingUserId == -1 && !mAddingUser) {
showDialog(DIALOG_ADD_USER);
setOnDismissListener(this);
}
}
}
private void onRemoveUserClicked(int userId) {
synchronized (mUserLock) {
if (mRemovingUserId == -1 && !mAddingUser) {
mRemovingUserId = userId;
showDialog(DIALOG_CONFIRM_REMOVE);
setOnDismissListener(this);
}
}
}
private void onUserCreated(int userId) {
mAddedUserId = userId;
showDialog(DIALOG_SETUP_USER);
}
@Override
public Dialog onCreateDialog(int dialogId) {
switch (dialogId) {
case DIALOG_CONFIRM_REMOVE:
return new AlertDialog.Builder(getActivity())
.setTitle(UserHandle.myUserId() == mRemovingUserId
? R.string.user_confirm_remove_self_title
: R.string.user_confirm_remove_title)
.setMessage(UserHandle.myUserId() == mRemovingUserId
? R.string.user_confirm_remove_self_message
: R.string.user_confirm_remove_message)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
removeUserNow();
}
})
.setNegativeButton(android.R.string.cancel, null)
.create();
case DIALOG_ADD_USER:
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.user_add_user_title)
.setMessage(R.string.user_add_user_message)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
addUserNow();
}
})
.setNegativeButton(android.R.string.cancel, null)
.create();
case DIALOG_SETUP_USER:
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.user_setup_dialog_title)
.setMessage(R.string.user_setup_dialog_message)
.setPositiveButton(R.string.user_setup_button_setup_now,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
switchUserNow(mAddedUserId);
}
})
.setNegativeButton(R.string.user_setup_button_setup_later, null)
.create();
default:
return null;
}
}
private void removeUserNow() {
if (mRemovingUserId == UserHandle.myUserId()) {
removeThisUser();
} else {
new Thread() {
public void run() {
synchronized (mUserLock) {
// TODO: Show some progress while removing the user
mUserManager.removeUser(mRemovingUserId);
mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
mRemovingUserId = -1;
}
}
}.start();
}
}
private void removeThisUser() {
try {
ActivityManagerNative.getDefault().switchUser(UserHandle.USER_OWNER);
((UserManager) getActivity().getSystemService(Context.USER_SERVICE))
.removeUser(UserHandle.myUserId());
} catch (RemoteException re) {
Log.e(TAG, "Unable to remove self user");
}
}
private void addUserNow() {
synchronized (mUserLock) {
mAddingUser = true;
updateUserList();
new Thread() {
public void run() {
// Could take a few seconds
UserInfo user = mUserManager.createUser(
getActivity().getResources().getString(R.string.user_new_user_name), 0);
if (user != null) {
assignDefaultPhoto(user);
}
synchronized (mUserLock) {
mAddingUser = false;
mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
mHandler.sendMessage(mHandler.obtainMessage(
MESSAGE_SETUP_USER, user.id, user.serialNumber));
}
}
}.start();
}
}
private void switchUserNow(int userId) {
try {
ActivityManagerNative.getDefault().switchUser(userId);
} catch (RemoteException re) {
// Nothing to do
}
}
private void updateUserList() {
List<UserInfo> users = mUserManager.getUsers();
mUserListCategory.removeAll();
mUserListCategory.setOrderingAsAdded(false);
for (UserInfo user : users) {
Preference pref;
if (user.id == UserHandle.myUserId()) {
pref = mMePreference;
mNicknamePreference.setText(user.name);
mNicknamePreference.setSummary(user.name);
} else {
pref = new UserPreference(getActivity(), null, user.id,
UserHandle.myUserId() == UserHandle.USER_OWNER, this);
pref.setOnPreferenceClickListener(this);
pref.setKey("id=" + user.id);
mUserListCategory.addPreference(pref);
if (user.id == UserHandle.USER_OWNER) {
pref.setSummary(R.string.user_owner);
}
pref.setTitle(user.name);
}
if (user.iconPath != null) {
setPhotoId(pref, user);
}
}
// Add a temporary entry for the user being created
if (mAddingUser) {
Preference pref = new UserPreference(getActivity(), null, UserPreference.USERID_UNKNOWN,
false, null);
pref.setEnabled(false);
pref.setTitle(R.string.user_new_user_name);
pref.setSummary(R.string.user_adding_new_user);
pref.setIcon(R.drawable.ic_user);
mUserListCategory.addPreference(pref);
}
getActivity().invalidateOptionsMenu();
}
private void assignProfilePhoto(final UserInfo user) {
if (!Utils.copyMeProfilePhoto(getActivity(), user)) {
assignDefaultPhoto(user);
}
}
private String getProfileName() {
String name = Utils.getMeProfileName(getActivity());
if (name != null) {
mProfileExists = true;
}
return name;
}
private void assignDefaultPhoto(UserInfo user) {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
USER_DRAWABLES[user.id % USER_DRAWABLES.length]);
ParcelFileDescriptor fd = mUserManager.setUserIcon(user.id);
if (fd != null) {
bitmap.compress(CompressFormat.PNG, 100,
new ParcelFileDescriptor.AutoCloseOutputStream(fd));
}
}
private void setPhotoId(Preference pref, UserInfo user) {
ParcelFileDescriptor fd = mUserManager.setUserIcon(user.id);
Drawable d = Drawable.createFromStream(new ParcelFileDescriptor.AutoCloseInputStream(fd),
user.iconPath);
if (d == null) return;
pref.setIcon(d);
}
private void setUserName(String name) {
mUserManager.setUserName(UserHandle.myUserId(), name);
mNicknamePreference.setSummary(name);
}
@Override
public boolean onPreferenceClick(Preference pref) {
if (pref == mMePreference) {
Intent editProfile;
if (!mProfileExists) {
editProfile = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
// TODO: Make this a proper API
editProfile.putExtra("newLocalProfile", true);
} else {
editProfile = new Intent(Intent.ACTION_EDIT, ContactsContract.Profile.CONTENT_URI);
}
// To make sure that it returns back here when done
// TODO: Make this a proper API
editProfile.putExtra("finishActivityOnSaveCompleted", true);
startActivity(editProfile);
}
return false;
}
@Override
public void onClick(View v) {
if (v.getTag() instanceof UserPreference) {
int userId = ((UserPreference) v.getTag()).getUserId();
onRemoveUserClicked(userId);
}
}
@Override
public void onDismiss(DialogInterface dialog) {
synchronized (mUserLock) {
mAddingUser = false;
mRemovingUserId = -1;
}
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mNicknamePreference) {
String value = (String) newValue;
if (preference == mNicknamePreference && value != null
&& value.length() > 0) {
setUserName(value);
}
return true;
}
return false;
}
}