Rotation Exif data is no longer lost when reducing size of cc images.

BitmapFactory.createBitmap doesn't carry-over image exif data. We now
hold onto exif data and reapply it through matrix transformations so
images are displayed properly.

Test: TH

PiperOrigin-RevId: 159492684
Change-Id: Ief58f5fc506214e4a6afaf36a1be7dd53c712d4d
diff --git a/java/com/android/dialer/callcomposer/CopyAndResizeImageWorker.java b/java/com/android/dialer/callcomposer/CopyAndResizeImageWorker.java
index aeb8e03..725cea7 100644
--- a/java/com/android/dialer/callcomposer/CopyAndResizeImageWorker.java
+++ b/java/com/android/dialer/callcomposer/CopyAndResizeImageWorker.java
@@ -21,6 +21,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.CompressFormat;
 import android.graphics.BitmapFactory;
+import android.media.ExifInterface;
 import android.net.Uri;
 import android.os.Build.VERSION_CODES;
 import android.support.annotation.NonNull;
@@ -47,17 +48,26 @@
   }
 
   /**
-   * @param input The input Uri is expected to be a image openable by {@link
-   *     android.content.ContentResolver#openInputStream(Uri)}.
+   * @param input The filepath where the image is located.
    * @return a Pair where the File contains the resized image, and the String is the result File's
    *     MIME type.
    */
   @Nullable
   @Override
   public Pair<File, String> doInBackground(@Nullable Uri input) throws Throwable {
+    // BitmapFactory.decodeStream strips exif data, so we need to save it here and apply it later.
+    int rotation = 0;
+    try {
+      rotation =
+          new ExifInterface(input.getPath())
+              .getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
+    } catch (Exception ignored) {
+      // Couldn't get exif tags, not the end of the world
+    }
+
     try (InputStream inputStream = context.getContentResolver().openInputStream(input)) {
       Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
-      bitmap = BitmapResizer.resizeForEnrichedCalling(bitmap);
+      bitmap = BitmapResizer.resizeForEnrichedCalling(bitmap, exifToDegrees(rotation));
 
       File outputFile = DialerUtils.createShareableFile(context);
       try (OutputStream outputStream = new FileOutputStream(outputFile)) {
@@ -67,4 +77,17 @@
       }
     }
   }
+
+  private static int exifToDegrees(int exifOrientation) {
+    switch (exifOrientation) {
+      case ExifInterface.ORIENTATION_ROTATE_90:
+        return 90;
+      case ExifInterface.ORIENTATION_ROTATE_180:
+        return 180;
+      case ExifInterface.ORIENTATION_ROTATE_270:
+        return 270;
+      default:
+        return 0;
+    }
+  }
 }
diff --git a/java/com/android/dialer/callcomposer/camera/ImagePersistTask.java b/java/com/android/dialer/callcomposer/camera/ImagePersistTask.java
index 7cb6921..8620701 100644
--- a/java/com/android/dialer/callcomposer/camera/ImagePersistTask.java
+++ b/java/com/android/dialer/callcomposer/camera/ImagePersistTask.java
@@ -20,7 +20,6 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
 import android.net.Uri;
 import android.os.Build.VERSION_CODES;
 import android.support.v4.content.FileProvider;
@@ -119,13 +118,9 @@
     mWidth = clippedWidth;
     mHeight = clippedHeight;
 
-    Matrix matrix = new Matrix();
-    matrix.postRotate(params.rotation);
-
     Bitmap clippedBitmap =
-        Bitmap.createBitmap(
-            bitmap, offsetLeft, offsetTop, clippedWidth, clippedHeight, matrix, true);
-    clippedBitmap = BitmapResizer.resizeForEnrichedCalling(clippedBitmap);
+        Bitmap.createBitmap(bitmap, offsetLeft, offsetTop, clippedWidth, clippedHeight);
+    clippedBitmap = BitmapResizer.resizeForEnrichedCalling(clippedBitmap, params.rotation);
     // EXIF data can take a big chunk of the file size and we've already manually rotated our image,
     // so remove all of the exif data.
     exifInterface.clearExif();
diff --git a/java/com/android/dialer/callcomposer/util/BitmapResizer.java b/java/com/android/dialer/callcomposer/util/BitmapResizer.java
index 658462d..84ada51 100644
--- a/java/com/android/dialer/callcomposer/util/BitmapResizer.java
+++ b/java/com/android/dialer/callcomposer/util/BitmapResizer.java
@@ -17,6 +17,7 @@
 package com.android.dialer.callcomposer.util;
 
 import android.graphics.Bitmap;
+import android.graphics.Matrix;
 import android.support.annotation.VisibleForTesting;
 import com.android.dialer.common.Assert;
 import com.android.dialer.common.LogUtil;
@@ -28,40 +29,44 @@
   /**
    * Returns a bitmap that is a resized version of the parameter image. The image will only be
    * resized down and sized to be appropriate for an enriched call.
+   *
+   * @param image to be resized
+   * @param rotation degrees to rotate the image clockwise
+   * @return resized image
    */
-  public static Bitmap resizeForEnrichedCalling(Bitmap image) {
+  public static Bitmap resizeForEnrichedCalling(Bitmap image, int rotation) {
     Assert.isWorkerThread();
 
     int width = image.getWidth();
     int height = image.getHeight();
 
+    Matrix matrix = new Matrix();
+    matrix.postRotate(rotation);
+
     LogUtil.i(
         "BitmapResizer.resizeForEnrichedCalling", "starting height: %d, width: %d", height, width);
 
     if (width <= MAX_OUTPUT_RESOLUTION && height <= MAX_OUTPUT_RESOLUTION) {
       LogUtil.i("BitmapResizer.resizeForEnrichedCalling", "no resizing needed");
-      return image;
+      return Bitmap.createBitmap(image, 0, 0, width, height, matrix, true);
     }
 
+    float ratio = 1;
     if (width > height) {
       // landscape
-      float ratio = width / (float) MAX_OUTPUT_RESOLUTION;
-      width = MAX_OUTPUT_RESOLUTION;
-      height = (int) (height / ratio);
-    } else if (height > width) {
-      // portrait
-      float ratio = height / (float) MAX_OUTPUT_RESOLUTION;
-      height = MAX_OUTPUT_RESOLUTION;
-      width = (int) (width / ratio);
+      ratio = MAX_OUTPUT_RESOLUTION / (float) width;
     } else {
-      // square
-      height = MAX_OUTPUT_RESOLUTION;
-      width = MAX_OUTPUT_RESOLUTION;
+      // portrait & square
+      ratio = MAX_OUTPUT_RESOLUTION / (float) height;
     }
 
     LogUtil.i(
-        "BitmapResizer.resizeForEnrichedCalling", "ending height: %d, width: %d", height, width);
+        "BitmapResizer.resizeForEnrichedCalling",
+        "ending height: %f, width: %f",
+        height * ratio,
+        width * ratio);
 
-    return Bitmap.createScaledBitmap(image, width, height, true);
+    matrix.postScale(ratio, ratio);
+    return Bitmap.createBitmap(image, 0, 0, width, height, matrix, true);
   }
 }