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

Commit 54caefd5 authored by Tiger Huang's avatar Tiger Huang Committed by Android (Google) Code Review
Browse files

Merge "Let the activity embedded in ActivityView can be directly touched"

parents 8ffae36f 04dc4cc6
Loading
Loading
Loading
Loading
+6 −47
Original line number Diff line number Diff line
@@ -28,15 +28,12 @@ import android.content.Context;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.hardware.input.InputManager;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.IWindowManager;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceSession;
@@ -51,9 +48,7 @@ import dalvik.system.CloseGuard;
import java.util.List;

/**
 * Activity container that allows launching activities into itself and does input forwarding.
 * <p>Creation of this view is only allowed to callers who have
 * {@link android.Manifest.permission#INJECT_EVENTS} permission.
 * Activity container that allows launching activities into itself.
 * <p>Activity launching into this container is restricted by the same rules that apply to launching
 * on VirtualDisplays.
 * @hide
@@ -76,9 +71,8 @@ public class ActivityView extends ViewGroup {
    private StateCallback mActivityViewCallback;

    private IActivityTaskManager mActivityTaskManager;
    private IInputForwarder mInputForwarder;
    // Temp container to store view coordinates on screen.
    private final int[] mLocationOnScreen = new int[2];
    // Temp container to store view coordinates in window.
    private final int[] mLocationInWindow = new int[2];

    private TaskStackListener mTaskStackListener;

@@ -280,7 +274,7 @@ public class ActivityView extends ViewGroup {
    }

    /**
     * Triggers an update of {@link ActivityView}'s location on screen to properly set touch exclude
     * Triggers an update of {@link ActivityView}'s location in window to properly set touch exclude
     * regions and avoid focus switches by touches on this view.
     */
    public void onLocationChanged() {
@@ -295,45 +289,14 @@ public class ActivityView extends ViewGroup {
    /** Send current location and size to the WM to set tap exclude region for this view. */
    private void updateLocation() {
        try {
            getLocationOnScreen(mLocationOnScreen);
            getLocationInWindow(mLocationInWindow);
            WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
                    mLocationOnScreen[0], mLocationOnScreen[1], getWidth(), getHeight());
                    mLocationInWindow[0], mLocationInWindow[1], getWidth(), getHeight());
        } catch (RemoteException e) {
            e.rethrowAsRuntimeException();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return injectInputEvent(event) || super.onTouchEvent(event);
    }

    @Override
    public boolean onGenericMotionEvent(MotionEvent event) {
        if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
            if (injectInputEvent(event)) {
                return true;
            }
        }
        return super.onGenericMotionEvent(event);
    }

    private boolean injectInputEvent(MotionEvent event) {
        if (mInputForwarder != null) {
            try {
                // The touch event that the ActivityView gets is in View space, but the event needs
                // to get forwarded in screen space. This offsets the touch event by the location
                // the ActivityView is on screen and sends it to the input forwarder.
                getLocationOnScreen(mLocationOnScreen);
                event.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]);
                return mInputForwarder.forwardEvent(event);
            } catch (RemoteException e) {
                e.rethrowAsRuntimeException();
            }
        }
        return false;
    }

    private class SurfaceCallback implements SurfaceHolder.Callback {
        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
@@ -416,7 +379,6 @@ public class ActivityView extends ViewGroup {
        }

        mTmpTransaction.show(mRootSurfaceControl).apply();
        mInputForwarder = InputManager.getInstance().createInputForwarder(displayId);
        mTaskStackListener = new TaskStackListenerImpl();
        try {
            mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
@@ -432,9 +394,6 @@ public class ActivityView extends ViewGroup {

        mSurfaceView.getHolder().removeCallback(mSurfaceCallback);

        if (mInputForwarder != null) {
            mInputForwarder = null;
        }
        cleanTapExcludeRegion();

        if (mTaskStackListener != null) {
+6 −2
Original line number Diff line number Diff line
@@ -16,10 +16,10 @@

package android.view;

import static android.view.Display.INVALID_DISPLAY;

import android.graphics.Region;
import android.os.IBinder;
import android.view.IWindow;
import android.view.InputChannel;

/**
 * Functions as a handle for a window that can receive input.
@@ -94,6 +94,10 @@ public final class InputWindowHandle {
    // Display this input is on.
    public int displayId;

    // If this value is set to a valid display ID, it indicates this window is a portal which
    // transports the touch of this window to the display indicated by portalToDisplayId.
    public int portalToDisplayId = INVALID_DISPLAY;

    private native void nativeDispose();

    public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
+6 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ static struct {
    jfieldID ownerUid;
    jfieldID inputFeatures;
    jfieldID displayId;
    jfieldID portalToDisplayId;
} gInputWindowHandleClassInfo;

static Mutex gHandleMutex;
@@ -154,6 +155,8 @@ bool NativeInputWindowHandle::updateInfo() {
            gInputWindowHandleClassInfo.inputFeatures);
    mInfo.displayId = env->GetIntField(obj,
            gInputWindowHandleClassInfo.displayId);
    mInfo.portalToDisplayId = env->GetIntField(obj,
            gInputWindowHandleClassInfo.portalToDisplayId);

    jobject inputApplicationHandleObj = env->GetObjectField(obj,
            gInputWindowHandleClassInfo.inputApplicationHandle);
@@ -307,6 +310,9 @@ int register_android_view_InputWindowHandle(JNIEnv* env) {

    GET_FIELD_ID(gInputWindowHandleClassInfo.displayId, clazz,
            "displayId", "I");

    GET_FIELD_ID(gInputWindowHandleClassInfo.portalToDisplayId, clazz,
            "portalToDisplayId", "I");
    return 0;
}

+61 −9
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_PRIVATE;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.InsetsState.TYPE_IME;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
@@ -43,6 +44,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
@@ -140,9 +142,11 @@ import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Region.Op;
import android.hardware.display.DisplayManagerInternal;
import android.os.Binder;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
@@ -157,6 +161,7 @@ import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputWindowHandle;
import android.view.InsetsState.InternalInsetType;
import android.view.MagnificationSpec;
import android.view.RemoteAnimationDefinition;
@@ -515,6 +520,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo

    private final InsetsStateController mInsetsStateController;

    private SurfaceControl mParentSurfaceControl;
    private InputWindowHandle mPortalWindowHandle;

    // Last systemUiVisibility we received from status bar.
    private int mLastStatusBarVisibility = 0;
    // Last systemUiVisibility we dispatched to windows.
@@ -2410,10 +2418,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            win.getTouchableRegion(mTmpRegion);
            mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
        }
        for (int i = mTapExcludeProvidingWindows.size() - 1; i >= 0; i--) {
            final WindowState win = mTapExcludeProvidingWindows.valueAt(i);
            win.amendTapExcludeRegion(mTouchExcludeRegion);
        }
        amendWindowTapExcludeRegion(mTouchExcludeRegion);
        // TODO(multi-display): Support docked stacks on secondary displays.
        if (mDisplayId == DEFAULT_DISPLAY && getSplitScreenPrimaryStack() != null) {
            mDividerControllerLocked.getTouchRegion(mTmpRect);
@@ -2425,6 +2430,18 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        }
    }

    /**
     * Union the region with all the tap exclude region provided by windows on this display.
     *
     * @param inOutRegion The region to be amended.
     */
    void amendWindowTapExcludeRegion(Region inOutRegion) {
        for (int i = mTapExcludeProvidingWindows.size() - 1; i >= 0; i--) {
            final WindowState win = mTapExcludeProvidingWindows.valueAt(i);
            win.amendTapExcludeRegion(inOutRegion);
        }
    }

    @Override
    void switchUser() {
        super.switchUser();
@@ -3586,6 +3603,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    private void updateBounds() {
        calculateBounds(mDisplayInfo, mTmpBounds);
        setBounds(mTmpBounds);
        if (mPortalWindowHandle != null && mParentSurfaceControl != null) {
            mPortalWindowHandle.touchableRegion.getBounds(mTmpRect);
            if (!mTmpBounds.equals(mTmpRect)) {
                mPortalWindowHandle.touchableRegion.set(mTmpBounds);
                mPendingTransaction.setInputWindowInfo(mParentSurfaceControl, mPortalWindowHandle);
            }
        }
    }

    // Determines the current display bounds based on the current state
@@ -4834,11 +4858,39 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
     * Re-parent the DisplayContent's top surfaces, {@link #mWindowingLayer} and
     * {@link #mOverlayLayer} to the specified surfaceControl.
     *
     * @param surfaceControlHandle The new SurfaceControl, where the DisplayContent's
     *                             surfaces will be re-parented to.
     * @param sc The new SurfaceControl, where the DisplayContent's surfaces will be re-parented to.
     */
    void reparentDisplayContent(SurfaceControl sc) {
        mPendingTransaction.reparent(mWindowingLayer, sc)
                .reparent(mOverlayLayer, sc);
        mParentSurfaceControl = sc;
        if (mPortalWindowHandle == null) {
            mPortalWindowHandle = createPortalWindowHandle(sc.toString());
        }
        mPendingTransaction.setInputWindowInfo(sc, mPortalWindowHandle)
                .reparent(mWindowingLayer, sc).reparent(mOverlayLayer, sc);
    }

    /**
     * Create a portal window handle for input. This window transports any touch to the display
     * indicated by {@link InputWindowHandle#portalToDisplayId} if the touch hits this window.
     *
     * @param name The name of the portal window handle.
     * @return the new portal window handle.
     */
    private InputWindowHandle createPortalWindowHandle(String name) {
        // Let surface flinger to set the display ID of this input window handle because we don't
        // know which display the parent surface control is on.
        final InputWindowHandle portalWindowHandle = new InputWindowHandle(
                null /* inputApplicationHandle */, null /* clientWindow */, INVALID_DISPLAY);
        portalWindowHandle.name = name;
        portalWindowHandle.token = new Binder();
        portalWindowHandle.layoutParamsFlags =
                FLAG_SPLIT_TOUCH | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL;
        getBounds(mTmpBounds);
        portalWindowHandle.touchableRegion.set(mTmpBounds);
        portalWindowHandle.scaleFactor = 1f;
        portalWindowHandle.ownerPid = Process.myPid();
        portalWindowHandle.ownerUid = Process.myUid();
        portalWindowHandle.portalToDisplayId = mDisplayId;
        return portalWindowHandle;
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -49,7 +49,9 @@ class TapExcludeRegionHolder {
    void amendRegion(Region region, Rect boundingRegion) {
        for (int i = mTapExcludeRects.size() - 1; i>= 0 ; --i) {
            final Rect rect = mTapExcludeRects.valueAt(i);
            if (boundingRegion != null) {
                rect.intersect(boundingRegion);
            }
            region.union(rect);
        }
    }
Loading