Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a4fc0b07 authored by Hangyu Kuang's avatar Hangyu Kuang Committed by Android (Google) Code Review
Browse files

Merge "Avoid transcoding in MediaPlayers"

parents 6e5b3f68 95c8a181
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
@@ -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;

@@ -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 {
+17 −0
Original line number Diff line number Diff line
@@ -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);
        }
    }

+22 −3
Original line number Diff line number Diff line
@@ -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);
            }
+22 −3
Original line number Diff line number Diff line
@@ -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 {
        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;
            }
+1 −1
Original line number Diff line number Diff line
@@ -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},