diff options
3 files changed, 61 insertions, 98 deletions
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java index cb9039b046ee..c746af4c9ea3 100644 --- a/core/java/android/content/pm/PackageStats.java +++ b/core/java/android/content/pm/PackageStats.java @@ -19,6 +19,9 @@ package android.content.pm; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; +import android.text.TextUtils; + +import java.util.Objects; /** * implementation of PackageStats associated with a @@ -173,4 +176,31 @@ public class PackageStats implements Parcelable { dest.writeLong(externalMediaSize); dest.writeLong(externalObbSize); } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof PackageStats)) { + return false; + } + + final PackageStats otherStats = (PackageStats) obj; + return ((TextUtils.equals(packageName, otherStats.packageName)) + && userHandle == otherStats.userHandle + && codeSize == otherStats.codeSize + && dataSize == otherStats.dataSize + && cacheSize == otherStats.cacheSize + && externalCodeSize == otherStats.externalCodeSize + && externalDataSize == otherStats.externalDataSize + && externalCacheSize == otherStats.externalCacheSize + && externalMediaSize == otherStats.externalMediaSize + && externalObbSize == otherStats.externalObbSize); + } + + @Override + public int hashCode() { + return Objects.hash(packageName, userHandle, codeSize, dataSize, + cacheSize, externalCodeSize, externalDataSize, externalCacheSize, externalMediaSize, + externalObbSize); + } + } diff --git a/services/core/java/com/android/server/storage/AppCollector.java b/services/core/java/com/android/server/storage/AppCollector.java index ee9c5bf2775d..25880fb90496 100644 --- a/services/core/java/com/android/server/storage/AppCollector.java +++ b/services/core/java/com/android/server/storage/AppCollector.java @@ -17,6 +17,8 @@ package com.android.server.storage; import android.annotation.NonNull; +import android.app.usage.StorageStats; +import android.app.usage.StorageStatsManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageStatsObserver; @@ -64,7 +66,8 @@ public class AppCollector { mBackgroundHandler = new BackgroundHandler(BackgroundThread.get().getLooper(), volume, context.getPackageManager(), - (UserManager) context.getSystemService(Context.USER_SERVICE)); + (UserManager) context.getSystemService(Context.USER_SERVICE), + (StorageStatsManager) context.getSystemService(Context.STORAGE_STATS_SERVICE)); } /** @@ -93,39 +96,20 @@ public class AppCollector { return value; } - private class StatsObserver extends IPackageStatsObserver.Stub { - private AtomicInteger mCount; - private final ArrayList<PackageStats> mPackageStats; - - public StatsObserver(int count) { - mCount = new AtomicInteger(count); - mPackageStats = new ArrayList<>(count); - } - - @Override - public void onGetStatsCompleted(PackageStats packageStats, boolean succeeded) - throws RemoteException { - if (succeeded) { - mPackageStats.add(packageStats); - } - - if (mCount.decrementAndGet() == 0) { - mStats.complete(mPackageStats); - } - } - } - private class BackgroundHandler extends Handler { static final int MSG_START_LOADING_SIZES = 0; private final VolumeInfo mVolume; private final PackageManager mPm; private final UserManager mUm; + private final StorageStatsManager mStorageStatsManager; - BackgroundHandler(Looper looper, @NonNull VolumeInfo volume, PackageManager pm, UserManager um) { + BackgroundHandler(Looper looper, @NonNull VolumeInfo volume, + PackageManager pm, UserManager um, StorageStatsManager storageStatsManager) { super(looper); mVolume = volume; mPm = pm; mUm = um; + mStorageStatsManager = storageStatsManager; } @Override @@ -149,14 +133,20 @@ public class AppCollector { mStats.complete(new ArrayList<>()); } - // Kick off the async package size query for all apps. - final StatsObserver observer = new StatsObserver(count); + List<PackageStats> stats = new ArrayList<>(); for (UserInfo user : users) { for (ApplicationInfo app : volumeApps) { - mPm.getPackageSizeInfoAsUser(app.packageName, user.id, - observer); + PackageStats packageStats = new PackageStats(app.packageName, user.id); + StorageStats storageStats = mStorageStatsManager.queryStatsForPackage( + app.volumeUuid, app.packageName, user.getUserHandle()); + packageStats.cacheSize = storageStats.getCacheBytes(); + packageStats.codeSize = storageStats.getCodeBytes(); + packageStats.dataSize = storageStats.getDataBytes(); + stats.add(packageStats); } } + + mStats.complete(stats); } } } diff --git a/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java b/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java index 29185e92d5ed..8cf7c8a62039 100644 --- a/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java +++ b/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java @@ -16,12 +16,15 @@ package com.android.server.storage; +import android.app.usage.StorageStats; +import android.app.usage.StorageStatsManager; import android.content.pm.UserInfo; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageStatsObserver; import android.content.pm.PackageManager; import android.content.pm.PackageStats; +import android.os.UserHandle; import android.os.UserManager; import android.os.storage.VolumeInfo; import android.test.AndroidTestCase; @@ -53,6 +56,7 @@ public class AppCollectorTest extends AndroidTestCase { @Mock private Context mContext; @Mock private PackageManager mPm; @Mock private UserManager mUm; + @Mock private StorageStatsManager mSsm; private List<ApplicationInfo> mApps; private List<UserInfo> mUsers; @@ -63,6 +67,7 @@ public class AppCollectorTest extends AndroidTestCase { mApps = new ArrayList<>(); when(mContext.getPackageManager()).thenReturn(mPm); when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUm); + when(mContext.getSystemService(Context.STORAGE_STATS_SERVICE)).thenReturn(mSsm); // Set up the app list. when(mPm.getInstalledApplications(anyInt())).thenReturn(mApps); @@ -100,39 +105,9 @@ public class AppCollectorTest extends AndroidTestCase { AppCollector collector = new AppCollector(mContext, volume); PackageStats stats = new PackageStats("com.test.app"); - // Set up this to handle the asynchronous call to the PackageManager. This returns the - // package info for the specified package. - doAnswer(new Answer<Void>() { - @Override - public Void answer(InvocationOnMock invocation) { - try { - ((IPackageStatsObserver.Stub) invocation.getArguments()[2]) - .onGetStatsCompleted(stats, true); - } catch (Exception e) { - // We fail instead of just letting the exception fly because throwing - // out of the callback like this on the background thread causes the test - // runner to crash, rather than reporting the failure. - fail(); - } - return null; - } - }).when(mPm).getPackageSizeInfoAsUser(eq("com.test.app"), eq(0), any()); - - - // Because getPackageStats is a blocking call, we block execution of the test until the - // call finishes. In order to finish the call, we need the above answer to execute. - List<PackageStats> myStats = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(1); - new Thread(new Runnable() { - @Override - public void run() { - myStats.addAll(collector.getPackageStats(TIMEOUT)); - latch.countDown(); - } - }).start(); - latch.await(); - - assertThat(myStats).containsExactly(stats); + when(mSsm.queryStatsForPackage(eq("testuuid"), + eq("com.test.app"), eq(UserHandle.of(0)))).thenReturn(new StorageStats()); + assertThat(collector.getPackageStats(TIMEOUT)).containsExactly(stats); } @Test @@ -151,43 +126,11 @@ public class AppCollectorTest extends AndroidTestCase { PackageStats otherStats = new PackageStats("com.test.app"); otherStats.userHandle = 1; - // Set up this to handle the asynchronous call to the PackageManager. This returns the - // package info for our packages. - doAnswer(new Answer<Void>() { - @Override - public Void answer(InvocationOnMock invocation) { - try { - ((IPackageStatsObserver.Stub) invocation.getArguments()[2]) - .onGetStatsCompleted(stats, true); - - // Now callback for the other uid. - ((IPackageStatsObserver.Stub) invocation.getArguments()[2]) - .onGetStatsCompleted(otherStats, true); - } catch (Exception e) { - // We fail instead of just letting the exception fly because throwing - // out of the callback like this on the background thread causes the test - // runner to crash, rather than reporting the failure. - fail(); - } - return null; - } - }).when(mPm).getPackageSizeInfoAsUser(eq("com.test.app"), eq(0), any()); - - - // Because getPackageStats is a blocking call, we block execution of the test until the - // call finishes. In order to finish the call, we need the above answer to execute. - List<PackageStats> myStats = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(1); - new Thread(new Runnable() { - @Override - public void run() { - myStats.addAll(collector.getPackageStats(TIMEOUT)); - latch.countDown(); - } - }).start(); - latch.await(); - - assertThat(myStats).containsAllOf(stats, otherStats); + when(mSsm.queryStatsForPackage(eq("testuuid"), + eq("com.test.app"), eq(UserHandle.of(0)))).thenReturn(new StorageStats()); + when(mSsm.queryStatsForPackage(eq("testuuid"), + eq("com.test.app"), eq(UserHandle.of(1)))).thenReturn(new StorageStats()); + assertThat(collector.getPackageStats(TIMEOUT)).containsExactly(stats, otherStats); } @Test(expected=NullPointerException.class) |