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