1 /* 2 * Copyright (C) 2014 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.cts.documentclient; 18 19 import android.app.Activity; 20 import android.content.ContentResolver; 21 import android.content.Intent; 22 import android.content.IntentSender; 23 import android.database.Cursor; 24 import android.net.Uri; 25 import android.os.Bundle; 26 import android.os.SystemClock; 27 import android.provider.DocumentsContract; 28 import android.provider.DocumentsContract.Document; 29 import android.provider.DocumentsContract.Path; 30 import android.provider.DocumentsProvider; 31 import android.support.test.uiautomator.UiObject; 32 import android.support.test.uiautomator.UiObjectNotFoundException; 33 import android.support.test.uiautomator.UiScrollable; 34 import android.support.test.uiautomator.UiSelector; 35 import android.test.MoreAsserts; 36 import android.util.Log; 37 38 import com.android.cts.documentclient.MyActivity.Result; 39 40 import java.util.List; 41 42 /** 43 * Tests for {@link DocumentsProvider} and interaction with platform intents 44 * like {@link Intent#ACTION_OPEN_DOCUMENT}. 45 */ 46 public class DocumentsClientTest extends DocumentsClientTestCase { 47 private static final String TAG = "DocumentsClientTest"; 48 49 private UiSelector findRootListSelector() throws UiObjectNotFoundException { 50 return new UiSelector().resourceId( 51 getDocumentsUiPackageId() + ":id/container_roots").childSelector( 52 new UiSelector().resourceId(getDocumentsUiPackageId() + ":id/roots_list")); 53 54 } 55 56 private void revealRoot(UiSelector rootsList, String label) throws UiObjectNotFoundException { 57 // We might need to expand drawer if not visible 58 if (!new UiObject(rootsList).waitForExists(TIMEOUT)) { 59 Log.d(TAG, "Failed to find roots list; trying to expand"); 60 final UiSelector hamburger = new UiSelector().resourceId( 61 getDocumentsUiPackageId() + ":id/toolbar").childSelector( 62 new UiSelector().className("android.widget.ImageButton").clickable(true)); 63 new UiObject(hamburger).click(); 64 } 65 66 // Wait for the first list item to appear 67 assertTrue("First list item", 68 new UiObject(rootsList.childSelector(new UiSelector())).waitForExists(TIMEOUT)); 69 70 // Now scroll around to find our item 71 new UiScrollable(rootsList).scrollIntoView(new UiSelector().text(label)); 72 } 73 74 private UiObject findSearchViewTextField() { 75 final UiSelector selector = new UiSelector().resourceId( 76 getDocumentsUiPackageId() + ":id/option_menu_search").childSelector( 77 new UiSelector().resourceId(getDocumentsUiPackageId() + ":id/search_src_text")); 78 return mDevice.findObject(selector); 79 } 80 81 private UiObject findRoot(String label) throws UiObjectNotFoundException { 82 final UiSelector rootsList = findRootListSelector(); 83 revealRoot(rootsList, label); 84 85 return new UiObject(rootsList.childSelector(new UiSelector().text(label))); 86 } 87 88 private UiObject findActionIcon(String rootLabel) throws UiObjectNotFoundException { 89 final UiSelector rootsList = findRootListSelector(); 90 revealRoot(rootsList, rootLabel); 91 92 final UiScrollable rootsListObject = new UiScrollable(rootsList); 93 final UiObject rootItem = rootsListObject.getChildByText( 94 new UiSelector().className("android.widget.LinearLayout"), rootLabel, false); 95 final UiSelector actionIcon = 96 new UiSelector().resourceId(getDocumentsUiPackageId() + ":id/action_icon_area"); 97 return new UiObject(rootItem.getSelector().childSelector(actionIcon)); 98 } 99 100 private UiObject findDocument(String label) throws UiObjectNotFoundException { 101 final UiSelector docList = new UiSelector().resourceId( 102 getDocumentsUiPackageId() + ":id/container_directory").childSelector( 103 new UiSelector().resourceId(getDocumentsUiPackageId() + ":id/dir_list")); 104 105 // Wait for the first list item to appear 106 assertTrue("First list item", 107 new UiObject(docList.childSelector(new UiSelector())).waitForExists(TIMEOUT)); 108 109 try { 110 //Enfornce to set the list mode 111 //Because UiScrollable can't reach the real bottom (when WEB_LINKABLE_FILE item) in grid mode when screen landscape mode 112 new UiObject(new UiSelector().resourceId("com.android.documentsui:id/option_menu_list")).click(); 113 mDevice.waitForIdle(); 114 }catch (UiObjectNotFoundException e){ 115 //do nothing, already be in list mode. 116 } 117 118 // Now scroll around to find our item 119 new UiScrollable(docList).scrollIntoView(new UiSelector().text(label)); 120 return new UiObject(docList.childSelector(new UiSelector().text(label))); 121 } 122 123 private UiObject findSaveButton() throws UiObjectNotFoundException { 124 return new UiObject(new UiSelector().resourceId( 125 getDocumentsUiPackageId() + ":id/container_save") 126 .childSelector(new UiSelector().resourceId("android:id/button1"))); 127 } 128 129 private UiObject findPositiveButton() throws UiObjectNotFoundException { 130 return new UiObject(new UiSelector().resourceId("android:id/button1")); 131 } 132 133 public void testOpenSimple() throws Exception { 134 if (!supportedHardware()) return; 135 136 try { 137 // Opening without permission should fail 138 readFully(Uri.parse("content://com.android.cts.documentprovider/document/doc:file1")); 139 fail("Able to read data before opened!"); 140 } catch (SecurityException expected) { 141 } 142 143 final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); 144 intent.addCategory(Intent.CATEGORY_OPENABLE); 145 intent.setType("*/*"); 146 mActivity.startActivityForResult(intent, REQUEST_CODE); 147 148 // Ensure that we see both of our roots 149 mDevice.waitForIdle(); 150 assertTrue("CtsLocal root", findRoot("CtsLocal").exists()); 151 assertTrue("CtsCreate root", findRoot("CtsCreate").exists()); 152 assertFalse("CtsGetContent root", findRoot("CtsGetContent").exists()); 153 154 // Choose the local root. 155 mDevice.waitForIdle(); 156 findRoot("CtsLocal").click(); 157 158 // Try picking a virtual file. Virtual files must not be returned for CATEGORY_OPENABLE 159 // though, so the click should be ignored. 160 mDevice.waitForIdle(); 161 findDocument("VIRTUAL_FILE").click(); 162 mDevice.waitForIdle(); 163 164 // Pick a regular file. 165 mDevice.waitForIdle(); 166 findDocument("FILE1").click(); 167 168 // Confirm that the returned file is a regular file caused by the second click. 169 final Result result = mActivity.getResult(); 170 final Uri uri = result.data.getData(); 171 assertEquals("doc:file1", DocumentsContract.getDocumentId(uri)); 172 173 // We should now have permission to read/write 174 MoreAsserts.assertEquals("fileone".getBytes(), readFully(uri)); 175 176 writeFully(uri, "replaced!".getBytes()); 177 SystemClock.sleep(500); 178 MoreAsserts.assertEquals("replaced!".getBytes(), readFully(uri)); 179 } 180 181 public void testOpenVirtual() throws Exception { 182 if (!supportedHardware()) return; 183 184 final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); 185 intent.setType("*/*"); 186 mActivity.startActivityForResult(intent, REQUEST_CODE); 187 188 // Pick a virtual file from the local root. 189 mDevice.waitForIdle(); 190 findRoot("CtsLocal").click(); 191 192 mDevice.waitForIdle(); 193 findDocument("VIRTUAL_FILE").click(); 194 195 // Confirm that the returned file is actually the selected one. 196 final Result result = mActivity.getResult(); 197 final Uri uri = result.data.getData(); 198 assertEquals("doc:virtual-file", DocumentsContract.getDocumentId(uri)); 199 200 final ContentResolver resolver = getInstrumentation().getContext().getContentResolver(); 201 final String streamTypes[] = resolver.getStreamTypes(uri, "*/*"); 202 assertEquals(1, streamTypes.length); 203 assertEquals("text/plain", streamTypes[0]); 204 205 // Virtual files are not readable unless an alternative MIME type is specified. 206 try { 207 readFully(uri); 208 fail("Unexpected success in reading a virtual file. It should've failed."); 209 } catch (IllegalArgumentException e) { 210 // Expected. 211 } 212 213 // However, they are readable using an alternative MIME type from getStreamTypes(). 214 MoreAsserts.assertEquals( 215 "Converted contents.".getBytes(), readTypedFully(uri, streamTypes[0])); 216 } 217 218 public void testCreateNew() throws Exception { 219 if (!supportedHardware()) return; 220 221 final String DISPLAY_NAME = "My New Awesome Document Title"; 222 final String MIME_TYPE = "image/png"; 223 224 final Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); 225 intent.addCategory(Intent.CATEGORY_OPENABLE); 226 intent.putExtra(Intent.EXTRA_TITLE, DISPLAY_NAME); 227 intent.setType(MIME_TYPE); 228 mActivity.startActivityForResult(intent, REQUEST_CODE); 229 230 mDevice.waitForIdle(); 231 findRoot("CtsCreate").click(); 232 233 mDevice.waitForIdle(); 234 findSaveButton().click(); 235 236 final Result result = mActivity.getResult(); 237 final Uri uri = result.data.getData(); 238 239 writeFully(uri, "meow!".getBytes()); 240 241 assertEquals(DISPLAY_NAME, getColumn(uri, Document.COLUMN_DISPLAY_NAME)); 242 assertEquals(MIME_TYPE, getColumn(uri, Document.COLUMN_MIME_TYPE)); 243 } 244 245 public void testCreateExisting() throws Exception { 246 if (!supportedHardware()) return; 247 248 final Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); 249 intent.addCategory(Intent.CATEGORY_OPENABLE); 250 intent.putExtra(Intent.EXTRA_TITLE, "NEVERUSED"); 251 intent.setType("mime2/file2"); 252 mActivity.startActivityForResult(intent, REQUEST_CODE); 253 254 mDevice.waitForIdle(); 255 findRoot("CtsCreate").click(); 256 257 // Pick file2, which should be selected since MIME matches, then try 258 // picking a non-matching MIME, which should leave file2 selected. 259 mDevice.waitForIdle(); 260 findDocument("FILE2").click(); 261 mDevice.waitForIdle(); 262 findDocument("FILE1").click(); 263 264 mDevice.waitForIdle(); 265 findSaveButton().click(); 266 267 mDevice.waitForIdle(); 268 findPositiveButton().click(); 269 270 final Result result = mActivity.getResult(); 271 final Uri uri = result.data.getData(); 272 273 MoreAsserts.assertEquals("filetwo".getBytes(), readFully(uri)); 274 } 275 276 public void testTree() throws Exception { 277 if (!supportedHardware()) return; 278 279 final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); 280 mActivity.startActivityForResult(intent, REQUEST_CODE); 281 282 mDevice.waitForIdle(); 283 findRoot("CtsCreate").click(); 284 285 mDevice.waitForIdle(); 286 findDocument("DIR2").click(); 287 mDevice.waitForIdle(); 288 findSaveButton().click(); 289 mDevice.waitForIdle(); 290 findPositiveButton().click(); 291 292 final Result result = mActivity.getResult(); 293 final Uri uri = result.data.getData(); 294 295 // We should have selected DIR2 296 Uri doc = DocumentsContract.buildDocumentUriUsingTree(uri, 297 DocumentsContract.getTreeDocumentId(uri)); 298 Uri children = DocumentsContract.buildChildDocumentsUriUsingTree(uri, 299 DocumentsContract.getTreeDocumentId(uri)); 300 301 assertEquals("DIR2", getColumn(doc, Document.COLUMN_DISPLAY_NAME)); 302 303 // Look around and make sure we can see children 304 final ContentResolver resolver = getInstrumentation().getContext().getContentResolver(); 305 Cursor cursor = resolver.query(children, new String[] { 306 Document.COLUMN_DISPLAY_NAME }, null, null, null); 307 try { 308 assertEquals(2, cursor.getCount()); 309 assertTrue(cursor.moveToFirst()); 310 assertEquals("FILE4", cursor.getString(0)); 311 } finally { 312 cursor.close(); 313 } 314 315 // Create some documents 316 Uri pic = DocumentsContract.createDocument(resolver, doc, "image/png", "pic.png"); 317 Uri dir = DocumentsContract.createDocument(resolver, doc, Document.MIME_TYPE_DIR, "my dir"); 318 Uri dirPic = DocumentsContract.createDocument(resolver, dir, "image/png", "pic2.png"); 319 320 writeFully(pic, "pic".getBytes()); 321 writeFully(dirPic, "dirPic".getBytes()); 322 323 // Read then delete existing doc 324 final Uri file4 = DocumentsContract.buildDocumentUriUsingTree(uri, "doc:file4"); 325 MoreAsserts.assertEquals("filefour".getBytes(), readFully(file4)); 326 assertTrue("delete", DocumentsContract.deleteDocument(resolver, file4)); 327 try { 328 MoreAsserts.assertEquals("filefour".getBytes(), readFully(file4)); 329 fail("Expected file to be gone"); 330 } catch (SecurityException expected) { 331 } 332 333 // And rename something 334 dirPic = DocumentsContract.renameDocument(resolver, dirPic, "wow"); 335 assertNotNull("rename", dirPic); 336 337 // We should only see single child 338 assertEquals("wow", getColumn(dirPic, Document.COLUMN_DISPLAY_NAME)); 339 MoreAsserts.assertEquals("dirPic".getBytes(), readFully(dirPic)); 340 341 try { 342 // Make sure we can't see files outside selected dir 343 getColumn(DocumentsContract.buildDocumentUriUsingTree(uri, "doc:file1"), 344 Document.COLUMN_DISPLAY_NAME); 345 fail("Somehow read document outside tree!"); 346 } catch (SecurityException expected) { 347 } 348 } 349 350 public void testGetContent_rootsShowing() throws Exception { 351 if (!supportedHardware()) return; 352 353 final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 354 intent.addCategory(Intent.CATEGORY_OPENABLE); 355 intent.setType("*/*"); 356 mActivity.startActivityForResult(intent, REQUEST_CODE); 357 358 // Look around, we should be able to see both DocumentsProviders and 359 // other GET_CONTENT sources. If the DocumentsProvider and GetContent 360 // root has the same package, they will be combined as one root item. 361 mDevice.waitForIdle(); 362 assertTrue("CtsLocal root", findRoot("CtsLocal").exists()); 363 assertTrue("CtsCreate root", findRoot("CtsCreate").exists()); 364 assertFalse("CtsGetContent root", findRoot("CtsGetContent").exists()); 365 366 mDevice.waitForIdle(); 367 // Both CtsLocal and CtsLocal have action icon and have the same action. 368 findActionIcon("CtsCreate"); 369 findActionIcon("CtsLocal").click(); 370 Result result = mActivity.getResult(); 371 assertEquals("ReSuLt", result.data.getAction()); 372 } 373 374 public void testGetContentWithQuery_matchingFileShowing() throws Exception { 375 if (!supportedHardware()) return; 376 377 final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 378 intent.addCategory(Intent.CATEGORY_OPENABLE); 379 intent.setType("*/*"); 380 final String queryString = "FILE2"; 381 intent.putExtra(Intent.EXTRA_CONTENT_QUERY, queryString); 382 mActivity.startActivityForResult(intent, REQUEST_CODE); 383 384 mDevice.waitForIdle(); 385 386 assertTrue(findDocument(queryString).exists()); 387 388 UiObject textField = findSearchViewTextField(); 389 assertTrue(textField.exists()); 390 assertEquals(queryString, textField.getText()); 391 } 392 393 public void testGetContent_returnsResultToCallingActivity() throws Exception { 394 if (!supportedHardware()) return; 395 396 final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 397 intent.addCategory(Intent.CATEGORY_OPENABLE); 398 intent.setType("*/*"); 399 mActivity.startActivityForResult(intent, REQUEST_CODE); 400 401 mDevice.waitForIdle(); 402 findRoot("CtsCreate").click(); 403 404 // Pick the file. 405 mDevice.waitForIdle(); 406 findDocument("FILE2").click(); 407 408 // Confirm that the returned file is a regular file caused by the click. 409 final Result result = mActivity.getResult(); 410 final Uri uri = result.data.getData(); 411 assertEquals("doc:file2", DocumentsContract.getDocumentId(uri)); 412 413 // We should now have permission to read 414 MoreAsserts.assertEquals("filetwo".getBytes(), readFully(uri)); 415 } 416 417 public void testTransferDocument() throws Exception { 418 if (!supportedHardware()) return; 419 420 try { 421 // Opening without permission should fail. 422 readFully(Uri.parse("content://com.android.cts.documentprovider/document/doc:file1")); 423 fail("Able to read data before opened!"); 424 } catch (SecurityException expected) { 425 } 426 427 final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); 428 mActivity.startActivityForResult(intent, REQUEST_CODE); 429 430 mDevice.waitForIdle(); 431 findRoot("CtsCreate").click(); 432 433 findDocument("DIR2").click(); 434 mDevice.waitForIdle(); 435 findSaveButton().click(); 436 mDevice.waitForIdle(); 437 findPositiveButton().click(); 438 439 final Result result = mActivity.getResult(); 440 final Uri uri = result.data.getData(); 441 442 // We should have selected DIR2. 443 final Uri docUri = DocumentsContract.buildDocumentUriUsingTree(uri, 444 DocumentsContract.getTreeDocumentId(uri)); 445 446 assertEquals("DIR2", getColumn(docUri, Document.COLUMN_DISPLAY_NAME)); 447 448 final ContentResolver resolver = getInstrumentation().getContext().getContentResolver(); 449 final Cursor cursor = resolver.query( 450 DocumentsContract.buildChildDocumentsUriUsingTree( 451 docUri, DocumentsContract.getDocumentId(docUri)), 452 new String[] { Document.COLUMN_DOCUMENT_ID, Document.COLUMN_DISPLAY_NAME, 453 Document.COLUMN_FLAGS }, 454 null, null, null); 455 456 Uri sourceFileUri = null; 457 Uri targetDirUri = null; 458 459 try { 460 assertEquals(2, cursor.getCount()); 461 assertTrue(cursor.moveToFirst()); 462 sourceFileUri = DocumentsContract.buildDocumentUriUsingTree( 463 docUri, cursor.getString(0)); 464 assertEquals("FILE4", cursor.getString(1)); 465 assertEquals(Document.FLAG_SUPPORTS_WRITE | 466 Document.FLAG_SUPPORTS_COPY | 467 Document.FLAG_SUPPORTS_MOVE | 468 Document.FLAG_SUPPORTS_REMOVE, cursor.getInt(2)); 469 470 assertTrue(cursor.moveToNext()); 471 targetDirUri = DocumentsContract.buildDocumentUriUsingTree( 472 docUri, cursor.getString(0)); 473 assertEquals("SUB_DIR2", cursor.getString(1)); 474 } finally { 475 cursor.close(); 476 } 477 478 // Move, copy then remove. 479 final Uri movedFileUri = DocumentsContract.moveDocument( 480 resolver, sourceFileUri, docUri, targetDirUri); 481 assertTrue(movedFileUri != null); 482 final Uri copiedFileUri = DocumentsContract.copyDocument( 483 resolver, movedFileUri, targetDirUri); 484 assertTrue(copiedFileUri != null); 485 486 // Confirm that the files are at the destinations. 487 Cursor cursorDst = resolver.query( 488 DocumentsContract.buildChildDocumentsUriUsingTree( 489 targetDirUri, DocumentsContract.getDocumentId(targetDirUri)), 490 new String[] { Document.COLUMN_DOCUMENT_ID }, 491 null, null, null); 492 try { 493 assertEquals(2, cursorDst.getCount()); 494 assertTrue(cursorDst.moveToFirst()); 495 assertEquals("doc:file4", cursorDst.getString(0)); 496 assertTrue(cursorDst.moveToNext()); 497 assertEquals("doc:file4_copy", cursorDst.getString(0)); 498 } finally { 499 cursorDst.close(); 500 } 501 502 // ... and gone from the source. 503 final Cursor cursorSrc = resolver.query( 504 DocumentsContract.buildChildDocumentsUriUsingTree( 505 docUri, DocumentsContract.getDocumentId(docUri)), 506 new String[] { Document.COLUMN_DOCUMENT_ID }, 507 null, null, null); 508 try { 509 assertEquals(1, cursorSrc.getCount()); 510 assertTrue(cursorSrc.moveToFirst()); 511 assertEquals("doc:sub_dir2", cursorSrc.getString(0)); 512 } finally { 513 cursorSrc.close(); 514 } 515 516 assertTrue(DocumentsContract.removeDocument(resolver, movedFileUri, targetDirUri)); 517 assertTrue(DocumentsContract.removeDocument(resolver, copiedFileUri, targetDirUri)); 518 519 // Finally, confirm that removing actually removed the files from the destination. 520 cursorDst = resolver.query( 521 DocumentsContract.buildChildDocumentsUriUsingTree( 522 targetDirUri, DocumentsContract.getDocumentId(targetDirUri)), 523 new String[] { Document.COLUMN_DOCUMENT_ID }, 524 null, null, null); 525 try { 526 assertEquals(0, cursorDst.getCount()); 527 } finally { 528 cursorDst.close(); 529 } 530 } 531 532 public void testFindDocumentPathInScopedAccess() throws Exception { 533 if (!supportedHardware()) return; 534 535 final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); 536 mActivity.startActivityForResult(intent, REQUEST_CODE); 537 538 mDevice.waitForIdle(); 539 findRoot("CtsCreate").click(); 540 541 mDevice.waitForIdle(); 542 findDocument("DIR2").click(); 543 mDevice.waitForIdle(); 544 findSaveButton().click(); 545 mDevice.waitForIdle(); 546 findPositiveButton().click(); 547 548 final Result result = mActivity.getResult(); 549 final Uri uri = result.data.getData(); 550 551 // We should have selected DIR2 552 Uri doc = DocumentsContract.buildDocumentUriUsingTree(uri, 553 DocumentsContract.getTreeDocumentId(uri)); 554 555 assertEquals("DIR2", getColumn(doc, Document.COLUMN_DISPLAY_NAME)); 556 557 final ContentResolver resolver = getInstrumentation().getContext().getContentResolver(); 558 559 // Create some documents 560 Uri dir = DocumentsContract.createDocument(resolver, doc, Document.MIME_TYPE_DIR, "my dir"); 561 Uri dirPic = DocumentsContract.createDocument(resolver, dir, "image/png", "pic2.png"); 562 563 writeFully(dirPic, "dirPic".getBytes()); 564 565 // Find the path of a document 566 Path path = DocumentsContract.findDocumentPath(resolver, dirPic); 567 assertNull(path.getRootId()); 568 569 final List<String> docs = path.getPath(); 570 assertEquals("Unexpected path: " + path, 3, docs.size()); 571 assertEquals(DocumentsContract.getTreeDocumentId(uri), docs.get(0)); 572 assertEquals(DocumentsContract.getDocumentId(dir), docs.get(1)); 573 assertEquals(DocumentsContract.getDocumentId(dirPic), docs.get(2)); 574 } 575 576 public void testOpenDocumentAtInitialLocation() throws Exception { 577 if (!supportedHardware()) return; 578 579 // Clear DocsUI's storage to avoid it opening stored last location 580 // which may make this test pass "luckily". 581 clearDocumentsUi(); 582 583 final Uri docUri = DocumentsContract.buildDocumentUri(PROVIDER_PACKAGE, "doc:file1"); 584 final Intent intent = new Intent(); 585 intent.setAction(Intent.ACTION_OPEN_DOCUMENT); 586 intent.addCategory(Intent.CATEGORY_OPENABLE); 587 intent.setType("*/*"); 588 intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, docUri); 589 mActivity.startActivityForResult(intent, REQUEST_CODE); 590 mDevice.waitForIdle(); 591 592 assertTrue(findDocument("FILE1").exists()); 593 } 594 595 public void testOpenDocumentTreeAtInitialLocation() throws Exception { 596 if (!supportedHardware()) return; 597 598 // Clear DocsUI's storage to avoid it opening stored last location 599 // which may make this test pass "luckily". 600 clearDocumentsUi(); 601 602 final Uri docUri = DocumentsContract.buildDocumentUri(PROVIDER_PACKAGE, "doc:dir2"); 603 final Intent intent = new Intent(); 604 intent.setAction(Intent.ACTION_OPEN_DOCUMENT_TREE); 605 intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, docUri); 606 mActivity.startActivityForResult(intent, REQUEST_CODE); 607 mDevice.waitForIdle(); 608 609 assertTrue(findDocument("FILE4").exists()); 610 } 611 612 public void testOpenRootWithoutRootIdAtInitialLocation() throws Exception { 613 if (!supportedHardware()) return; 614 615 // Clear DocsUI's storage to avoid it opening stored last location 616 // which may make this test pass "luckily". 617 clearDocumentsUi(); 618 619 final Uri rootsUri = DocumentsContract.buildRootsUri(PROVIDER_PACKAGE); 620 final Intent intent = new Intent(Intent.ACTION_VIEW); 621 intent.setDataAndType(rootsUri, "vnd.android.document/root"); 622 mActivity.startActivity(intent); 623 mDevice.waitForIdle(); 624 625 assertTrue(findDocument("DIR1").exists()); 626 } 627 628 public void testCreateDocumentAtInitialLocation() throws Exception { 629 if (!supportedHardware()) return; 630 631 // Clear DocsUI's storage to avoid it opening stored last location 632 // which may make this test pass "luckily". 633 clearDocumentsUi(); 634 635 final Uri treeUri = DocumentsContract.buildTreeDocumentUri(PROVIDER_PACKAGE, "doc:local"); 636 final Uri docUri = DocumentsContract.buildDocumentUriUsingTree(treeUri, "doc:file1"); 637 final Intent intent = new Intent(); 638 intent.setAction(Intent.ACTION_CREATE_DOCUMENT); 639 intent.setType("plain/text"); 640 intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, docUri); 641 mActivity.startActivityForResult(intent, REQUEST_CODE); 642 mDevice.waitForIdle(); 643 644 assertTrue(findDocument("FILE1").exists()); 645 } 646 647 public void testCreateWebLink() throws Exception { 648 if (!supportedHardware()) return; 649 650 final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); 651 intent.setType("*/*"); 652 mActivity.startActivityForResult(intent, REQUEST_CODE); 653 654 // Pick a virtual file from the local root. 655 mDevice.waitForIdle(); 656 findRoot("CtsLocal").click(); 657 658 mDevice.waitForIdle(); 659 findDocument("WEB_LINKABLE_FILE").click(); 660 661 // Confirm that the returned file is actually the selected one. 662 final Result result = mActivity.getResult(); 663 final Uri uri = result.data.getData(); 664 assertEquals("doc:web-linkable-file", DocumentsContract.getDocumentId(uri)); 665 666 final ContentResolver resolver = getInstrumentation().getContext().getContentResolver(); 667 668 Bundle bundle = new Bundle(); 669 bundle.putStringArray(Intent.EXTRA_EMAIL, new String[] { "x (at) x.com" }); 670 final IntentSender intentSender = DocumentsContract.createWebLinkIntent(resolver, 671 uri, bundle); 672 673 final int WEB_LINK_REQUEST_CODE = 1; 674 mActivity.startIntentSenderForResult(intentSender, WEB_LINK_REQUEST_CODE, 675 null, 0, 0, 0); 676 mDevice.waitForIdle(); 677 678 // Confirm the permissions dialog. The dialog is provided by the stub 679 // provider. 680 UiObject okButton = new UiObject(new UiSelector().resourceId("android:id/button1")); 681 assertNotNull(okButton); 682 assertTrue(okButton.waitForExists(TIMEOUT)); 683 okButton.click(); 684 685 final Result webLinkResult = mActivity.getResult(); 686 assertEquals(WEB_LINK_REQUEST_CODE, webLinkResult.requestCode); 687 assertEquals(Activity.RESULT_OK, webLinkResult.resultCode); 688 689 final Uri webLinkUri = webLinkResult.data.getData(); 690 assertEquals("http://www.foobar.com/shared/SW33TCH3RR13S", webLinkUri.toString()); 691 } 692 693 public void testEject() throws Exception { 694 if (!supportedHardware()) return; 695 696 final Intent intent = new Intent(Intent.ACTION_VIEW); 697 intent.addCategory(Intent.CATEGORY_DEFAULT); 698 intent.setDataAndType( 699 DocumentsContract.buildChildDocumentsUri(PROVIDER_PACKAGE, "doc:dir1"), 700 Document.MIME_TYPE_DIR); 701 mActivity.startActivity(intent); 702 703 findActionIcon("eject").click(); 704 705 try { 706 findRoot("eject").click(); 707 fail("Root eject was not ejected"); 708 } catch(UiObjectNotFoundException e) { 709 // expected 710 } 711 } 712 } 713