Avoid transcoding in MediaPlayers

Test: Manual
Bug: 158466177
Change-Id: I71776e1e81002b1505f5094c92fdd10706d1268e
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index f9cbdd4..44890be 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -31,6 +31,8 @@
 import android.content.res.AssetManager;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.os.FileUtils;
+import android.os.SystemProperties;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
@@ -1523,6 +1525,11 @@
         if (fileDescriptor == null) {
             throw new NullPointerException("fileDescriptor cannot be null");
         }
+        boolean optimize = SystemProperties.getBoolean("fuse.sys.transcode_exif_optimize", false);
+        FileDescriptor modernFd = optimize ? FileUtils.convertToModernFd(fileDescriptor) : null;
+        if (modernFd != null) {
+            fileDescriptor = modernFd;
+        }
 
         mAssetInputStream = null;
         mFilename = null;
@@ -2533,11 +2540,20 @@
 
     private void initForFilename(String filename) throws IOException {
         FileInputStream in = null;
+        FileInputStream legacyInputStream = null;
         mAssetInputStream = null;
         mFilename = filename;
         mIsInputStream = false;
         try {
             in = new FileInputStream(filename);
+            boolean optimize = SystemProperties.getBoolean("fuse.sys.transcode_exif_optimize",
+                    false);
+            FileDescriptor modernFd = optimize ? FileUtils.convertToModernFd(in.getFD()) : null;
+            if (modernFd != null) {
+                legacyInputStream = in;
+                in = new FileInputStream(modernFd);
+            }
+
             if (isSeekableFD(in.getFD())) {
                 mSeekableFileDescriptor = in.getFD();
             } else {
@@ -2546,6 +2562,7 @@
             loadAttributes(in);
         } finally {
             closeQuietly(in);
+            closeQuietly(legacyInputStream);
         }
     }
 
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 835a709..ca8b9b9 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -30,7 +30,10 @@
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Build;
+import android.os.Bundle;
+import android.os.FileUtils;
 import android.os.IBinder;
+import android.os.SystemProperties;
 import android.text.TextUtils;
 
 import java.io.FileDescriptor;
@@ -48,7 +51,6 @@
  * frame and meta data from an input media file.
  */
 public class MediaMetadataRetriever implements AutoCloseable {
-
     // borrowed from ExoPlayer
     private static final String[] STANDARD_GENRES = new String[] {
             // These are the official ID3v1 genres.
@@ -296,7 +298,19 @@
      * non-negative.
      * @throws IllegalArgumentException if the arguments are invalid
      */
-    public native void setDataSource(FileDescriptor fd, long offset, long length)
+    public void setDataSource(FileDescriptor fd, long offset, long length)
+            throws IllegalArgumentException  {
+        boolean optimize = SystemProperties.getBoolean("fuse.sys.transcode_retriever_optimize",
+                false);
+        FileDescriptor modernFd = optimize ? FileUtils.convertToModernFd(fd) : null;
+        if (modernFd == null) {
+            _setDataSource(fd, offset, length);
+        } else {
+            _setDataSource(modernFd, offset, length);
+        }
+    }
+
+    private native void _setDataSource(FileDescriptor fd, long offset, long length)
             throws IllegalArgumentException;
 
     /**
@@ -340,7 +354,12 @@
         try {
             ContentResolver resolver = context.getContentResolver();
             try {
-                fd = resolver.openAssetFileDescriptor(uri, "r");
+                boolean optimize =
+                        SystemProperties.getBoolean("fuse.sys.transcode_retriever_optimize", false);
+                Bundle opts = new Bundle();
+                opts.putBoolean("android.provider.extra.ACCEPT_ORIGINAL_MEDIA_FORMAT", true);
+                fd = optimize ? resolver.openTypedAssetFileDescriptor(uri, "*/*", opts)
+                        : resolver.openAssetFileDescriptor(uri, "r");
             } catch(FileNotFoundException e) {
                 throw new IllegalArgumentException("could not access " + uri);
             }
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 851c1ec..47d276a 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -31,6 +31,8 @@
 import android.media.SubtitleController.Anchor;
 import android.media.SubtitleTrack.RenderingWidget;
 import android.net.Uri;
+import android.os.Bundle;
+import android.os.FileUtils;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -1104,7 +1106,13 @@
     }
 
     private boolean attemptDataSource(ContentResolver resolver, Uri uri) {
-        try (AssetFileDescriptor afd = resolver.openAssetFileDescriptor(uri, "r")) {
+        boolean optimize = SystemProperties.getBoolean("fuse.sys.transcode_player_optimize",
+                false);
+        Bundle opts = new Bundle();
+        opts.putBoolean("android.provider.extra.ACCEPT_ORIGINAL_MEDIA_FORMAT", true);
+        try (AssetFileDescriptor afd = optimize
+                ? resolver.openTypedAssetFileDescriptor(uri, "*/*", opts)
+                : resolver.openAssetFileDescriptor(uri, "r")) {
             setDataSource(afd);
             return true;
         } catch (NullPointerException | SecurityException | IOException ex) {
@@ -1245,7 +1253,13 @@
      */
     public void setDataSource(FileDescriptor fd, long offset, long length)
             throws IOException, IllegalArgumentException, IllegalStateException {
-        _setDataSource(fd, offset, length);
+        boolean optimize = SystemProperties.getBoolean("fuse.sys.transcode_player_optimize", false);
+        FileDescriptor modernFd = optimize ? FileUtils.convertToModernFd(fd) : null;
+        if (modernFd == null) {
+            _setDataSource(fd, offset, length);
+        } else {
+            _setDataSource(modernFd, offset, length);
+        }
     }
 
     private native void _setDataSource(FileDescriptor fd, long offset, long length)
@@ -2899,8 +2913,13 @@
 
         AssetFileDescriptor fd = null;
         try {
+            boolean optimize = SystemProperties.getBoolean("fuse.sys.transcode_player_optimize",
+                    false);
             ContentResolver resolver = context.getContentResolver();
-            fd = resolver.openAssetFileDescriptor(uri, "r");
+            Bundle opts = new Bundle();
+            opts.putBoolean("android.provider.extra.ACCEPT_ORIGINAL_MEDIA_FORMAT", true);
+            fd = optimize ? resolver.openTypedAssetFileDescriptor(uri, "*/*", opts)
+                    : resolver.openAssetFileDescriptor(uri, "r");
             if (fd == null) {
                 return;
             }
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 6fbd29c..126897a 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -704,7 +704,7 @@
             (void *)android_media_MediaMetadataRetriever_setDataSourceAndHeaders
         },
 
-        {"setDataSource",   "(Ljava/io/FileDescriptor;JJ)V",
+        {"_setDataSource",   "(Ljava/io/FileDescriptor;JJ)V",
                 (void *)android_media_MediaMetadataRetriever_setDataSourceFD},
         {"_setDataSource",   "(Landroid/media/MediaDataSource;)V",
                 (void *)android_media_MediaMetadataRetriever_setDataSourceCallback},