Don't crash when primary volume is null in AppCollector.

getPrimaryStorageCurrentVolume() may return a null value. I did
not plan for this case in the AppCollector. This case occurs when
the primary storage is not mounted when the function is called.

By adding in a null check after getPrimaryStorageCurrentVolume()
and adding in preconditions to verify the non-nullness of the
volume as it propagates through the AppCollector, we ensure that
there should be no more NPE crashes for this reason.

Bug: 35636901
Test: FrameworkServicesTests
Change-Id: I4009e55502f71b8f14dd917ddd00caef3551aafd
(cherry picked from commit d54f3a487bba1dc5008e2e1482ef451a59500752)
diff --git a/services/core/java/com/android/server/storage/AppCollector.java b/services/core/java/com/android/server/storage/AppCollector.java
index cf05e9f..ee9c5bf 100644
--- a/services/core/java/com/android/server/storage/AppCollector.java
+++ b/services/core/java/com/android/server/storage/AppCollector.java
@@ -16,6 +16,7 @@
 
 package com.android.server.storage;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageStatsObserver;
@@ -32,6 +33,7 @@
 import android.os.storage.VolumeInfo;
 import android.util.Log;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -56,7 +58,9 @@
      * @param context Android context used to get
      * @param volume Volume to check for apps.
      */
-    public AppCollector(Context context, VolumeInfo volume) {
+    public AppCollector(Context context, @NonNull VolumeInfo volume) {
+        Preconditions.checkNotNull(volume);
+
         mBackgroundHandler = new BackgroundHandler(BackgroundThread.get().getLooper(),
                 volume,
                 context.getPackageManager(),
@@ -117,7 +121,7 @@
         private final PackageManager mPm;
         private final UserManager mUm;
 
-        BackgroundHandler(Looper looper, VolumeInfo volume, PackageManager pm, UserManager um) {
+        BackgroundHandler(Looper looper, @NonNull VolumeInfo volume, PackageManager pm, UserManager um) {
             super(looper);
             mVolume = volume;
             mPm = pm;
diff --git a/services/core/java/com/android/server/storage/DiskStatsLoggingService.java b/services/core/java/com/android/server/storage/DiskStatsLoggingService.java
index 7c43162..4035ade 100644
--- a/services/core/java/com/android/server/storage/DiskStatsLoggingService.java
+++ b/services/core/java/com/android/server/storage/DiskStatsLoggingService.java
@@ -29,6 +29,7 @@
 import android.os.Environment;
 import android.os.Environment.UserEnvironment;
 import android.os.UserHandle;
+import android.os.storage.VolumeInfo;
 import android.provider.Settings;
 import android.util.Log;
 
@@ -61,10 +62,16 @@
             return false;
         }
 
+
+        VolumeInfo volume = getPackageManager().getPrimaryStorageCurrentVolume();
+        // volume is null if the primary storage is not yet mounted.
+        if (volume == null) {
+            return false;
+        }
+        AppCollector collector = new AppCollector(this, volume);
+
         final int userId = UserHandle.myUserId();
         UserEnvironment environment = new UserEnvironment(userId);
-        AppCollector collector = new AppCollector(this,
-                getPackageManager().getPrimaryStorageCurrentVolume());
         LogRunnable task = new LogRunnable();
         task.setRootDirectory(environment.getExternalStorageDirectory());
         task.setDownloadsDirectory(
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 da22e77..29185e9 100644
--- a/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java
@@ -187,10 +187,14 @@
         }).start();
         latch.await();
 
-        // This should
         assertThat(myStats).containsAllOf(stats, otherStats);
     }
 
+    @Test(expected=NullPointerException.class)
+    public void testNullVolumeShouldCauseNPE() throws Exception {
+        AppCollector collector = new AppCollector(mContext, null);
+    }
+
     private void addApplication(String packageName, String uuid) {
         ApplicationInfo info = new ApplicationInfo();
         info.packageName = packageName;