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

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

Merge "Revert "Add device document to MtpDatabase.""

parents cfb96e77 b63e8c6c
Loading
Loading
Loading
Loading
+13 −34
Original line number Diff line number Diff line
@@ -42,7 +42,6 @@ import static com.android.mtp.MtpDatabase.strings;
 * Also see the comments of {@link MtpDatabase}.
 */
class Mapper {
    private static final String[] EMPTY_ARGS = new String[0];
    private final MtpDatabase mDatabase;

    /**
@@ -56,43 +55,21 @@ class Mapper {
        mDatabase = database;
    }

    synchronized String putDeviceDocument(int deviceId, String name, MtpRoot[] roots) {
        final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
        Preconditions.checkState(mMappingMode.containsKey(/* no parent for root */ null));
        database.beginTransaction();
        try {
            final ContentValues[] valuesList = new ContentValues[1];
            valuesList[0] = new ContentValues();
            MtpDatabase.getDeviceDocumentValues(valuesList[0], deviceId, name, roots);
            putDocuments(
                    valuesList,
                    COLUMN_PARENT_DOCUMENT_ID + " IS NULL",
                    EMPTY_ARGS,
                    /* heuristic */ false,
                    COLUMN_DEVICE_ID);
            database.setTransactionSuccessful();
            return valuesList[0].getAsString(Document.COLUMN_DOCUMENT_ID);
        } finally {
            database.endTransaction();
        }
    }

    /**
     * Puts root information to database.
     * @param parentDocumentId Document ID of device document.
     * @param deviceId Device ID
     * @param resources Resources required to localize root name.
     * @param roots List of root information.
     * @return If roots are added or removed from the database.
     */
    synchronized boolean putRootDocuments(
            String parentDocumentId, Resources resources, MtpRoot[] roots) {
    synchronized boolean putRootDocuments(int deviceId, Resources resources, MtpRoot[] roots) {
        final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
        database.beginTransaction();
        try {
            final boolean heuristic;
            final String mapColumn;
            Preconditions.checkState(mMappingMode.containsKey(parentDocumentId));
            switch (mMappingMode.get(parentDocumentId)) {
            Preconditions.checkState(mMappingMode.containsKey(/* no parent for root */ null));
            switch (mMappingMode.get(/* no parent for root */ null)) {
                case MAP_BY_MTP_IDENTIFIER:
                    heuristic = false;
                    mapColumn = COLUMN_STORAGE_ID;
@@ -106,14 +83,16 @@ class Mapper {
            }
            final ContentValues[] valuesList = new ContentValues[roots.length];
            for (int i = 0; i < roots.length; i++) {
                if (roots[i].mDeviceId != deviceId) {
                    throw new IllegalArgumentException();
                }
                valuesList[i] = new ContentValues();
                MtpDatabase.getStorageDocumentValues(
                        valuesList[i], resources, parentDocumentId, roots[i]);
                MtpDatabase.getRootDocumentValues(valuesList[i], resources, roots[i]);
            }
            final boolean changed = putDocuments(
                    valuesList,
                    COLUMN_PARENT_DOCUMENT_ID + "=?",
                    strings(parentDocumentId),
                    COLUMN_PARENT_DOCUMENT_ID + " IS NULL",
                    new String[0],
                    heuristic,
                    mapColumn);
            final ContentValues values = new ContentValues();
@@ -167,7 +146,7 @@ class Mapper {
        final ContentValues[] valuesList = new ContentValues[documents.length];
        for (int i = 0; i < documents.length; i++) {
            valuesList[i] = new ContentValues();
            MtpDatabase.getObjectDocumentValues(
            MtpDatabase.getChildDocumentValues(
                    valuesList[i], deviceId, parentId, documents[i]);
        }
        putDocuments(
@@ -214,7 +193,7 @@ class Mapper {
            args = strings(parentDocumentId);
        } else {
            selection = COLUMN_PARENT_DOCUMENT_ID + " IS NULL";
            args = EMPTY_ARGS;
            args = new String[0];
        }

        final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
@@ -333,7 +312,7 @@ class Mapper {
            args = strings(parentId);
        } else {
            selection = COLUMN_PARENT_DOCUMENT_ID + " IS NULL";
            args = EMPTY_ARGS;
            args = new String[0];
        }
        final String groupKey;
        switch (mMappingMode.get(parentId)) {
+13 −39
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
@@ -36,9 +35,9 @@ import android.provider.DocumentsContract.Root;
import com.android.internal.annotations.VisibleForTesting;

import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * Database for MTP objects.
@@ -108,14 +107,11 @@ class MtpDatabase {
     * @return Database cursor.
     */
    Cursor queryRoots(String[] columnNames) {
        final SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
        builder.setTables(JOIN_ROOTS);
        builder.setProjectionMap(COLUMN_MAP_ROOTS);
        return builder.query(
                mDatabase,
        return mDatabase.query(
                VIEW_ROOTS,
                columnNames,
                COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_DOCUMENT_TYPE + " = ?",
                strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED, DOCUMENT_TYPE_STORAGE),
                COLUMN_ROW_STATE + " IN (?, ?)",
                strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED),
                null,
                null,
                null);
@@ -132,8 +128,8 @@ class MtpDatabase {
        return mDatabase.query(
                TABLE_DOCUMENTS,
                columnNames,
                COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_DOCUMENT_TYPE + "=?",
                strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED, DOCUMENT_TYPE_STORAGE),
                COLUMN_ROW_STATE + " IN (?, ?)",
                strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED),
                null,
                null,
                null);
@@ -220,7 +216,7 @@ class MtpDatabase {
     */
    String putNewDocument(int deviceId, String parentDocumentId, MtpObjectInfo info) {
        final ContentValues values = new ContentValues();
        getObjectDocumentValues(values, deviceId, parentDocumentId, info);
        getChildDocumentValues(values, deviceId, parentDocumentId, info);
        mDatabase.beginTransaction();
        try {
            final long id = mDatabase.insert(TABLE_DOCUMENTS, null, values);
@@ -348,6 +344,7 @@ class MtpDatabase {
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(QUERY_CREATE_DOCUMENTS);
            db.execSQL(QUERY_CREATE_ROOT_EXTRA);
            db.execSQL(QUERY_CREATE_VIEW_ROOTS);
        }

        @Override
@@ -361,41 +358,18 @@ class MtpDatabase {
        context.deleteDatabase(DATABASE_NAME);
    }

    static void getDeviceDocumentValues(
            ContentValues values, int deviceId, String name, MtpRoot[] roots) {
        values.clear();
        values.put(COLUMN_DEVICE_ID, deviceId);
        values.putNull(COLUMN_STORAGE_ID);
        values.putNull(COLUMN_OBJECT_HANDLE);
        values.putNull(COLUMN_PARENT_DOCUMENT_ID);
        values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
        values.put(COLUMN_DOCUMENT_TYPE, DOCUMENT_TYPE_DEVICE);
        values.put(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
        values.put(Document.COLUMN_DISPLAY_NAME, name);
        values.putNull(Document.COLUMN_SUMMARY);
        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 : roots) {
            size += root.mMaxCapacity - root.mFreeSpace;
        }
        values.put(Document.COLUMN_SIZE, size);
    }

    /**
     * Gets {@link ContentValues} for the given root.
     * @param values {@link ContentValues} that receives values.
     * @param resources Resources used to get localized root name.
     * @param root Root to be converted {@link ContentValues}.
     */
    static void getStorageDocumentValues(
            ContentValues values, Resources resources, String parentDocumentId, MtpRoot root) {
    static void getRootDocumentValues(ContentValues values, Resources resources, MtpRoot root) {
        values.clear();
        values.put(COLUMN_DEVICE_ID, root.mDeviceId);
        values.put(COLUMN_STORAGE_ID, root.mStorageId);
        values.putNull(COLUMN_OBJECT_HANDLE);
        values.put(COLUMN_PARENT_DOCUMENT_ID, parentDocumentId);
        values.putNull(COLUMN_PARENT_DOCUMENT_ID);
        values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
        values.put(COLUMN_DOCUMENT_TYPE, DOCUMENT_TYPE_STORAGE);
        values.put(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
@@ -415,7 +389,7 @@ class MtpDatabase {
     * @param parentId Parent document ID of the object.
     * @param info MTP object info.
     */
    static void getObjectDocumentValues(
    static void getChildDocumentValues(
            ContentValues values, int deviceId, String parentId, MtpObjectInfo info) {
        values.clear();
        final String mimeType = info.getFormat() == MtpConstants.FORMAT_ASSOCIATION ?
+29 −36
Original line number Diff line number Diff line
@@ -16,13 +16,9 @@

package com.android.mtp;

import android.database.sqlite.SQLiteQueryBuilder;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;

import java.util.HashMap;
import java.util.Map;

/**
 * Class containing MtpDatabase constants.
 */
@@ -45,13 +41,9 @@ class MtpDatabaseConstants {
    static final String TABLE_ROOT_EXTRA = "RootExtra";

    /**
     * 'FROM' closure of joining TABLE_DOCUMENTS and TABLE_ROOT_EXTRA.
     * View to join Documents and RootExtra tables to provide roots information.
     */
    static final String JOIN_ROOTS = createJoinFromClosure(
            TABLE_DOCUMENTS,
            TABLE_ROOT_EXTRA,
            Document.COLUMN_DOCUMENT_ID,
            Root.COLUMN_ROOT_ID);
    static final String VIEW_ROOTS = "Roots";

    static final String COLUMN_DEVICE_ID = "device_id";
    static final String COLUMN_STORAGE_ID = "storage_id";
@@ -94,6 +86,8 @@ class MtpDatabaseConstants {

    /**
     * Document that represents a MTP device.
     * Note we have "device" document only when the device has multiple storage volumes. Otherwise
     * we regard the single "storage" document as root.
     */
    static final int DOCUMENT_TYPE_DEVICE = 0;

@@ -137,31 +131,30 @@ class MtpDatabaseConstants {
            Root.COLUMN_MIME_TYPES + " TEXT NOT NULL);";

    /**
     * Map for columns names to provide DocumentContract.Root compatible columns.
     * @see SQLiteQueryBuilder#setProjectionMap(Map)
     * Creates a view to join Documents table and RootExtra table on their primary keys to
     * provide DocumentContract.Root equivalent information.
     */
    static final Map<String, String> COLUMN_MAP_ROOTS;
    static {
        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);
        COLUMN_MAP_ROOTS.put(
                Root.COLUMN_DOCUMENT_ID, TABLE_DOCUMENTS + "." + Document.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);
    }

    private static String createJoinFromClosure(
            String table1, String table2, String column1, String column2) {
        return table1 + " INNER JOIN " + table2 +
                " ON " + table1 + "." + column1 + " = " + table2 + "." + column2;
    }
    static final String QUERY_CREATE_VIEW_ROOTS =
            "CREATE VIEW " + VIEW_ROOTS + " AS SELECT " +
                    TABLE_DOCUMENTS + "." + Document.COLUMN_DOCUMENT_ID + " AS " +
                            Root.COLUMN_ROOT_ID + "," +
                    TABLE_ROOT_EXTRA + "." + Root.COLUMN_FLAGS + "," +
                    TABLE_DOCUMENTS + "." + Document.COLUMN_ICON + " AS " +
                            Root.COLUMN_ICON + "," +
                    TABLE_DOCUMENTS + "." + Document.COLUMN_DISPLAY_NAME + " AS " +
                            Root.COLUMN_TITLE + "," +
                    TABLE_DOCUMENTS + "." + Document.COLUMN_SUMMARY + " AS " +
                            Root.COLUMN_SUMMARY + "," +
                    TABLE_DOCUMENTS + "." + Document.COLUMN_DOCUMENT_ID + " AS " +
                    Root.COLUMN_DOCUMENT_ID + "," +
                    TABLE_ROOT_EXTRA + "." + Root.COLUMN_AVAILABLE_BYTES + "," +
                    TABLE_ROOT_EXTRA + "." + Root.COLUMN_CAPACITY_BYTES + "," +
                    TABLE_ROOT_EXTRA + "." + Root.COLUMN_MIME_TYPES + "," +
                    TABLE_DOCUMENTS + "." + COLUMN_ROW_STATE +
            " FROM " + TABLE_DOCUMENTS + " INNER JOIN " + TABLE_ROOT_EXTRA +
            " ON " +
                    COLUMN_PARENT_DOCUMENT_ID + " IS NULL AND " +
                    TABLE_DOCUMENTS + "." + Document.COLUMN_DOCUMENT_ID +
                    "=" +
                    TABLE_ROOT_EXTRA + "." + Root.COLUMN_ROOT_ID;
}
+3 −0
Original line number Diff line number Diff line
@@ -190,6 +190,9 @@ public class MtpDocumentsProvider extends DocumentsProvider {
            getDocumentLoader(parentIdentifier).clearTask(parentIdentifier);
            notifyChildDocumentsChange(parentIdentifier.mDocumentId);
        } catch (IOException error) {
            for (final StackTraceElement element : error.getStackTrace()) {
                Log.e("hirono", element.toString());
            }
            throw new FileNotFoundException(error.getMessage());
        }
    }
+8 −27
Original line number Diff line number Diff line
@@ -7,11 +7,8 @@ import android.net.Uri;
import android.os.Process;
import android.provider.DocumentsContract;
import android.util.Log;
import android.util.SparseArray;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
@@ -109,42 +106,26 @@ final class RootScanner {
            int pollingCount = 0;
            while (!Thread.interrupted()) {
                final int[] deviceIds = mManager.getOpenedDeviceIds();
                final Map<String, MtpRoot[]> rootsMap = new HashMap<>();
                if (deviceIds.length == 0) {
                    return;
                }
                boolean changed = false;

                // Update devices.
                mDatabase.getMapper().startAddingDocuments(null /* parentDocumentId */);
                for (final int deviceId : deviceIds) {
                for (int deviceId : deviceIds) {
                    try {
                        final MtpRoot[] roots = mManager.getRoots(deviceId);
                        final String id = mDatabase.getMapper().putDeviceDocument(
                                deviceId,
                                mManager.getDeviceName(deviceId),
                                roots);
                        if (id != null) {
                        if (mDatabase.getMapper().putRootDocuments(deviceId, mResources, roots)) {
                            changed = true;
                            rootsMap.put(id, roots);
                        }
                    } catch (IOException exception) {
                    } catch (IOException | SQLiteException exception) {
                        // The error may happen on the device. We would like to continue getting
                        // roots for other devices.
                        Log.e(MtpDocumentsProvider.TAG, exception.getMessage());
                    }
                }
                mDatabase.getMapper().stopAddingDocuments(null /* parentDocumentId */);

                // Update roots.
                for (final String documentId : rootsMap.keySet()) {
                    mDatabase.getMapper().startAddingDocuments(documentId);
                    if (mDatabase.getMapper().putRootDocuments(
                            documentId, mResources, rootsMap.get(documentId))) {
                        changed = true;
                    }
                    if (mDatabase.getMapper().stopAddingDocuments(documentId)) {
                if (mDatabase.getMapper().stopAddingDocuments(null /* parentDocumentId */)) {
                    changed = true;
                }
                }

                if (changed) {
                    notifyChange();
                }
Loading