1ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani/* 2ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani * Copyright (C) 2013 The Android Open Source Project 3ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani * 4ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani * Licensed under the Apache License, Version 2.0 (the "License"); 5ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani * you may not use this file except in compliance with the License. 6ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani * You may obtain a copy of the License at 7ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani * 8ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani * http://www.apache.org/licenses/LICENSE-2.0 9ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani * 10ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani * Unless required by applicable law or agreed to in writing, software 11ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani * distributed under the License is distributed on an "AS IS" BASIS, 12ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani * See the License for the specific language governing permissions and 14ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani * limitations under the License. 15ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani */ 16ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 17ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasanipackage com.android.settings.users; 18ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 19ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.app.Activity; 20ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.app.AlertDialog; 21ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.app.Dialog; 22ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.app.Fragment; 23ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.content.DialogInterface; 24ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.content.Intent; 25ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.content.pm.UserInfo; 26ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.graphics.Bitmap; 27ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.graphics.drawable.Drawable; 28ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.os.AsyncTask; 29ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.os.Bundle; 30ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.os.UserHandle; 31ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.os.UserManager; 32ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.text.TextUtils; 33ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.view.LayoutInflater; 34ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.view.View; 35ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.view.WindowManager; 36ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.widget.EditText; 37ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport android.widget.ImageView; 38ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 39ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasaniimport com.android.settings.R; 406e58d516f05bbceabdddd3aa08a94fcc32858e71Wei Liuimport com.android.settingslib.Utils; 416e58d516f05bbceabdddd3aa08a94fcc32858e71Wei Liuimport com.android.settingslib.drawable.CircleFramedDrawable; 42ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 437a5e897db05536db273385c62d57f2deffded734Fyodor Kupolovimport java.io.File; 447a5e897db05536db273385c62d57f2deffded734Fyodor Kupolov 45247520c369370885a1c085e53ee679dce0fd55ceAmith Yamasani/** 46247520c369370885a1c085e53ee679dce0fd55ceAmith Yamasani * This class encapsulates a Dialog for editing the user nickname and photo. 47247520c369370885a1c085e53ee679dce0fd55ceAmith Yamasani */ 48ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasanipublic class EditUserInfoController { 49247520c369370885a1c085e53ee679dce0fd55ceAmith Yamasani 50247520c369370885a1c085e53ee679dce0fd55ceAmith Yamasani private static final String KEY_AWAITING_RESULT = "awaiting_result"; 51247520c369370885a1c085e53ee679dce0fd55ceAmith Yamasani private static final String KEY_SAVED_PHOTO = "pending_photo"; 52247520c369370885a1c085e53ee679dce0fd55ceAmith Yamasani 53ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani private Dialog mEditUserInfoDialog; 54ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani private Bitmap mSavedPhoto; 55ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani private EditUserPhotoController mEditUserPhotoController; 56ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani private UserHandle mUser; 57ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani private UserManager mUserManager; 58ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani private boolean mWaitingForActivityResult = false; 59ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 60ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani public interface OnContentChangedCallback { 61ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani public void onPhotoChanged(Drawable photo); 62ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani public void onLabelChanged(CharSequence label); 63ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 64ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 65ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani public void clear() { 667a5e897db05536db273385c62d57f2deffded734Fyodor Kupolov mEditUserPhotoController.removeNewUserPhotoBitmapFile(); 67ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani mEditUserInfoDialog = null; 68ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani mSavedPhoto = null; 69ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 70ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 71ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani public Dialog getDialog() { 72ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani return mEditUserInfoDialog; 73ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 74ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 75ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani public void onRestoreInstanceState(Bundle icicle) { 767a5e897db05536db273385c62d57f2deffded734Fyodor Kupolov String pendingPhoto = icicle.getString(KEY_SAVED_PHOTO); 777a5e897db05536db273385c62d57f2deffded734Fyodor Kupolov if (pendingPhoto != null) { 787a5e897db05536db273385c62d57f2deffded734Fyodor Kupolov mSavedPhoto = EditUserPhotoController.loadNewUserPhotoBitmap(new File(pendingPhoto)); 797a5e897db05536db273385c62d57f2deffded734Fyodor Kupolov } 80247520c369370885a1c085e53ee679dce0fd55ceAmith Yamasani mWaitingForActivityResult = icicle.getBoolean(KEY_AWAITING_RESULT, false); 81ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 82ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 83ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani public void onSaveInstanceState(Bundle outState) { 84ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani if (mEditUserInfoDialog != null && mEditUserInfoDialog.isShowing() 85ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani && mEditUserPhotoController != null) { 867a5e897db05536db273385c62d57f2deffded734Fyodor Kupolov // Bitmap cannot be stored into bundle because it may exceed parcel limit 877a5e897db05536db273385c62d57f2deffded734Fyodor Kupolov // Store it in a temporary file instead 887a5e897db05536db273385c62d57f2deffded734Fyodor Kupolov File file = mEditUserPhotoController.saveNewUserPhotoBitmap(); 897a5e897db05536db273385c62d57f2deffded734Fyodor Kupolov if (file != null) { 907a5e897db05536db273385c62d57f2deffded734Fyodor Kupolov outState.putString(KEY_SAVED_PHOTO, file.getPath()); 917a5e897db05536db273385c62d57f2deffded734Fyodor Kupolov } 92ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 93ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani if (mWaitingForActivityResult) { 947a5e897db05536db273385c62d57f2deffded734Fyodor Kupolov outState.putBoolean(KEY_AWAITING_RESULT, mWaitingForActivityResult); 95ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 96ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 97ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 98ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani public void startingActivityForResult() { 99ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani mWaitingForActivityResult = true; 100ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 101ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 102ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani public void onActivityResult(int requestCode, int resultCode, Intent data) { 103ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani mWaitingForActivityResult = false; 104ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 105ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani if (mEditUserInfoDialog != null && mEditUserInfoDialog.isShowing() 106ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani && mEditUserPhotoController.onActivityResult(requestCode, resultCode, data)) { 107ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani return; 108ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 109ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 110ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 111ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani public Dialog createDialog(final Fragment fragment, final Drawable currentUserIcon, 112ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani final CharSequence currentUserName, 113ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani int titleResId, final OnContentChangedCallback callback, UserHandle user) { 114ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani Activity activity = fragment.getActivity(); 115ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani mUser = user; 116ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani if (mUserManager == null) { 117ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani mUserManager = UserManager.get(activity); 118ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 119ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani LayoutInflater inflater = activity.getLayoutInflater(); 120ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani View content = inflater.inflate(R.layout.edit_user_info_dialog_content, null); 121ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 122ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani UserInfo info = mUserManager.getUserInfo(mUser.getIdentifier()); 123ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 124ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani final EditText userNameView = (EditText) content.findViewById(R.id.user_name); 125ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani userNameView.setText(info.name); 126ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 127ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani final ImageView userPhotoView = (ImageView) content.findViewById(R.id.user_photo); 128ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani Drawable drawable = null; 129ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani if (mSavedPhoto != null) { 13095b86a5488a27d95bda8b6db1f608d6ce55dae8aAlexandra Gherghina drawable = CircleFramedDrawable.getInstance(activity, mSavedPhoto); 131ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } else { 132ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani drawable = currentUserIcon; 133ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani if (drawable == null) { 134d7cadf3de2cf8272e817a416549fc2d47852f3b9Zoltan Szatmary-Ban drawable = Utils.getUserIcon(activity, mUserManager, info); 135ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 136ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 137ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani userPhotoView.setImageDrawable(drawable); 138ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani mEditUserPhotoController = new EditUserPhotoController(fragment, userPhotoView, 139ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani mSavedPhoto, drawable, mWaitingForActivityResult); 140ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani mEditUserInfoDialog = new AlertDialog.Builder(activity) 141ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani .setTitle(R.string.profile_info_settings_title) 142ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani .setView(content) 143ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani .setCancelable(true) 144ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 145ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani @Override 146ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani public void onClick(DialogInterface dialog, int which) { 147ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani if (which == DialogInterface.BUTTON_POSITIVE) { 148ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani // Update the name if changed. 149ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani CharSequence userName = userNameView.getText(); 150ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani if (!TextUtils.isEmpty(userName)) { 151ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani if (currentUserName == null 152ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani || !userName.toString().equals(currentUserName.toString())) { 153ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani if (callback != null) { 154ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani callback.onLabelChanged(userName.toString()); 155ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 156ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani mUserManager.setUserName(mUser.getIdentifier(), 157ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani userName.toString()); 158ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 159ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 160ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani // Update the photo if changed. 161ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani Drawable drawable = mEditUserPhotoController.getNewUserPhotoDrawable(); 162ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani Bitmap bitmap = mEditUserPhotoController.getNewUserPhotoBitmap(); 163ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani if (drawable != null && bitmap != null 164ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani && !drawable.equals(currentUserIcon)) { 165ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani if (callback != null) { 166ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani callback.onPhotoChanged(drawable); 167ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 168ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani new AsyncTask<Void, Void, Void>() { 169ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani @Override 170ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani protected Void doInBackground(Void... params) { 171ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani mUserManager.setUserIcon(mUser.getIdentifier(), 172ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani mEditUserPhotoController.getNewUserPhotoBitmap()); 173ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani return null; 174ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 175ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); 176ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 177ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani fragment.getActivity().removeDialog( 178ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani RestrictedProfileSettings.DIALOG_ID_EDIT_USER_INFO); 179ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 180ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani clear(); 181ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 182ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani }) 183ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { 184ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani @Override 185ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani public void onClick(DialogInterface dialog, int which) { 186ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani clear(); 187ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 188ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani }) 189ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani .create(); 190ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 191ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani // Make sure the IME is up. 192ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani mEditUserInfoDialog.getWindow().setSoftInputMode( 193ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); 194ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani 195ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani return mEditUserInfoDialog; 196ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani } 197ee3987475e1d29e8355bdb9e068149eb01e3fd43Amith Yamasani} 198