MtpDocumentsProviderTest.java revision 4604b74603ea951c0f0d0fc2d9b6bd46ae54e245
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.mtp;
18
19import android.database.Cursor;
20import android.mtp.MtpConstants;
21import android.mtp.MtpObjectInfo;
22import android.net.Uri;
23import android.provider.DocumentsContract.Root;
24import android.provider.DocumentsContract;
25import android.test.AndroidTestCase;
26import android.test.suitebuilder.annotation.SmallTest;
27
28import java.io.FileNotFoundException;
29import java.io.IOException;
30
31@SmallTest
32public class MtpDocumentsProviderTest extends AndroidTestCase {
33    private final static Uri ROOTS_URI =
34            DocumentsContract.buildRootsUri(MtpDocumentsProvider.AUTHORITY);
35    private TestContentResolver mResolver;
36    private MtpDocumentsProvider mProvider;
37    private TestMtpManager mMtpManager;
38    private final TestResources mResources = new TestResources();
39    private MtpDatabase mDatabase;
40
41    @Override
42    public void setUp() throws IOException {
43        mResolver = new TestContentResolver();
44        mMtpManager = new TestMtpManager(getContext());
45        mProvider = new MtpDocumentsProvider();
46        mDatabase = new MtpDatabase(getContext(), true);
47        mProvider.onCreateForTesting(mResources, mMtpManager, mResolver, mDatabase);
48    }
49
50    @Override
51    public void tearDown() {
52        try {
53            mProvider.close();
54        } catch (InterruptedException e) {
55            fail();
56        }
57    }
58
59    public void testOpenAndCloseDevice() throws Exception {
60        mMtpManager.addValidDevice(0);
61        mMtpManager.setRoots(0, new MtpRoot[] {
62                new MtpRoot(
63                        0 /* deviceId */,
64                        1 /* storageId */,
65                        "Device A" /* device model name */,
66                        "Storage A" /* volume description */,
67                        1024 /* free space */,
68                        2048 /* total space */,
69                        "" /* no volume identifier */)
70        });
71
72        mProvider.openDevice(0);
73        mResolver.waitForNotification(ROOTS_URI, 1);
74
75        mProvider.closeDevice(0);
76        mResolver.waitForNotification(ROOTS_URI, 2);
77    }
78
79    public void testOpenAndCloseErrorDevice() throws Exception {
80        try {
81            mProvider.openDevice(1);
82            fail();
83        } catch (Throwable error) {
84            assertTrue(error instanceof IOException);
85        }
86
87        try {
88            mProvider.closeDevice(1);
89            fail();
90        } catch (Throwable error) {
91            assertTrue(error instanceof IOException);
92        }
93
94        // Check if the following notification is the first one or not.
95        mMtpManager.addValidDevice(0);
96        mMtpManager.setRoots(0, new MtpRoot[] {
97                new MtpRoot(
98                        0 /* deviceId */,
99                        1 /* storageId */,
100                        "Device A" /* device model name */,
101                        "Storage A" /* volume description */,
102                        1024 /* free space */,
103                        2048 /* total space */,
104                        "" /* no volume identifier */)
105        });
106        mProvider.openDevice(0);
107        mResolver.waitForNotification(ROOTS_URI, 1);
108    }
109
110    public void testQueryRoots() throws Exception {
111        mMtpManager.addValidDevice(0);
112        mMtpManager.addValidDevice(1);
113        mMtpManager.setRoots(0, new MtpRoot[] {
114                new MtpRoot(
115                        0 /* deviceId */,
116                        1 /* storageId */,
117                        "Device A" /* device model name */,
118                        "Storage A" /* volume description */,
119                        1024 /* free space */,
120                        2048 /* total space */,
121                        "" /* no volume identifier */)
122        });
123        mMtpManager.setRoots(1, new MtpRoot[] {
124                new MtpRoot(
125                        1 /* deviceId */,
126                        1 /* storageId */,
127                        "Device B" /* device model name */,
128                        "Storage B" /* volume description */,
129                        2048 /* free space */,
130                        4096 /* total space */,
131                        "Identifier B" /* no volume identifier */)
132        });
133
134        {
135            mProvider.openDevice(0);
136            mResolver.waitForNotification(ROOTS_URI, 1);
137            final Cursor cursor = mProvider.queryRoots(null);
138            assertEquals(1, cursor.getCount());
139            cursor.moveToNext();
140            assertEquals("1", cursor.getString(0));
141            assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
142            // TODO: Add storage icon for MTP devices.
143            assertTrue(cursor.isNull(2) /* icon */);
144            assertEquals("Device A Storage A", cursor.getString(3));
145            assertEquals("0_1_0", cursor.getString(4));
146            assertEquals(1024, cursor.getInt(5));
147        }
148
149        {
150            mProvider.openDevice(1);
151            mResolver.waitForNotification(ROOTS_URI, 2);
152            final Cursor cursor = mProvider.queryRoots(null);
153            assertEquals(2, cursor.getCount());
154            cursor.moveToNext();
155            cursor.moveToNext();
156            assertEquals("2", cursor.getString(0));
157            assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
158            // TODO: Add storage icon for MTP devices.
159            assertTrue(cursor.isNull(2) /* icon */);
160            assertEquals("Device B Storage B", cursor.getString(3));
161            assertEquals("1_1_0", cursor.getString(4));
162            assertEquals(2048, cursor.getInt(5));
163        }
164    }
165
166    public void testQueryRoots_error() throws Exception {
167        mMtpManager.addValidDevice(0);
168        mMtpManager.addValidDevice(1);
169        // Not set roots for device 0 so that MtpManagerMock#getRoots throws IOException.
170        mMtpManager.setRoots(1, new MtpRoot[] {
171                new MtpRoot(
172                        1 /* deviceId */,
173                        1 /* storageId */,
174                        "Device B" /* device model name */,
175                        "Storage B" /* volume description */,
176                        2048 /* free space */,
177                        4096 /* total space */,
178                        "Identifier B" /* no volume identifier */)
179        });
180        {
181            mProvider.openDevice(0);
182            mProvider.openDevice(1);
183            mResolver.waitForNotification(ROOTS_URI, 1);
184
185            final Cursor cursor = mProvider.queryRoots(null);
186            assertEquals(1, cursor.getCount());
187            cursor.moveToNext();
188            assertEquals("1", cursor.getString(0));
189            assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
190            // TODO: Add storage icon for MTP devices.
191            assertTrue(cursor.isNull(2) /* icon */);
192            assertEquals("Device B Storage B", cursor.getString(3));
193            assertEquals("1_1_0", cursor.getString(4));
194            assertEquals(2048, cursor.getInt(5));
195        }
196    }
197
198    public void testQueryDocument() throws IOException {
199        mMtpManager.addValidDevice(0);
200        mProvider.openDevice(0);
201        mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
202                .setObjectHandle(2)
203                .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
204                .setName("image.jpg")
205                .setDateModified(1422716400000L)
206                .setCompressedSize(1024 * 1024 * 5)
207                .setThumbCompressedSize(1024 * 50)
208                .build());
209        final Cursor cursor = mProvider.queryDocument("0_1_2", null);
210        assertEquals(1, cursor.getCount());
211
212        cursor.moveToNext();
213        assertEquals("0_1_2", cursor.getString(0));
214        assertEquals("image/jpeg", cursor.getString(1));
215        assertEquals("image.jpg", cursor.getString(2));
216        assertEquals(1422716400000L, cursor.getLong(3));
217        assertEquals(
218                DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
219                DocumentsContract.Document.FLAG_SUPPORTS_WRITE |
220                DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL,
221                cursor.getInt(4));
222        assertEquals(1024 * 1024 * 5, cursor.getInt(5));
223    }
224
225    public void testQueryDocument_directory() throws IOException {
226        mMtpManager.addValidDevice(0);
227        mProvider.openDevice(0);
228        mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
229                .setObjectHandle(2)
230                .setFormat(MtpConstants.FORMAT_ASSOCIATION)
231                .setName("directory")
232                .setDateModified(1422716400000L)
233                .build());
234        final Cursor cursor = mProvider.queryDocument("0_1_2", null);
235        assertEquals(1, cursor.getCount());
236
237        cursor.moveToNext();
238        assertEquals("0_1_2", cursor.getString(0));
239        assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
240        assertEquals("directory", cursor.getString(2));
241        assertEquals(1422716400000L, cursor.getLong(3));
242        assertEquals(
243                DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
244                DocumentsContract.Document.FLAG_SUPPORTS_WRITE |
245                DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE,
246                cursor.getInt(4));
247        assertEquals(0, cursor.getInt(5));
248    }
249
250    public void testQueryDocument_forRoot() throws IOException {
251        mMtpManager.addValidDevice(0);
252        mProvider.openDevice(0);
253        mMtpManager.setRoots(0, new MtpRoot[] {
254                new MtpRoot(
255                        0 /* deviceId */,
256                        1 /* storageId */,
257                        "Device A" /* device model name */,
258                        "Storage A" /* volume description */,
259                        1024 /* free space */,
260                        4096 /* total space */,
261                        "" /* no volume identifier */)
262        });
263        final Cursor cursor = mProvider.queryDocument("0_1_0", null);
264        assertEquals(1, cursor.getCount());
265
266        cursor.moveToNext();
267        assertEquals("0_1_0", cursor.getString(0));
268        assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
269        assertEquals("Device A Storage A", cursor.getString(2));
270        assertTrue(cursor.isNull(3));
271        assertEquals(0, cursor.getInt(4));
272        assertEquals(3072, cursor.getInt(5));
273    }
274
275    public void testQueryChildDocuments() throws Exception {
276        mMtpManager.addValidDevice(0);
277        mProvider.openDevice(0);
278        mMtpManager.setObjectHandles(0, 0, -1, new int[] { 1 });
279
280        mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
281                .setObjectHandle(1)
282                .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
283                .setName("image.jpg")
284                .setCompressedSize(1024 * 1024 * 5)
285                .setThumbCompressedSize(5 * 1024)
286                .setProtectionStatus(MtpConstants.PROTECTION_STATUS_READ_ONLY)
287                .build());
288
289        final Cursor cursor = mProvider.queryChildDocuments("0_0_0", null, null);
290        assertEquals(1, cursor.getCount());
291
292        assertTrue(cursor.moveToNext());
293        assertEquals("0_0_1", cursor.getString(0));
294        assertEquals("image/jpeg", cursor.getString(1));
295        assertEquals("image.jpg", cursor.getString(2));
296        assertEquals(0, cursor.getLong(3));
297        assertEquals(DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL, cursor.getInt(4));
298        assertEquals(1024 * 1024 * 5, cursor.getInt(5));
299
300        assertFalse(cursor.moveToNext());
301    }
302
303    public void testQueryChildDocuments_cursorError() throws Exception {
304        mMtpManager.addValidDevice(0);
305        mProvider.openDevice(0);
306        try {
307            mProvider.queryChildDocuments("0_0_0", null, null);
308            fail();
309        } catch (Throwable error) {
310            assertTrue(error instanceof FileNotFoundException);
311        }
312    }
313
314    public void testQueryChildDocuments_documentError() throws Exception {
315        mMtpManager.addValidDevice(0);
316        mProvider.openDevice(0);
317        mMtpManager.setObjectHandles(0, 0, -1, new int[] { 1 });
318        try {
319            mProvider.queryChildDocuments("0_0_0", null, null);
320            fail();
321        } catch (Throwable error) {
322            assertTrue(error instanceof FileNotFoundException);
323        }
324    }
325
326    public void testDeleteDocument() throws IOException {
327        mMtpManager.addValidDevice(0);
328        mProvider.openDevice(0);
329        mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
330                .setObjectHandle(1)
331                .setParent(2)
332                .build());
333        mProvider.deleteDocument("0_0_1");
334        assertEquals(1, mResolver.getChangeCount(
335                DocumentsContract.buildChildDocumentsUri(
336                        MtpDocumentsProvider.AUTHORITY, "0_0_2")));
337    }
338
339    public void testDeleteDocument_error() throws IOException {
340        mMtpManager.addValidDevice(0);
341        mProvider.openDevice(0);
342        mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
343                .setObjectHandle(2)
344                .build());
345        try {
346            mProvider.deleteDocument("0_0_1");
347            fail();
348        } catch (Throwable e) {
349            assertTrue(e instanceof IOException);
350        }
351        assertEquals(0, mResolver.getChangeCount(
352                DocumentsContract.buildChildDocumentsUri(
353                        MtpDocumentsProvider.AUTHORITY, "0_0_2")));
354    }
355}
356