1 package org.robolectric.shadows; 2 3 import static com.google.common.truth.Truth.assertThat; 4 import static org.junit.Assert.assertThrows; 5 import static org.robolectric.Shadows.shadowOf; 6 7 import android.app.usage.StorageStats; 8 import android.app.usage.StorageStatsManager; 9 import android.content.Context; 10 import android.content.pm.PackageManager; 11 import android.os.Build; 12 import android.os.Parcel; 13 import android.os.Process; 14 import android.os.UserHandle; 15 import android.os.storage.StorageManager; 16 import androidx.test.core.app.ApplicationProvider; 17 import androidx.test.ext.junit.runners.AndroidJUnit4; 18 import java.io.IOException; 19 import java.util.UUID; 20 import org.junit.Before; 21 import org.junit.Test; 22 import org.junit.runner.RunWith; 23 import org.robolectric.annotation.Config; 24 25 /** Tests for {@link ShadowStorageStatsManager}. */ 26 @RunWith(AndroidJUnit4.class) 27 @Config(minSdk = Build.VERSION_CODES.O) 28 public final class ShadowStorageStatsManagerTest { 29 30 private StorageStatsManager storageStatsManager; 31 32 @Before setUp()33 public void setUp() { 34 storageStatsManager = 35 (StorageStatsManager) 36 ApplicationProvider.getApplicationContext() 37 .getSystemService(Context.STORAGE_STATS_SERVICE); 38 } 39 40 @Test getFreeBytes_defaultUuid_shouldReturnDefaultValue()41 public void getFreeBytes_defaultUuid_shouldReturnDefaultValue() throws Exception { 42 // Act 43 long defaultFreeBytes = shadowOf(storageStatsManager).getFreeBytes(StorageManager.UUID_DEFAULT); 44 45 // Assert 46 assertThat(defaultFreeBytes).isEqualTo(ShadowStorageStatsManager.DEFAULT_STORAGE_FREE_BYTES); 47 } 48 49 @Test getFreeBytes_unregisteredUuid_throwsException()50 public void getFreeBytes_unregisteredUuid_throwsException() { 51 // Arrange 52 UUID newUuid = UUID.randomUUID(); 53 54 // Act & Assert 55 assertThrows(IOException.class, () -> shadowOf(storageStatsManager).getFreeBytes(newUuid)); 56 } 57 58 @Test getFreeBytes_registeredNewUuid_returnSetupValue()59 public void getFreeBytes_registeredNewUuid_returnSetupValue() throws Exception { 60 // Arrange 61 UUID newUuid = UUID.randomUUID(); 62 long expectedFreeBytes = 16 * 1024L; 63 long expectedTotalBytes = 32 * 1024L; 64 shadowOf(storageStatsManager) 65 .setStorageDeviceFreeAndTotalBytes(newUuid, expectedFreeBytes, expectedTotalBytes); 66 67 // Act 68 long defaultFreeBytes = shadowOf(storageStatsManager).getFreeBytes(StorageManager.UUID_DEFAULT); 69 long newUuidFreeBytes = shadowOf(storageStatsManager).getFreeBytes(newUuid); 70 71 // Assert 72 assertThat(defaultFreeBytes).isEqualTo(ShadowStorageStatsManager.DEFAULT_STORAGE_FREE_BYTES); 73 assertThat(newUuidFreeBytes).isEqualTo(expectedFreeBytes); 74 } 75 76 @Test getFreeBytes_afterRemoveStorageDevice_throwsException()77 public void getFreeBytes_afterRemoveStorageDevice_throwsException() { 78 // Arange 79 shadowOf(storageStatsManager).removeStorageDevice(StorageManager.UUID_DEFAULT); 80 81 // Act & Assert 82 assertThrows( 83 IOException.class, 84 () -> shadowOf(storageStatsManager).getFreeBytes(StorageManager.UUID_DEFAULT)); 85 } 86 87 @Test getTotalBytes_defaultUuid_shouldReturnDefaultValue()88 public void getTotalBytes_defaultUuid_shouldReturnDefaultValue() throws Exception { 89 // Act 90 long defaultTotalBytes = 91 shadowOf(storageStatsManager).getTotalBytes(StorageManager.UUID_DEFAULT); 92 93 // Assert 94 assertThat(defaultTotalBytes).isEqualTo(ShadowStorageStatsManager.DEFAULT_STORAGE_TOTAL_BYTES); 95 } 96 97 @Test getTotalBytes_unregisteredUuid_throwsException()98 public void getTotalBytes_unregisteredUuid_throwsException() { 99 // Arrange 100 UUID newUuid = UUID.randomUUID(); 101 102 // Act & Assert 103 assertThrows(IOException.class, () -> shadowOf(storageStatsManager).getTotalBytes(newUuid)); 104 } 105 106 @Test getTotalBytes_registeredNewUuid_returnSetupValue()107 public void getTotalBytes_registeredNewUuid_returnSetupValue() throws Exception { 108 // Arrange 109 UUID newUuid = UUID.randomUUID(); 110 long expectedFreeBytes = 16 * 1024L; 111 long expectedTotalBytes = 32 * 1024L; 112 shadowOf(storageStatsManager) 113 .setStorageDeviceFreeAndTotalBytes(newUuid, expectedFreeBytes, expectedTotalBytes); 114 115 // Act 116 long defaultTotalBytes = 117 shadowOf(storageStatsManager).getTotalBytes(StorageManager.UUID_DEFAULT); 118 long newUuidTotalBytes = shadowOf(storageStatsManager).getTotalBytes(newUuid); 119 120 // Assert 121 assertThat(defaultTotalBytes).isEqualTo(ShadowStorageStatsManager.DEFAULT_STORAGE_TOTAL_BYTES); 122 assertThat(newUuidTotalBytes).isEqualTo(expectedTotalBytes); 123 } 124 125 @Test getTotalBytes_afterRemoveStorageDevice_throwsException()126 public void getTotalBytes_afterRemoveStorageDevice_throwsException() { 127 // Arange 128 shadowOf(storageStatsManager).removeStorageDevice(StorageManager.UUID_DEFAULT); 129 130 // Act & Assert 131 assertThrows( 132 IOException.class, 133 () -> shadowOf(storageStatsManager).getTotalBytes(StorageManager.UUID_DEFAULT)); 134 } 135 136 @Test queryPackageWithoutSetup_shouldFail()137 public void queryPackageWithoutSetup_shouldFail() { 138 assertThrows( 139 PackageManager.NameNotFoundException.class, 140 () -> 141 shadowOf(storageStatsManager) 142 .queryStatsForPackage( 143 UUID.randomUUID(), "somePackageName", Process.myUserHandle())); 144 } 145 146 @Test queryUserWithoutSetup_shouldFail()147 public void queryUserWithoutSetup_shouldFail() { 148 assertThrows( 149 PackageManager.NameNotFoundException.class, 150 () -> 151 shadowOf(storageStatsManager) 152 .queryStatsForUser(UUID.randomUUID(), Process.myUserHandle())); 153 } 154 155 @Test queryPackageWithCorrectArguments_shouldReturnSetupValue()156 public void queryPackageWithCorrectArguments_shouldReturnSetupValue() throws Exception { 157 // Arrange 158 StorageStats expected = buildStorageStats(); 159 UUID uuid = UUID.randomUUID(); 160 String packageName = "somePackageName"; 161 UserHandle userHandle = Process.myUserHandle(); 162 shadowOf(storageStatsManager).addStorageStats(uuid, packageName, userHandle, expected); 163 164 // Act 165 StorageStats actual = 166 shadowOf(storageStatsManager).queryStatsForPackage(uuid, packageName, userHandle); 167 168 // Assert 169 assertThat(actual).isEqualTo(expected); 170 } 171 172 @Test queryUserWithCorrectArguments_shouldReturnSetupValue()173 public void queryUserWithCorrectArguments_shouldReturnSetupValue() throws Exception { 174 // Arrange 175 StorageStats expected = buildStorageStats(); 176 UUID uuid = UUID.randomUUID(); 177 String packageName = "somePackageName"; 178 UserHandle userHandle = Process.myUserHandle(); 179 shadowOf(storageStatsManager).addStorageStats(uuid, packageName, userHandle, expected); 180 181 // Act 182 StorageStats actual = shadowOf(storageStatsManager).queryStatsForUser(uuid, userHandle); 183 184 // Assert 185 assertThat(actual).isEqualTo(expected); 186 } 187 188 @Test queryUser_shouldReturnAccumulatedStats()189 public void queryUser_shouldReturnAccumulatedStats() throws Exception { 190 // Arrange 191 StorageStats storageStats = buildStorageStats(); 192 UUID uuid1 = UUID.randomUUID(); 193 UUID uuid2 = UUID.randomUUID(); 194 String packageName1 = "somePackageName1"; 195 String packageName2 = "somePackageName2"; 196 String packageName3 = "somePackageName3"; 197 UserHandle userHandle = Process.myUserHandle(); 198 shadowOf(storageStatsManager).addStorageStats(uuid1, packageName1, userHandle, storageStats); 199 shadowOf(storageStatsManager).addStorageStats(uuid1, packageName2, userHandle, storageStats); 200 shadowOf(storageStatsManager).addStorageStats(uuid1, packageName3, userHandle, storageStats); 201 shadowOf(storageStatsManager).addStorageStats(uuid2, packageName1, userHandle, storageStats); 202 shadowOf(storageStatsManager).addStorageStats(uuid2, packageName2, userHandle, storageStats); 203 204 // Act 205 StorageStats actual1 = shadowOf(storageStatsManager).queryStatsForUser(uuid1, userHandle); 206 StorageStats actual2 = shadowOf(storageStatsManager).queryStatsForUser(uuid2, userHandle); 207 208 // Assert 209 assertThat(actual1.getAppBytes()).isEqualTo(9000L); // 3000 * 3 210 assertThat(actual1.getDataBytes()).isEqualTo(6000L); // 2000 * 3 211 assertThat(actual1.getCacheBytes()).isEqualTo(3000L); // 1000 * 3 212 assertThat(actual2.getAppBytes()).isEqualTo(6000L); // 3000 * 2 213 assertThat(actual2.getDataBytes()).isEqualTo(4000L); // 2000 * 2 214 assertThat(actual2.getCacheBytes()).isEqualTo(2000L); // 1000 * 2 215 } 216 217 @Test queryUser_packageStatsUpdated_shouldUpdateUserStats()218 public void queryUser_packageStatsUpdated_shouldUpdateUserStats() throws Exception { 219 // Arrange 220 UUID uuid = UUID.randomUUID(); 221 String packageName1 = "somePackageName1"; 222 String packageName2 = "somePackageName2"; 223 UserHandle userHandle = Process.myUserHandle(); 224 shadowOf(storageStatsManager) 225 .addStorageStats(uuid, packageName1, userHandle, buildStorageStats()); 226 shadowOf(storageStatsManager) 227 .addStorageStats(uuid, packageName2, userHandle, buildStorageStats()); 228 shadowOf(storageStatsManager) 229 .addStorageStats( 230 uuid, 231 packageName2, 232 userHandle, 233 buildStorageStats( 234 /* codeSize= */ 2000L, /* dataSize= */ 1000L, /* cacheSize= */ 3000L)); 235 236 // Act 237 StorageStats actual = shadowOf(storageStatsManager).queryStatsForUser(uuid, userHandle); 238 239 // Assert 240 assertThat(actual.getAppBytes()).isEqualTo(5000L); // 3000 + 2000 241 assertThat(actual.getDataBytes()).isEqualTo(3000L); // 2000 + 1000 242 assertThat(actual.getCacheBytes()).isEqualTo(4000L); // 1000 + 3000 243 } 244 245 @Test queryUser_packageStatsUpdated_singlePackage_shouldUpdateUserStats()246 public void queryUser_packageStatsUpdated_singlePackage_shouldUpdateUserStats() throws Exception { 247 // Arrange 248 UUID uuid = UUID.randomUUID(); 249 String packageName = "somePackageName1"; 250 UserHandle userHandle = Process.myUserHandle(); 251 shadowOf(storageStatsManager) 252 .addStorageStats(uuid, packageName, userHandle, buildStorageStats()); 253 shadowOf(storageStatsManager) 254 .addStorageStats( 255 uuid, 256 packageName, 257 userHandle, 258 buildStorageStats( 259 /* codeSize= */ 2000L, /* dataSize= */ 1000L, /* cacheSize= */ 3000L)); 260 261 // Act 262 StorageStats actual = shadowOf(storageStatsManager).queryStatsForUser(uuid, userHandle); 263 264 // Assert 265 assertThat(actual.getAppBytes()).isEqualTo(2000L); 266 assertThat(actual.getDataBytes()).isEqualTo(1000L); 267 assertThat(actual.getCacheBytes()).isEqualTo(3000L); 268 } 269 270 @Test queryPackageWithWrongArguments_shouldFail()271 public void queryPackageWithWrongArguments_shouldFail() { 272 // Arrange 273 StorageStats expected = buildStorageStats(); 274 UUID uuid = UUID.randomUUID(); 275 UUID differentUUID = UUID.randomUUID(); 276 String packageName = "somePackageName"; 277 UserHandle userHandle = UserHandle.getUserHandleForUid(0); 278 // getUserHandleForUid will divide uid by 100000. Pass in some arbitrary number > 100000 to be 279 // different from system uid 0. 280 UserHandle differentUserHandle = UserHandle.getUserHandleForUid(1200000); 281 282 assertThat(uuid).isNotEqualTo(differentUUID); 283 assertThat(userHandle).isNotEqualTo(differentUserHandle); 284 285 // Act 286 shadowOf(storageStatsManager).addStorageStats(uuid, packageName, userHandle, expected); 287 288 // Assert 289 assertThrows( 290 PackageManager.NameNotFoundException.class, 291 () -> 292 shadowOf(storageStatsManager) 293 .queryStatsForPackage(uuid, "differentPackageName", userHandle)); 294 295 assertThrows( 296 PackageManager.NameNotFoundException.class, 297 () -> 298 shadowOf(storageStatsManager) 299 .queryStatsForPackage(differentUUID, packageName, userHandle)); 300 301 assertThrows( 302 PackageManager.NameNotFoundException.class, 303 () -> 304 shadowOf(storageStatsManager) 305 .queryStatsForPackage(uuid, packageName, differentUserHandle)); 306 } 307 308 @Test queryUserWithWrongArguments_shouldFail()309 public void queryUserWithWrongArguments_shouldFail() { 310 // Arrange 311 StorageStats expected = buildStorageStats(); 312 UUID uuid = UUID.randomUUID(); 313 UUID differentUUID = UUID.randomUUID(); 314 UserHandle userHandle = UserHandle.getUserHandleForUid(0); 315 // getUserHandleForUid will divide uid by 100000. Pass in some arbitrary number > 100000 to be 316 // different from system uid 0. 317 UserHandle differentUserHandle = UserHandle.getUserHandleForUid(1200000); 318 319 assertThat(uuid).isNotEqualTo(differentUUID); 320 assertThat(userHandle).isNotEqualTo(differentUserHandle); 321 322 // Act 323 shadowOf(storageStatsManager) 324 .addStorageStats(uuid, /* packageName= */ "somePackageName", userHandle, expected); 325 326 // Assert 327 assertThrows( 328 PackageManager.NameNotFoundException.class, 329 () -> shadowOf(storageStatsManager).queryStatsForUser(differentUUID, userHandle)); 330 331 assertThrows( 332 PackageManager.NameNotFoundException.class, 333 () -> shadowOf(storageStatsManager).queryStatsForUser(uuid, differentUserHandle)); 334 } 335 336 @Test queryPackageAfterClearSetup_shouldFail()337 public void queryPackageAfterClearSetup_shouldFail() { 338 // Arrange 339 StorageStats expected = buildStorageStats(); 340 UUID uuid = UUID.randomUUID(); 341 String packageName = "somePackageName"; 342 UserHandle userHandle = Process.myUserHandle(); 343 shadowOf(storageStatsManager).addStorageStats(uuid, packageName, userHandle, expected); 344 345 // Act 346 shadowOf(storageStatsManager).clearStorageStats(); 347 348 // Assert 349 assertThrows( 350 PackageManager.NameNotFoundException.class, 351 () -> shadowOf(storageStatsManager).queryStatsForPackage(uuid, packageName, userHandle)); 352 } 353 354 @Test queryUserAfterClearSetup_shouldFail()355 public void queryUserAfterClearSetup_shouldFail() { 356 // Arrange 357 StorageStats expected = buildStorageStats(); 358 UUID uuid = UUID.randomUUID(); 359 String packageName = "somePackageName"; 360 UserHandle userHandle = Process.myUserHandle(); 361 shadowOf(storageStatsManager).addStorageStats(uuid, packageName, userHandle, expected); 362 363 // Act 364 shadowOf(storageStatsManager).clearStorageStats(); 365 366 // Assert 367 assertThrows( 368 PackageManager.NameNotFoundException.class, 369 () -> shadowOf(storageStatsManager).queryStatsForUser(uuid, userHandle)); 370 } 371 buildStorageStats()372 private static StorageStats buildStorageStats() { 373 return buildStorageStats(/* codeSize= */ 3000L, /* dataSize= */ 2000L, /* cacheSize= */ 1000L); 374 } 375 buildStorageStats(long codeSize, long dataSize, long cacheSize)376 private static StorageStats buildStorageStats(long codeSize, long dataSize, long cacheSize) { 377 Parcel parcel = Parcel.obtain(); 378 parcel.writeLong(codeSize); 379 parcel.writeLong(dataSize); 380 parcel.writeLong(cacheSize); 381 parcel.setDataPosition(0); 382 return StorageStats.CREATOR.createFromParcel(parcel); 383 } 384 } 385