Loading core/java/android/os/FileUtils.java +56 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -1424,6 +1432,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 { Loading media/java/android/media/ExifInterface.java +17 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 { Loading @@ -2546,6 +2562,7 @@ public class ExifInterface { loadAttributes(in); } finally { closeQuietly(in); closeQuietly(legacyInputStream); } } Loading media/java/android/media/MediaMetadataRetriever.java +22 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading Loading @@ -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; /** Loading Loading @@ -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); } Loading media/java/android/media/MediaPlayer.java +22 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -1245,7 +1253,13 @@ public class MediaPlayer extends PlayerBase */ public void setDataSource(FileDescriptor fd, long offset, long length) throws IOException, IllegalArgumentException, IllegalStateException { 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) Loading Loading @@ -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; } Loading media/jni/android_media_MediaMetadataRetriever.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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}, Loading Loading
core/java/android/os/FileUtils.java +56 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -1424,6 +1432,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 { Loading
media/java/android/media/ExifInterface.java +17 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 { Loading @@ -2546,6 +2562,7 @@ public class ExifInterface { loadAttributes(in); } finally { closeQuietly(in); closeQuietly(legacyInputStream); } } Loading
media/java/android/media/MediaMetadataRetriever.java +22 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading Loading @@ -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; /** Loading Loading @@ -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); } Loading
media/java/android/media/MediaPlayer.java +22 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -1245,7 +1253,13 @@ public class MediaPlayer extends PlayerBase */ public void setDataSource(FileDescriptor fd, long offset, long length) throws IOException, IllegalArgumentException, IllegalStateException { 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) Loading Loading @@ -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; } Loading
media/jni/android_media_MediaMetadataRetriever.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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}, Loading