Do not always report configuration change to activity
Activity that does not handle any of the configuration changes was not relaunched when only changing its size and without cross the size threshold, see ActivityRecord#crossesSizeThreshold(), but the new configuration would still be scheduled to the client. In that case, Activity#onConfigurationChanged() was called when ActivityConfigurationChangeItem executed, because it requested to always report to the activity. This was wrong since the activity didn't request to handle any of the configuration changes. On the other hand, if configuration change sent from view root came earlier than ActivityConfigurationChangeItem, the new configuration change did not propagate to ResourcesManager. Allow the new configuration changes propagate to ResourcesManager and report to activity only if the activity has been declared to handle. Bug: 155589510 Test: atest AppConfigurationTests Change-Id: If7dd769098a9f06efafda0250bfce71c6c96fb49
This commit is contained in:
@@ -604,11 +604,8 @@ public final class ActivityThread extends ClientTransactionHandler {
|
|||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Received config update for non-existing activity");
|
"Received config update for non-existing activity");
|
||||||
}
|
}
|
||||||
// Given alwaysReportChange=false because the configuration is from view root, the
|
|
||||||
// activity may not be able to handle the changes. In that case the activity will be
|
|
||||||
// relaunched immediately, then Activity#onConfigurationChanged shouldn't be called.
|
|
||||||
activity.mMainThread.handleActivityConfigurationChanged(token, overrideConfig,
|
activity.mMainThread.handleActivityConfigurationChanged(token, overrideConfig,
|
||||||
newDisplayId, false /* alwaysReportChange */);
|
newDisplayId);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4520,8 +4517,7 @@ public final class ActivityThread extends ClientTransactionHandler {
|
|||||||
// simply finishing, and we are not starting another activity.
|
// simply finishing, and we are not starting another activity.
|
||||||
if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
|
if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
|
||||||
if (r.newConfig != null) {
|
if (r.newConfig != null) {
|
||||||
performConfigurationChangedForActivity(r, r.newConfig,
|
performConfigurationChangedForActivity(r, r.newConfig);
|
||||||
false /* alwaysReportChange */);
|
|
||||||
if (DEBUG_CONFIGURATION) {
|
if (DEBUG_CONFIGURATION) {
|
||||||
Slog.v(TAG, "Resuming activity " + r.activityInfo.name + " with newConfig "
|
Slog.v(TAG, "Resuming activity " + r.activityInfo.name + " with newConfig "
|
||||||
+ r.activity.mCurrentConfig);
|
+ r.activity.mCurrentConfig);
|
||||||
@@ -4841,8 +4837,7 @@ public final class ActivityThread extends ClientTransactionHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (r.newConfig != null) {
|
if (r.newConfig != null) {
|
||||||
performConfigurationChangedForActivity(r, r.newConfig,
|
performConfigurationChangedForActivity(r, r.newConfig);
|
||||||
false /* alwaysReportChange */);
|
|
||||||
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
|
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
|
||||||
+ r.activityInfo.name + " with new config "
|
+ r.activityInfo.name + " with new config "
|
||||||
+ r.activity.mCurrentConfig);
|
+ r.activity.mCurrentConfig);
|
||||||
@@ -5510,12 +5505,11 @@ public final class ActivityThread extends ClientTransactionHandler {
|
|||||||
* @param r ActivityClientRecord representing the Activity.
|
* @param r ActivityClientRecord representing the Activity.
|
||||||
* @param newBaseConfig The new configuration to use. This may be augmented with
|
* @param newBaseConfig The new configuration to use. This may be augmented with
|
||||||
* {@link ActivityClientRecord#overrideConfig}.
|
* {@link ActivityClientRecord#overrideConfig}.
|
||||||
* @param alwaysReportChange If the configuration is changed, always report to activity.
|
|
||||||
*/
|
*/
|
||||||
private void performConfigurationChangedForActivity(ActivityClientRecord r,
|
private void performConfigurationChangedForActivity(ActivityClientRecord r,
|
||||||
Configuration newBaseConfig, boolean alwaysReportChange) {
|
Configuration newBaseConfig) {
|
||||||
performConfigurationChangedForActivity(r, newBaseConfig, r.activity.getDisplayId(),
|
performConfigurationChangedForActivity(r, newBaseConfig, r.activity.getDisplayId(),
|
||||||
false /* movedToDifferentDisplay */, alwaysReportChange);
|
false /* movedToDifferentDisplay */);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -5528,19 +5522,16 @@ public final class ActivityThread extends ClientTransactionHandler {
|
|||||||
* {@link ActivityClientRecord#overrideConfig}.
|
* {@link ActivityClientRecord#overrideConfig}.
|
||||||
* @param displayId The id of the display where the Activity currently resides.
|
* @param displayId The id of the display where the Activity currently resides.
|
||||||
* @param movedToDifferentDisplay Indicates if the activity was moved to different display.
|
* @param movedToDifferentDisplay Indicates if the activity was moved to different display.
|
||||||
* @param alwaysReportChange If the configuration is changed, always report to activity.
|
|
||||||
* @return {@link Configuration} instance sent to client, null if not sent.
|
* @return {@link Configuration} instance sent to client, null if not sent.
|
||||||
*/
|
*/
|
||||||
private Configuration performConfigurationChangedForActivity(ActivityClientRecord r,
|
private Configuration performConfigurationChangedForActivity(ActivityClientRecord r,
|
||||||
Configuration newBaseConfig, int displayId, boolean movedToDifferentDisplay,
|
Configuration newBaseConfig, int displayId, boolean movedToDifferentDisplay) {
|
||||||
boolean alwaysReportChange) {
|
|
||||||
r.tmpConfig.setTo(newBaseConfig);
|
r.tmpConfig.setTo(newBaseConfig);
|
||||||
if (r.overrideConfig != null) {
|
if (r.overrideConfig != null) {
|
||||||
r.tmpConfig.updateFrom(r.overrideConfig);
|
r.tmpConfig.updateFrom(r.overrideConfig);
|
||||||
}
|
}
|
||||||
final Configuration reportedConfig = performActivityConfigurationChanged(r.activity,
|
final Configuration reportedConfig = performActivityConfigurationChanged(r.activity,
|
||||||
r.tmpConfig, r.overrideConfig, displayId, movedToDifferentDisplay,
|
r.tmpConfig, r.overrideConfig, displayId, movedToDifferentDisplay);
|
||||||
alwaysReportChange);
|
|
||||||
freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
|
freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
|
||||||
return reportedConfig;
|
return reportedConfig;
|
||||||
}
|
}
|
||||||
@@ -5596,12 +5587,11 @@ public final class ActivityThread extends ClientTransactionHandler {
|
|||||||
* ActivityManager.
|
* ActivityManager.
|
||||||
* @param displayId Id of the display where activity currently resides.
|
* @param displayId Id of the display where activity currently resides.
|
||||||
* @param movedToDifferentDisplay Indicates if the activity was moved to different display.
|
* @param movedToDifferentDisplay Indicates if the activity was moved to different display.
|
||||||
* @param alwaysReportChange If the configuration is changed, always report to activity.
|
|
||||||
* @return Configuration sent to client, null if no changes and not moved to different display.
|
* @return Configuration sent to client, null if no changes and not moved to different display.
|
||||||
*/
|
*/
|
||||||
private Configuration performActivityConfigurationChanged(Activity activity,
|
private Configuration performActivityConfigurationChanged(Activity activity,
|
||||||
Configuration newConfig, Configuration amOverrideConfig, int displayId,
|
Configuration newConfig, Configuration amOverrideConfig, int displayId,
|
||||||
boolean movedToDifferentDisplay, boolean alwaysReportChange) {
|
boolean movedToDifferentDisplay) {
|
||||||
if (activity == null) {
|
if (activity == null) {
|
||||||
throw new IllegalArgumentException("No activity provided.");
|
throw new IllegalArgumentException("No activity provided.");
|
||||||
}
|
}
|
||||||
@@ -5614,30 +5604,26 @@ public final class ActivityThread extends ClientTransactionHandler {
|
|||||||
// callback, see also PinnedStackTests#testConfigurationChangeOrderDuringTransition
|
// callback, see also PinnedStackTests#testConfigurationChangeOrderDuringTransition
|
||||||
handleWindowingModeChangeIfNeeded(activity, newConfig);
|
handleWindowingModeChangeIfNeeded(activity, newConfig);
|
||||||
|
|
||||||
boolean shouldChangeConfig = false;
|
boolean shouldReportChange = false;
|
||||||
if (activity.mCurrentConfig == null) {
|
if (activity.mCurrentConfig == null) {
|
||||||
shouldChangeConfig = true;
|
shouldReportChange = true;
|
||||||
} else {
|
} else {
|
||||||
// If the new config is the same as the config this Activity is already running with and
|
// If the new config is the same as the config this Activity is already running with and
|
||||||
// the override config also didn't change, then don't bother calling
|
// the override config also didn't change, then don't bother calling
|
||||||
// onConfigurationChanged.
|
// onConfigurationChanged.
|
||||||
final int diff = activity.mCurrentConfig.diffPublicOnly(newConfig);
|
final int diff = activity.mCurrentConfig.diffPublicOnly(newConfig);
|
||||||
|
if (diff == 0 && !movedToDifferentDisplay
|
||||||
if (diff != 0 || !mResourcesManager.isSameResourcesOverrideConfig(activityToken,
|
&& mResourcesManager.isSameResourcesOverrideConfig(activityToken,
|
||||||
amOverrideConfig)) {
|
amOverrideConfig)) {
|
||||||
// Always send the task-level config changes. For system-level configuration, if
|
|
||||||
// this activity doesn't handle any of the config changes, then don't bother
|
|
||||||
// calling onConfigurationChanged as we're going to destroy it.
|
|
||||||
if (alwaysReportChange
|
|
||||||
|| (~activity.mActivityInfo.getRealConfigChanged() & diff) == 0
|
|
||||||
|| !REPORT_TO_ACTIVITY) {
|
|
||||||
shouldChangeConfig = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!shouldChangeConfig && !movedToDifferentDisplay) {
|
|
||||||
// Nothing significant, don't proceed with updating and reporting.
|
// Nothing significant, don't proceed with updating and reporting.
|
||||||
return null;
|
return null;
|
||||||
|
} else if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0
|
||||||
|
|| !REPORT_TO_ACTIVITY) {
|
||||||
|
// If this activity doesn't handle any of the config changes, then don't bother
|
||||||
|
// calling onConfigurationChanged. Otherwise, report to the activity for the
|
||||||
|
// changes.
|
||||||
|
shouldReportChange = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Propagate the configuration change to ResourcesManager and Activity.
|
// Propagate the configuration change to ResourcesManager and Activity.
|
||||||
@@ -5675,7 +5661,7 @@ public final class ActivityThread extends ClientTransactionHandler {
|
|||||||
activity.dispatchMovedToDisplay(displayId, configToReport);
|
activity.dispatchMovedToDisplay(displayId, configToReport);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldChangeConfig) {
|
if (shouldReportChange) {
|
||||||
activity.mCalled = false;
|
activity.mCalled = false;
|
||||||
activity.onConfigurationChanged(configToReport);
|
activity.onConfigurationChanged(configToReport);
|
||||||
if (!activity.mCalled) {
|
if (!activity.mCalled) {
|
||||||
@@ -5792,7 +5778,7 @@ public final class ActivityThread extends ClientTransactionHandler {
|
|||||||
// config and avoid onConfigurationChanged if it hasn't changed.
|
// config and avoid onConfigurationChanged if it hasn't changed.
|
||||||
Activity a = (Activity) cb;
|
Activity a = (Activity) cb;
|
||||||
performConfigurationChangedForActivity(mActivities.get(a.getActivityToken()),
|
performConfigurationChangedForActivity(mActivities.get(a.getActivityToken()),
|
||||||
config, false /* alwaysReportChange */);
|
config);
|
||||||
} else if (!equivalent) {
|
} else if (!equivalent) {
|
||||||
performConfigurationChanged(cb, config);
|
performConfigurationChanged(cb, config);
|
||||||
} else {
|
} else {
|
||||||
@@ -5943,18 +5929,6 @@ public final class ActivityThread extends ClientTransactionHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handleActivityConfigurationChanged(IBinder activityToken,
|
|
||||||
@NonNull Configuration overrideConfig, int displayId) {
|
|
||||||
handleActivityConfigurationChanged(activityToken, overrideConfig, displayId,
|
|
||||||
// This is the only place that uses alwaysReportChange=true. The entry point should
|
|
||||||
// be from ActivityConfigurationChangeItem or MoveToDisplayItem, so the server side
|
|
||||||
// has confirmed the activity should handle the configuration instead of relaunch.
|
|
||||||
// If Activity#onConfigurationChanged is called unexpectedly, then we can know it is
|
|
||||||
// something wrong from server side.
|
|
||||||
true /* alwaysReportChange */);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle new activity configuration and/or move to a different display. This method is a noop
|
* Handle new activity configuration and/or move to a different display. This method is a noop
|
||||||
* if {@link #updatePendingActivityConfiguration(IBinder, Configuration)} has been called with
|
* if {@link #updatePendingActivityConfiguration(IBinder, Configuration)} has been called with
|
||||||
@@ -5964,10 +5938,10 @@ public final class ActivityThread extends ClientTransactionHandler {
|
|||||||
* @param overrideConfig Activity override config.
|
* @param overrideConfig Activity override config.
|
||||||
* @param displayId Id of the display where activity was moved to, -1 if there was no move and
|
* @param displayId Id of the display where activity was moved to, -1 if there was no move and
|
||||||
* value didn't change.
|
* value didn't change.
|
||||||
* @param alwaysReportChange If the configuration is changed, always report to activity.
|
|
||||||
*/
|
*/
|
||||||
void handleActivityConfigurationChanged(IBinder activityToken,
|
@Override
|
||||||
@NonNull Configuration overrideConfig, int displayId, boolean alwaysReportChange) {
|
public void handleActivityConfigurationChanged(IBinder activityToken,
|
||||||
|
@NonNull Configuration overrideConfig, int displayId) {
|
||||||
ActivityClientRecord r = mActivities.get(activityToken);
|
ActivityClientRecord r = mActivities.get(activityToken);
|
||||||
// Check input params.
|
// Check input params.
|
||||||
if (r == null || r.activity == null) {
|
if (r == null || r.activity == null) {
|
||||||
@@ -6010,15 +5984,14 @@ public final class ActivityThread extends ClientTransactionHandler {
|
|||||||
+ ", config=" + overrideConfig);
|
+ ", config=" + overrideConfig);
|
||||||
|
|
||||||
final Configuration reportedConfig = performConfigurationChangedForActivity(r,
|
final Configuration reportedConfig = performConfigurationChangedForActivity(r,
|
||||||
mCompatConfiguration, displayId, true /* movedToDifferentDisplay */,
|
mCompatConfiguration, displayId, true /* movedToDifferentDisplay */);
|
||||||
alwaysReportChange);
|
|
||||||
if (viewRoot != null) {
|
if (viewRoot != null) {
|
||||||
viewRoot.onMovedToDisplay(displayId, reportedConfig);
|
viewRoot.onMovedToDisplay(displayId, reportedConfig);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
|
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
|
||||||
+ r.activityInfo.name + ", config=" + overrideConfig);
|
+ r.activityInfo.name + ", config=" + overrideConfig);
|
||||||
performConfigurationChangedForActivity(r, mCompatConfiguration, alwaysReportChange);
|
performConfigurationChangedForActivity(r, mCompatConfiguration);
|
||||||
}
|
}
|
||||||
// Notify the ViewRootImpl instance about configuration changes. It may have initiated this
|
// Notify the ViewRootImpl instance about configuration changes. It may have initiated this
|
||||||
// update to make sure that resources are updated before updating itself.
|
// update to make sure that resources are updated before updating itself.
|
||||||
|
|||||||
Reference in New Issue
Block a user