summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Makoto Onuki <omakoto@google.com> 2022-01-24 19:01:51 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-01-24 19:01:51 +0000
commit615951d16e38440120dcda924aeb2ba8f71fe19c (patch)
treea45e515dfdc58e6a9a8a5aebee65b876e4daecbb
parentdcd02645845f4b174ecd0892010eaed0728e3e27 (diff)
parent18005c149684642b5fbc0979201e31a1708eecd8 (diff)
Merge "Add a check to detect "duplicate app instances" bug"
-rw-r--r--core/java/android/app/Application.java50
-rw-r--r--core/java/android/app/StackTrace.java4
2 files changed, 54 insertions, 0 deletions
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 7f849ef00d7d..9eb3e8fb0160 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -29,9 +29,13 @@ import android.content.Intent;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
+import android.util.ArrayMap;
import android.util.Log;
+import android.util.Slog;
import android.view.autofill.AutofillManager;
+import com.android.internal.annotations.GuardedBy;
+
import java.util.ArrayList;
/**
@@ -53,6 +57,10 @@ import java.util.ArrayList;
*/
public class Application extends ContextWrapper implements ComponentCallbacks2 {
private static final String TAG = "Application";
+
+ /** Whether to enable the check to detect "duplicate application instances". */
+ private static final boolean DEBUG_DUP_APP_INSTANCES = true;
+
@UnsupportedAppUsage
private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
new ArrayList<ActivityLifecycleCallbacks>();
@@ -66,6 +74,13 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 {
@UnsupportedAppUsage
public LoadedApk mLoadedApk;
+ @GuardedBy("sInstances")
+ private static final ArrayMap<Class<?>, Application> sInstances =
+ DEBUG_DUP_APP_INSTANCES ? new ArrayMap<>(1) : null;
+
+ // Only set when DEBUG_DUP_APP_INSTANCES is true.
+ private StackTrace mConstructorStackTrace;
+
public interface ActivityLifecycleCallbacks {
/**
@@ -231,6 +246,41 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 {
public Application() {
super(null);
+ if (DEBUG_DUP_APP_INSTANCES) {
+ checkDuplicateInstances();
+ }
+ }
+
+ private void checkDuplicateInstances() {
+ final Class<?> myClass = this.getClass();
+
+ // We only activate this check for custom application classes.
+ // Otherwise, it'd misfire if multiple apps share the same process, if all of them use
+ // the same Application class (on the same classloader).
+ if (myClass == Application.class) {
+ return;
+ }
+ synchronized (sInstances) {
+ final Application firstInstance = sInstances.get(myClass);
+ if (firstInstance == null) {
+ this.mConstructorStackTrace = new StackTrace("First ctor was called here");
+ sInstances.put(myClass, this);
+ return;
+ }
+ final StackTrace currentStackTrace = new StackTrace("Current ctor was called here",
+ firstInstance.mConstructorStackTrace);
+ this.mConstructorStackTrace = currentStackTrace;
+ Slog.wtf(TAG, "Application ctor called twice for " + myClass
+ + " first LoadedApk=" + firstInstance.getLoadedApkInfo(),
+ currentStackTrace);
+ }
+ }
+
+ private String getLoadedApkInfo() {
+ if (mLoadedApk == null) {
+ return "null";
+ }
+ return mLoadedApk + "/pkg=" + mLoadedApk.mPackageName;
}
/**
diff --git a/core/java/android/app/StackTrace.java b/core/java/android/app/StackTrace.java
index ec058f88118b..6a77abdefea9 100644
--- a/core/java/android/app/StackTrace.java
+++ b/core/java/android/app/StackTrace.java
@@ -24,4 +24,8 @@ public class StackTrace extends Exception {
public StackTrace(String message) {
super(message);
}
+
+ public StackTrace(String message, Throwable innerStackTrace) {
+ super(message, innerStackTrace);
+ }
}