Merge "Reduce jank in QuickContactActivity dismissal."
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index 04abbe2..b9f1afc 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -942,9 +942,7 @@
 
         // If we just started creating a new contact and haven't added any data, it's too
         // early to do a join
-        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
-        if (mState.size() == 1 && mState.get(0).isContactInsert()
-                && !EntityModifier.hasChanges(mState, accountTypes)) {
+        if (mState.size() == 1 && mState.get(0).isContactInsert() && !hasPendingChanges()) {
             Toast.makeText(getActivity(), R.string.toast_join_with_empty_contact,
                             Toast.LENGTH_LONG).show();
             return true;
@@ -962,6 +960,15 @@
     }
 
     /**
+     * Return true if there are any edits to the current contact which need to
+     * be saved.
+     */
+    private boolean hasPendingChanges() {
+        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
+        return EntityModifier.hasChanges(mState, accountTypes);
+    }
+
+    /**
      * Saves or creates the contact based on the mode, and if successful
      * finishes the activity.
      */
@@ -977,8 +984,7 @@
 
         mStatus = Status.SAVING;
 
-        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
-        if (!EntityModifier.hasChanges(mState, accountTypes)) {
+        if (!hasPendingChanges()) {
             if (mLookupUri == null && saveMode == SaveMode.RELOAD) {
                 // We don't have anything to save and there isn't even an existing contact yet.
                 // Nothing to do, simply go back to editing mode
@@ -1031,8 +1037,7 @@
     }
 
     private boolean revert() {
-        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
-        if (mState == null || !EntityModifier.hasChanges(mState, accountTypes)) {
+        if (mState == null || !hasPendingChanges()) {
             doRevertAction();
         } else {
             CancelEditDialogFragment.show(this);
diff --git a/src/com/android/contacts/editor/PhotoEditorView.java b/src/com/android/contacts/editor/PhotoEditorView.java
index d2e4340..8a0dd0e 100644
--- a/src/com/android/contacts/editor/PhotoEditorView.java
+++ b/src/com/android/contacts/editor/PhotoEditorView.java
@@ -20,6 +20,7 @@
 import com.android.contacts.model.DataKind;
 import com.android.contacts.model.EntityDelta;
 import com.android.contacts.model.EntityDelta.ValuesDelta;
+import com.android.contacts.ContactsUtils;
 
 import android.content.Context;
 import android.graphics.Bitmap;
@@ -127,6 +128,24 @@
     }
 
     /**
+     * Creates a byte[] containing the PNG-compressed bitmap, or null if
+     * something goes wrong.
+     */
+    private static byte[] compressBitmap(Bitmap bitmap) {
+        final int size = bitmap.getWidth() * bitmap.getHeight() * 4;
+        final ByteArrayOutputStream out = new ByteArrayOutputStream(size);
+        try {
+            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
+            out.flush();
+            out.close();
+            return out.toByteArray();
+        } catch (IOException e) {
+            Log.w(TAG, "Unable to serialize photo: " + e.toString());
+            return null;
+        }
+    }
+
+    /**
      * Assign the given {@link Bitmap} as the new value, updating UI and
      * readying for persisting through {@link ValuesDelta}.
      */
@@ -145,6 +164,16 @@
 
         // When the user chooses a new photo mark it as super primary
         mEntry.put(Photo.IS_SUPER_PRIMARY, 1);
+
+        // Even though high-res photos cannot be saved by passing them via
+        // an EntityDeltaList (since they cause the Bundle size limit to be
+        // exceeded), we still pass a low-res thumbnail. This simplifies
+        // code all over the place, because we don't have to test whether
+        // there is a change in EITHER the delta-list OR a changed photo...
+        // this way, there is always a change in the delta-list.
+        final int size = ContactsUtils.getThumbnailSize(getContext());
+        byte[] compressed = compressBitmap(Bitmap.createScaledBitmap(photo, size, size, false));
+        if (compressed != null) mEntry.put(Photo.PHOTO, compressed);
     }
 
     /**