Merge "Add more sane multi-profile app attribution." into oc-dev
This commit is contained in:
@@ -120,7 +120,6 @@ public class StorageProfileFragment extends DashboardFragment
|
|||||||
@Override
|
@Override
|
||||||
public void onLoadFinished(Loader<SparseArray<AppsStorageResult>> loader,
|
public void onLoadFinished(Loader<SparseArray<AppsStorageResult>> loader,
|
||||||
SparseArray<AppsStorageResult> result) {
|
SparseArray<AppsStorageResult> result) {
|
||||||
scrubAppsFromResult(result.get(mUserId));
|
|
||||||
mPreferenceController.onLoadFinished(result, mUserId);
|
mPreferenceController.onLoadFinished(result, mUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,17 +131,4 @@ public class StorageProfileFragment extends DashboardFragment
|
|||||||
void setPreferenceController(StorageItemPreferenceController controller) {
|
void setPreferenceController(StorageItemPreferenceController controller) {
|
||||||
mPreferenceController = controller;
|
mPreferenceController = controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AppsStorageResult scrubAppsFromResult(AppsStorageResult result) {
|
|
||||||
if (result == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(b/35927909): Attribute app sizes better than zeroing out for profiles.
|
|
||||||
result.gamesSize = 0;
|
|
||||||
result.musicAppsSize = 0;
|
|
||||||
result.videoAppsSize = 0;
|
|
||||||
result.otherAppsSize = 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,7 @@ import android.content.pm.ApplicationInfo;
|
|||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
@@ -34,6 +35,8 @@ import com.android.settings.utils.AsyncLoader;
|
|||||||
import com.android.settingslib.applications.StorageStatsSource;
|
import com.android.settingslib.applications.StorageStatsSource;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,6 +51,7 @@ public class StorageAsyncLoader
|
|||||||
private String mUuid;
|
private String mUuid;
|
||||||
private StorageStatsSource mStatsManager;
|
private StorageStatsSource mStatsManager;
|
||||||
private PackageManagerWrapper mPackageManager;
|
private PackageManagerWrapper mPackageManager;
|
||||||
|
private ArraySet<String> mSeenPackages;
|
||||||
|
|
||||||
public StorageAsyncLoader(Context context, UserManagerWrapper userManager,
|
public StorageAsyncLoader(Context context, UserManagerWrapper userManager,
|
||||||
String uuid, StorageStatsSource source, PackageManagerWrapper pm) {
|
String uuid, StorageStatsSource source, PackageManagerWrapper pm) {
|
||||||
@@ -64,8 +68,18 @@ public class StorageAsyncLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
private SparseArray<AppsStorageResult> loadApps() {
|
private SparseArray<AppsStorageResult> loadApps() {
|
||||||
|
mSeenPackages = new ArraySet<>();
|
||||||
SparseArray<AppsStorageResult> result = new SparseArray<>();
|
SparseArray<AppsStorageResult> result = new SparseArray<>();
|
||||||
List<UserInfo> infos = mUserManager.getUsers();
|
List<UserInfo> infos = mUserManager.getUsers();
|
||||||
|
// Sort the users by user id ascending.
|
||||||
|
Collections.sort(
|
||||||
|
infos,
|
||||||
|
new Comparator<UserInfo>() {
|
||||||
|
@Override
|
||||||
|
public int compare(UserInfo userInfo, UserInfo otherUser) {
|
||||||
|
return Integer.compare(userInfo.id, otherUser.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
for (int i = 0, userCount = infos.size(); i < userCount; i++) {
|
for (int i = 0, userCount = infos.size(); i < userCount; i++) {
|
||||||
UserInfo info = infos.get(i);
|
UserInfo info = infos.get(i);
|
||||||
result.put(info.id, getStorageResultForUser(info.id));
|
result.put(info.id, getStorageResultForUser(info.id));
|
||||||
@@ -93,10 +107,11 @@ public class StorageAsyncLoader
|
|||||||
|
|
||||||
long blamedSize = stats.getDataBytes() - stats.getCacheBytes();
|
long blamedSize = stats.getDataBytes() - stats.getCacheBytes();
|
||||||
|
|
||||||
// Only count app code against the current user; we don't want
|
// This isn't quite right because it slams the first user by user id with the whole code
|
||||||
// double-counting on multi-user devices.
|
// size, but this ensures that we count all apps seen once.
|
||||||
if (userId == UserHandle.myUserId()) {
|
if (!mSeenPackages.contains(app.packageName)) {
|
||||||
blamedSize += stats.getCodeBytes();
|
blamedSize += stats.getCodeBytes();
|
||||||
|
mSeenPackages.add(app.packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (app.category) {
|
switch (app.category) {
|
||||||
@@ -140,6 +155,7 @@ public class StorageAsyncLoader
|
|||||||
public long musicAppsSize;
|
public long musicAppsSize;
|
||||||
public long videoAppsSize;
|
public long videoAppsSize;
|
||||||
public long otherAppsSize;
|
public long otherAppsSize;
|
||||||
|
public long cacheSize;
|
||||||
public StorageStatsSource.ExternalStorageStats externalStats;
|
public StorageStatsSource.ExternalStorageStats externalStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -96,7 +96,13 @@ public class UserProfileController extends PreferenceController
|
|||||||
int userId = mUser.id;
|
int userId = mUser.id;
|
||||||
StorageAsyncLoader.AppsStorageResult result = stats.get(userId);
|
StorageAsyncLoader.AppsStorageResult result = stats.get(userId);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
setSize(result.externalStats.totalBytes, mTotalSizeBytes);
|
setSize(
|
||||||
|
result.externalStats.totalBytes
|
||||||
|
+ result.otherAppsSize
|
||||||
|
+ result.videoAppsSize
|
||||||
|
+ result.musicAppsSize
|
||||||
|
+ result.gamesSize,
|
||||||
|
mTotalSizeBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -43,7 +43,7 @@ public class StorageProfileFragmentTest {
|
|||||||
private ArgumentCaptor<SparseArray<StorageAsyncLoader.AppsStorageResult>> mCaptor;
|
private ArgumentCaptor<SparseArray<StorageAsyncLoader.AppsStorageResult>> mCaptor;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void verifyAppSizesAreZeroedOut() {
|
public void verifyAppSizesAreNotZeroedOut() {
|
||||||
StorageItemPreferenceController controller = mock(StorageItemPreferenceController.class);
|
StorageItemPreferenceController controller = mock(StorageItemPreferenceController.class);
|
||||||
StorageProfileFragment fragment = new StorageProfileFragment();
|
StorageProfileFragment fragment = new StorageProfileFragment();
|
||||||
StorageAsyncLoader.AppsStorageResult result = new StorageAsyncLoader.AppsStorageResult();
|
StorageAsyncLoader.AppsStorageResult result = new StorageAsyncLoader.AppsStorageResult();
|
||||||
@@ -62,10 +62,10 @@ public class StorageProfileFragmentTest {
|
|||||||
verify(controller).onLoadFinished(mCaptor.capture(), anyInt());
|
verify(controller).onLoadFinished(mCaptor.capture(), anyInt());
|
||||||
|
|
||||||
StorageAsyncLoader.AppsStorageResult extractedResult = mCaptor.getValue().get(0);
|
StorageAsyncLoader.AppsStorageResult extractedResult = mCaptor.getValue().get(0);
|
||||||
assertThat(extractedResult.musicAppsSize).isEqualTo(0);
|
assertThat(extractedResult.musicAppsSize).isEqualTo(100);
|
||||||
assertThat(extractedResult.videoAppsSize).isEqualTo(0);
|
assertThat(extractedResult.videoAppsSize).isEqualTo(400);
|
||||||
assertThat(extractedResult.otherAppsSize).isEqualTo(0);
|
assertThat(extractedResult.otherAppsSize).isEqualTo(200);
|
||||||
assertThat(extractedResult.gamesSize).isEqualTo(0);
|
assertThat(extractedResult.gamesSize).isEqualTo(300);
|
||||||
assertThat(extractedResult.externalStats.audioBytes).isEqualTo(1);
|
assertThat(extractedResult.externalStats.audioBytes).isEqualTo(1);
|
||||||
assertThat(extractedResult.externalStats.videoBytes).isEqualTo(2);
|
assertThat(extractedResult.externalStats.videoBytes).isEqualTo(2);
|
||||||
assertThat(extractedResult.externalStats.imageBytes).isEqualTo(3);
|
assertThat(extractedResult.externalStats.imageBytes).isEqualTo(3);
|
||||||
|
@@ -27,6 +27,7 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.support.test.filters.SmallTest;
|
import android.support.test.filters.SmallTest;
|
||||||
@@ -74,7 +75,8 @@ public class StorageAsyncLoaderTest {
|
|||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
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(anyInt(), anyInt())).thenReturn(mInfo);
|
when(mPackageManager.getInstalledApplicationsAsUser(eq(PRIMARY_USER_ID), anyInt()))
|
||||||
|
.thenReturn(mInfo);
|
||||||
UserInfo info = new UserInfo();
|
UserInfo info = new UserInfo();
|
||||||
mUsers = new ArrayList<>();
|
mUsers = new ArrayList<>();
|
||||||
mUsers.add(info);
|
mUsers.add(info);
|
||||||
@@ -174,13 +176,37 @@ public class StorageAsyncLoaderTest {
|
|||||||
info.category = ApplicationInfo.CATEGORY_UNDEFINED;
|
info.category = ApplicationInfo.CATEGORY_UNDEFINED;
|
||||||
mInfo.add(info);
|
mInfo.add(info);
|
||||||
when(mSource.getStatsForPackage(anyString(), anyString(), any(UserHandle.class)))
|
when(mSource.getStatsForPackage(anyString(), anyString(), any(UserHandle.class)))
|
||||||
.thenThrow(new IllegalStateException());
|
.thenThrow(new NameNotFoundException());
|
||||||
|
|
||||||
SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
|
SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
|
||||||
|
|
||||||
// Should not crash.
|
// Should not crash.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPackageIsNotDoubleCounted() throws Exception {
|
||||||
|
UserInfo info = new UserInfo();
|
||||||
|
info.id = SECONDARY_USER_ID;
|
||||||
|
mUsers.add(info);
|
||||||
|
when(mSource.getExternalStorageStats(anyString(), eq(UserHandle.SYSTEM)))
|
||||||
|
.thenReturn(new StorageStatsSource.ExternalStorageStats(9, 2, 3, 4, 0));
|
||||||
|
when(mSource.getExternalStorageStats(anyString(), eq(new UserHandle(SECONDARY_USER_ID))))
|
||||||
|
.thenReturn(new StorageStatsSource.ExternalStorageStats(10, 3, 3, 4, 0));
|
||||||
|
addPackage(PACKAGE_NAME_1, 0, 1, 10, ApplicationInfo.CATEGORY_VIDEO);
|
||||||
|
ArrayList<ApplicationInfo> secondaryUserApps = new ArrayList<>();
|
||||||
|
ApplicationInfo appInfo = new ApplicationInfo();
|
||||||
|
appInfo.packageName = PACKAGE_NAME_1;
|
||||||
|
appInfo.category = ApplicationInfo.CATEGORY_VIDEO;
|
||||||
|
secondaryUserApps.add(appInfo);
|
||||||
|
|
||||||
|
SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
|
||||||
|
|
||||||
|
assertThat(result.size()).isEqualTo(2);
|
||||||
|
assertThat(result.get(PRIMARY_USER_ID).videoAppsSize).isEqualTo(11L);
|
||||||
|
// No code size for the second user.
|
||||||
|
assertThat(result.get(SECONDARY_USER_ID).videoAppsSize).isEqualTo(10L);
|
||||||
|
}
|
||||||
|
|
||||||
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 =
|
||||||
@@ -196,4 +222,5 @@ public class StorageAsyncLoaderTest {
|
|||||||
mInfo.add(info);
|
mInfo.add(info);
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user