Add a remote control mechanism for window containers
This adds a "IWindowContainer" interface which is an opaque
handle to a window-container in WM. It has very minimal
functionality and is intended to be used mostly as an
identifier.
Along with this handle, there is a WindowContainerTransaction
which can collect a set of container + configuration changess
and apply them all together. This will be used for remote
rotation control and other batched operations in the future.
Bug: 124011688
Test: Added some wm/core tests.
Change-Id: I691e7c11cd8c30f1a24fd64c6018a18933047847
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 3da8481..222f26e 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -227,6 +227,7 @@
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
+import android.view.WindowContainerTransaction;
import android.view.WindowManager;
import com.android.internal.R;
@@ -289,6 +290,7 @@
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -3249,6 +3251,47 @@
}
}
+ private void sanitizeAndApplyConfigChange(ConfigurationContainer container,
+ WindowContainerTransaction.Change change) {
+ if (!(container instanceof TaskRecord)) {
+ throw new RuntimeException("Invalid token in task transaction");
+ }
+ // The "client"-facing API should prevent bad changes; however, just in case, sanitize
+ // masks here.
+ int configMask = change.getConfigSetMask();
+ int windowMask = change.getWindowSetMask();
+ configMask &= ActivityInfo.CONFIG_WINDOW_CONFIGURATION
+ | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+ windowMask &= WindowConfiguration.WINDOW_CONFIG_BOUNDS;
+ Configuration c = new Configuration(container.getRequestedOverrideConfiguration());
+ c.setTo(change.getConfiguration(), configMask, windowMask);
+ container.onRequestedOverrideConfigurationChanged(c);
+ }
+
+ @Override
+ public void applyContainerTransaction(WindowContainerTransaction t) {
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "applyContainerTransaction()");
+ long ident = Binder.clearCallingIdentity();
+ try {
+ if (t == null) {
+ return;
+ }
+ synchronized (mGlobalLock) {
+ Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries =
+ t.getChanges().entrySet().iterator();
+ while (entries.hasNext()) {
+ final Map.Entry<IBinder, WindowContainerTransaction.Change> entry =
+ entries.next();
+ final ConfigurationContainer cc = ConfigurationContainer.RemoteToken.fromBinder(
+ entry.getKey()).getContainer();
+ sanitizeAndApplyConfigChange(cc, entry.getValue());
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
@Override
public boolean releaseActivityInstance(IBinder token) {
synchronized (mGlobalLock) {