Add checks to detect wrong conditions when creating Applications

Bug: 185177290
Test: Boot + monitor logcat
Change-Id: Icd9f5e891c7b7fe32ee4144d95dd26139b87d9cf
(cherry picked from commit 9b9ee9dc4b8465b351e58f6804f52379e26cb737)
Merged-In:Icd9f5e891c7b7fe32ee4144d95dd26139b87d9cf
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d90010e..7ac4bdd 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4535,6 +4535,12 @@
         // we are back active so skip it.
         unscheduleGcIdler();
 
+        // To investigate "duplciate Application objects" bug (b/185177290)
+        if (UserHandle.myUserId() != UserHandle.getUserId(data.info.applicationInfo.uid)) {
+            Slog.wtf(TAG, "handleCreateService called with wrong appinfo UID: myUserId="
+                    + UserHandle.myUserId() + " appinfo.uid=" + data.info.applicationInfo.uid);
+        }
+
         LoadedApk packageInfo = getPackageInfoNoCheck(
                 data.info.applicationInfo, data.compatInfo);
         Service service = null;
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 77af474..4e32e9a 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1341,15 +1341,43 @@
         return mResources;
     }
 
+    /**
+     * Used to investigate "duplicate app objects" bug (b/185177290).
+     * makeApplication() should only be called on the main thread, so no synchronization should
+     * be needed, but syncing anyway just in case.
+     */
+    @GuardedBy("sApplicationCache")
+    private static final ArrayMap<String, Application> sApplicationCache = new ArrayMap<>(4);
+
     @UnsupportedAppUsage
     public Application makeApplication(boolean forceDefaultAppClass,
             Instrumentation instrumentation) {
         if (mApplication != null) {
             return mApplication;
         }
-
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
 
+        // For b/185177290.
+        final boolean wrongUser =
+                UserHandle.myUserId() != UserHandle.getUserId(mApplicationInfo.uid);
+        if (wrongUser) {
+            Slog.wtf(TAG, "makeApplication called with wrong appinfo UID: myUserId="
+                    + UserHandle.myUserId() + " appinfo.uid=" + mApplicationInfo.uid);
+        }
+        synchronized (sApplicationCache) {
+            final Application cached = sApplicationCache.get(mPackageName);
+            if (cached != null) {
+                // Looks like this is always happening for the system server, because
+                // the LoadedApk created in systemMain() -> attach() isn't cached properly?
+                if (!"android".equals(mPackageName)) {
+                    Slog.wtf(TAG, "App instance already created for package=" + mPackageName
+                            + " instance=" + cached);
+                }
+                // TODO Return the cached one, unles it's for the wrong user?
+                // For now, we just add WTF checks.
+            }
+        }
+
         Application app = null;
 
         final String myProcessName = Process.myProcessName();
@@ -1397,6 +1425,9 @@
         }
         mActivityThread.mAllApplications.add(app);
         mApplication = app;
+        synchronized (sApplicationCache) {
+            sApplicationCache.put(mPackageName, app);
+        }
 
         if (instrumentation != null) {
             try {