Home | History | Annotate | Download | only in mtp
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.mtp;
     18 
     19 import android.annotation.IntDef;
     20 import android.database.sqlite.SQLiteQueryBuilder;
     21 import android.provider.DocumentsContract.Document;
     22 import android.provider.DocumentsContract.Root;
     23 
     24 import java.lang.annotation.Retention;
     25 import java.lang.annotation.RetentionPolicy;
     26 import java.util.HashMap;
     27 import java.util.Map;
     28 
     29 /**
     30  * Class containing MtpDatabase constants.
     31  */
     32 class MtpDatabaseConstants {
     33     static final int DATABASE_VERSION = 5;
     34     static final String DATABASE_NAME = "database";
     35 
     36     static final int FLAG_DATABASE_IN_MEMORY = 1;
     37     static final int FLAG_DATABASE_IN_FILE = 0;
     38 
     39     /**
     40      * Table representing documents including root documents.
     41      */
     42     static final String TABLE_DOCUMENTS = "Documents";
     43 
     44     /**
     45      * Table containing additional information only available for root documents.
     46      * The table uses same primary keys with corresponding documents.
     47      */
     48     static final String TABLE_ROOT_EXTRA = "RootExtra";
     49 
     50     /**
     51      * Table containing last boot count.
     52      */
     53     static final String TABLE_LAST_BOOT_COUNT = "LastBootCount";
     54 
     55     /**
     56      * 'FROM' closure of joining TABLE_DOCUMENTS and TABLE_ROOT_EXTRA.
     57      */
     58     static final String JOIN_ROOTS = createJoinFromClosure(
     59             TABLE_DOCUMENTS,
     60             TABLE_ROOT_EXTRA,
     61             Document.COLUMN_DOCUMENT_ID,
     62             Root.COLUMN_ROOT_ID);
     63 
     64     static final String COLUMN_DEVICE_ID = "device_id";
     65     static final String COLUMN_STORAGE_ID = "storage_id";
     66     static final String COLUMN_OBJECT_HANDLE = "object_handle";
     67     static final String COLUMN_PARENT_DOCUMENT_ID = "parent_document_id";
     68     static final String COLUMN_DOCUMENT_TYPE = "document_type";
     69     static final String COLUMN_ROW_STATE = "row_state";
     70     static final String COLUMN_MAPPING_KEY = "mapping_key";
     71 
     72     /**
     73      * Value for TABLE_LAST_BOOT_COUNT.
     74      * Type: INTEGER
     75      */
     76     static final String COLUMN_VALUE = "value";
     77 
     78     /**
     79      * The state represents that the row has a valid object handle.
     80      */
     81     static final int ROW_STATE_VALID = 0;
     82 
     83     /**
     84      * The state represents that the rows added at the previous cycle and need to be updated with
     85      * fresh values.
     86      * The row may not have valid object handle. External application can still fetch the documents.
     87      * If the external application tries to fetch object handle, the provider resolves pending
     88      * documents with invalidated documents ahead.
     89      */
     90     static final int ROW_STATE_INVALIDATED = 1;
     91 
     92     /**
     93      * The documents are of device/storage that are disconnected now. The documents are invisible
     94      * but their document ID will be reuse when the device/storage is connected again.
     95      */
     96     static final int ROW_STATE_DISCONNECTED = 2;
     97 
     98     @IntDef(value = { DOCUMENT_TYPE_DEVICE, DOCUMENT_TYPE_STORAGE, DOCUMENT_TYPE_OBJECT })
     99     @Retention(RetentionPolicy.SOURCE)
    100     public @interface DocumentType {}
    101 
    102     /**
    103      * Document that represents a MTP device.
    104      */
    105     static final int DOCUMENT_TYPE_DEVICE = 0;
    106 
    107     /**
    108      * Document that represents a MTP storage.
    109      */
    110     static final int DOCUMENT_TYPE_STORAGE = 1;
    111 
    112     /**
    113      * Document that represents a MTP object.
    114      */
    115     static final int DOCUMENT_TYPE_OBJECT = 2;
    116 
    117     static final String SELECTION_DOCUMENT_ID = Document.COLUMN_DOCUMENT_ID + " = ?";
    118     static final String SELECTION_ROOT_ID = Root.COLUMN_ROOT_ID + " = ?";
    119 
    120     static final String QUERY_CREATE_DOCUMENTS =
    121             "CREATE TABLE " + TABLE_DOCUMENTS + " (" +
    122             Document.COLUMN_DOCUMENT_ID +
    123                 " INTEGER PRIMARY KEY AUTOINCREMENT," +
    124             COLUMN_DEVICE_ID + " INTEGER," +
    125             COLUMN_STORAGE_ID + " INTEGER," +
    126             COLUMN_OBJECT_HANDLE + " INTEGER," +
    127             COLUMN_PARENT_DOCUMENT_ID + " INTEGER," +
    128             COLUMN_ROW_STATE + " INTEGER NOT NULL," +
    129             COLUMN_DOCUMENT_TYPE + " INTEGER NOT NULL," +
    130             COLUMN_MAPPING_KEY + " STRING," +
    131             Document.COLUMN_MIME_TYPE + " TEXT NOT NULL," +
    132             Document.COLUMN_DISPLAY_NAME + " TEXT NOT NULL," +
    133             Document.COLUMN_SUMMARY + " TEXT," +
    134             Document.COLUMN_LAST_MODIFIED + " INTEGER," +
    135             Document.COLUMN_ICON + " INTEGER," +
    136             Document.COLUMN_FLAGS + " INTEGER NOT NULL," +
    137             Document.COLUMN_SIZE + " INTEGER);";
    138 
    139     static final String QUERY_CREATE_ROOT_EXTRA =
    140             "CREATE TABLE " + TABLE_ROOT_EXTRA + " (" +
    141             Root.COLUMN_ROOT_ID + " INTEGER PRIMARY KEY," +
    142             Root.COLUMN_FLAGS + " INTEGER NOT NULL," +
    143             Root.COLUMN_AVAILABLE_BYTES + " INTEGER," +
    144             Root.COLUMN_CAPACITY_BYTES + " INTEGER," +
    145             Root.COLUMN_MIME_TYPES + " TEXT NOT NULL);";
    146 
    147     static final String QUERY_CREATE_LAST_BOOT_COUNT =
    148             "CREATE TABLE " + TABLE_LAST_BOOT_COUNT + " (value INTEGER NOT NULL);";
    149 
    150     /**
    151      * Map for columns names to provide DocumentContract.Root compatible columns.
    152      * @see SQLiteQueryBuilder#setProjectionMap(Map)
    153      */
    154     static final Map<String, String> COLUMN_MAP_ROOTS;
    155     static {
    156         COLUMN_MAP_ROOTS = new HashMap<>();
    157         COLUMN_MAP_ROOTS.put(Root.COLUMN_ROOT_ID, TABLE_ROOT_EXTRA + "." + Root.COLUMN_ROOT_ID);
    158         COLUMN_MAP_ROOTS.put(Root.COLUMN_FLAGS, TABLE_ROOT_EXTRA + "." + Root.COLUMN_FLAGS);
    159         COLUMN_MAP_ROOTS.put(
    160                 Root.COLUMN_ICON,
    161                 TABLE_DOCUMENTS + "." + Document.COLUMN_ICON + " AS " + Root.COLUMN_ICON);
    162         COLUMN_MAP_ROOTS.put(
    163                 Root.COLUMN_TITLE,
    164                 TABLE_DOCUMENTS + "." + Document.COLUMN_DISPLAY_NAME + " AS " + Root.COLUMN_TITLE);
    165         COLUMN_MAP_ROOTS.put(
    166                 Root.COLUMN_SUMMARY,
    167                 TABLE_DOCUMENTS + "." + Document.COLUMN_SUMMARY + " AS " + Root.COLUMN_SUMMARY);
    168         COLUMN_MAP_ROOTS.put(
    169                 Root.COLUMN_DOCUMENT_ID,
    170                 TABLE_DOCUMENTS + "." + Document.COLUMN_DOCUMENT_ID +
    171                 " AS " + Root.COLUMN_DOCUMENT_ID);
    172         COLUMN_MAP_ROOTS.put(
    173                 Root.COLUMN_AVAILABLE_BYTES, TABLE_ROOT_EXTRA + "." + Root.COLUMN_AVAILABLE_BYTES);
    174         COLUMN_MAP_ROOTS.put(
    175                 Root.COLUMN_CAPACITY_BYTES, TABLE_ROOT_EXTRA + "." + Root.COLUMN_CAPACITY_BYTES);
    176         COLUMN_MAP_ROOTS.put(
    177                 Root.COLUMN_MIME_TYPES, TABLE_ROOT_EXTRA + "." + Root.COLUMN_MIME_TYPES);
    178         COLUMN_MAP_ROOTS.put(COLUMN_DEVICE_ID, COLUMN_DEVICE_ID);
    179     }
    180 
    181     private static String createJoinFromClosure(
    182             String table1, String table2, String column1, String column2) {
    183         return table1 + " LEFT JOIN " + table2 +
    184                 " ON " + table1 + "." + column1 + " = " + table2 + "." + column2;
    185     }
    186 }
    187