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
This commit is contained in:
Yuncheol Heo
2020-05-01 11:50:52 -07:00
parent 9d3317b8da
commit 8f5f53ca0f
3 changed files with 76 additions and 57 deletions

View File

@@ -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.
* <p>
* 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.
* <p>
* 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.
* <p>This class must finish initializing before {@link #startActivity(Intent)} can be called.

View File

@@ -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());
}

View File

@@ -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.
* <p>
* 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 */,