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
This commit is contained in:
Andrii Kulian
2021-07-23 17:17:09 -07:00
parent a22be8fb7e
commit 8c3b7511ab
3 changed files with 53 additions and 0 deletions

View File

@@ -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();
}
/**

View File

@@ -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;

View File

@@ -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);
}
}
}