Merge "Add WindowProvider support to WindowLayoutComponentImpl and allow WindowProviderService to broadcast configuration changes to listeners." into tm-qpr-dev

This commit is contained in:
An An Yu
2022-11-17 07:39:47 +00:00
committed by Android (Google) Code Review
3 changed files with 70 additions and 12 deletions

View File

@@ -15,8 +15,10 @@
*/ */
package android.window; package android.window;
import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder;
import android.view.WindowManager.LayoutParams.WindowType; import android.view.WindowManager.LayoutParams.WindowType;
/** /**
@@ -36,4 +38,11 @@ public interface WindowProvider {
/** Gets the launch options of this provider */ /** Gets the launch options of this provider */
@Nullable @Nullable
Bundle getWindowContextOptions(); Bundle getWindowContextOptions();
/**
* Gets the WindowContextToken of this provider.
* @see android.content.Context#getWindowContextToken
*/
@NonNull
IBinder getWindowContextToken();
} }

View File

@@ -27,7 +27,10 @@ import android.annotation.UiContext;
import android.app.ActivityThread; import android.app.ActivityThread;
import android.app.LoadedApk; import android.app.LoadedApk;
import android.app.Service; import android.app.Service;
import android.content.ComponentCallbacks;
import android.content.ComponentCallbacksController;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration;
import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
@@ -54,6 +57,8 @@ public abstract class WindowProviderService extends Service implements WindowPro
private final WindowContextController mController = new WindowContextController(mWindowToken); private final WindowContextController mController = new WindowContextController(mWindowToken);
private WindowManager mWindowManager; private WindowManager mWindowManager;
private boolean mInitialized; private boolean mInitialized;
private final ComponentCallbacksController mCallbacksController =
new ComponentCallbacksController();
/** /**
* Returns {@code true} if the {@code windowContextOptions} declares that it is a * 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; 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}. * Returns the display ID to launch this {@link WindowProviderService}.
* *
@@ -181,5 +228,6 @@ public abstract class WindowProviderService extends Service implements WindowPro
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
mController.detachIfNeeded(); mController.detachIfNeeded();
mCallbacksController.clearCallbacks();
} }
} }

View File

@@ -36,6 +36,7 @@ import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.window.WindowContext; import android.window.WindowContext;
import android.window.WindowProvider;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -71,7 +72,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
private final List<CommonFoldingFeature> mLastReportedFoldingFeatures = new ArrayList<>(); private final List<CommonFoldingFeature> mLastReportedFoldingFeatures = new ArrayList<>();
private final Map<IBinder, WindowContextConfigListener> mWindowContextConfigListeners = private final Map<IBinder, ConfigurationChangeListener> mConfigurationChangeListeners =
new ArrayMap<>(); new ArrayMap<>();
public WindowLayoutComponentImpl(@NonNull Context context) { public WindowLayoutComponentImpl(@NonNull Context context) {
@@ -121,21 +122,21 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
} }
if (!context.isUiContext()) { if (!context.isUiContext()) {
throw new IllegalArgumentException("Context must be a UI Context, which should be" 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) -> { mFoldingFeatureProducer.getData((features) -> {
// Get the WindowLayoutInfo from the activity and pass the value to the layoutConsumer.
WindowLayoutInfo newWindowLayout = getWindowLayoutInfo(context, features); WindowLayoutInfo newWindowLayout = getWindowLayoutInfo(context, features);
consumer.accept(newWindowLayout); consumer.accept(newWindowLayout);
}); });
mWindowLayoutChangeListeners.put(context, consumer); 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 IBinder windowContextToken = context.getWindowContextToken();
final WindowContextConfigListener listener = final ConfigurationChangeListener listener =
new WindowContextConfigListener(windowContextToken); new ConfigurationChangeListener(windowContextToken);
context.registerComponentCallbacks(listener); 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)) { if (!mWindowLayoutChangeListeners.get(context).equals(consumer)) {
continue; continue;
} }
if (context instanceof WindowContext) { if (context instanceof WindowProvider) {
final IBinder token = context.getWindowContextToken(); final IBinder token = context.getWindowContextToken();
context.unregisterComponentCallbacks(mWindowContextConfigListeners.get(token)); context.unregisterComponentCallbacks(mConfigurationChangeListeners.get(token));
mWindowContextConfigListeners.remove(token); mConfigurationChangeListeners.remove(token);
} }
break; 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; final IBinder mToken;
WindowContextConfigListener(IBinder token) { ConfigurationChangeListener(IBinder token) {
mToken = token; mToken = token;
} }