Do not store bitmap into Bundle in onSaveInstanceState

It may cause TransactionTooLargeException because of the parcel size limit

Bug: 27990767
Change-Id: Ie1a702810a5c26e25fc485ebae09dc65e2b48e41
diff --git a/src/com/android/settings/users/EditUserInfoController.java b/src/com/android/settings/users/EditUserInfoController.java
index a4c07bd..315ebcb 100644
--- a/src/com/android/settings/users/EditUserInfoController.java
+++ b/src/com/android/settings/users/EditUserInfoController.java
@@ -40,6 +40,8 @@
 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 void clear() {
+        mEditUserPhotoController.removeNewUserPhotoBitmapFile();
         mEditUserInfoDialog = null;
         mSavedPhoto = null;
     }
@@ -70,19 +73,25 @@
     }
 
     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 0d327a0..01b553c 100644
--- a/src/com/android/settings/users/EditUserPhotoController.java
+++ b/src/com/android/settings/users/EditUserPhotoController.java
@@ -50,8 +50,10 @@
 
 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 @@
 
     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 @@
         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 {