From 7a5e897db05536db273385c62d57f2deffded734 Mon Sep 17 00:00:00 2001 From: Fyodor Kupolov Date: Tue, 5 Apr 2016 10:46:20 -0700 Subject: [PATCH] Do not store bitmap into Bundle in onSaveInstanceState It may cause TransactionTooLargeException because of the parcel size limit Bug: 27990767 Change-Id: Ie1a702810a5c26e25fc485ebae09dc65e2b48e41 --- .../users/EditUserInfoController.java | 19 ++++++++--- .../users/EditUserPhotoController.java | 33 +++++++++++++++++-- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/com/android/settings/users/EditUserInfoController.java b/src/com/android/settings/users/EditUserInfoController.java index a4c07bdecf4..315ebcb4adc 100644 --- a/src/com/android/settings/users/EditUserInfoController.java +++ b/src/com/android/settings/users/EditUserInfoController.java @@ -40,6 +40,8 @@ import com.android.settings.R; import com.android.settingslib.Utils; import com.android.settingslib.drawable.CircleFramedDrawable; +import java.io.File; + /** * This class encapsulates a Dialog for editing the user nickname and photo. */ @@ -61,6 +63,7 @@ public class EditUserInfoController { } public void clear() { + mEditUserPhotoController.removeNewUserPhotoBitmapFile(); mEditUserInfoDialog = null; mSavedPhoto = null; } @@ -70,19 +73,25 @@ public class EditUserInfoController { } public void onRestoreInstanceState(Bundle icicle) { - mSavedPhoto = (Bitmap) icicle.getParcelable(KEY_SAVED_PHOTO); + String pendingPhoto = icicle.getString(KEY_SAVED_PHOTO); + if (pendingPhoto != null) { + mSavedPhoto = EditUserPhotoController.loadNewUserPhotoBitmap(new File(pendingPhoto)); + } mWaitingForActivityResult = icicle.getBoolean(KEY_AWAITING_RESULT, false); } public void onSaveInstanceState(Bundle outState) { if (mEditUserInfoDialog != null && mEditUserInfoDialog.isShowing() && mEditUserPhotoController != null) { - outState.putParcelable(KEY_SAVED_PHOTO, - mEditUserPhotoController.getNewUserPhotoBitmap()); + // 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); + outState.putBoolean(KEY_AWAITING_RESULT, mWaitingForActivityResult); } } diff --git a/src/com/android/settings/users/EditUserPhotoController.java b/src/com/android/settings/users/EditUserPhotoController.java index 0d327a00ee5..01b553c9493 100644 --- a/src/com/android/settings/users/EditUserPhotoController.java +++ b/src/com/android/settings/users/EditUserPhotoController.java @@ -50,8 +50,10 @@ import com.android.settingslib.drawable.CircleFramedDrawable; import java.io.File; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.util.ArrayList; import java.util.List; @@ -69,6 +71,7 @@ public class EditUserPhotoController { private static final String CROP_PICTURE_FILE_NAME = "CropEditUserPhoto.jpg"; private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto2.jpg"; + private static final String NEW_USER_PHOTO_FILE_NAME = "NewUserPhoto.png"; private final int mPhotoSize; @@ -329,9 +332,33 @@ public class EditUserPhotoController { if (purge) { fullPath.delete(); } - final Uri fileUri = - FileProvider.getUriForFile(context, RestrictedProfileSettings.FILE_PROVIDER_AUTHORITY, fullPath); - return fileUri; + return FileProvider.getUriForFile(context, + RestrictedProfileSettings.FILE_PROVIDER_AUTHORITY, fullPath); + } + + File saveNewUserPhotoBitmap() { + if (mNewUserPhotoBitmap == null) { + return null; + } + try { + File file = new File(mContext.getCacheDir(), NEW_USER_PHOTO_FILE_NAME); + OutputStream os = new FileOutputStream(file); + mNewUserPhotoBitmap.compress(Bitmap.CompressFormat.PNG, 100, os); + os.flush(); + os.close(); + return file; + } catch (IOException e) { + Log.e(TAG, "Cannot create temp file", e); + } + return null; + } + + static Bitmap loadNewUserPhotoBitmap(File file) { + return BitmapFactory.decodeFile(file.getAbsolutePath()); + } + + void removeNewUserPhotoBitmapFile() { + new File(mContext.getCacheDir(), NEW_USER_PHOTO_FILE_NAME).delete(); } private static final class AdapterItem {