diff options
| author | 2022-01-24 19:01:51 +0000 | |
|---|---|---|
| committer | 2022-01-24 19:01:51 +0000 | |
| commit | 615951d16e38440120dcda924aeb2ba8f71fe19c (patch) | |
| tree | a45e515dfdc58e6a9a8a5aebee65b876e4daecbb | |
| parent | dcd02645845f4b174ecd0892010eaed0728e3e27 (diff) | |
| parent | 18005c149684642b5fbc0979201e31a1708eecd8 (diff) | |
Merge "Add a check to detect "duplicate app instances" bug"
| -rw-r--r-- | core/java/android/app/Application.java | 50 | ||||
| -rw-r--r-- | core/java/android/app/StackTrace.java | 4 |
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); + } } |