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.functional.externalstoragetests;
18 
19 import android.app.UiAutomation;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.provider.Settings;
23 import android.support.test.uiautomator.By;
24 import android.support.test.uiautomator.UiDevice;
25 import android.support.test.uiautomator.UiObject2;
26 import android.support.test.uiautomator.Until;
27 import android.test.InstrumentationTestCase;
28 import android.test.suitebuilder.annotation.LargeTest;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31 import junit.framework.Assert;
32 
33 public class PortableStorageTests extends InstrumentationTestCase {
34     private UiDevice mDevice = null;
35     private Context mContext = null;
36     private UiAutomation mUiAutomation = null;
37     private ExternalStorageHelper storageHelper;
38 
39     @Override
setUp()40     protected void setUp() throws Exception {
41         super.setUp();
42         mDevice = UiDevice.getInstance(getInstrumentation());
43         mContext = getInstrumentation().getContext();
44         mUiAutomation = getInstrumentation().getUiAutomation();
45         storageHelper = ExternalStorageHelper.getInstance(mDevice, mContext, mUiAutomation,
46                 getInstrumentation());
47         mDevice.setOrientationNatural();
48     }
49 
50     /**
51      * Test to ensure sd card can be adopted as portable storage
52      */
53     @LargeTest
testAdoptAsPortableViaUI()54     public void testAdoptAsPortableViaUI() throws InterruptedException {
55         // ensure notification
56         storageHelper.executeShellCommand(String.format(
57                 "sm partition %s %s", storageHelper.getAdoptionDisk(), "public"));
58         Thread.sleep(storageHelper.TIMEOUT);
59         storageHelper.setupAsPortableUiFlow();
60         storageHelper.executeShellCommand(String.format("sm forget all"));
61         Thread.sleep(storageHelper.TIMEOUT);
62     }
63 
64     /**
65      * tests to ensure copy option is visible for items on portable storage
66      */
67     @LargeTest
testCopyFromPortable()68     public void testCopyFromPortable() throws InterruptedException {
69         ensureHasPortable();
70         storageHelper.createFiles(2,
71                 String.format("/storage/%s", storageHelper.getAdoptionVolumeUuid("public")));
72         storageHelper.openSDCard();
73         mDevice.wait(Until.findObject(By.res("android:id/title").text("Test_0")),
74                 storageHelper.TIMEOUT).click(storageHelper.TIMEOUT);
75         mDevice.wait(Until.findObject(By.desc(Pattern.compile("More options",
76                 Pattern.CASE_INSENSITIVE))), storageHelper.TIMEOUT).click();
77         assertNotNull(mDevice.wait(Until.findObject(By.res("android:id/title").text("Copy to…")),
78                 2 * storageHelper.TIMEOUT));
79         mDevice.wait(Until.findObject(By.res("android:id/title").text("Copy to…")),
80                 storageHelper.TIMEOUT).clickAndWait(Until.newWindow(), storageHelper.TIMEOUT);
81         mDevice.pressBack();
82     }
83 
84     /**
85      * tests to ensure that resources on portable storage can be deleted via UI
86      */
87     @LargeTest
testDeleteFromPortable()88     public void testDeleteFromPortable() throws InterruptedException {
89         ensureHasPortable();
90         storageHelper.createFiles(2,
91                 String.format("/storage/%s", storageHelper.getAdoptionVolumeUuid("public")));
92         storageHelper.openSDCard();
93         mDevice.wait(Until.findObject(By.res("android:id/title").text("Test_0")),
94                 storageHelper.TIMEOUT).click(storageHelper.TIMEOUT);
95         mDevice.wait(Until.findObject(By.res("com.android.documentsui:id/menu_sort")),
96                 storageHelper.TIMEOUT).clickAndWait(Until.newWindow(), storageHelper.TIMEOUT);
97         assertNull(mDevice.wait(Until.findObject(By.res("android:id/title").text("Test_0")),
98                 2 * storageHelper.TIMEOUT));
99     }
100 
101     /**
102      * tests to ensure that external storage is explorable via UI
103      */
104     @LargeTest
testExplorePortable()105     public void testExplorePortable() throws InterruptedException {
106         ensureHasPortable();
107         // Create 2 random files on SDCard
108         storageHelper.createFiles(2,
109                 String.format("/storage/%s", storageHelper.getAdoptionVolumeUuid("public")));
110         Intent intent = new Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS);
111         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
112         mContext.startActivity(intent);
113         Thread.sleep(storageHelper.TIMEOUT * 2);
114         mDevice.wait(Until.findObject(By.textContains("SD card")), storageHelper.TIMEOUT)
115                 .clickAndWait(Until.newWindow(), storageHelper.TIMEOUT);
116         for (int i = 0; i < 2; ++i) {
117             Assert.assertTrue(mDevice.wait(Until.hasObject(By.res("android:id/title")
118                     .text(String.format("Test_%d", i))), storageHelper.TIMEOUT));
119         }
120     }
121 
122     /**
123      * tests to ensure that resources on portable storage can be shared via UI
124      */
125     @LargeTest
testShareableFromPortable()126     public void testShareableFromPortable() throws InterruptedException {
127         ensureHasPortable();
128         storageHelper.createFiles(2,
129                 String.format("/storage/%s", storageHelper.getAdoptionVolumeUuid("public")));
130         storageHelper.openSDCard();
131         mDevice.wait(Until.findObject(By.res("android:id/title").text("Test_0")),
132                 storageHelper.TIMEOUT).click(storageHelper.TIMEOUT);
133         mDevice.wait(Until.findObject(By.res("com.android.documentsui:id/menu_list")),
134                 storageHelper.TIMEOUT).click();
135         assertNotNull(mDevice.wait(Until.findObject(By.res("android:id/resolver_list")),
136                 storageHelper.TIMEOUT));
137         // click and ensure intent is sent to share? or actual share?
138         mDevice.pressBack();
139     }
140 
141     /**
142      * tests to ensure that portable overflow menu contain all setting options
143      */
144     @LargeTest
testPortableOverflowSettings()145     public void testPortableOverflowSettings() throws InterruptedException {
146         ensureHasPortable();
147         storageHelper.createFiles(2,
148                 String.format("/storage/%s", storageHelper.getAdoptionVolumeUuid("public")));
149         storageHelper.openSDCard();
150         mDevice.wait(Until.findObject(By.res("android:id/title").text("Test_0")),
151                 storageHelper.TIMEOUT).click(storageHelper.TIMEOUT);
152         assertTrue(mDevice.wait(Until.hasObject(By.res(storageHelper.DOCUMENTS_PKG, "menu_search")),
153                 storageHelper.TIMEOUT));
154         assertTrue(mDevice.wait(Until.hasObject(By.res(storageHelper.DOCUMENTS_PKG, "menu_sort")),
155                 storageHelper.TIMEOUT));
156         assertTrue(mDevice.wait(Until.hasObject(By.text("1 selected")), storageHelper.TIMEOUT));
157     }
158 
159     /**
160      * tests to ensure that portable storage has setting options format, format as internal, eject
161      */
162     @LargeTest
testPortableSettings()163     public void testPortableSettings() throws InterruptedException {
164         ensureHasPortable();
165         storageHelper.openSDCard();
166         Pattern pattern = Pattern.compile("More options", Pattern.CASE_INSENSITIVE);
167         mDevice.wait(Until.findObject(By.desc(pattern)), storageHelper.TIMEOUT).click();
168         pattern = Pattern.compile("Storage settings", Pattern.CASE_INSENSITIVE);
169         mDevice.wait(Until.findObject(By.text(pattern)), storageHelper.TIMEOUT)
170                 .clickAndWait(
171                         Until.newWindow(), storageHelper.TIMEOUT);
172         pattern = Pattern.compile("Eject", Pattern.CASE_INSENSITIVE);
173         assertTrue(mDevice.wait(Until.hasObject(By.text(pattern)), storageHelper.TIMEOUT));
174         pattern = Pattern.compile("Format", Pattern.CASE_INSENSITIVE);
175         assertTrue(mDevice.wait(Until.hasObject(By.text(pattern)), storageHelper.TIMEOUT));
176         pattern = Pattern.compile("Format as internal", Pattern.CASE_INSENSITIVE);
177         assertTrue(mDevice.wait(Until.hasObject(By.text(pattern)),
178                 storageHelper.TIMEOUT));
179     }
180 
181     /**
182      * tests to ensure that portable storage can be ejected from settings
183      */
184     @LargeTest
testEjectPortable()185     public void testEjectPortable() throws InterruptedException {
186         ensureHasPortable();
187         storageHelper.openStorageSettings();
188         mDevice.wait(Until.findObject(By.res(storageHelper.SETTINGS_PKG, "unmount")),
189                 storageHelper.TIMEOUT).click();
190         assertTrue(mDevice.wait(Until.hasObject(By.res("android:id/summary").text("Ejected")),
191                 4 * storageHelper.TIMEOUT));
192         mDevice.wait(Until.findObject(By.textContains("SD card")), 2 * storageHelper.TIMEOUT)
193                 .click();
194         Pattern pattern = Pattern.compile("Mount", Pattern.CASE_INSENSITIVE);
195         mDevice.wait(Until.findObject(By.res("android:id/button1").text(pattern)),
196                 2 * storageHelper.TIMEOUT).clickAndWait(Until.newWindow(), storageHelper.TIMEOUT);
197         ;
198     }
199 
200     /**
201      * tests to ensure that portable storage can be erased and formated from settings
202      */
203     @LargeTest
testFormatPortable()204     public void testFormatPortable() throws InterruptedException {
205         ensureHasPortable();
206         storageHelper.openSDCard();
207         Pattern pattern = Pattern.compile("More options", Pattern.CASE_INSENSITIVE);
208         mDevice.wait(Until.findObject(By.desc(pattern)), storageHelper.TIMEOUT).click();
209         pattern = Pattern.compile("Storage settings", Pattern.CASE_INSENSITIVE);
210         mDevice.wait(Until.findObject(By.text(pattern)), storageHelper.TIMEOUT)
211                 .clickAndWait(
212                         Until.newWindow(), storageHelper.TIMEOUT);
213         UiObject2 format = mDevice.wait(Until.findObject(By.text("Format")), storageHelper.TIMEOUT);
214         format.clickAndWait(Until.newWindow(), storageHelper.TIMEOUT);
215         pattern = Pattern.compile("Erase & Format", Pattern.CASE_INSENSITIVE);
216         mDevice.wait(Until.findObject(By.text(pattern)), storageHelper.TIMEOUT).click();
217         pattern = Pattern.compile("Done", Pattern.CASE_INSENSITIVE);
218         mDevice.wait(Until.findObject(By.text(pattern)), 20 * storageHelper.TIMEOUT).click();
219     }
220 
221     /**
222      * tests to ensure that portable storage can be erased and formated as internal from settings
223      */
224     @LargeTest
testFormatPortableAsAdoptable()225     public void testFormatPortableAsAdoptable() throws InterruptedException {
226         try {
227             ensureHasPortable();
228             storageHelper.openSDCard();
229             Pattern pattern = Pattern.compile("More options", Pattern.CASE_INSENSITIVE);
230             mDevice.wait(Until.findObject(By.desc(pattern)), storageHelper.TIMEOUT).click();
231             pattern = Pattern.compile("Storage settings", Pattern.CASE_INSENSITIVE);
232             mDevice.wait(Until.findObject(By.text(pattern)), storageHelper.TIMEOUT)
233                     .clickAndWait(
234                             Until.newWindow(), storageHelper.TIMEOUT);
235             pattern = Pattern.compile("Format", Pattern.CASE_INSENSITIVE);
236             assertTrue(mDevice.wait(Until.hasObject(By.text(pattern)), storageHelper.TIMEOUT));
237             pattern = Pattern.compile("Format as internal", Pattern.CASE_INSENSITIVE);
238             assertTrue(mDevice.wait(Until.hasObject(By.text(pattern)),
239                     storageHelper.TIMEOUT));
240             // Next flow is same as adoption, so no need to test
241         } finally {
242             storageHelper.partitionDisk("public");
243         }
244     }
245 
ensureHasPortable()246     private void ensureHasPortable() throws InterruptedException {
247         storageHelper.partitionDisk("public");
248         storageHelper.settingsUiCleanUp();
249     }
250 
251     @Override
tearDown()252     protected void tearDown() throws Exception {
253         mDevice.unfreezeRotation();
254         mDevice.pressBack();
255         mDevice.pressHome();
256         super.tearDown();
257     }
258 }
259