| /* |
| * Copyright (C) 2018 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.emergency.preferences; |
| |
| import android.app.AlertDialog; |
| import android.app.Fragment; |
| import android.content.Context; |
| import android.content.DialogInterface; |
| import android.content.Intent; |
| import android.graphics.Bitmap; |
| import android.graphics.drawable.Drawable; |
| import android.os.AsyncTask; |
| import android.os.Bundle; |
| import android.os.UserHandle; |
| import android.os.UserManager; |
| import android.text.TextUtils; |
| import android.util.AttributeSet; |
| import android.view.View; |
| import android.widget.EditText; |
| import android.widget.ImageView; |
| import androidx.annotation.VisibleForTesting; |
| import androidx.preference.DialogPreference; |
| import com.android.emergency.CircleFramedDrawable; |
| import com.android.emergency.R; |
| import com.android.internal.util.UserIcons; |
| import com.android.settingslib.CustomDialogPreference; |
| |
| import java.io.File; |
| |
| /** |
| * Custom {@link DialogPreference} that allows us to editing the user name and photo. |
| */ |
| public class EmergencyNamePreference extends CustomDialogPreference { |
| |
| private static final String KEY_AWAITING_RESULT = "awaiting_result"; |
| private static final String KEY_SAVED_PHOTO = "pending_photo"; |
| |
| private UserManager mUserManager = getContext().getSystemService(UserManager.class); |
| private EditUserPhotoController mEditUserPhotoController; |
| private Fragment mFragment; |
| private Bitmap mSavedPhoto; |
| private EditText mUserNameView; |
| private ImageView mUserPhotoView; |
| private boolean mWaitingForActivityResult = false; |
| |
| public EmergencyNamePreference(Context context, AttributeSet attrs, |
| int defStyleAttr, int defStyleRes) { |
| super(context, attrs, defStyleAttr, defStyleRes); |
| setSummary(mUserManager.getUserName()); |
| setIcon(getCircularUserIcon()); |
| setDialogLayoutResource(R.layout.edit_user_info_dialog_content); |
| } |
| |
| public EmergencyNamePreference(Context context, AttributeSet attrs, int defStyleAttr) { |
| this(context, attrs, defStyleAttr, 0); |
| } |
| |
| public EmergencyNamePreference(Context context, AttributeSet attrs) { |
| this(context, attrs, androidx.preference.R.attr.dialogPreferenceStyle); |
| } |
| |
| public EmergencyNamePreference(Context context) { |
| this(context, null); |
| } |
| |
| /** |
| * Setup fragment for Dialog and EditUserPhotoController. |
| */ |
| public void setFragment(Fragment fragment) { |
| mFragment = fragment; |
| } |
| |
| /** |
| * Reload user name and photo form UserManager. |
| */ |
| public void reloadFromUserManager() { |
| setSummary(mUserManager.getUserName()); |
| setIcon(getCircularUserIcon()); |
| } |
| |
| /** |
| * Restore user photo when EditUserPhotoController had pending photo. |
| */ |
| public void onRestoreInstanceState(Bundle icicle) { |
| String pendingPhoto = icicle.getString(KEY_SAVED_PHOTO); |
| if (pendingPhoto != null) { |
| mSavedPhoto = EditUserPhotoController.loadNewUserPhotoBitmap(new File(pendingPhoto)); |
| } |
| mWaitingForActivityResult = icicle.getBoolean(KEY_AWAITING_RESULT, false); |
| } |
| |
| /** |
| * Save a temp user photo when layout need to recreating but Dialog is showing. |
| */ |
| public void onSaveInstanceState(Bundle outState) { |
| if (getDialog() != null && getDialog().isShowing() |
| && mEditUserPhotoController != null) { |
| // Bitmap cannot be stored into bundle because it may exceed parcel limit |
| // Store it in a temporary file instead |
| File file = mEditUserPhotoController.saveNewUserPhotoBitmap(); |
| if (file != null) { |
| outState.putString(KEY_SAVED_PHOTO, file.getPath()); |
| } |
| } |
| if (mWaitingForActivityResult) { |
| outState.putBoolean(KEY_AWAITING_RESULT, mWaitingForActivityResult); |
| } |
| } |
| |
| /** |
| * Set mWaitingForActivityResult to true when EmergencyNamePreferenceDialogFragment |
| * startActivityForResult, means we are waiting the activity result. |
| */ |
| public void startingActivityForResult() { |
| mWaitingForActivityResult = true; |
| } |
| |
| /** |
| * Reset mWaitingForActivityResult and send the result code to EditUserPhotoController when |
| * EmergencyNamePreferenceDialogFragment onActivityResult. |
| */ |
| public void onActivityResult(int requestCode, int resultCode, Intent data) { |
| mWaitingForActivityResult = false; |
| |
| if (getDialog() != null) { |
| mEditUserPhotoController.onActivityResult(requestCode, resultCode, data); |
| } |
| } |
| |
| @Override |
| protected void onBindDialogView(View view) { |
| super.onBindDialogView(view); |
| |
| mUserNameView = view.findViewById(R.id.user_name); |
| mUserNameView.setText(mUserManager.getUserName()); |
| mUserPhotoView = view.findViewById(R.id.user_photo); |
| Drawable drawable; |
| if (mSavedPhoto != null) { |
| drawable = CircleFramedDrawable.getInstance(getContext(), mSavedPhoto); |
| } else { |
| drawable = getCircularUserIcon(); |
| } |
| mUserPhotoView.setImageDrawable(drawable); |
| |
| mEditUserPhotoController = createEditUserPhotoController(mUserPhotoView, |
| getCircularUserIcon()); |
| } |
| |
| @Override |
| protected void onPrepareDialogBuilder(AlertDialog.Builder builder, |
| DialogInterface.OnClickListener listener) { |
| super.onPrepareDialogBuilder(builder, listener); |
| builder.setTitle(R.string.name) |
| .setCancelable(true) |
| .setPositiveButton(android.R.string.ok, listener) |
| .setNegativeButton(android.R.string.cancel, listener) |
| .create(); |
| } |
| |
| @Override |
| protected void onDialogClosed(boolean positiveResult) { |
| super.onDialogClosed(positiveResult); |
| if (positiveResult) { |
| // Update the name if changed. |
| CharSequence userName = mUserNameView.getText(); |
| if (!TextUtils.isEmpty(userName)) { |
| if (mUserManager.getUserName() == null |
| || !userName.toString().equals(mUserManager.getUserName())) { |
| mUserManager.setUserName(UserHandle.myUserId(), userName.toString()); |
| setSummary(userName); |
| } |
| } |
| // Update the photo if changed. |
| Drawable drawable = mEditUserPhotoController.getNewUserPhotoDrawable(); |
| Bitmap bitmap = mEditUserPhotoController.getNewUserPhotoBitmap(); |
| if (drawable != null && bitmap != null |
| && !drawable.equals(getCircularUserIcon())) { |
| new AsyncTask<Void, Void, Void>() { |
| @Override |
| protected Void doInBackground(Void... params) { |
| mUserManager.setUserIcon(UserHandle.myUserId(), |
| mEditUserPhotoController.getNewUserPhotoBitmap()); |
| return null; |
| } |
| }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); |
| setIcon(drawable); |
| } |
| if (mFragment != null) { |
| mFragment.getActivity().removeDialog(1); |
| } |
| } |
| clear(); |
| } |
| |
| private void clear() { |
| mEditUserPhotoController.removeNewUserPhotoBitmapFile(); |
| mSavedPhoto = null; |
| } |
| |
| private Drawable getCircularUserIcon() { |
| Bitmap bitmapUserIcon = mUserManager.getUserIcon(UserHandle.myUserId()); |
| |
| if (bitmapUserIcon == null) { |
| // get default user icon. |
| final Drawable defaultUserIcon = UserIcons.getDefaultUserIcon( |
| getContext().getResources(), UserHandle.myUserId(), false); |
| bitmapUserIcon = UserIcons.convertToBitmap(defaultUserIcon); |
| } |
| Drawable drawableUserIcon = new CircleFramedDrawable(bitmapUserIcon, |
| (int) getContext().getResources().getDimension(R.dimen.circle_avatar_size)); |
| |
| return drawableUserIcon; |
| } |
| |
| @VisibleForTesting |
| EditUserPhotoController createEditUserPhotoController(ImageView userPhotoView, |
| Drawable drawable) { |
| return new EditUserPhotoController(mFragment, userPhotoView, |
| mSavedPhoto, drawable, mWaitingForActivityResult); |
| } |
| |
| public static class EmergencyNamePreferenceDialogFragment extends |
| CustomPreferenceDialogFragment { |
| |
| public static CustomDialogPreference.CustomPreferenceDialogFragment newInstance( |
| String key) { |
| final CustomDialogPreference.CustomPreferenceDialogFragment |
| fragment = new EmergencyNamePreferenceDialogFragment(); |
| final Bundle b = new Bundle(1 /* capacity */); |
| b.putString(ARG_KEY, key); |
| fragment.setArguments(b); |
| return fragment; |
| } |
| |
| private EmergencyNamePreference getEmergencyNamePreference() { |
| return (EmergencyNamePreference) getPreference(); |
| } |
| |
| @Override |
| public void onCreate(Bundle icicle) { |
| super.onCreate(icicle); |
| getEmergencyNamePreference().setFragment(this); |
| if (icicle != null) { |
| getEmergencyNamePreference().onRestoreInstanceState(icicle); |
| } |
| } |
| |
| @Override |
| public void onSaveInstanceState(Bundle outState) { |
| super.onSaveInstanceState(outState); |
| getEmergencyNamePreference().onSaveInstanceState(outState); |
| } |
| |
| @Override |
| public void onActivityResult(int requestCode, int resultCode, Intent data) { |
| getEmergencyNamePreference().onActivityResult(requestCode, resultCode, data); |
| } |
| |
| @Override |
| public void startActivityForResult(Intent intent, int requestCode) { |
| getEmergencyNamePreference().startingActivityForResult(); |
| super.startActivityForResult(intent, requestCode); |
| } |
| } |
| } |