Ignore null package names on AppIdleHistory writes

AppIdleHistory will fail to persist to disk if a null package name makes
it into the map. This change avoids the failure and adds more detail to
the log in the event of a failure.

Test: atest AppIdleHistoryTests
Fixes: 122609407
Change-Id: I30115265a1b963a0d66bad4fe15c69907ee8e53c

Merged-In: Ifec5a14f488fdb425bdcfee6ffe1f48f9fa9d1e8
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
index 36504ac..4a13dce 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
@@ -28,7 +28,6 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.app.usage.UsageStatsManager;
 import android.os.FileUtils;
 import android.test.AndroidTestCase;
 
@@ -150,4 +149,21 @@
         aih = new AppIdleHistory(mStorageDir, 5000);
         assertEquals(REASON_MAIN_TIMEOUT, aih.getAppStandbyReason(PACKAGE_1, USER_ID, 5000));
     }
+
+    public void testNullPackage() throws Exception {
+        AppIdleHistory aih = new AppIdleHistory(mStorageDir, 1000);
+        // Report usage of a package
+        aih.reportUsage(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
+                REASON_SUB_USAGE_MOVE_TO_FOREGROUND, 2000, 0);
+        // "Accidentally" report usage against a null named package
+        aih.reportUsage(null, USER_ID, STANDBY_BUCKET_ACTIVE,
+                REASON_SUB_USAGE_MOVE_TO_FOREGROUND, 2000, 0);
+        // Persist data
+        aih.writeAppIdleTimes(USER_ID);
+        // Recover data from disk
+        aih = new AppIdleHistory(mStorageDir, 5000);
+        // Verify data is intact
+        assertEquals(REASON_MAIN_USAGE | REASON_SUB_USAGE_MOVE_TO_FOREGROUND,
+                aih.getAppStandbyReason(PACKAGE_1, USER_ID, 3000));
+    }
 }
\ No newline at end of file
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index 1e4861a..82292cf 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -578,7 +578,7 @@
                 }
             }
         } catch (IOException | XmlPullParserException e) {
-            Slog.e(TAG, "Unable to read app idle file for user " + userId);
+            Slog.e(TAG, "Unable to read app idle file for user " + userId, e);
         } finally {
             IoUtils.closeQuietly(fis);
         }
@@ -608,6 +608,11 @@
             final int N = userHistory.size();
             for (int i = 0; i < N; i++) {
                 String packageName = userHistory.keyAt(i);
+                // Skip any unexpected null package names
+                if (packageName == null) {
+                    Slog.w(TAG, "Skipping App Idle write for unexpected null package");
+                    continue;
+                }
                 AppUsageHistory history = userHistory.valueAt(i);
                 xml.startTag(null, TAG_PACKAGE);
                 xml.attribute(null, ATTR_NAME, packageName);
@@ -641,7 +646,7 @@
             appIdleFile.finishWrite(fos);
         } catch (Exception e) {
             appIdleFile.failWrite(fos);
-            Slog.e(TAG, "Error writing app idle file for user " + userId);
+            Slog.e(TAG, "Error writing app idle file for user " + userId, e);
         }
     }