Merge "ActivityThread: Preserve windows when relaunching all activities" into qt-dev
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index aa35a6f..0260faa 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -28,6 +28,8 @@
import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX;
import static android.view.Display.INVALID_DISPLAY;
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
@@ -4608,7 +4610,7 @@
private void onCoreSettingsChange() {
if (updateDebugViewAttributeState()) {
// request all activities to relaunch for the changes to take place
- relaunchAllActivities();
+ relaunchAllActivities(false /* preserveWindows */);
}
}
@@ -4625,10 +4627,13 @@
return previousState != View.sDebugViewAttributes;
}
- private void relaunchAllActivities() {
+ private void relaunchAllActivities(boolean preserveWindows) {
for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
- final Activity activity = entry.getValue().activity;
- if (!activity.mFinished) {
+ final ActivityClientRecord r = entry.getValue();
+ if (!r.activity.mFinished) {
+ if (preserveWindows && r.window != null) {
+ r.mPreserveWindow = true;
+ }
scheduleRelaunchActivity(entry.getKey());
}
}
@@ -5461,7 +5466,8 @@
}
}
- void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {
+ @VisibleForTesting(visibility = PACKAGE)
+ public void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {
// Updates triggered by package installation go through a package update
// receiver. Here we try to capture ApplicationInfo changes that are
// caused by other sources, such as overlays. That means we want to be as conservative
@@ -5507,7 +5513,8 @@
newConfig.assetsSeq = (mConfiguration != null ? mConfiguration.assetsSeq : 0) + 1;
handleConfigurationChanged(newConfig, null);
- relaunchAllActivities();
+ // Preserve windows to avoid black flickers when overlays change.
+ relaunchAllActivities(true /* preserveWindows */);
}
static void freeTextLayoutCachesIfNeeded(int configDiff) {
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 9cb3489..711eaa7 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -38,6 +38,7 @@
import android.os.IBinder;
import android.util.MergedConfiguration;
import android.view.Display;
+import android.view.View;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
@@ -153,6 +154,34 @@
}
@Test
+ public void testHandleActivity_assetsChanged() {
+ final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
+
+ final IBinder[] token = new IBinder[1];
+ final View[] decorView = new View[1];
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ final ActivityThread activityThread = activity.getActivityThread();
+
+ token[0] = activity.getActivityToken();
+ decorView[0] = activity.getWindow().getDecorView();
+
+ // Relaunches all activities
+ activityThread.handleApplicationInfoChanged(activity.getApplicationInfo());
+ });
+
+ final View[] newDecorView = new View[1];
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ final ActivityThread activityThread = activity.getActivityThread();
+
+ final Activity newActivity = activityThread.getActivity(token[0]);
+ newDecorView[0] = activity.getWindow().getDecorView();
+ });
+
+ assertEquals("Window must be preserved", decorView[0], newDecorView[0]);
+ }
+
+ @Test
public void testHandleActivityConfigurationChanged_DropStaleConfigurations() {
final TestActivity activity = mActivityTestRule.launchActivity(new Intent());