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

Commit ac0cb359 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android Git Automerger
Browse files

am 8e656df0: Merge "Add extras to AFD, send orientation metadata." into klp-dev

* commit '8e656df0':
  Add extras to AFD, send orientation metadata.
parents bd0a4143 8e656df0
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -7497,11 +7497,13 @@ package android.content.res {
  public class AssetFileDescriptor implements java.io.Closeable android.os.Parcelable {
    ctor public AssetFileDescriptor(android.os.ParcelFileDescriptor, long, long);
    ctor public AssetFileDescriptor(android.os.ParcelFileDescriptor, long, long, android.os.Bundle);
    method public void close() throws java.io.IOException;
    method public java.io.FileInputStream createInputStream() throws java.io.IOException;
    method public java.io.FileOutputStream createOutputStream() throws java.io.IOException;
    method public int describeContents();
    method public long getDeclaredLength();
    method public android.os.Bundle getExtras();
    method public java.io.FileDescriptor getFileDescriptor();
    method public long getLength();
    method public android.os.ParcelFileDescriptor getParcelFileDescriptor();
+48 −8
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.content.res;

import android.os.Bundle;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
@@ -42,9 +43,11 @@ public class AssetFileDescriptor implements Parcelable, Closeable {
    private final ParcelFileDescriptor mFd;
    private final long mStartOffset;
    private final long mLength;
    private final Bundle mExtras;

    /**
     * Create a new AssetFileDescriptor from the given values.
     *
     * @param fd The underlying file descriptor.
     * @param startOffset The location within the file that the asset starts.
     *            This must be 0 if length is UNKNOWN_LENGTH.
@@ -53,6 +56,22 @@ public class AssetFileDescriptor implements Parcelable, Closeable {
     */
    public AssetFileDescriptor(ParcelFileDescriptor fd, long startOffset,
            long length) {
        this(fd, startOffset, length, null);
    }

    /**
     * Create a new AssetFileDescriptor from the given values.
     *
     * @param fd The underlying file descriptor.
     * @param startOffset The location within the file that the asset starts.
     *            This must be 0 if length is UNKNOWN_LENGTH.
     * @param length The number of bytes of the asset, or
     *            {@link #UNKNOWN_LENGTH} if it extends to the end of the file.
     * @param extras additional details that can be used to interpret the
     *            underlying file descriptor. May be null.
     */
    public AssetFileDescriptor(ParcelFileDescriptor fd, long startOffset,
            long length, Bundle extras) {
        if (fd == null) {
            throw new IllegalArgumentException("fd must not be null");
        }
@@ -63,6 +82,7 @@ public class AssetFileDescriptor implements Parcelable, Closeable {
        mFd = fd;
        mStartOffset = startOffset;
        mLength = length;
        mExtras = extras;
    }

    /**
@@ -89,6 +109,14 @@ public class AssetFileDescriptor implements Parcelable, Closeable {
        return mStartOffset;
    }

    /**
     * Returns any additional details that can be used to interpret the
     * underlying file descriptor. May be null.
     */
    public Bundle getExtras() {
        return mExtras;
    }

    /**
     * Returns the total number of bytes of this asset entry's data.  May be
     * {@link #UNKNOWN_LENGTH} if the asset extends to the end of the file.
@@ -308,22 +336,34 @@ public class AssetFileDescriptor implements Parcelable, Closeable {
        }
    }

    
    /* Parcelable interface */
    @Override
    public int describeContents() {
        return mFd.describeContents();
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        mFd.writeToParcel(out, flags);
        out.writeLong(mStartOffset);
        out.writeLong(mLength);
        if (mExtras != null) {
            out.writeInt(1);
            out.writeBundle(mExtras);
        } else {
            out.writeInt(0);
        }
    }

    AssetFileDescriptor(Parcel src) {
        mFd = ParcelFileDescriptor.CREATOR.createFromParcel(src);
        mStartOffset = src.readLong();
        mLength = src.readLong();
        if (src.readInt() != 0) {
            mExtras = src.readBundle();
        } else {
            mExtras = null;
        }
    }

    public static final Parcelable.Creator<AssetFileDescriptor> CREATOR
+72 −3
Original line number Diff line number Diff line
@@ -28,7 +28,9 @@ import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Point;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -42,8 +44,10 @@ import libcore.io.IoUtils;
import libcore.io.Libcore;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;

@@ -76,6 +80,15 @@ public final class DocumentsContract {
    /** {@hide} */
    public static final String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME";

    /**
     * Included in {@link AssetFileDescriptor#getExtras()} when returned
     * thumbnail should be rotated.
     *
     * @see MediaStore.Images.ImageColumns#ORIENTATION
     * @hide
     */
    public static final String EXTRA_ORIENTATION = "android.content.extra.ORIENTATION";

    /** {@hide} */
    public static final String ACTION_MANAGE_ROOT = "android.provider.action.MANAGE_ROOT";
    /** {@hide} */
@@ -657,6 +670,7 @@ public final class DocumentsContract {
        openOpts.putParcelable(DocumentsContract.EXTRA_THUMBNAIL_SIZE, size);

        AssetFileDescriptor afd = null;
        Bitmap bitmap = null;
        try {
            afd = client.openTypedAssetFileDescriptor(documentUri, "image/*", openOpts, signal);

@@ -688,21 +702,36 @@ public final class DocumentsContract {

            opts.inJustDecodeBounds = false;
            opts.inSampleSize = Math.min(widthSample, heightSample);
            Log.d(TAG, "Decoding with sample size " + opts.inSampleSize);
            if (is != null) {
                is.reset();
                return BitmapFactory.decodeStream(is, null, opts);
                bitmap = BitmapFactory.decodeStream(is, null, opts);
            } else {
                try {
                    Libcore.os.lseek(fd, offset, SEEK_SET);
                } catch (ErrnoException e) {
                    e.rethrowAsIOException();
                }
                return BitmapFactory.decodeFileDescriptor(fd, null, opts);
                bitmap = BitmapFactory.decodeFileDescriptor(fd, null, opts);
            }

            // Transform the bitmap if requested. We use a side-channel to
            // communicate the orientation, since EXIF thumbnails don't contain
            // the rotation flags of the original image.
            final Bundle extras = afd.getExtras();
            final int orientation = (extras != null) ? extras.getInt(EXTRA_ORIENTATION, 0) : 0;
            if (orientation != 0) {
                final int width = bitmap.getWidth();
                final int height = bitmap.getHeight();

                final Matrix m = new Matrix();
                m.setRotate(orientation, width / 2, height / 2);
                bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, m, false);
            }
        } finally {
            IoUtils.closeQuietly(afd);
        }

        return bitmap;
    }

    /**
@@ -770,4 +799,44 @@ public final class DocumentsContract {

        client.call(METHOD_DELETE_DOCUMENT, null, in);
    }

    /**
     * Open the given image for thumbnail purposes, using any embedded EXIF
     * thumbnail if available, and providing orientation hints from the parent
     * image.
     *
     * @hide
     */
    public static AssetFileDescriptor openImageThumbnail(File file) throws FileNotFoundException {
        final ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
                file, ParcelFileDescriptor.MODE_READ_ONLY);
        Bundle extras = null;

        try {
            final ExifInterface exif = new ExifInterface(file.getAbsolutePath());

            switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1)) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    extras = new Bundle(1);
                    extras.putInt(EXTRA_ORIENTATION, 90);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    extras = new Bundle(1);
                    extras.putInt(EXTRA_ORIENTATION, 180);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    extras = new Bundle(1);
                    extras.putInt(EXTRA_ORIENTATION, 270);
                    break;
            }

            final long[] thumb = exif.getThumbnailRange();
            if (thumb != null) {
                return new AssetFileDescriptor(pfd, thumb[0], thumb[1], extras);
            }
        } catch (IOException e) {
        }

        return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH, extras);
    }
}
+2 −13
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsContract;
import android.provider.DocumentsProvider;
import android.webkit.MimeTypeMap;

@@ -313,19 +314,7 @@ public class ExternalStorageProvider extends DocumentsProvider {
            String documentId, Point sizeHint, CancellationSignal signal)
            throws FileNotFoundException {
        final File file = getFileForDocId(documentId);
        final ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
                file, ParcelFileDescriptor.MODE_READ_ONLY);

        try {
            final ExifInterface exif = new ExifInterface(file.getAbsolutePath());
            final long[] thumb = exif.getThumbnailRange();
            if (thumb != null) {
                return new AssetFileDescriptor(pfd, thumb[0], thumb[1]);
            }
        } catch (IOException e) {
        }

        return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH);
        return DocumentsContract.openImageThumbnail(file);
    }

    private static String getTypeForFile(File file) {