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 17package com.android.documentsui.picker; 18 19import static junit.framework.Assert.assertTrue; 20 21import static org.junit.Assert.assertEquals; 22import static org.junit.Assert.assertNotNull; 23 24import android.app.Activity; 25import android.content.ClipData; 26import android.content.Intent; 27import android.net.Uri; 28import android.os.AsyncTask; 29import android.provider.DocumentsContract; 30import android.provider.DocumentsContract.Path; 31import android.support.test.filters.MediumTest; 32import android.support.test.runner.AndroidJUnit4; 33 34import com.android.documentsui.AbstractActionHandler; 35import com.android.documentsui.R; 36import com.android.documentsui.base.DocumentStack; 37import com.android.documentsui.base.RootInfo; 38import com.android.documentsui.base.Shared; 39import com.android.documentsui.base.State; 40import com.android.documentsui.base.State.ActionType; 41import com.android.documentsui.testing.DocumentStackAsserts; 42import com.android.documentsui.testing.TestEnv; 43import com.android.documentsui.testing.TestProvidersAccess; 44import com.android.documentsui.testing.TestLastAccessedStorage; 45import com.android.documentsui.testing.TestResolveInfo; 46 47import org.junit.AfterClass; 48import org.junit.Before; 49import org.junit.Test; 50import org.junit.runner.RunWith; 51 52import java.util.Arrays; 53 54@RunWith(AndroidJUnit4.class) 55@MediumTest 56public class ActionHandlerTest { 57 58 private TestEnv mEnv; 59 private TestActivity mActivity; 60 private ActionHandler<TestActivity> mHandler; 61 private TestLastAccessedStorage mLastAccessed; 62 63 @Before 64 public void setUp() { 65 mEnv = TestEnv.create(); 66 mActivity = TestActivity.create(mEnv); 67 mEnv.roots.configurePm(mActivity.packageMgr); 68 mLastAccessed = new TestLastAccessedStorage(); 69 70 mHandler = new ActionHandler<>( 71 mActivity, 72 mEnv.state, 73 mEnv.roots, 74 mEnv.docs, 75 mEnv.searchViewManager, 76 mEnv::lookupExecutor, 77 mEnv.injector, 78 mLastAccessed 79 ); 80 81 mEnv.dialogs.confirmNext(); 82 83 mEnv.selectionMgr.toggleSelection("1"); 84 85 AsyncTask.setDefaultExecutor(mEnv.mExecutor); 86 } 87 88 @AfterClass 89 public static void tearDownOnce() { 90 AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 91 } 92 93 @Test 94 public void testInitLocation_CopyDestination_DefaultsToDownloads() throws Exception { 95 mActivity.resources.bools.put(R.bool.show_documents_root, false); 96 97 Intent intent = mActivity.getIntent(); 98 intent.setAction(Shared.ACTION_PICK_COPY_DESTINATION); 99 mHandler.initLocation(mActivity.getIntent()); 100 assertRootPicked(TestProvidersAccess.DOWNLOADS.getUri()); 101 } 102 103 @Test 104 public void testInitLocation_CopyDestination_DocumentsRootEnabled() throws Exception { 105 mActivity.resources.bools.put(R.bool.show_documents_root, true); 106 107 Intent intent = mActivity.getIntent(); 108 intent.setAction(Shared.ACTION_PICK_COPY_DESTINATION); 109 mHandler.initLocation(intent); 110 assertRootPicked(TestProvidersAccess.HOME.getUri()); 111 } 112 113 @Test 114 public void testInitLocation_LaunchToDocuments() throws Exception { 115 mEnv.docs.nextIsDocumentsUri = true; 116 mEnv.docs.nextPath = new Path( 117 TestProvidersAccess.HOME.rootId, 118 Arrays.asList( 119 TestEnv.FOLDER_0.documentId, 120 TestEnv.FOLDER_1.documentId, 121 TestEnv.FILE_GIF.documentId)); 122 mEnv.docs.nextDocuments = 123 Arrays.asList(TestEnv.FOLDER_0, TestEnv.FOLDER_1, TestEnv.FILE_GIF); 124 125 mActivity.refreshCurrentRootAndDirectory.assertNotCalled(); 126 Intent intent = mActivity.getIntent(); 127 intent.setAction(Intent.ACTION_GET_CONTENT); 128 intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, TestEnv.FILE_GIF.derivedUri); 129 mHandler.initLocation(intent); 130 131 mEnv.beforeAsserts(); 132 133 DocumentStackAsserts.assertEqualsTo(mEnv.state.stack, TestProvidersAccess.HOME, 134 Arrays.asList(TestEnv.FOLDER_0, TestEnv.FOLDER_1)); 135 mActivity.refreshCurrentRootAndDirectory.assertCalled(); 136 } 137 138 @Test 139 public void testInitLocation_RestoresLastAccessedStack() throws Exception { 140 final DocumentStack stack = 141 new DocumentStack(TestProvidersAccess.HAMMY, TestEnv.FOLDER_0, TestEnv.FOLDER_1); 142 mLastAccessed.setLastAccessed(mActivity, stack); 143 144 mHandler.initLocation(mActivity.getIntent()); 145 146 mEnv.beforeAsserts(); 147 assertEquals(stack, mEnv.state.stack); 148 mActivity.refreshCurrentRootAndDirectory.assertCalled(); 149 } 150 151 @Test 152 public void testInitLocation_DefaultToRecents_ActionGetContent() throws Exception { 153 testInitLocationDefaultToRecentsOnAction(State.ACTION_GET_CONTENT); 154 } 155 156 @Test 157 public void testInitLocation_DefaultToRecents_ActionOpen() throws Exception { 158 testInitLocationDefaultToRecentsOnAction(State.ACTION_OPEN); 159 } 160 161 @Test 162 public void testInitLocation_DefaultToRecents_ActionOpenTree() throws Exception { 163 testInitLocationDefaultToRecentsOnAction(State.ACTION_OPEN_TREE); 164 } 165 166 @Test 167 public void testInitLocation_DefaultsToDownloads_ActionCreate() throws Exception { 168 mEnv.state.action = State.ACTION_CREATE; 169 mActivity.resources.bools.put(R.bool.show_documents_root, false); 170 171 mActivity.refreshCurrentRootAndDirectory.assertNotCalled(); 172 173 mHandler.initLocation(mActivity.getIntent()); 174 175 assertRootPicked(TestProvidersAccess.DOWNLOADS.getUri()); 176 } 177 178 @Test 179 public void testOpenContainerDocument() { 180 mHandler.openContainerDocument(TestEnv.FOLDER_0); 181 182 assertEquals(TestEnv.FOLDER_0, mEnv.state.stack.peek()); 183 184 mActivity.refreshCurrentRootAndDirectory.assertCalled(); 185 } 186 187 @Test 188 public void testPickDocument_SetsCorrectResultAndFinishes_ActionPickCopyDestination() 189 throws Exception { 190 191 mEnv.state.action = State.ACTION_PICK_COPY_DESTINATION; 192 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 193 mEnv.state.stack.push(TestEnv.FOLDER_1); 194 mEnv.state.stack.push(TestEnv.FOLDER_2); 195 196 mActivity.finishedHandler.assertNotCalled(); 197 198 mHandler.pickDocument(TestEnv.FOLDER_2); 199 200 mEnv.beforeAsserts(); 201 202 assertLastAccessedStackUpdated(); 203 204 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 205 final Intent result = mActivity.setResult.getLastValue().second; 206 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, false); 207 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false); 208 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false); 209 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false); 210 assertContent(result, TestEnv.FOLDER_2.derivedUri); 211 212 mActivity.finishedHandler.assertCalled(); 213 } 214 215 @Test 216 public void testPickDocument_SetsCorrectResultAndFinishes_ActionOpenTree() throws Exception { 217 mEnv.state.action = State.ACTION_OPEN_TREE; 218 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 219 mEnv.state.stack.push(TestEnv.FOLDER_1); 220 mEnv.state.stack.push(TestEnv.FOLDER_2); 221 222 mActivity.finishedHandler.assertNotCalled(); 223 224 mHandler.pickDocument(TestEnv.FOLDER_2); 225 226 mEnv.beforeAsserts(); 227 228 assertLastAccessedStackUpdated(); 229 230 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 231 final Intent result = mActivity.setResult.getLastValue().second; 232 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true); 233 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true); 234 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true); 235 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, true); 236 assertContent(result, DocumentsContract.buildTreeDocumentUri( 237 TestProvidersAccess.HOME.authority, TestEnv.FOLDER_2.documentId)); 238 239 mActivity.finishedHandler.assertCalled(); 240 } 241 242 @Test 243 public void testSaveDocument_SetsCorrectResultAndFinishes() throws Exception { 244 mEnv.state.action = State.ACTION_CREATE; 245 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 246 mEnv.state.stack.push(TestEnv.FOLDER_1); 247 248 final String mimeType = "audio/aac"; 249 final String displayName = "foobar.m4a"; 250 251 mHandler.saveDocument(mimeType, displayName, (boolean inProgress) -> {}); 252 253 mEnv.beforeAsserts(); 254 255 mEnv.docs.assertCreatedDocument(TestEnv.FOLDER_1, mimeType, displayName); 256 final Uri docUri = mEnv.docs.getLastCreatedDocumentUri(); 257 258 assertLastAccessedStackUpdated(); 259 260 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 261 final Intent result = mActivity.setResult.getLastValue().second; 262 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true); 263 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true); 264 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true); 265 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false); 266 assertContent(result, docUri); 267 268 mActivity.finishedHandler.assertCalled(); 269 } 270 271 @Test 272 public void testSaveDocument_ConfirmsOverwrite() { 273 mEnv.state.action = State.ACTION_CREATE; 274 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 275 mEnv.state.stack.push(TestEnv.FOLDER_1); 276 277 mHandler.saveDocument(null, TestEnv.FILE_JPG); 278 279 mEnv.dialogs.assertOverwriteConfirmed(TestEnv.FILE_JPG); 280 } 281 282 @Test 283 public void testFinishPicking_SetsCorrectResultAndFinishes_ActionGetContent() throws Exception { 284 mEnv.state.action = State.ACTION_GET_CONTENT; 285 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 286 mEnv.state.stack.push(TestEnv.FOLDER_1); 287 288 mActivity.finishedHandler.assertNotCalled(); 289 290 mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri); 291 292 mEnv.beforeAsserts(); 293 294 assertLastAccessedStackUpdated(); 295 296 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 297 final Intent result = mActivity.setResult.getLastValue().second; 298 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true); 299 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false); 300 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false); 301 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false); 302 assertContent(result, TestEnv.FILE_JPG.derivedUri); 303 304 mActivity.finishedHandler.assertCalled(); 305 } 306 307 @Test 308 public void testFinishPicking_SetsCorrectResultAndFinishes_ActionGetContent_MultipleSelection() 309 throws Exception { 310 mEnv.state.action = State.ACTION_GET_CONTENT; 311 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 312 mEnv.state.stack.push(TestEnv.FOLDER_1); 313 mEnv.state.acceptMimes = new String[] { "image/*" }; 314 315 mActivity.finishedHandler.assertNotCalled(); 316 317 mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri, TestEnv.FILE_GIF.derivedUri); 318 319 mEnv.beforeAsserts(); 320 321 assertLastAccessedStackUpdated(); 322 323 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 324 final Intent result = mActivity.setResult.getLastValue().second; 325 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true); 326 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false); 327 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false); 328 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false); 329 assertContent(result, TestEnv.FILE_JPG.derivedUri, TestEnv.FILE_GIF.derivedUri); 330 331 mActivity.finishedHandler.assertCalled(); 332 } 333 334 @Test 335 public void testFinishPicking_SetsCorrectResultAndFinishes_ActionOpen() throws Exception { 336 mEnv.state.action = State.ACTION_OPEN; 337 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 338 mEnv.state.stack.push(TestEnv.FOLDER_1); 339 340 mActivity.finishedHandler.assertNotCalled(); 341 342 mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri); 343 344 mEnv.beforeAsserts(); 345 346 assertLastAccessedStackUpdated(); 347 348 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 349 final Intent result = mActivity.setResult.getLastValue().second; 350 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true); 351 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true); 352 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true); 353 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false); 354 assertContent(result, TestEnv.FILE_JPG.derivedUri); 355 356 mActivity.finishedHandler.assertCalled(); 357 } 358 359 @Test 360 public void testFinishPicking_SetsCorrectResultAndFinishes_ActionOpen_MultipleSelection() 361 throws Exception { 362 mEnv.state.action = State.ACTION_OPEN; 363 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 364 mEnv.state.stack.push(TestEnv.FOLDER_1); 365 mEnv.state.acceptMimes = new String[] { "image/*" }; 366 367 mActivity.finishedHandler.assertNotCalled(); 368 369 mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri, TestEnv.FILE_GIF.derivedUri); 370 371 mEnv.beforeAsserts(); 372 373 assertLastAccessedStackUpdated(); 374 375 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 376 final Intent result = mActivity.setResult.getLastValue().second; 377 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true); 378 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true); 379 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true); 380 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false); 381 assertContent(result, TestEnv.FILE_JPG.derivedUri, TestEnv.FILE_GIF.derivedUri); 382 383 mActivity.finishedHandler.assertCalled(); 384 } 385 386 @Test 387 public void testFinishPicking_SetsCorrectResultAndFinishes_ActionCreate() throws Exception { 388 mEnv.state.action = State.ACTION_CREATE; 389 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 390 mEnv.state.stack.push(TestEnv.FOLDER_1); 391 392 mActivity.finishedHandler.assertNotCalled(); 393 394 mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri); 395 396 mEnv.beforeAsserts(); 397 398 assertLastAccessedStackUpdated(); 399 400 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 401 final Intent result = mActivity.setResult.getLastValue().second; 402 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true); 403 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true); 404 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true); 405 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false); 406 assertContent(result, TestEnv.FILE_JPG.derivedUri); 407 408 mActivity.finishedHandler.assertCalled(); 409 } 410 411 @Test 412 public void testOnAppPickedResult_OnOK() throws Exception { 413 Intent intent = new Intent(); 414 mHandler.onActivityResult(AbstractActionHandler.CODE_FORWARD, Activity.RESULT_OK, intent); 415 mActivity.finishedHandler.assertCalled(); 416 mActivity.setResult.assertCalled(); 417 418 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 419 assertEquals(intent, mActivity.setResult.getLastValue().second); 420 } 421 422 @Test 423 public void testOnAppPickedResult_OnNotOK() throws Exception { 424 Intent intent = new Intent(); 425 mHandler.onActivityResult(0, Activity.RESULT_OK, intent); 426 mActivity.finishedHandler.assertNotCalled(); 427 mActivity.setResult.assertNotCalled(); 428 429 mHandler.onActivityResult(AbstractActionHandler.CODE_FORWARD, Activity.RESULT_CANCELED, 430 intent); 431 mActivity.finishedHandler.assertNotCalled(); 432 mActivity.setResult.assertNotCalled(); 433 } 434 435 @Test 436 public void testOpenAppRoot() throws Exception { 437 mHandler.openRoot(TestResolveInfo.create()); 438 assertEquals((long) mActivity.startActivityForResult.getLastValue().second, 439 AbstractActionHandler.CODE_FORWARD); 440 assertNotNull(mActivity.startActivityForResult.getLastValue().first); 441 } 442 443 private void testInitLocationDefaultToRecentsOnAction(@ActionType int action) 444 throws Exception { 445 mEnv.state.action = action; 446 447 mActivity.refreshCurrentRootAndDirectory.assertNotCalled(); 448 449 mHandler.initLocation(mActivity.getIntent()); 450 451 mEnv.beforeAsserts(); 452 assertEquals(TestProvidersAccess.RECENTS, mEnv.state.stack.getRoot()); 453 mActivity.refreshCurrentRootAndDirectory.assertCalled(); 454 } 455 456 private void assertRootPicked(Uri expectedUri) throws Exception { 457 mEnv.beforeAsserts(); 458 459 mActivity.rootPicked.assertCalled(); 460 RootInfo root = mActivity.rootPicked.getLastValue(); 461 assertNotNull(root); 462 assertEquals(expectedUri, root.getUri()); 463 } 464 465 private void assertLastAccessedStackUpdated() { 466 assertEquals( 467 mEnv.state.stack, mLastAccessed.getLastAccessed(mActivity, mEnv.roots, mEnv.state)); 468 } 469 470 private void assertPermission(Intent intent, int permission, boolean granted) { 471 int flags = intent.getFlags(); 472 473 if (granted) { 474 assertEquals(permission, flags & permission); 475 } else { 476 assertEquals(0, flags & permission); 477 } 478 } 479 480 private void assertContent(Intent intent, Uri... contents) { 481 if (contents.length == 1) { 482 assertEquals(contents[0], intent.getData()); 483 } else { 484 ClipData clipData = intent.getClipData(); 485 486 assertNotNull(clipData); 487 for (int i = 0; i < mEnv.state.acceptMimes.length; ++i) { 488 assertEquals(mEnv.state.acceptMimes[i], clipData.getDescription().getMimeType(i)); 489 } 490 for (int i = 0; i < contents.length; ++i) { 491 assertEquals(contents[i], clipData.getItemAt(i).getUri()); 492 } 493 } 494 } 495} 496