diff options
author | Yurii Zubrytskyi <zyy@google.com> | 2023-11-01 19:05:46 -0700 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-11-16 18:44:22 +0000 |
commit | f6e816f08ee45c71435c26f3656e4c488656e90f (patch) | |
tree | 1855b7d19ce7ec3274d35b8759bbd9319196527f | |
parent | 5d204d1ca15bca69bd0003176d2fbf4e435204cc (diff) | |
download | base-f6e816f08ee45c71435c26f3656e4c488656e90f.tar.gz |
Runtime: fix the theme colors on device reset
When launching an activity we may handle the launch
before applying the application info update that carries
new overlay paths for the app. In this case the activity
will have enough time to load the resources with no
overlays applied, and use e.g. wrong accent colors.
This change makes sure we apply pending application info
updates on any activity launch, and that the resource
paths are up to date on the very first Resources object
creation.
Bug: 299064578
Test: manual, factory reset for 8a, 10x
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:7230cdf9d79e634a03eb126f89d0bf2591dccb8a)
Merged-In: I501d9ce39f6e0437484632c85bf2773fe4a16474
Change-Id: I501d9ce39f6e0437484632c85bf2773fe4a16474
-rw-r--r-- | core/java/android/app/ActivityThread.java | 49 | ||||
-rw-r--r-- | core/java/android/app/LoadedApk.java | 13 |
2 files changed, 56 insertions, 6 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index f4caef0f2553..016d7214bda9 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -359,6 +359,15 @@ public final class ActivityThread extends ClientTransactionHandler /** Maps from activity token to the pending override configuration. */ @GuardedBy("mPendingOverrideConfigs") private final ArrayMap<IBinder, Configuration> mPendingOverrideConfigs = new ArrayMap<>(); + + /** + * A queue of pending ApplicationInfo updates. In case when we get a concurrent update + * this queue allows us to only apply the latest object, and it can be applied on demand + * instead of waiting for the handler thread to reach the scheduled callback. + */ + @GuardedBy("mResourcesManager") + private final ArrayMap<String, ApplicationInfo> mPendingAppInfoUpdates = new ArrayMap<>(); + /** The activities to be truly destroyed (not include relaunch). */ final Map<IBinder, ClientTransactionItem> mActivitiesToBeDestroyed = Collections.synchronizedMap(new ArrayMap<IBinder, ClientTransactionItem>()); @@ -1260,9 +1269,19 @@ public final class ActivityThread extends ClientTransactionHandler } public void scheduleApplicationInfoChanged(ApplicationInfo ai) { + synchronized (mResourcesManager) { + var oldAi = mPendingAppInfoUpdates.put(ai.packageName, ai); + if (oldAi != null && oldAi.createTimestamp > ai.createTimestamp) { + Slog.w(TAG, "Skipping application info changed for obsolete AI with TS " + + ai.createTimestamp + " < already pending TS " + + oldAi.createTimestamp); + mPendingAppInfoUpdates.put(ai.packageName, oldAi); + return; + } + } mResourcesManager.appendPendingAppInfoUpdate(new String[]{ai.sourceDir}, ai); - mH.removeMessages(H.APPLICATION_INFO_CHANGED, ai); - sendMessage(H.APPLICATION_INFO_CHANGED, ai); + mH.removeMessages(H.APPLICATION_INFO_CHANGED, ai.packageName); + sendMessage(H.APPLICATION_INFO_CHANGED, ai.packageName); } public void updateTimeZone() { @@ -2437,7 +2456,7 @@ public final class ActivityThread extends ClientTransactionHandler break; } case APPLICATION_INFO_CHANGED: - handleApplicationInfoChanged((ApplicationInfo) msg.obj); + applyPendingApplicationInfoChanges((String) msg.obj); break; case RUN_ISOLATED_ENTRY_POINT: handleRunIsolatedEntryPoint((String) ((SomeArgs) msg.obj).arg1, @@ -3922,7 +3941,8 @@ public final class ActivityThread extends ClientTransactionHandler mProfiler.startProfiling(); } - // Make sure we are running with the most recent config. + // Make sure we are running with the most recent config and resource paths. + applyPendingApplicationInfoChanges(r.activityInfo.packageName); mConfigurationController.handleConfigurationChanged(null, null); updateDeviceIdForNonUIContexts(deviceId); @@ -6248,6 +6268,17 @@ public final class ActivityThread extends ClientTransactionHandler r.mLastReportedWindowingMode = newWindowingMode; } + private void applyPendingApplicationInfoChanges(String packageName) { + final ApplicationInfo ai; + synchronized (mResourcesManager) { + ai = mPendingAppInfoUpdates.remove(packageName); + } + if (ai == null) { + return; + } + handleApplicationInfoChanged(ai); + } + /** * Updates the application info. * @@ -6273,6 +6304,16 @@ public final class ActivityThread extends ClientTransactionHandler apk = ref != null ? ref.get() : null; ref = mResourcePackages.get(ai.packageName); resApk = ref != null ? ref.get() : null; + for (ActivityClientRecord ar : mActivities.values()) { + if (ar.activityInfo.applicationInfo.packageName.equals(ai.packageName)) { + ar.activityInfo.applicationInfo = ai; + if (apk != null || resApk != null) { + ar.packageInfo = apk != null ? apk : resApk; + } else { + apk = ar.packageInfo; + } + } + } } if (apk != null) { diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index b5efb73225d6..f092ce2363aa 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -343,7 +343,9 @@ public final class LoadedApk { */ public void updateApplicationInfo(@NonNull ApplicationInfo aInfo, @Nullable List<String> oldPaths) { - setApplicationInfo(aInfo); + if (!setApplicationInfo(aInfo)) { + return; + } final List<String> newPaths = new ArrayList<>(); makePaths(mActivityThread, aInfo, newPaths); @@ -388,7 +390,13 @@ public final class LoadedApk { mAppComponentFactory = createAppFactory(aInfo, mDefaultClassLoader); } - private void setApplicationInfo(ApplicationInfo aInfo) { + private boolean setApplicationInfo(ApplicationInfo aInfo) { + if (mApplicationInfo != null && mApplicationInfo.createTimestamp > aInfo.createTimestamp) { + Slog.w(TAG, "New application info for package " + aInfo.packageName + + " is out of date with TS " + aInfo.createTimestamp + " < the current TS " + + mApplicationInfo.createTimestamp); + return false; + } final int myUid = Process.myUid(); aInfo = adjustNativeLibraryPaths(aInfo); mApplicationInfo = aInfo; @@ -411,6 +419,7 @@ public final class LoadedApk { if (aInfo.requestsIsolatedSplitLoading() && !ArrayUtils.isEmpty(mSplitNames)) { mSplitLoader = new SplitDependencyLoaderImpl(aInfo.splitDependencies); } + return true; } void setSdkSandboxStorage(@Nullable String sdkSandboxClientAppVolumeUuid, |