blob: 7fe6cb96352265e3d65d3ce0e44069a98f4da232 [file] [log] [blame]
Daichi Hirono6de8a0e2015-10-27 16:18:17 +09001/*
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
Daichi Hirono9678f602015-10-22 12:35:05 +090017package com.android.mtp;
18
Daichi Hirono9678f602015-10-22 12:35:05 +090019import android.database.Cursor;
Daichi Hirono497b4732016-03-14 14:46:37 +090020import android.media.MediaFile;
21import android.media.MediaFile.MediaFileType;
Daichi Hirono9678f602015-10-22 12:35:05 +090022import android.mtp.MtpConstants;
23import android.mtp.MtpObjectInfo;
Daichi Hirono3bb37e72016-02-29 15:30:56 +090024import android.net.Uri;
Daichi Hirono9678f602015-10-22 12:35:05 +090025import android.provider.DocumentsContract;
Daichi Hirono49f920f2015-11-19 10:19:52 +090026import android.provider.DocumentsContract.Document;
Daichi Hirono0378da42015-11-05 11:56:12 +090027import android.provider.DocumentsContract.Root;
Daichi Hirono9678f602015-10-22 12:35:05 +090028import android.test.AndroidTestCase;
29import android.test.suitebuilder.annotation.SmallTest;
30
Daichi Hirono49f920f2015-11-19 10:19:52 +090031import java.io.FileNotFoundException;
Daichi Hirono3bb37e72016-02-29 15:30:56 +090032import java.util.Arrays;
Daichi Hirono49f920f2015-11-19 10:19:52 +090033
Daichi Hirono9984ebd2015-12-15 16:02:27 +090034import static android.provider.DocumentsContract.Document.*;
Daichi Hirono259ce802015-11-20 17:51:53 +090035import static com.android.mtp.MtpDatabase.strings;
Daichi Hirono9984ebd2015-12-15 16:02:27 +090036import static com.android.mtp.MtpDatabaseConstants.*;
Daichi Hirono0f325372016-02-21 15:50:30 +090037import static com.android.mtp.TestUtil.OPERATIONS_SUPPORTED;
Daichi Hirono49f920f2015-11-19 10:19:52 +090038
Daichi Hirono9678f602015-10-22 12:35:05 +090039@SmallTest
40public class MtpDatabaseTest extends AndroidTestCase {
Daichi Hirono0f325372016-02-21 15:50:30 +090041 private static final String[] COLUMN_NAMES = new String[] {
Daichi Hirono9678f602015-10-22 12:35:05 +090042 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +090043 MtpDatabaseConstants.COLUMN_DEVICE_ID,
44 MtpDatabaseConstants.COLUMN_STORAGE_ID,
45 MtpDatabaseConstants.COLUMN_OBJECT_HANDLE,
Daichi Hirono9678f602015-10-22 12:35:05 +090046 DocumentsContract.Document.COLUMN_MIME_TYPE,
47 DocumentsContract.Document.COLUMN_DISPLAY_NAME,
48 DocumentsContract.Document.COLUMN_SUMMARY,
49 DocumentsContract.Document.COLUMN_LAST_MODIFIED,
50 DocumentsContract.Document.COLUMN_ICON,
51 DocumentsContract.Document.COLUMN_FLAGS,
Daichi Hirono4b54e032015-12-11 15:24:53 +090052 DocumentsContract.Document.COLUMN_SIZE,
53 MtpDatabaseConstants.COLUMN_DOCUMENT_TYPE
Daichi Hirono9678f602015-10-22 12:35:05 +090054 };
55
Daichi Hirono85a808b2015-10-27 17:22:13 +090056 private final TestResources resources = new TestResources();
Daichi Hirono4604b742015-11-12 12:12:48 +090057 MtpDatabase mDatabase;
58
59 @Override
60 public void setUp() {
Daichi Hirono47eb1922015-11-16 13:01:31 +090061 mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
Daichi Hirono4604b742015-11-12 12:12:48 +090062 }
63
64 @Override
65 public void tearDown() {
66 mDatabase.close();
67 mDatabase = null;
68 }
Daichi Hirono85a808b2015-10-27 17:22:13 +090069
Daichi Hirono9984ebd2015-12-15 16:02:27 +090070 private static int getInt(Cursor cursor, String columnName) {
71 return cursor.getInt(cursor.getColumnIndex(columnName));
72 }
73
74 private static boolean isNull(Cursor cursor, String columnName) {
75 return cursor.isNull(cursor.getColumnIndex(columnName));
76 }
77
78 private static String getString(Cursor cursor, String columnName) {
79 return cursor.getString(cursor.getColumnIndex(columnName));
80 }
81
Daichi Hirono81d48532015-12-16 15:03:19 +090082 public void testPutSingleStorageDocuments() throws Exception {
Daichi Hirono0f325372016-02-21 15:50:30 +090083 addTestDevice();
Daichi Hirono81d48532015-12-16 15:03:19 +090084
85 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +090086 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +090087 new MtpRoot(0, 1, "Storage", 1000, 2000, "")
Daichi Hirono81d48532015-12-16 15:03:19 +090088 });
89 mDatabase.getMapper().stopAddingDocuments("1");
90
91 {
92 final Cursor cursor = mDatabase.queryRootDocuments(COLUMN_NAMES);
93 assertEquals(1, cursor.getCount());
94
95 cursor.moveToNext();
96 assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
97 assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
98 assertEquals(1, getInt(cursor, COLUMN_STORAGE_ID));
99 assertTrue(isNull(cursor, COLUMN_OBJECT_HANDLE));
Daichi Hirono8e873642016-02-07 15:17:16 +0900100 assertEquals(
101 DocumentsContract.Document.MIME_TYPE_DIR, getString(cursor, COLUMN_MIME_TYPE));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900102 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono81d48532015-12-16 15:03:19 +0900103 assertTrue(isNull(cursor, COLUMN_SUMMARY));
104 assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
105 assertEquals(R.drawable.ic_root_mtp, getInt(cursor, COLUMN_ICON));
Daichi Hironob3383fd2016-03-18 15:25:00 +0900106 assertEquals(Document.FLAG_DIR_SUPPORTS_CREATE, getInt(cursor, COLUMN_FLAGS));
Daichi Hirono81d48532015-12-16 15:03:19 +0900107 assertEquals(1000, getInt(cursor, COLUMN_SIZE));
108 assertEquals(
Daichi Hirono8e873642016-02-07 15:17:16 +0900109 MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE,
110 getInt(cursor, COLUMN_DOCUMENT_TYPE));
Daichi Hirono81d48532015-12-16 15:03:19 +0900111
112 cursor.close();
113 }
114
115 {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900116 final Cursor cursor = mDatabase.queryRoots(resources, new String [] {
Daichi Hirono81d48532015-12-16 15:03:19 +0900117 Root.COLUMN_ROOT_ID,
118 Root.COLUMN_FLAGS,
119 Root.COLUMN_ICON,
120 Root.COLUMN_TITLE,
121 Root.COLUMN_SUMMARY,
122 Root.COLUMN_DOCUMENT_ID,
123 Root.COLUMN_AVAILABLE_BYTES,
124 Root.COLUMN_CAPACITY_BYTES
125 });
126 assertEquals(1, cursor.getCount());
127
128 cursor.moveToNext();
Daichi Hirono6a5ea7e2016-02-02 16:35:03 +0900129 assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
Daichi Hirono81d48532015-12-16 15:03:19 +0900130 assertEquals(
Daichi Hirono83c679e72016-08-18 15:13:36 +0900131 Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY,
Daichi Hirono81d48532015-12-16 15:03:19 +0900132 getInt(cursor, Root.COLUMN_FLAGS));
133 assertEquals(R.drawable.ic_root_mtp, getInt(cursor, Root.COLUMN_ICON));
134 assertEquals("Device Storage", getString(cursor, Root.COLUMN_TITLE));
135 assertTrue(isNull(cursor, Root.COLUMN_SUMMARY));
Daichi Hirono6a5ea7e2016-02-02 16:35:03 +0900136 assertEquals(1, getInt(cursor, Root.COLUMN_DOCUMENT_ID));
Daichi Hirono81d48532015-12-16 15:03:19 +0900137 assertEquals(1000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
138 assertEquals(2000, getInt(cursor, Root.COLUMN_CAPACITY_BYTES));
139
140 cursor.close();
141 }
142 }
143
144 public void testPutStorageDocuments() throws Exception {
Daichi Hirono619afda2016-02-07 14:23:43 +0900145 addTestDevice();
146
147 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900148 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900149 new MtpRoot(0, 1, "Storage", 1000, 2000, ""),
150 new MtpRoot(0, 2, "Storage", 2000, 4000, ""),
151 new MtpRoot(0, 3, "/@#%&<>Storage", 3000, 6000,"")
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900152 });
Daichi Hirono9678f602015-10-22 12:35:05 +0900153
Daichi Hirono0378da42015-11-05 11:56:12 +0900154 {
Daichi Hirono4604b742015-11-12 12:12:48 +0900155 final Cursor cursor = mDatabase.queryRootDocuments(COLUMN_NAMES);
Daichi Hirono0378da42015-11-05 11:56:12 +0900156 assertEquals(3, cursor.getCount());
Daichi Hirono9678f602015-10-22 12:35:05 +0900157
Daichi Hirono0378da42015-11-05 11:56:12 +0900158 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900159 assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900160 assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
161 assertEquals(1, getInt(cursor, COLUMN_STORAGE_ID));
162 assertTrue(isNull(cursor, COLUMN_OBJECT_HANDLE));
163 assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, getString(cursor, COLUMN_MIME_TYPE));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900164 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900165 assertTrue(isNull(cursor, COLUMN_SUMMARY));
166 assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
167 assertEquals(R.drawable.ic_root_mtp, getInt(cursor, COLUMN_ICON));
Daichi Hironob3383fd2016-03-18 15:25:00 +0900168 assertEquals(Document.FLAG_DIR_SUPPORTS_CREATE, getInt(cursor, COLUMN_FLAGS));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900169 assertEquals(1000, getInt(cursor, COLUMN_SIZE));
Daichi Hirono4b54e032015-12-11 15:24:53 +0900170 assertEquals(
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900171 MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE, getInt(cursor, COLUMN_DOCUMENT_TYPE));
Daichi Hirono9678f602015-10-22 12:35:05 +0900172
Daichi Hirono0378da42015-11-05 11:56:12 +0900173 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900174 assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900175 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono9678f602015-10-22 12:35:05 +0900176
Daichi Hirono0378da42015-11-05 11:56:12 +0900177 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900178 assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900179 assertEquals("/@#%&<>Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono88d2f782015-10-27 16:41:06 +0900180
Daichi Hirono0378da42015-11-05 11:56:12 +0900181 cursor.close();
182 }
Daichi Hirono9678f602015-10-22 12:35:05 +0900183 }
184
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900185 private MtpObjectInfo createDocument(int objectHandle, String name, int format, int size) {
Daichi Hirono9678f602015-10-22 12:35:05 +0900186 final MtpObjectInfo.Builder builder = new MtpObjectInfo.Builder();
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900187 builder.setObjectHandle(objectHandle);
188 builder.setName(name);
189 builder.setFormat(format);
190 builder.setCompressedSize(size);
191 return builder.build();
192 }
Daichi Hirono9678f602015-10-22 12:35:05 +0900193
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900194 public void testPutChildDocuments() throws Exception {
Daichi Hirono619afda2016-02-07 14:23:43 +0900195 addTestDevice();
196 addTestStorage("1");
197
198 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900199 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900200 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
201 createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
202 createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
Daichi Hirono64111e02016-03-24 21:07:38 +0900203 }, new long[] { 1024L, 2L * 1024L * 1024L, 3L * 1024L * 1024L});
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900204
Daichi Hirono619afda2016-02-07 14:23:43 +0900205 final Cursor cursor = mDatabase.queryChildDocuments(COLUMN_NAMES, "2");
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900206 assertEquals(3, cursor.getCount());
207
Daichi Hirono9678f602015-10-22 12:35:05 +0900208 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900209 assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900210 assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
211 assertEquals(0, getInt(cursor, COLUMN_STORAGE_ID));
212 assertEquals(100, getInt(cursor, COLUMN_OBJECT_HANDLE));
213 assertEquals("text/plain", getString(cursor, COLUMN_MIME_TYPE));
214 assertEquals("note.txt", getString(cursor, COLUMN_DISPLAY_NAME));
215 assertTrue(isNull(cursor, COLUMN_SUMMARY));
216 assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
217 assertTrue(isNull(cursor, COLUMN_ICON));
Daichi Hirono9678f602015-10-22 12:35:05 +0900218 assertEquals(
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900219 COLUMN_FLAGS,
Daichi Hirono9678f602015-10-22 12:35:05 +0900220 DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
221 DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
Daichi Hirono88d2f782015-10-27 16:41:06 +0900222 cursor.getInt(9));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900223 assertEquals(1024, getInt(cursor, COLUMN_SIZE));
Daichi Hirono4b54e032015-12-11 15:24:53 +0900224 assertEquals(
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900225 MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, getInt(cursor, COLUMN_DOCUMENT_TYPE));
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900226
227 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900228 assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900229 assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
230 assertEquals(0, getInt(cursor, COLUMN_STORAGE_ID));
231 assertEquals(101, getInt(cursor, COLUMN_OBJECT_HANDLE));
232 assertEquals("image/jpeg", getString(cursor, COLUMN_MIME_TYPE));
233 assertEquals("image.jpg", getString(cursor, COLUMN_DISPLAY_NAME));
234 assertTrue(isNull(cursor, COLUMN_SUMMARY));
235 assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
236 assertTrue(isNull(cursor, COLUMN_ICON));
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900237 assertEquals(
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900238 COLUMN_FLAGS,
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900239 DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
240 DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
241 cursor.getInt(9));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900242 assertEquals(2 * 1024 * 1024, getInt(cursor, COLUMN_SIZE));
Daichi Hirono4b54e032015-12-11 15:24:53 +0900243 assertEquals(
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900244 MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, getInt(cursor, COLUMN_DOCUMENT_TYPE));
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900245
246 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900247 assertEquals(5, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900248 assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
249 assertEquals(0, getInt(cursor, COLUMN_STORAGE_ID));
250 assertEquals(102, getInt(cursor, COLUMN_OBJECT_HANDLE));
251 assertEquals("audio/mpeg", getString(cursor, COLUMN_MIME_TYPE));
252 assertEquals("music.mp3", getString(cursor, COLUMN_DISPLAY_NAME));
253 assertTrue(isNull(cursor, COLUMN_SUMMARY));
254 assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
255 assertTrue(isNull(cursor, COLUMN_ICON));
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900256 assertEquals(
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900257 COLUMN_FLAGS,
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900258 DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
259 DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
260 cursor.getInt(9));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900261 assertEquals(3 * 1024 * 1024, getInt(cursor, COLUMN_SIZE));
Daichi Hirono4b54e032015-12-11 15:24:53 +0900262 assertEquals(
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900263 MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, getInt(cursor, COLUMN_DOCUMENT_TYPE));
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900264
265 cursor.close();
Daichi Hirono9678f602015-10-22 12:35:05 +0900266 }
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900267
Daichi Hirono61ba9232016-02-26 12:58:39 +0900268 public void testPutChildDocuments_operationsSupported() throws Exception {
269 addTestDevice();
270 addTestStorage("1");
271
272 // Put a document with empty supported operations.
273 mDatabase.getMapper().startAddingDocuments("2");
274 mDatabase.getMapper().putChildDocuments(0, "2", new int[0], new MtpObjectInfo[] {
275 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
Daichi Hirono64111e02016-03-24 21:07:38 +0900276 }, new long[] { 1024L });
Daichi Hirono61ba9232016-02-26 12:58:39 +0900277 mDatabase.getMapper().stopAddingDocuments("2");
278
279 try (final Cursor cursor =
280 mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
281 assertEquals(1, cursor.getCount());
282 cursor.moveToNext();
283 assertEquals(0, cursor.getInt(0));
284 }
285
286 // Put a document with writable operations.
287 mDatabase.getMapper().startAddingDocuments("2");
288 mDatabase.getMapper().putChildDocuments(0, "2", new int[] {
289 MtpConstants.OPERATION_SEND_OBJECT,
290 MtpConstants.OPERATION_SEND_OBJECT_INFO,
291 }, new MtpObjectInfo[] {
292 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
Daichi Hirono64111e02016-03-24 21:07:38 +0900293 }, new long[] { 1024L });
Daichi Hirono61ba9232016-02-26 12:58:39 +0900294 mDatabase.getMapper().stopAddingDocuments("2");
295
296 try (final Cursor cursor =
297 mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
298 assertEquals(1, cursor.getCount());
299 cursor.moveToNext();
300 assertEquals(Document.FLAG_SUPPORTS_WRITE, cursor.getInt(0));
301 }
302
303 // Put a document with deletable operations.
304 mDatabase.getMapper().startAddingDocuments("2");
305 mDatabase.getMapper().putChildDocuments(0, "2", new int[] {
306 MtpConstants.OPERATION_DELETE_OBJECT
307 }, new MtpObjectInfo[] {
308 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
Daichi Hirono64111e02016-03-24 21:07:38 +0900309 }, new long[] { 1024L });
Daichi Hirono61ba9232016-02-26 12:58:39 +0900310 mDatabase.getMapper().stopAddingDocuments("2");
311
312 try (final Cursor cursor =
313 mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
314 assertEquals(1, cursor.getCount());
315 cursor.moveToNext();
316 assertEquals(Document.FLAG_SUPPORTS_DELETE, cursor.getInt(0));
317 }
318 }
319
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900320 public void testRestoreIdForRootDocuments() throws Exception {
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900321 final String[] columns = new String[] {
322 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +0900323 MtpDatabaseConstants.COLUMN_STORAGE_ID,
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900324 DocumentsContract.Document.COLUMN_DISPLAY_NAME
325 };
Daichi Hirono4604b742015-11-12 12:12:48 +0900326
Daichi Hirono619afda2016-02-07 14:23:43 +0900327 // Add device and two storages.
328 addTestDevice();
329 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900330 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900331 new MtpRoot(0, 100, "Storage A", 1000, 0, ""),
332 new MtpRoot(0, 101, "Storage B", 1001, 0, "")
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900333 });
334
335 {
Daichi Hirono4604b742015-11-12 12:12:48 +0900336 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900337 assertEquals(2, cursor.getCount());
338 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900339 assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900340 assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900341 assertEquals("Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900342 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900343 assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900344 assertEquals(101, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900345 assertEquals("Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900346 cursor.close();
347 }
348
Daichi Hirono619afda2016-02-07 14:23:43 +0900349 // Clear mapping and add a device.
Daichi Hirono259ce802015-11-20 17:51:53 +0900350 mDatabase.getMapper().clearMapping();
Daichi Hirono619afda2016-02-07 14:23:43 +0900351 addTestDevice();
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900352
353 {
Daichi Hirono4604b742015-11-12 12:12:48 +0900354 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hirono8e873642016-02-07 15:17:16 +0900355 assertEquals(0, cursor.getCount());
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900356 cursor.close();
357 }
358
Daichi Hirono619afda2016-02-07 14:23:43 +0900359 // Add two storages, but one's name is different from previous one.
360 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900361 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900362 new MtpRoot(0, 200, "Storage A", 2000, 0, ""),
363 new MtpRoot(0, 202, "Storage C", 2002, 0, "")
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900364 });
Daichi Hirono619afda2016-02-07 14:23:43 +0900365 mDatabase.getMapper().stopAddingDocuments("1");
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900366
367 {
Daichi Hirono8e873642016-02-07 15:17:16 +0900368 // After compeleting mapping, Storage A can be obtained with new storage ID.
Daichi Hirono4604b742015-11-12 12:12:48 +0900369 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900370 assertEquals(2, cursor.getCount());
371 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900372 assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900373 assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900374 assertEquals("Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900375 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900376 assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900377 assertEquals(202, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900378 assertEquals("Storage C", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900379 cursor.close();
380 }
381 }
382
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900383 public void testRestoreIdForChildDocuments() throws Exception {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900384 final String[] columns = new String[] {
385 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +0900386 MtpDatabaseConstants.COLUMN_OBJECT_HANDLE,
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900387 DocumentsContract.Document.COLUMN_DISPLAY_NAME
388 };
Daichi Hirono619afda2016-02-07 14:23:43 +0900389
390 addTestDevice();
391 addTestStorage("1");
392
393 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900394 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900395 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
396 createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
397 createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
Daichi Hirono64111e02016-03-24 21:07:38 +0900398 }, new long[] { 1024L, 2L * 1024L * 1024L, 3L * 1024L * 1024L});
Daichi Hirono259ce802015-11-20 17:51:53 +0900399 mDatabase.getMapper().clearMapping();
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900400
Daichi Hirono619afda2016-02-07 14:23:43 +0900401 addTestDevice();
402 addTestStorage("1");
403
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900404 {
Daichi Hirono8e873642016-02-07 15:17:16 +0900405 // Don't return objects that lost MTP object handles.
Daichi Hirono619afda2016-02-07 14:23:43 +0900406 final Cursor cursor = mDatabase.queryChildDocuments(columns, "2");
Daichi Hirono8e873642016-02-07 15:17:16 +0900407 assertEquals(0, cursor.getCount());
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900408 cursor.close();
409 }
410
Daichi Hirono619afda2016-02-07 14:23:43 +0900411 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900412 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900413 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
414 createDocument(203, "video.mp4", MtpConstants.FORMAT_MP4_CONTAINER, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900415 }, new long[] { 1024L, 1024L });
Daichi Hirono619afda2016-02-07 14:23:43 +0900416 mDatabase.getMapper().stopAddingDocuments("2");
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900417
418 {
Daichi Hirono619afda2016-02-07 14:23:43 +0900419 final Cursor cursor = mDatabase.queryChildDocuments(columns, "2");
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900420 assertEquals(2, cursor.getCount());
421
422 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900423 assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900424 assertEquals(200, getInt(cursor, COLUMN_OBJECT_HANDLE));
425 assertEquals("note.txt", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900426
427 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900428 assertEquals(6, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900429 assertEquals(203, getInt(cursor, COLUMN_OBJECT_HANDLE));
430 assertEquals("video.mp4", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono619afda2016-02-07 14:23:43 +0900431
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900432 cursor.close();
433 }
434 }
435
Daichi Hironob3fe72b2015-12-15 07:45:06 +0000436 public void testRestoreIdForDifferentDevices() throws Exception {
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900437 final String[] columns = new String[] {
438 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +0900439 MtpDatabaseConstants.COLUMN_STORAGE_ID,
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900440 DocumentsContract.Document.COLUMN_DISPLAY_NAME
441 };
Daichi Hirono0378da42015-11-05 11:56:12 +0900442 final String[] rootColumns = new String[] {
443 Root.COLUMN_ROOT_ID,
444 Root.COLUMN_AVAILABLE_BYTES
445 };
Daichi Hirono81d48532015-12-16 15:03:19 +0900446 mDatabase.getMapper().startAddingDocuments(null);
Daichi Hirono619afda2016-02-07 14:23:43 +0900447 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
Daichi Hironoebd24052016-02-06 21:05:57 +0900448 0, "Device A", "Device key A", true, new MtpRoot[0], null, null));
Daichi Hirono619afda2016-02-07 14:23:43 +0900449 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
Daichi Hironoebd24052016-02-06 21:05:57 +0900450 1, "Device B", "Device key B", true, new MtpRoot[0], null, null));
Daichi Hirono81d48532015-12-16 15:03:19 +0900451 mDatabase.getMapper().stopAddingDocuments(null);
452
453 mDatabase.getMapper().startAddingDocuments("1");
454 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono0f325372016-02-21 15:50:30 +0900455 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900456 new MtpRoot(0, 100, "Storage", 0, 0, "")
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900457 });
Daichi Hirono0f325372016-02-21 15:50:30 +0900458 mDatabase.getMapper().putStorageDocuments("2", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900459 new MtpRoot(1, 100, "Storage", 0, 0, "")
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900460 });
461
462 {
Daichi Hirono4604b742015-11-12 12:12:48 +0900463 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900464 assertEquals(2, cursor.getCount());
465 cursor.moveToNext();
Daichi Hirono81d48532015-12-16 15:03:19 +0900466 assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900467 assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900468 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900469 cursor.moveToNext();
Daichi Hirono81d48532015-12-16 15:03:19 +0900470 assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900471 assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900472 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900473 cursor.close();
474 }
475
Daichi Hirono0378da42015-11-05 11:56:12 +0900476 {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900477 final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
Daichi Hirono0378da42015-11-05 11:56:12 +0900478 assertEquals(2, cursor.getCount());
479 cursor.moveToNext();
Daichi Hirono6a5ea7e2016-02-02 16:35:03 +0900480 assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900481 assertEquals(0, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
Daichi Hirono0378da42015-11-05 11:56:12 +0900482 cursor.moveToNext();
Daichi Hirono6a5ea7e2016-02-02 16:35:03 +0900483 assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900484 assertEquals(0, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
Daichi Hirono0378da42015-11-05 11:56:12 +0900485 cursor.close();
486 }
487
Daichi Hirono259ce802015-11-20 17:51:53 +0900488 mDatabase.getMapper().clearMapping();
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900489
Daichi Hirono619afda2016-02-07 14:23:43 +0900490 mDatabase.getMapper().startAddingDocuments(null);
491 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
Daichi Hironoebd24052016-02-06 21:05:57 +0900492 0, "Device A", "Device key A", true, new MtpRoot[0], null, null));
Daichi Hirono619afda2016-02-07 14:23:43 +0900493 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
Daichi Hironoebd24052016-02-06 21:05:57 +0900494 1, "Device B", "Device key B", true, new MtpRoot[0], null, null));
Daichi Hirono619afda2016-02-07 14:23:43 +0900495 mDatabase.getMapper().stopAddingDocuments(null);
496
Daichi Hirono81d48532015-12-16 15:03:19 +0900497 mDatabase.getMapper().startAddingDocuments("1");
498 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono0f325372016-02-21 15:50:30 +0900499 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900500 new MtpRoot(0, 200, "Storage", 2000, 0, "")
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900501 });
Daichi Hirono0f325372016-02-21 15:50:30 +0900502 mDatabase.getMapper().putStorageDocuments("2", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900503 new MtpRoot(1, 300, "Storage", 3000, 0, "")
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900504 });
Daichi Hirono81d48532015-12-16 15:03:19 +0900505 mDatabase.getMapper().stopAddingDocuments("1");
506 mDatabase.getMapper().stopAddingDocuments("2");
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900507
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900508 {
Daichi Hirono4604b742015-11-12 12:12:48 +0900509 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900510 assertEquals(2, cursor.getCount());
511 cursor.moveToNext();
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900512 assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900513 assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900514 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900515 cursor.moveToNext();
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900516 assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900517 assertEquals(300, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900518 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900519 cursor.close();
520 }
Daichi Hirono0378da42015-11-05 11:56:12 +0900521
522 {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900523 final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
Daichi Hirono0378da42015-11-05 11:56:12 +0900524 assertEquals(2, cursor.getCount());
525 cursor.moveToNext();
Daichi Hirono6a5ea7e2016-02-02 16:35:03 +0900526 assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900527 assertEquals(2000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
Daichi Hirono0378da42015-11-05 11:56:12 +0900528 cursor.moveToNext();
Daichi Hirono6a5ea7e2016-02-02 16:35:03 +0900529 assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900530 assertEquals(3000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
Daichi Hirono0378da42015-11-05 11:56:12 +0900531 cursor.close();
532 }
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900533 }
534
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900535 public void testRestoreIdForDifferentParents() throws Exception {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900536 final String[] columns = new String[] {
537 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +0900538 MtpDatabaseConstants.COLUMN_OBJECT_HANDLE
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900539 };
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900540
Daichi Hirono619afda2016-02-07 14:23:43 +0900541 // Add device, storage, and two directories.
542 addTestDevice();
543 addTestStorage("1");
544 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900545 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hirono619afda2016-02-07 14:23:43 +0900546 createDocument(50, "A", MtpConstants.FORMAT_ASSOCIATION, 0),
547 createDocument(51, "B", MtpConstants.FORMAT_ASSOCIATION, 0),
Daichi Hirono64111e02016-03-24 21:07:38 +0900548 }, new long[] { 0L, 0L });
Daichi Hirono619afda2016-02-07 14:23:43 +0900549 mDatabase.getMapper().stopAddingDocuments("2");
550
551 // Put note.txt in each directory.
552 mDatabase.getMapper().startAddingDocuments("3");
553 mDatabase.getMapper().startAddingDocuments("4");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900554 mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900555 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900556 }, new long[] { 1024L });
Daichi Hirono61ba9232016-02-26 12:58:39 +0900557 mDatabase.getMapper().putChildDocuments(0, "4", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900558 createDocument(101, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900559 }, new long[] { 1024L });
Daichi Hirono619afda2016-02-07 14:23:43 +0900560
561 // Clear mapping.
Daichi Hirono259ce802015-11-20 17:51:53 +0900562 mDatabase.getMapper().clearMapping();
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900563
Daichi Hirono619afda2016-02-07 14:23:43 +0900564 // Add device, storage, and two directories again.
565 addTestDevice();
566 addTestStorage("1");
567 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900568 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hirono619afda2016-02-07 14:23:43 +0900569 createDocument(50, "A", MtpConstants.FORMAT_ASSOCIATION, 0),
570 createDocument(51, "B", MtpConstants.FORMAT_ASSOCIATION, 0),
Daichi Hirono64111e02016-03-24 21:07:38 +0900571 }, new long[] { 0L, 0L });
Daichi Hirono619afda2016-02-07 14:23:43 +0900572 mDatabase.getMapper().stopAddingDocuments("2");
573
574 // Add note.txt in each directory again.
575 mDatabase.getMapper().startAddingDocuments("3");
576 mDatabase.getMapper().startAddingDocuments("4");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900577 mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900578 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900579 }, new long[] { 1024L });
Daichi Hirono61ba9232016-02-26 12:58:39 +0900580 mDatabase.getMapper().putChildDocuments(0, "4", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900581 createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900582 }, new long[] { 1024L });
Daichi Hirono619afda2016-02-07 14:23:43 +0900583 mDatabase.getMapper().stopAddingDocuments("3");
584 mDatabase.getMapper().stopAddingDocuments("4");
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900585
Daichi Hirono619afda2016-02-07 14:23:43 +0900586 // Check if the two note.txt are mapped correctly.
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900587 {
Daichi Hirono619afda2016-02-07 14:23:43 +0900588 final Cursor cursor = mDatabase.queryChildDocuments(columns, "3");
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900589 assertEquals(1, cursor.getCount());
590 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900591 assertEquals(5, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900592 assertEquals(200, getInt(cursor, COLUMN_OBJECT_HANDLE));
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900593 cursor.close();
594 }
595 {
Daichi Hirono619afda2016-02-07 14:23:43 +0900596 final Cursor cursor = mDatabase.queryChildDocuments(columns, "4");
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900597 assertEquals(1, cursor.getCount());
598 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900599 assertEquals(6, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9fca5412016-02-07 13:20:22 +0900600 assertEquals(201, getInt(cursor, COLUMN_OBJECT_HANDLE));
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900601 cursor.close();
602 }
603 }
604
Daichi Hirono619afda2016-02-07 14:23:43 +0900605 public void testClearMtpIdentifierBeforeResolveRootDocuments() throws Exception {
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900606 final String[] columns = new String[] {
607 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +0900608 MtpDatabaseConstants.COLUMN_STORAGE_ID,
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900609 DocumentsContract.Document.COLUMN_DISPLAY_NAME
610 };
Daichi Hirono0378da42015-11-05 11:56:12 +0900611 final String[] rootColumns = new String[] {
612 Root.COLUMN_ROOT_ID,
613 Root.COLUMN_AVAILABLE_BYTES
614 };
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900615
Daichi Hirono8e873642016-02-07 15:17:16 +0900616 addTestDevice();
Daichi Hirono81d48532015-12-16 15:03:19 +0900617
618 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900619 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900620 new MtpRoot(0, 100, "Storage", 0, 0, ""),
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900621 });
Daichi Hirono259ce802015-11-20 17:51:53 +0900622 mDatabase.getMapper().clearMapping();
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900623
Daichi Hironoebd24052016-02-06 21:05:57 +0900624 addTestDevice();
Daichi Hirono619afda2016-02-07 14:23:43 +0900625
626 try (final Cursor cursor = mDatabase.queryRoots(resources, rootColumns)) {
627 assertEquals(1, cursor.getCount());
628 cursor.moveToNext();
629 assertEquals("1", getString(cursor, Root.COLUMN_ROOT_ID));
630 }
631
Daichi Hirono81d48532015-12-16 15:03:19 +0900632 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900633 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900634 new MtpRoot(0, 200, "Storage", 2000, 0, ""),
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900635 });
Daichi Hirono259ce802015-11-20 17:51:53 +0900636 mDatabase.getMapper().clearMapping();
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900637
Daichi Hironoebd24052016-02-06 21:05:57 +0900638 addTestDevice();
Daichi Hirono619afda2016-02-07 14:23:43 +0900639
Daichi Hirono81d48532015-12-16 15:03:19 +0900640 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900641 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900642 new MtpRoot(0, 300, "Storage", 3000, 0, ""),
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900643 });
Daichi Hirono81d48532015-12-16 15:03:19 +0900644 mDatabase.getMapper().stopAddingDocuments("1");
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900645
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900646 {
Daichi Hirono4604b742015-11-12 12:12:48 +0900647 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900648 assertEquals(1, cursor.getCount());
649 cursor.moveToNext();
Daichi Hirono81d48532015-12-16 15:03:19 +0900650 assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900651 assertEquals(300, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900652 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900653 cursor.close();
654 }
Daichi Hirono0378da42015-11-05 11:56:12 +0900655 {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900656 final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
Daichi Hirono0378da42015-11-05 11:56:12 +0900657 assertEquals(1, cursor.getCount());
658 cursor.moveToNext();
Daichi Hirono6a5ea7e2016-02-02 16:35:03 +0900659 assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900660 assertEquals(3000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
Daichi Hirono0378da42015-11-05 11:56:12 +0900661 cursor.close();
662 }
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900663 }
664
665 public void testPutSameNameRootsAfterClearing() throws Exception {
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900666 final String[] columns = new String[] {
667 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +0900668 MtpDatabaseConstants.COLUMN_STORAGE_ID,
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900669 DocumentsContract.Document.COLUMN_DISPLAY_NAME
670 };
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900671
Daichi Hirono619afda2016-02-07 14:23:43 +0900672 // Add a device and a storage.
673 addTestDevice();
674 addTestStorage("1");
675
676 // Disconnect devices.
Daichi Hirono259ce802015-11-20 17:51:53 +0900677 mDatabase.getMapper().clearMapping();
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900678
Daichi Hirono619afda2016-02-07 14:23:43 +0900679 // Add a device and two storages that has same name.
680 addTestDevice();
681 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900682 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900683 new MtpRoot(0, 200, "Storage", 2000, 0, ""),
684 new MtpRoot(0, 201, "Storage", 2001, 0, ""),
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900685 });
Daichi Hirono619afda2016-02-07 14:23:43 +0900686 mDatabase.getMapper().stopAddingDocuments("1");
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900687
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900688 {
Daichi Hirono4604b742015-11-12 12:12:48 +0900689 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900690 assertEquals(2, cursor.getCount());
Daichi Hirono619afda2016-02-07 14:23:43 +0900691
692 // First storage reuse document ID of previous storage.
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900693 cursor.moveToNext();
Daichi Hirono9fca5412016-02-07 13:20:22 +0900694 // One reuses exisitng document ID 1.
Daichi Hirono619afda2016-02-07 14:23:43 +0900695 assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900696 assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900697 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono619afda2016-02-07 14:23:43 +0900698
699 // Second one has new document ID.
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900700 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900701 assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900702 assertEquals(201, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900703 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono619afda2016-02-07 14:23:43 +0900704
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900705 cursor.close();
706 }
707 }
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900708
Daichi Hirono619afda2016-02-07 14:23:43 +0900709 public void testReplaceExistingRoots() throws Exception {
Daichi Hirono8e873642016-02-07 15:17:16 +0900710 addTestDevice();
Daichi Hirono81d48532015-12-16 15:03:19 +0900711
Daichi Hirono4604b742015-11-12 12:12:48 +0900712 // The client code should be able to replace existing rows with new information.
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900713 // Add one.
Daichi Hirono81d48532015-12-16 15:03:19 +0900714 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900715 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900716 new MtpRoot(0, 100, "Storage A", 0, 0, ""),
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900717 });
Daichi Hirono81d48532015-12-16 15:03:19 +0900718 mDatabase.getMapper().stopAddingDocuments("1");
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900719 // Replace it.
Daichi Hirono81d48532015-12-16 15:03:19 +0900720 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900721 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900722 new MtpRoot(0, 100, "Storage B", 1000, 1000, ""),
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900723 });
Daichi Hirono81d48532015-12-16 15:03:19 +0900724 mDatabase.getMapper().stopAddingDocuments("1");
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900725 {
726 final String[] columns = new String[] {
727 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +0900728 MtpDatabaseConstants.COLUMN_STORAGE_ID,
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900729 DocumentsContract.Document.COLUMN_DISPLAY_NAME
730 };
Daichi Hirono4604b742015-11-12 12:12:48 +0900731 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900732 assertEquals(1, cursor.getCount());
733 cursor.moveToNext();
Daichi Hirono81d48532015-12-16 15:03:19 +0900734 assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900735 assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900736 assertEquals("Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900737 cursor.close();
738 }
739 {
740 final String[] columns = new String[] {
741 Root.COLUMN_ROOT_ID,
Daichi Hirono81d48532015-12-16 15:03:19 +0900742 Root.COLUMN_TITLE,
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900743 Root.COLUMN_AVAILABLE_BYTES
744 };
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900745 final Cursor cursor = mDatabase.queryRoots(resources, columns);
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900746 assertEquals(1, cursor.getCount());
747 cursor.moveToNext();
Daichi Hirono6a5ea7e2016-02-02 16:35:03 +0900748 assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
Daichi Hirono81d48532015-12-16 15:03:19 +0900749 assertEquals("Device Storage B", getString(cursor, Root.COLUMN_TITLE));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900750 assertEquals(1000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900751 cursor.close();
752 }
753 }
754
Daichi Hirono619afda2016-02-07 14:23:43 +0900755 public void testFailToReplaceExisitingUnmappedRoots() throws Exception {
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900756 // The client code should not be able to replace rows before resolving 'unmapped' rows.
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900757 // Add one.
Daichi Hirono619afda2016-02-07 14:23:43 +0900758 addTestDevice();
Daichi Hirono81d48532015-12-16 15:03:19 +0900759 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900760 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900761 new MtpRoot(0, 100, "Storage A", 0, 0, ""),
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900762 });
Daichi Hirono259ce802015-11-20 17:51:53 +0900763 mDatabase.getMapper().clearMapping();
Daichi Hirono49f920f2015-11-19 10:19:52 +0900764
Daichi Hirono619afda2016-02-07 14:23:43 +0900765 addTestDevice();
766 try (final Cursor oldCursor =
767 mDatabase.queryRoots(resources, strings(Root.COLUMN_ROOT_ID))) {
768 assertEquals(1, oldCursor.getCount());
769 oldCursor.moveToNext();
770 assertEquals("1", getString(oldCursor, Root.COLUMN_ROOT_ID));
Daichi Hirono49f920f2015-11-19 10:19:52 +0900771
Daichi Hirono619afda2016-02-07 14:23:43 +0900772 // Add one.
773 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900774 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hirono619afda2016-02-07 14:23:43 +0900775 new MtpRoot(0, 101, "Storage B", 1000, 1000, ""),
776 });
777 // Add one more before resolving unmapped documents.
Daichi Hirono0f325372016-02-21 15:50:30 +0900778 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hirono619afda2016-02-07 14:23:43 +0900779 new MtpRoot(0, 102, "Storage B", 1000, 1000, ""),
780 });
781 mDatabase.getMapper().stopAddingDocuments("1");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900782
Daichi Hirono619afda2016-02-07 14:23:43 +0900783 // Because the roots shares the same name, the roots should have new IDs.
784 try (final Cursor newCursor = mDatabase.queryChildDocuments(
785 strings(Document.COLUMN_DOCUMENT_ID), "1")) {
786 assertEquals(2, newCursor.getCount());
787 newCursor.moveToNext();
788 assertFalse(oldCursor.getString(0).equals(newCursor.getString(0)));
789 newCursor.moveToNext();
790 assertFalse(oldCursor.getString(0).equals(newCursor.getString(0)));
791 }
792 }
Daichi Hirono49f920f2015-11-19 10:19:52 +0900793 }
794
Daichi Hirono619afda2016-02-07 14:23:43 +0900795 public void testQueryDocuments() throws Exception {
796 addTestDevice();
797 addTestStorage("1");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900798
Daichi Hirono619afda2016-02-07 14:23:43 +0900799 final Cursor cursor = mDatabase.queryDocument("2", strings(Document.COLUMN_DISPLAY_NAME));
Daichi Hirono49f920f2015-11-19 10:19:52 +0900800 assertEquals(1, cursor.getCount());
801 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900802 assertEquals("Storage", getString(cursor, Document.COLUMN_DISPLAY_NAME));
Daichi Hirono49f920f2015-11-19 10:19:52 +0900803 cursor.close();
804 }
805
Daichi Hirono619afda2016-02-07 14:23:43 +0900806 public void testQueryRoots() throws Exception {
Daichi Hirono81d48532015-12-16 15:03:19 +0900807 // Add device document.
Daichi Hirono8e873642016-02-07 15:17:16 +0900808 addTestDevice();
Daichi Hirono81d48532015-12-16 15:03:19 +0900809
810 // It the device does not have storages, it shows a device root.
811 {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900812 final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
Daichi Hirono81d48532015-12-16 15:03:19 +0900813 assertEquals(1, cursor.getCount());
814 cursor.moveToNext();
815 assertEquals("Device", cursor.getString(0));
816 cursor.close();
817 }
818
819 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900820 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900821 new MtpRoot(0, 100, "Storage A", 0, 0, "")
Daichi Hirono81d48532015-12-16 15:03:19 +0900822 });
823 mDatabase.getMapper().stopAddingDocuments("1");
824
825 // It the device has single storage, it shows a storage root.
826 {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900827 final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
Daichi Hirono81d48532015-12-16 15:03:19 +0900828 assertEquals(1, cursor.getCount());
829 cursor.moveToNext();
830 assertEquals("Device Storage A", cursor.getString(0));
831 cursor.close();
832 }
833
834 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900835 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900836 new MtpRoot(0, 100, "Storage A", 0, 0, ""),
837 new MtpRoot(0, 101, "Storage B", 0, 0, "")
Daichi Hirono81d48532015-12-16 15:03:19 +0900838 });
839 mDatabase.getMapper().stopAddingDocuments("1");
840
841 // It the device has multiple storages, it shows a device root.
842 {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900843 final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
Daichi Hirono81d48532015-12-16 15:03:19 +0900844 assertEquals(1, cursor.getCount());
845 cursor.moveToNext();
846 assertEquals("Device", cursor.getString(0));
847 cursor.close();
848 }
849 }
850
Daichi Hirono49f920f2015-11-19 10:19:52 +0900851 public void testGetParentId() throws FileNotFoundException {
Daichi Hirono619afda2016-02-07 14:23:43 +0900852 addTestDevice();
Daichi Hirono49f920f2015-11-19 10:19:52 +0900853
Daichi Hirono7a375c42015-12-14 17:14:29 +0900854 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900855 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900856 new MtpRoot(0, 100, "Storage A", 0, 0, ""),
Daichi Hirono49f920f2015-11-19 10:19:52 +0900857 });
Daichi Hirono7a375c42015-12-14 17:14:29 +0900858 mDatabase.getMapper().stopAddingDocuments("1");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900859
Daichi Hirono7a375c42015-12-14 17:14:29 +0900860 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900861 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
862 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900863 }, new long[] { 1024L });
Daichi Hirono7a375c42015-12-14 17:14:29 +0900864 mDatabase.getMapper().stopAddingDocuments("2");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900865
Daichi Hirono619afda2016-02-07 14:23:43 +0900866 assertEquals("2", mDatabase.getParentIdentifier("3").mDocumentId);
867 }
868
869 public void testDeleteDocument() throws Exception {
870 addTestDevice();
871 addTestStorage("1");
872
873 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900874 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
875 createDocument(200, "dir", MtpConstants.FORMAT_ASSOCIATION, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900876 }, new long[] { 1024L });
Daichi Hirono619afda2016-02-07 14:23:43 +0900877 mDatabase.getMapper().stopAddingDocuments("2");
878
879 mDatabase.getMapper().startAddingDocuments("3");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900880 mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
881 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900882 }, new long[] { 1024L });
Daichi Hirono619afda2016-02-07 14:23:43 +0900883 mDatabase.getMapper().stopAddingDocuments("3");
884
885 mDatabase.deleteDocument("3");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900886
887 {
888 // Do not query deleted documents.
889 final Cursor cursor =
Daichi Hirono619afda2016-02-07 14:23:43 +0900890 mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "2");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900891 assertEquals(0, cursor.getCount());
892 cursor.close();
893 }
894
895 {
896 // Child document should be deleted also.
897 final Cursor cursor =
Daichi Hirono619afda2016-02-07 14:23:43 +0900898 mDatabase.queryDocument("4", strings(Document.COLUMN_DOCUMENT_ID));
Daichi Hirono49f920f2015-11-19 10:19:52 +0900899 assertEquals(0, cursor.getCount());
900 cursor.close();
901 }
902 }
903
Daichi Hirono619afda2016-02-07 14:23:43 +0900904 public void testPutNewDocument() throws Exception {
905 addTestDevice();
906 addTestStorage("1");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900907
908 assertEquals(
Daichi Hirono619afda2016-02-07 14:23:43 +0900909 "3",
Daichi Hirono49f920f2015-11-19 10:19:52 +0900910 mDatabase.putNewDocument(
Daichi Hirono61ba9232016-02-26 12:58:39 +0900911 0, "2", OPERATIONS_SUPPORTED,
Daichi Hirono64111e02016-03-24 21:07:38 +0900912 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
913 1024L));
Daichi Hirono49f920f2015-11-19 10:19:52 +0900914
915 {
916 final Cursor cursor =
Daichi Hirono619afda2016-02-07 14:23:43 +0900917 mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "2");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900918 assertEquals(1, cursor.getCount());
919 cursor.moveToNext();
920 assertEquals("3", cursor.getString(0));
921 cursor.close();
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900922 }
Daichi Hirono619afda2016-02-07 14:23:43 +0900923
924 // The new document should not be mapped with existing invalidated document.
925 mDatabase.getMapper().clearMapping();
Daichi Hirono8e873642016-02-07 15:17:16 +0900926 addTestDevice();
927 addTestStorage("1");
928
Daichi Hirono619afda2016-02-07 14:23:43 +0900929 mDatabase.getMapper().startAddingDocuments("2");
930 mDatabase.putNewDocument(
Daichi Hirono61ba9232016-02-26 12:58:39 +0900931 0, "2", OPERATIONS_SUPPORTED,
Daichi Hirono64111e02016-03-24 21:07:38 +0900932 createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
933 1024L);
Daichi Hirono619afda2016-02-07 14:23:43 +0900934 mDatabase.getMapper().stopAddingDocuments("2");
935
936 {
937 final Cursor cursor =
938 mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "2");
939 assertEquals(1, cursor.getCount());
940 cursor.moveToNext();
941 assertEquals("4", cursor.getString(0));
942 cursor.close();
943 }
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900944 }
Daichi Hirono20754c52015-12-15 18:52:26 +0900945
Daichi Hirono619afda2016-02-07 14:23:43 +0900946 public void testGetDocumentIdForDevice() throws Exception {
947 addTestDevice();
948 assertEquals("1", mDatabase.getDocumentIdForDevice(0));
Daichi Hirono20754c52015-12-15 18:52:26 +0900949 }
Daichi Hirono83983d72016-01-29 17:37:36 +0900950
Daichi Hirono619afda2016-02-07 14:23:43 +0900951 public void testGetClosedDevice() throws Exception {
Daichi Hirono83983d72016-01-29 17:37:36 +0900952 mDatabase.getMapper().startAddingDocuments(null);
953 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
Daichi Hironoebd24052016-02-06 21:05:57 +0900954 0, "Device", null /* deviceKey */, /* opened is */ false, new MtpRoot[0], null,
955 null));
Daichi Hirono83983d72016-01-29 17:37:36 +0900956 mDatabase.getMapper().stopAddingDocuments(null);
957
958 final String[] columns = new String [] {
959 DocumentsContract.Root.COLUMN_ROOT_ID,
960 DocumentsContract.Root.COLUMN_TITLE,
961 DocumentsContract.Root.COLUMN_AVAILABLE_BYTES
962 };
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900963 try (final Cursor cursor = mDatabase.queryRoots(resources, columns)) {
Daichi Hirono83983d72016-01-29 17:37:36 +0900964 assertEquals(1, cursor.getCount());
965 assertTrue(cursor.moveToNext());
966 assertEquals(1, cursor.getLong(0));
967 assertEquals("Device", cursor.getString(1));
968 assertTrue(cursor.isNull(2));
969 }
970 }
Daichi Hirono619afda2016-02-07 14:23:43 +0900971
Daichi Hironoebd24052016-02-06 21:05:57 +0900972 public void testMappingWithoutKey() throws FileNotFoundException {
973 mDatabase.getMapper().startAddingDocuments(null);
974 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
975 0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
976 null));
977 mDatabase.getMapper().stopAddingDocuments(null);
978
979 mDatabase.getMapper().startAddingDocuments(null);
980 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
981 0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
982 null));
983 mDatabase.getMapper().stopAddingDocuments(null);
984
985 try (final Cursor cursor =
986 mDatabase.queryRoots(resources, strings(DocumentsContract.Root.COLUMN_ROOT_ID))) {
987 assertEquals(1, cursor.getCount());
988 assertTrue(cursor.moveToNext());
989 assertEquals(1, cursor.getLong(0));
990 }
991 }
992
993 public void testMappingFailsWithoutKey() throws FileNotFoundException {
994 mDatabase.getMapper().startAddingDocuments(null);
995 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
996 0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
997 null));
998 mDatabase.getMapper().stopAddingDocuments(null);
999
1000 // MTP identifier is cleared here. Mapping no longer works without device key.
1001 mDatabase.getMapper().startAddingDocuments(null);
1002 mDatabase.getMapper().stopAddingDocuments(null);
1003
1004 mDatabase.getMapper().startAddingDocuments(null);
1005 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
1006 0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
1007 null));
1008 mDatabase.getMapper().stopAddingDocuments(null);
1009
1010 try (final Cursor cursor =
1011 mDatabase.queryRoots(resources, strings(DocumentsContract.Root.COLUMN_ROOT_ID))) {
1012 assertEquals(1, cursor.getCount());
1013 assertTrue(cursor.moveToNext());
1014 assertEquals(2, cursor.getLong(0));
1015 }
1016 }
1017
1018 public void testUpdateDocumentWithoutChange() throws FileNotFoundException {
1019 mDatabase.getMapper().startAddingDocuments(null);
1020 assertTrue(mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
1021 0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null,
1022 null)));
1023 assertFalse(mDatabase.getMapper().stopAddingDocuments(null));
1024
1025 mDatabase.getMapper().startAddingDocuments(null);
1026 assertFalse(mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
1027 0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null,
1028 null)));
1029 assertFalse(mDatabase.getMapper().stopAddingDocuments(null));
1030 }
1031
Daichi Hirono3bb37e72016-02-29 15:30:56 +09001032 public void testSetBootCount() {
1033 assertEquals(0, mDatabase.getLastBootCount());
1034 mDatabase.setLastBootCount(10);
1035 assertEquals(10, mDatabase.getLastBootCount());
1036 try {
1037 mDatabase.setLastBootCount(-1);
1038 fail();
1039 } catch (IllegalArgumentException e) {}
1040 }
1041
1042 public void testCleanDatabase() throws FileNotFoundException {
1043 // Add tree.
1044 addTestDevice();
1045 addTestStorage("1");
1046 mDatabase.getMapper().startAddingDocuments("2");
1047 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
1048 createDocument(100, "apple.txt", MtpConstants.FORMAT_TEXT, 1024),
1049 createDocument(101, "orange.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +09001050 }, new long[] { 1024L, 1024L });
Daichi Hirono3bb37e72016-02-29 15:30:56 +09001051 mDatabase.getMapper().stopAddingDocuments("2");
1052
1053 // Disconnect the device.
1054 mDatabase.getMapper().startAddingDocuments(null);
1055 mDatabase.getMapper().stopAddingDocuments(null);
1056
1057 // Clean database.
1058 mDatabase.cleanDatabase(new Uri[] {
1059 DocumentsContract.buildDocumentUri(MtpDocumentsProvider.AUTHORITY, "3")
1060 });
1061
1062 // Add tree again.
1063 addTestDevice();
1064 addTestStorage("1");
1065 mDatabase.getMapper().startAddingDocuments("2");
1066 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
1067 createDocument(100, "apple.txt", MtpConstants.FORMAT_TEXT, 1024),
1068 createDocument(101, "orange.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +09001069 }, new long[] { 1024L, 1024L });
Daichi Hirono3bb37e72016-02-29 15:30:56 +09001070 mDatabase.getMapper().stopAddingDocuments("2");
1071
1072 try (final Cursor cursor = mDatabase.queryChildDocuments(
1073 strings(COLUMN_DOCUMENT_ID, Document.COLUMN_DISPLAY_NAME), "2")) {
1074 assertEquals(2, cursor.getCount());
1075
1076 // Persistent uri uses the same ID.
1077 cursor.moveToNext();
1078 assertEquals("3", cursor.getString(0));
1079 assertEquals("apple.txt", cursor.getString(1));
1080
1081 // Others does not.
1082 cursor.moveToNext();
1083 assertEquals("5", cursor.getString(0));
1084 assertEquals("orange.txt", cursor.getString(1));
1085 }
1086 }
1087
Daichi Hirono497b4732016-03-14 14:46:37 +09001088 public void testFormatCodeForMpeg() throws FileNotFoundException {
1089 addTestDevice();
1090 addTestStorage("1");
1091 mDatabase.getMapper().startAddingDocuments("2");
1092 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
1093 createDocument(100, "audio.m4a", MtpConstants.FORMAT_MPEG, 1000),
1094 createDocument(101, "video.m4v", MtpConstants.FORMAT_MPEG, 1000),
1095 createDocument(102, "unknown.mp4", MtpConstants.FORMAT_MPEG, 1000),
1096 createDocument(103, "inconsistent.txt", MtpConstants.FORMAT_MPEG, 1000),
1097 createDocument(104, "noext", MtpConstants.FORMAT_UNDEFINED, 1000),
Daichi Hirono64111e02016-03-24 21:07:38 +09001098 }, new long[] { 1000L, 1000L, 1000L, 1000L, 1000L });
Daichi Hirono497b4732016-03-14 14:46:37 +09001099 mDatabase.getMapper().stopAddingDocuments("2");
1100 try (final Cursor cursor = mDatabase.queryChildDocuments(
1101 strings(COLUMN_DISPLAY_NAME, COLUMN_MIME_TYPE),
1102 "2")) {
1103 assertEquals(5, cursor.getCount());
1104 cursor.moveToNext();
1105 assertEquals("audio.m4a", cursor.getString(0));
1106 assertEquals("audio/mp4", cursor.getString(1));
1107 cursor.moveToNext();
1108 assertEquals("video.m4v", cursor.getString(0));
1109 assertEquals("video/mp4", cursor.getString(1));
1110 cursor.moveToNext();
1111 // Assume that the file is video as we don't have any hints to find out if the file is
1112 // video or audio.
1113 assertEquals("unknown.mp4", cursor.getString(0));
1114 assertEquals("video/mp4", cursor.getString(1));
1115 // Don't return mime type that is inconsistent with format code.
1116 cursor.moveToNext();
1117 assertEquals("inconsistent.txt", cursor.getString(0));
Daichi Hironodaa61d42016-08-10 14:59:18 +09001118 assertEquals("video/mpeg", cursor.getString(1));
Daichi Hirono497b4732016-03-14 14:46:37 +09001119 cursor.moveToNext();
1120 assertEquals("noext", cursor.getString(0));
1121 assertEquals("application/octet-stream", cursor.getString(1));
1122 }
1123 }
1124
Daichi Hirono619afda2016-02-07 14:23:43 +09001125 private void addTestDevice() throws FileNotFoundException {
Daichi Hironof578fa22016-02-19 18:05:42 +09001126 TestUtil.addTestDevice(mDatabase);
Daichi Hirono619afda2016-02-07 14:23:43 +09001127 }
1128
1129 private void addTestStorage(String parentId) throws FileNotFoundException {
Daichi Hironof578fa22016-02-19 18:05:42 +09001130 TestUtil.addTestStorage(mDatabase, parentId);
Daichi Hirono619afda2016-02-07 14:23:43 +09001131 }
Daichi Hirono9678f602015-10-22 12:35:05 +09001132}