From 8f5f53ca0fed52106ebddc84dd5e738e6facd566 Mon Sep 17 00:00:00 2001 From: Yuncheol Heo Date: Fri, 1 May 2020 11:50:52 -0700 Subject: [PATCH] Migrate Tap exclusion logic to TaskEmbedder. We want to pass the touches on ActivityView to the Activity inside ActivityView, not to be consumed by Activity hosting ActivityView. To do that, we need to set a tap exclude region, so touches can go through. Bug: 155424730 Test: Make sure the Activity inside ActivityView gets touch. Change-Id: Ia9b2c7eba0c48512a633c798b1012e5fbec8422f --- core/java/android/window/TaskEmbedder.java | 69 +++++++++++++++++-- .../window/TaskOrganizerTaskEmbedder.java | 6 +- .../window/VirtualDisplayTaskEmbedder.java | 58 ++-------------- 3 files changed, 76 insertions(+), 57 deletions(-) diff --git a/core/java/android/window/TaskEmbedder.java b/core/java/android/window/TaskEmbedder.java index 4257ce0848290..ca6c568c2668c 100644 --- a/core/java/android/window/TaskEmbedder.java +++ b/core/java/android/window/TaskEmbedder.java @@ -36,11 +36,14 @@ import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; import android.hardware.display.VirtualDisplay; +import android.os.RemoteException; import android.os.UserHandle; import android.view.IWindow; import android.view.IWindowManager; +import android.view.IWindowSession; import android.view.KeyEvent; import android.view.SurfaceControl; +import android.view.WindowManagerGlobal; import dalvik.system.CloseGuard; @@ -184,31 +187,45 @@ public abstract class TaskEmbedder { /** * Called when the task embedder should be initialized. + * NOTE: all overriding methods should call this one after they finish their initialization. * @return whether to report whether the embedder was initialized. */ - public abstract boolean onInitialize(); + public boolean onInitialize() { + updateLocationAndTapExcludeRegion(); + return true; + } /** * Called when the task embedder should be released. * @return whether to report whether the embedder was released. */ - protected abstract boolean onRelease(); + protected boolean onRelease() { + // Clear tap-exclude region (if any) for this window. + clearTapExcludeRegion(); + return true; + } /** * Starts presentation of tasks in this container. */ - public abstract void start(); + public void start() { + updateLocationAndTapExcludeRegion(); + } /** * Stops presentation of tasks in this container. */ - public abstract void stop(); + public void stop() { + clearTapExcludeRegion(); + } /** * This should be called whenever the position or size of the surface changes * or if touchable areas above the surface are added or removed. */ - public abstract void notifyBoundsChanged(); + public void notifyBoundsChanged() { + updateLocationAndTapExcludeRegion(); + } /** * Called to update the dimensions whenever the host size changes. @@ -267,6 +284,48 @@ public abstract class TaskEmbedder { // Do nothing } + /** + * Updates position and bounds information needed by WM and IME to manage window + * focus and touch events properly. + *

+ * This should be called whenever the position or size of the surface changes + * or if touchable areas above the surface are added or removed. + */ + protected void updateLocationAndTapExcludeRegion() { + if (!isInitialized() || mHost.getWindow() == null) { + return; + } + applyTapExcludeRegion(mHost.getWindow(), mHost.getTapExcludeRegion()); + } + + /** + * Call to update the tap exclude region for the window. + *

+ * This should not normally be called directly, but through + * {@link #updateLocationAndTapExcludeRegion()}. This method + * is provided as an optimization when managing multiple TaskSurfaces within a view. + * + * @see IWindowSession#updateTapExcludeRegion(IWindow, Region) + */ + private void applyTapExcludeRegion(IWindow window, @Nullable Region tapExcludeRegion) { + try { + IWindowSession session = WindowManagerGlobal.getWindowSession(); + session.updateTapExcludeRegion(window, tapExcludeRegion); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + + /** + * Removes the tap exclude region set by {@link #updateLocationAndTapExcludeRegion()}. + */ + private void clearTapExcludeRegion() { + if (!isInitialized() || mHost.getWindow() == null) { + return; + } + applyTapExcludeRegion(mHost.getWindow(), null); + } + /** * Set the callback to be notified about state changes. *

This class must finish initializing before {@link #startActivity(Intent)} can be called. diff --git a/core/java/android/window/TaskOrganizerTaskEmbedder.java b/core/java/android/window/TaskOrganizerTaskEmbedder.java index 2fb46509f337d..1b87521f3a96c 100644 --- a/core/java/android/window/TaskOrganizerTaskEmbedder.java +++ b/core/java/android/window/TaskOrganizerTaskEmbedder.java @@ -75,7 +75,8 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder { // infrastructure is ready. mTaskOrganizer.registerOrganizer(WINDOWING_MODE_MULTI_WINDOW); mTaskOrganizer.setInterceptBackPressedOnTaskRoot(true); - return true; + + return super.onInitialize(); } @Override @@ -96,6 +97,7 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder { */ @Override public void start() { + super.start(); if (DEBUG) { log("start"); } @@ -119,6 +121,7 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder { */ @Override public void stop() { + super.stop(); if (DEBUG) { log("stop"); } @@ -143,6 +146,7 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder { */ @Override public void notifyBoundsChanged() { + super.notifyBoundsChanged(); if (DEBUG) { log("notifyBoundsChanged: screenBounds=" + mHost.getScreenBounds()); } diff --git a/core/java/android/window/VirtualDisplayTaskEmbedder.java b/core/java/android/window/VirtualDisplayTaskEmbedder.java index 6f85dc263a4d1..2e6cbeee7d22a 100644 --- a/core/java/android/window/VirtualDisplayTaskEmbedder.java +++ b/core/java/android/window/VirtualDisplayTaskEmbedder.java @@ -21,7 +21,6 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_C import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC; import static android.view.Display.INVALID_DISPLAY; -import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.ActivityTaskManager; @@ -40,7 +39,6 @@ import android.os.RemoteException; import android.os.SystemClock; import android.util.DisplayMetrics; import android.util.Log; -import android.view.IWindow; import android.view.IWindowManager; import android.view.IWindowSession; import android.view.InputDevice; @@ -134,20 +132,15 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder { e.rethrowAsRuntimeException(); } - if (mHost.getWindow() != null) { - updateLocationAndTapExcludeRegion(); - } - return true; + return super.onInitialize(); } @Override protected boolean onRelease() { + super.onRelease(); // Clear activity view geometry for IME on this display clearActivityViewGeometryForIme(); - // Clear tap-exclude region (if any) for this window. - clearTapExcludeRegion(); - if (mTaskStackListener != null) { try { mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener); @@ -170,9 +163,9 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder { */ @Override public void start() { + super.start(); if (isInitialized()) { mVirtualDisplay.setDisplayState(true); - updateLocationAndTapExcludeRegion(); } } @@ -181,22 +174,13 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder { */ @Override public void stop() { + super.stop(); if (isInitialized()) { mVirtualDisplay.setDisplayState(false); clearActivityViewGeometryForIme(); - clearTapExcludeRegion(); } } - /** - * This should be called whenever the position or size of the surface changes - * or if touchable areas above the surface are added or removed. - */ - @Override - public void notifyBoundsChanged() { - updateLocationAndTapExcludeRegion(); - } - /** * Called to update the dimensions whenever the host size changes. * @@ -298,12 +282,13 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder { * This should be called whenever the position or size of the surface changes * or if touchable areas above the surface are added or removed. */ - private void updateLocationAndTapExcludeRegion() { + @Override + protected void updateLocationAndTapExcludeRegion() { + super.updateLocationAndTapExcludeRegion(); if (!isInitialized() || mHost.getWindow() == null) { return; } reportLocation(mHost.getScreenToTaskMatrix(), mHost.getPositionInWindow()); - applyTapExcludeRegion(mHost.getWindow(), mHost.getTapExcludeRegion()); } /** @@ -331,24 +316,6 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder { } } - /** - * Call to update the tap exclude region for the window. - *

- * This should not normally be called directly, but through - * {@link #updateLocationAndTapExcludeRegion()}. This method - * is provided as an optimization when managing multiple TaskSurfaces within a view. - * - * @see IWindowSession#updateTapExcludeRegion(IWindow, Region) - */ - private void applyTapExcludeRegion(IWindow window, @Nullable Region tapExcludeRegion) { - try { - IWindowSession session = WindowManagerGlobal.getWindowSession(); - session.updateTapExcludeRegion(window, tapExcludeRegion); - } catch (RemoteException e) { - e.rethrowAsRuntimeException(); - } - } - /** * @see InputMethodManager#reportActivityView(int, Matrix) */ @@ -357,17 +324,6 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder { mContext.getSystemService(InputMethodManager.class).reportActivityView(displayId, null); } - /** - * Removes the tap exclude region set by {@link #updateLocationAndTapExcludeRegion()}. - */ - private void clearTapExcludeRegion() { - if (mHost.getWindow() == null) { - Log.w(TAG, "clearTapExcludeRegion: not attached to window!"); - return; - } - applyTapExcludeRegion(mHost.getWindow(), null); - } - private static KeyEvent createKeyEvent(int action, int code, int displayId) { long when = SystemClock.uptimeMillis(); final KeyEvent ev = new KeyEvent(when, when, action, code, 0 /* repeat */,