Loading core/java/android/app/Application.java +50 −0 Original line number Diff line number Diff line Loading @@ -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; /** Loading @@ -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>(); Loading @@ -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 { /** Loading Loading @@ -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; } /** Loading core/java/android/app/StackTrace.java +4 −0 Original line number Diff line number Diff line Loading @@ -24,4 +24,8 @@ public class StackTrace extends Exception { public StackTrace(String message) { super(message); } public StackTrace(String message, Throwable innerStackTrace) { super(message, innerStackTrace); } } Loading
core/java/android/app/Application.java +50 −0 Original line number Diff line number Diff line Loading @@ -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; /** Loading @@ -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>(); Loading @@ -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 { /** Loading Loading @@ -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; } /** Loading
core/java/android/app/StackTrace.java +4 −0 Original line number Diff line number Diff line Loading @@ -24,4 +24,8 @@ public class StackTrace extends Exception { public StackTrace(String message) { super(message); } public StackTrace(String message, Throwable innerStackTrace) { super(message, innerStackTrace); } }