diff --git a/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java b/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java index d5d96a5f080..f54c685730d 100644 --- a/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java +++ b/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java @@ -23,7 +23,6 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.UserInfo; import android.os.UserHandle; -import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; @@ -75,27 +74,31 @@ public class StorageAsyncLoader Log.d(TAG, "Loading apps"); List applicationInfos = mPackageManager.getInstalledApplicationsAsUser(0, userId); - ArraySet seenUid = new ArraySet<>(); // some apps share a uid AppsStorageResult result = new AppsStorageResult(); + UserHandle myUser = UserHandle.of(userId); for (int i = 0, size = applicationInfos.size(); i < size; i++) { ApplicationInfo app = applicationInfos.get(i); - if (seenUid.contains(app.uid)) { - continue; - } - seenUid.add(app.uid); + StorageStatsSource.AppStorageStats stats = + mStatsManager.getStatsForPackage(mUuid, app.packageName, myUser); - StorageStatsSource.AppStorageStats stats = mStatsManager.getStatsForUid(mUuid, app.uid); - // Note: This omits cache intentionally -- we are not attributing it to the apps. - long appSize = stats.getCodeBytes() + stats.getDataBytes(); + long attributedAppSizeInBytes = stats.getDataBytes(); + // This matches how the package manager calculates sizes -- by zeroing out code sizes of + // system apps which are not updated. My initial tests suggest that this results in the + // original code size being counted for updated system apps when they shouldn't, but + // I am not sure how to avoid this problem without specifically going in to find that + // code size. + if (!app.isSystemApp() || app.isUpdatedSystemApp()) { + attributedAppSizeInBytes += stats.getCodeBytes(); + } switch (app.category) { case CATEGORY_GAME: - result.gamesSize += appSize; + result.gamesSize += attributedAppSizeInBytes; break; case CATEGORY_AUDIO: - result.musicAppsSize += appSize; + result.musicAppsSize += attributedAppSizeInBytes; break; default: - result.otherAppsSize += appSize; + result.otherAppsSize += attributedAppSizeInBytes; break; } } diff --git a/tests/unit/src/com/android/settings/deviceinfo/storage/StorageAsyncLoaderTest.java b/tests/unit/src/com/android/settings/deviceinfo/storage/StorageAsyncLoaderTest.java index 70e05d65962..10ba293d457 100644 --- a/tests/unit/src/com/android/settings/deviceinfo/storage/StorageAsyncLoaderTest.java +++ b/tests/unit/src/com/android/settings/deviceinfo/storage/StorageAsyncLoaderTest.java @@ -18,6 +18,7 @@ package com.android.settings.deviceinfo.storage; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; @@ -45,13 +46,14 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; -import java.util.Map; @RunWith(AndroidJUnit4.class) @SmallTest public class StorageAsyncLoaderTest { private static final int PRIMARY_USER_ID = 0; private static final int SECONDARY_USER_ID = 10; + private static final String PACKAGE_NAME_1 = "com.blah.test"; + private static final String PACKAGE_NAME_2 = "com.blah.test2"; @Mock private StorageStatsSource mSource; @@ -81,8 +83,8 @@ public class StorageAsyncLoaderTest { @Test public void testLoadingApps() throws Exception { - addPackage(1001, 0, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED); - addPackage(1002, 0, 100, 1000, ApplicationInfo.CATEGORY_UNDEFINED); + addPackage(PACKAGE_NAME_1, 0, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED); + addPackage(PACKAGE_NAME_2, 0, 100, 1000, ApplicationInfo.CATEGORY_UNDEFINED); SparseArray result = mLoader.loadInBackground(); @@ -93,7 +95,7 @@ public class StorageAsyncLoaderTest { @Test public void testGamesAreFiltered() throws Exception { - addPackage(1001, 0, 1, 10, ApplicationInfo.CATEGORY_GAME); + addPackage(PACKAGE_NAME_1, 0, 1, 10, ApplicationInfo.CATEGORY_GAME); SparseArray result = mLoader.loadInBackground(); @@ -102,20 +104,9 @@ public class StorageAsyncLoaderTest { assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(0); } - @Test - public void testDuplicateUidsAreSkipped() throws Exception { - addPackage(1001, 0, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED); - addPackage(1001, 0, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED); - - SparseArray result = mLoader.loadInBackground(); - - assertThat(result.size()).isEqualTo(1); - assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(11L); - } - @Test public void testCacheIsIgnored() throws Exception { - addPackage(1001, 100, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED); + addPackage(PACKAGE_NAME_1, 100, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED); SparseArray result = mLoader.loadInBackground(); @@ -140,16 +131,43 @@ public class StorageAsyncLoaderTest { assertThat(result.get(SECONDARY_USER_ID).externalStats.totalBytes).isEqualTo(10L); } - private void addPackage(int uid, long cacheSize, long codeSize, long dataSize, int category) { + @Test + public void testSystemAppsBaseSizeIsIgnored() throws Exception { + ApplicationInfo systemApp = + addPackage(PACKAGE_NAME_1, 100, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED); + systemApp.flags = ApplicationInfo.FLAG_SYSTEM; + + SparseArray result = mLoader.loadInBackground(); + + assertThat(result.size()).isEqualTo(1); + assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(10L); + } + + @Test + public void testUpdatedSystemAppCodeSizeIsCounted() throws Exception { + ApplicationInfo systemApp = + addPackage(PACKAGE_NAME_1, 100, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED); + systemApp.flags = ApplicationInfo.FLAG_SYSTEM & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; + + SparseArray result = mLoader.loadInBackground(); + + assertThat(result.size()).isEqualTo(1); + assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(11L); + } + + private ApplicationInfo addPackage( + String packageName, long cacheSize, long codeSize, long dataSize, int category) { StorageStatsSource.AppStorageStats storageStats = mock(StorageStatsSource.AppStorageStats.class); when(storageStats.getCodeBytes()).thenReturn(codeSize); when(storageStats.getDataBytes()).thenReturn(dataSize); - when(mSource.getStatsForUid(anyString(), eq(uid))).thenReturn(storageStats); + when(mSource.getStatsForPackage(anyString(), eq(packageName), any(UserHandle.class))) + .thenReturn(storageStats); ApplicationInfo info = new ApplicationInfo(); - info.uid = uid; + info.packageName = packageName; info.category = category; mInfo.add(info); + return info; } }