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

Commit df544176 authored by Tomasz Mikolajewski's avatar Tomasz Mikolajewski
Browse files

Fix uploading multiple files via MtpDocumentsProvider.

Uploading was breaking as SendObject request was not being sent directly
after SendObjectInfo which is assumed by the MTP stack in Android.

Change-Id: I36b94f56682e79dec38add9be5f70f55d07e22e7
parent ab65d363
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -225,6 +225,8 @@ public class MtpDocumentsProvider extends DocumentsProvider {
            throws FileNotFoundException {
        try {
            final Identifier parentId = Identifier.createFromDocumentId(parentDocumentId);
            final ParcelFileDescriptor pipe[] = ParcelFileDescriptor.createReliablePipe();
            pipe[0].close();  // 0 bytes for a new document.
            final int objectHandle = mMtpManager.createDocument(
                    parentId.mDeviceId,
                    new MtpObjectInfo.Builder()
@@ -232,7 +234,7 @@ public class MtpDocumentsProvider extends DocumentsProvider {
                            .setParent(parentId.mObjectHandle)
                            .setFormat(CursorHelper.mimeTypeToFormatType(mimeType))
                            .setName(displayName)
                            .build());
                            .build(), pipe[1]);
            final String documentId =  new Identifier(parentId.mDeviceId, parentId.mStorageId,
                   objectHandle).toDocumentId();
            notifyChildDocumentsChange(parentDocumentId);
+12 −11
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.Context;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.mtp.MtpConstants;
import android.mtp.MtpDevice;
import android.mtp.MtpObjectInfo;
import android.os.ParcelFileDescriptor;
@@ -138,13 +139,20 @@ class MtpManager {
        }
    }

    synchronized int createDocument(int deviceId, MtpObjectInfo objectInfo) throws IOException {
    synchronized int createDocument(int deviceId, MtpObjectInfo objectInfo,
            ParcelFileDescriptor source) throws IOException {
        final MtpDevice device = getDevice(deviceId);
        final MtpObjectInfo result = device.sendObjectInfo(objectInfo);
        if (result == null) {
        final MtpObjectInfo sendObjectInfoResult = device.sendObjectInfo(objectInfo);
        if (sendObjectInfoResult == null) {
            throw new IOException("Failed to create a document");
        }
        return result.getObjectHandle();
        if (objectInfo.getFormat() != MtpConstants.FORMAT_ASSOCIATION) {
            if (!device.sendObject(sendObjectInfoResult.getObjectHandle(),
                    sendObjectInfoResult.getCompressedSize(), source)) {
                throw new IOException("Failed to send contents of a document");
            }
        }
        return sendObjectInfoResult.getObjectHandle();
    }

    synchronized int getParent(int deviceId, int objectHandle) throws IOException {
@@ -162,13 +170,6 @@ class MtpManager {
        device.importFile(objectHandle, target);
    }

    synchronized void sendObject(int deviceId, int objectHandle, int size,
            ParcelFileDescriptor source) throws IOException {
        final MtpDevice device = getDevice(deviceId);
        if (!device.sendObject(objectHandle, size, source))
            throw new IOException("Failed to send a document");
    }

    private MtpDevice getDevice(int deviceId) throws IOException {
        final MtpDevice device = mDevices.get(deviceId);
        if (device == null) {
+7 −12
Original line number Diff line number Diff line
@@ -139,20 +139,15 @@ class PipeManager {
                // Delete the target object info if it already exists (as a placeholder).
                mManager.deleteDocument(mIdentifier.mDeviceId, mIdentifier.mObjectHandle);

                // Create the target object info with a correct file size.
                final int targetObjectHandle =
                        mManager.createDocument(
                                mIdentifier.mDeviceId,
                // Create the target object info with a correct file size and upload the file.
                final MtpObjectInfo targetObjectInfo =
                        new MtpObjectInfo.Builder(placeholderObjectInfo)
                                .setCompressedSize((int) tempFile.length())
                                        .build());

                // Upload the object.
                                .build();
                final ParcelFileDescriptor tempInputDescriptor = ParcelFileDescriptor.open(
                        tempFile, ParcelFileDescriptor.MODE_READ_ONLY);
                mManager.sendObject(mIdentifier.mDeviceId,
                        targetObjectHandle, (int) tempFile.length(), tempInputDescriptor);

                mManager.createDocument(mIdentifier.mDeviceId,
                        targetObjectInfo, tempInputDescriptor);
            } catch (IOException error) {
                Log.w(MtpDocumentsProvider.TAG,
                        "Failed to send a file because of: " + error.getMessage());
+16 −22
Original line number Diff line number Diff line
@@ -137,32 +137,26 @@ public class TestMtpManager extends MtpManager {
    }

    @Override
    int createDocument(int deviceId, MtpObjectInfo objectInfo) throws IOException {
    int createDocument(int deviceId, MtpObjectInfo objectInfo, ParcelFileDescriptor source)
            throws IOException {
        final String key = pack(deviceId, CREATED_DOCUMENT_HANDLE);
        if (!mObjectInfos.containsKey(key)) {
            mObjectInfos.put(key, objectInfo);
        } else {
        if (mObjectInfos.containsKey(key)) {
            throw new IOException();
        }
        return CREATED_DOCUMENT_HANDLE;
    }

    @Override
    void sendObject(int deviceId, int objectHandle, int size, ParcelFileDescriptor source)
            throws IOException {
        final String key = pack(deviceId, objectHandle);
        if (!mObjectInfos.containsKey(key)) {
        mObjectInfos.put(key, objectInfo);
        if (objectInfo.getFormat() != 0x3001) {
            try (final ParcelFileDescriptor.AutoCloseInputStream inputStream =
                    new ParcelFileDescriptor.AutoCloseInputStream(source)) {
                final byte[] buffer = new byte[objectInfo.getCompressedSize()];
                if (inputStream.read(buffer, 0, objectInfo.getCompressedSize()) !=
                        objectInfo.getCompressedSize()) {
                    throw new IOException();
                }

        ParcelFileDescriptor.AutoCloseInputStream inputStream =
                new ParcelFileDescriptor.AutoCloseInputStream(source);
        byte[] buffer = new byte[size];
        if (inputStream.read(buffer, 0, size) != size) {
            throw new IOException();
                mImportFileBytes.put(pack(deviceId, CREATED_DOCUMENT_HANDLE), buffer);
            }

        mImportFileBytes.put(pack(deviceId, objectHandle), buffer);
        }
        return CREATED_DOCUMENT_HANDLE;
    }

    @Override