blob: 2113ef708b54b03778337f9a60426cf289592f6a [file] [log] [blame]
Jun Onoa46c3d22017-11-22 12:07:49 +09001/*
2 * Copyright (C) 2017 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;
18
Jun Ono6b69cbb2017-12-08 19:07:55 +090019import static com.android.documentsui.base.Providers.AUTHORITY_STORAGE;
20import static com.android.documentsui.base.Providers.ROOT_ID_DEVICE;
Jun Onoa46c3d22017-11-22 12:07:49 +090021
Jun Ono6b69cbb2017-12-08 19:07:55 +090022import android.content.BroadcastReceiver;
Jun Ono6b69cbb2017-12-08 19:07:55 +090023import android.content.ContentProviderClient;
Stephen Hughes496b6ad2019-10-04 12:23:26 +080024import android.content.ContentResolver;
Brett Chabot2027ca02018-12-13 19:06:31 -080025import android.content.Context;
Jun Onoa46c3d22017-11-22 12:07:49 +090026import android.content.Intent;
27import android.content.IntentFilter;
Jun Ono6b69cbb2017-12-08 19:07:55 +090028import android.content.res.Resources;
Jun Onoa46c3d22017-11-22 12:07:49 +090029import android.net.Uri;
Jun Ono6b69cbb2017-12-08 19:07:55 +090030import android.os.Build;
Jun Ono8cf0f002018-01-18 12:37:09 +090031import android.os.Bundle;
Jun Onoa46c3d22017-11-22 12:07:49 +090032import android.os.RemoteException;
Takamasa Kuramitsu3bdd3f52018-06-05 12:21:07 +090033import android.os.SystemClock;
Jun Onoa46c3d22017-11-22 12:07:49 +090034import android.provider.Settings;
Jun Onoa46c3d22017-11-22 12:07:49 +090035import android.text.TextUtils;
Jun Ono6b69cbb2017-12-08 19:07:55 +090036import android.util.Log;
Jun Onoa46c3d22017-11-22 12:07:49 +090037
Brett Chabot2027ca02018-12-13 19:06:31 -080038import androidx.test.filters.LargeTest;
39
Jun Onoa46c3d22017-11-22 12:07:49 +090040import com.android.documentsui.base.DocumentInfo;
Jun Ono6b69cbb2017-12-08 19:07:55 +090041import com.android.documentsui.base.RootInfo;
42import com.android.documentsui.base.State;
Jun Onoa46c3d22017-11-22 12:07:49 +090043import com.android.documentsui.files.FilesActivity;
Felka Changc181d522019-02-21 14:36:08 +080044import com.android.documentsui.filters.HugeLongTest;
Jun Onoa46c3d22017-11-22 12:07:49 +090045import com.android.documentsui.services.TestNotificationService;
46
Jun Ono6b69cbb2017-12-08 19:07:55 +090047import java.util.HashMap;
Stephen Hughes496b6ad2019-10-04 12:23:26 +080048import java.util.ArrayList;
Jun Onoa46c3d22017-11-22 12:07:49 +090049import java.util.List;
Jun Ono6b69cbb2017-12-08 19:07:55 +090050import java.util.Map;
Stephen Hughes496b6ad2019-10-04 12:23:26 +080051import java.util.UUID;
Brett Chabot2027ca02018-12-13 19:06:31 -080052import java.util.concurrent.CountDownLatch;
53import java.util.concurrent.TimeUnit;
felkachangc7fbae22018-11-21 14:13:53 +080054import java.util.zip.ZipEntry;
55import java.util.zip.ZipInputStream;
Jun Onoa46c3d22017-11-22 12:07:49 +090056
57/**
58* This class test the below points
Jun Ono6b69cbb2017-12-08 19:07:55 +090059* - Copy large number of files on the internal/external storage
Jun Onoa46c3d22017-11-22 12:07:49 +090060*/
61@LargeTest
62public class FileCopyUiTest extends ActivityTest<FilesActivity> {
Jun Ono6b69cbb2017-12-08 19:07:55 +090063 private static final String TAG = "FileCopyUiTest";
64
Jun Ono6b69cbb2017-12-08 19:07:55 +090065 private static final String TARGET_FOLDER = "test_folder";
66
Jun Ono6b69cbb2017-12-08 19:07:55 +090067 private static final int TARGET_COUNT = 1000;
68
69 private static final int WAIT_TIME_SECONDS = 180;
70
71 private final Map<String, Long> mTargetFileList = new HashMap<String, Long>();
Jun Onoa46c3d22017-11-22 12:07:49 +090072
Stephen Hughes496b6ad2019-10-04 12:23:26 +080073 private final List<RootAndFolderPair> mFoldersToCleanup = new ArrayList<>();
74
Jun Onoa46c3d22017-11-22 12:07:49 +090075 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
76 @Override
77 public void onReceive(Context context, Intent intent) {
78 String action = intent.getAction();
79 if (TestNotificationService.ACTION_OPERATION_RESULT.equals(action)) {
80 mOperationExecuted = intent.getBooleanExtra(
81 TestNotificationService.EXTRA_RESULT, false);
82 if (!mOperationExecuted) {
83 mErrorReason = intent.getStringExtra(
84 TestNotificationService.EXTRA_ERROR_REASON);
85 }
86 mCountDownLatch.countDown();
87 }
88 }
89 };
90
91 private CountDownLatch mCountDownLatch;
92
93 private boolean mOperationExecuted;
94
95 private String mErrorReason;
96
Jun Ono6b69cbb2017-12-08 19:07:55 +090097 private DocumentsProviderHelper mStorageDocsHelper;
98
Jun Ono6b69cbb2017-12-08 19:07:55 +090099 private RootInfo mPrimaryRoot;
100
101 private RootInfo mSdCardRoot;
102
103 private String mSdCardLabel;
104
105 private boolean mIsVirtualSdCard;
106
107 private int mPreTestStayAwakeValue;
108
Jun Onoa46c3d22017-11-22 12:07:49 +0900109 public FileCopyUiTest() {
110 super(FilesActivity.class);
111 }
112
113 @Override
114 public void setUp() throws Exception {
115 super.setUp();
Jun Ono8cf0f002018-01-18 12:37:09 +0900116
Stephen Hughes496b6ad2019-10-04 12:23:26 +0800117 mFoldersToCleanup.clear();
118
Jun Ono6b69cbb2017-12-08 19:07:55 +0900119 // Create ContentProviderClient and DocumentsProviderHelper for using SD Card.
Takamasa Kuramitsu3bdd3f52018-06-05 12:21:07 +0900120 ContentProviderClient storageClient =
121 mResolver.acquireUnstableContentProviderClient(AUTHORITY_STORAGE);
122 mStorageDocsHelper = new DocumentsProviderHelper(AUTHORITY_STORAGE, storageClient);
Jun Ono6b69cbb2017-12-08 19:07:55 +0900123
Jun Ono8cf0f002018-01-18 12:37:09 +0900124 // Set a flag to prevent many refreshes.
125 Bundle bundle = new Bundle();
126 bundle.putBoolean(StubProvider.EXTRA_ENABLE_ROOT_NOTIFICATION, false);
127 mDocsHelper.configure(null, bundle);
128
Jun Ono6b69cbb2017-12-08 19:07:55 +0900129 // Set "Stay awake" until test is finished.
130 mPreTestStayAwakeValue = Settings.Global.getInt(context.getContentResolver(),
131 Settings.Global.STAY_ON_WHILE_PLUGGED_IN);
Takamasa Kuramitsu3bdd3f52018-06-05 12:21:07 +0900132 device.executeShellCommand("settings put global stay_on_while_plugged_in 3");
Jun Ono6b69cbb2017-12-08 19:07:55 +0900133
134 // If Internal Storage is not shown, turn on.
135 State state = ((FilesActivity) getActivity()).getDisplayState();
136 if (!state.showAdvanced) {
Takamasa Kuramitsu3bdd3f52018-06-05 12:21:07 +0900137 bots.main.clickToolbarOverflowItem(
138 context.getResources().getString(R.string.menu_advanced_show));
Jun Ono6b69cbb2017-12-08 19:07:55 +0900139 }
140
141 try {
Takamasa Kuramitsu3bdd3f52018-06-05 12:21:07 +0900142 bots.notifications.setNotificationAccess(getActivity(), true);
Jun Ono6b69cbb2017-12-08 19:07:55 +0900143 } catch (Exception e) {
144 Log.d(TAG, "Cannot set notification access. ", e);
145 }
Jun Onoa46c3d22017-11-22 12:07:49 +0900146
Jun Onoa46c3d22017-11-22 12:07:49 +0900147 mOperationExecuted = false;
148 mErrorReason = "No response from Notification";
Jun Ono6b69cbb2017-12-08 19:07:55 +0900149
150 initStorageRootInfo();
151 assertNotNull("Internal Storage not found", mPrimaryRoot);
152
153 // If SD Card is not found, enable Virtual SD Card
154 if (mSdCardRoot == null) {
155 mIsVirtualSdCard = enableVirtualSdCard();
156 assertTrue("Cannot set virtual SD Card", mIsVirtualSdCard);
157 // Call initStorageRootInfo() again for setting SD Card root
158 initStorageRootInfo();
159 }
Ivan Chiang49f44122019-10-18 15:48:43 +0800160
161 IntentFilter filter = new IntentFilter();
162 filter.addAction(TestNotificationService.ACTION_OPERATION_RESULT);
163 context.registerReceiver(mReceiver, filter);
164 context.sendBroadcast(new Intent(
165 TestNotificationService.ACTION_CHANGE_EXECUTION_MODE));
Jun Onoa46c3d22017-11-22 12:07:49 +0900166 }
167
168 @Override
169 public void tearDown() throws Exception {
Jun Ono6b69cbb2017-12-08 19:07:55 +0900170 // Delete created files
171 deleteDocuments(Build.MODEL);
172 deleteDocuments(mSdCardLabel);
173
Stephen Hughes496b6ad2019-10-04 12:23:26 +0800174 for (RootAndFolderPair rootAndFolder : mFoldersToCleanup) {
175 deleteDocuments(rootAndFolder.root, rootAndFolder.folder);
176 }
177
Jun Ono6b69cbb2017-12-08 19:07:55 +0900178 if (mIsVirtualSdCard) {
Takamasa Kuramitsu3bdd3f52018-06-05 12:21:07 +0900179 device.executeShellCommand("sm set-virtual-disk false");
Jun Ono6b69cbb2017-12-08 19:07:55 +0900180 }
181
Takamasa Kuramitsu3bdd3f52018-06-05 12:21:07 +0900182 device.executeShellCommand("settings put global stay_on_while_plugged_in "
Jun Ono6b69cbb2017-12-08 19:07:55 +0900183 + mPreTestStayAwakeValue);
Jun Onoa46c3d22017-11-22 12:07:49 +0900184
185 context.unregisterReceiver(mReceiver);
186 try {
Takamasa Kuramitsu3bdd3f52018-06-05 12:21:07 +0900187 bots.notifications.setNotificationAccess(getActivity(), false);
Jun Onoa46c3d22017-11-22 12:07:49 +0900188 } catch (Exception e) {
Jun Ono6b69cbb2017-12-08 19:07:55 +0900189 Log.d(TAG, "Cannot set notification access. ", e);
Jun Onoa46c3d22017-11-22 12:07:49 +0900190 }
Jun Ono6b69cbb2017-12-08 19:07:55 +0900191
Jun Onoa46c3d22017-11-22 12:07:49 +0900192 super.tearDown();
193 }
194
Jun Ono6b69cbb2017-12-08 19:07:55 +0900195 private boolean createDocuments(String label, RootInfo root,
196 DocumentsProviderHelper helper) throws Exception {
197 if (TextUtils.isEmpty(label) || root == null) {
198 return false;
Jun Onoa46c3d22017-11-22 12:07:49 +0900199 }
Jun Onoa46c3d22017-11-22 12:07:49 +0900200
Jun Ono6b69cbb2017-12-08 19:07:55 +0900201 // If Test folder is already created, delete it
202 if (bots.directory.hasDocuments(TARGET_FOLDER)) {
203 deleteDocuments(label);
Jun Onoa46c3d22017-11-22 12:07:49 +0900204 }
Jun Onoa46c3d22017-11-22 12:07:49 +0900205
Jun Ono6b69cbb2017-12-08 19:07:55 +0900206 // Create folder and create file in its folder
207 bots.roots.openRoot(label);
208 Uri uri = helper.createFolder(root, TARGET_FOLDER);
Jun Onoa46c3d22017-11-22 12:07:49 +0900209 device.waitForIdle();
Jun Ono6b69cbb2017-12-08 19:07:55 +0900210 if (!bots.directory.hasDocuments(TARGET_FOLDER)) {
211 return false;
Jun Onoa46c3d22017-11-22 12:07:49 +0900212 }
Jun Ono6b69cbb2017-12-08 19:07:55 +0900213
214 loadImages(uri, helper);
215
216 // Check that image files are loaded completely
217 DocumentInfo parent = helper.findDocument(root.documentId, TARGET_FOLDER);
218 List<DocumentInfo> children = helper.listChildren(parent.documentId, TARGET_COUNT);
219 for (DocumentInfo docInfo : children) {
220 mTargetFileList.put(docInfo.displayName, docInfo.size);
221 }
222 assertTrue("Lack of loading file. File count = " + mTargetFileList.size(),
223 mTargetFileList.size() == TARGET_COUNT);
224
225 return true;
Jun Onoa46c3d22017-11-22 12:07:49 +0900226 }
227
Stephen Hughes496b6ad2019-10-04 12:23:26 +0800228 private boolean deleteDocuments(String label, String targetFolder) throws Exception {
Jun Ono6b69cbb2017-12-08 19:07:55 +0900229 if (TextUtils.isEmpty(label)) {
230 return false;
231 }
232
233 bots.roots.openRoot(label);
Stephen Hughes496b6ad2019-10-04 12:23:26 +0800234 if (!bots.directory.hasDocuments(targetFolder)) {
Jun Ono6b69cbb2017-12-08 19:07:55 +0900235 return true;
236 }
237
Stephen Hughes496b6ad2019-10-04 12:23:26 +0800238 bots.directory.selectDocument(targetFolder, 1);
Jun Onoa46c3d22017-11-22 12:07:49 +0900239 device.waitForIdle();
240
Jun Ono6b69cbb2017-12-08 19:07:55 +0900241 bots.main.clickToolbarItem(R.id.action_menu_delete);
Jun Onoa46c3d22017-11-22 12:07:49 +0900242 bots.main.clickDialogOkButton();
243 device.waitForIdle();
244
Stephen Hughes496b6ad2019-10-04 12:23:26 +0800245 bots.directory.findDocument(targetFolder).waitUntilGone(WAIT_TIME_SECONDS);
246 return !bots.directory.hasDocuments(targetFolder);
247 }
248
249 private boolean deleteDocuments(String label) throws Exception {
250 return deleteDocuments(label, TARGET_FOLDER);
Jun Ono6b69cbb2017-12-08 19:07:55 +0900251 }
252
253 private void loadImages(Uri root, DocumentsProviderHelper helper) throws Exception {
254 Context testContext = getInstrumentation().getContext();
255 Resources res = testContext.getResources();
256 try {
257 int resId = res.getIdentifier(
258 "uitest_images", "raw", testContext.getPackageName());
259 loadImageFromResources(root, helper, resId, res);
260 } catch (Exception e) {
261 Log.d(TAG, "Error occurs when loading image. ", e);
262 }
263 }
264
265 private void loadImageFromResources(Uri root, DocumentsProviderHelper helper, int resId,
266 Resources res) throws Exception {
felkachangc7fbae22018-11-21 14:13:53 +0800267 ZipInputStream in = null;
Jun Ono6b69cbb2017-12-08 19:07:55 +0900268 int read = 0;
Takamasa Kuramitsu3bdd3f52018-06-05 12:21:07 +0900269 int count = 0;
Jun Ono6b69cbb2017-12-08 19:07:55 +0900270 try {
felkachangc7fbae22018-11-21 14:13:53 +0800271 in = new ZipInputStream(res.openRawResource(resId));
272 ZipEntry archiveEntry = null;
felkachang1556c362018-08-30 16:21:59 +0800273 while ((archiveEntry = in.getNextEntry()) != null && (count++ < TARGET_COUNT)) {
274 String fileName = archiveEntry.getName();
Jun Ono6b69cbb2017-12-08 19:07:55 +0900275 Uri uri = helper.createDocument(root, "image/png", fileName);
276 byte[] buff = new byte[1024];
277 while ((read = in.read(buff)) > 0) {
278 helper.writeAppendDocument(uri, buff);
279 }
Jun Ono6b69cbb2017-12-08 19:07:55 +0900280 buff = null;
281 }
282 } finally {
283 if (in != null) {
284 try {
285 in.close();
286 in = null;
287 } catch (Exception e) {
288 Log.d(TAG, "Error occurs when close ZipInputStream. ", e);
289 }
290 }
291 }
292 }
293
294 /** @return true if virtual SD Card setting is completed. Othrewise false */
295 private boolean enableVirtualSdCard() throws Exception {
Takamasa Kuramitsu3bdd3f52018-06-05 12:21:07 +0900296 boolean result = false;
Jun Ono6b69cbb2017-12-08 19:07:55 +0900297 try {
Takamasa Kuramitsu3bdd3f52018-06-05 12:21:07 +0900298 device.executeShellCommand("sm set-virtual-disk true");
299 String diskId = getAdoptionDisk();
300 assertNotNull("Failed to setup virtual disk.", diskId);
301 device.executeShellCommand(String.format("sm partition %s public", diskId));
302 result = waitForPublicVolume();
Jun Ono6b69cbb2017-12-08 19:07:55 +0900303 } catch (Exception e) {
Takamasa Kuramitsu3bdd3f52018-06-05 12:21:07 +0900304 result = false;
305 }
306 return result;
307 }
308
309 private String getAdoptionDisk() throws Exception {
310 int attempt = 0;
311 String disks = device.executeShellCommand("sm list-disks adoptable");
312 while ((disks == null || disks.isEmpty()) && attempt++ < 15) {
313 SystemClock.sleep(1000);
314 disks = device.executeShellCommand("sm list-disks adoptable");
315 }
316
317 if (disks == null || disks.isEmpty()) {
318 return null;
319 }
320 return disks.split("\n")[0].trim();
321 }
322
323 private boolean waitForPublicVolume() throws Exception {
324 int attempt = 0;
325 String volumes = device.executeShellCommand("sm list-volumes public");
326 while ((volumes == null || volumes.isEmpty() || !volumes.contains("mounted"))
327 && attempt++ < 15) {
328 SystemClock.sleep(1000);
329 volumes = device.executeShellCommand("sm list-volumes public");
330 }
331
332 if (volumes == null || volumes.isEmpty()) {
Jun Ono6b69cbb2017-12-08 19:07:55 +0900333 return false;
334 }
335 return true;
336 }
337
Jun Ono6b69cbb2017-12-08 19:07:55 +0900338 private void initStorageRootInfo() throws RemoteException {
339 List<RootInfo> rootList = mStorageDocsHelper.getRootList();
340 for (RootInfo info : rootList) {
341 if (ROOT_ID_DEVICE.equals(info.rootId)) {
342 mPrimaryRoot = info;
343 } else if (info.isSd()) {
344 mSdCardRoot = info;
345 mSdCardLabel = info.title;
346 }
347 }
348 }
349
350 private void copyFiles(String sourceRoot, String targetRoot) throws Exception {
351 mCountDownLatch = new CountDownLatch(1);
352 // Copy folder and child files
353 bots.roots.openRoot(sourceRoot);
354 bots.directory.selectDocument(TARGET_FOLDER, 1);
355 device.waitForIdle();
Takamasa Kuramitsu3bdd3f52018-06-05 12:21:07 +0900356 bots.main.clickToolbarOverflowItem(context.getResources().getString(R.string.menu_copy));
Jun Ono6b69cbb2017-12-08 19:07:55 +0900357 device.waitForIdle();
358 bots.roots.openRoot(targetRoot);
359 bots.main.clickDialogOkButton();
360 device.waitForIdle();
361
362 // Wait until copy operation finished
363 try {
364 mCountDownLatch.await(WAIT_TIME_SECONDS, TimeUnit.SECONDS);
Jun Onoa46c3d22017-11-22 12:07:49 +0900365 } catch (Exception e) {
366 fail("Cannot wait because of error." + e.toString());
367 }
368
369 assertTrue(mErrorReason, mOperationExecuted);
Jun Ono6b69cbb2017-12-08 19:07:55 +0900370 }
Jun Onoa46c3d22017-11-22 12:07:49 +0900371
Jun Ono6b69cbb2017-12-08 19:07:55 +0900372 private void assertFilesCopied(String rootLabel, RootInfo rootInfo,
373 DocumentsProviderHelper helper) throws Exception {
374 // Check that copied folder exists
375 bots.roots.openRoot(rootLabel);
Jun Onoa46c3d22017-11-22 12:07:49 +0900376 device.waitForIdle();
Jun Ono6b69cbb2017-12-08 19:07:55 +0900377 bots.directory.assertDocumentsPresent(TARGET_FOLDER);
Jun Onoa46c3d22017-11-22 12:07:49 +0900378
Jun Ono6b69cbb2017-12-08 19:07:55 +0900379 // Check that copied files exist
380 DocumentInfo parent = helper.findDocument(rootInfo.documentId, TARGET_FOLDER);
381 List<DocumentInfo> children = helper.listChildren(parent.documentId, TARGET_COUNT);
382 for (DocumentInfo info : children) {
383 Long size = mTargetFileList.get(info.displayName);
384 assertNotNull("Cannot find file.", size);
385 assertTrue("Copied file contents differ.", info.size == size);
Jun Onoa46c3d22017-11-22 12:07:49 +0900386 }
Jun Ono6b69cbb2017-12-08 19:07:55 +0900387 }
Jun Onoa46c3d22017-11-22 12:07:49 +0900388
Jun Ono6b69cbb2017-12-08 19:07:55 +0900389 // Copy Internal Storage -> Internal Storage //
Felka Changc181d522019-02-21 14:36:08 +0800390 @HugeLongTest
Jun Ono6b69cbb2017-12-08 19:07:55 +0900391 public void testCopyDocuments_InternalStorage() throws Exception {
392 createDocuments(StubProvider.ROOT_0_ID, rootDir0, mDocsHelper);
393 copyFiles(StubProvider.ROOT_0_ID, StubProvider.ROOT_1_ID);
394
395 // Check that original folder exists
396 bots.roots.openRoot(StubProvider.ROOT_0_ID);
397 bots.directory.assertDocumentsPresent(TARGET_FOLDER);
398
399 // Check that copied files exist
400 assertFilesCopied(StubProvider.ROOT_1_ID, rootDir1, mDocsHelper);
401 }
402
403 // Copy SD Card -> Internal Storage //
Felka Changc181d522019-02-21 14:36:08 +0800404 @HugeLongTest
Jun Ono6b69cbb2017-12-08 19:07:55 +0900405 public void testCopyDocuments_FromSdCard() throws Exception {
406 createDocuments(mSdCardLabel, mSdCardRoot, mStorageDocsHelper);
407 copyFiles(mSdCardLabel, Build.MODEL);
408
409 // Check that original folder exists
410 bots.roots.openRoot(mSdCardLabel);
411 bots.directory.assertDocumentsPresent(TARGET_FOLDER);
412
413 // Check that copied files exist
414 assertFilesCopied(Build.MODEL, mPrimaryRoot, mStorageDocsHelper);
415 }
416
417 // Copy Internal Storage -> SD Card //
Felka Changc181d522019-02-21 14:36:08 +0800418 @HugeLongTest
Jun Ono6b69cbb2017-12-08 19:07:55 +0900419 public void testCopyDocuments_ToSdCard() throws Exception {
420 createDocuments(Build.MODEL, mPrimaryRoot, mStorageDocsHelper);
421 copyFiles(Build.MODEL, mSdCardLabel);
422
423 // Check that original folder exists
424 bots.roots.openRoot(Build.MODEL);
425 bots.directory.assertDocumentsPresent(TARGET_FOLDER);
426
427 // Check that copied files exist
428 assertFilesCopied(mSdCardLabel, mSdCardRoot, mStorageDocsHelper);
Jun Onoa46c3d22017-11-22 12:07:49 +0900429 }
Tony Huang9c3c60b2018-11-09 17:45:38 +0800430
Felka Changc181d522019-02-21 14:36:08 +0800431 @HugeLongTest
Tony Huang9c3c60b2018-11-09 17:45:38 +0800432 public void testCopyDocuments_documentsDisabled() throws Exception {
433 mDocsHelper.createDocument(rootDir0, "text/plain", fileName1);
434 bots.roots.openRoot(StubProvider.ROOT_0_ID);
435 bots.directory.selectDocument(fileName1, 1);
436 device.waitForIdle();
437 bots.main.clickToolbarOverflowItem(context.getResources().getString(R.string.menu_copy));
438 device.waitForIdle();
439 bots.roots.openRoot(StubProvider.ROOT_0_ID);
440 device.waitForIdle();
441
442 assertFalse(bots.directory.findDocument(fileName1).isEnabled());
443 }
Stephen Hughes496b6ad2019-10-04 12:23:26 +0800444
445 @HugeLongTest
446 public void testRecursiveCopyDocuments_InternalStorageToDownloadsProvider() throws Exception {
447 // Create Download folder if it doesn't exist.
448 DocumentInfo info = mStorageDocsHelper.findFile(mPrimaryRoot.documentId, "Download");
449
450 if (info == null) {
451 ContentResolver cr = context.getContentResolver();
452 Uri uri = mStorageDocsHelper.createFolder(mPrimaryRoot.documentId, "Download");
453 info = DocumentInfo.fromUri(cr, uri);
454 }
455
456 assertTrue(info != null && info.isDirectory());
457
458 // Setup folder /storage/emulated/0/Download/UUID
459 String randomFolder = UUID.randomUUID().toString();
460 assertNull(mStorageDocsHelper.findFile(info.documentId, randomFolder));
461
462 Uri subFolderUri = mStorageDocsHelper.createFolder(info.documentId, randomFolder);
463 assertNotNull(subFolderUri);
464 mFoldersToCleanup.add(new RootAndFolderPair("Downloads", randomFolder));
465
466 // Load images into /storage/emulated/0/Download/UUID
467 loadImages(subFolderUri, mStorageDocsHelper);
468
469 mCountDownLatch = new CountDownLatch(1);
470
471 // Open Internal Storage Root.
472 bots.roots.openRoot(Build.MODEL);
473 device.waitForIdle();
474
475 // Select Download folder.
476 bots.directory.selectDocument("Download");
477 device.waitForIdle();
478
479 // Click copy button.
480 bots.main.clickToolbarOverflowItem(context.getResources().getString(R.string.menu_copy));
481 device.waitForIdle();
482
483 // Downloads folder is automatically opened, so just open the folder defined
484 // by the UUID.
485 bots.directory.openDocument(randomFolder);
486 device.waitForIdle();
487
488 // Initiate the copy operation.
489 bots.main.clickDialogOkButton();
490 device.waitForIdle();
491
492 try {
493 mCountDownLatch.await(WAIT_TIME_SECONDS, TimeUnit.SECONDS);
494 } catch (Exception e) {
495 fail("Cannot wait because of error." + e.toString());
496 }
497
498 assertFalse(mOperationExecuted);
499 }
500
501 /** Holds a pair of a root and folder. */
502 private static final class RootAndFolderPair {
503
504 private final String root;
505 private final String folder;
506
507 RootAndFolderPair(String root, String folder) {
508 this.root = root;
509 this.folder = folder;
510 }
511 }
Jun Onoa46c3d22017-11-22 12:07:49 +0900512}