From 169aeafb2d97b810ae123ad036d0c58336961c55 Mon Sep 17 00:00:00 2001 From: Makoto Onuki Date: Wed, 9 Mar 2022 16:05:37 -0800 Subject: [PATCH] Fix compat issue with apps directly calling LoadedApk.makeApplication(). Unfortuantely, it seems apps may be calling makeApplication() directly, in which case returning the cached instance would break their expectation. So let's not return the cached instance for external callers. Test: Launch the kr.go.kdca.coov-19 app Fix: 222737976 Change-Id: Idd7d2873d71edad182a7877117745fe021e18a80 --- core/java/android/app/ActivityThread.java | 10 +++---- core/java/android/app/LoadedApk.java | 35 +++++++++++++++++++---- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 64f0301fab22b..b1a4e4148eec1 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3587,7 +3587,7 @@ public final class ActivityThread extends ClientTransactionHandler } try { - Application app = r.packageInfo.makeApplication(false, mInstrumentation); + Application app = r.packageInfo.makeApplicationInner(false, mInstrumentation); if (localLOGV) Slog.v(TAG, "Performing launch of " + r); if (localLOGV) Slog.v( @@ -4286,7 +4286,7 @@ public final class ActivityThread extends ClientTransactionHandler BroadcastReceiver receiver; ContextImpl context; try { - app = packageInfo.makeApplication(false, mInstrumentation); + app = packageInfo.makeApplicationInner(false, mInstrumentation); context = (ContextImpl) app.getBaseContext(); if (data.info.splitName != null) { context = (ContextImpl) context.createContextForSplit(data.info.splitName); @@ -4475,7 +4475,7 @@ public final class ActivityThread extends ClientTransactionHandler try { if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name); - Application app = packageInfo.makeApplication(false, mInstrumentation); + Application app = packageInfo.makeApplicationInner(false, mInstrumentation); final java.lang.ClassLoader cl; if (data.info.splitName != null) { @@ -6695,7 +6695,7 @@ public final class ActivityThread extends ClientTransactionHandler try { // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. - app = data.info.makeApplication(data.restrictedBackupMode, null); + app = data.info.makeApplicationInner(data.restrictedBackupMode, null); // Propagate autofill compat state app.setAutofillOptions(data.autofillOptions); @@ -7565,7 +7565,7 @@ public final class ActivityThread extends ClientTransactionHandler mInstrumentation.basicInit(this); ContextImpl context = ContextImpl.createAppContext( this, getSystemContext().mPackageInfo); - mInitialApplication = context.mPackageInfo.makeApplication(true, null); + mInitialApplication = context.mPackageInfo.makeApplicationInner(true, null); mInitialApplication.onCreate(); } catch (Exception e) { throw new RuntimeException( diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index cf259e577a5af..d35c5bebd3010 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -1352,9 +1352,28 @@ public final class LoadedApk { return mResources; } + /** + * This is for 3p apps accessing this hidden API directly... in which case, we don't return + * the cached Application instance. + */ @UnsupportedAppUsage public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { + return makeApplicationInner(forceDefaultAppClass, instrumentation, + /* allowDuplicateInstances= */ true); + } + + /** + * This is for all the (internal) callers, for which we do return the cached instance. + */ + public Application makeApplicationInner(boolean forceDefaultAppClass, + Instrumentation instrumentation) { + return makeApplicationInner(forceDefaultAppClass, instrumentation, + /* allowDuplicateInstances= */ false); + } + + private Application makeApplicationInner(boolean forceDefaultAppClass, + Instrumentation instrumentation, boolean allowDuplicateInstances) { if (mApplication != null) { return mApplication; } @@ -1366,11 +1385,15 @@ public final class LoadedApk { // 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 + Slog.wtfStack(TAG, "App instance already created for package=" + mPackageName + " instance=" + cached); } - mApplication = cached; - return cached; + if (!allowDuplicateInstances) { + mApplication = cached; + return cached; + } + // Some apps intentionally call makeApplication() to create a new Application + // instance... Sigh... } } @@ -1421,8 +1444,10 @@ public final class LoadedApk { } mActivityThread.mAllApplications.add(app); mApplication = app; - synchronized (sApplications) { - sApplications.put(mPackageName, app); + if (!allowDuplicateInstances) { + synchronized (sApplications) { + sApplications.put(mPackageName, app); + } } if (instrumentation != null) {