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

Commit a4f617f4 authored by Prabir Pradhan's avatar Prabir Pradhan Committed by Android (Google) Code Review
Browse files

Merge "Ensure handwriting session can only be started from inside app bounds" into tm-dev

parents 2ec1d951 4f4eece2
Loading
Loading
Loading
Loading
+32 −0
Original line number Original line Diff line number Diff line
@@ -164,6 +164,38 @@ public final class InputWindowHandle {
        this.displayId = displayId;
        this.displayId = displayId;
    }
    }


    public InputWindowHandle(InputWindowHandle other) {
        // Do not copy ptr to prevent this copy from sharing the same native object.
        ptr = 0;
        inputApplicationHandle = new InputApplicationHandle(other.inputApplicationHandle);
        token = other.token;
        windowToken = other.windowToken;
        window = other.window;
        name = other.name;
        layoutParamsFlags = other.layoutParamsFlags;
        layoutParamsType = other.layoutParamsType;
        dispatchingTimeoutMillis = other.dispatchingTimeoutMillis;
        frameLeft = other.frameLeft;
        frameTop = other.frameTop;
        frameRight = other.frameRight;
        frameBottom = other.frameBottom;
        surfaceInset = other.surfaceInset;
        scaleFactor = other.scaleFactor;
        touchableRegion.set(other.touchableRegion);
        inputConfig = other.inputConfig;
        touchOcclusionMode = other.touchOcclusionMode;
        ownerPid = other.ownerPid;
        ownerUid = other.ownerUid;
        packageName = other.packageName;
        displayId = other.displayId;
        touchableRegionSurfaceControl = other.touchableRegionSurfaceControl;
        replaceTouchableRegionWithCrop = other.replaceTouchableRegionWithCrop;
        if (other.transform != null) {
            transform = new Matrix();
            transform.set(other.transform);
        }
    }

    @Override
    @Override
    public String toString() {
    public String toString() {
        return new StringBuilder(name != null ? name : "")
        return new StringBuilder(name != null ? name : "")
+11 −7
Original line number Original line Diff line number Diff line
@@ -27,7 +27,6 @@ import android.view.InputWindowHandle;
import android.view.SurfaceControl;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.WindowManager;



final class HandwritingEventReceiverSurface {
final class HandwritingEventReceiverSurface {


    public static final String TAG = HandwritingEventReceiverSurface.class.getSimpleName();
    public static final String TAG = HandwritingEventReceiverSurface.class.getSimpleName();
@@ -39,7 +38,6 @@ final class HandwritingEventReceiverSurface {
    // TODO(b/217538817): Specify the ordering in WM by usage.
    // TODO(b/217538817): Specify the ordering in WM by usage.
    private static final int HANDWRITING_SURFACE_LAYER = Integer.MAX_VALUE - 1;
    private static final int HANDWRITING_SURFACE_LAYER = Integer.MAX_VALUE - 1;


    private final InputApplicationHandle mApplicationHandle;
    private final InputWindowHandle mWindowHandle;
    private final InputWindowHandle mWindowHandle;
    private final InputChannel mClientChannel;
    private final InputChannel mClientChannel;
    private final SurfaceControl mInputSurface;
    private final SurfaceControl mInputSurface;
@@ -47,13 +45,11 @@ final class HandwritingEventReceiverSurface {


    HandwritingEventReceiverSurface(String name, int displayId, @NonNull SurfaceControl sc,
    HandwritingEventReceiverSurface(String name, int displayId, @NonNull SurfaceControl sc,
            @NonNull InputChannel inputChannel) {
            @NonNull InputChannel inputChannel) {
        mApplicationHandle = new InputApplicationHandle(null, name,
                DEFAULT_DISPATCHING_TIMEOUT_MILLIS);

        mClientChannel = inputChannel;
        mClientChannel = inputChannel;
        mInputSurface = sc;
        mInputSurface = sc;


        mWindowHandle = new InputWindowHandle(mApplicationHandle, displayId);
        mWindowHandle = new InputWindowHandle(new InputApplicationHandle(null, name,
                DEFAULT_DISPATCHING_TIMEOUT_MILLIS), displayId);
        mWindowHandle.name = name;
        mWindowHandle.name = name;
        mWindowHandle.token = mClientChannel.getToken();
        mWindowHandle.token = mClientChannel.getToken();
        mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
        mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
@@ -61,7 +57,6 @@ final class HandwritingEventReceiverSurface {
        mWindowHandle.ownerPid = Process.myPid();
        mWindowHandle.ownerPid = Process.myPid();
        mWindowHandle.ownerUid = Process.myUid();
        mWindowHandle.ownerUid = Process.myUid();
        mWindowHandle.scaleFactor = 1.0f;
        mWindowHandle.scaleFactor = 1.0f;
        mWindowHandle.replaceTouchableRegionWithCrop(null /* use this surface's bounds */);
        mWindowHandle.inputConfig =
        mWindowHandle.inputConfig =
                InputConfig.NOT_FOCUSABLE
                InputConfig.NOT_FOCUSABLE
                        | InputConfig.NOT_TOUCHABLE
                        | InputConfig.NOT_TOUCHABLE
@@ -69,6 +64,7 @@ final class HandwritingEventReceiverSurface {
                        | InputConfig.INTERCEPTS_STYLUS
                        | InputConfig.INTERCEPTS_STYLUS
                        | InputConfig.TRUSTED_OVERLAY;
                        | InputConfig.TRUSTED_OVERLAY;


        // The touchable region of this input surface is not initially configured.
        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
        t.setInputWindowInfo(mInputSurface, mWindowHandle);
        t.setInputWindowInfo(mInputSurface, mWindowHandle);
        t.setLayer(mInputSurface, HANDWRITING_SURFACE_LAYER);
        t.setLayer(mInputSurface, HANDWRITING_SURFACE_LAYER);
@@ -85,6 +81,10 @@ final class HandwritingEventReceiverSurface {
        mWindowHandle.ownerUid = imeUid;
        mWindowHandle.ownerUid = imeUid;
        mWindowHandle.inputConfig &= ~InputConfig.SPY;
        mWindowHandle.inputConfig &= ~InputConfig.SPY;


        // Update the touchable region so that the IME can intercept stylus events
        // across the entire display.
        mWindowHandle.replaceTouchableRegionWithCrop(null /* use this surface's bounds */);

        new SurfaceControl.Transaction()
        new SurfaceControl.Transaction()
                .setInputWindowInfo(mInputSurface, mWindowHandle)
                .setInputWindowInfo(mInputSurface, mWindowHandle)
                .apply();
                .apply();
@@ -108,4 +108,8 @@ final class HandwritingEventReceiverSurface {
    SurfaceControl getSurface() {
    SurfaceControl getSurface() {
        return mInputSurface;
        return mInputSurface;
    }
    }

    InputWindowHandle getInputWindowHandle() {
        return mWindowHandle;
    }
}
}
+21 −4
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@ import android.annotation.AnyThread;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.UiThread;
import android.annotation.UiThread;
import android.hardware.input.InputManagerInternal;
import android.hardware.input.InputManagerInternal;
import android.os.IBinder;
import android.os.Looper;
import android.os.Looper;
import android.util.Slog;
import android.util.Slog;
import android.view.BatchedInputEventReceiver;
import android.view.BatchedInputEventReceiver;
@@ -90,7 +91,7 @@ final class HandwritingModeController {
     * InputEventReceiver that batches events according to the current thread's Choreographer.
     * InputEventReceiver that batches events according to the current thread's Choreographer.
     */
     */
    @UiThread
    @UiThread
    void initializeHandwritingSpy(int displayId) {
    void initializeHandwritingSpy(int displayId, IBinder focusedWindowToken) {
        // When resetting, reuse resources if we are reinitializing on the same display.
        // When resetting, reuse resources if we are reinitializing on the same display.
        reset(displayId == mCurrentDisplayId);
        reset(displayId == mCurrentDisplayId);
        mCurrentDisplayId = displayId;
        mCurrentDisplayId = displayId;
@@ -110,8 +111,16 @@ final class HandwritingModeController {
            Slog.e(TAG, "Failed to create input surface");
            Slog.e(TAG, "Failed to create input surface");
            return;
            return;
        }
        }
        mHandwritingSurface =

                new HandwritingEventReceiverSurface(name, displayId, surface, channel);
        mHandwritingSurface = new HandwritingEventReceiverSurface(
                name, displayId, surface, channel);

        // Configure the handwriting window to receive events over the focused window's bounds.
        mWindowManagerInternal.replaceInputSurfaceTouchableRegionWithWindowCrop(
                mHandwritingSurface.getSurface(),
                mHandwritingSurface.getInputWindowHandle(),
                focusedWindowToken);

        // Use a dup of the input channel so that event processing can be paused by disposing the
        // Use a dup of the input channel so that event processing can be paused by disposing the
        // event receiver without causing a fd hangup.
        // event receiver without causing a fd hangup.
        mHandwritingEventReceiver = new BatchedInputEventReceiver.SimpleBatchedInputEventReceiver(
        mHandwritingEventReceiver = new BatchedInputEventReceiver.SimpleBatchedInputEventReceiver(
@@ -127,6 +136,10 @@ final class HandwritingModeController {
        return OptionalInt.of(mCurrentRequestId);
        return OptionalInt.of(mCurrentRequestId);
    }
    }


    boolean isStylusGestureOngoing() {
        return mRecordingGesture;
    }

    /**
    /**
     * Starts a {@link HandwritingSession} to transfer to the IME.
     * Starts a {@link HandwritingSession} to transfer to the IME.
     *
     *
@@ -145,6 +158,10 @@ final class HandwritingModeController {
            Slog.e(TAG, "Cannot start handwriting session: Invalid request id: " + requestId);
            Slog.e(TAG, "Cannot start handwriting session: Invalid request id: " + requestId);
            return null;
            return null;
        }
        }
        if (!mRecordingGesture) {
            Slog.e(TAG, "Cannot start handwriting session: No stylus gesture is being recorded.");
            return null;
        }
        Objects.requireNonNull(mHandwritingEventReceiver,
        Objects.requireNonNull(mHandwritingEventReceiver,
                "Handwriting session was already transferred to IME.");
                "Handwriting session was already transferred to IME.");
        if (DEBUG) Slog.d(TAG, "Starting handwriting session in display: " + mCurrentDisplayId);
        if (DEBUG) Slog.d(TAG, "Starting handwriting session in display: " + mCurrentDisplayId);
@@ -231,7 +248,7 @@ final class HandwritingModeController {
            mInkWindowInitRunnable = null;
            mInkWindowInitRunnable = null;
        }
        }


        if (action == MotionEvent.ACTION_UP) {
        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
            mRecordingGesture = false;
            mRecordingGesture = false;
            mHandwritingBuffer.clear();
            mHandwritingBuffer.clear();
            return;
            return;
+8 −3
Original line number Original line Diff line number Diff line
@@ -3439,6 +3439,10 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
                    Slog.e(TAG, "Stylus handwriting was not initialized.");
                    Slog.e(TAG, "Stylus handwriting was not initialized.");
                    return;
                    return;
                }
                }
                if (!mHwController.isStylusGestureOngoing()) {
                    Slog.e(TAG, "There is no ongoing stylus gesture to start stylus handwriting.");
                    return;
                }
                if (DEBUG) Slog.v(TAG, "Client requesting Stylus Handwriting to be started");
                if (DEBUG) Slog.v(TAG, "Client requesting Stylus Handwriting to be started");
                final IInputMethodInvoker curMethod = getCurMethodLocked();
                final IInputMethodInvoker curMethod = getCurMethodLocked();
                if (curMethod != null) {
                if (curMethod != null) {
@@ -4831,8 +4835,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
            case MSG_RESET_HANDWRITING: {
            case MSG_RESET_HANDWRITING: {
                synchronized (ImfLock.class) {
                synchronized (ImfLock.class) {
                    if (mBindingController.supportsStylusHandwriting()
                    if (mBindingController.supportsStylusHandwriting()
                            && getCurMethodLocked() != null) {
                            && getCurMethodLocked() != null && mCurFocusedWindow != null) {
                        mHwController.initializeHandwritingSpy(mCurTokenDisplayId);
                        mHwController.initializeHandwritingSpy(
                                mCurTokenDisplayId, mCurFocusedWindow);
                    } else {
                    } else {
                        mHwController.reset();
                        mHwController.reset();
                    }
                    }
@@ -4860,7 +4865,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
                            session.getHandwritingChannel(), session.getRecordedEvents())) {
                            session.getHandwritingChannel(), session.getRecordedEvents())) {
                        // When failed to issue IPCs, re-initialize handwriting state.
                        // When failed to issue IPCs, re-initialize handwriting state.
                        Slog.w(TAG, "Resetting handwriting mode.");
                        Slog.w(TAG, "Resetting handwriting mode.");
                        mHwController.initializeHandwritingSpy(mCurTokenDisplayId);
                        scheduleResetStylusHandwriting();
                    }
                    }
                }
                }
                return true;
                return true;
+23 −0
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@ import android.view.IInputFilter;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IWindow;
import android.view.IWindow;
import android.view.InputChannel;
import android.view.InputChannel;
import android.view.InputWindowHandle;
import android.view.MagnificationSpec;
import android.view.MagnificationSpec;
import android.view.RemoteAnimationTarget;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl;
@@ -853,4 +854,26 @@ public abstract class WindowManagerInternal {
     * support handwriting (Scribe) by the IME.
     * support handwriting (Scribe) by the IME.
     */
     */
    public abstract SurfaceControl getHandwritingSurfaceForDisplay(int displayId);
    public abstract SurfaceControl getHandwritingSurfaceForDisplay(int displayId);

    /**
     * Replaces the touchable region of the provided input surface with the crop of the window with
     * the provided token. This method will associate the inputSurface with a copy of
     * the given inputWindowHandle, where the copy is configured using
     * {@link InputWindowHandle#replaceTouchableRegionWithCrop(SurfaceControl)} with the surface
     * of the provided windowToken.
     *
     * This is a no-op if windowToken is not valid or the window is not found.
     *
     * This does not change any other properties of the inputSurface.
     *
     * This method exists to avoid leaking the window's SurfaceControl outside WindowManagerService.
     *
     * @param inputSurface The surface for which the touchable region should be set.
     * @param inputWindowHandle The {@link InputWindowHandle} for the input surface.
     * @param windowToken The window whose bounds should be used as the touchable region for the
     *                    inputSurface.
     */
    public abstract void replaceInputSurfaceTouchableRegionWithWindowCrop(
            @NonNull SurfaceControl inputSurface, @NonNull InputWindowHandle inputWindowHandle,
            @NonNull IBinder windowToken);
}
}
Loading