User management UI: take 2
Single screen user management, also visible on secondary users.
Work in progress, especially with respect to synchronizing with
the Me profile.
Change-Id: Id6e94a85d53356847e4e019c52e3388de9ecb354
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index d5a90f6..6f2002a 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -107,14 +107,13 @@
R.id.application_settings,
R.id.personal_section,
R.id.security_settings,
+ R.id.user_settings,
R.id.account_settings,
R.id.account_add,
R.id.system_section,
R.id.about_settings
};
- private boolean mEnableUserManagement = false;
-
// TODO: Update Call Settings based on airplane mode state.
protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
@@ -129,11 +128,6 @@
getWindow().setUiOptions(0);
}
- if (android.provider.Settings.Secure.getInt(getContentResolver(), "multiuser_enabled", -1)
- > 0) {
- mEnableUserManagement = true;
- }
-
mAuthenticatorHelper = new AuthenticatorHelper();
mAuthenticatorHelper.updateAuthDescriptions(this);
mAuthenticatorHelper.onAccountsUpdated(this, null);
@@ -418,8 +412,7 @@
int headerIndex = i + 1;
i = insertAccountsHeaders(target, headerIndex);
} else if (id == R.id.user_settings) {
- if (!mEnableUserManagement
- || !UserHandle.MU_ENABLED || UserHandle.myUserId() != 0
+ if (!UserHandle.MU_ENABLED
|| !getResources().getBoolean(R.bool.enable_user_management)
|| Utils.isMonkeyRunning()) {
target.remove(header);
diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java
deleted file mode 100644
index 518c6b6..0000000
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * 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.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.CompressFormat;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserManager;
-import android.preference.CheckBoxPreference;
-import android.preference.EditTextPreference;
-import android.preference.Preference;
-import android.preference.PreferenceGroup;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-
-import com.android.settings.DialogCreatable;
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-
-import java.util.HashMap;
-import java.util.List;
-
-public class UserDetailsSettings extends SettingsPreferenceFragment
- implements Preference.OnPreferenceChangeListener, DialogCreatable,
- Preference.OnPreferenceClickListener {
-
- private static final String TAG = "UserDetailsSettings";
-
- private static final int MENU_REMOVE_USER = Menu.FIRST;
- private static final int DIALOG_CONFIRM_REMOVE = 1;
-
- private static final String KEY_USER_NAME = "user_name";
- private static final String KEY_USER_PICTURE = "user_picture";
-
- public static final String EXTRA_USER_ID = "user_id";
-
- private static final int RESULT_PICK_IMAGE = 1;
- private static final int RESULT_CROP_IMAGE = 2;
-
- private EditTextPreference mNamePref;
- private Preference mPicturePref;
-
- private IPackageManager mIPm;
- private PackageManager mPm;
- private UserManager mUm;
- private int mUserId;
- private boolean mNewUser;
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- addPreferencesFromResource(R.xml.user_details);
- Bundle args = getArguments();
- mNewUser = args == null || args.getInt(EXTRA_USER_ID, -1) == -1;
- mUserId = mNewUser ? -1 : args.getInt(EXTRA_USER_ID, -1);
- mIPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
- mUm = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
-
- if (icicle != null && icicle.containsKey(EXTRA_USER_ID)) {
- mUserId = icicle.getInt(EXTRA_USER_ID);
- mNewUser = false;
- }
-
- if (mUserId == -1) {
- mUserId = mUm.createUser(getString(R.string.user_new_user_name), 0).id;
- }
- mNamePref = (EditTextPreference) findPreference(KEY_USER_NAME);
- mNamePref.setOnPreferenceChangeListener(this);
- mPicturePref = findPreference(KEY_USER_PICTURE);
- mPicturePref.setOnPreferenceClickListener(this);
- setHasOptionsMenu(true);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mPm = getActivity().getPackageManager();
- if (mUserId >= 0) {
- initExistingUser();
- } else {
- initNewUser();
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putInt(EXTRA_USER_ID, mUserId);
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- if (mUserId == 0) {
- return;
- }
- MenuItem addAccountItem = menu.add(0, MENU_REMOVE_USER, 0,
- mNewUser ? R.string.user_discard_user_menu : R.string.user_remove_user_menu);
- addAccountItem.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_REMOVE_USER) {
- onRemoveUserClicked();
- return true;
- } else {
- return super.onOptionsItemSelected(item);
- }
- }
-
- private void initExistingUser() {
- List<UserInfo> users = mUm.getUsers();
- UserInfo foundUser = null;
- for (UserInfo user : users) {
- if (user.id == mUserId) {
- foundUser = user;
- break;
- }
- }
- if (foundUser != null) {
- mNamePref.setSummary(foundUser.name);
- mNamePref.setText(foundUser.name);
- if (foundUser.iconPath != null) {
- setPhotoId(foundUser.iconPath);
- }
- }
- }
-
- private void initNewUser() {
- // TODO: Check if there's already a "New user" and localize
- mNamePref.setText(getString(R.string.user_new_user_name));
- mNamePref.setSummary(getString(R.string.user_new_user_name));
- }
-
- private void onRemoveUserClicked() {
- if (mNewUser) {
- removeUserNow();
- } else {
- showDialog(DIALOG_CONFIRM_REMOVE);
- }
- }
-
- private void removeUserNow() {
- mUm.removeUser(mUserId);
- finish();
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- if (preference instanceof CheckBoxPreference) {
- String packageName = preference.getKey();
- int newState = ((Boolean) newValue) ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
- : PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
- try {
- mIPm.setApplicationEnabledSetting(packageName, newState, 0, mUserId);
- } catch (RemoteException re) {
- Log.e(TAG, "Unable to change enabled state of package " + packageName
- + " for user " + mUserId);
- }
- } else if (preference == mNamePref) {
- String name = (String) newValue;
- if (TextUtils.isEmpty(name)) {
- return false;
- }
- mUm.setUserName(mUserId, (String) newValue);
- mNamePref.setSummary((String) newValue);
- }
- return true;
- }
-
- @Override
- public Dialog onCreateDialog(int dialogId) {
- switch (dialogId) {
- case DIALOG_CONFIRM_REMOVE:
- return new AlertDialog.Builder(getActivity())
- .setTitle(R.string.user_confirm_remove_title)
- .setMessage(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();
- default:
- return null;
- }
- }
-
- @Override
- public boolean onPreferenceClick(Preference preference) {
- if (preference == mPicturePref) {
- Intent intent = new Intent();
- intent.setType("image/*");
- intent.setAction(Intent.ACTION_GET_CONTENT);
-
- startActivityForResult(intent, RESULT_PICK_IMAGE);
- }
- return false;
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (resultCode != Activity.RESULT_OK) {
- return;
- }
- switch (requestCode) {
- case RESULT_PICK_IMAGE:
- if (data.getData() != null) {
- Uri imageUri = data.getData();
- System.err.println("imageUri = " + imageUri);
- cropImage(imageUri);
- }
- break;
- case RESULT_CROP_IMAGE:
- saveCroppedImage(data);
- break;
- }
- }
-
- private void cropImage(Uri imageUri) {
- final Uri inputPhotoUri = imageUri;
- Intent intent = new Intent("com.android.camera.action.CROP");
- intent.setDataAndType(inputPhotoUri, "image/*");
- intent.putExtra("crop", "true");
- intent.putExtra("aspectX", 1);
- intent.putExtra("aspectY", 1);
- intent.putExtra("outputX", 96);
- intent.putExtra("outputY", 96);
- intent.putExtra("return-data", true);
- startActivityForResult(intent, RESULT_CROP_IMAGE);
- }
-
- private void saveCroppedImage(Intent data) {
- if (data.hasExtra("data")) {
- Bitmap bitmap = (Bitmap) data.getParcelableExtra("data");
- ParcelFileDescriptor fd = mUm.setUserIcon(mUserId);
- if (fd != null) {
- bitmap.compress(CompressFormat.PNG, 100,
- new ParcelFileDescriptor.AutoCloseOutputStream(fd));
- setPhotoId(mUm.getUserInfo(mUserId).iconPath);
- }
- }
- }
-
- private void setPhotoId(String realPath) {
- Drawable d = Drawable.createFromPath(realPath);
- if (d == null) return;
- mPicturePref.setIcon(d);
- }
-}
diff --git a/src/com/android/settings/users/UserPreference.java b/src/com/android/settings/users/UserPreference.java
new file mode 100644
index 0000000..2ced7ae
--- /dev/null
+++ b/src/com/android/settings/users/UserPreference.java
@@ -0,0 +1,85 @@
+/*
+ * 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 com.android.internal.util.CharSequences;
+import com.android.settings.R;
+
+import android.content.Context;
+import android.os.UserManager;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+
+public class UserPreference extends Preference {
+
+ public static final int USERID_UNKNOWN = -10;
+
+ private OnClickListener mDeleteClickListener;
+ private int mSerialNumber = -1;
+ private int mUserId = USERID_UNKNOWN;
+
+ public UserPreference(Context context, AttributeSet attrs) {
+ this(context, attrs, USERID_UNKNOWN, false, null);
+ }
+
+ UserPreference(Context context, AttributeSet attrs, int userId, boolean showDelete,
+ OnClickListener deleteListener) {
+ super(context, attrs);
+ if (showDelete) {
+ setWidgetLayoutResource(R.layout.preference_user_delete_widget);
+ mDeleteClickListener = deleteListener;
+ }
+ mUserId = userId;
+ }
+
+ @Override
+ protected void onBindView(View view) {
+ view.setClickable(true);
+ view.setFocusable(true);
+ View deleteView = view.findViewById(R.id.trash_user);
+ if (deleteView != null) {
+ deleteView.setOnClickListener(mDeleteClickListener);
+ deleteView.setTag(this);
+ }
+ super.onBindView(view);
+ }
+
+ public int getSerialNumber() {
+ if (mSerialNumber < 0) {
+ // If the userId is unknown
+ if (mUserId == USERID_UNKNOWN) return Integer.MAX_VALUE;
+ mSerialNumber = ((UserManager) getContext().getSystemService(Context.USER_SERVICE))
+ .getUserSerialNumber(mUserId);
+ if (mSerialNumber < 0) return mUserId;
+ }
+ return mSerialNumber;
+ }
+
+ public int getUserId() {
+ return mUserId;
+ }
+
+ public int compareTo(Preference another) {
+ if (another instanceof UserPreference) {
+ return getSerialNumber() > ((UserPreference) another).getSerialNumber() ? 1 : -1;
+ } else {
+ return 1;
+ }
+ }
+}
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index e530493..7369a92 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -16,52 +16,170 @@
package com.android.settings.users;
+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.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
import android.os.UserManager;
+import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceActivity;
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.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.settings.R;
import com.android.settings.SettingsPreferenceFragment;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.List;
public class UserSettings extends SettingsPreferenceFragment
- implements OnPreferenceClickListener {
+ 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 MESSAGE_UPDATE_LIST = 1;
+
+ 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 boolean mAddingUser;
+
+ private final Object mUserLock = new Object();
+ private UserManager mUserManager;
+ private boolean mProfileChanged;
+
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_UPDATE_LIST:
+ updateUserList();
+ break;
+ }
+ }
+ };
+
+ private ContentObserver mProfileObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ mProfileChanged = true;
+ }
+ };
+
+ 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.setSummary(mUserManager.getUserInfo(UserHandle.myUserId()).name);
+ loadProfile(false);
setHasOptionsMenu(true);
+ // Register to watch for profile changes
+ getActivity().getContentResolver().registerContentObserver(
+ ContactsContract.Profile.CONTENT_URI, false, mProfileObserver);
+ getActivity().registerReceiver(mUserChangeReceiver,
+ new IntentFilter(Intent.ACTION_USER_REMOVED));
}
@Override
public void onResume() {
super.onResume();
+ if (mProfileChanged) {
+ loadProfile(true);
+ mProfileChanged = false;
+ }
updateUserList();
}
@Override
+ public void onDestroy() {
+ super.onDestroy();
+ getActivity().getContentResolver().unregisterContentObserver(mProfileObserver);
+ getActivity().unregisterReceiver(mUserChangeReceiver);
+ }
+
+ @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- MenuItem addAccountItem = menu.add(0, MENU_ADD_USER, 0, R.string.user_add_user_menu);
- addAccountItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
- | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ if (UserHandle.myUserId() == UserHandle.USER_OWNER) {
+ 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
@@ -70,52 +188,270 @@
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(boolean force) {
+ UserInfo user = mUserManager.getUserInfo(UserHandle.myUserId());
+ if (force || user.iconPath == null || user.iconPath.equals("")) {
+ assignProfilePhoto(user);
+ }
+ String profileName = getProfileName();
+ mMePreference.setTitle(profileName);
+ }
+
private void onAddUserClicked() {
- ((PreferenceActivity) getActivity()).startPreferencePanel(
- UserDetailsSettings.class.getName(), null, R.string.user_details_title,
- null, this, 0);
+ 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);
+ }
+ }
+ }
+
+ @Override
+ public Dialog onCreateDialog(int dialogId) {
+ switch (dialogId) {
+ case DIALOG_CONFIRM_REMOVE:
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.user_confirm_remove_title)
+ .setMessage(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();
+ 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() {
+ // TODO:
+ Toast.makeText(getActivity(), "Not implemented yet!", Toast.LENGTH_SHORT).show();
+
+ synchronized (mUserLock) {
+ mRemovingUserId = -1;
+ }
+ }
+
+ 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);
+ }
+ }
+ }.start();
+ }
}
private void updateUserList() {
- List<UserInfo> users = ((UserManager) getActivity().getSystemService(Context.USER_SERVICE))
- .getUsers();
+ List<UserInfo> users = mUserManager.getUsers();
mUserListCategory.removeAll();
+ mUserListCategory.setOrderingAsAdded(false);
+
for (UserInfo user : users) {
- Preference pref = new Preference(getActivity());
- pref.setTitle(user.name);
- pref.setOnPreferenceClickListener(this);
- pref.setKey("id=" + user.id);
- if (user.iconPath != null) {
- setPhotoId(pref, user.iconPath);
+ Preference pref;
+ if (user.id == UserHandle.myUserId()) {
+ pref = mMePreference;
+ } 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);
}
}
- private void setPhotoId(Preference pref, String realPath) {
- Drawable d = Drawable.createFromPath(realPath);
+ /* TODO: Put this in an AsyncTask */
+ private void assignProfilePhoto(final UserInfo user) {
+ // If the contact is "me", then use my local profile photo. Otherwise, build a
+ // uri to get the avatar of the contact.
+ Uri contactUri = Profile.CONTENT_URI;
+
+ InputStream avatarDataStream = Contacts.openContactPhotoInputStream(
+ getActivity().getContentResolver(),
+ contactUri, true);
+ // If there's no profile photo, assign a default avatar
+ if (avatarDataStream == null) {
+ assignDefaultPhoto(user);
+ setPhotoId(mMePreference, user);
+ return;
+ }
+
+ ParcelFileDescriptor fd = mUserManager.setUserIcon(user.id);
+ FileOutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+ byte[] buffer = new byte[4096];
+ int readSize;
+ try {
+ while ((readSize = avatarDataStream.read(buffer)) > 0) {
+ os.write(buffer, 0, readSize);
+ }
+ os.close();
+ avatarDataStream.close();
+ } catch (IOException ioe) {
+ Log.e(TAG, "Error copying profile photo " + ioe);
+ }
+
+ setPhotoId(mMePreference, user);
+ }
+
+ private String getProfileName() {
+ Cursor cursor = getActivity().getContentResolver().query(
+ Profile.CONTENT_URI, CONTACT_PROJECTION, null, null, null);
+ if (cursor == null) {
+ Log.w(TAG, "getProfileName() returned NULL cursor!"
+ + " contact uri used " + Profile.CONTENT_URI);
+ return null;
+ }
+
+ try {
+ if (cursor.moveToFirst()) {
+ return cursor.getString(cursor.getColumnIndex(Phone.DISPLAY_NAME));
+ }
+ } finally {
+ cursor.close();
+ }
+ return null;
+ }
+
+ 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) {
- String sid = pref.getKey();
- if (sid != null && sid.startsWith("id=")) {
- int id = Integer.parseInt(sid.substring(3));
- Bundle args = new Bundle();
- args.putInt(UserDetailsSettings.EXTRA_USER_ID, id);
- ((PreferenceActivity) getActivity()).startPreferencePanel(
- UserDetailsSettings.class.getName(),
- args, 0, pref.getTitle(), this, 0);
+ if (pref == mMePreference) {
+ Intent editProfile = new Intent(Intent.ACTION_EDIT);
+ editProfile.setData(ContactsContract.Profile.CONTENT_URI);
+ 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;
}
+
}