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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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.
|
||||||
|
@@ -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 =
|
||||||
|
Reference in New Issue
Block a user