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

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

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

parents ad1f8e69 81d48536
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