Add WindowProvider support to WindowLayoutComponentImpl and allow
WindowProviderService to broadcast configuration changes to listeners. This is needed to allow IME to listen to WindowLayoutInfo changes. Bug: 237342281 Test: CTS InputMethodServiceTest Change-Id: Id8ddce5889b52859172caf3b4f0763bb5010b5dc
This commit is contained in:
@@ -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 @@ public interface WindowProvider {
|
||||
/** Gets the launch options of this provider */
|
||||
@Nullable
|
||||
Bundle getWindowContextOptions();
|
||||
|
||||
/**
|
||||
* Gets the WindowContextToken of this provider.
|
||||
* @see android.content.Context#getWindowContextToken
|
||||
*/
|
||||
@NonNull
|
||||
IBinder getWindowContextToken();
|
||||
}
|
||||
|
||||
@@ -27,7 +27,10 @@ import android.annotation.UiContext;
|
||||
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 @@ public abstract class WindowProviderService extends Service implements WindowPro
|
||||
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 @@ public abstract class WindowProviderService extends Service implements WindowPro
|
||||
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 abstract class WindowProviderService extends Service implements WindowPro
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mController.detachIfNeeded();
|
||||
mCallbacksController.clearCallbacks();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import android.os.Bundle;
|
||||
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 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
|
||||
|
||||
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 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
|
||||
}
|
||||
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 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
|
||||
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 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
|
||||
}
|
||||
}
|
||||
|
||||
private final class WindowContextConfigListener implements ComponentCallbacks {
|
||||
private final class ConfigurationChangeListener implements ComponentCallbacks {
|
||||
final IBinder mToken;
|
||||
|
||||
WindowContextConfigListener(IBinder token) {
|
||||
ConfigurationChangeListener(IBinder token) {
|
||||
mToken = token;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user