diff --git a/core/java/android/window/WindowProviderService.java b/core/java/android/window/WindowProviderService.java index f8484d15344e0..2d2c8de726466 100644 --- a/core/java/android/window/WindowProviderService.java +++ b/core/java/android/window/WindowProviderService.java @@ -165,10 +165,11 @@ public abstract class WindowProviderService extends Service implements WindowPro } } + // Suppress the lint because ths is overridden from Context. @SuppressLint("OnNameExpected") @Override - // Suppress the lint because ths is overridden from Context. - public @Nullable Object getSystemService(@NonNull String name) { + @Nullable + public Object getSystemService(@NonNull String name) { if (WINDOW_SERVICE.equals(name)) { return mWindowManager; } diff --git a/core/java/android/window/WindowTokenClient.java b/core/java/android/window/WindowTokenClient.java index 547535d90e5aa..7db4243d3a83e 100644 --- a/core/java/android/window/WindowTokenClient.java +++ b/core/java/android/window/WindowTokenClient.java @@ -19,8 +19,8 @@ import static android.window.ConfigurationHelper.freeTextLayoutCachesIfNeeded; import static android.window.ConfigurationHelper.isDifferentDisplay; import static android.window.ConfigurationHelper.shouldUpdateResources; +import android.annotation.AnyThread; import android.annotation.BinderThread; -import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.IWindowToken; @@ -40,6 +40,7 @@ import android.view.IWindowManager; import android.view.WindowManager.LayoutParams.WindowType; import android.view.WindowManagerGlobal; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.lang.ref.WeakReference; @@ -68,6 +69,7 @@ public class WindowTokenClient extends IWindowToken.Stub { private IWindowManager mWms; + @GuardedBy("itself") private final Configuration mConfiguration = new Configuration(); private boolean mShouldDumpConfigForIme; @@ -91,7 +93,6 @@ public class WindowTokenClient extends IWindowToken.Stub { throw new IllegalStateException("Context is already attached."); } mContextRef = new WeakReference<>(context); - mConfiguration.setTo(context.getResources().getConfiguration()); mShouldDumpConfigForIme = Build.IS_DEBUGGABLE && context instanceof AbstractInputMethodService; } @@ -137,8 +138,7 @@ public class WindowTokenClient extends IWindowToken.Stub { if (configuration == null) { return false; } - mHandler.post(() -> onConfigurationChanged(configuration, displayId, - false /* shouldReportConfigChange */)); + onConfigurationChanged(configuration, displayId, false /* shouldReportConfigChange */); mAttachToWindowContainer = true; return true; } catch (RemoteException e) { @@ -199,8 +199,19 @@ public class WindowTokenClient extends IWindowToken.Stub { * * Similar to {@link #onConfigurationChanged(Configuration, int)}, but adds a flag to control * whether to dispatch configuration update or not. + *
+ * Note that this method must be executed on the main thread if
+ * {@code shouldReportConfigChange} is {@code true}, which is usually from
+ * {@link IWindowToken#onConfigurationChanged(Configuration, int)}
+ * directly, while this method could be run on any thread if it is used to initialize
+ * Context's {@code Configuration} via {@link #attachToDisplayArea(int, int, Bundle)}
+ * or {@link #attachToDisplayContent(int)}.
+ *
+ * @param shouldReportConfigChange {@code true} to indicate that the {@code Configuration}
+ * should be dispatched to listeners.
+ *
*/
- @MainThread
+ @AnyThread
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public void onConfigurationChanged(Configuration newConfig, int newDisplayId,
boolean shouldReportConfigChange) {
@@ -208,18 +219,29 @@ public class WindowTokenClient extends IWindowToken.Stub {
if (context == null) {
return;
}
- final boolean displayChanged = isDifferentDisplay(context.getDisplayId(), newDisplayId);
- final boolean shouldUpdateResources = shouldUpdateResources(this, mConfiguration,
- newConfig, newConfig /* overrideConfig */, displayChanged,
- null /* configChanged */);
+ final boolean displayChanged;
+ final boolean shouldUpdateResources;
+ final int diff;
+ final Configuration currentConfig;
+
+ synchronized (mConfiguration) {
+ displayChanged = isDifferentDisplay(context.getDisplayId(), newDisplayId);
+ shouldUpdateResources = shouldUpdateResources(this, mConfiguration,
+ newConfig, newConfig /* overrideConfig */, displayChanged,
+ null /* configChanged */);
+ diff = mConfiguration.diffPublicOnly(newConfig);
+ currentConfig = mShouldDumpConfigForIme ? new Configuration(mConfiguration) : null;
+ if (shouldUpdateResources) {
+ mConfiguration.setTo(newConfig);
+ }
+ }
if (!shouldUpdateResources && mShouldDumpConfigForIme) {
Log.d(TAG, "Configuration not dispatch to IME because configuration is up"
+ " to date. Current config=" + context.getResources().getConfiguration()
- + ", reported config=" + mConfiguration
+ + ", reported config=" + currentConfig
+ ", updated config=" + newConfig);
}
-
if (shouldUpdateResources) {
// TODO(ag/9789103): update resource manager logic to track non-activity tokens
mResourcesManager.updateResourcesForActivity(this, newConfig, newDisplayId);
@@ -229,7 +251,7 @@ public class WindowTokenClient extends IWindowToken.Stub {
windowContext.dispatchConfigurationChanged(newConfig);
}
- final int diff = mConfiguration.diffPublicOnly(newConfig);
+
if (shouldReportConfigChange && diff != 0
&& context instanceof WindowProviderService) {
final WindowProviderService windowProviderService = (WindowProviderService) context;
@@ -244,11 +266,10 @@ public class WindowTokenClient extends IWindowToken.Stub {
Log.d(TAG, "Configuration not dispatch to IME because configuration has no "
+ " public difference with updated config. "
+ " Current config=" + context.getResources().getConfiguration()
- + ", reported config=" + mConfiguration
+ + ", reported config=" + currentConfig
+ ", updated config=" + newConfig);
}
}
- mConfiguration.setTo(newConfig);
}
if (displayChanged) {
context.updateDisplay(newDisplayId);
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index dbc08cd5d1a94..e7c03aa7a099c 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -637,12 +637,19 @@ public abstract class ConfigurationContainer