Don't look up storage for uninstalled apps.

This also catches any potential state exceptions which may
occur when errors occur during storage queries on a package.
This should stop the crashes.

Change-Id: Idab92434f74eaf44ba7b3fdbbc6c2c1ac9b10ee2
Fixes: 36075582
Test: FrameworkServicesTest & manually verified file is populated
(cherry picked from commit 579e5581d5339dbdc79b9176fcc2fad660d155db)
diff --git a/services/core/java/com/android/server/storage/AppCollector.java b/services/core/java/com/android/server/storage/AppCollector.java
index 25880fb..a77d33f 100644
--- a/services/core/java/com/android/server/storage/AppCollector.java
+++ b/services/core/java/com/android/server/storage/AppCollector.java
@@ -116,33 +116,33 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_START_LOADING_SIZES: {
-                    final List<ApplicationInfo> apps = mPm.getInstalledApplications(
-                            PackageManager.GET_UNINSTALLED_PACKAGES
-                                    | PackageManager.GET_DISABLED_COMPONENTS);
-
-                    final List<ApplicationInfo> volumeApps = new ArrayList<>();
-                    for (ApplicationInfo app : apps) {
-                        if (Objects.equals(app.volumeUuid, mVolume.getFsUuid())) {
-                            volumeApps.add(app);
-                        }
-                    }
-
-                    List<UserInfo> users = mUm.getUsers();
-                    final int count = users.size() * volumeApps.size();
-                    if (count == 0) {
-                        mStats.complete(new ArrayList<>());
-                    }
-
                     List<PackageStats> stats = new ArrayList<>();
-                    for (UserInfo user : users) {
-                        for (ApplicationInfo app : volumeApps) {
-                            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);
+                    List<UserInfo> users = mUm.getUsers();
+                    for (int userCount = 0, userSize = users.size();
+                            userCount < userSize; userCount++) {
+                        UserInfo user = users.get(userCount);
+                        final List<ApplicationInfo> apps = mPm.getInstalledApplicationsAsUser(
+                                PackageManager.MATCH_DISABLED_COMPONENTS, user.id);
+
+                        for (int appCount = 0, size = apps.size(); appCount < size; appCount++) {
+                            ApplicationInfo app = apps.get(appCount);
+                            if (!Objects.equals(app.volumeUuid, mVolume.getFsUuid())) {
+                                continue;
+                            }
+
+                            try {
+                                StorageStats storageStats =
+                                        mStorageStatsManager.queryStatsForPackage(app.volumeUuid,
+                                                app.packageName, user.getUserHandle());
+                                PackageStats packageStats = new PackageStats(app.packageName,
+                                        user.id);
+                                packageStats.cacheSize = storageStats.getCacheBytes();
+                                packageStats.codeSize = storageStats.getCodeBytes();
+                                packageStats.dataSize = storageStats.getDataBytes();
+                                stats.add(packageStats);
+                            } catch (IllegalStateException e) {
+                                Log.e(TAG, "An exception occurred while fetching app size", e);
+                            }
                         }
                     }
 
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 8cf7c8a..3cdf109 100644
--- a/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java
@@ -28,6 +28,9 @@
 import android.os.UserManager;
 import android.os.storage.VolumeInfo;
 import android.test.AndroidTestCase;
+import android.util.ArrayMap;
+import android.util.Log;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -40,12 +43,14 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 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;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.when;
@@ -57,24 +62,29 @@
     @Mock private PackageManager mPm;
     @Mock private UserManager mUm;
     @Mock private StorageStatsManager mSsm;
-    private List<ApplicationInfo> mApps;
     private List<UserInfo> mUsers;
+    private Map<Integer, List<ApplicationInfo>> mUserApps;
 
     @Before
     public void setUp() throws Exception {
         super.setUp();
         MockitoAnnotations.initMocks(this);
-        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);
+        doAnswer((InvocationOnMock invocation) -> {
+            Integer userId = (Integer) invocation.getArguments()[1];
+            return mUserApps.get(userId);
+        }).when(mPm).getInstalledApplicationsAsUser(anyInt(), anyInt());
 
         // Set up the user list with a single user (0).
         mUsers = new ArrayList<>();
         mUsers.add(new UserInfo(0, "", 0));
+
+        mUserApps = new ArrayMap<>();
+        mUserApps.put(0, new ArrayList<>());
         when(mUm.getUsers()).thenReturn(mUsers);
     }
 
@@ -89,7 +99,7 @@
 
     @Test
     public void testAppOnExternalVolume() throws Exception {
-        addApplication("com.test.app", "differentuuid");
+        addApplication("com.test.app", "differentuuid", 0);
         VolumeInfo volume = new VolumeInfo("testuuid", 0, null, null);
         volume.fsUuid = "testuuid";
         AppCollector collector = new AppCollector(mContext, volume);
@@ -99,7 +109,7 @@
 
     @Test
     public void testOneValidApp() throws Exception {
-        addApplication("com.test.app", "testuuid");
+        addApplication("com.test.app", "testuuid", 0);
         VolumeInfo volume = new VolumeInfo("testuuid", 0, null, null);
         volume.fsUuid = "testuuid";
         AppCollector collector = new AppCollector(mContext, volume);
@@ -112,11 +122,9 @@
 
     @Test
     public void testMultipleUsersOneApp() throws Exception {
-        addApplication("com.test.app", "testuuid");
-        ApplicationInfo otherUsersApp = new ApplicationInfo();
-        otherUsersApp.packageName = "com.test.app";
-        otherUsersApp.volumeUuid = "testuuid";
-        otherUsersApp.uid = 1;
+        addApplication("com.test.app", "testuuid", 0);
+        mUserApps.put(1, new ArrayList<>());
+        addApplication("com.test.app", "testuuid", 1);
         mUsers.add(new UserInfo(1, "", 0));
 
         VolumeInfo volume = new VolumeInfo("testuuid", 0, null, null);
@@ -138,11 +146,28 @@
         AppCollector collector = new AppCollector(mContext, null);
     }
 
-    private void addApplication(String packageName, String uuid) {
+    @Test
+    public void testAppNotFoundDoesntCauseCrash() throws Exception {
+        VolumeInfo volume = new VolumeInfo("testuuid", 0, null, null);
+        addApplication("com.test.app", "uuid", 0);
+        mUsers.add(new UserInfo(1, "", 0));
+        mUserApps.put(1, new ArrayList<>());
+        AppCollector collector = new AppCollector(mContext, volume);
+        when(mSsm.queryStatsForPackage(anyString(), anyString(), any(UserHandle.class))).thenThrow(
+                new IllegalStateException());
+
+        assertThat(collector.getPackageStats(TIMEOUT)).isEmpty();
+    }
+
+    private void addApplication(String packageName, String uuid, int userId) {
         ApplicationInfo info = new ApplicationInfo();
         info.packageName = packageName;
         info.volumeUuid = uuid;
-        mApps.add(info);
+        List<ApplicationInfo> userApps = mUserApps.get(userId);
+        if (userApps == null) {
+            userApps = new ArrayList<>();
+            mUserApps.put(userId, userApps);
+        }
+        userApps.add(info);
     }
-
 }