• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 android.scopedstorage.cts.host;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import android.platform.test.annotations.AppModeFull;
22 
23 import com.android.tradefed.device.contentprovider.ContentProviderHandler;
24 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
25 
26 import org.junit.After;
27 import org.junit.Before;
28 import org.junit.Test;
29 import org.junit.runner.RunWith;
30 
31 /**
32  * Runs the legacy file path access tests.
33  */
34 @RunWith(DeviceJUnit4ClassRunner.class)
35 @AppModeFull
36 public class LegacyStorageHostTest extends BaseHostTestCase {
37 
38     private boolean mIsExternalStorageSetup;
39 
40     private ContentProviderHandler mContentProviderHandler;
41 
42     /**
43      * Runs the given phase of LegacyFileAccessTest by calling into the device.
44      * Throws an exception if the test phase fails.
45      */
runDeviceTest(String phase)46     void runDeviceTest(String phase) throws Exception {
47         assertThat(runDeviceTests("android.scopedstorage.cts.legacy",
48                 "android.scopedstorage.cts.legacy.LegacyStorageTest", phase)).isTrue();
49     }
50 
51     /**
52      * <p> Keep in mind that granting WRITE_EXTERNAL_STORAGE also grants READ_EXTERNAL_STORAGE,
53      * so in order to test a case where the reader has only WRITE, we must explicitly revoke READ.
54      */
grantPermissions(String... perms)55     private void grantPermissions(String... perms) throws Exception {
56         int currentUserId = getCurrentUserId();
57         for (String perm : perms) {
58             executeShellCommand("pm grant --user %d android.scopedstorage.cts.legacy %s",
59                     currentUserId, perm);
60         }
61     }
62 
revokePermissions(String... perms)63     private void revokePermissions(String... perms) throws Exception {
64         int currentUserId = getCurrentUserId();
65         for (String perm : perms) {
66             executeShellCommand("pm revoke --user %d android.scopedstorage.cts.legacy %s",
67                     currentUserId, perm);
68         }
69     }
70 
71     /**
72      * Creates a file {@code filePath} in shell and may bypass Media Provider restrictions for
73      * creating file.
74      */
createFileAsShell(String filePath)75     private void createFileAsShell(String filePath) throws Exception {
76         executeShellCommand("touch %s", filePath);
77         assertThat(getDevice().doesFileExist(filePath)).isTrue();
78     }
79 
setupExternalStorage()80     private void setupExternalStorage() throws Exception {
81         if (!mIsExternalStorageSetup) {
82             runDeviceTest("setupExternalStorage");
83             mIsExternalStorageSetup = true;
84         }
85     }
86 
87     @Before
setup()88     public void setup() throws Exception {
89         mContentProviderHandler = new ContentProviderHandler(getDevice());
90         mContentProviderHandler.setUp();
91         setupExternalStorage();
92         // Granting WRITE automatically grants READ as well, so we grant them both explicitly by
93         // default in order to avoid confusion. Test cases that don't want any of those permissions
94         // have to revoke the unwanted permissions.
95         grantPermissions("android.permission.WRITE_EXTERNAL_STORAGE",
96                 "android.permission.READ_EXTERNAL_STORAGE");
97     }
98 
99     @After
tearDown()100     public void tearDown() throws Exception {
101         mContentProviderHandler.tearDown();
102         revokePermissions("android.permission.WRITE_EXTERNAL_STORAGE",
103                 "android.permission.READ_EXTERNAL_STORAGE");
104     }
105 
106     @Test
testCreateFilesInRandomPlaces_hasW()107     public void testCreateFilesInRandomPlaces_hasW() throws Exception {
108         revokePermissions("android.permission.READ_EXTERNAL_STORAGE");
109         executeShellCommand("mkdir -p /sdcard/Android/data/com.android.shell -m 2770");
110         runDeviceTest("testCreateFilesInRandomPlaces_hasW");
111     }
112 
113     @Test
testCantInsertFilesInOtherAppPrivateDir_hasRW()114     public void testCantInsertFilesInOtherAppPrivateDir_hasRW() throws Exception {
115         runDeviceTest("testCantInsertFilesInOtherAppPrivateDir_hasRW");
116     }
117 
118     @Test
testCantUpdateFilesInOtherAppPrivateDir_hasRW()119     public void testCantUpdateFilesInOtherAppPrivateDir_hasRW() throws Exception {
120         runDeviceTest("testCantUpdateFilesInOtherAppPrivateDir_hasRW");
121     }
122 
123     @Test
testCantInsertFilesInOtherAppPrivateDir_hasMES()124     public void testCantInsertFilesInOtherAppPrivateDir_hasMES() throws Exception {
125         allowAppOps("android:manage_external_storage");
126         try {
127             runDeviceTest("testCantInsertFilesInOtherAppPrivateDir_hasMES");
128         } finally {
129             denyAppOps("android:manage_external_storage");
130         }
131     }
132 
133     @Test
testCantUpdateFilesInOtherAppPrivateDir_hasMES()134     public void testCantUpdateFilesInOtherAppPrivateDir_hasMES() throws Exception {
135         allowAppOps("android:manage_external_storage");
136         try {
137             runDeviceTest("testCantUpdateFilesInOtherAppPrivateDir_hasMES");
138         } finally {
139             denyAppOps("android:manage_external_storage");
140         }
141     }
142 
143     @Test
testCantInsertFilesInOtherAppPrivateDir_hasSystemGallery()144     public void testCantInsertFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
145         runDeviceTest("testCantInsertFilesInOtherAppPrivateDir_hasSystemGallery");
146     }
147 
148     @Test
testCantUpdateFilesInOtherAppPrivateDir_hasSystemGallery()149     public void testCantUpdateFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
150         runDeviceTest("testCantUpdateFilesInOtherAppPrivateDir_hasSystemGallery");
151     }
152 
153     @Test
testMkdirInRandomPlaces_hasW()154     public void testMkdirInRandomPlaces_hasW() throws Exception {
155         revokePermissions("android.permission.READ_EXTERNAL_STORAGE");
156         executeShellCommand("mkdir -p /sdcard/Android/data/com.android.shell -m 2770");
157         runDeviceTest("testMkdirInRandomPlaces_hasW");
158     }
159 
160     @Test
testReadOnlyExternalStorage_hasR()161     public void testReadOnlyExternalStorage_hasR() throws Exception {
162         revokePermissions("android.permission.WRITE_EXTERNAL_STORAGE");
163         runDeviceTest("testReadOnlyExternalStorage_hasR");
164     }
165 
166     @Test
testCantAccessExternalStorage()167     public void testCantAccessExternalStorage() throws Exception {
168         revokePermissions("android.permission.WRITE_EXTERNAL_STORAGE",
169                 "android.permission.READ_EXTERNAL_STORAGE");
170         runDeviceTest("testCantAccessExternalStorage");
171     }
172 
173     @Test
testListFiles_hasR()174     public void testListFiles_hasR() throws Exception {
175         revokePermissions("android.permission.WRITE_EXTERNAL_STORAGE");
176         runDeviceTest("testListFiles_hasR");
177     }
178 
179     @Test
testInsertHiddenFile()180     public void testInsertHiddenFile() throws Exception {
181         runDeviceTest("testInsertHiddenFile");
182     }
183 
184     @Test
testCanRename_hasRW()185     public void testCanRename_hasRW() throws Exception {
186         runDeviceTest("testCanRename_hasRW");
187     }
188 
189     @Test
testCanTrashOtherAndroidMediaFiles_hasRW()190     public void testCanTrashOtherAndroidMediaFiles_hasRW() throws Exception {
191         runDeviceTest("testCanTrashOtherAndroidMediaFiles_hasRW");
192     }
193 
194     @Test
testCantRename_hasR()195     public void testCantRename_hasR() throws Exception {
196         revokePermissions("android.permission.WRITE_EXTERNAL_STORAGE");
197         runDeviceTest("testCantRename_hasR");
198     }
199 
200     @Test
testCantRename_noStoragePermission()201     public void testCantRename_noStoragePermission() throws Exception {
202         revokePermissions("android.permission.WRITE_EXTERNAL_STORAGE",
203                 "android.permission.READ_EXTERNAL_STORAGE");
204         runDeviceTest("testCantRename_noStoragePermission");
205     }
206 
207     @Test
testRenameDirectoryAndUpdateDB_hasW()208     public void testRenameDirectoryAndUpdateDB_hasW() throws Exception {
209         runDeviceTest("testRenameDirectoryAndUpdateDB_hasW");
210     }
211 
212     @Test
testCanDeleteAllFiles_hasRW()213     public void testCanDeleteAllFiles_hasRW() throws Exception {
214         runDeviceTest("testCanDeleteAllFiles_hasRW");
215     }
216 
217     @Test
testLegacyAppCanOwnAFile_hasW()218     public void testLegacyAppCanOwnAFile_hasW() throws Exception {
219         runDeviceTest("testLegacyAppCanOwnAFile_hasW");
220     }
221 
222     @Test
testCreateAndRenameDoesntLeaveStaleDBRow_hasRW()223     public void testCreateAndRenameDoesntLeaveStaleDBRow_hasRW() throws Exception {
224         runDeviceTest("testCreateAndRenameDoesntLeaveStaleDBRow_hasRW");
225     }
226 
227     @Test
testRenameDoesntInvalidateUri_hasRW()228     public void testRenameDoesntInvalidateUri_hasRW() throws Exception {
229         runDeviceTest("testRenameDoesntInvalidateUri_hasRW");
230     }
231 
232     @Test
testCanRenameAFileWithNoDBRow_hasRW()233     public void testCanRenameAFileWithNoDBRow_hasRW() throws Exception {
234         runDeviceTest("testCanRenameAFileWithNoDBRow_hasRW");
235     }
236 
237     @Test
testCreateDoesntUpsert()238     public void testCreateDoesntUpsert() throws Exception {
239         runDeviceTest("testCreateDoesntUpsert");
240     }
241 
242     @Test
testCaseInsensitivity()243     public void testCaseInsensitivity() throws Exception {
244         runDeviceTest("testAndroidDataObbCannotBeDeleted");
245     }
246 
247     @Test
testLegacyAppUpdatingOwnershipOfExistingEntry()248     public void testLegacyAppUpdatingOwnershipOfExistingEntry() throws Exception {
249         runDeviceTest("testLegacyAppUpdatingOwnershipOfExistingEntry");
250     }
251 
252     @Test
testInsertWithUnsupportedMimeType()253     public void testInsertWithUnsupportedMimeType() throws Exception {
254         runDeviceTest("testInsertWithUnsupportedMimeType");
255     }
256 
257     @Test
testLegacySystemGalleryCanRenameImagesAndVideosWithoutDbUpdates()258     public void testLegacySystemGalleryCanRenameImagesAndVideosWithoutDbUpdates() throws Exception {
259         runDeviceTest("testLegacySystemGalleryCanRenameImagesAndVideosWithoutDbUpdates");
260     }
261 
262     /**
263      * (b/205673506): Test that legacy System Gallery can update() media file's releative_path to a
264      * non default top level directory.
265      */
266     @Test
testLegacySystemGalleryCanUpdateToExistingDirectory()267     public void testLegacySystemGalleryCanUpdateToExistingDirectory() throws Exception {
268         runDeviceTest("testLegacySystemGalleryCanUpdateToExistingDirectory");
269     }
270 
271     @Test
testLegacySystemGalleryWithoutWESCannotRename()272     public void testLegacySystemGalleryWithoutWESCannotRename() throws Exception {
273         revokePermissions("android.permission.WRITE_EXTERNAL_STORAGE");
274         runDeviceTest("testLegacySystemGalleryWithoutWESCannotRename");
275     }
276 
277     @Test
testLegacyWESCanRenameImagesAndVideosWithDbUpdates_hasW()278     public void testLegacyWESCanRenameImagesAndVideosWithDbUpdates_hasW() throws Exception {
279         runDeviceTest("testLegacyWESCanRenameImagesAndVideosWithDbUpdates_hasW");
280     }
281 
282     @Test
testScanUpdatesMetadataForNewlyAddedFile_hasRW()283     public void testScanUpdatesMetadataForNewlyAddedFile_hasRW() throws Exception {
284         runDeviceTest("testScanUpdatesMetadataForNewlyAddedFile_hasRW");
285     }
286 
287     @Test
testInsertFromExternalDirsViaData()288     public void testInsertFromExternalDirsViaData() throws Exception {
289         runDeviceTest("testInsertFromExternalDirsViaData");
290     }
291 
292     @Test
testUpdateToExternalDirsViaData()293     public void testUpdateToExternalDirsViaData() throws Exception {
294         runDeviceTest("testUpdateToExternalDirsViaData");
295     }
296 
297     @Test
testInsertFromExternalDirsViaRelativePath()298     public void testInsertFromExternalDirsViaRelativePath() throws Exception {
299         runDeviceTest("testInsertFromExternalDirsViaRelativePath");
300     }
301 
302     @Test
testUpdateToExternalDirsViaRelativePath()303     public void testUpdateToExternalDirsViaRelativePath() throws Exception {
304         runDeviceTest("testUpdateToExternalDirsViaRelativePath");
305     }
306 
allowAppOps(String... ops)307     private void allowAppOps(String... ops) throws Exception {
308         for (String op : ops) {
309             executeShellCommand("cmd appops set --uid android.scopedstorage.cts.legacy "
310                     + op + " allow");
311         }
312     }
313 
denyAppOps(String... ops)314     private void denyAppOps(String... ops) throws Exception {
315         for (String op : ops) {
316             executeShellCommand("cmd appops set --uid android.scopedstorage.cts.legacy "
317                     + op + " deny");
318         }
319     }
320 }
321