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
482 lines
17 KiB
Java
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;
|
|
}
|
|
|
|
}
|