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

Commit 3d73c3ad authored by Biswarup Pal's avatar Biswarup Pal Committed by Android (Google) Code Review
Browse files

Merge "Refactor FileUtils#convertToModernFd" into sc-dev

parents 9d0057ed d80f7605
Loading
Loading
Loading
Loading
+7 −34
Original line number Original line Diff line number Diff line
@@ -46,8 +46,6 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.ProviderInfo;
import android.content.res.AssetFileDescriptor;
import android.net.Uri;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Document;
import android.provider.MediaStore;
import android.provider.MediaStore;
import android.system.ErrnoException;
import android.system.ErrnoException;
@@ -83,7 +81,6 @@ import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collection;
import java.util.Comparator;
import java.util.Comparator;
import java.util.Locale;
import java.util.Objects;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit;
@@ -1446,47 +1443,23 @@ public final class FileUtils {
        }
        }
    }
    }


    // TODO(b/170488060): Consider better approach
    /** {@hide} */
    /** {@hide} */
    @VisibleForTesting
    @VisibleForTesting
    public static FileDescriptor convertToModernFd(FileDescriptor fd) {
    public static ParcelFileDescriptor convertToModernFd(FileDescriptor fd) {
        try {
        try {
            Context context = AppGlobals.getInitialApplication();
            Context context = AppGlobals.getInitialApplication();
            // /mnt/user paths are not accessible directly so convert to a /storage path
            if (UserHandle.getAppId(Process.myUid()) == getMediaProviderAppId(context)) {
            String filePath = Os.readlink("/proc/self/fd/" + fd.getInt$()).replace(
                // Never convert modern fd for MediaProvider, because this requires
                    "/mnt/user/" + UserHandle.myUserId(), "/storage");
            File realFile = new File(filePath);
            String fileName = realFile.getName();
            boolean isCameraVideo = !fileName.startsWith(".") && fileName.endsWith(".mp4")
                    && contains(CAMERA_DIR_LOWER_CASE, filePath.toLowerCase(Locale.ROOT));

            if (!SystemProperties.getBoolean("sys.fuse.transcode_enabled", false)
                    || UserHandle.getAppId(Process.myUid()) == getMediaProviderAppId(context)
                    || !isCameraVideo) {
                // 1. If transcode is enabled we optimize by default, unless explicitly disabled.
                // 2. Never convert modern fd for MediaProvider, because this requires
                // MediaStore#scanFile and can cause infinite loops when MediaProvider scans
                // MediaStore#scanFile and can cause infinite loops when MediaProvider scans
                // 3. Only convert published mp4 videos in the DCIM/Camera dir
                return null;
                return null;
            }
            }
            Log.i(TAG, "Changing to modern format dataSource for: " + realFile);
            return MediaStore.getOriginalMediaFormatFileDescriptor(context,
            ContentResolver resolver = context.getContentResolver();
                    ParcelFileDescriptor.dup(fd));

            Uri uri = MediaStore.scanFile(resolver, realFile);
            if (uri != null) {
                Bundle opts = new Bundle();
                opts.putBoolean(MediaStore.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) {
        } catch (Exception e) {
            Log.w(TAG, "Failed to change to modern format dataSource", e);
            Log.w(TAG, "Failed to convert to modern format file descriptor", e);
        }
            return null;
            return null;
        }
        }
    }


    private static int getMediaProviderAppId(Context context) {
    private static int getMediaProviderAppId(Context context) {
        if (sMediaProviderAppId != -1) {
        if (sMediaProviderAppId != -1) {
+17 −13
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@ import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory;
import android.os.FileUtils;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.system.ErrnoException;
import android.system.ErrnoException;
import android.system.Os;
import android.system.Os;
import android.system.OsConstants;
import android.system.OsConstants;
@@ -1531,16 +1532,24 @@ public class ExifInterface {
        if (fileDescriptor == null) {
        if (fileDescriptor == null) {
            throw new NullPointerException("fileDescriptor cannot be null");
            throw new NullPointerException("fileDescriptor cannot be null");
        }
        }
        FileDescriptor modernFd = FileUtils.convertToModernFd(fileDescriptor);
        // If a file descriptor has a modern file descriptor, this means that the file can be
        // transcoded and not using the modern file descriptor will trigger the transcoding
        // operation. Thus, to avoid unnecessary transcoding, need to convert to modern file
        // descriptor if it exists. As of Android S, transcoding is not supported for image files,
        // so this is for protecting against non-image files sent to ExifInterface, but support may
        // be added in the future.
        ParcelFileDescriptor modernFd = FileUtils.convertToModernFd(fileDescriptor);
        if (modernFd != null) {
        if (modernFd != null) {
            fileDescriptor = modernFd;
            fileDescriptor = modernFd.getFileDescriptor();
        }
        }


        mAssetInputStream = null;
        mAssetInputStream = null;
        mFilename = null;
        mFilename = null;


        boolean isFdDuped = false;
        boolean isFdDuped = false;
        if (isSeekableFD(fileDescriptor)) {
        // Can't save attributes to files with transcoding because apps get a different copy of
        // that file when they're not using it through framework libraries like ExifInterface.
        if (isSeekableFD(fileDescriptor) && modernFd == null) {
            mSeekableFileDescriptor = fileDescriptor;
            mSeekableFileDescriptor = fileDescriptor;
            // Keep the original file descriptor in order to save attributes when it's seekable.
            // Keep the original file descriptor in order to save attributes when it's seekable.
            // Otherwise, just close the given file descriptor after reading it because the save
            // Otherwise, just close the given file descriptor after reading it because the save
@@ -2545,27 +2554,22 @@ public class ExifInterface {


    private void initForFilename(String filename) throws IOException {
    private void initForFilename(String filename) throws IOException {
        FileInputStream in = null;
        FileInputStream in = null;
        FileInputStream legacyInputStream = null;
        mAssetInputStream = null;
        mAssetInputStream = null;
        mFilename = filename;
        mFilename = filename;
        mIsInputStream = false;
        mIsInputStream = false;
        try {
        try {
            in = new FileInputStream(filename);
            in = new FileInputStream(filename);
            FileDescriptor modernFd = FileUtils.convertToModernFd(in.getFD());
            ParcelFileDescriptor modernFd = FileUtils.convertToModernFd(in.getFD());
            if (modernFd != null) {
            if (modernFd != null) {
                legacyInputStream = in;
                closeQuietly(in);
                in = new FileInputStream(modernFd);
                in = new FileInputStream(modernFd.getFileDescriptor());
            }

            if (isSeekableFD(in.getFD())) {
                mSeekableFileDescriptor = in.getFD();
            } else {
                mSeekableFileDescriptor = null;
                mSeekableFileDescriptor = null;
            } else if (isSeekableFD(in.getFD())) {
                mSeekableFileDescriptor = in.getFD();
            }
            }
            loadAttributes(in);
            loadAttributes(in);
        } finally {
        } finally {
            closeQuietly(in);
            closeQuietly(in);
            closeQuietly(legacyInputStream);
        }
        }
    }
    }


+3 −2
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Bundle;
import android.os.FileUtils;
import android.os.FileUtils;
import android.os.IBinder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.SystemProperties;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.text.TextUtils;


@@ -300,11 +301,11 @@ public class MediaMetadataRetriever implements AutoCloseable {
     */
     */
    public void setDataSource(FileDescriptor fd, long offset, long length)
    public void setDataSource(FileDescriptor fd, long offset, long length)
            throws IllegalArgumentException  {
            throws IllegalArgumentException  {
        FileDescriptor modernFd = FileUtils.convertToModernFd(fd);
        ParcelFileDescriptor modernFd = FileUtils.convertToModernFd(fd);
        if (modernFd == null) {
        if (modernFd == null) {
            _setDataSource(fd, offset, length);
            _setDataSource(fd, offset, length);
        } else {
        } else {
            _setDataSource(modernFd, offset, length);
            _setDataSource(modernFd.getFileDescriptor(), offset, length);
        }
        }
    }
    }


+3 −3
Original line number Original line Diff line number Diff line
@@ -46,6 +46,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Looper;
import android.os.Message;
import android.os.Message;
import android.os.Parcel;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.Parcelable;
import android.os.PersistableBundle;
import android.os.PersistableBundle;
import android.os.PowerManager;
import android.os.PowerManager;
@@ -97,7 +98,6 @@ import java.util.UUID;
import java.util.Vector;
import java.util.Vector;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;



/**
/**
 * MediaPlayer class can be used to control playback of audio/video files and streams.
 * MediaPlayer class can be used to control playback of audio/video files and streams.
 *
 *
@@ -1268,11 +1268,11 @@ public class MediaPlayer extends PlayerBase
     */
     */
    public void setDataSource(FileDescriptor fd, long offset, long length)
    public void setDataSource(FileDescriptor fd, long offset, long length)
            throws IOException, IllegalArgumentException, IllegalStateException {
            throws IOException, IllegalArgumentException, IllegalStateException {
        FileDescriptor modernFd = FileUtils.convertToModernFd(fd);
        ParcelFileDescriptor modernFd = FileUtils.convertToModernFd(fd);
        if (modernFd == null) {
        if (modernFd == null) {
            _setDataSource(fd, offset, length);
            _setDataSource(fd, offset, length);
        } else {
        } else {
            _setDataSource(modernFd, offset, length);
            _setDataSource(modernFd.getFileDescriptor(), offset, length);
        }
        }
    }
    }