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