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.server.pm;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.mockito.Matchers.eq;
21 import static org.mockito.Matchers.isNull;
22 import static org.mockito.Mockito.verify;
23 import static org.mockito.Mockito.when;
24 
25 import android.content.Context;
26 import android.content.pm.UserInfo;
27 import android.os.FileUtils;
28 import android.os.storage.StorageManager;
29 import android.os.storage.VolumeInfo;
30 import android.platform.test.annotations.Presubmit;
31 
32 import androidx.test.InstrumentationRegistry;
33 import androidx.test.filters.SmallTest;
34 import androidx.test.runner.AndroidJUnit4;
35 
36 import org.junit.Before;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 import org.mockito.Mock;
40 import org.mockito.MockitoAnnotations;
41 
42 import java.io.File;
43 import java.io.FileOutputStream;
44 import java.io.IOException;
45 import java.nio.charset.Charset;
46 import java.util.Arrays;
47 import java.util.Collections;
48 
49 /**
50  * <p>Run with:<pre>
51  * m FrameworksServicesTests &&
52  * adb install \
53  * -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
54  * adb shell am instrument -e class com.android.server.pm.UserDataPreparerTest \
55  * -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
56  * </pre>
57  */
58 @RunWith(AndroidJUnit4.class)
59 @Presubmit
60 @SmallTest
61 public class UserDataPreparerTest {
62 
63     private static final int TEST_USER_SERIAL = 1000;
64     private static final int TEST_USER_ID = 10;
65 
66     private TestUserDataPreparer mUserDataPreparer;
67 
68     @Mock
69     private StorageManager mStorageManagerMock;
70 
71     @Mock
72     private Context mContextMock;
73 
74     @Mock
75     private Installer mInstaller;
76 
77     private Object mInstallLock;
78 
79     @Before
setup()80     public void setup() {
81         Context ctx = InstrumentationRegistry.getContext();
82         FileUtils.deleteContents(ctx.getCacheDir());
83         mInstallLock = new Object();
84         MockitoAnnotations.initMocks(this);
85         mUserDataPreparer = new TestUserDataPreparer(mInstaller, mInstallLock, mContextMock, false,
86                 ctx.getCacheDir());
87         when(mContextMock.getSystemServiceName(StorageManager.class))
88                 .thenReturn(Context.STORAGE_SERVICE);
89         when(mContextMock.getSystemService(eq(Context.STORAGE_SERVICE)))
90                 .thenReturn(mStorageManagerMock);
91         VolumeInfo testVolume = new VolumeInfo("testuuid", VolumeInfo.TYPE_PRIVATE, null, null);
92         when(mStorageManagerMock.getWritablePrivateVolumes()).thenReturn(Arrays.asList(testVolume));
93     }
94 
95     @Test
testPrepareUserData_De()96     public void testPrepareUserData_De() throws Exception {
97         File userDeDir = mUserDataPreparer.getDataUserDeDirectory(null, TEST_USER_ID);
98         userDeDir.mkdirs();
99         File systemDeDir = mUserDataPreparer.getDataSystemDeDirectory(TEST_USER_ID);
100         systemDeDir.mkdirs();
101         mUserDataPreparer
102                 .prepareUserData(TEST_USER_ID, TEST_USER_SERIAL, StorageManager.FLAG_STORAGE_DE);
103         verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID),
104                 eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_DE));
105         verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID),
106                 eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_DE));
107         int serialNumber = UserDataPreparer.getSerialNumber(userDeDir);
108         assertEquals(TEST_USER_SERIAL, serialNumber);
109         serialNumber = UserDataPreparer.getSerialNumber(systemDeDir);
110         assertEquals(TEST_USER_SERIAL, serialNumber);
111     }
112 
113     @Test
testPrepareUserData_Ce()114     public void testPrepareUserData_Ce() throws Exception {
115         File userCeDir = mUserDataPreparer.getDataUserCeDirectory(null, TEST_USER_ID);
116         userCeDir.mkdirs();
117         File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID);
118         systemCeDir.mkdirs();
119         mUserDataPreparer
120                 .prepareUserData(TEST_USER_ID, TEST_USER_SERIAL, StorageManager.FLAG_STORAGE_CE);
121         verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID),
122                 eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_CE));
123         verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID),
124                 eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_CE));
125         int serialNumber = UserDataPreparer.getSerialNumber(userCeDir);
126         assertEquals(TEST_USER_SERIAL, serialNumber);
127         serialNumber = UserDataPreparer.getSerialNumber(systemCeDir);
128         assertEquals(TEST_USER_SERIAL, serialNumber);
129     }
130 
131     @Test
testDestroyUserData()132     public void testDestroyUserData() throws Exception {
133         // Add file in CE
134         File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID);
135         systemCeDir.mkdirs();
136         File ceFile = new File(systemCeDir, "file");
137         writeFile(ceFile, "-----" );
138         testDestroyUserData_De();
139         // CE directory should be preserved
140         assertEquals(Collections.singletonList(ceFile), Arrays.asList(FileUtils.listFilesOrEmpty(
141                 systemCeDir)));
142 
143         testDestroyUserData_Ce();
144 
145         // Verify that testDir is empty
146         assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
147                 mUserDataPreparer.testDir)));
148     }
149 
150     @Test
testDestroyUserData_De()151     public void testDestroyUserData_De() throws Exception {
152         File systemDir = mUserDataPreparer.getUserSystemDirectory(TEST_USER_ID);
153         systemDir.mkdirs();
154         writeFile(new File(systemDir, "file"), "-----" );
155         File systemDeDir = mUserDataPreparer.getDataSystemDeDirectory(TEST_USER_ID);
156         systemDeDir.mkdirs();
157         writeFile(new File(systemDeDir, "file"), "-----" );
158 
159         mUserDataPreparer.destroyUserData(TEST_USER_ID, StorageManager.FLAG_STORAGE_DE);
160 
161         verify(mInstaller).destroyUserData(isNull(String.class), eq(TEST_USER_ID),
162                         eq(StorageManager.FLAG_STORAGE_DE));
163         verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID),
164                         eq(StorageManager.FLAG_STORAGE_DE));
165 
166         assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(systemDir)));
167         assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
168                 systemDeDir)));
169     }
170 
171     @Test
testDestroyUserData_Ce()172     public void testDestroyUserData_Ce() throws Exception {
173         File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID);
174         systemCeDir.mkdirs();
175         writeFile(new File(systemCeDir, "file"), "-----" );
176 
177         mUserDataPreparer.destroyUserData(TEST_USER_ID, StorageManager.FLAG_STORAGE_CE);
178 
179         verify(mInstaller).destroyUserData(isNull(String.class), eq(TEST_USER_ID),
180                 eq(StorageManager.FLAG_STORAGE_CE));
181         verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID),
182                 eq(StorageManager.FLAG_STORAGE_CE));
183 
184         assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
185                 systemCeDir)));
186     }
187 
188     @Test
testReconcileUsers()189     public void testReconcileUsers() throws Exception {
190         UserInfo u1 = new UserInfo(1, "u1", 0);
191         UserInfo u2 = new UserInfo(2, "u2", 0);
192         File testDir = mUserDataPreparer.testDir;
193         File dir1 = new File(testDir, "1");
194         dir1.mkdirs();
195         File dir2 = new File(testDir, "2");
196         dir2.mkdirs();
197         File dir3 = new File(testDir, "3");
198         dir3.mkdirs();
199 
200         mUserDataPreparer
201                 .reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL, Arrays.asList(u1, u2),
202                         Arrays.asList(dir1, dir2, dir3));
203         // Verify that user 3 data is removed
204         verify(mInstaller).destroyUserData(isNull(String.class), eq(3),
205                 eq(StorageManager.FLAG_STORAGE_DE|StorageManager.FLAG_STORAGE_CE));
206     }
207 
writeFile(File file, String content)208     private static void writeFile(File file, String content) throws IOException {
209         try (FileOutputStream os = new FileOutputStream(file)) {
210             os.write(content.getBytes(Charset.defaultCharset()));
211         }
212     }
213 
214     private static class TestUserDataPreparer extends UserDataPreparer {
215         File testDir;
216 
TestUserDataPreparer(Installer installer, Object installLock, Context context, boolean onlyCore, File testDir)217         TestUserDataPreparer(Installer installer, Object installLock, Context context,
218                 boolean onlyCore, File testDir) {
219             super(installer, installLock, context, onlyCore);
220             this.testDir = testDir;
221         }
222 
223         @Override
getDataMiscCeDirectory(int userId)224         protected File getDataMiscCeDirectory(int userId) {
225             return new File(testDir, "misc_ce_" + userId);
226         }
227 
228         @Override
getDataSystemCeDirectory(int userId)229         protected File getDataSystemCeDirectory(int userId) {
230             return new File(testDir, "system_ce_" + userId);
231         }
232 
233         @Override
getDataMiscDeDirectory(int userId)234         protected File getDataMiscDeDirectory(int userId) {
235             return new File(testDir, "misc_de_" + userId);
236         }
237 
238         @Override
getUserSystemDirectory(int userId)239         protected File getUserSystemDirectory(int userId) {
240             return new File(testDir, "user_system_" + userId);
241         }
242 
243         @Override
getDataUserCeDirectory(String volumeUuid, int userId)244         protected File getDataUserCeDirectory(String volumeUuid, int userId) {
245             return new File(testDir, "user_ce_" + userId);
246         }
247 
248         @Override
getDataSystemDeDirectory(int userId)249         protected File getDataSystemDeDirectory(int userId) {
250             return new File(testDir, "system_de_" + userId);
251         }
252 
253         @Override
getDataUserDeDirectory(String volumeUuid, int userId)254         protected File getDataUserDeDirectory(String volumeUuid, int userId) {
255             return new File(testDir, "user_de_" + userId);
256         }
257 
258         @Override
isFileEncryptedEmulatedOnly()259         protected boolean isFileEncryptedEmulatedOnly() {
260             return false;
261         }
262     }
263 
264 }
265