From 8c3b7511abb7946fa8a867f32d84ac7558ef82c1 Mon Sep 17 00:00:00 2001 From: Andrii Kulian Date: Fri, 23 Jul 2021 17:17:09 -0700 Subject: [PATCH] Notify split controller about activity configuration change Track activity configuration changes, so that split controller has a chance to apply metrics-based rules like launching a placeholder. Not using ComponentCallbacks here, since they are only triggered for Application configuration changes, which might be problematic if there are multiple running activities with different sizes. They are also usually triggered before individual activity resources are updated. Also moved post-creation actions to onActivityPostCreated(), since onActivityCreated() is called from the base implementation in Activity#onCreate() and there is still a chance that app may perform some actions after calling super in its override. Bug: 194538838 Test: Configure a placeholder, launch in a small size, enlarge. Change-Id: Ied55d5f920890fa554cdd66419235d61ab03b440 --- core/java/android/app/Activity.java | 13 +++++++++++ core/java/android/app/Application.java | 17 ++++++++++++++ .../extensions/organizer/SplitController.java | 23 +++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index db5dcc5c264bd..643020a7dbd26 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -1539,6 +1539,17 @@ public class Activity extends ContextThemeWrapper getApplication().dispatchActivityPostDestroyed(this); } + private void dispatchActivityConfigurationChanged() { + getApplication().dispatchActivityConfigurationChanged(this); + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((Application.ActivityLifecycleCallbacks) callbacks[i]) + .onActivityConfigurationChanged(this); + } + } + } + private Object[] collectActivityLifecycleCallbacks() { Object[] callbacks = null; synchronized (mActivityLifecycleCallbacks) { @@ -3028,6 +3039,8 @@ public class Activity extends ContextThemeWrapper // view changes from above. mActionBar.onConfigurationChanged(newConfig); } + + dispatchActivityConfigurationChanged(); } /** diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java index 618eda8c84e89..a1eab6553cff0 100644 --- a/core/java/android/app/Application.java +++ b/core/java/android/app/Application.java @@ -205,6 +205,13 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { */ default void onActivityPostDestroyed(@NonNull Activity activity) { } + + /** + * Called when the Activity configuration was changed. + * @hide + */ + default void onActivityConfigurationChanged(@NonNull Activity activity) { + } } /** @@ -554,6 +561,16 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { } } + /* package */ void dispatchActivityConfigurationChanged(@NonNull Activity activity) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityConfigurationChanged( + activity); + } + } + } + @UnsupportedAppUsage private Object[] collectActivityLifecycleCallbacks() { Object[] callbacks = null; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java index 7298d34977704..ca04eae242c1a 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java @@ -213,6 +213,20 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen updateCallbackIfNecessary(); } + private void onActivityConfigurationChanged(@NonNull Activity activity) { + final TaskFragmentContainer currentContainer = getContainerWithActivity( + activity.getActivityToken()); + + if (currentContainer != null) { + // Changes to activities in controllers are handled in + // onTaskFragmentParentInfoChanged + return; + } + + // Check if activity requires a placeholder + launchPlaceholderIfNecessary(activity); + } + /** * Returns a container that this activity is registered with. An activity can only belong to one * container, or no container at all. @@ -546,6 +560,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + } + + @Override + public void onActivityPostCreated(Activity activity, Bundle savedInstanceState) { // Calling after Activity#onCreate is complete to allow the app launch something // first. In case of a configured placeholder activity we want to make sure // that we don't launch it if an activity itself already requested something to be @@ -576,5 +594,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen @Override public void onActivityDestroyed(Activity activity) { } + + @Override + public void onActivityConfigurationChanged(Activity activity) { + SplitController.this.onActivityConfigurationChanged(activity); + } } }