Storage Settings Apps category shows image/video/audio APPs

There is AOSP built in file browser for image/video/audio
file category, all APPs except games should be included in
Apps category.

- Shows image/video/audio APPs in APPs category.
- Count Image/Video/Audio APPs storage size to Apps storage size.
- Remove APP size & cache size for Images/Videos/Audios category.

Bug: 170918505
Test: atest StorageAsyncLoaderTest.java
Change-Id: I07e0a3a66a13f36b9e0cbde289d8ba90df4ae295
This commit is contained in:
Arc Wang
2021-04-28 19:54:37 +08:00
parent e06f5a93b1
commit 4cd89bb082
3 changed files with 51 additions and 6 deletions

View File

@@ -511,7 +511,7 @@ public class ManageApplications extends InstrumentedFragment
if (storageType == STORAGE_TYPE_MUSIC) { if (storageType == STORAGE_TYPE_MUSIC) {
filter = new CompoundFilter(ApplicationsState.FILTER_AUDIO, filter); filter = new CompoundFilter(ApplicationsState.FILTER_AUDIO, filter);
} else if (storageType == STORAGE_TYPE_DEFAULT) { } else if (storageType == STORAGE_TYPE_DEFAULT) {
filter = new CompoundFilter(ApplicationsState.FILTER_OTHER_APPS, filter); filter = new CompoundFilter(ApplicationsState.FILTER_APPS_EXCEPT_GAMES, filter);
} }
return filter; return filter;
} }

View File

@@ -120,7 +120,9 @@ public class StorageAsyncLoader
// This isn't quite right because it slams the first user by user id with the whole code // This isn't quite right because it slams the first user by user id with the whole code
// size, but this ensures that we count all apps seen once. // size, but this ensures that we count all apps seen once.
boolean isAddCodeBytesForFirstUserId = false;
if (!mSeenPackages.contains(app.packageName)) { if (!mSeenPackages.contains(app.packageName)) {
isAddCodeBytesForFirstUserId = true;
blamedSize += stats.getCodeBytes(); blamedSize += stats.getCodeBytes();
mSeenPackages.add(app.packageName); mSeenPackages.add(app.packageName);
} }
@@ -130,13 +132,34 @@ public class StorageAsyncLoader
result.gamesSize += blamedSize; result.gamesSize += blamedSize;
break; break;
case CATEGORY_AUDIO: case CATEGORY_AUDIO:
// TODO(b/170918505): Should revamp audio size calculation with the data
// from media provider.
result.musicAppsSize += blamedSize; result.musicAppsSize += blamedSize;
if (isAddCodeBytesForFirstUserId) {
result.musicAppsSize -= stats.getCodeBytes();
}
result.otherAppsSize += blamedSize;
break; break;
case CATEGORY_VIDEO: case CATEGORY_VIDEO:
// TODO(b/170918505): Should revamp video size calculation with the data
// from media provider.
result.videoAppsSize += blamedSize; result.videoAppsSize += blamedSize;
if (isAddCodeBytesForFirstUserId) {
result.videoAppsSize -= stats.getCodeBytes();
}
result.otherAppsSize += blamedSize;
break; break;
case CATEGORY_IMAGE: case CATEGORY_IMAGE:
// TODO(b/170918505): Should revamp image size calculation with the data
// from media provider.
result.photosAppsSize += blamedSize; result.photosAppsSize += blamedSize;
if (isAddCodeBytesForFirstUserId) {
result.photosAppsSize -= stats.getCodeBytes();
}
result.otherAppsSize += blamedSize;
break; break;
default: default:
// The deprecated game flag does not set the category. // The deprecated game flag does not set the category.

View File

@@ -22,7 +22,9 @@ import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.content.Context; import android.content.Context;
@@ -30,20 +32,22 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.net.TrafficStats; import android.net.TrafficStats;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.util.SparseArray; import android.util.SparseArray;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
import com.android.settings.R;
import com.android.settingslib.applications.StorageStatsSource; import com.android.settingslib.applications.StorageStatsSource;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
@@ -57,11 +61,11 @@ public class StorageAsyncLoaderTest {
private static final int SECONDARY_USER_ID = 10; private static final int SECONDARY_USER_ID = 10;
private static final String PACKAGE_NAME_1 = "com.blah.test"; private static final String PACKAGE_NAME_1 = "com.blah.test";
private static final String PACKAGE_NAME_2 = "com.blah.test2"; private static final String PACKAGE_NAME_2 = "com.blah.test2";
private static final String PACKAGE_NAME_3 = "com.blah.test3";
private static final long DEFAULT_QUOTA = 64 * TrafficStats.MB_IN_BYTES; private static final long DEFAULT_QUOTA = 64 * TrafficStats.MB_IN_BYTES;
@Mock @Mock
private StorageStatsSource mSource; private StorageStatsSource mSource;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext; private Context mContext;
@Mock @Mock
private PackageManager mPackageManager; private PackageManager mPackageManager;
@@ -76,6 +80,7 @@ public class StorageAsyncLoaderTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext());
mInfo = new ArrayList<>(); mInfo = new ArrayList<>();
mLoader = new StorageAsyncLoader(mContext, mUserManager, "id", mSource, mPackageManager); mLoader = new StorageAsyncLoader(mContext, mUserManager, "id", mSource, mPackageManager);
when(mPackageManager.getInstalledApplicationsAsUser(eq(PRIMARY_USER_ID), anyInt())) when(mPackageManager.getInstalledApplicationsAsUser(eq(PRIMARY_USER_ID), anyInt()))
@@ -85,6 +90,10 @@ public class StorageAsyncLoaderTest {
mUsers.add(info); mUsers.add(info);
when(mUserManager.getUsers()).thenReturn(mUsers); when(mUserManager.getUsers()).thenReturn(mUsers);
when(mSource.getCacheQuotaBytes(anyString(), anyInt())).thenReturn(DEFAULT_QUOTA); when(mSource.getCacheQuotaBytes(anyString(), anyInt())).thenReturn(DEFAULT_QUOTA);
final Resources resources = spy(mContext.getResources());
when(mContext.getResources()).thenReturn(resources);
doReturn("content://com.android.providers.media.documents/root/videos_root")
.when(resources).getString(R.string.config_videos_storage_category_uri);
} }
@Test @Test
@@ -169,8 +178,8 @@ public class StorageAsyncLoaderTest {
SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground(); SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
assertThat(result.size()).isEqualTo(1); assertThat(result.size()).isEqualTo(1);
assertThat(result.get(PRIMARY_USER_ID).videoAppsSize).isEqualTo(11L); // Code size is not included for file based video category.
assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(0); assertThat(result.get(PRIMARY_USER_ID).videoAppsSize).isEqualTo(10L);
} }
@Test @Test
@@ -206,7 +215,8 @@ public class StorageAsyncLoaderTest {
SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground(); SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
assertThat(result.size()).isEqualTo(2); assertThat(result.size()).isEqualTo(2);
assertThat(result.get(PRIMARY_USER_ID).videoAppsSize).isEqualTo(11L); // Code size is not included for file based video category.
assertThat(result.get(PRIMARY_USER_ID).videoAppsSize).isEqualTo(10L);
// No code size for the second user. // No code size for the second user.
assertThat(result.get(SECONDARY_USER_ID).videoAppsSize).isEqualTo(10L); assertThat(result.get(SECONDARY_USER_ID).videoAppsSize).isEqualTo(10L);
} }
@@ -221,6 +231,18 @@ public class StorageAsyncLoaderTest {
assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(DEFAULT_QUOTA + 11); assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(DEFAULT_QUOTA + 11);
} }
@Test
public void testAppsAreFiltered() throws Exception {
addPackage(PACKAGE_NAME_1, 0, 1, 10, ApplicationInfo.CATEGORY_IMAGE);
addPackage(PACKAGE_NAME_2, 0, 1, 10, ApplicationInfo.CATEGORY_VIDEO);
addPackage(PACKAGE_NAME_3, 0, 1, 10, ApplicationInfo.CATEGORY_AUDIO);
SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
assertThat(result.size()).isEqualTo(1);
assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(33L);
}
private ApplicationInfo addPackage(String packageName, long cacheSize, long codeSize, private ApplicationInfo addPackage(String packageName, long cacheSize, long codeSize,
long dataSize, int category) throws Exception { long dataSize, int category) throws Exception {
StorageStatsSource.AppStorageStats storageStats = StorageStatsSource.AppStorageStats storageStats =