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

Commit 4124fb10 authored by Daichi Hirono's avatar Daichi Hirono Committed by Android (Google) Code Review
Browse files

Merge "Implement MtpDocumentsProvider#queryDocument."

parents 0d3ad99d e5323b74
Loading
Loading
Loading
Loading
+35 −5
Original line number Diff line number Diff line
@@ -19,14 +19,44 @@ package com.android.mtp;
/**
 * Static utilities for ID.
 */
abstract class Identifier {
class Identifier {
    int mDeviceId;
    int mStorageId;
    int mObjectHandle;

    static Identifier createFromRootId(String rootId) {
        final String[] components = rootId.split(":");
        return new Identifier(
                Integer.parseInt(components[0]),
                Integer.parseInt(components[1]));
    }

    static Identifier createFromDocumentId(String documentId) {
        final String[] components = documentId.split(":");
        return new Identifier(
                Integer.parseInt(components[0]),
                Integer.parseInt(components[1]),
                Integer.parseInt(components[2]));
    }


    Identifier(int deviceId, int storageId) {
        this(deviceId, storageId, MtpDocument.DUMMY_HANDLE_FOR_ROOT);
    }

    Identifier(int deviceId, int storageId, int objectHandle) {
        mDeviceId = deviceId;
        mStorageId = storageId;
        mObjectHandle = objectHandle;
    }

    // TODO: Make the ID persistent.
    static String createRootId(long deviceId, long storageId) {
        return String.format("%d:%d", deviceId, storageId);
    String toRootId() {
        return String.format("%d:%d", mDeviceId, mStorageId);
    }

    // TODO: Make the ID persistent.
    static String createDocumentId(String rootId, long objectHandle) {
        return String.format("%s:%d", rootId, objectHandle);
    String toDocumentId() {
        return String.format("%d:%d:%d", mDeviceId, mStorageId, mObjectHandle);
    }
}
+92 −1
Original line number Diff line number Diff line
@@ -16,8 +16,99 @@

package com.android.mtp;

import android.mtp.MtpObjectInfo;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;

import java.util.Date;

class MtpDocument {
    static final int DUMMY_HANDLE_FOR_ROOT = 0;

    // TODO: Implement model class for MTP document.
    private final int mObjectHandle;
    private final int mFormat;
    private final String mName;
    private final Date mDateModified;
    private final int mSize;
    private final int mThumbSize;

    /**
     * Constructor for root document.
     */
    MtpDocument(MtpRoot root) {
        this(DUMMY_HANDLE_FOR_ROOT,
             0x3001,  // Directory.
             root.mDescription,
             null,  // Unknown,
             (int) Math.min(root.mMaxCapacity - root.mFreeSpace, Integer.MAX_VALUE),
             0);
    }

    MtpDocument(MtpObjectInfo objectInfo) {
        this(objectInfo.getObjectHandle(),
             objectInfo.getFormat(),
             objectInfo.getName(),
             objectInfo.getDateModified() != 0 ? new Date(objectInfo.getDateModified()) : null,
             objectInfo.getCompressedSize(),
             objectInfo.getThumbCompressedSize());
    }

    MtpDocument(int objectHandle,
                int format,
                String name,
                Date dateModified,
                int size,
                int thumbSize) {
        this.mObjectHandle = objectHandle;
        this.mFormat = format;
        this.mName = name;
        this.mDateModified = dateModified;
        this.mSize = size;
        this.mThumbSize = thumbSize;
    }

    String getMimeType() {
        // TODO: Add complete list of mime types.
        switch (mFormat) {
            case 0x3001:
                return DocumentsContract.Document.MIME_TYPE_DIR;
            case 0x3009:
                return "audio/mp3";
            case 0x3801:
                return "image/jpeg";
            default:
                return "";
        }
    }

    Object[] getRow(Identifier rootIdentifier, String[] columnNames) {
        final Object[] rows = new Object[columnNames.length];
        for (int i = 0; i < columnNames.length; i++) {
            if (Document.COLUMN_DOCUMENT_ID.equals(columnNames[i])) {
                final Identifier identifier = new Identifier(
                        rootIdentifier.mDeviceId, rootIdentifier.mStorageId, mObjectHandle);
                rows[i] = identifier.toDocumentId();
            } else if (Document.COLUMN_DISPLAY_NAME.equals(columnNames[i])) {
                rows[i] = mName;
            } else if (Document.COLUMN_MIME_TYPE.equals(columnNames[i])) {
                rows[i] = getMimeType();
            } else if (Document.COLUMN_LAST_MODIFIED.equals(columnNames[i])) {
                rows[i] = mDateModified != null ? mDateModified.getTime() : null;
            } else if (Document.COLUMN_FLAGS.equals(columnNames[i])) {
                int flag = 0;
                if (mObjectHandle != DUMMY_HANDLE_FOR_ROOT) {
                    flag |= DocumentsContract.Document.FLAG_SUPPORTS_DELETE;
                    if (mThumbSize > 0) {
                        flag |= DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL;
                    }
                }
                rows[i] = flag;
            } else if (Document.COLUMN_SIZE.equals(columnNames[i])) {
                rows[i] = mSize;
            } else {
                rows[i] = null;
            }
        }
        return rows;
    }
}
+43 −7
Original line number Diff line number Diff line
@@ -87,14 +87,14 @@ public class MtpDocumentsProvider extends DocumentsProvider {
                // TODO: Add retry logic here.

                for (final MtpRoot root : roots) {
                    final String rootId = Identifier.createRootId(deviceId, root.mStorageId);
                    final Identifier rootIdentifier = new Identifier(deviceId, root.mStorageId);
                    final MatrixCursor.RowBuilder builder = cursor.newRow();
                    builder.add(Root.COLUMN_ROOT_ID, rootId);
                    builder.add(Root.COLUMN_ROOT_ID, rootIdentifier.toRootId());
                    builder.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_IS_CHILD);
                    builder.add(Root.COLUMN_TITLE, root.mDescription);
                    builder.add(
                            Root.COLUMN_DOCUMENT_ID,
                            Identifier.createDocumentId(rootId, MtpDocument.DUMMY_HANDLE_FOR_ROOT));
                            rootIdentifier.toDocumentId());
                    builder.add(Root.COLUMN_AVAILABLE_BYTES , root.mFreeSpace);
                }
            } catch (IOException error) {
@@ -109,12 +109,48 @@ public class MtpDocumentsProvider extends DocumentsProvider {
    @Override
    public Cursor queryDocument(String documentId, String[] projection)
            throws FileNotFoundException {
        if (projection == null) {
            projection = MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION;
        }
        final Identifier identifier = Identifier.createFromDocumentId(documentId);

        MtpDocument document = null;
        if (identifier.mObjectHandle != MtpDocument.DUMMY_HANDLE_FOR_ROOT) {
            try {
                document = mMtpManager.getDocument(identifier.mDeviceId, identifier.mObjectHandle);
            } catch (IOException e) {
                throw new FileNotFoundException(e.getMessage());
            }
        } else {
            MtpRoot[] roots;
            try {
                roots = mMtpManager.getRoots(identifier.mDeviceId);
                if (roots != null) {
                    for (final MtpRoot root : roots) {
                        if (identifier.mStorageId == root.mStorageId) {
                            document = new MtpDocument(root);
                            break;
                        }
                    }
                }
                if (document == null) {
                    throw new FileNotFoundException();
                }
            } catch (IOException e) {
                throw new FileNotFoundException(e.getMessage());
            }
        }

        final MatrixCursor cursor = new MatrixCursor(projection);
        cursor.addRow(document.getRow(
                new Identifier(identifier.mDeviceId, identifier.mStorageId),
                projection));
        return cursor;
    }

    @Override
    public Cursor queryChildDocuments(String parentDocumentId,
            String[] projection, String sortOrder)
    public Cursor queryChildDocuments(
            String parentDocumentId, String[] projection, String sortOrder)
                    throws FileNotFoundException {
        throw new FileNotFoundException();
    }
+5 −0
Original line number Diff line number Diff line
@@ -98,6 +98,11 @@ class MtpManager {
        return results;
    }

    synchronized MtpDocument getDocument(int deviceId, int objectHandle) throws IOException {
        final MtpDevice device = getDevice(deviceId);
        return new MtpDocument(device.getObjectInfo(objectHandle));
    }

    private MtpDevice getDevice(int deviceId) throws IOException {
        final MtpDevice device = mDevices.get(deviceId);
        if (device == null) {
+2 −2
Original line number Diff line number Diff line
@@ -21,14 +21,14 @@ import android.mtp.MtpStorageInfo;
import com.android.internal.annotations.VisibleForTesting;

class MtpRoot {
    final long mStorageId;
    final int mStorageId;
    final String mDescription;
    final long mFreeSpace;
    final long mMaxCapacity;
    final String mVolumeIdentifier;

    @VisibleForTesting
    MtpRoot(long storageId,
    MtpRoot(int storageId,
            String description,
            long freeSpace,
            long maxCapacity,
Loading