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

Commit 81d48536 authored by Daichi Hirono's avatar Daichi Hirono
Browse files

Show MTP device as root when it has multiple/zero storages.

The CL updates MtpDocumentsProvider#queryRoots so that it fetches
devices from Database as well as storages when we don't have storages
under the device, or when we have multiple storages under the device.

BUG=26120019
Change-Id: Id2b140f00a1d49fa4da7e17d2564dbbaa1795e1e
parent 9dcbdcd5
Loading
Loading
Loading
Loading
+29 −30
Original line number Diff line number Diff line
@@ -66,10 +66,13 @@ class Mapper {
        database.beginTransaction();
        try {
            final ContentValues[] valuesList = new ContentValues[1];
            final ContentValues[] extraValuesList = new ContentValues[1];
            valuesList[0] = new ContentValues();
            MtpDatabase.getDeviceDocumentValues(valuesList[0], device);
            extraValuesList[0] = new ContentValues();
            MtpDatabase.getDeviceDocumentValues(valuesList[0], extraValuesList[0], device);
            final boolean changed = putDocuments(
                    valuesList,
                    extraValuesList,
                    COLUMN_PARENT_DOCUMENT_ID + " IS NULL",
                    EMPTY_ARGS,
                    /* heuristic */ false,
@@ -88,7 +91,7 @@ class Mapper {
     * @param roots List of root information.
     * @return If roots are added or removed from the database.
     */
    synchronized boolean putRootDocuments(
    synchronized boolean putStorageDocuments(
            String parentDocumentId, Resources resources, MtpRoot[] roots) {
        final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
        database.beginTransaction();
@@ -109,36 +112,21 @@ class Mapper {
                    throw new Error("Unexpected map mode.");
            }
            final ContentValues[] valuesList = new ContentValues[roots.length];
            final ContentValues[] extraValuesList = new ContentValues[roots.length];
            for (int i = 0; i < roots.length; i++) {
                valuesList[i] = new ContentValues();
                extraValuesList[i] = new ContentValues();
                MtpDatabase.getStorageDocumentValues(
                        valuesList[i], resources, parentDocumentId, roots[i]);
                        valuesList[i], extraValuesList[i], resources, parentDocumentId, roots[i]);
            }
            final boolean changed = putDocuments(
                    valuesList,
                    extraValuesList,
                    COLUMN_PARENT_DOCUMENT_ID + "=?",
                    strings(parentDocumentId),
                    heuristic,
                    mapColumn);
            final ContentValues values = new ContentValues();
            int i = 0;
            for (final MtpRoot root : roots) {
                // Use the same value for the root ID and the corresponding document ID.
                final String documentId = valuesList[i++].getAsString(Document.COLUMN_DOCUMENT_ID);
                // If it fails to insert/update documents, the document ID will be set with -1.
                // In this case we don't insert/update root extra information neither.
                if (documentId == null) {
                    continue;
                }
                values.put(Root.COLUMN_ROOT_ID, documentId);
                values.put(
                        Root.COLUMN_FLAGS,
                        Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
                values.put(Root.COLUMN_AVAILABLE_BYTES, root.mFreeSpace);
                values.put(Root.COLUMN_CAPACITY_BYTES, root.mMaxCapacity);
                values.put(Root.COLUMN_MIME_TYPES, "");
                database.replace(TABLE_ROOT_EXTRA, null, values);
            }

            database.setTransactionSuccessful();
            return changed;
        } finally {
@@ -176,6 +164,7 @@ class Mapper {
        }
        putDocuments(
                valuesList,
                null,
                COLUMN_PARENT_DOCUMENT_ID + "=?",
                strings(parentId),
                heuristic,
@@ -257,6 +246,7 @@ class Mapper {
     * rows. If the methods adds rows to database, it updates valueList with correct document ID.
     *
     * @param valuesList Values for documents to be stored in the database.
     * @param rootExtraValuesList Values for root extra to be stored in the database.
     * @param selection SQL where closure to select rows that shares the same parent.
     * @param args Argument for selection SQL.
     * @param heuristic Whether the mapping mode is heuristic.
@@ -264,6 +254,7 @@ class Mapper {
     */
    private boolean putDocuments(
            ContentValues[] valuesList,
            @Nullable ContentValues[] rootExtraValuesList,
            String selection,
            String[] args,
            boolean heuristic,
@@ -272,7 +263,14 @@ class Mapper {
        boolean added = false;
        database.beginTransaction();
        try {
            for (final ContentValues values : valuesList) {
            for (int i = 0; i < valuesList.length; i++) {
                final ContentValues values = valuesList[i];
                final ContentValues rootExtraValues;
                if (rootExtraValuesList != null) {
                    rootExtraValues = rootExtraValuesList[i];
                } else {
                    rootExtraValues = null;
                }
                final Cursor candidateCursor = database.query(
                        TABLE_DOCUMENTS,
                        strings(Document.COLUMN_DOCUMENT_ID),
@@ -290,25 +288,26 @@ class Mapper {
                    final long rowId;
                    if (candidateCursor.getCount() == 0) {
                        rowId = database.insert(TABLE_DOCUMENTS, null, values);
                        if (rowId == -1) {
                            throw new SQLiteException("Failed to put a document into database.");
                        }
                        added = true;
                    } else if (!heuristic) {
                        candidateCursor.moveToNext();
                        final String documentId = candidateCursor.getString(0);
                        rowId = database.update(
                        rowId = candidateCursor.getLong(0);
                        database.update(
                                TABLE_DOCUMENTS,
                                values,
                                SELECTION_DOCUMENT_ID,
                                strings(documentId));
                                strings(rowId));
                    } else {
                        values.put(COLUMN_ROW_STATE, ROW_STATE_PENDING);
                        rowId = database.insert(TABLE_DOCUMENTS, null, values);
                        rowId = database.insertOrThrow(TABLE_DOCUMENTS, null, values);
                    }
                    // Document ID is a primary integer key of the table. So the returned row
                    // IDs should be same with the document ID.
                    values.put(Document.COLUMN_DOCUMENT_ID, rowId);
                    if (rootExtraValues != null) {
                        rootExtraValues.put(Root.COLUMN_ROOT_ID, rowId);
                        database.replace(TABLE_ROOT_EXTRA, null, rootExtraValues);
                    }
                } finally {
                    candidateCursor.close();
                }
+112 −15
Original line number Diff line number Diff line
@@ -23,6 +23,9 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.MatrixCursor;
import android.database.MatrixCursor.RowBuilder;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
@@ -106,17 +109,93 @@ class MtpDatabase {
     * @return Database cursor.
     */
    Cursor queryRoots(String[] columnNames) {
        final String selection =
                COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_DOCUMENT_TYPE + " = ?";
        final Cursor deviceCursor = mDatabase.query(
                TABLE_DOCUMENTS,
                strings(COLUMN_DEVICE_ID),
                selection,
                strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED, DOCUMENT_TYPE_DEVICE),
                COLUMN_DEVICE_ID,
                null,
                null,
                null);

        try {
            final SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
            builder.setTables(JOIN_ROOTS);
            builder.setProjectionMap(COLUMN_MAP_ROOTS);
        return builder.query(
            final MatrixCursor result = new MatrixCursor(columnNames);
            final ContentValues values = new ContentValues();

            while (deviceCursor.moveToNext()) {
                final int deviceId = deviceCursor.getInt(0);
                final Cursor storageCursor = builder.query(
                        mDatabase,
                        columnNames,
                COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_DOCUMENT_TYPE + " = ?",
                strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED, DOCUMENT_TYPE_STORAGE),
                        selection + " AND " + COLUMN_DEVICE_ID + " = ?",
                        strings(ROW_STATE_VALID,
                                ROW_STATE_INVALIDATED,
                                DOCUMENT_TYPE_STORAGE,
                                deviceId),
                        null,
                        null,
                        null);
                try {
                    values.clear();
                    if (storageCursor.getCount() == 1) {
                        storageCursor.moveToNext();
                        DatabaseUtils.cursorRowToContentValues(storageCursor, values);
                    } else {
                        final Cursor cursor = builder.query(
                                mDatabase,
                                columnNames,
                                selection + " AND " + COLUMN_DEVICE_ID + " = ?",
                                strings(ROW_STATE_VALID,
                                        ROW_STATE_INVALIDATED,
                                        DOCUMENT_TYPE_DEVICE,
                                        deviceId),
                                null,
                                null,
                                null);
                        try {
                            cursor.moveToNext();
                            DatabaseUtils.cursorRowToContentValues(cursor, values);
                        } finally {
                            cursor.close();
                        }

                        long capacityBytes = 0;
                        long availableBytes = 0;
                        int capacityIndex = cursor.getColumnIndex(Root.COLUMN_CAPACITY_BYTES);
                        int availableIndex = cursor.getColumnIndex(Root.COLUMN_AVAILABLE_BYTES);
                        while (storageCursor.moveToNext()) {
                            // If requested columnNames does not include COLUMN_XXX_BYTES, we don't
                            // calculate corresponding values.
                            if (capacityIndex != -1) {
                                capacityBytes += cursor.getLong(capacityIndex);
                            }
                            if (availableIndex != -1) {
                                availableBytes += cursor.getLong(availableIndex);
                            }
                        }
                        values.put(Root.COLUMN_CAPACITY_BYTES, capacityBytes);
                        values.put(Root.COLUMN_AVAILABLE_BYTES, availableBytes);
                    }
                } finally {
                    storageCursor.close();
                }

                final RowBuilder row = result.newRow();
                for (final String key : values.keySet()) {
                    row.add(key, values.get(key));
                }
            }

            return result;
        } finally {
            deviceCursor.close();
        }
    }

    /**
@@ -380,7 +459,10 @@ class MtpDatabase {
        context.deleteDatabase(DATABASE_NAME);
    }

    static void getDeviceDocumentValues(ContentValues values, MtpDeviceRecord device) {
    static void getDeviceDocumentValues(
            ContentValues values,
            ContentValues extraValues,
            MtpDeviceRecord device) {
        values.clear();
        values.put(COLUMN_DEVICE_ID, device.deviceId);
        values.putNull(COLUMN_STORAGE_ID);
@@ -394,11 +476,15 @@ class MtpDatabase {
        values.putNull(Document.COLUMN_LAST_MODIFIED);
        values.put(Document.COLUMN_ICON, R.drawable.ic_root_mtp);
        values.put(Document.COLUMN_FLAGS, 0);
        long size = 0;
        for (final MtpRoot root : device.roots) {
            size += root.mMaxCapacity - root.mFreeSpace;
        }
        values.put(Document.COLUMN_SIZE, size);
        values.putNull(Document.COLUMN_SIZE);

        extraValues.clear();
        extraValues.put(
                Root.COLUMN_FLAGS,
                Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
        extraValues.putNull(Root.COLUMN_AVAILABLE_BYTES);
        extraValues.putNull(Root.COLUMN_CAPACITY_BYTES);
        extraValues.put(Root.COLUMN_MIME_TYPES, "");
    }

    /**
@@ -408,7 +494,11 @@ class MtpDatabase {
     * @param root Root to be converted {@link ContentValues}.
     */
    static void getStorageDocumentValues(
            ContentValues values, Resources resources, String parentDocumentId, MtpRoot root) {
            ContentValues values,
            ContentValues extraValues,
            Resources resources,
            String parentDocumentId,
            MtpRoot root) {
        values.clear();
        values.put(COLUMN_DEVICE_ID, root.mDeviceId);
        values.put(COLUMN_STORAGE_ID, root.mStorageId);
@@ -424,6 +514,13 @@ class MtpDatabase {
        values.put(Document.COLUMN_FLAGS, 0);
        values.put(Document.COLUMN_SIZE,
                (int) Math.min(root.mMaxCapacity - root.mFreeSpace, Integer.MAX_VALUE));

        extraValues.put(
                Root.COLUMN_FLAGS,
                Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
        extraValues.put(Root.COLUMN_AVAILABLE_BYTES, root.mFreeSpace);
        extraValues.put(Root.COLUMN_CAPACITY_BYTES, root.mMaxCapacity);
        extraValues.put(Root.COLUMN_MIME_TYPES, "");
    }

    /**
+15 −7
Original line number Diff line number Diff line
@@ -126,14 +126,14 @@ class MtpDatabaseConstants {
            Document.COLUMN_LAST_MODIFIED + " INTEGER," +
            Document.COLUMN_ICON + " INTEGER," +
            Document.COLUMN_FLAGS + " INTEGER NOT NULL," +
            Document.COLUMN_SIZE + " INTEGER NOT NULL);";
            Document.COLUMN_SIZE + " INTEGER);";

    static final String QUERY_CREATE_ROOT_EXTRA =
            "CREATE TABLE " + TABLE_ROOT_EXTRA + " (" +
            Root.COLUMN_ROOT_ID + " INTEGER PRIMARY KEY," +
            Root.COLUMN_FLAGS + " INTEGER NOT NULL," +
            Root.COLUMN_AVAILABLE_BYTES + " INTEGER NOT NULL," +
            Root.COLUMN_CAPACITY_BYTES + " INTEGER NOT NULL," +
            Root.COLUMN_AVAILABLE_BYTES + " INTEGER," +
            Root.COLUMN_CAPACITY_BYTES + " INTEGER," +
            Root.COLUMN_MIME_TYPES + " TEXT NOT NULL);";

    /**
@@ -145,18 +145,26 @@ class MtpDatabaseConstants {
        COLUMN_MAP_ROOTS = new HashMap<>();
        COLUMN_MAP_ROOTS.put(Root.COLUMN_ROOT_ID, TABLE_ROOT_EXTRA + "." + Root.COLUMN_ROOT_ID);
        COLUMN_MAP_ROOTS.put(Root.COLUMN_FLAGS, TABLE_ROOT_EXTRA + "." + Root.COLUMN_FLAGS);
        COLUMN_MAP_ROOTS.put(Root.COLUMN_ICON, TABLE_DOCUMENTS + "." + Document.COLUMN_ICON);
        COLUMN_MAP_ROOTS.put(
                Root.COLUMN_TITLE, TABLE_DOCUMENTS + "." + Document.COLUMN_DISPLAY_NAME);
        COLUMN_MAP_ROOTS.put(Root.COLUMN_SUMMARY, TABLE_DOCUMENTS + "." + Document.COLUMN_SUMMARY);
                Root.COLUMN_ICON,
                TABLE_DOCUMENTS + "." + Document.COLUMN_ICON + " AS " + Root.COLUMN_ICON);
        COLUMN_MAP_ROOTS.put(
                Root.COLUMN_DOCUMENT_ID, TABLE_DOCUMENTS + "." + Document.COLUMN_DOCUMENT_ID);
                Root.COLUMN_TITLE,
                TABLE_DOCUMENTS + "." + Document.COLUMN_DISPLAY_NAME + " AS " + Root.COLUMN_TITLE);
        COLUMN_MAP_ROOTS.put(
                Root.COLUMN_SUMMARY,
                TABLE_DOCUMENTS + "." + Document.COLUMN_SUMMARY + " AS " + Root.COLUMN_SUMMARY);
        COLUMN_MAP_ROOTS.put(
                Root.COLUMN_DOCUMENT_ID,
                TABLE_DOCUMENTS + "." + Document.COLUMN_DOCUMENT_ID +
                " AS " + Root.COLUMN_DOCUMENT_ID);
        COLUMN_MAP_ROOTS.put(
                Root.COLUMN_AVAILABLE_BYTES, TABLE_ROOT_EXTRA + "." + Root.COLUMN_AVAILABLE_BYTES);
        COLUMN_MAP_ROOTS.put(
                Root.COLUMN_CAPACITY_BYTES, TABLE_ROOT_EXTRA + "." + Root.COLUMN_CAPACITY_BYTES);
        COLUMN_MAP_ROOTS.put(
                Root.COLUMN_MIME_TYPES, TABLE_ROOT_EXTRA + "." + Root.COLUMN_MIME_TYPES);
        COLUMN_MAP_ROOTS.put(COLUMN_DEVICE_ID, COLUMN_DEVICE_ID);
    }

    private static String createJoinFromClosure(
+1 −1
Original line number Diff line number Diff line
@@ -127,7 +127,7 @@ final class RootScanner {
                        continue;
                    }
                    mDatabase.getMapper().startAddingDocuments(documentId);
                    if (mDatabase.getMapper().putRootDocuments(
                    if (mDatabase.getMapper().putStorageDocuments(
                            documentId, mResources, device.roots)) {
                        changed = true;
                    }
+1 −1
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ public class DocumentLoaderTest extends AndroidTestCase {
    public void setUp() {
        mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        mDatabase.getMapper().startAddingDocuments("deviceDocId");
        mDatabase.getMapper().putRootDocuments("deviceDocId", new TestResources(), new MtpRoot[] {
        mDatabase.getMapper().putStorageDocuments("deviceDocId", new TestResources(), new MtpRoot[] {
                new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "")
        });
        mDatabase.getMapper().stopAddingDocuments("deviceDocId");
Loading