blob: 32b169e6fa9f1017157c8f64d4e5859c86ffcf17 [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 |
Steve McKay5a10ff12017-08-01 15:02:50 -0700240 DocumentsContract.Document.FLAG_SUPPORTS_WRITE |
241 DocumentsContract.Document.FLAG_SUPPORTS_METADATA,
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900242 cursor.getInt(9));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900243 assertEquals(2 * 1024 * 1024, getInt(cursor, COLUMN_SIZE));
Daichi Hirono4b54e032015-12-11 15:24:53 +0900244 assertEquals(
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900245 MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, getInt(cursor, COLUMN_DOCUMENT_TYPE));
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900246
247 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900248 assertEquals(5, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900249 assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
250 assertEquals(0, getInt(cursor, COLUMN_STORAGE_ID));
251 assertEquals(102, getInt(cursor, COLUMN_OBJECT_HANDLE));
252 assertEquals("audio/mpeg", getString(cursor, COLUMN_MIME_TYPE));
253 assertEquals("music.mp3", getString(cursor, COLUMN_DISPLAY_NAME));
254 assertTrue(isNull(cursor, COLUMN_SUMMARY));
255 assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
256 assertTrue(isNull(cursor, COLUMN_ICON));
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900257 assertEquals(
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900258 COLUMN_FLAGS,
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900259 DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
260 DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
261 cursor.getInt(9));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900262 assertEquals(3 * 1024 * 1024, getInt(cursor, COLUMN_SIZE));
Daichi Hirono4b54e032015-12-11 15:24:53 +0900263 assertEquals(
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900264 MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, getInt(cursor, COLUMN_DOCUMENT_TYPE));
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900265
266 cursor.close();
Daichi Hirono9678f602015-10-22 12:35:05 +0900267 }
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900268
Daichi Hirono61ba9232016-02-26 12:58:39 +0900269 public void testPutChildDocuments_operationsSupported() throws Exception {
270 addTestDevice();
271 addTestStorage("1");
272
273 // Put a document with empty supported operations.
274 mDatabase.getMapper().startAddingDocuments("2");
275 mDatabase.getMapper().putChildDocuments(0, "2", new int[0], new MtpObjectInfo[] {
276 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
Daichi Hirono64111e02016-03-24 21:07:38 +0900277 }, new long[] { 1024L });
Daichi Hirono61ba9232016-02-26 12:58:39 +0900278 mDatabase.getMapper().stopAddingDocuments("2");
279
280 try (final Cursor cursor =
281 mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
282 assertEquals(1, cursor.getCount());
283 cursor.moveToNext();
284 assertEquals(0, cursor.getInt(0));
285 }
286
287 // Put a document with writable operations.
288 mDatabase.getMapper().startAddingDocuments("2");
289 mDatabase.getMapper().putChildDocuments(0, "2", new int[] {
290 MtpConstants.OPERATION_SEND_OBJECT,
291 MtpConstants.OPERATION_SEND_OBJECT_INFO,
292 }, new MtpObjectInfo[] {
293 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
Daichi Hirono64111e02016-03-24 21:07:38 +0900294 }, new long[] { 1024L });
Daichi Hirono61ba9232016-02-26 12:58:39 +0900295 mDatabase.getMapper().stopAddingDocuments("2");
296
297 try (final Cursor cursor =
298 mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
299 assertEquals(1, cursor.getCount());
300 cursor.moveToNext();
301 assertEquals(Document.FLAG_SUPPORTS_WRITE, cursor.getInt(0));
302 }
303
304 // Put a document with deletable operations.
305 mDatabase.getMapper().startAddingDocuments("2");
306 mDatabase.getMapper().putChildDocuments(0, "2", new int[] {
307 MtpConstants.OPERATION_DELETE_OBJECT
308 }, new MtpObjectInfo[] {
309 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
Daichi Hirono64111e02016-03-24 21:07:38 +0900310 }, new long[] { 1024L });
Daichi Hirono61ba9232016-02-26 12:58:39 +0900311 mDatabase.getMapper().stopAddingDocuments("2");
312
313 try (final Cursor cursor =
314 mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
315 assertEquals(1, cursor.getCount());
316 cursor.moveToNext();
317 assertEquals(Document.FLAG_SUPPORTS_DELETE, cursor.getInt(0));
318 }
319 }
320
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900321 public void testRestoreIdForRootDocuments() throws Exception {
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900322 final String[] columns = new String[] {
323 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +0900324 MtpDatabaseConstants.COLUMN_STORAGE_ID,
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900325 DocumentsContract.Document.COLUMN_DISPLAY_NAME
326 };
Daichi Hirono4604b742015-11-12 12:12:48 +0900327
Daichi Hirono619afda2016-02-07 14:23:43 +0900328 // Add device and two storages.
329 addTestDevice();
330 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900331 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900332 new MtpRoot(0, 100, "Storage A", 1000, 0, ""),
333 new MtpRoot(0, 101, "Storage B", 1001, 0, "")
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900334 });
335
336 {
Daichi Hirono4604b742015-11-12 12:12:48 +0900337 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900338 assertEquals(2, cursor.getCount());
339 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900340 assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900341 assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900342 assertEquals("Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900343 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900344 assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900345 assertEquals(101, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900346 assertEquals("Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900347 cursor.close();
348 }
349
Daichi Hirono619afda2016-02-07 14:23:43 +0900350 // Clear mapping and add a device.
Daichi Hirono259ce802015-11-20 17:51:53 +0900351 mDatabase.getMapper().clearMapping();
Daichi Hirono619afda2016-02-07 14:23:43 +0900352 addTestDevice();
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900353
354 {
Daichi Hirono4604b742015-11-12 12:12:48 +0900355 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hirono8e873642016-02-07 15:17:16 +0900356 assertEquals(0, cursor.getCount());
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900357 cursor.close();
358 }
359
Daichi Hirono619afda2016-02-07 14:23:43 +0900360 // Add two storages, but one's name is different from previous one.
361 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900362 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900363 new MtpRoot(0, 200, "Storage A", 2000, 0, ""),
364 new MtpRoot(0, 202, "Storage C", 2002, 0, "")
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900365 });
Daichi Hirono619afda2016-02-07 14:23:43 +0900366 mDatabase.getMapper().stopAddingDocuments("1");
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900367
368 {
Daichi Hirono8e873642016-02-07 15:17:16 +0900369 // After compeleting mapping, Storage A can be obtained with new storage ID.
Daichi Hirono4604b742015-11-12 12:12:48 +0900370 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900371 assertEquals(2, cursor.getCount());
372 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900373 assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900374 assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900375 assertEquals("Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900376 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900377 assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900378 assertEquals(202, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900379 assertEquals("Storage C", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900380 cursor.close();
381 }
382 }
383
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900384 public void testRestoreIdForChildDocuments() throws Exception {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900385 final String[] columns = new String[] {
386 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +0900387 MtpDatabaseConstants.COLUMN_OBJECT_HANDLE,
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900388 DocumentsContract.Document.COLUMN_DISPLAY_NAME
389 };
Daichi Hirono619afda2016-02-07 14:23:43 +0900390
391 addTestDevice();
392 addTestStorage("1");
393
394 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900395 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900396 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
397 createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
398 createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
Daichi Hirono64111e02016-03-24 21:07:38 +0900399 }, new long[] { 1024L, 2L * 1024L * 1024L, 3L * 1024L * 1024L});
Daichi Hirono259ce802015-11-20 17:51:53 +0900400 mDatabase.getMapper().clearMapping();
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900401
Daichi Hirono619afda2016-02-07 14:23:43 +0900402 addTestDevice();
403 addTestStorage("1");
404
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900405 {
Daichi Hirono8e873642016-02-07 15:17:16 +0900406 // Don't return objects that lost MTP object handles.
Daichi Hirono619afda2016-02-07 14:23:43 +0900407 final Cursor cursor = mDatabase.queryChildDocuments(columns, "2");
Daichi Hirono8e873642016-02-07 15:17:16 +0900408 assertEquals(0, cursor.getCount());
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900409 cursor.close();
410 }
411
Daichi Hirono619afda2016-02-07 14:23:43 +0900412 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900413 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900414 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
415 createDocument(203, "video.mp4", MtpConstants.FORMAT_MP4_CONTAINER, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900416 }, new long[] { 1024L, 1024L });
Daichi Hirono619afda2016-02-07 14:23:43 +0900417 mDatabase.getMapper().stopAddingDocuments("2");
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900418
419 {
Daichi Hirono619afda2016-02-07 14:23:43 +0900420 final Cursor cursor = mDatabase.queryChildDocuments(columns, "2");
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900421 assertEquals(2, cursor.getCount());
422
423 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900424 assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900425 assertEquals(200, getInt(cursor, COLUMN_OBJECT_HANDLE));
426 assertEquals("note.txt", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900427
428 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900429 assertEquals(6, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900430 assertEquals(203, getInt(cursor, COLUMN_OBJECT_HANDLE));
431 assertEquals("video.mp4", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono619afda2016-02-07 14:23:43 +0900432
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900433 cursor.close();
434 }
435 }
436
Daichi Hironob3fe72b2015-12-15 07:45:06 +0000437 public void testRestoreIdForDifferentDevices() throws Exception {
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900438 final String[] columns = new String[] {
439 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +0900440 MtpDatabaseConstants.COLUMN_STORAGE_ID,
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900441 DocumentsContract.Document.COLUMN_DISPLAY_NAME
442 };
Daichi Hirono0378da42015-11-05 11:56:12 +0900443 final String[] rootColumns = new String[] {
444 Root.COLUMN_ROOT_ID,
445 Root.COLUMN_AVAILABLE_BYTES
446 };
Daichi Hirono81d48532015-12-16 15:03:19 +0900447 mDatabase.getMapper().startAddingDocuments(null);
Daichi Hirono619afda2016-02-07 14:23:43 +0900448 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
Daichi Hironoebd24052016-02-06 21:05:57 +0900449 0, "Device A", "Device key A", true, new MtpRoot[0], null, null));
Daichi Hirono619afda2016-02-07 14:23:43 +0900450 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
Daichi Hironoebd24052016-02-06 21:05:57 +0900451 1, "Device B", "Device key B", true, new MtpRoot[0], null, null));
Daichi Hirono81d48532015-12-16 15:03:19 +0900452 mDatabase.getMapper().stopAddingDocuments(null);
453
454 mDatabase.getMapper().startAddingDocuments("1");
455 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono0f325372016-02-21 15:50:30 +0900456 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900457 new MtpRoot(0, 100, "Storage", 0, 0, "")
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900458 });
Daichi Hirono0f325372016-02-21 15:50:30 +0900459 mDatabase.getMapper().putStorageDocuments("2", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900460 new MtpRoot(1, 100, "Storage", 0, 0, "")
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900461 });
462
463 {
Daichi Hirono4604b742015-11-12 12:12:48 +0900464 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900465 assertEquals(2, cursor.getCount());
466 cursor.moveToNext();
Daichi Hirono81d48532015-12-16 15:03:19 +0900467 assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900468 assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900469 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900470 cursor.moveToNext();
Daichi Hirono81d48532015-12-16 15:03:19 +0900471 assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900472 assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900473 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900474 cursor.close();
475 }
476
Daichi Hirono0378da42015-11-05 11:56:12 +0900477 {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900478 final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
Daichi Hirono0378da42015-11-05 11:56:12 +0900479 assertEquals(2, cursor.getCount());
480 cursor.moveToNext();
Daichi Hirono6a5ea7e2016-02-02 16:35:03 +0900481 assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900482 assertEquals(0, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
Daichi Hirono0378da42015-11-05 11:56:12 +0900483 cursor.moveToNext();
Daichi Hirono6a5ea7e2016-02-02 16:35:03 +0900484 assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900485 assertEquals(0, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
Daichi Hirono0378da42015-11-05 11:56:12 +0900486 cursor.close();
487 }
488
Daichi Hirono259ce802015-11-20 17:51:53 +0900489 mDatabase.getMapper().clearMapping();
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900490
Daichi Hirono619afda2016-02-07 14:23:43 +0900491 mDatabase.getMapper().startAddingDocuments(null);
492 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
Daichi Hironoebd24052016-02-06 21:05:57 +0900493 0, "Device A", "Device key A", true, new MtpRoot[0], null, null));
Daichi Hirono619afda2016-02-07 14:23:43 +0900494 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
Daichi Hironoebd24052016-02-06 21:05:57 +0900495 1, "Device B", "Device key B", true, new MtpRoot[0], null, null));
Daichi Hirono619afda2016-02-07 14:23:43 +0900496 mDatabase.getMapper().stopAddingDocuments(null);
497
Daichi Hirono81d48532015-12-16 15:03:19 +0900498 mDatabase.getMapper().startAddingDocuments("1");
499 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono0f325372016-02-21 15:50:30 +0900500 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900501 new MtpRoot(0, 200, "Storage", 2000, 0, "")
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900502 });
Daichi Hirono0f325372016-02-21 15:50:30 +0900503 mDatabase.getMapper().putStorageDocuments("2", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900504 new MtpRoot(1, 300, "Storage", 3000, 0, "")
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900505 });
Daichi Hirono81d48532015-12-16 15:03:19 +0900506 mDatabase.getMapper().stopAddingDocuments("1");
507 mDatabase.getMapper().stopAddingDocuments("2");
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900508
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900509 {
Daichi Hirono4604b742015-11-12 12:12:48 +0900510 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900511 assertEquals(2, cursor.getCount());
512 cursor.moveToNext();
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900513 assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900514 assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900515 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900516 cursor.moveToNext();
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900517 assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900518 assertEquals(300, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900519 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900520 cursor.close();
521 }
Daichi Hirono0378da42015-11-05 11:56:12 +0900522
523 {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900524 final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
Daichi Hirono0378da42015-11-05 11:56:12 +0900525 assertEquals(2, cursor.getCount());
526 cursor.moveToNext();
Daichi Hirono6a5ea7e2016-02-02 16:35:03 +0900527 assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900528 assertEquals(2000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
Daichi Hirono0378da42015-11-05 11:56:12 +0900529 cursor.moveToNext();
Daichi Hirono6a5ea7e2016-02-02 16:35:03 +0900530 assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900531 assertEquals(3000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
Daichi Hirono0378da42015-11-05 11:56:12 +0900532 cursor.close();
533 }
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900534 }
535
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900536 public void testRestoreIdForDifferentParents() throws Exception {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900537 final String[] columns = new String[] {
538 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +0900539 MtpDatabaseConstants.COLUMN_OBJECT_HANDLE
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900540 };
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900541
Daichi Hirono619afda2016-02-07 14:23:43 +0900542 // Add device, storage, and two directories.
543 addTestDevice();
544 addTestStorage("1");
545 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900546 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hirono619afda2016-02-07 14:23:43 +0900547 createDocument(50, "A", MtpConstants.FORMAT_ASSOCIATION, 0),
548 createDocument(51, "B", MtpConstants.FORMAT_ASSOCIATION, 0),
Daichi Hirono64111e02016-03-24 21:07:38 +0900549 }, new long[] { 0L, 0L });
Daichi Hirono619afda2016-02-07 14:23:43 +0900550 mDatabase.getMapper().stopAddingDocuments("2");
551
552 // Put note.txt in each directory.
553 mDatabase.getMapper().startAddingDocuments("3");
554 mDatabase.getMapper().startAddingDocuments("4");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900555 mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900556 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900557 }, new long[] { 1024L });
Daichi Hirono61ba9232016-02-26 12:58:39 +0900558 mDatabase.getMapper().putChildDocuments(0, "4", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900559 createDocument(101, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900560 }, new long[] { 1024L });
Daichi Hirono619afda2016-02-07 14:23:43 +0900561
562 // Clear mapping.
Daichi Hirono259ce802015-11-20 17:51:53 +0900563 mDatabase.getMapper().clearMapping();
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900564
Daichi Hirono619afda2016-02-07 14:23:43 +0900565 // Add device, storage, and two directories again.
566 addTestDevice();
567 addTestStorage("1");
568 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900569 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hirono619afda2016-02-07 14:23:43 +0900570 createDocument(50, "A", MtpConstants.FORMAT_ASSOCIATION, 0),
571 createDocument(51, "B", MtpConstants.FORMAT_ASSOCIATION, 0),
Daichi Hirono64111e02016-03-24 21:07:38 +0900572 }, new long[] { 0L, 0L });
Daichi Hirono619afda2016-02-07 14:23:43 +0900573 mDatabase.getMapper().stopAddingDocuments("2");
574
575 // Add note.txt in each directory again.
576 mDatabase.getMapper().startAddingDocuments("3");
577 mDatabase.getMapper().startAddingDocuments("4");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900578 mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900579 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900580 }, new long[] { 1024L });
Daichi Hirono61ba9232016-02-26 12:58:39 +0900581 mDatabase.getMapper().putChildDocuments(0, "4", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900582 createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900583 }, new long[] { 1024L });
Daichi Hirono619afda2016-02-07 14:23:43 +0900584 mDatabase.getMapper().stopAddingDocuments("3");
585 mDatabase.getMapper().stopAddingDocuments("4");
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900586
Daichi Hirono619afda2016-02-07 14:23:43 +0900587 // Check if the two note.txt are mapped correctly.
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900588 {
Daichi Hirono619afda2016-02-07 14:23:43 +0900589 final Cursor cursor = mDatabase.queryChildDocuments(columns, "3");
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900590 assertEquals(1, cursor.getCount());
591 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900592 assertEquals(5, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900593 assertEquals(200, getInt(cursor, COLUMN_OBJECT_HANDLE));
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900594 cursor.close();
595 }
596 {
Daichi Hirono619afda2016-02-07 14:23:43 +0900597 final Cursor cursor = mDatabase.queryChildDocuments(columns, "4");
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900598 assertEquals(1, cursor.getCount());
599 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900600 assertEquals(6, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9fca5412016-02-07 13:20:22 +0900601 assertEquals(201, getInt(cursor, COLUMN_OBJECT_HANDLE));
Daichi Hironoa8a3722e2015-10-26 16:39:54 +0900602 cursor.close();
603 }
604 }
605
Daichi Hirono619afda2016-02-07 14:23:43 +0900606 public void testClearMtpIdentifierBeforeResolveRootDocuments() throws Exception {
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900607 final String[] columns = new String[] {
608 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +0900609 MtpDatabaseConstants.COLUMN_STORAGE_ID,
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900610 DocumentsContract.Document.COLUMN_DISPLAY_NAME
611 };
Daichi Hirono0378da42015-11-05 11:56:12 +0900612 final String[] rootColumns = new String[] {
613 Root.COLUMN_ROOT_ID,
614 Root.COLUMN_AVAILABLE_BYTES
615 };
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900616
Daichi Hirono8e873642016-02-07 15:17:16 +0900617 addTestDevice();
Daichi Hirono81d48532015-12-16 15:03:19 +0900618
619 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900620 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900621 new MtpRoot(0, 100, "Storage", 0, 0, ""),
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900622 });
Daichi Hirono259ce802015-11-20 17:51:53 +0900623 mDatabase.getMapper().clearMapping();
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900624
Daichi Hironoebd24052016-02-06 21:05:57 +0900625 addTestDevice();
Daichi Hirono619afda2016-02-07 14:23:43 +0900626
627 try (final Cursor cursor = mDatabase.queryRoots(resources, rootColumns)) {
628 assertEquals(1, cursor.getCount());
629 cursor.moveToNext();
630 assertEquals("1", getString(cursor, Root.COLUMN_ROOT_ID));
631 }
632
Daichi Hirono81d48532015-12-16 15:03:19 +0900633 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900634 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900635 new MtpRoot(0, 200, "Storage", 2000, 0, ""),
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900636 });
Daichi Hirono259ce802015-11-20 17:51:53 +0900637 mDatabase.getMapper().clearMapping();
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900638
Daichi Hironoebd24052016-02-06 21:05:57 +0900639 addTestDevice();
Daichi Hirono619afda2016-02-07 14:23:43 +0900640
Daichi Hirono81d48532015-12-16 15:03:19 +0900641 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900642 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900643 new MtpRoot(0, 300, "Storage", 3000, 0, ""),
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900644 });
Daichi Hirono81d48532015-12-16 15:03:19 +0900645 mDatabase.getMapper().stopAddingDocuments("1");
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900646
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900647 {
Daichi Hirono4604b742015-11-12 12:12:48 +0900648 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900649 assertEquals(1, cursor.getCount());
650 cursor.moveToNext();
Daichi Hirono81d48532015-12-16 15:03:19 +0900651 assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900652 assertEquals(300, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900653 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900654 cursor.close();
655 }
Daichi Hirono0378da42015-11-05 11:56:12 +0900656 {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900657 final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
Daichi Hirono0378da42015-11-05 11:56:12 +0900658 assertEquals(1, cursor.getCount());
659 cursor.moveToNext();
Daichi Hirono6a5ea7e2016-02-02 16:35:03 +0900660 assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900661 assertEquals(3000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
Daichi Hirono0378da42015-11-05 11:56:12 +0900662 cursor.close();
663 }
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900664 }
665
666 public void testPutSameNameRootsAfterClearing() throws Exception {
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900667 final String[] columns = new String[] {
668 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +0900669 MtpDatabaseConstants.COLUMN_STORAGE_ID,
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900670 DocumentsContract.Document.COLUMN_DISPLAY_NAME
671 };
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900672
Daichi Hirono619afda2016-02-07 14:23:43 +0900673 // Add a device and a storage.
674 addTestDevice();
675 addTestStorage("1");
676
677 // Disconnect devices.
Daichi Hirono259ce802015-11-20 17:51:53 +0900678 mDatabase.getMapper().clearMapping();
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900679
Daichi Hirono619afda2016-02-07 14:23:43 +0900680 // Add a device and two storages that has same name.
681 addTestDevice();
682 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900683 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900684 new MtpRoot(0, 200, "Storage", 2000, 0, ""),
685 new MtpRoot(0, 201, "Storage", 2001, 0, ""),
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900686 });
Daichi Hirono619afda2016-02-07 14:23:43 +0900687 mDatabase.getMapper().stopAddingDocuments("1");
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900688
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900689 {
Daichi Hirono4604b742015-11-12 12:12:48 +0900690 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900691 assertEquals(2, cursor.getCount());
Daichi Hirono619afda2016-02-07 14:23:43 +0900692
693 // First storage reuse document ID of previous storage.
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900694 cursor.moveToNext();
Daichi Hirono9fca5412016-02-07 13:20:22 +0900695 // One reuses exisitng document ID 1.
Daichi Hirono619afda2016-02-07 14:23:43 +0900696 assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900697 assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900698 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono619afda2016-02-07 14:23:43 +0900699
700 // Second one has new document ID.
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900701 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900702 assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900703 assertEquals(201, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900704 assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hirono619afda2016-02-07 14:23:43 +0900705
Daichi Hirono6de8a0e2015-10-27 16:18:17 +0900706 cursor.close();
707 }
708 }
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900709
Daichi Hirono619afda2016-02-07 14:23:43 +0900710 public void testReplaceExistingRoots() throws Exception {
Daichi Hirono8e873642016-02-07 15:17:16 +0900711 addTestDevice();
Daichi Hirono81d48532015-12-16 15:03:19 +0900712
Daichi Hirono4604b742015-11-12 12:12:48 +0900713 // The client code should be able to replace existing rows with new information.
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900714 // Add one.
Daichi Hirono81d48532015-12-16 15:03:19 +0900715 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900716 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900717 new MtpRoot(0, 100, "Storage A", 0, 0, ""),
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900718 });
Daichi Hirono81d48532015-12-16 15:03:19 +0900719 mDatabase.getMapper().stopAddingDocuments("1");
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900720 // Replace it.
Daichi Hirono81d48532015-12-16 15:03:19 +0900721 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900722 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900723 new MtpRoot(0, 100, "Storage B", 1000, 1000, ""),
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900724 });
Daichi Hirono81d48532015-12-16 15:03:19 +0900725 mDatabase.getMapper().stopAddingDocuments("1");
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900726 {
727 final String[] columns = new String[] {
728 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Daichi Hirono18d70d52015-11-13 15:19:47 +0900729 MtpDatabaseConstants.COLUMN_STORAGE_ID,
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900730 DocumentsContract.Document.COLUMN_DISPLAY_NAME
731 };
Daichi Hirono4604b742015-11-12 12:12:48 +0900732 final Cursor cursor = mDatabase.queryRootDocuments(columns);
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900733 assertEquals(1, cursor.getCount());
734 cursor.moveToNext();
Daichi Hirono81d48532015-12-16 15:03:19 +0900735 assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900736 assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900737 assertEquals("Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900738 cursor.close();
739 }
740 {
741 final String[] columns = new String[] {
742 Root.COLUMN_ROOT_ID,
Daichi Hirono81d48532015-12-16 15:03:19 +0900743 Root.COLUMN_TITLE,
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900744 Root.COLUMN_AVAILABLE_BYTES
745 };
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900746 final Cursor cursor = mDatabase.queryRoots(resources, columns);
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900747 assertEquals(1, cursor.getCount());
748 cursor.moveToNext();
Daichi Hirono6a5ea7e2016-02-02 16:35:03 +0900749 assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
Daichi Hirono81d48532015-12-16 15:03:19 +0900750 assertEquals("Device Storage B", getString(cursor, Root.COLUMN_TITLE));
Daichi Hirono9984ebd2015-12-15 16:02:27 +0900751 assertEquals(1000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900752 cursor.close();
753 }
754 }
755
Daichi Hirono619afda2016-02-07 14:23:43 +0900756 public void testFailToReplaceExisitingUnmappedRoots() throws Exception {
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900757 // The client code should not be able to replace rows before resolving 'unmapped' rows.
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900758 // Add one.
Daichi Hirono619afda2016-02-07 14:23:43 +0900759 addTestDevice();
Daichi Hirono81d48532015-12-16 15:03:19 +0900760 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900761 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900762 new MtpRoot(0, 100, "Storage A", 0, 0, ""),
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900763 });
Daichi Hirono259ce802015-11-20 17:51:53 +0900764 mDatabase.getMapper().clearMapping();
Daichi Hirono49f920f2015-11-19 10:19:52 +0900765
Daichi Hirono619afda2016-02-07 14:23:43 +0900766 addTestDevice();
767 try (final Cursor oldCursor =
768 mDatabase.queryRoots(resources, strings(Root.COLUMN_ROOT_ID))) {
769 assertEquals(1, oldCursor.getCount());
770 oldCursor.moveToNext();
771 assertEquals("1", getString(oldCursor, Root.COLUMN_ROOT_ID));
Daichi Hirono49f920f2015-11-19 10:19:52 +0900772
Daichi Hirono619afda2016-02-07 14:23:43 +0900773 // Add one.
774 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900775 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hirono619afda2016-02-07 14:23:43 +0900776 new MtpRoot(0, 101, "Storage B", 1000, 1000, ""),
777 });
778 // Add one more before resolving unmapped documents.
Daichi Hirono0f325372016-02-21 15:50:30 +0900779 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hirono619afda2016-02-07 14:23:43 +0900780 new MtpRoot(0, 102, "Storage B", 1000, 1000, ""),
781 });
782 mDatabase.getMapper().stopAddingDocuments("1");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900783
Daichi Hirono619afda2016-02-07 14:23:43 +0900784 // Because the roots shares the same name, the roots should have new IDs.
785 try (final Cursor newCursor = mDatabase.queryChildDocuments(
786 strings(Document.COLUMN_DOCUMENT_ID), "1")) {
787 assertEquals(2, newCursor.getCount());
788 newCursor.moveToNext();
789 assertFalse(oldCursor.getString(0).equals(newCursor.getString(0)));
790 newCursor.moveToNext();
791 assertFalse(oldCursor.getString(0).equals(newCursor.getString(0)));
792 }
793 }
Daichi Hirono49f920f2015-11-19 10:19:52 +0900794 }
795
Daichi Hirono619afda2016-02-07 14:23:43 +0900796 public void testQueryDocuments() throws Exception {
797 addTestDevice();
798 addTestStorage("1");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900799
Daichi Hirono619afda2016-02-07 14:23:43 +0900800 final Cursor cursor = mDatabase.queryDocument("2", strings(Document.COLUMN_DISPLAY_NAME));
Daichi Hirono49f920f2015-11-19 10:19:52 +0900801 assertEquals(1, cursor.getCount());
802 cursor.moveToNext();
Daichi Hirono619afda2016-02-07 14:23:43 +0900803 assertEquals("Storage", getString(cursor, Document.COLUMN_DISPLAY_NAME));
Daichi Hirono49f920f2015-11-19 10:19:52 +0900804 cursor.close();
805 }
806
Daichi Hirono619afda2016-02-07 14:23:43 +0900807 public void testQueryRoots() throws Exception {
Daichi Hirono81d48532015-12-16 15:03:19 +0900808 // Add device document.
Daichi Hirono8e873642016-02-07 15:17:16 +0900809 addTestDevice();
Daichi Hirono81d48532015-12-16 15:03:19 +0900810
811 // It the device does not have storages, it shows a device root.
812 {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900813 final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
Daichi Hirono81d48532015-12-16 15:03:19 +0900814 assertEquals(1, cursor.getCount());
815 cursor.moveToNext();
816 assertEquals("Device", cursor.getString(0));
817 cursor.close();
818 }
819
820 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900821 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900822 new MtpRoot(0, 100, "Storage A", 0, 0, "")
Daichi Hirono81d48532015-12-16 15:03:19 +0900823 });
824 mDatabase.getMapper().stopAddingDocuments("1");
825
826 // It the device has single storage, it shows a storage root.
827 {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900828 final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
Daichi Hirono81d48532015-12-16 15:03:19 +0900829 assertEquals(1, cursor.getCount());
830 cursor.moveToNext();
831 assertEquals("Device Storage A", cursor.getString(0));
832 cursor.close();
833 }
834
835 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900836 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900837 new MtpRoot(0, 100, "Storage A", 0, 0, ""),
838 new MtpRoot(0, 101, "Storage B", 0, 0, "")
Daichi Hirono81d48532015-12-16 15:03:19 +0900839 });
840 mDatabase.getMapper().stopAddingDocuments("1");
841
842 // It the device has multiple storages, it shows a device root.
843 {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900844 final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
Daichi Hirono81d48532015-12-16 15:03:19 +0900845 assertEquals(1, cursor.getCount());
846 cursor.moveToNext();
847 assertEquals("Device", cursor.getString(0));
848 cursor.close();
849 }
850 }
851
Daichi Hirono49f920f2015-11-19 10:19:52 +0900852 public void testGetParentId() throws FileNotFoundException {
Daichi Hirono619afda2016-02-07 14:23:43 +0900853 addTestDevice();
Daichi Hirono49f920f2015-11-19 10:19:52 +0900854
Daichi Hirono7a375c42015-12-14 17:14:29 +0900855 mDatabase.getMapper().startAddingDocuments("1");
Daichi Hirono0f325372016-02-21 15:50:30 +0900856 mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900857 new MtpRoot(0, 100, "Storage A", 0, 0, ""),
Daichi Hirono49f920f2015-11-19 10:19:52 +0900858 });
Daichi Hirono7a375c42015-12-14 17:14:29 +0900859 mDatabase.getMapper().stopAddingDocuments("1");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900860
Daichi Hirono7a375c42015-12-14 17:14:29 +0900861 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900862 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
863 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900864 }, new long[] { 1024L });
Daichi Hirono7a375c42015-12-14 17:14:29 +0900865 mDatabase.getMapper().stopAddingDocuments("2");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900866
Daichi Hirono619afda2016-02-07 14:23:43 +0900867 assertEquals("2", mDatabase.getParentIdentifier("3").mDocumentId);
868 }
869
870 public void testDeleteDocument() throws Exception {
871 addTestDevice();
872 addTestStorage("1");
873
874 mDatabase.getMapper().startAddingDocuments("2");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900875 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
876 createDocument(200, "dir", MtpConstants.FORMAT_ASSOCIATION, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900877 }, new long[] { 1024L });
Daichi Hirono619afda2016-02-07 14:23:43 +0900878 mDatabase.getMapper().stopAddingDocuments("2");
879
880 mDatabase.getMapper().startAddingDocuments("3");
Daichi Hirono61ba9232016-02-26 12:58:39 +0900881 mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
882 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +0900883 }, new long[] { 1024L });
Daichi Hirono619afda2016-02-07 14:23:43 +0900884 mDatabase.getMapper().stopAddingDocuments("3");
885
886 mDatabase.deleteDocument("3");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900887
888 {
889 // Do not query deleted documents.
890 final Cursor cursor =
Daichi Hirono619afda2016-02-07 14:23:43 +0900891 mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "2");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900892 assertEquals(0, cursor.getCount());
893 cursor.close();
894 }
895
896 {
897 // Child document should be deleted also.
898 final Cursor cursor =
Daichi Hirono619afda2016-02-07 14:23:43 +0900899 mDatabase.queryDocument("4", strings(Document.COLUMN_DOCUMENT_ID));
Daichi Hirono49f920f2015-11-19 10:19:52 +0900900 assertEquals(0, cursor.getCount());
901 cursor.close();
902 }
903 }
904
Daichi Hirono619afda2016-02-07 14:23:43 +0900905 public void testPutNewDocument() throws Exception {
906 addTestDevice();
907 addTestStorage("1");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900908
909 assertEquals(
Daichi Hirono619afda2016-02-07 14:23:43 +0900910 "3",
Daichi Hirono49f920f2015-11-19 10:19:52 +0900911 mDatabase.putNewDocument(
Daichi Hirono61ba9232016-02-26 12:58:39 +0900912 0, "2", OPERATIONS_SUPPORTED,
Daichi Hirono64111e02016-03-24 21:07:38 +0900913 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
914 1024L));
Daichi Hirono49f920f2015-11-19 10:19:52 +0900915
916 {
917 final Cursor cursor =
Daichi Hirono619afda2016-02-07 14:23:43 +0900918 mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "2");
Daichi Hirono49f920f2015-11-19 10:19:52 +0900919 assertEquals(1, cursor.getCount());
920 cursor.moveToNext();
921 assertEquals("3", cursor.getString(0));
922 cursor.close();
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900923 }
Daichi Hirono619afda2016-02-07 14:23:43 +0900924
925 // The new document should not be mapped with existing invalidated document.
926 mDatabase.getMapper().clearMapping();
Daichi Hirono8e873642016-02-07 15:17:16 +0900927 addTestDevice();
928 addTestStorage("1");
929
Daichi Hirono619afda2016-02-07 14:23:43 +0900930 mDatabase.getMapper().startAddingDocuments("2");
931 mDatabase.putNewDocument(
Daichi Hirono61ba9232016-02-26 12:58:39 +0900932 0, "2", OPERATIONS_SUPPORTED,
Daichi Hirono64111e02016-03-24 21:07:38 +0900933 createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
934 1024L);
Daichi Hirono619afda2016-02-07 14:23:43 +0900935 mDatabase.getMapper().stopAddingDocuments("2");
936
937 {
938 final Cursor cursor =
939 mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "2");
940 assertEquals(1, cursor.getCount());
941 cursor.moveToNext();
942 assertEquals("4", cursor.getString(0));
943 cursor.close();
944 }
Daichi Hironocfcb0c02015-11-10 12:52:59 +0900945 }
Daichi Hirono20754c52015-12-15 18:52:26 +0900946
Daichi Hirono619afda2016-02-07 14:23:43 +0900947 public void testGetDocumentIdForDevice() throws Exception {
948 addTestDevice();
949 assertEquals("1", mDatabase.getDocumentIdForDevice(0));
Daichi Hirono20754c52015-12-15 18:52:26 +0900950 }
Daichi Hirono83983d72016-01-29 17:37:36 +0900951
Daichi Hirono619afda2016-02-07 14:23:43 +0900952 public void testGetClosedDevice() throws Exception {
Daichi Hirono83983d72016-01-29 17:37:36 +0900953 mDatabase.getMapper().startAddingDocuments(null);
954 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
Daichi Hironoebd24052016-02-06 21:05:57 +0900955 0, "Device", null /* deviceKey */, /* opened is */ false, new MtpRoot[0], null,
956 null));
Daichi Hirono83983d72016-01-29 17:37:36 +0900957 mDatabase.getMapper().stopAddingDocuments(null);
958
959 final String[] columns = new String [] {
960 DocumentsContract.Root.COLUMN_ROOT_ID,
961 DocumentsContract.Root.COLUMN_TITLE,
962 DocumentsContract.Root.COLUMN_AVAILABLE_BYTES
963 };
Daichi Hironof83ccbd2016-02-04 16:58:55 +0900964 try (final Cursor cursor = mDatabase.queryRoots(resources, columns)) {
Daichi Hirono83983d72016-01-29 17:37:36 +0900965 assertEquals(1, cursor.getCount());
966 assertTrue(cursor.moveToNext());
967 assertEquals(1, cursor.getLong(0));
968 assertEquals("Device", cursor.getString(1));
969 assertTrue(cursor.isNull(2));
970 }
971 }
Daichi Hirono619afda2016-02-07 14:23:43 +0900972
Daichi Hironoebd24052016-02-06 21:05:57 +0900973 public void testMappingWithoutKey() throws FileNotFoundException {
974 mDatabase.getMapper().startAddingDocuments(null);
975 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
976 0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
977 null));
978 mDatabase.getMapper().stopAddingDocuments(null);
979
980 mDatabase.getMapper().startAddingDocuments(null);
981 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
982 0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
983 null));
984 mDatabase.getMapper().stopAddingDocuments(null);
985
986 try (final Cursor cursor =
987 mDatabase.queryRoots(resources, strings(DocumentsContract.Root.COLUMN_ROOT_ID))) {
988 assertEquals(1, cursor.getCount());
989 assertTrue(cursor.moveToNext());
990 assertEquals(1, cursor.getLong(0));
991 }
992 }
993
994 public void testMappingFailsWithoutKey() throws FileNotFoundException {
995 mDatabase.getMapper().startAddingDocuments(null);
996 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
997 0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
998 null));
999 mDatabase.getMapper().stopAddingDocuments(null);
1000
1001 // MTP identifier is cleared here. Mapping no longer works without device key.
1002 mDatabase.getMapper().startAddingDocuments(null);
1003 mDatabase.getMapper().stopAddingDocuments(null);
1004
1005 mDatabase.getMapper().startAddingDocuments(null);
1006 mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
1007 0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
1008 null));
1009 mDatabase.getMapper().stopAddingDocuments(null);
1010
1011 try (final Cursor cursor =
1012 mDatabase.queryRoots(resources, strings(DocumentsContract.Root.COLUMN_ROOT_ID))) {
1013 assertEquals(1, cursor.getCount());
1014 assertTrue(cursor.moveToNext());
1015 assertEquals(2, cursor.getLong(0));
1016 }
1017 }
1018
1019 public void testUpdateDocumentWithoutChange() throws FileNotFoundException {
1020 mDatabase.getMapper().startAddingDocuments(null);
1021 assertTrue(mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
1022 0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null,
1023 null)));
1024 assertFalse(mDatabase.getMapper().stopAddingDocuments(null));
1025
1026 mDatabase.getMapper().startAddingDocuments(null);
1027 assertFalse(mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
1028 0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null,
1029 null)));
1030 assertFalse(mDatabase.getMapper().stopAddingDocuments(null));
1031 }
1032
Daichi Hirono3bb37e72016-02-29 15:30:56 +09001033 public void testSetBootCount() {
1034 assertEquals(0, mDatabase.getLastBootCount());
1035 mDatabase.setLastBootCount(10);
1036 assertEquals(10, mDatabase.getLastBootCount());
1037 try {
1038 mDatabase.setLastBootCount(-1);
1039 fail();
1040 } catch (IllegalArgumentException e) {}
1041 }
1042
1043 public void testCleanDatabase() throws FileNotFoundException {
1044 // Add tree.
1045 addTestDevice();
1046 addTestStorage("1");
1047 mDatabase.getMapper().startAddingDocuments("2");
1048 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
1049 createDocument(100, "apple.txt", MtpConstants.FORMAT_TEXT, 1024),
1050 createDocument(101, "orange.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +09001051 }, new long[] { 1024L, 1024L });
Daichi Hirono3bb37e72016-02-29 15:30:56 +09001052 mDatabase.getMapper().stopAddingDocuments("2");
1053
1054 // Disconnect the device.
1055 mDatabase.getMapper().startAddingDocuments(null);
1056 mDatabase.getMapper().stopAddingDocuments(null);
1057
1058 // Clean database.
1059 mDatabase.cleanDatabase(new Uri[] {
1060 DocumentsContract.buildDocumentUri(MtpDocumentsProvider.AUTHORITY, "3")
1061 });
1062
1063 // Add tree again.
1064 addTestDevice();
1065 addTestStorage("1");
1066 mDatabase.getMapper().startAddingDocuments("2");
1067 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
1068 createDocument(100, "apple.txt", MtpConstants.FORMAT_TEXT, 1024),
1069 createDocument(101, "orange.txt", MtpConstants.FORMAT_TEXT, 1024),
Daichi Hirono64111e02016-03-24 21:07:38 +09001070 }, new long[] { 1024L, 1024L });
Daichi Hirono3bb37e72016-02-29 15:30:56 +09001071 mDatabase.getMapper().stopAddingDocuments("2");
1072
1073 try (final Cursor cursor = mDatabase.queryChildDocuments(
1074 strings(COLUMN_DOCUMENT_ID, Document.COLUMN_DISPLAY_NAME), "2")) {
1075 assertEquals(2, cursor.getCount());
1076
1077 // Persistent uri uses the same ID.
1078 cursor.moveToNext();
1079 assertEquals("3", cursor.getString(0));
1080 assertEquals("apple.txt", cursor.getString(1));
1081
1082 // Others does not.
1083 cursor.moveToNext();
1084 assertEquals("5", cursor.getString(0));
1085 assertEquals("orange.txt", cursor.getString(1));
1086 }
1087 }
1088
Daichi Hirono497b4732016-03-14 14:46:37 +09001089 public void testFormatCodeForMpeg() throws FileNotFoundException {
1090 addTestDevice();
1091 addTestStorage("1");
1092 mDatabase.getMapper().startAddingDocuments("2");
1093 mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
1094 createDocument(100, "audio.m4a", MtpConstants.FORMAT_MPEG, 1000),
1095 createDocument(101, "video.m4v", MtpConstants.FORMAT_MPEG, 1000),
1096 createDocument(102, "unknown.mp4", MtpConstants.FORMAT_MPEG, 1000),
1097 createDocument(103, "inconsistent.txt", MtpConstants.FORMAT_MPEG, 1000),
1098 createDocument(104, "noext", MtpConstants.FORMAT_UNDEFINED, 1000),
Daichi Hirono64111e02016-03-24 21:07:38 +09001099 }, new long[] { 1000L, 1000L, 1000L, 1000L, 1000L });
Daichi Hirono497b4732016-03-14 14:46:37 +09001100 mDatabase.getMapper().stopAddingDocuments("2");
1101 try (final Cursor cursor = mDatabase.queryChildDocuments(
1102 strings(COLUMN_DISPLAY_NAME, COLUMN_MIME_TYPE),
1103 "2")) {
1104 assertEquals(5, cursor.getCount());
1105 cursor.moveToNext();
1106 assertEquals("audio.m4a", cursor.getString(0));
1107 assertEquals("audio/mp4", cursor.getString(1));
1108 cursor.moveToNext();
1109 assertEquals("video.m4v", cursor.getString(0));
1110 assertEquals("video/mp4", cursor.getString(1));
1111 cursor.moveToNext();
1112 // Assume that the file is video as we don't have any hints to find out if the file is
1113 // video or audio.
1114 assertEquals("unknown.mp4", cursor.getString(0));
1115 assertEquals("video/mp4", cursor.getString(1));
1116 // Don't return mime type that is inconsistent with format code.
1117 cursor.moveToNext();
1118 assertEquals("inconsistent.txt", cursor.getString(0));
Daichi Hironodaa61d42016-08-10 14:59:18 +09001119 assertEquals("video/mpeg", cursor.getString(1));
Daichi Hirono497b4732016-03-14 14:46:37 +09001120 cursor.moveToNext();
1121 assertEquals("noext", cursor.getString(0));
1122 assertEquals("application/octet-stream", cursor.getString(1));
1123 }
1124 }
1125
Daichi Hirono619afda2016-02-07 14:23:43 +09001126 private void addTestDevice() throws FileNotFoundException {
Daichi Hironof578fa22016-02-19 18:05:42 +09001127 TestUtil.addTestDevice(mDatabase);
Daichi Hirono619afda2016-02-07 14:23:43 +09001128 }
1129
1130 private void addTestStorage(String parentId) throws FileNotFoundException {
Daichi Hironof578fa22016-02-19 18:05:42 +09001131 TestUtil.addTestStorage(mDatabase, parentId);
Daichi Hirono619afda2016-02-07 14:23:43 +09001132 }
Daichi Hirono9678f602015-10-22 12:35:05 +09001133}