Merge "Fix #testChangeFontScaleNoRelaunch flaky" into tm-dev am: 8c1fad0d74

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17197588

Change-Id: I6aac370b859a965962d906af5127096097d4d701
This commit is contained in:
Charles Chen
2022-03-21 09:00:53 +00:00
committed by Automerger Merge Worker
3 changed files with 87 additions and 8 deletions

View File

@@ -872,7 +872,7 @@ public class Activity extends ContextThemeWrapper
@UnsupportedAppUsage @UnsupportedAppUsage
/*package*/ int mConfigChangeFlags; /*package*/ int mConfigChangeFlags;
@UnsupportedAppUsage @UnsupportedAppUsage
/*package*/ Configuration mCurrentConfig; /*package*/ Configuration mCurrentConfig = Configuration.EMPTY;
private SearchManager mSearchManager; private SearchManager mSearchManager;
private MenuInflater mMenuInflater; private MenuInflater mMenuInflater;

View File

@@ -5885,19 +5885,17 @@ public final class ActivityThread extends ClientTransactionHandler
final boolean movedToDifferentDisplay = isDifferentDisplay(activity.getDisplayId(), final boolean movedToDifferentDisplay = isDifferentDisplay(activity.getDisplayId(),
displayId); displayId);
final Configuration currentConfig = activity.mCurrentConfig; final Configuration currentConfig = activity.mCurrentConfig;
final int diff = (currentConfig == null) ? 0xffffffff final int diff = currentConfig.diffPublicOnly(newConfig);
: currentConfig.diffPublicOnly(newConfig);
final boolean hasPublicConfigChange = diff != 0; final boolean hasPublicConfigChange = diff != 0;
final ActivityClientRecord r = getActivityClient(activityToken);
// TODO(b/173090263): Use diff instead after the improvement of AssetManager and // TODO(b/173090263): Use diff instead after the improvement of AssetManager and
// ResourcesImpl constructions. // ResourcesImpl constructions.
final boolean shouldUpdateResources = hasPublicConfigChange final boolean shouldUpdateResources = hasPublicConfigChange
|| shouldUpdateResources(activityToken, currentConfig, newConfig, amOverrideConfig, || shouldUpdateResources(activityToken, currentConfig, newConfig, amOverrideConfig,
movedToDifferentDisplay, hasPublicConfigChange); movedToDifferentDisplay, hasPublicConfigChange);
final boolean shouldReportChange = hasPublicConfigChange final boolean shouldReportChange = shouldReportChange(diff, currentConfig, newConfig,
// If this activity doesn't handle any of the config changes, then don't bother r != null ? r.mSizeConfigurations : null,
// calling onConfigurationChanged. Otherwise, report to the activity for the activity.mActivityInfo.getRealConfigChanged());
// changes.
&& (~activity.mActivityInfo.getRealConfigChanged() & diff) == 0;
// Nothing significant, don't proceed with updating and reporting. // Nothing significant, don't proceed with updating and reporting.
if (!shouldUpdateResources) { if (!shouldUpdateResources) {
return null; return null;
@@ -5944,6 +5942,40 @@ public final class ActivityThread extends ClientTransactionHandler
return configToReport; return configToReport;
} }
/**
* Returns {@code true} if {@link Activity#onConfigurationChanged(Configuration)} should be
* dispatched.
*
* @param publicDiff Usually computed by {@link Configuration#diffPublicOnly(Configuration)}.
* This parameter is to prevent we compute it again.
* @param currentConfig The current configuration cached in {@link Activity#mCurrentConfig}.
* It is {@code null} before the first config update from the server side.
* @param newConfig The updated {@link Configuration}
* @param sizeBuckets The Activity's {@link SizeConfigurationBuckets} if not {@code null}
* @param handledConfigChanges Bit mask of configuration changes that the activity can handle
* @return {@code true} if the config change should be reported to the Activity
*/
@VisibleForTesting
public static boolean shouldReportChange(int publicDiff, @Nullable Configuration currentConfig,
@NonNull Configuration newConfig, @Nullable SizeConfigurationBuckets sizeBuckets,
int handledConfigChanges) {
// Don't report the change if there's no public diff between current and new config.
if (publicDiff == 0) {
return false;
}
final int diffWithBucket = SizeConfigurationBuckets.filterDiff(publicDiff, currentConfig,
newConfig, sizeBuckets);
// Compare to the diff which filter the change without crossing size buckets with
// {@code handledConfigChanges}. The small changes should not block Activity to receive
// its handled config updates. Also, if Activity handles all small changes, we should
// dispatch the updated config to it.
final int diff = diffWithBucket != 0 ? diffWithBucket : publicDiff;
// 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.
return (~handledConfigChanges & diff) == 0;
}
public final void applyConfigurationToResources(Configuration config) { public final void applyConfigurationToResources(Configuration config) {
synchronized (mResourcesManager) { synchronized (mResourcesManager) {
mResourcesManager.applyConfigurationToResources(config, null); mResourcesManager.applyConfigurationToResources(config, null);

View File

@@ -16,12 +16,15 @@
package android.app.activity; package android.app.activity;
import static android.app.ActivityThread.shouldReportChange;
import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE; import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE;
import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY; import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY;
import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE; import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME; import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME;
import static android.app.servertransaction.ActivityLifecycleItem.ON_START; import static android.app.servertransaction.ActivityLifecycleItem.ON_START;
import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP; import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
import static android.content.pm.ActivityInfo.CONFIG_FONT_SCALE;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
@@ -31,6 +34,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSess
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.clearInvocations;
@@ -56,6 +61,7 @@ import android.os.UserHandle;
import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.Presubmit;
import android.testing.PollingCheck; import android.testing.PollingCheck;
import android.view.WindowManagerGlobal; import android.view.WindowManagerGlobal;
import android.window.SizeConfigurationBuckets;
import androidx.test.annotation.UiThreadTest; import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -195,6 +201,47 @@ public class ActivityThreadClientTest {
} }
} }
@Test
public void testShouldReportChange() {
final Configuration newConfig = new Configuration();
final Configuration currentConfig = new Configuration();
assertFalse("Must not report change if no public diff",
shouldReportChange(0 /* publicDiff */, currentConfig, newConfig,
null /* sizeBuckets */, 0 /* handledConfigChanges */));
final int[] verticalThresholds = {100, 400};
final SizeConfigurationBuckets buckets = new SizeConfigurationBuckets(
null /* horizontal */,
verticalThresholds,
null /* smallest */,
null /* screenLayoutSize */,
false /* screenLayoutLongSet */);
currentConfig.screenHeightDp = 200;
newConfig.screenHeightDp = 300;
assertFalse("Must not report changes if the diff is small and not handled",
shouldReportChange(CONFIG_SCREEN_SIZE /* publicDiff */, currentConfig,
newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */));
assertTrue("Must report changes if the small diff is handled",
shouldReportChange(CONFIG_SCREEN_SIZE /* publicDiff */, currentConfig, newConfig,
buckets, CONFIG_SCREEN_SIZE /* handledConfigChanges */));
currentConfig.fontScale = 0.8f;
newConfig.fontScale = 1.2f;
assertTrue("Must report handled changes regardless of small unhandled change",
shouldReportChange(CONFIG_SCREEN_SIZE | CONFIG_FONT_SCALE /* publicDiff */,
currentConfig, newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */));
newConfig.screenHeightDp = 500;
assertFalse("Must not report changes if there's unhandled big changes",
shouldReportChange(CONFIG_SCREEN_SIZE | CONFIG_FONT_SCALE /* publicDiff */,
currentConfig, newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */));
}
private void recreateAndVerifyNoRelaunch(ActivityThread activityThread, TestActivity activity) { private void recreateAndVerifyNoRelaunch(ActivityThread activityThread, TestActivity activity) {
clearInvocations(activityThread); clearInvocations(activityThread);
getInstrumentation().runOnMainSync(() -> activity.recreate()); getInstrumentation().runOnMainSync(() -> activity.recreate());