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