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

Commit bdf0cb72 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Use InputConfig flags in InputWindowHandle API

Use the android.os.InputConfig flags to control input window behavior in
InputWindowHandle. This consolidates the old boolean flags and
inputFeatures flags into one set of flags so that the InputConfigs are
the sole set of flags that change change how an input window behaves.

After this change, InputFeatures and LayoutParamsFlags are specific to
WM, which is responsible for converting them into InputConfig flags.
Trivial conversions between these flags are done in InputConfigAdapter.

The LayoutParams type and flags are still part of the this API to send
these attributes to native code. However, they are no longer used by
input.

Bug: 216806304
Test: manual: verify touch functionality
Test: atest WindowStateTests
Change-Id: I5b384770272c111680783ee8ab01ecd6e03f42be
parent ed142dca
Loading
Loading
Loading
Loading
+68 −34
Original line number Diff line number Diff line
@@ -16,20 +16,57 @@

package android.view;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.graphics.Matrix;
import android.graphics.Region;
import android.gui.TouchOcclusionMode;
import android.os.IBinder;
import android.os.InputConfig;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;

/**
 * Functions as a handle for a window that can receive input.
 * Enables the native input dispatcher to refer indirectly to the window manager's window state.
 * Functions as a handle for a window that can receive input, and allows for the behavior of the
 * input window to be configured.
 * @hide
 */
public final class InputWindowHandle {

    /**
     * An internal annotation for all the {@link android.os.InputConfig} flags that can be
     * specified to {@link #inputConfig} to control the behavior of an input window. Only the
     * flags listed here are valid for use in Java.
     *
     * The default flag value is 0, which is what we expect for a normal application window. Adding
     * a flag indicates that the window's behavior deviates from that of a normal application
     * window.
     *
     * The flags are defined as an AIDL enum to keep it in sync with native code.
     * {@link android.os.InputConfig} flags that are not listed here should not be used in Java, and
     * are only meant to be used in native code.
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true, value = {
            InputConfig.DEFAULT,
            InputConfig.NO_INPUT_CHANNEL,
            InputConfig.NOT_FOCUSABLE,
            InputConfig.NOT_TOUCHABLE,
            InputConfig.PREVENT_SPLITTING,
            InputConfig.DUPLICATE_TOUCH_TO_WALLPAPER,
            InputConfig.IS_WALLPAPER,
            InputConfig.PAUSE_DISPATCHING,
            InputConfig.TRUSTED_OVERLAY,
            InputConfig.WATCH_OUTSIDE_TOUCH,
            InputConfig.SLIPPERY,
            InputConfig.DISABLE_USER_ACTIVITY,
            InputConfig.SPY,
            InputConfig.INTERCEPTS_STYLUS,
    })
    public @interface InputConfigFlags {}

    // Pointer to the native input window handle.
    // This field is lazily initialized via JNI.
    @SuppressWarnings("unused")
@@ -57,6 +94,7 @@ public final class InputWindowHandle {
    public String name;

    // Window layout params attributes. (WindowManager.LayoutParams)
    // These values do not affect any input configurations. Use {@link #inputConfig} instead.
    public int layoutParamsFlags;
    public int layoutParamsType;

@@ -78,20 +116,9 @@ public final class InputWindowHandle {
    // Window touchable region.
    public final Region touchableRegion = new Region();

    // Window is visible.
    public boolean visible;

    // Window can be focused.
    public boolean focusable;

    // Window has wallpaper.  (window is the current wallpaper target)
    public boolean hasWallpaper;

    // Input event dispatching is paused.
    public boolean paused;

    // Window is trusted overlay.
    public boolean trustedOverlay;
    // Flags that specify the behavior of this input window. See {@link #InputConfigFlags}.
    @InputConfigFlags
    public int inputConfig;

    // What effect this window has on touch occlusion if it lets touches pass through
    // By default windows will block touches if they are untrusted and from a different UID due to
@@ -105,26 +132,21 @@ public final class InputWindowHandle {
    // Owner package of the window
    public String packageName;

    // Window input features.
    @WindowManager.LayoutParams.InputFeatureFlags
    public int inputFeatures;

    // Display this input is on.
    // Display this input window is on.
    public int displayId;

    /**
     * Crops the touchable region to the bounds of the surface provided.
     * Crops the {@link #touchableRegion} to the bounds of the surface provided.
     *
     * This can be used in cases where the window is not
     * {@link android.view.WindowManager#FLAG_NOT_TOUCH_MODAL} but should be constrained to the
     * bounds of a parent window. That is the window should receive touch events outside its
     * window but be limited to its stack bounds, such as in the case of split screen.
     * This can be used in cases where the window should be constrained to the bounds of a parent
     * window. That is, the window should receive touch events outside its window frame, but be
     * limited to its stack bounds, such as in the case of split screen.
     */
    public WeakReference<SurfaceControl> touchableRegionSurfaceControl = new WeakReference<>(null);

    /**
     * Replace {@link touchableRegion} with the bounds of {@link touchableRegionSurfaceControl}. If
     * the handle is {@code null}, the bounds of the surface associated with this window is used
     * Replace {@link #touchableRegion} with the bounds of {@link #touchableRegionSurfaceControl}.
     * If the handle is {@code null}, the bounds of the surface associated with this window is used
     * as the touchable region.
     */
    public boolean replaceTouchableRegionWithCrop;
@@ -148,7 +170,6 @@ public final class InputWindowHandle {
                .append(", frame=[").append(frameLeft).append(",").append(frameTop).append(",")
                        .append(frameRight).append(",").append(frameBottom).append("]")
                .append(", touchableRegion=").append(touchableRegion)
                .append(", visible=").append(visible)
                .append(", scaleFactor=").append(scaleFactor)
                .append(", transform=").append(transform)
                .append(", windowToken=").append(windowToken)
@@ -166,11 +187,11 @@ public final class InputWindowHandle {
    }

    /**
     * Set the window touchable region to the bounds of {@link touchableRegionBounds} ignoring any
     * touchable region provided.
     * Set the window's touchable region to the bounds of {@link #touchableRegionSurfaceControl}
     * and ignore the value of {@link #touchableRegion}.
     *
     * @param bounds surface to set the touchable region to. Set to {@code null} to set the bounds
     * to the current surface.
     * @param bounds surface to set the touchable region to. Set to {@code null} to set the
     *               touchable region as the current surface bounds.
     */
    public void replaceTouchableRegionWithCrop(@Nullable SurfaceControl bounds) {
        setTouchableRegionCrop(bounds);
@@ -196,4 +217,17 @@ public final class InputWindowHandle {
        window = IWindow.Stub.asInterface(windowToken);
        return window;
    }

    /**
     * Set the provided inputConfig flag values.
     * @param inputConfig the flag values to change
     * @param value the provided flag values are set when true, and cleared when false
     */
    public void setInputConfig(@InputConfigFlags int inputConfig, boolean value) {
        if (value) {
            this.inputConfig |= inputConfig;
            return;
        }
        this.inputConfig &= ~inputConfig;
    }
}
+15 −31
Original line number Diff line number Diff line
@@ -3379,29 +3379,17 @@ public interface WindowManager extends ViewManager {
         * area, but will not stop events from being sent to other windows below it in z-order.
         * An input event will be dispatched to all spy windows above the top non-spy window at the
         * event's coordinates.
         * @hide
         */
        public static final int INPUT_FEATURE_SPY = 1 << 2;

        /**
         * When used with the window flag {@link #FLAG_NOT_TOUCHABLE}, this window will continue
         * to receive events from a stylus device within its touchable region. All other pointer
         * events, such as from a mouse or touchscreen, will be dispatched to the windows behind it.
         *
         * This input feature has no effect when the window flag {@link #FLAG_NOT_TOUCHABLE} is
         * not set.
         *
         * The window must be a trusted overlay to use this input feature.
         *
         * @see #FLAG_NOT_TOUCHABLE
         *
         * @hide
         */
        public static final int INPUT_FEATURE_INTERCEPTS_STYLUS = 1 << 3;
        @RequiresPermission(permission.MONITOR_INPUT)
        public static final int INPUT_FEATURE_SPY = 1 << 2;

        /**
         * An internal annotation for flags that can be specified to {@link #inputFeatures}.
         *
         * NOTE: These are not the same as {@link android.os.InputConfig} flags.
         *
         * @hide
         */
        @Retention(RetentionPolicy.SOURCE)
@@ -3409,18 +3397,18 @@ public interface WindowManager extends ViewManager {
                INPUT_FEATURE_NO_INPUT_CHANNEL,
                INPUT_FEATURE_DISABLE_USER_ACTIVITY,
                INPUT_FEATURE_SPY,
            INPUT_FEATURE_INTERCEPTS_STYLUS,
        })
        public @interface InputFeatureFlags {}
        public @interface InputFeatureFlags {
        }

        /**
         * Control special features of the input subsystem.
         * Control a set of features of the input subsystem that are exposed to the app process.
         *
         * WARNING: Do NOT use {@link android.os.InputConfig} flags! This must be set to flag values
         * included in {@link InputFeatureFlags}.
         *
         * @see #INPUT_FEATURE_NO_INPUT_CHANNEL
         * @see #INPUT_FEATURE_DISABLE_USER_ACTIVITY
         * @see #INPUT_FEATURE_SPY
         * @see #INPUT_FEATURE_INTERCEPTS_STYLUS
         * @hide
         * @see InputFeatureFlags
         */
        @InputFeatureFlags
        @UnsupportedAppUsage
@@ -4840,10 +4828,6 @@ public interface WindowManager extends ViewManager {
                inputFeatures &= ~INPUT_FEATURE_SPY;
                features.add("INPUT_FEATURE_SPY");
            }
            if ((inputFeatures & INPUT_FEATURE_INTERCEPTS_STYLUS) != 0) {
                inputFeatures &= ~INPUT_FEATURE_INTERCEPTS_STYLUS;
                features.add("INPUT_FEATURE_INTERCEPTS_STYLUS");
            }
            if (inputFeatures != 0) {
                features.add(Integer.toHexString(inputFeatures));
            }
+10 −123
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
#include <binder/IPCThreadState.h>
#include <ftl/cast.h>
#include <gui/SurfaceControl.h>
#include <gui/WindowInfo.h>
#include <nativehelper/JNIHelp.h>
@@ -63,16 +64,11 @@ static struct {
    jfieldID surfaceInset;
    jfieldID scaleFactor;
    jfieldID touchableRegion;
    jfieldID visible;
    jfieldID focusable;
    jfieldID hasWallpaper;
    jfieldID paused;
    jfieldID trustedOverlay;
    jfieldID touchOcclusionMode;
    jfieldID ownerPid;
    jfieldID ownerUid;
    jfieldID packageName;
    jfieldID inputFeatures;
    jfieldID inputConfig;
    jfieldID displayId;
    jfieldID replaceTouchableRegionWithCrop;
    WeakRefHandleField touchableRegionSurfaceControl;
@@ -162,95 +158,8 @@ bool NativeInputWindowHandle::updateInfo() {
    mInfo.layoutParamsFlags = flags;
    mInfo.layoutParamsType = type;

    // TODO(b/216806304): Expose InputConfig as InputWindowHandle API so we don't have to use
    //  WindowManager.LayoutParams.InputFeatureFlags here.
    const auto inputFeatures =
            static_cast<uint32_t>(env->GetIntField(obj, gInputWindowHandleClassInfo.inputFeatures));

    using InputConfig = gui::WindowInfo::InputConfig;
    // Determine the value for each of the InputConfig flags. We rely on a switch statement and
    // -Wswitch-enum to give us a build error if we forget to explicitly handle an InputConfig flag.
    mInfo.inputConfig = InputConfig::DEFAULT;
    InputConfig enumerationStart = InputConfig::DEFAULT;
    switch (enumerationStart) {
        case InputConfig::DEFAULT:
            FALLTHROUGH_INTENDED;
        case InputConfig::NO_INPUT_CHANNEL:
            if ((inputFeatures & 0x00000001) != 0) {
                mInfo.inputConfig |= InputConfig::NO_INPUT_CHANNEL;
            }
            FALLTHROUGH_INTENDED;
        case InputConfig::NOT_VISIBLE:
            if (env->GetBooleanField(obj, gInputWindowHandleClassInfo.visible) == JNI_FALSE) {
                mInfo.inputConfig |= InputConfig::NOT_VISIBLE;
            }
            FALLTHROUGH_INTENDED;
        case InputConfig::NOT_FOCUSABLE:
            if (env->GetBooleanField(obj, gInputWindowHandleClassInfo.focusable) == JNI_FALSE) {
                mInfo.inputConfig |= InputConfig::NOT_FOCUSABLE;
            }
            FALLTHROUGH_INTENDED;
        case InputConfig::NOT_TOUCHABLE:
            if (flags.test(WindowInfo::Flag::NOT_TOUCHABLE)) {
                mInfo.inputConfig |= InputConfig::NOT_TOUCHABLE;
            }
            FALLTHROUGH_INTENDED;
        case InputConfig::PREVENT_SPLITTING:
            if (!flags.test(WindowInfo::Flag::SPLIT_TOUCH)) {
                mInfo.inputConfig |= InputConfig::PREVENT_SPLITTING;
            }
            FALLTHROUGH_INTENDED;
        case InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER:
            if (env->GetBooleanField(obj, gInputWindowHandleClassInfo.hasWallpaper) == JNI_TRUE) {
                mInfo.inputConfig |= InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER;
            }
            FALLTHROUGH_INTENDED;
        case InputConfig::IS_WALLPAPER:
            if (type == WindowInfo::Type::WALLPAPER) {
                mInfo.inputConfig |= InputConfig::IS_WALLPAPER;
            }
            FALLTHROUGH_INTENDED;
        case InputConfig::PAUSE_DISPATCHING:
            if (env->GetBooleanField(obj, gInputWindowHandleClassInfo.paused) == JNI_TRUE) {
                mInfo.inputConfig |= InputConfig::PAUSE_DISPATCHING;
            }
            FALLTHROUGH_INTENDED;
        case InputConfig::TRUSTED_OVERLAY:
            if (env->GetBooleanField(obj, gInputWindowHandleClassInfo.trustedOverlay) == JNI_TRUE) {
                mInfo.inputConfig |= InputConfig::TRUSTED_OVERLAY;
            }
            FALLTHROUGH_INTENDED;
        case InputConfig::WATCH_OUTSIDE_TOUCH:
            if (flags.test(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH)) {
                mInfo.inputConfig |= InputConfig::WATCH_OUTSIDE_TOUCH;
            }
            FALLTHROUGH_INTENDED;
        case InputConfig::SLIPPERY:
            if (flags.test(WindowInfo::Flag::SLIPPERY)) {
                mInfo.inputConfig |= InputConfig::SLIPPERY;
            }
            FALLTHROUGH_INTENDED;
        case InputConfig::DISABLE_USER_ACTIVITY:
            if ((inputFeatures & 0x00000002) != 0) {
                mInfo.inputConfig |= InputConfig::DISABLE_USER_ACTIVITY;
            }
            FALLTHROUGH_INTENDED;
        case InputConfig::DROP_INPUT:
            // This flag cannot be set from Java.
            FALLTHROUGH_INTENDED;
        case InputConfig::DROP_INPUT_IF_OBSCURED:
            // This flag cannot be set from Java.
            FALLTHROUGH_INTENDED;
        case InputConfig::SPY:
            if ((inputFeatures & 0x00000004) != 0) {
                mInfo.inputConfig |= InputConfig::SPY;
            }
            FALLTHROUGH_INTENDED;
        case InputConfig::INTERCEPTS_STYLUS:
            if ((inputFeatures & 0x00000008) != 0) {
                mInfo.inputConfig |= InputConfig::INTERCEPTS_STYLUS;
            }
    }
    mInfo.inputConfig = static_cast<gui::WindowInfo::InputConfig>(
            env->GetIntField(obj, gInputWindowHandleClassInfo.inputConfig));

    mInfo.touchOcclusionMode = static_cast<TouchOcclusionMode>(
            env->GetIntField(obj, gInputWindowHandleClassInfo.touchOcclusionMode));
@@ -388,17 +297,6 @@ jobject android_view_InputWindowHandle_fromWindowInfo(JNIEnv* env, gui::WindowIn
    env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.touchableRegion,
                        regionObj.get());

    using InputConfig = gui::WindowInfo::InputConfig;
    env->SetBooleanField(inputWindowHandle, gInputWindowHandleClassInfo.visible,
                         !windowInfo.inputConfig.test(InputConfig::NOT_VISIBLE));
    env->SetBooleanField(inputWindowHandle, gInputWindowHandleClassInfo.focusable,
                         !windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_FOCUSABLE));
    env->SetBooleanField(inputWindowHandle, gInputWindowHandleClassInfo.hasWallpaper,
                         windowInfo.inputConfig.test(InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER));
    env->SetBooleanField(inputWindowHandle, gInputWindowHandleClassInfo.paused,
                         windowInfo.inputConfig.test(InputConfig::PAUSE_DISPATCHING));
    env->SetBooleanField(inputWindowHandle, gInputWindowHandleClassInfo.trustedOverlay,
                         windowInfo.inputConfig.test(InputConfig::TRUSTED_OVERLAY));
    env->SetIntField(inputWindowHandle, gInputWindowHandleClassInfo.touchOcclusionMode,
                     static_cast<int32_t>(windowInfo.touchOcclusionMode));
    env->SetIntField(inputWindowHandle, gInputWindowHandleClassInfo.ownerPid, windowInfo.ownerPid);
@@ -406,8 +304,11 @@ jobject android_view_InputWindowHandle_fromWindowInfo(JNIEnv* env, gui::WindowIn
    ScopedLocalRef<jstring> packageName(env, env->NewStringUTF(windowInfo.packageName.data()));
    env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.packageName,
                        packageName.get());
    // TODO(b/216806304): Write InputConfig flag to Java once it's exposed as an InputWindowHandle
    //  API.

    const auto inputConfig = windowInfo.inputConfig.get();
    static_assert(sizeof(inputConfig) == sizeof(int32_t));
    env->SetIntField(inputWindowHandle, gInputWindowHandleClassInfo.inputConfig,
                     static_cast<int32_t>(inputConfig));

    float transformVals[9];
    for (int i = 0; i < 9; i++) {
@@ -510,19 +411,6 @@ int register_android_view_InputWindowHandle(JNIEnv* env) {
    GET_FIELD_ID(gInputWindowHandleClassInfo.touchableRegion, clazz,
            "touchableRegion", "Landroid/graphics/Region;");

    GET_FIELD_ID(gInputWindowHandleClassInfo.visible, clazz,
            "visible", "Z");

    GET_FIELD_ID(gInputWindowHandleClassInfo.focusable, clazz, "focusable", "Z");

    GET_FIELD_ID(gInputWindowHandleClassInfo.hasWallpaper, clazz,
            "hasWallpaper", "Z");

    GET_FIELD_ID(gInputWindowHandleClassInfo.paused, clazz,
            "paused", "Z");

    GET_FIELD_ID(gInputWindowHandleClassInfo.trustedOverlay, clazz, "trustedOverlay", "Z");

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

    GET_FIELD_ID(gInputWindowHandleClassInfo.ownerPid, clazz,
@@ -534,8 +422,7 @@ int register_android_view_InputWindowHandle(JNIEnv* env) {
    GET_FIELD_ID(gInputWindowHandleClassInfo.packageName, clazz, "packageName",
                 "Ljava/lang/String;");

    GET_FIELD_ID(gInputWindowHandleClassInfo.inputFeatures, clazz,
            "inputFeatures", "I");
    GET_FIELD_ID(gInputWindowHandleClassInfo.inputConfig, clazz, "inputConfig", "I");

    GET_FIELD_ID(gInputWindowHandleClassInfo.displayId, clazz,
            "displayId", "I");
+3 −7
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.input;
import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;

import android.os.IBinder;
import android.os.InputConfig;
import android.view.InputApplicationHandle;
import android.view.InputChannel;
import android.view.InputMonitor;
@@ -56,18 +57,13 @@ class GestureMonitorSpyWindow {
        mWindowHandle.name = name;
        mWindowHandle.token = mClientChannel.getToken();
        mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
        mWindowHandle.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
        mWindowHandle.visible = true;
        mWindowHandle.focusable = false;
        mWindowHandle.hasWallpaper = false;
        mWindowHandle.paused = false;
        mWindowHandle.ownerPid = pid;
        mWindowHandle.ownerUid = uid;
        mWindowHandle.inputFeatures = WindowManager.LayoutParams.INPUT_FEATURE_SPY;
        mWindowHandle.scaleFactor = 1.0f;
        mWindowHandle.trustedOverlay = true;
        mWindowHandle.replaceTouchableRegionWithCrop(null /* use this surface's bounds */);
        mWindowHandle.inputConfig =
                InputConfig.NOT_FOCUSABLE | InputConfig.SPY | InputConfig.TRUSTED_OVERLAY;

        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
        t.setInputWindowInfo(mInputSurface, mWindowHandle);
+8 −10
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.inputmethod;
import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;

import android.annotation.NonNull;
import android.os.InputConfig;
import android.os.Process;
import android.view.InputApplicationHandle;
import android.view.InputChannel;
@@ -56,20 +57,17 @@ final class HandwritingEventReceiverSurface {
        mWindowHandle.name = name;
        mWindowHandle.token = mClientChannel.getToken();
        mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
        mWindowHandle.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
        mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
        mWindowHandle.visible = true;
        mWindowHandle.focusable = false;
        mWindowHandle.hasWallpaper = false;
        mWindowHandle.paused = false;
        mWindowHandle.ownerPid = Process.myPid();
        mWindowHandle.ownerUid = Process.myUid();
        mWindowHandle.inputFeatures = WindowManager.LayoutParams.INPUT_FEATURE_SPY
                | WindowManager.LayoutParams.INPUT_FEATURE_INTERCEPTS_STYLUS;
        mWindowHandle.scaleFactor = 1.0f;
        mWindowHandle.trustedOverlay = true;
        mWindowHandle.replaceTouchableRegionWithCrop(null /* use this surface's bounds */);
        mWindowHandle.inputConfig =
                InputConfig.NOT_FOCUSABLE
                        | InputConfig.NOT_TOUCHABLE
                        | InputConfig.SPY
                        | InputConfig.INTERCEPTS_STYLUS
                        | InputConfig.TRUSTED_OVERLAY;

        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
        t.setInputWindowInfo(mInputSurface, mWindowHandle);
@@ -85,7 +83,7 @@ final class HandwritingEventReceiverSurface {
    void startIntercepting(int imePid, int imeUid) {
        mWindowHandle.ownerPid = imePid;
        mWindowHandle.ownerUid = imeUid;
        mWindowHandle.inputFeatures &= ~WindowManager.LayoutParams.INPUT_FEATURE_SPY;
        mWindowHandle.inputConfig &= ~InputConfig.SPY;

        new SurfaceControl.Transaction()
                .setInputWindowInfo(mInputSurface, mWindowHandle)
Loading