1 /*
2  * Copyright (C) 2012 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.multiuserstorageapp;
18 
19 import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirNoAccess;
20 import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getAllPackageSpecificPathsExceptObb;
21 import static com.android.cts.externalstorageapp.CommonExternalStorageTest.readInt;
22 import static com.android.cts.externalstorageapp.CommonExternalStorageTest.writeInt;
23 
24 import android.os.Environment;
25 import android.test.AndroidTestCase;
26 import android.util.Log;
27 
28 import java.io.File;
29 
30 /**
31  * Test multi-user emulated storage environment, ensuring that each user has
32  * isolated storage minus shared OBB directory.
33  */
34 public class MultiUserStorageTest extends AndroidTestCase {
35     private static final String TAG = "MultiUserStorageTest";
36 
37     private static final String FILE_PREFIX = "MUST_";
38 
39     private final String FILE_SINGLETON = FILE_PREFIX + "singleton";
40     private final String FILE_OBB_SINGLETON = FILE_PREFIX + "obb_singleton";
41     private final String FILE_OBB_API_SINGLETON = FILE_PREFIX + "obb_api_singleton";
42     private final String FILE_MY_UID = FILE_PREFIX + android.os.Process.myUid();
43 
44     private static final int OBB_API_VALUE = 0xcafe;
45     private static final int OBB_VALUE = 0xf00d;
46 
wipeTestFiles(File dir)47     private void wipeTestFiles(File dir) {
48         dir.mkdirs();
49         final File[] files = dir.listFiles();
50         if (files == null) return;
51         for (File file : files) {
52             if (file.getName().startsWith(FILE_PREFIX)) {
53                 Log.d(TAG, "Wiping " + file);
54                 file.delete();
55             }
56         }
57     }
58 
testCleanIsolatedStorage()59     public void testCleanIsolatedStorage() throws Exception {
60         wipeTestFiles(Environment.getExternalStorageDirectory());
61     }
62 
testWriteIsolatedStorage()63     public void testWriteIsolatedStorage() throws Exception {
64         final int uid = android.os.Process.myUid();
65 
66         writeInt(buildApiPath(FILE_SINGLETON), uid);
67         writeInt(buildApiPath(FILE_MY_UID), uid);
68 
69         // Write to every external path we think we have access to
70         for (File path : getAllPackageSpecificPathsExceptObb(getContext())) {
71             assertNotNull("Valid media must be inserted during CTS", path);
72             assertEquals("Valid media must be inserted during CTS", Environment.MEDIA_MOUNTED,
73                     Environment.getExternalStorageState(path));
74 
75             writeInt(new File(path, FILE_SINGLETON), uid);
76         }
77     }
78 
testReadIsolatedStorage()79     public void testReadIsolatedStorage() throws Exception {
80         final int uid = android.os.Process.myUid();
81 
82         // Expect that the value we wrote earlier is still valid and wasn't
83         // overwritten by us running as another user.
84         assertEquals("Failed to read singleton file from API path", uid,
85                 readInt(buildApiPath(FILE_SINGLETON)));
86         assertEquals("Failed to read singleton file from env path", uid,
87                 readInt(buildEnvPath(FILE_SINGLETON)));
88         assertEquals("Failed to read singleton file from raw path", uid,
89                 readInt(buildRawPath(FILE_SINGLETON)));
90 
91         assertEquals("Failed to read UID file from API path", uid,
92                 readInt(buildApiPath(FILE_MY_UID)));
93 
94         for (File path : getAllPackageSpecificPathsExceptObb(getContext())) {
95             assertNotNull("Valid media must be inserted during CTS", path);
96             assertEquals("Valid media must be inserted during CTS", Environment.MEDIA_MOUNTED,
97                     Environment.getExternalStorageState(path));
98 
99             assertEquals("Unexpected value in singleton file at " + path, uid,
100                     readInt(new File(path, FILE_SINGLETON)));
101         }
102     }
103 
testCleanObbStorage()104     public void testCleanObbStorage() throws Exception {
105         wipeTestFiles(getContext().getObbDir());
106     }
107 
testWriteObbStorage()108     public void testWriteObbStorage() throws Exception {
109         writeInt(buildApiObbPath(FILE_OBB_API_SINGLETON), OBB_API_VALUE);
110         writeInt(buildEnvObbPath(FILE_OBB_SINGLETON), OBB_VALUE);
111     }
112 
testReadObbStorage()113     public void testReadObbStorage() throws Exception {
114         assertEquals("Failed to read OBB file from API path", OBB_API_VALUE,
115                 readInt(buildApiObbPath(FILE_OBB_API_SINGLETON)));
116 
117         assertEquals("Failed to read OBB file from env path", OBB_VALUE,
118                 readInt(buildEnvObbPath(FILE_OBB_SINGLETON)));
119         assertEquals("Failed to read OBB file from raw path", OBB_VALUE,
120                 readInt(buildRawObbPath(FILE_OBB_SINGLETON)));
121     }
122 
123     /**
124      * Verify that we can't poke at storage of other users.
125      */
testUserIsolation()126     public void testUserIsolation() throws Exception {
127         final File myPath = Environment.getExternalStorageDirectory();
128         final int myId = android.os.Process.myUid() / 100000;
129         assertEquals(String.valueOf(myId), myPath.getName());
130 
131         Log.d(TAG, "My path is " + myPath);
132         final File basePath = myPath.getParentFile();
133         for (int i = 0; i < 128; i++) {
134             if (i == myId) continue;
135 
136             final File otherPath = new File(basePath, String.valueOf(i));
137             assertDirNoAccess(otherPath);
138         }
139     }
140 
buildApiObbPath(String file)141     private File buildApiObbPath(String file) {
142         return new File(getContext().getObbDir(), file);
143     }
144 
buildEnvObbPath(String file)145     private File buildEnvObbPath(String file) {
146         return new File(new File(System.getenv("EXTERNAL_STORAGE"), "Android/obb"), file);
147     }
148 
buildRawObbPath(String file)149     private File buildRawObbPath(String file) {
150         return new File("/sdcard/Android/obb/", file);
151     }
152 
buildApiPath(String file)153     private static File buildApiPath(String file) {
154         return new File(Environment.getExternalStorageDirectory(), file);
155     }
156 
buildEnvPath(String file)157     private static File buildEnvPath(String file) {
158         return new File(System.getenv("EXTERNAL_STORAGE"), file);
159     }
160 
buildRawPath(String file)161     private static File buildRawPath(String file) {
162         return new File("/sdcard/", file);
163     }
164 }
165