Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8f5f53ca authored by Yuncheol Heo's avatar Yuncheol Heo
Browse files

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
parent 9d3317b8
Loading
Loading
Loading
Loading
+64 −5
Original line number Diff line number Diff line
@@ -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.
+5 −1
Original line number Diff line number Diff line
@@ -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());
        }
+7 −51
Original line number Diff line number Diff line
@@ -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,20 +174,11 @@ 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();
    }

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