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

Commit 64111e08 authored by Daichi Hirono's avatar Daichi Hirono
Browse files

Get object size that is more than 4GB.

MtpObjectInfo contains object size as 32-bit integer and the provider
needs to invoke MtpDevice#getObjectSizeLong hidden API to get 64-bit
object size.

The CL switches to use MtpDevice#getObjectSizeLong hidden API if
MtpObjectInfo#getCompressedSize() returns 0xffffffffL, which means the
object size is more than 4GB.

BUG=27805369

Change-Id: I87ea02c09aa784246cf016def309d1f39ed20e90
parent 787821bc
Loading
Loading
Loading
Loading
+35 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.Nullable;
import android.annotation.WorkerThread;
import android.content.ContentResolver;
import android.database.Cursor;
import android.mtp.MtpConstants;
import android.mtp.MtpObjectInfo;
import android.net.Uri;
import android.os.Bundle;
@@ -340,13 +341,46 @@ class DocumentLoader implements AutoCloseable {
                    Log.e(MtpDocumentsProvider.TAG, "Failed to load object info", error);
                }
            }
            final long[] objectSizeList = new long[infoList.size()];
            for (int i = 0; i < infoList.size(); i++) {
                final MtpObjectInfo info = infoList.get(i);
                // Compressed size is 32-bit unsigned integer but getCompressedSize returns the
                // value in Java int (signed 32-bit integer). Use getCompressedSizeLong instead
                // to get the value in Java long.
                if (info.getCompressedSizeLong() != 0xffffffffl) {
                    objectSizeList[i] = info.getCompressedSizeLong();
                    continue;
                }

                if (!MtpDeviceRecord.isSupported(
                        mOperationsSupported,
                        MtpConstants.OPERATION_GET_OBJECT_PROP_DESC) ||
                        !MtpDeviceRecord.isSupported(
                                mOperationsSupported,
                                MtpConstants.OPERATION_GET_OBJECT_PROP_VALUE)) {
                    objectSizeList[i] = -1;
                    continue;
                }

                // Object size is more than 4GB.
                try {
                    objectSizeList[i] = mManager.getObjectSizeLong(
                            mIdentifier.mDeviceId,
                            info.getObjectHandle(),
                            info.getFormat());
                } catch (IOException error) {
                    Log.e(MtpDocumentsProvider.TAG, "Failed to get object size property.", error);
                    objectSizeList[i] = -1;
                }
            }
            synchronized (this) {
                try {
                    mDatabase.getMapper().putChildDocuments(
                            mIdentifier.mDeviceId,
                            mIdentifier.mDocumentId,
                            mOperationsSupported,
                            infoList.toArray(new MtpObjectInfo[infoList.size()]));
                            infoList.toArray(new MtpObjectInfo[infoList.size()]),
                            objectSizeList);
                } catch (FileNotFoundException error) {
                    // Looks like the parent document information is removed.
                    // Adding documents has already cancelled in Mapper so we don't need to invoke
+13 −2
Original line number Diff line number Diff line
@@ -128,16 +128,27 @@ class Mapper {
     * @param deviceId Device ID
     * @param parentId Parent document ID.
     * @param documents List of document information.
     * @param documentSizes 64-bit size of documents. MtpObjectInfo#getComporessedSize will be
     *     ignored because it does not contain 4GB> object size. Can be -1 if the size is unknown.
     * @throws FileNotFoundException
     */
    synchronized void putChildDocuments(
            int deviceId, String parentId, int[] operationsSupported, MtpObjectInfo[] documents)
            int deviceId, String parentId,
            int[] operationsSupported,
            MtpObjectInfo[] documents,
            long[] documentSizes)
            throws FileNotFoundException {
        assert documents.length == documentSizes.length;
        final ContentValues[] valuesList = new ContentValues[documents.length];
        for (int i = 0; i < documents.length; i++) {
            valuesList[i] = new ContentValues();
            MtpDatabase.getObjectDocumentValues(
                    valuesList[i], deviceId, parentId, operationsSupported, documents[i]);
                    valuesList[i],
                    deviceId,
                    parentId,
                    operationsSupported,
                    documents[i],
                    documentSizes[i]);
        }
        putDocuments(
                parentId,
+16 −7
Original line number Diff line number Diff line
@@ -372,12 +372,16 @@ class MtpDatabase {
     * newly added and never mapped with existing ones.
     * @param parentDocumentId
     * @param info
     * @param size Object size. info#getCompressedSize() will be ignored because it does not contain
     *     object size more than 4GB.
     * @return Document ID of added document.
     */
    String putNewDocument(
            int deviceId, String parentDocumentId, int[] operationsSupported, MtpObjectInfo info) {
            int deviceId, String parentDocumentId, int[] operationsSupported, MtpObjectInfo info,
            long size) {
        final ContentValues values = new ContentValues();
        getObjectDocumentValues(values, deviceId, parentDocumentId, operationsSupported, info);
        getObjectDocumentValues(
                values, deviceId, parentDocumentId, operationsSupported, info, size);
        mDatabase.beginTransaction();
        try {
            final long id = mDatabase.insert(TABLE_DOCUMENTS, null, values);
@@ -586,9 +590,9 @@ class MtpDatabase {
    }

    void updateObject(String documentId, int deviceId, String parentId, int[] operationsSupported,
                      MtpObjectInfo info) {
                      MtpObjectInfo info, Long size) {
        final ContentValues values = new ContentValues();
        getObjectDocumentValues(values, deviceId, parentId, operationsSupported, info);
        getObjectDocumentValues(values, deviceId, parentId, operationsSupported, info, size);

        mDatabase.beginTransaction();
        try {
@@ -811,11 +815,12 @@ class MtpDatabase {
     * @param values {@link ContentValues} that receives values.
     * @param deviceId Device ID of the object.
     * @param parentId Parent document ID of the object.
     * @param info MTP object info.
     * @param info MTP object info. getCompressedSize will be ignored.
     * @param size 64-bit size of documents. Negative value is regarded as unknown size.
     */
    static void getObjectDocumentValues(
            ContentValues values, int deviceId, String parentId,
            int[] operationsSupported, MtpObjectInfo info) {
            int[] operationsSupported, MtpObjectInfo info, long size) {
        values.clear();
        final String mimeType = getMimeType(info);
        values.put(COLUMN_DEVICE_ID, deviceId);
@@ -834,7 +839,11 @@ class MtpDatabase {
        values.put(Document.COLUMN_FLAGS, getDocumentFlags(
                operationsSupported, mimeType, info.getThumbCompressedSizeLong(),
                info.getProtectionStatus(), DOCUMENT_TYPE_OBJECT));
        values.put(Document.COLUMN_SIZE, info.getCompressedSizeLong());
        if (size >= 0) {
            values.put(Document.COLUMN_SIZE, size);
        } else {
            values.putNull(Document.COLUMN_SIZE);
        }
    }

    private static String getMimeType(MtpObjectInfo info) {
+1 −2
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.mtp.MtpObjectInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.FileUriExposedException;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.storage.StorageManager;
@@ -388,7 +387,7 @@ public class MtpDocumentsProvider extends DocumentsProvider {
                    new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build();
            final String documentId = mDatabase.putNewDocument(
                    parentId.mDeviceId, parentDocumentId, record.operationsSupported,
                    infoWithHandle);
                    infoWithHandle, 0l);
            getDocumentLoader(parentId).clearTask(parentId);
            notifyChildDocumentsChange(parentDocumentId);
            return documentId;
+5 −0
Original line number Diff line number Diff line
@@ -229,6 +229,11 @@ class MtpManager {
        return device.readEvent(signal);
    }

    long getObjectSizeLong(int deviceId, int objectHandle, int format) throws IOException {
        final MtpDevice device = getDevice(deviceId);
        return device.getObjectSizeLong(objectHandle, format);
    }

    private synchronized MtpDevice getDevice(int deviceId) throws IOException {
        final MtpDevice device = mDevices.get(deviceId);
        if (device == null) {
Loading