Merge "Add WindowProvider support to WindowLayoutComponentImpl and allow WindowProviderService to broadcast configuration changes to listeners." into tm-qpr-dev
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user