1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.documentsui.picker;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertNotNull;
23 import static org.mockito.Mockito.mock;
24 import static org.mockito.Mockito.verify;
25 
26 import android.app.Activity;
27 import android.content.ClipData;
28 import android.content.ComponentName;
29 import android.content.Intent;
30 import android.content.pm.ResolveInfo;
31 import android.net.Uri;
32 import android.os.AsyncTask;
33 import android.provider.DocumentsContract;
34 import android.provider.DocumentsContract.Path;
35 
36 import androidx.fragment.app.FragmentActivity;
37 import androidx.test.filters.MediumTest;
38 import androidx.test.runner.AndroidJUnit4;
39 
40 import com.android.documentsui.DocumentsAccess;
41 import com.android.documentsui.Injector;
42 import com.android.documentsui.R;
43 import com.android.documentsui.TestUserIdManager;
44 import com.android.documentsui.UserIdManager;
45 import com.android.documentsui.base.DocumentInfo;
46 import com.android.documentsui.base.DocumentStack;
47 import com.android.documentsui.base.Lookup;
48 import com.android.documentsui.base.RootInfo;
49 import com.android.documentsui.base.Shared;
50 import com.android.documentsui.base.State;
51 import com.android.documentsui.base.State.ActionType;
52 import com.android.documentsui.picker.ActionHandler.Addons;
53 import com.android.documentsui.queries.SearchViewManager;
54 import com.android.documentsui.roots.ProvidersAccess;
55 import com.android.documentsui.testing.DocumentStackAsserts;
56 import com.android.documentsui.testing.TestEnv;
57 import com.android.documentsui.testing.TestLastAccessedStorage;
58 import com.android.documentsui.testing.TestProvidersAccess;
59 import com.android.documentsui.testing.TestResolveInfo;
60 import com.android.documentsui.util.VersionUtils;
61 
62 import org.junit.AfterClass;
63 import org.junit.Before;
64 import org.junit.Test;
65 import org.junit.runner.RunWith;
66 
67 import java.util.Arrays;
68 import java.util.concurrent.Executor;
69 
70 @RunWith(AndroidJUnit4.class)
71 @MediumTest
72 public class ActionHandlerTest {
73 
74     private static final String EXTRA_INTENT = "EXTRA_INTENT";
75     private static final String EXTRA_USER = "EXTRA_USER";
76 
77     private TestEnv mEnv;
78     private TestActivity mActivity;
79     private TestableActionHandler<TestActivity> mHandler;
80     private TestLastAccessedStorage mLastAccessed;
81     private PickCountRecordStorage mPickCountRecord;
82     private TestUserIdManager mTestUserIdManager;
83 
84     @Before
setUp()85     public void setUp() {
86         mEnv = TestEnv.create();
87         mActivity = TestActivity.create(mEnv);
88         mEnv.providers.configurePm(mActivity.packageMgr);
89         mEnv.injector.pickResult = new PickResult();
90         mLastAccessed = new TestLastAccessedStorage();
91         mTestUserIdManager = new TestUserIdManager();
92         mPickCountRecord = mock(PickCountRecordStorage.class);
93 
94         mHandler = new TestableActionHandler<>(
95                 mActivity,
96                 mEnv.state,
97                 mEnv.providers,
98                 mEnv.docs,
99                 mEnv.searchViewManager,
100                 mEnv::lookupExecutor,
101                 mEnv.injector,
102                 mLastAccessed,
103                 mPickCountRecord,
104                 mTestUserIdManager
105         );
106 
107         mEnv.selectionMgr.select("1");
108 
109         AsyncTask.setDefaultExecutor(mEnv.mExecutor);
110     }
111 
112     private static class TestableActionHandler<T extends FragmentActivity & Addons>
113         extends ActionHandler {
114 
115         private UpdatePickResultTask mTask;
116 
TestableActionHandler( T activity, State state, ProvidersAccess providers, DocumentsAccess docs, SearchViewManager searchMgr, Lookup<String, Executor> executors, Injector injector, LastAccessedStorage lastAccessed, PickCountRecordStorage pickCountRecordStorage, UserIdManager userIdManager)117         TestableActionHandler(
118                 T activity,
119                 State state,
120                 ProvidersAccess providers,
121                 DocumentsAccess docs,
122                 SearchViewManager searchMgr,
123                 Lookup<String, Executor> executors,
124                 Injector injector,
125                 LastAccessedStorage lastAccessed,
126                 PickCountRecordStorage pickCountRecordStorage,
127                 UserIdManager userIdManager) {
128             super(activity, state, providers, docs, searchMgr, executors, injector, lastAccessed,
129                     userIdManager);
130             mTask = new UpdatePickResultTask(
131                     mActivity, mInjector.pickResult, pickCountRecordStorage);
132         }
133 
134         @Override
getUpdatePickResultTask()135         public UpdatePickResultTask getUpdatePickResultTask() {
136             return mTask;
137         }
138     }
139 
140     @AfterClass
tearDownOnce()141     public static void tearDownOnce() {
142         AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
143     }
144 
145     @Test
testInitLocation_RestoresIfStackIsLoaded()146     public void testInitLocation_RestoresIfStackIsLoaded() throws Exception {
147         mEnv.state.stack.changeRoot(TestProvidersAccess.DOWNLOADS);
148         mEnv.state.stack.push(TestEnv.FOLDER_0);
149 
150         mHandler.initLocation(mActivity.getIntent());
151         mActivity.restoreRootAndDirectory.assertCalled();
152     }
153 
154     @Test
testInitLocation_LoadsRootDocIfStackOnlyHasRoot()155     public void testInitLocation_LoadsRootDocIfStackOnlyHasRoot() throws Exception {
156         mEnv.state.stack.changeRoot(TestProvidersAccess.HAMMY);
157 
158         mHandler.initLocation(mActivity.getIntent());
159         assertRootPicked(TestProvidersAccess.HAMMY.getUri());
160     }
161 
162     @Test
testInitLocation_CopyDestination_DefaultsToDownloads()163     public void testInitLocation_CopyDestination_DefaultsToDownloads() throws Exception {
164         Intent intent = mActivity.getIntent();
165         intent.setAction(Shared.ACTION_PICK_COPY_DESTINATION);
166         mHandler.initLocation(mActivity.getIntent());
167         assertRootPicked(TestProvidersAccess.DOWNLOADS.getUri());
168     }
169 
170     @Test
testInitLocation_LaunchToDocuments()171     public void testInitLocation_LaunchToDocuments() throws Exception {
172         if (!mEnv.features.isLaunchToDocumentEnabled()) {
173             return;
174         }
175 
176         mEnv.docs.nextIsDocumentsUri = true;
177         mEnv.docs.nextPath = new Path(
178                 TestProvidersAccess.HOME.rootId,
179                 Arrays.asList(
180                         TestEnv.FOLDER_0.documentId,
181                         TestEnv.FOLDER_1.documentId,
182                         TestEnv.FILE_GIF.documentId));
183         mEnv.docs.nextDocuments =
184                 Arrays.asList(TestEnv.FOLDER_0, TestEnv.FOLDER_1, TestEnv.FILE_GIF);
185 
186         mActivity.refreshCurrentRootAndDirectory.assertNotCalled();
187         Intent intent = mActivity.getIntent();
188         intent.setAction(Intent.ACTION_GET_CONTENT);
189         intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, TestEnv.FILE_GIF.derivedUri);
190         mHandler.initLocation(intent);
191 
192         mEnv.beforeAsserts();
193 
194         DocumentStackAsserts.assertEqualsTo(mEnv.state.stack, TestProvidersAccess.HOME,
195                 Arrays.asList(TestEnv.FOLDER_0, TestEnv.FOLDER_1));
196         mActivity.refreshCurrentRootAndDirectory.assertCalled();
197     }
198 
199     @Test
testInitLocation_RestoresLastAccessedStack()200     public void testInitLocation_RestoresLastAccessedStack() throws Exception {
201         final DocumentStack stack =
202                 new DocumentStack(TestProvidersAccess.HAMMY, TestEnv.FOLDER_0, TestEnv.FOLDER_1);
203         mLastAccessed.setLastAccessed(mActivity, stack);
204 
205         mHandler.initLocation(mActivity.getIntent());
206 
207         mEnv.beforeAsserts();
208         assertEquals(stack, mEnv.state.stack);
209         mActivity.refreshCurrentRootAndDirectory.assertCalled();
210     }
211 
212     @Test
testInitLocation_DefaultToRecents_ActionGetContent()213     public void testInitLocation_DefaultToRecents_ActionGetContent() throws Exception {
214         testInitLocationDefaultToRecentsOnAction(State.ACTION_GET_CONTENT);
215     }
216 
217     @Test
testInitLocation_DefaultToRecents_ActionOpen()218     public void testInitLocation_DefaultToRecents_ActionOpen() throws Exception {
219         testInitLocationDefaultToRecentsOnAction(State.ACTION_OPEN);
220     }
221 
222     @Test
testInitLocation_DefaultsToDownloads_ActionCreate()223     public void testInitLocation_DefaultsToDownloads_ActionCreate() throws Exception {
224         testInitLocationDefaultToDownloadsOnAction(State.ACTION_CREATE);
225     }
226 
227     @Test
testInitLocation_DefaultToDeviceRoot_ActionOpenTree()228     public void testInitLocation_DefaultToDeviceRoot_ActionOpenTree() throws Exception {
229         mEnv.state.action = State.ACTION_OPEN_TREE;
230 
231         mHandler.initLocation(mActivity.getIntent());
232 
233         assertRootPicked(TestProvidersAccess.EXTERNALSTORAGE.getUri());
234     }
235 
236     @Test
testInitLocation_DefaultToDeviceRoot_ActionOpenTree_RootDoesNotSupportChildren()237     public void testInitLocation_DefaultToDeviceRoot_ActionOpenTree_RootDoesNotSupportChildren()
238             throws Exception {
239         mEnv.state.action = State.ACTION_OPEN_TREE;
240 
241         String authority = TestProvidersAccess.NO_TREE_ROOT.authority;
242         String rootId = TestProvidersAccess.NO_TREE_ROOT.rootId;
243         Uri hintUri = DocumentsContract.buildRootUri(authority, rootId);
244 
245         mActivity.getIntent().putExtra(DocumentsContract.EXTRA_INITIAL_URI, hintUri);
246         mHandler.initLocation(mActivity.getIntent());
247 
248         assertRootPicked(TestProvidersAccess.EXTERNALSTORAGE.getUri());
249     }
250 
251     @Test
testOpenContainerDocument()252     public void testOpenContainerDocument() {
253         mHandler.openContainerDocument(TestEnv.FOLDER_0);
254 
255         assertEquals(TestEnv.FOLDER_0, mEnv.state.stack.peek());
256 
257         mActivity.refreshCurrentRootAndDirectory.assertCalled();
258     }
259 
260     @Test
testOpenContainerDocument_sameDocumentInfo()261     public void testOpenContainerDocument_sameDocumentInfo() {
262         mHandler.openContainerDocument(TestEnv.FOLDER_0);
263         mHandler.openContainerDocument(TestEnv.FOLDER_0);
264 
265         assertEquals(1, mEnv.state.stack.size());
266     }
267 
268     @Test
testIncreasePickCountRecordCalled()269     public void testIncreasePickCountRecordCalled() throws Exception {
270         mEnv.state.action = State.ACTION_GET_CONTENT;
271         mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
272         mEnv.state.stack.push(TestEnv.FOLDER_1);
273 
274         mActivity.finishedHandler.assertNotCalled();
275         mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri);
276 
277         mEnv.beforeAsserts();
278 
279         verify(mPickCountRecord).increasePickCountRecord(
280             mActivity.getApplicationContext(), TestEnv.FILE_JPG.derivedUri);
281 
282         mActivity.finishedHandler.assertCalled();
283     }
284 
285     @Test
testPickDocument_SetsCorrectResultAndFinishes_ActionPickCopyDestination()286     public void testPickDocument_SetsCorrectResultAndFinishes_ActionPickCopyDestination()
287             throws Exception {
288 
289         mEnv.state.action = State.ACTION_PICK_COPY_DESTINATION;
290         mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
291         mEnv.state.stack.push(TestEnv.FOLDER_1);
292         mEnv.state.stack.push(TestEnv.FOLDER_2);
293 
294         mActivity.finishedHandler.assertNotCalled();
295 
296         mHandler.pickDocument(null, TestEnv.FOLDER_2);
297 
298         mEnv.beforeAsserts();
299 
300         assertLastAccessedStackUpdated();
301 
302         assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first);
303         final Intent result = mActivity.setResult.getLastValue().second;
304         assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, false);
305         assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
306         assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false);
307         assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
308         assertContent(result, TestEnv.FOLDER_2.derivedUri);
309 
310         mActivity.finishedHandler.assertCalled();
311     }
312 
313     @Test
testPickDocument_SetsCorrectResultAndFinishes_ActionOpenTree()314     public void testPickDocument_SetsCorrectResultAndFinishes_ActionOpenTree() throws Exception {
315         mEnv.state.action = State.ACTION_OPEN_TREE;
316         mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
317         mEnv.state.stack.push(TestEnv.FOLDER_1);
318         mEnv.state.stack.push(TestEnv.FOLDER_2);
319 
320         mActivity.finishedHandler.assertNotCalled();
321 
322         Uri uri = DocumentsContract.buildTreeDocumentUri(
323                 TestEnv.FOLDER_2.authority, TestEnv.FOLDER_2.documentId);
324         mHandler.finishPicking(uri);
325 
326         mEnv.beforeAsserts();
327 
328         assertLastAccessedStackUpdated();
329 
330         assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first);
331         final Intent result = mActivity.setResult.getLastValue().second;
332         assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
333         assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
334         assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true);
335         assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, true);
336         assertContent(result, DocumentsContract.buildTreeDocumentUri(
337                 TestProvidersAccess.HOME.authority, TestEnv.FOLDER_2.documentId));
338 
339         mActivity.finishedHandler.assertCalled();
340     }
341 
342     @Test
testSaveDocument_SetsCorrectResultAndFinishes()343     public void testSaveDocument_SetsCorrectResultAndFinishes() throws Exception {
344         mEnv.state.action = State.ACTION_CREATE;
345         mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
346         mEnv.state.stack.push(TestEnv.FOLDER_1);
347 
348         final String mimeType = "audio/aac";
349         final String displayName = "foobar.m4a";
350 
351         mHandler.saveDocument(mimeType, displayName, (boolean inProgress) -> {});
352 
353         mEnv.beforeAsserts();
354 
355         mEnv.docs.assertCreatedDocument(TestEnv.FOLDER_1, mimeType, displayName);
356         final Uri docUri = mEnv.docs.getLastCreatedDocumentUri();
357 
358         assertLastAccessedStackUpdated();
359 
360         assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first);
361         final Intent result = mActivity.setResult.getLastValue().second;
362         assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
363         assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
364         assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true);
365         assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
366         assertContent(result, docUri);
367 
368         mActivity.finishedHandler.assertCalled();
369     }
370 
371     @Test
testSaveDocument_ConfirmsOverwrite()372     public void testSaveDocument_ConfirmsOverwrite() {
373         if (!mEnv.features.isOverwriteConfirmationEnabled()) {
374             return;
375         }
376 
377         mEnv.state.action = State.ACTION_CREATE;
378         mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
379         mEnv.state.stack.push(TestEnv.FOLDER_1);
380 
381         mHandler.saveDocument(null, TestEnv.FILE_JPG);
382 
383         mEnv.dialogs.assertOverwriteConfirmed(TestEnv.FILE_JPG);
384     }
385 
386     @Test
testPickDocument_ConfirmsOpenTree()387     public void testPickDocument_ConfirmsOpenTree() {
388         mEnv.state.action = State.ACTION_OPEN_TREE;
389         mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
390 
391         mHandler.pickDocument(null, TestEnv.FOLDER_1);
392 
393         mEnv.dialogs.assertDocumentTreeConfirmed(TestEnv.FOLDER_1);
394     }
395 
396     @Test
testFinishPicking_SetsCorrectResultAndFinishes_ActionGetContent()397     public void testFinishPicking_SetsCorrectResultAndFinishes_ActionGetContent() throws Exception {
398         mEnv.state.action = State.ACTION_GET_CONTENT;
399         mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
400         mEnv.state.stack.push(TestEnv.FOLDER_1);
401 
402         mActivity.finishedHandler.assertNotCalled();
403 
404         mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri);
405 
406         mEnv.beforeAsserts();
407 
408         assertLastAccessedStackUpdated();
409 
410         assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first);
411         final Intent result = mActivity.setResult.getLastValue().second;
412         assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
413         assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
414         assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false);
415         assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
416         assertContent(result, TestEnv.FILE_JPG.derivedUri);
417 
418         mActivity.finishedHandler.assertCalled();
419     }
420 
421     @Test
testFinishPicking_SetsCorrectResultAndFinishes_ActionGetContent_MultipleSelection()422     public void testFinishPicking_SetsCorrectResultAndFinishes_ActionGetContent_MultipleSelection()
423             throws Exception {
424         mEnv.state.action = State.ACTION_GET_CONTENT;
425         mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
426         mEnv.state.stack.push(TestEnv.FOLDER_1);
427         mEnv.state.acceptMimes = new String[] { "image/*" };
428 
429         mActivity.finishedHandler.assertNotCalled();
430 
431         mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri, TestEnv.FILE_GIF.derivedUri);
432 
433         mEnv.beforeAsserts();
434 
435         assertLastAccessedStackUpdated();
436 
437         assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first);
438         final Intent result = mActivity.setResult.getLastValue().second;
439         assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
440         assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
441         assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false);
442         assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
443         assertContent(result, TestEnv.FILE_JPG.derivedUri, TestEnv.FILE_GIF.derivedUri);
444 
445         mActivity.finishedHandler.assertCalled();
446     }
447 
448     @Test
testFinishPicking_SetsCorrectResultAndFinishes_ActionOpen()449     public void testFinishPicking_SetsCorrectResultAndFinishes_ActionOpen() throws Exception {
450         mEnv.state.action = State.ACTION_OPEN;
451         mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
452         mEnv.state.stack.push(TestEnv.FOLDER_1);
453 
454         mActivity.finishedHandler.assertNotCalled();
455 
456         mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri);
457 
458         mEnv.beforeAsserts();
459 
460         assertLastAccessedStackUpdated();
461 
462         assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first);
463         final Intent result = mActivity.setResult.getLastValue().second;
464         assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
465         assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
466         assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true);
467         assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
468         assertContent(result, TestEnv.FILE_JPG.derivedUri);
469 
470         mActivity.finishedHandler.assertCalled();
471     }
472 
473     @Test
testFinishPicking_SetsCorrectResultAndFinishes_ActionOpen_MultipleSelection()474     public void testFinishPicking_SetsCorrectResultAndFinishes_ActionOpen_MultipleSelection()
475             throws Exception {
476         mEnv.state.action = State.ACTION_OPEN;
477         mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
478         mEnv.state.stack.push(TestEnv.FOLDER_1);
479         mEnv.state.acceptMimes = new String[] { "image/*" };
480 
481         mActivity.finishedHandler.assertNotCalled();
482 
483         mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri, TestEnv.FILE_GIF.derivedUri);
484 
485         mEnv.beforeAsserts();
486 
487         assertLastAccessedStackUpdated();
488 
489         assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first);
490         final Intent result = mActivity.setResult.getLastValue().second;
491         assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
492         assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
493         assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true);
494         assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
495         assertContent(result, TestEnv.FILE_JPG.derivedUri, TestEnv.FILE_GIF.derivedUri);
496 
497         mActivity.finishedHandler.assertCalled();
498     }
499 
500     @Test
testFinishPicking_SetsCorrectResultAndFinishes_ActionCreate()501     public void testFinishPicking_SetsCorrectResultAndFinishes_ActionCreate() throws Exception {
502         mEnv.state.action = State.ACTION_CREATE;
503         mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
504         mEnv.state.stack.push(TestEnv.FOLDER_1);
505 
506         mActivity.finishedHandler.assertNotCalled();
507 
508         mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri);
509 
510         mEnv.beforeAsserts();
511 
512         assertLastAccessedStackUpdated();
513 
514         assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first);
515         final Intent result = mActivity.setResult.getLastValue().second;
516         assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
517         assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
518         assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true);
519         assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
520         assertContent(result, TestEnv.FILE_JPG.derivedUri);
521 
522         mActivity.finishedHandler.assertCalled();
523     }
524 
525 
526     @Test
testOpenAppRoot()527     public void testOpenAppRoot() throws Exception {
528         mHandler.openRoot(TestResolveInfo.create(), TestProvidersAccess.USER_ID);
529         assertNotNull(mActivity.startActivity.getLastValue());
530     }
531 
532     @Test
testOpenAppRoot_otherUser()533     public void testOpenAppRoot_otherUser() throws Exception {
534         ResolveInfo info = TestResolveInfo.create();
535         mEnv.state.canShareAcrossProfile = true;
536         mHandler.openRoot(info, TestProvidersAccess.OtherUser.USER_ID);
537         assertThat(mActivity.startActivityAsUser.getLastValue().first.getComponent()).isEqualTo(
538                 new ComponentName(info.activityInfo.applicationInfo.packageName,
539                 info.activityInfo.name));
540         assertThat(mActivity.startActivityAsUser.getLastValue().second)
541             .isEqualTo(TestProvidersAccess.OtherUser.USER_HANDLE);
542 
543         int flags = mActivity.startActivityAsUser.getLastValue().first.getFlags();
544         assertEquals(0, flags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
545         assertEquals(0, flags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
546         assertEquals(0, flags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
547         assertEquals(0, flags & Intent.FLAG_GRANT_READ_URI_PERMISSION);
548         assertEquals(Intent.FLAG_ACTIVITY_FORWARD_RESULT,
549                 flags & Intent.FLAG_ACTIVITY_FORWARD_RESULT);
550         assertEquals(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP,
551                 flags & Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
552     }
553 
554     @Test
testOpenAppRoot_removeFlagsAddForwardResult()555     public void testOpenAppRoot_removeFlagsAddForwardResult() throws Exception {
556         ResolveInfo info = TestResolveInfo.create();
557         mActivity.intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
558                 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
559                 | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
560                 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
561                 | Intent.FLAG_GRANT_READ_URI_PERMISSION);
562         mHandler.openRoot(info, TestProvidersAccess.USER_ID);
563         assertThat(mActivity.startActivity.getLastValue().getComponent()).isEqualTo(
564                 new ComponentName(info.activityInfo.applicationInfo.packageName,
565                 info.activityInfo.name));
566 
567         int flags = mActivity.startActivity.getLastValue().getFlags();
568         assertEquals(0, flags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
569         assertEquals(0, flags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
570         assertEquals(0, flags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
571         assertEquals(0, flags & Intent.FLAG_GRANT_READ_URI_PERMISSION);
572         assertEquals(Intent.FLAG_ACTIVITY_FORWARD_RESULT,
573                 flags & Intent.FLAG_ACTIVITY_FORWARD_RESULT);
574         assertEquals(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP,
575                 flags & Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
576     }
577 
578     @Test
testOpenAppRootWithQueryContent_matchedContent()579     public void testOpenAppRootWithQueryContent_matchedContent() throws Exception {
580         final String queryContent = "query";
581         mActivity.intent.putExtra(Intent.EXTRA_CONTENT_QUERY, queryContent);
582         mHandler.openRoot(TestResolveInfo.create(), TestProvidersAccess.USER_ID);
583         assertEquals(queryContent,
584                 mActivity.startActivity.getLastValue().getStringExtra(
585                 Intent.EXTRA_CONTENT_QUERY));
586     }
587 
588     @Test
testOpenAppRoot_doesNotHappen_differentUser()589     public void testOpenAppRoot_doesNotHappen_differentUser() throws Exception {
590         final String queryContent = "query";
591         mActivity.intent.putExtra(Intent.EXTRA_CONTENT_QUERY, queryContent);
592         mHandler.openRoot(TestResolveInfo.create(), TestProvidersAccess.OtherUser.USER_ID);
593         assertThat(mActivity.startActivityForResult.getLastValue()).isNull();
594         mEnv.dialogs.assertActionNotAllowedShown();
595     }
596 
597     @Test
testPreviewItem()598     public void testPreviewItem() throws Exception {
599         mActivity.resources.setQuickViewerPackage("corptropolis.viewer");
600         mActivity.currentRoot = TestProvidersAccess.HOME;
601 
602         mHandler.onDocumentOpened(TestEnv.FILE_GIF, ActionHandler.VIEW_TYPE_PREVIEW,
603                 ActionHandler.VIEW_TYPE_REGULAR, true);
604         mActivity.assertActivityStarted(Intent.ACTION_QUICK_VIEW);
605     }
606 
607     @Test
testPreviewItem_onOtherUser()608     public void testPreviewItem_onOtherUser() throws Exception {
609         if (VersionUtils.isAtLeastR()) {
610             mActivity.resources.setQuickViewerPackage("corptropolis.viewer");
611             mActivity.currentRoot = TestProvidersAccess.OtherUser.DOWNLOADS;
612             mEnv.model.reset();
613             DocumentInfo otherUserDoc = mEnv.model.createDocumentForUser("a.png",
614                     "image/png", /* flags= */ 0, TestProvidersAccess.OtherUser.USER_ID);
615             mEnv.model.update();
616 
617             mHandler.onDocumentOpened(otherUserDoc, ActionHandler.VIEW_TYPE_PREVIEW,
618                     ActionHandler.VIEW_TYPE_REGULAR, true);
619             mActivity.assertActivityAsUserStarted(Intent.ACTION_QUICK_VIEW,
620                     TestProvidersAccess.OtherUser.USER_HANDLE);
621         }
622     }
623 
624     @Test
testPreviewItem_archives()625     public void testPreviewItem_archives() throws Exception {
626         mActivity.resources.setQuickViewerPackage("corptropolis.viewer");
627         mActivity.currentRoot = TestProvidersAccess.HOME;
628 
629         mHandler.onDocumentOpened(TestEnv.FILE_ARCHIVE, ActionHandler.VIEW_TYPE_PREVIEW,
630                 ActionHandler.VIEW_TYPE_REGULAR, true);
631         mActivity.assertActivityStarted(Intent.ACTION_QUICK_VIEW);
632     }
633 
634     @Test
testPreviewItem_noQuickViewer()635     public void testPreviewItem_noQuickViewer() throws Exception {
636         mActivity.currentRoot = TestProvidersAccess.HOME;
637 
638         mHandler.onDocumentOpened(TestEnv.FILE_GIF, ActionHandler.VIEW_TYPE_PREVIEW,
639                 ActionHandler.VIEW_TYPE_REGULAR, true);
640         mActivity.assertActivityStarted(Intent.ACTION_VIEW);
641     }
642 
testInitLocationDefaultToRecentsOnAction(@ctionType int action)643     private void testInitLocationDefaultToRecentsOnAction(@ActionType int action)
644             throws Exception {
645         mEnv.state.action = action;
646 
647         mActivity.refreshCurrentRootAndDirectory.assertNotCalled();
648 
649         mHandler.initLocation(mActivity.getIntent());
650 
651         mEnv.beforeAsserts();
652         assertEquals(TestProvidersAccess.RECENTS, mEnv.state.stack.getRoot());
653         mActivity.refreshCurrentRootAndDirectory.assertCalled();
654     }
655 
testInitLocationDefaultToDownloadsOnAction(@ctionType int action)656     private void testInitLocationDefaultToDownloadsOnAction(@ActionType int action)
657             throws Exception {
658         mEnv.state.action = action;
659         mActivity.resources.strings.put(R.string.default_root_uri,
660                 TestProvidersAccess.DOWNLOADS.getUri().toString());
661 
662         mActivity.refreshCurrentRootAndDirectory.assertNotCalled();
663 
664         mHandler.initLocation(mActivity.getIntent());
665 
666         assertRootPicked(TestProvidersAccess.DOWNLOADS.getUri());
667     }
668 
assertRootPicked(Uri expectedUri)669     private void assertRootPicked(Uri expectedUri) throws Exception {
670         mEnv.beforeAsserts();
671 
672         mActivity.rootPicked.assertCalled();
673         RootInfo root = mActivity.rootPicked.getLastValue();
674         assertNotNull(root);
675         assertEquals(expectedUri, root.getUri());
676     }
677 
assertLastAccessedStackUpdated()678     private void assertLastAccessedStackUpdated() {
679         assertEquals(mEnv.state.stack, mLastAccessed.getLastAccessed(
680                 mActivity, mEnv.providers, mEnv.state));
681     }
682 
assertPermission(Intent intent, int permission, boolean granted)683     private void assertPermission(Intent intent, int permission, boolean granted) {
684         int flags = intent.getFlags();
685 
686         if (granted) {
687             assertEquals(permission, flags & permission);
688         } else {
689             assertEquals(0, flags & permission);
690         }
691     }
692 
assertContent(Intent intent, Uri... contents)693     private void assertContent(Intent intent, Uri... contents) {
694         if (contents.length == 1) {
695             assertEquals(contents[0], intent.getData());
696         } else {
697             ClipData clipData = intent.getClipData();
698 
699             assertNotNull(clipData);
700             for (int i = 0; i < mEnv.state.acceptMimes.length; ++i) {
701                 assertEquals(mEnv.state.acceptMimes[i], clipData.getDescription().getMimeType(i));
702             }
703             for (int i = 0; i < contents.length; ++i) {
704                 assertEquals(contents[i], clipData.getItemAt(i).getUri());
705             }
706         }
707     }
708 }
709