summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/FileUtils.java56
-rw-r--r--media/java/android/media/ExifInterface.java17
-rw-r--r--media/java/android/media/MediaMetadataRetriever.java25
-rw-r--r--media/java/android/media/MediaPlayer.java25
-rw-r--r--media/jni/android_media_MediaMetadataRetriever.cpp2
5 files changed, 118 insertions, 7 deletions
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 70c924a46c17..bbafc7b0875a 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -40,9 +40,16 @@ import static android.system.OsConstants.W_OK;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
+import android.app.AppGlobals;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.res.AssetFileDescriptor;
+import android.net.Uri;
import android.provider.DocumentsContract.Document;
+import android.provider.MediaStore;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructStat;
@@ -118,6 +125,7 @@ public final class FileUtils {
// non-final so it can be toggled by Robolectric's ShadowFileUtils
private static boolean sEnableCopyOptimizations = true;
+ private static volatile int sMediaProviderAppId = -1;
private static final long COPY_CHECKPOINT_BYTES = 524288;
@@ -1425,6 +1433,54 @@ public final class FileUtils {
}
/** {@hide} */
+ public static FileDescriptor convertToModernFd(FileDescriptor fd) {
+ try {
+ Context context = AppGlobals.getInitialApplication();
+ if (UserHandle.getAppId(Process.myUid()) == getMediaProviderAppId(context)) {
+ // Never convert modern fd for MediaProvider, because this requires
+ // MediaStore#scanFile and can cause infinite loops when MediaProvider scans
+ return null;
+ }
+ File realFile = ParcelFileDescriptor.getFile(fd);
+ Log.i(TAG, "Changing to modern format dataSource for: " + realFile);
+ ContentResolver resolver = context.getContentResolver();
+
+ Uri uri = MediaStore.scanFile(resolver, realFile);
+ if (uri != null) {
+ Bundle opts = new Bundle();
+ // TODO(b/158465539): Use API constant
+ opts.putBoolean("android.provider.extra.ACCEPT_ORIGINAL_MEDIA_FORMAT", true);
+ AssetFileDescriptor afd = resolver.openTypedAssetFileDescriptor(uri, "*/*", opts);
+ Log.i(TAG, "Changed to modern format dataSource for: " + realFile);
+ return afd.getFileDescriptor();
+ } else {
+ Log.i(TAG, "Failed to change to modern format dataSource for: " + realFile);
+ }
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to change to modern format dataSource");
+ }
+ return null;
+ }
+
+ private static int getMediaProviderAppId(Context context) {
+ if (sMediaProviderAppId != -1) {
+ return sMediaProviderAppId;
+ }
+
+ PackageManager pm = context.getPackageManager();
+ ProviderInfo provider = context.getPackageManager().resolveContentProvider(
+ MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.MATCH_SYSTEM_ONLY);
+ if (provider == null) {
+ return -1;
+ }
+
+ sMediaProviderAppId = UserHandle.getAppId(provider.applicationInfo.uid);
+ return sMediaProviderAppId;
+ }
+
+ /** {@hide} */
@VisibleForTesting
public static class MemoryPipe extends Thread implements AutoCloseable {
private final FileDescriptor[] pipe;
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index f9cbdd42bc4f..44890bee2291 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -31,6 +31,8 @@ import android.compat.annotation.UnsupportedAppUsage;
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 @@ public class ExifInterface {
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 @@ public class ExifInterface {
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 @@ public class ExifInterface {
loadAttributes(in);
} finally {
closeQuietly(in);
+ closeQuietly(legacyInputStream);
}
}
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 835a7091bb70..ca8b9b936e99 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -30,7 +30,10 @@ import android.content.res.AssetFileDescriptor;
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 @@ import java.util.Map;
* 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 @@ public class MediaMetadataRetriever implements AutoCloseable {
* 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 @@ public class MediaMetadataRetriever implements AutoCloseable {
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 851c1ec8ec1f..47d276a50034 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -31,6 +31,8 @@ import android.graphics.SurfaceTexture;
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 @@ public class MediaPlayer extends PlayerBase
}
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 class MediaPlayer extends PlayerBase
*/
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 @@ public class MediaPlayer extends PlayerBase
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 6fbd29cb8623..126897a908f8 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -704,7 +704,7 @@ static const JNINativeMethod nativeMethods[] = {
(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},