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