1 /*
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 
17 package com.android.documentsui;
18 
19 import static android.content.Context.RECEIVER_EXPORTED;
20 
21 import static com.android.documentsui.StubProvider.EXTRA_SIZE;
22 import static com.android.documentsui.StubProvider.ROOT_0_ID;
23 import static com.android.documentsui.StubProvider.ROOT_1_ID;
24 
25 import android.content.BroadcastReceiver;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.IntentFilter;
29 import android.net.Uri;
30 import android.os.Bundle;
31 import android.os.RemoteException;
32 import android.util.Log;
33 
34 import androidx.test.filters.LargeTest;
35 
36 import com.android.documentsui.files.FilesActivity;
37 import com.android.documentsui.filters.HugeLongTest;
38 import com.android.documentsui.services.TestNotificationService;
39 
40 import java.util.concurrent.CountDownLatch;
41 import java.util.concurrent.TimeUnit;
42 
43 /**
44 * This class tests the below points.
45 * - Cancel copying or moving file before starting it.
46 * - Cancel during copying or moving file.
47 */
48 @LargeTest
49 public class CancelFromNotificationUiTest extends ActivityTest<FilesActivity> {
50     private static final String TAG = "CancelFromNotificationUiTest";
51 
52     private static final String TARGET_FILE = "stub.data";
53 
54     private static final int BUFFER_SIZE = 10 * 1024 * 1024;
55 
56     private static final int WAIT_TIME_SECONDS = 120;
57 
58     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
59         @Override
60         public void onReceive(Context context, Intent intent) {
61             String action = intent.getAction();
62             if (TestNotificationService.ACTION_OPERATION_RESULT.equals(action)) {
63                 mOperationExecuted = intent.getBooleanExtra(
64                         TestNotificationService.EXTRA_RESULT, false);
65                 if (!mOperationExecuted) {
66                     mErrorReason = intent.getStringExtra(
67                             TestNotificationService.EXTRA_ERROR_REASON);
68                 }
69                 mCountDownLatch.countDown();
70             }
71         }
72     };
73 
74     private CountDownLatch mCountDownLatch;
75 
76     private boolean mOperationExecuted;
77 
78     private String mErrorReason;
79 
CancelFromNotificationUiTest()80     public CancelFromNotificationUiTest() {
81         super(FilesActivity.class);
82     }
83 
84     @Override
setUp()85     public void setUp() throws Exception {
86         super.setUp();
87 
88         // super.setUp() method will change the storage size to 100MB.
89         // So, reset the storage size again to 500MB.
90         Bundle bundle = new Bundle();
91         bundle.putLong(EXTRA_SIZE, 500L);
92         // Set a flag to prevent many refreshes.
93         bundle.putBoolean(StubProvider.EXTRA_ENABLE_ROOT_NOTIFICATION, false);
94         mDocsHelper.configure(null, bundle);
95 
96         try {
97             bots.notifications.setNotificationAccess(getActivity(), true);
98         } catch (Exception e) {
99             Log.d(TAG, "Cannot set notification access. ", e);
100         }
101 
102         initTestFiles();
103 
104         IntentFilter filter = new IntentFilter();
105         filter.addAction(TestNotificationService.ACTION_OPERATION_RESULT);
106         context.registerReceiver(mReceiver, filter, RECEIVER_EXPORTED);
107         context.sendBroadcast(new Intent(
108                 TestNotificationService.ACTION_CHANGE_CANCEL_MODE));
109 
110         mOperationExecuted = false;
111         mErrorReason = "No response from Notification";
112         mCountDownLatch = new CountDownLatch(1);
113     }
114 
115     @Override
tearDown()116     public void tearDown() throws Exception {
117         mCountDownLatch.countDown();
118         mCountDownLatch = null;
119 
120         context.unregisterReceiver(mReceiver);
121         try {
122             bots.notifications.setNotificationAccess(getActivity(), false);
123         } catch (Exception e) {
124             Log.d(TAG, "Cannot set notification access. ", e);
125         }
126         super.tearDown();
127     }
128 
129     @Override
initTestFiles()130     public void initTestFiles() throws RemoteException {
131         try {
132             createStubFile();
133         } catch (Exception e) {
134             fail("Initialization failed. " + e.toString());
135         }
136     }
137 
createStubFile()138     private void createStubFile() throws Exception {
139         Uri uri = mDocsHelper.createDocument(rootDir0, "*/*", TARGET_FILE);
140         byte[] stubByte = new byte[BUFFER_SIZE];
141         mDocsHelper.writeDocument(uri, stubByte);
142         for (int i = 0; i < 49; i++) {
143             stubByte = null;
144             stubByte = new byte[BUFFER_SIZE];
145             mDocsHelper.writeAppendDocument(uri, stubByte, stubByte.length);
146         }
147     }
148 
149     @HugeLongTest
testCopyDocument_Cancel()150     public void testCopyDocument_Cancel() throws Exception {
151         bots.roots.openRoot(ROOT_0_ID);
152 
153         bots.directory.findDocument(TARGET_FILE);
154         device.waitForIdle();
155 
156         bots.directory.selectDocument(TARGET_FILE, 1);
157         device.waitForIdle();
158 
159         bots.main.clickToolbarOverflowItem(context.getResources().getString(R.string.menu_copy));
160         device.waitForIdle();
161 
162         bots.main.clickDialogCancelButton();
163         device.waitForIdle();
164 
165         bots.directory.waitForDocument(TARGET_FILE);
166     }
167 
168     @HugeLongTest
testCopyDocument_CancelFromNotification()169     public void testCopyDocument_CancelFromNotification() throws Exception {
170         bots.roots.openRoot(ROOT_0_ID);
171         bots.directory.findDocument(TARGET_FILE);
172         device.waitForIdle();
173 
174         bots.directory.selectDocument(TARGET_FILE, 1);
175         device.waitForIdle();
176 
177         bots.main.clickToolbarOverflowItem(context.getResources().getString(R.string.menu_copy));
178         device.waitForIdle();
179 
180         bots.roots.openRoot(ROOT_1_ID);
181         bots.main.clickDialogOkButton();
182         device.waitForIdle();
183 
184         try {
185             mCountDownLatch.await(WAIT_TIME_SECONDS, TimeUnit.SECONDS);
186         } catch (Exception e) {
187             fail("Cannot wait because of error." + e.toString());
188         }
189 
190         assertTrue(mErrorReason, mOperationExecuted);
191 
192         bots.roots.openRoot(ROOT_1_ID);
193         device.waitForIdle();
194         assertFalse(bots.directory.hasDocuments(TARGET_FILE));
195 
196         bots.roots.openRoot(ROOT_0_ID);
197         device.waitForIdle();
198         assertTrue(bots.directory.hasDocuments(TARGET_FILE));
199     }
200 
201     @HugeLongTest
testMoveDocument_Cancel()202     public void testMoveDocument_Cancel() throws Exception {
203         bots.roots.openRoot(ROOT_0_ID);
204 
205         bots.directory.findDocument(TARGET_FILE);
206         device.waitForIdle();
207 
208         bots.directory.selectDocument(TARGET_FILE, 1);
209         device.waitForIdle();
210 
211         bots.main.clickToolbarOverflowItem(context.getResources().getString(R.string.menu_move));
212         device.waitForIdle();
213 
214         bots.main.clickDialogCancelButton();
215         device.waitForIdle();
216 
217         bots.directory.waitForDocument(TARGET_FILE);
218     }
219 
220     @HugeLongTest
221     // (TODO: b/156756197) : Deflake tests
222     // Notice because this class inherits JUnit3 TestCase, the right way to suppress a test
223     // is by removing "test" from prefix, instead of adding @Ignore.
ignored_testMoveDocument_CancelFromNotification()224     public void ignored_testMoveDocument_CancelFromNotification() throws Exception {
225         bots.roots.openRoot(ROOT_0_ID);
226         bots.directory.findDocument(TARGET_FILE);
227         device.waitForIdle();
228 
229         bots.directory.selectDocument(TARGET_FILE, 1);
230         device.waitForIdle();
231 
232         bots.main.clickToolbarOverflowItem(context.getResources().getString(R.string.menu_move));
233         device.waitForIdle();
234 
235         bots.roots.openRoot(ROOT_1_ID);
236         bots.main.clickDialogOkButton();
237         device.waitForIdle();
238 
239         try {
240             mCountDownLatch.await(WAIT_TIME_SECONDS, TimeUnit.SECONDS);
241         } catch (Exception e) {
242             fail("Cannot wait because of error." + e.toString());
243         }
244 
245         assertTrue(mErrorReason, mOperationExecuted);
246 
247         bots.roots.openRoot(ROOT_1_ID);
248         device.waitForIdle();
249         assertFalse(bots.directory.hasDocuments(TARGET_FILE));
250 
251         bots.roots.openRoot(ROOT_0_ID);
252         device.waitForIdle();
253         assertTrue(bots.directory.hasDocuments(TARGET_FILE));
254     }
255 }
256