diff options
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 19 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/app/activity/ActivityThreadTest.java | 29 |
2 files changed, 42 insertions, 6 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index aa35a6feb5ff..0260faae4567 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_COLUMNS; 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 @@ public final class ActivityThread extends ClientTransactionHandler { private void onCoreSettingsChange() { if (updateDebugViewAttributeState()) { // request all activities to relaunch for the changes to take place - relaunchAllActivities(); + relaunchAllActivities(false /* preserveWindows */); } } @@ -4625,10 +4627,13 @@ public final class ActivityThread extends ClientTransactionHandler { 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 @@ public final class ActivityThread extends ClientTransactionHandler { } } - 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 @@ public final class ActivityThread extends ClientTransactionHandler { 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 9cb34895dea4..711eaa7edc2a 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.content.res.Configuration; 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 @@ public class ActivityThreadTest { } @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()); |