Loading core/java/android/app/ActivityThread.java +35 −64 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package android.app; import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN; import static android.app.ConfigurationController.createNewConfigAndUpdateIfNotNull; import static android.app.ConfigurationController.freeTextLayoutCachesIfNeeded; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE; Loading @@ -31,6 +30,10 @@ import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE; 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 android.window.ConfigurationHelper.diffPublicWithSizeBuckets; import static android.window.ConfigurationHelper.freeTextLayoutCachesIfNeeded; import static android.window.ConfigurationHelper.isDifferentDisplay; import static android.window.ConfigurationHelper.shouldUpdateResources; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; Loading Loading @@ -91,7 +94,6 @@ import android.database.sqlite.SQLiteDebug.DbStats; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.HardwareRenderer; import android.graphics.Rect; import android.graphics.Typeface; import android.hardware.display.DisplayManagerGlobal; import android.inputmethodservice.InputMethodService; Loading Loading @@ -186,6 +188,7 @@ import android.webkit.WebView; import android.window.SizeConfigurationBuckets; import android.window.SplashScreen; import android.window.SplashScreenView; import android.window.WindowProviderService; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -5756,7 +5759,7 @@ public final class ActivityThread extends ClientTransactionHandler } @Override public ArrayList<ComponentCallbacks2> collectComponentCallbacks(boolean includeActivities) { public ArrayList<ComponentCallbacks2> collectComponentCallbacks(boolean includeUiContexts) { ArrayList<ComponentCallbacks2> callbacks = new ArrayList<ComponentCallbacks2>(); Loading @@ -5765,7 +5768,7 @@ public final class ActivityThread extends ClientTransactionHandler for (int i=0; i<NAPP; i++) { callbacks.add(mAllApplications.get(i)); } if (includeActivities) { if (includeUiContexts) { for (int i = mActivities.size() - 1; i >= 0; i--) { final Activity a = mActivities.valueAt(i).activity; if (a != null && !a.mFinished) { Loading @@ -5775,11 +5778,15 @@ public final class ActivityThread extends ClientTransactionHandler } final int NSVC = mServices.size(); for (int i=0; i<NSVC; i++) { final ComponentCallbacks2 serviceComp = mServices.valueAt(i); if (serviceComp instanceof InputMethodService) { final Service service = mServices.valueAt(i); if (service instanceof InputMethodService) { mHasImeComponent = true; } callbacks.add(serviceComp); // If {@code includeUiContext} is set to false, WindowProviderService should not be // collected because WindowProviderService is a UI Context. if (includeUiContexts || !(service instanceof WindowProviderService)) { callbacks.add(service); } } } synchronized (mProviderMap) { Loading Loading @@ -5834,35 +5841,26 @@ public final class ActivityThread extends ClientTransactionHandler // change callback, see also PinnedStackTests#testConfigurationChangeOrderDuringTransition handleWindowingModeChangeIfNeeded(activity, newConfig); final boolean movedToDifferentDisplay = isDifferentDisplay(activity, displayId); boolean shouldReportChange = false; if (activity.mCurrentConfig == null) { shouldReportChange = true; } else { // 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 // onConfigurationChanged. final boolean movedToDifferentDisplay = isDifferentDisplay(activity.getDisplayId(), displayId); final SizeConfigurationBuckets buckets = getActivityClient(activityToken) .mSizeConfigurations; final int diff = diffPublicWithSizeBuckets(activity.mCurrentConfig, newConfig, buckets); final boolean hasPublicConfigChange = diff != 0; // TODO(b/173090263): Use diff instead after the improvement of AssetManager and // ResourcesImpl constructions. int diff = activity.mCurrentConfig.diffPublicOnly(newConfig); final ActivityClientRecord cr = getActivityClient(activityToken); diff = SizeConfigurationBuckets.filterDiff(diff, activity.mCurrentConfig, newConfig, cr != null ? cr.mSizeConfigurations : null); if (diff == 0) { if (!shouldUpdateWindowMetricsBounds(activity.mCurrentConfig, newConfig) && !movedToDifferentDisplay && mResourcesManager.isSameResourcesOverrideConfig( activityToken, amOverrideConfig)) { // Nothing significant, don't proceed with updating and reporting. return null; } } else if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) { final boolean shouldUpdateResources = hasPublicConfigChange || shouldUpdateResources(activityToken, activity.mCurrentConfig, newConfig, amOverrideConfig, movedToDifferentDisplay, hasPublicConfigChange); final boolean shouldReportChange = hasPublicConfigChange // 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; } && (~activity.mActivityInfo.getRealConfigChanged() & diff) == 0; // Nothing significant, don't proceed with updating and reporting. if (!shouldUpdateResources) { return null; } // Propagate the configuration change to ResourcesManager and Activity. Loading Loading @@ -5913,26 +5911,6 @@ public final class ActivityThread extends ClientTransactionHandler return configToReport; } // TODO(b/173090263): Remove this method after the improvement of AssetManager and ResourcesImpl // constructions. /** * Returns {@code true} if the metrics reported by {@link android.view.WindowMetrics} APIs * should be updated. * * @see WindowManager#getCurrentWindowMetrics() * @see WindowManager#getMaximumWindowMetrics() */ private static boolean shouldUpdateWindowMetricsBounds(@NonNull Configuration currentConfig, @NonNull Configuration newConfig) { final Rect currentBounds = currentConfig.windowConfiguration.getBounds(); final Rect newBounds = newConfig.windowConfiguration.getBounds(); final Rect currentMaxBounds = currentConfig.windowConfiguration.getMaxBounds(); final Rect newMaxBounds = newConfig.windowConfiguration.getMaxBounds(); return !currentBounds.equals(newBounds) || !currentMaxBounds.equals(newMaxBounds); } public final void applyConfigurationToResources(Configuration config) { synchronized (mResourcesManager) { mResourcesManager.applyConfigurationToResources(config, null); Loading Loading @@ -6080,7 +6058,8 @@ public final class ActivityThread extends ClientTransactionHandler // display. displayId = r.activity.getDisplayId(); } final boolean movedToDifferentDisplay = isDifferentDisplay(r.activity, displayId); final boolean movedToDifferentDisplay = isDifferentDisplay( r.activity.getDisplayId(), displayId); if (r.overrideConfig != null && !r.overrideConfig.isOtherSeqNewer(overrideConfig) && !movedToDifferentDisplay) { if (DEBUG_CONFIGURATION) { Loading Loading @@ -6116,14 +6095,6 @@ public final class ActivityThread extends ClientTransactionHandler mSomeActivitiesChanged = true; } /** * Checks if the display id of activity is different from the given one. Note that * {@link Display#INVALID_DISPLAY} means no difference. */ private static boolean isDifferentDisplay(@NonNull Activity activity, int displayId) { return displayId != INVALID_DISPLAY && displayId != activity.getDisplayId(); } final void handleProfilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) { if (start) { try { Loading Loading @@ -6301,7 +6272,7 @@ public final class ActivityThread extends ClientTransactionHandler final void handleLowMemory() { final ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true /* includeActivities */); collectComponentCallbacks(true /* includeUiContexts */); final int N = callbacks.size(); for (int i=0; i<N; i++) { Loading Loading @@ -6334,7 +6305,7 @@ public final class ActivityThread extends ClientTransactionHandler } final ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true /* includeActivities */); collectComponentCallbacks(true /* includeUiContexts */); final int N = callbacks.size(); for (int i = 0; i < N; i++) { Loading core/java/android/app/ActivityThreadInternal.java +1 −1 Original line number Diff line number Diff line Loading @@ -38,5 +38,5 @@ interface ActivityThreadInternal { Application getApplication(); ArrayList<ComponentCallbacks2> collectComponentCallbacks(boolean includeActivities); ArrayList<ComponentCallbacks2> collectComponentCallbacks(boolean includeUiContexts); } core/java/android/app/ConfigurationController.java +2 −15 Original line number Diff line number Diff line Loading @@ -17,17 +17,16 @@ package android.app; import static android.app.ActivityThread.DEBUG_CONFIGURATION; import static android.window.ConfigurationHelper.freeTextLayoutCachesIfNeeded; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentCallbacks2; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.HardwareRenderer; import android.inputmethodservice.InputMethodService; import android.os.Build; Loading Loading @@ -228,7 +227,7 @@ class ConfigurationController { } final ArrayList<ComponentCallbacks2> callbacks = mActivityThread.collectComponentCallbacks(false /* includeActivities */); mActivityThread.collectComponentCallbacks(false /* includeUiContexts */); freeTextLayoutCachesIfNeeded(configDiff); Loading Loading @@ -326,16 +325,4 @@ class ConfigurationController { return newConfig; } /** Ask test layout engine to free its caches if there is a locale change. */ static void freeTextLayoutCachesIfNeeded(int configDiff) { if (configDiff != 0) { boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0); if (hasLocaleConfigChange) { Canvas.freeTextLayoutCaches(); if (DEBUG_CONFIGURATION) { Slog.v(TAG, "Cleared TextLayout Caches"); } } } } } core/java/android/app/ResourcesManager.java +1 −1 Original line number Diff line number Diff line Loading @@ -730,7 +730,7 @@ public class ResourcesManager { * @return true if activity resources override config matches the provided one or they are both * null, false otherwise. */ boolean isSameResourcesOverrideConfig(@Nullable IBinder activityToken, public boolean isSameResourcesOverrideConfig(@Nullable IBinder activityToken, @Nullable Configuration overrideConfig) { synchronized (mLock) { final ActivityResources activityResources Loading core/java/android/window/ConfigurationHelper.java 0 → 100644 +132 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.window; import static android.view.Display.INVALID_DISPLAY; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ResourcesManager; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Rect; import android.os.IBinder; import android.view.Display; import android.view.WindowManager; /** * A helper class to maintain {@link android.content.res.Configuration} related methods used both * in {@link android.app.Activity} and {@link WindowContext}. * * @hide */ public class ConfigurationHelper { private ConfigurationHelper() {} /** Ask text layout engine to free its caches if there is a locale change. */ public static void freeTextLayoutCachesIfNeeded(int configDiff) { if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) { Canvas.freeTextLayoutCaches(); } } /** * A helper method to filter out {@link ActivityInfo#CONFIG_SCREEN_SIZE} if the * {@link Configuration#diffPublicOnly(Configuration) diff} of two {@link Configuration} * doesn't cross the boundary. * * @see SizeConfigurationBuckets#filterDiff(int, Configuration, Configuration, * SizeConfigurationBuckets) */ public static int diffPublicWithSizeBuckets(@Nullable Configuration currentConfig, @NonNull Configuration newConfig, @Nullable SizeConfigurationBuckets buckets) { // If current configuration is null, it is definitely different from updated Configuration. if (currentConfig == null) { return 0xffffffff; } int publicDiff = currentConfig.diffPublicOnly(newConfig); return SizeConfigurationBuckets.filterDiff(publicDiff, currentConfig, newConfig, buckets); } /** * Returns {@code true} if the {@link android.content.res.Resources} associated with * a {@code token} needs to be updated. * * @param token A {@link Context#getActivityToken() activity token} or * {@link Context#getWindowContextToken() window context token} * @param config The original {@link Configuration} * @param newConfig The updated Configuration * @param displayChanged a flag to indicate there's a display change * @param configChanged a flag to indicate there's a Configuration change. * * @see ResourcesManager#updateResourcesForActivity(IBinder, Configuration, int) */ public static boolean shouldUpdateResources(IBinder token, @Nullable Configuration config, @NonNull Configuration newConfig, @NonNull Configuration overrideConfig, boolean displayChanged, @Nullable Boolean configChanged) { // The configuration has not yet been initialized. We should update it. if (config == null) { return true; } // If the token associated context is moved to another display, we should update the // ResourcesKey. if (displayChanged) { return true; } // 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 update the Resources if (!ResourcesManager.getInstance().isSameResourcesOverrideConfig(token, overrideConfig)) { return true; } // If there's a update on WindowConfiguration#mBounds or maxBounds, we should update the // Resources to make WindowMetrics API report the updated result. if (shouldUpdateWindowMetricsBounds(config, newConfig)) { return true; } return configChanged == null ? config.diff(newConfig) != 0 : configChanged; } /** * Returns {@code true} if {@code displayId} is different from {@code newDisplayId}. * Note that {@link Display#INVALID_DISPLAY} means no difference. */ public static boolean isDifferentDisplay(int displayId, int newDisplayId) { return newDisplayId != INVALID_DISPLAY && displayId != newDisplayId; } // TODO(b/173090263): Remove this method after the improvement of AssetManager and ResourcesImpl // constructions. /** * Returns {@code true} if the metrics reported by {@link android.view.WindowMetrics} APIs * should be updated. * * @see WindowManager#getCurrentWindowMetrics() * @see WindowManager#getMaximumWindowMetrics() */ private static boolean shouldUpdateWindowMetricsBounds(@NonNull Configuration currentConfig, @NonNull Configuration newConfig) { final Rect currentBounds = currentConfig.windowConfiguration.getBounds(); final Rect newBounds = newConfig.windowConfiguration.getBounds(); final Rect currentMaxBounds = currentConfig.windowConfiguration.getMaxBounds(); final Rect newMaxBounds = newConfig.windowConfiguration.getMaxBounds(); return !currentBounds.equals(newBounds) || !currentMaxBounds.equals(newMaxBounds); } } Loading
core/java/android/app/ActivityThread.java +35 −64 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package android.app; import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN; import static android.app.ConfigurationController.createNewConfigAndUpdateIfNotNull; import static android.app.ConfigurationController.freeTextLayoutCachesIfNeeded; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE; Loading @@ -31,6 +30,10 @@ import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE; 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 android.window.ConfigurationHelper.diffPublicWithSizeBuckets; import static android.window.ConfigurationHelper.freeTextLayoutCachesIfNeeded; import static android.window.ConfigurationHelper.isDifferentDisplay; import static android.window.ConfigurationHelper.shouldUpdateResources; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; Loading Loading @@ -91,7 +94,6 @@ import android.database.sqlite.SQLiteDebug.DbStats; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.HardwareRenderer; import android.graphics.Rect; import android.graphics.Typeface; import android.hardware.display.DisplayManagerGlobal; import android.inputmethodservice.InputMethodService; Loading Loading @@ -186,6 +188,7 @@ import android.webkit.WebView; import android.window.SizeConfigurationBuckets; import android.window.SplashScreen; import android.window.SplashScreenView; import android.window.WindowProviderService; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -5756,7 +5759,7 @@ public final class ActivityThread extends ClientTransactionHandler } @Override public ArrayList<ComponentCallbacks2> collectComponentCallbacks(boolean includeActivities) { public ArrayList<ComponentCallbacks2> collectComponentCallbacks(boolean includeUiContexts) { ArrayList<ComponentCallbacks2> callbacks = new ArrayList<ComponentCallbacks2>(); Loading @@ -5765,7 +5768,7 @@ public final class ActivityThread extends ClientTransactionHandler for (int i=0; i<NAPP; i++) { callbacks.add(mAllApplications.get(i)); } if (includeActivities) { if (includeUiContexts) { for (int i = mActivities.size() - 1; i >= 0; i--) { final Activity a = mActivities.valueAt(i).activity; if (a != null && !a.mFinished) { Loading @@ -5775,11 +5778,15 @@ public final class ActivityThread extends ClientTransactionHandler } final int NSVC = mServices.size(); for (int i=0; i<NSVC; i++) { final ComponentCallbacks2 serviceComp = mServices.valueAt(i); if (serviceComp instanceof InputMethodService) { final Service service = mServices.valueAt(i); if (service instanceof InputMethodService) { mHasImeComponent = true; } callbacks.add(serviceComp); // If {@code includeUiContext} is set to false, WindowProviderService should not be // collected because WindowProviderService is a UI Context. if (includeUiContexts || !(service instanceof WindowProviderService)) { callbacks.add(service); } } } synchronized (mProviderMap) { Loading Loading @@ -5834,35 +5841,26 @@ public final class ActivityThread extends ClientTransactionHandler // change callback, see also PinnedStackTests#testConfigurationChangeOrderDuringTransition handleWindowingModeChangeIfNeeded(activity, newConfig); final boolean movedToDifferentDisplay = isDifferentDisplay(activity, displayId); boolean shouldReportChange = false; if (activity.mCurrentConfig == null) { shouldReportChange = true; } else { // 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 // onConfigurationChanged. final boolean movedToDifferentDisplay = isDifferentDisplay(activity.getDisplayId(), displayId); final SizeConfigurationBuckets buckets = getActivityClient(activityToken) .mSizeConfigurations; final int diff = diffPublicWithSizeBuckets(activity.mCurrentConfig, newConfig, buckets); final boolean hasPublicConfigChange = diff != 0; // TODO(b/173090263): Use diff instead after the improvement of AssetManager and // ResourcesImpl constructions. int diff = activity.mCurrentConfig.diffPublicOnly(newConfig); final ActivityClientRecord cr = getActivityClient(activityToken); diff = SizeConfigurationBuckets.filterDiff(diff, activity.mCurrentConfig, newConfig, cr != null ? cr.mSizeConfigurations : null); if (diff == 0) { if (!shouldUpdateWindowMetricsBounds(activity.mCurrentConfig, newConfig) && !movedToDifferentDisplay && mResourcesManager.isSameResourcesOverrideConfig( activityToken, amOverrideConfig)) { // Nothing significant, don't proceed with updating and reporting. return null; } } else if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) { final boolean shouldUpdateResources = hasPublicConfigChange || shouldUpdateResources(activityToken, activity.mCurrentConfig, newConfig, amOverrideConfig, movedToDifferentDisplay, hasPublicConfigChange); final boolean shouldReportChange = hasPublicConfigChange // 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; } && (~activity.mActivityInfo.getRealConfigChanged() & diff) == 0; // Nothing significant, don't proceed with updating and reporting. if (!shouldUpdateResources) { return null; } // Propagate the configuration change to ResourcesManager and Activity. Loading Loading @@ -5913,26 +5911,6 @@ public final class ActivityThread extends ClientTransactionHandler return configToReport; } // TODO(b/173090263): Remove this method after the improvement of AssetManager and ResourcesImpl // constructions. /** * Returns {@code true} if the metrics reported by {@link android.view.WindowMetrics} APIs * should be updated. * * @see WindowManager#getCurrentWindowMetrics() * @see WindowManager#getMaximumWindowMetrics() */ private static boolean shouldUpdateWindowMetricsBounds(@NonNull Configuration currentConfig, @NonNull Configuration newConfig) { final Rect currentBounds = currentConfig.windowConfiguration.getBounds(); final Rect newBounds = newConfig.windowConfiguration.getBounds(); final Rect currentMaxBounds = currentConfig.windowConfiguration.getMaxBounds(); final Rect newMaxBounds = newConfig.windowConfiguration.getMaxBounds(); return !currentBounds.equals(newBounds) || !currentMaxBounds.equals(newMaxBounds); } public final void applyConfigurationToResources(Configuration config) { synchronized (mResourcesManager) { mResourcesManager.applyConfigurationToResources(config, null); Loading Loading @@ -6080,7 +6058,8 @@ public final class ActivityThread extends ClientTransactionHandler // display. displayId = r.activity.getDisplayId(); } final boolean movedToDifferentDisplay = isDifferentDisplay(r.activity, displayId); final boolean movedToDifferentDisplay = isDifferentDisplay( r.activity.getDisplayId(), displayId); if (r.overrideConfig != null && !r.overrideConfig.isOtherSeqNewer(overrideConfig) && !movedToDifferentDisplay) { if (DEBUG_CONFIGURATION) { Loading Loading @@ -6116,14 +6095,6 @@ public final class ActivityThread extends ClientTransactionHandler mSomeActivitiesChanged = true; } /** * Checks if the display id of activity is different from the given one. Note that * {@link Display#INVALID_DISPLAY} means no difference. */ private static boolean isDifferentDisplay(@NonNull Activity activity, int displayId) { return displayId != INVALID_DISPLAY && displayId != activity.getDisplayId(); } final void handleProfilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) { if (start) { try { Loading Loading @@ -6301,7 +6272,7 @@ public final class ActivityThread extends ClientTransactionHandler final void handleLowMemory() { final ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true /* includeActivities */); collectComponentCallbacks(true /* includeUiContexts */); final int N = callbacks.size(); for (int i=0; i<N; i++) { Loading Loading @@ -6334,7 +6305,7 @@ public final class ActivityThread extends ClientTransactionHandler } final ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true /* includeActivities */); collectComponentCallbacks(true /* includeUiContexts */); final int N = callbacks.size(); for (int i = 0; i < N; i++) { Loading
core/java/android/app/ActivityThreadInternal.java +1 −1 Original line number Diff line number Diff line Loading @@ -38,5 +38,5 @@ interface ActivityThreadInternal { Application getApplication(); ArrayList<ComponentCallbacks2> collectComponentCallbacks(boolean includeActivities); ArrayList<ComponentCallbacks2> collectComponentCallbacks(boolean includeUiContexts); }
core/java/android/app/ConfigurationController.java +2 −15 Original line number Diff line number Diff line Loading @@ -17,17 +17,16 @@ package android.app; import static android.app.ActivityThread.DEBUG_CONFIGURATION; import static android.window.ConfigurationHelper.freeTextLayoutCachesIfNeeded; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentCallbacks2; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.HardwareRenderer; import android.inputmethodservice.InputMethodService; import android.os.Build; Loading Loading @@ -228,7 +227,7 @@ class ConfigurationController { } final ArrayList<ComponentCallbacks2> callbacks = mActivityThread.collectComponentCallbacks(false /* includeActivities */); mActivityThread.collectComponentCallbacks(false /* includeUiContexts */); freeTextLayoutCachesIfNeeded(configDiff); Loading Loading @@ -326,16 +325,4 @@ class ConfigurationController { return newConfig; } /** Ask test layout engine to free its caches if there is a locale change. */ static void freeTextLayoutCachesIfNeeded(int configDiff) { if (configDiff != 0) { boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0); if (hasLocaleConfigChange) { Canvas.freeTextLayoutCaches(); if (DEBUG_CONFIGURATION) { Slog.v(TAG, "Cleared TextLayout Caches"); } } } } }
core/java/android/app/ResourcesManager.java +1 −1 Original line number Diff line number Diff line Loading @@ -730,7 +730,7 @@ public class ResourcesManager { * @return true if activity resources override config matches the provided one or they are both * null, false otherwise. */ boolean isSameResourcesOverrideConfig(@Nullable IBinder activityToken, public boolean isSameResourcesOverrideConfig(@Nullable IBinder activityToken, @Nullable Configuration overrideConfig) { synchronized (mLock) { final ActivityResources activityResources Loading
core/java/android/window/ConfigurationHelper.java 0 → 100644 +132 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.window; import static android.view.Display.INVALID_DISPLAY; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ResourcesManager; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Rect; import android.os.IBinder; import android.view.Display; import android.view.WindowManager; /** * A helper class to maintain {@link android.content.res.Configuration} related methods used both * in {@link android.app.Activity} and {@link WindowContext}. * * @hide */ public class ConfigurationHelper { private ConfigurationHelper() {} /** Ask text layout engine to free its caches if there is a locale change. */ public static void freeTextLayoutCachesIfNeeded(int configDiff) { if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) { Canvas.freeTextLayoutCaches(); } } /** * A helper method to filter out {@link ActivityInfo#CONFIG_SCREEN_SIZE} if the * {@link Configuration#diffPublicOnly(Configuration) diff} of two {@link Configuration} * doesn't cross the boundary. * * @see SizeConfigurationBuckets#filterDiff(int, Configuration, Configuration, * SizeConfigurationBuckets) */ public static int diffPublicWithSizeBuckets(@Nullable Configuration currentConfig, @NonNull Configuration newConfig, @Nullable SizeConfigurationBuckets buckets) { // If current configuration is null, it is definitely different from updated Configuration. if (currentConfig == null) { return 0xffffffff; } int publicDiff = currentConfig.diffPublicOnly(newConfig); return SizeConfigurationBuckets.filterDiff(publicDiff, currentConfig, newConfig, buckets); } /** * Returns {@code true} if the {@link android.content.res.Resources} associated with * a {@code token} needs to be updated. * * @param token A {@link Context#getActivityToken() activity token} or * {@link Context#getWindowContextToken() window context token} * @param config The original {@link Configuration} * @param newConfig The updated Configuration * @param displayChanged a flag to indicate there's a display change * @param configChanged a flag to indicate there's a Configuration change. * * @see ResourcesManager#updateResourcesForActivity(IBinder, Configuration, int) */ public static boolean shouldUpdateResources(IBinder token, @Nullable Configuration config, @NonNull Configuration newConfig, @NonNull Configuration overrideConfig, boolean displayChanged, @Nullable Boolean configChanged) { // The configuration has not yet been initialized. We should update it. if (config == null) { return true; } // If the token associated context is moved to another display, we should update the // ResourcesKey. if (displayChanged) { return true; } // 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 update the Resources if (!ResourcesManager.getInstance().isSameResourcesOverrideConfig(token, overrideConfig)) { return true; } // If there's a update on WindowConfiguration#mBounds or maxBounds, we should update the // Resources to make WindowMetrics API report the updated result. if (shouldUpdateWindowMetricsBounds(config, newConfig)) { return true; } return configChanged == null ? config.diff(newConfig) != 0 : configChanged; } /** * Returns {@code true} if {@code displayId} is different from {@code newDisplayId}. * Note that {@link Display#INVALID_DISPLAY} means no difference. */ public static boolean isDifferentDisplay(int displayId, int newDisplayId) { return newDisplayId != INVALID_DISPLAY && displayId != newDisplayId; } // TODO(b/173090263): Remove this method after the improvement of AssetManager and ResourcesImpl // constructions. /** * Returns {@code true} if the metrics reported by {@link android.view.WindowMetrics} APIs * should be updated. * * @see WindowManager#getCurrentWindowMetrics() * @see WindowManager#getMaximumWindowMetrics() */ private static boolean shouldUpdateWindowMetricsBounds(@NonNull Configuration currentConfig, @NonNull Configuration newConfig) { final Rect currentBounds = currentConfig.windowConfiguration.getBounds(); final Rect newBounds = newConfig.windowConfiguration.getBounds(); final Rect currentMaxBounds = currentConfig.windowConfiguration.getMaxBounds(); final Rect newMaxBounds = newConfig.windowConfiguration.getMaxBounds(); return !currentBounds.equals(newBounds) || !currentMaxBounds.equals(newMaxBounds); } }