summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Rob Carr <racarr@google.com> 2022-01-15 21:11:07 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-01-15 21:11:07 +0000
commit87945271bd6bf3d48eb7f0f43698eae3ab166e64 (patch)
tree57cc37296d54e77f90f32ee9367cd3a22d4df532
parente5ee7c84738c5f738eab9585d87c71a3d2e9bbc6 (diff)
parent5d4ef457c51b4d545b7cc40f43fcd94101675bbf (diff)
Merge changes I82c427ad,I5806d69d
* changes: WindowManager: Add basics of generic overlay support. WindowManager Task: Update surface visibility
-rw-r--r--services/core/java/com/android/server/wm/OverlayHost.java129
-rw-r--r--services/core/java/com/android/server/wm/Task.java15
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java32
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerInternal.java13
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java23
5 files changed, 212 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/wm/OverlayHost.java b/services/core/java/com/android/server/wm/OverlayHost.java
new file mode 100644
index 000000000000..14f8983571c8
--- /dev/null
+++ b/services/core/java/com/android/server/wm/OverlayHost.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.content.res.Configuration;
+import android.view.SurfaceControl;
+import android.view.SurfaceControlViewHost;
+
+import java.util.ArrayList;
+
+/**
+ * Utility class to assist WindowContainer in the hosting of
+ * SurfacePackage based overlays. Manages overlays inside
+ * one parent control, and manages the lifetime of that parent control
+ * in order to obscure details from WindowContainer.
+ *
+ * Also handles multiplexing of event dispatch and tracking of overlays
+ * to make things easier for WindowContainer.
+ */
+class OverlayHost {
+ // Lazily initialized when required
+ SurfaceControl mSurfaceControl;
+ final ArrayList<SurfaceControlViewHost.SurfacePackage> mOverlays = new ArrayList<>();
+ final WindowManagerService mWmService;
+
+ OverlayHost(WindowManagerService wms) {
+ mWmService = wms;
+ }
+
+ void requireOverlaySurfaceControl() {
+ if (mSurfaceControl == null) {
+ final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(null)
+ .setContainerLayer()
+ .setHidden(true)
+ .setName("Overlay Host Leash");
+
+ mSurfaceControl = b.build();
+ }
+ }
+
+ void setParent(SurfaceControl.Transaction t, SurfaceControl newParent) {
+ if (mSurfaceControl == null) {
+ return;
+ }
+ t.reparent(mSurfaceControl, newParent);
+ if (newParent != null) {
+ t.show(mSurfaceControl);
+ } else {
+ t.hide(mSurfaceControl);
+ }
+ }
+
+ void setLayer(SurfaceControl.Transaction t, int layer) {
+ if (mSurfaceControl != null) {
+ t.setLayer(mSurfaceControl, layer);
+ }
+ }
+
+ void addOverlay(SurfaceControlViewHost.SurfacePackage p, SurfaceControl currentParent) {
+ requireOverlaySurfaceControl();
+ mOverlays.add(p);
+
+ SurfaceControl.Transaction t = mWmService.mTransactionFactory.get();
+ t.reparent(p.getSurfaceControl(), mSurfaceControl)
+ .show(p.getSurfaceControl());
+ setParent(t,currentParent);
+ t.apply();
+ }
+
+ boolean removeOverlay(SurfaceControlViewHost.SurfacePackage p) {
+ final SurfaceControl.Transaction t = mWmService.mTransactionFactory.get();
+
+ for (int i = mOverlays.size() - 1; i >= 0; i--) {
+ SurfaceControlViewHost.SurfacePackage l = mOverlays.get(i);
+ if (l.getSurfaceControl().isSameSurface(p.getSurfaceControl())) {
+ mOverlays.remove(i);
+ t.reparent(l.getSurfaceControl(), null);
+ l.release();
+ }
+ }
+ t.apply();
+ return mOverlays.size() > 0;
+ }
+
+ void dispatchConfigurationChanged(Configuration c) {
+ for (int i = mOverlays.size() - 1; i >= 0; i--) {
+ SurfaceControlViewHost.SurfacePackage l = mOverlays.get(i);
+ try {
+ l.getRemoteInterface().onConfigurationChanged(c);
+ } catch (Exception e) {
+ removeOverlay(l);
+ }
+ }
+ }
+
+ private void dispatchDetachedFromWindow() {
+ for (int i = mOverlays.size() - 1; i >= 0; i--) {
+ SurfaceControlViewHost.SurfacePackage l = mOverlays.get(i);
+ try {
+ l.getRemoteInterface().onDispatchDetachedFromWindow();
+ } catch (Exception e) {
+ // Oh well we are tearing down anyway.
+ }
+ l.release();
+ }
+ }
+
+ void release() {
+ dispatchDetachedFromWindow();
+ mOverlays.clear();
+ final SurfaceControl.Transaction t = mWmService.mTransactionFactory.get();
+ t.remove(mSurfaceControl).apply();
+ mSurfaceControl = null;
+ }
+}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index dc170900b659..cfd1f6e2e36b 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -125,6 +125,8 @@ import static com.android.server.wm.TaskProto.SURFACE_HEIGHT;
import static com.android.server.wm.TaskProto.SURFACE_WIDTH;
import static com.android.server.wm.TaskProto.TASK_FRAGMENT;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
+import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainerChildProto.TASK;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
@@ -609,6 +611,8 @@ class Task extends TaskFragment {
*/
ActivityRecord mChildPipActivity;
+ boolean mLastSurfaceShowing = true;
+
private Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent,
Intent _affinityIntent, String _affinity, String _rootAffinity,
ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
@@ -3308,6 +3312,17 @@ class Task extends TaskFragment {
if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
scheduleAnimation();
}
+
+ // We intend to let organizer manage task visibility but it doesn't
+ // have enough information until we finish shell transitions.
+ // In the mean time we do an easy fix here.
+ final boolean show = isVisible() || isAnimating(TRANSITION | PARENTS);
+ if (mSurfaceControl != null) {
+ if (show != mLastSurfaceShowing) {
+ getSyncTransaction().setVisibility(mSurfaceControl, show);
+ }
+ }
+ mLastSurfaceShowing = show;
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 61acb97c9db1..137d7f869e4e 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -85,6 +85,7 @@ import android.view.MagnificationSpec;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
+import android.view.SurfaceControlViewHost;
import android.view.SurfaceControl.Builder;
import android.view.SurfaceSession;
import android.view.TaskTransitionSpec;
@@ -312,6 +313,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
private final List<WindowContainerListener> mListeners = new ArrayList<>();
+ private OverlayHost mOverlayHost;
+
WindowContainer(WindowManagerService wms) {
mWmService = wms;
mTransitionController = mWmService.mAtmService.getTransitionController();
@@ -341,6 +344,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
super.onConfigurationChanged(newParentConfig);
updateSurfacePositionNonOrganized();
scheduleAnimation();
+ if (mOverlayHost != null) {
+ mOverlayHost.dispatchConfigurationChanged(getConfiguration());
+ }
}
void reparent(WindowContainer newParent, int position) {
@@ -487,6 +493,11 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
t.reparent(sc, mSurfaceControl);
}
}
+
+ if (mOverlayHost != null) {
+ mOverlayHost.setParent(t, mSurfaceControl);
+ }
+
scheduleAnimation();
}
@@ -632,6 +643,10 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
mLastSurfacePosition.set(0, 0);
scheduleAnimation();
}
+ if (mOverlayHost != null) {
+ mOverlayHost.release();
+ mOverlayHost = null;
+ }
// This must happen after updating the surface so that sync transactions can be handled
// properly.
@@ -2308,6 +2323,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
wc.assignLayer(t, layer++);
}
}
+ if (mOverlayHost != null) {
+ mOverlayHost.setLayer(t, layer++);
+ }
}
void assignChildLayers() {
@@ -3570,4 +3588,18 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
@AnimationType int type, @Nullable AnimationAdapter snapshotAnim);
}
+
+ void addOverlay(SurfaceControlViewHost.SurfacePackage overlay) {
+ if (mOverlayHost == null) {
+ mOverlayHost = new OverlayHost(mWmService);
+ }
+ mOverlayHost.addOverlay(overlay, mSurfaceControl);
+ }
+
+ void removeOverlay(SurfaceControlViewHost.SurfacePackage overlay) {
+ if (mOverlayHost != null && !mOverlayHost.removeOverlay(overlay)) {
+ mOverlayHost.release();
+ mOverlayHost = null;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 62c674b15f89..1ab191bb6650 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -32,6 +32,7 @@ import android.view.IWindow;
import android.view.InputChannel;
import android.view.MagnificationSpec;
import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControlViewHost;
import android.view.WindowInfo;
import android.view.WindowManager.DisplayImePolicy;
@@ -767,4 +768,16 @@ public abstract class WindowManagerInternal {
* {@code false} otherwise.
*/
public abstract boolean shouldRestoreImeVisibility(IBinder imeTargetWindowToken);
+
+ /**
+ * Internal methods for other parts of SystemServer to manage
+ * SurfacePackage based overlays on tasks.
+ *
+ * Callers prepare a view hierarchy with SurfaceControlViewHost
+ * and send the package to WM here. The remote view hierarchy will receive
+ * configuration change, lifecycle events, etc, forwarded over the
+ * ISurfaceControlViewHost interface inside the SurfacePackage.
+ */
+ public abstract void addTaskOverlay(int taskId, SurfaceControlViewHost.SurfacePackage overlay);
+ public abstract void removeTaskOverlay(int taskId, SurfaceControlViewHost.SurfacePackage overlay);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 7d9a13480dc6..e4216bfb6679 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -267,6 +267,7 @@ import android.view.RemoteAnimationAdapter;
import android.view.ScrollCaptureResponse;
import android.view.Surface;
import android.view.SurfaceControl;
+import android.view.SurfaceControlViewHost;
import android.view.SurfaceSession;
import android.view.TaskTransitionSpec;
import android.view.View;
@@ -7910,6 +7911,28 @@ public class WindowManagerService extends IWindowManager.Stub
public boolean shouldRestoreImeVisibility(IBinder imeTargetWindowToken) {
return WindowManagerService.this.shouldRestoreImeVisibility(imeTargetWindowToken);
}
+
+ @Override
+ public void addTaskOverlay(int taskId, SurfaceControlViewHost.SurfacePackage overlay) {
+ synchronized (mGlobalLock) {
+ final Task task = mRoot.getRootTask(taskId);
+ if (task == null) {
+ throw new IllegalArgumentException("no task with taskId" + taskId);
+ }
+ task.addOverlay(overlay);
+ }
+ }
+
+ @Override
+ public void removeTaskOverlay(int taskId, SurfaceControlViewHost.SurfacePackage overlay) {
+ synchronized (mGlobalLock) {
+ final Task task = mRoot.getRootTask(taskId);
+ if (task == null) {
+ throw new IllegalArgumentException("no task with taskId" + taskId);
+ }
+ task.removeOverlay(overlay);
+ }
+ }
}
void registerAppFreezeListener(AppFreezeListener listener) {