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