Merge "Add WindowProvider support to WindowLayoutComponentImpl and allow WindowProviderService to broadcast configuration changes to listeners." into tm-qpr-dev
diff --git a/core/java/android/window/WindowProvider.java b/core/java/android/window/WindowProvider.java
index b078b93..dbdc68f 100644
--- a/core/java/android/window/WindowProvider.java
+++ b/core/java/android/window/WindowProvider.java
@@ -15,8 +15,10 @@
*/
package android.window;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
+import android.os.IBinder;
import android.view.WindowManager.LayoutParams.WindowType;
/**
@@ -36,4 +38,11 @@
/** Gets the launch options of this provider */
@Nullable
Bundle getWindowContextOptions();
+
+ /**
+ * Gets the WindowContextToken of this provider.
+ * @see android.content.Context#getWindowContextToken
+ */
+ @NonNull
+ IBinder getWindowContextToken();
}
diff --git a/core/java/android/window/WindowProviderService.java b/core/java/android/window/WindowProviderService.java
index 2d2c8de..fdc3e5a 100644
--- a/core/java/android/window/WindowProviderService.java
+++ b/core/java/android/window/WindowProviderService.java
@@ -27,7 +27,10 @@
import android.app.ActivityThread;
import android.app.LoadedApk;
import android.app.Service;
+import android.content.ComponentCallbacks;
+import android.content.ComponentCallbacksController;
import android.content.Context;
+import android.content.res.Configuration;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.os.IBinder;
@@ -54,6 +57,8 @@
private final WindowContextController mController = new WindowContextController(mWindowToken);
private WindowManager mWindowManager;
private boolean mInitialized;
+ private final ComponentCallbacksController mCallbacksController =
+ new ComponentCallbacksController();
/**
* Returns {@code true} if the {@code windowContextOptions} declares that it is a
@@ -118,6 +123,48 @@
return mOptions;
}
+ @SuppressLint({"OnNameExpected", "ExecutorRegistration"})
+ // Suppress lint because this is a legacy named function and doesn't have an optional param
+ // for executor.
+ // TODO(b/259347943): Update documentation for U.
+ /**
+ * Here we override to prevent WindowProviderService from invoking
+ * {@link Application.registerComponentCallback}, which will result in callback registered
+ * for process-level Configuration change updates.
+ */
+ @Override
+ public void registerComponentCallbacks(@NonNull ComponentCallbacks callback) {
+ // For broadcasting Configuration Changes.
+ mCallbacksController.registerCallbacks(callback);
+ }
+
+ @SuppressLint("OnNameExpected")
+ @Override
+ public void unregisterComponentCallbacks(@NonNull ComponentCallbacks callback) {
+ mCallbacksController.unregisterCallbacks(callback);
+ }
+
+ @SuppressLint("OnNameExpected")
+ @Override
+ public void onConfigurationChanged(@Nullable Configuration configuration) {
+ // This is only called from WindowTokenClient.
+ mCallbacksController.dispatchConfigurationChanged(configuration);
+ }
+
+ /**
+ * Override {@link Service}'s empty implementation and listen to {@link ActivityThread} for
+ * low memory and trim memory events.
+ */
+ @Override
+ public void onLowMemory() {
+ mCallbacksController.dispatchLowMemory();
+ }
+
+ @Override
+ public void onTrimMemory(int level) {
+ mCallbacksController.dispatchTrimMemory(level);
+ }
+
/**
* Returns the display ID to launch this {@link WindowProviderService}.
*
@@ -181,5 +228,6 @@
public void onDestroy() {
super.onDestroy();
mController.detachIfNeeded();
+ mCallbacksController.clearCallbacks();
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
index b516e140..2192b5c 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
@@ -36,6 +36,7 @@
import android.os.IBinder;
import android.util.ArrayMap;
import android.window.WindowContext;
+import android.window.WindowProvider;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -71,7 +72,7 @@
private final List<CommonFoldingFeature> mLastReportedFoldingFeatures = new ArrayList<>();
- private final Map<IBinder, WindowContextConfigListener> mWindowContextConfigListeners =
+ private final Map<IBinder, ConfigurationChangeListener> mConfigurationChangeListeners =
new ArrayMap<>();
public WindowLayoutComponentImpl(@NonNull Context context) {
@@ -121,21 +122,21 @@
}
if (!context.isUiContext()) {
throw new IllegalArgumentException("Context must be a UI Context, which should be"
- + " an Activity or a WindowContext");
+ + " an Activity, WindowContext or InputMethodService");
}
mFoldingFeatureProducer.getData((features) -> {
- // Get the WindowLayoutInfo from the activity and pass the value to the layoutConsumer.
WindowLayoutInfo newWindowLayout = getWindowLayoutInfo(context, features);
consumer.accept(newWindowLayout);
});
mWindowLayoutChangeListeners.put(context, consumer);
- if (context instanceof WindowContext) {
+ // TODO(b/258065175) Further extend this to ContextWrappers.
+ if (context instanceof WindowProvider) {
final IBinder windowContextToken = context.getWindowContextToken();
- final WindowContextConfigListener listener =
- new WindowContextConfigListener(windowContextToken);
+ final ConfigurationChangeListener listener =
+ new ConfigurationChangeListener(windowContextToken);
context.registerComponentCallbacks(listener);
- mWindowContextConfigListeners.put(windowContextToken, listener);
+ mConfigurationChangeListeners.put(windowContextToken, listener);
}
}
@@ -150,10 +151,10 @@
if (!mWindowLayoutChangeListeners.get(context).equals(consumer)) {
continue;
}
- if (context instanceof WindowContext) {
+ if (context instanceof WindowProvider) {
final IBinder token = context.getWindowContextToken();
- context.unregisterComponentCallbacks(mWindowContextConfigListeners.get(token));
- mWindowContextConfigListeners.remove(token);
+ context.unregisterComponentCallbacks(mConfigurationChangeListeners.get(token));
+ mConfigurationChangeListeners.remove(token);
}
break;
}
@@ -349,10 +350,10 @@
}
}
- private final class WindowContextConfigListener implements ComponentCallbacks {
+ private final class ConfigurationChangeListener implements ComponentCallbacks {
final IBinder mToken;
- WindowContextConfigListener(IBinder token) {
+ ConfigurationChangeListener(IBinder token) {
mToken = token;
}