From ed142dcacbf044ab120a205f4736513c0a9277e1 Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Mon, 7 Feb 2022 06:10:36 -0800 Subject: [PATCH 1/2] WindowInfo: Merge InputConfig and Feature flags InputFeatureFlags are now a WM-only flag, but is temporarily used by InputWindowHandle until the cleanup is completed. Bug: 216806304 Test: atest libgui_test Test: atest inputflinger_tests Change-Id: I1260431e99d2c50261dc8b0356dc3e21ba76d39f --- core/java/android/view/InputWindowHandle.java | 1 + core/java/android/view/WindowManager.java | 15 +++---- ...droid_hardware_input_InputWindowHandle.cpp | 43 ++++++++++++++++--- 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java index 2b579d09d3a22..44a0e891e21e5 100644 --- a/core/java/android/view/InputWindowHandle.java +++ b/core/java/android/view/InputWindowHandle.java @@ -106,6 +106,7 @@ public final class InputWindowHandle { public String packageName; // Window input features. + @WindowManager.LayoutParams.InputFeatureFlags public int inputFeatures; // Display this input is on. diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index dbfae46a6e724..b4b354bc32439 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -106,7 +106,6 @@ import android.graphics.Region; import android.os.Build; import android.os.Bundle; import android.os.IBinder; -import android.os.IInputConstants; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -3360,8 +3359,7 @@ public interface WindowManager extends ViewManager { * * @hide */ - public static final int INPUT_FEATURE_NO_INPUT_CHANNEL = - IInputConstants.InputFeature.NO_INPUT_CHANNEL; + public static final int INPUT_FEATURE_NO_INPUT_CHANNEL = 1 << 0; /** * When this window has focus, does not call user activity for all input events so @@ -3374,18 +3372,16 @@ public interface WindowManager extends ViewManager { * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static final int INPUT_FEATURE_DISABLE_USER_ACTIVITY = - IInputConstants.InputFeature.DISABLE_USER_ACTIVITY; + public static final int INPUT_FEATURE_DISABLE_USER_ACTIVITY = 1 << 1; /** * An input spy window. This window will receive all pointer events within its touchable - * area, but will will not stop events from being sent to other windows below it in z-order. + * 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 = - IInputConstants.InputFeature.SPY; + public static final int INPUT_FEATURE_SPY = 1 << 2; /** * When used with the window flag {@link #FLAG_NOT_TOUCHABLE}, this window will continue @@ -3401,8 +3397,7 @@ public interface WindowManager extends ViewManager { * * @hide */ - public static final int INPUT_FEATURE_INTERCEPTS_STYLUS = - IInputConstants.InputFeature.INTERCEPTS_STYLUS; + public static final int INPUT_FEATURE_INTERCEPTS_STYLUS = 1 << 3; /** * An internal annotation for flags that can be specified to {@link #inputFeatures}. diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp index f453d1f06e22c..0ffeb617690c9 100644 --- a/core/jni/android_hardware_input_InputWindowHandle.cpp +++ b/core/jni/android_hardware_input_InputWindowHandle.cpp @@ -162,13 +162,23 @@ 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(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::NONE; - InputConfig enumerationStart = InputConfig::NONE; + mInfo.inputConfig = InputConfig::DEFAULT; + InputConfig enumerationStart = InputConfig::DEFAULT; switch (enumerationStart) { - case InputConfig::NONE: + 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) { @@ -219,6 +229,27 @@ bool NativeInputWindowHandle::updateInfo() { 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.touchOcclusionMode = static_cast( @@ -228,8 +259,6 @@ bool NativeInputWindowHandle::updateInfo() { mInfo.ownerUid = env->GetIntField(obj, gInputWindowHandleClassInfo.ownerUid); mInfo.packageName = getStringField(env, obj, gInputWindowHandleClassInfo.packageName, ""); - mInfo.inputFeatures = static_cast( - env->GetIntField(obj, gInputWindowHandleClassInfo.inputFeatures)); mInfo.displayId = env->GetIntField(obj, gInputWindowHandleClassInfo.displayId); @@ -377,8 +406,8 @@ jobject android_view_InputWindowHandle_fromWindowInfo(JNIEnv* env, gui::WindowIn ScopedLocalRef packageName(env, env->NewStringUTF(windowInfo.packageName.data())); env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.packageName, packageName.get()); - env->SetIntField(inputWindowHandle, gInputWindowHandleClassInfo.inputFeatures, - static_cast(windowInfo.inputFeatures.get())); + // TODO(b/216806304): Write InputConfig flag to Java once it's exposed as an InputWindowHandle + // API. float transformVals[9]; for (int i = 0; i < 9; i++) { From bdf0cb726262ea8345cfa6b22e431e93b7062fe3 Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Mon, 7 Feb 2022 12:34:38 -0800 Subject: [PATCH 2/2] 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 --- core/java/android/view/InputWindowHandle.java | 102 ++++++++----- core/java/android/view/WindowManager.java | 46 ++---- ...droid_hardware_input_InputWindowHandle.cpp | 133 ++--------------- .../server/input/GestureMonitorSpyWindow.java | 10 +- .../HandwritingEventReceiverSurface.java | 18 +-- .../wm/AccessibilityWindowsPopulator.java | 7 +- .../server/wm/ActivityRecordInputSink.java | 7 +- .../java/com/android/server/wm/DragState.java | 40 ++--- .../android/server/wm/InputConfigAdapter.java | 138 ++++++++++++++++++ .../android/server/wm/InputConsumerImpl.java | 12 +- .../com/android/server/wm/InputMonitor.java | 60 ++++---- .../server/wm/InputWindowHandleWrapper.java | 65 +++++---- .../java/com/android/server/wm/Letterbox.java | 7 +- .../com/android/server/wm/TaskPositioner.java | 20 +-- .../server/wm/TaskPositioningController.java | 15 +- .../server/wm/WindowManagerService.java | 52 ++++--- .../com/android/server/wm/WindowState.java | 1 + .../android/server/wm/StubTransaction.java | 7 + .../android/server/wm/WindowStateTests.java | 21 ++- 19 files changed, 406 insertions(+), 355 deletions(-) create mode 100644 services/core/java/com/android/server/wm/InputConfigAdapter.java diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java index 44a0e891e21e5..ef0c19c8dc02b 100644 --- a/core/java/android/view/InputWindowHandle.java +++ b/core/java/android/view/InputWindowHandle.java @@ -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") @@ -56,7 +93,8 @@ public final class InputWindowHandle { // The window name. public String name; - // Window layout params attributes. (WindowManager.LayoutParams) + // 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 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; + } } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index b4b354bc32439..45169efd7d356 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -3379,48 +3379,36 @@ 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 */ + @RequiresPermission(permission.MONITOR_INPUT) 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; - /** * 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) - @IntDef(flag = true, prefix = { "INPUT_FEATURE_" }, value = { - INPUT_FEATURE_NO_INPUT_CHANNEL, - INPUT_FEATURE_DISABLE_USER_ACTIVITY, - INPUT_FEATURE_SPY, - INPUT_FEATURE_INTERCEPTS_STYLUS, + @IntDef(flag = true, prefix = {"INPUT_FEATURE_"}, value = { + INPUT_FEATURE_NO_INPUT_CHANNEL, + INPUT_FEATURE_DISABLE_USER_ACTIVITY, + INPUT_FEATURE_SPY, }) - 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)); } diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp index 0ffeb617690c9..db92310f2a261 100644 --- a/core/jni/android_hardware_input_InputWindowHandle.cpp +++ b/core/jni/android_hardware_input_InputWindowHandle.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -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(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( + env->GetIntField(obj, gInputWindowHandleClassInfo.inputConfig)); mInfo.touchOcclusionMode = static_cast( 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(windowInfo.touchOcclusionMode)); env->SetIntField(inputWindowHandle, gInputWindowHandleClassInfo.ownerPid, windowInfo.ownerPid); @@ -406,8 +304,11 @@ jobject android_view_InputWindowHandle_fromWindowInfo(JNIEnv* env, gui::WindowIn ScopedLocalRef 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(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"); diff --git a/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java b/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java index dbd3f3529208f..d238dae634adf 100644 --- a/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java +++ b/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java @@ -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); diff --git a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java index 3c454080ef1c2..1a19385e71c52 100644 --- a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java +++ b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java @@ -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) diff --git a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java index f9689a8a2bca7..d4648a4f313c9 100644 --- a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java +++ b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java @@ -27,6 +27,7 @@ import android.graphics.RectF; import android.graphics.Region; import android.os.Handler; import android.os.IBinder; +import android.os.InputConfig; import android.os.Looper; import android.os.Message; import android.util.Slog; @@ -153,7 +154,8 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener { final List tempVisibleWindows = new ArrayList<>(); for (InputWindowHandle window : windowHandles) { - if (window.visible && window.getWindow() != null) { + final boolean visible = (window.inputConfig & InputConfig.NOT_VISIBLE) == 0; + if (visible && window.getWindow() != null) { tempVisibleWindows.add(window); } } @@ -641,7 +643,8 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener { final RecentsAnimationController controller = service.getRecentsAnimationController(); instance.mIgnoreDuetoRecentsAnimation = windowState != null && controller != null && controller.shouldIgnoreForAccessibility(windowState); - instance.mIsTrustedOverlay = inputWindowHandle.trustedOverlay; + instance.mIsTrustedOverlay = + (inputWindowHandle.inputConfig & InputConfig.TRUSTED_OVERLAY) != 0; // TODO (b/199358388) : gets the letterbox bounds of the window from other way. if (windowState != null && windowState.areAppWindowBoundsLetterboxed()) { diff --git a/services/core/java/com/android/server/wm/ActivityRecordInputSink.java b/services/core/java/com/android/server/wm/ActivityRecordInputSink.java index 19d5449254ff4..8622bd32fc685 100644 --- a/services/core/java/com/android/server/wm/ActivityRecordInputSink.java +++ b/services/core/java/com/android/server/wm/ActivityRecordInputSink.java @@ -19,6 +19,7 @@ package com.android.server.wm; import android.app.compat.CompatChanges; import android.compat.annotation.ChangeId; import android.os.IBinder; +import android.os.InputConfig; import android.os.InputConstants; import android.os.Looper; import android.os.Process; @@ -111,13 +112,12 @@ class ActivityRecordInputSink { mActivityRecord.getDisplayId()); inputWindowHandle.replaceTouchableRegionWithCrop = true; inputWindowHandle.name = mName; + inputWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; inputWindowHandle.ownerUid = Process.myUid(); inputWindowHandle.ownerPid = Process.myPid(); - inputWindowHandle.layoutParamsFlags = - WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; inputWindowHandle.dispatchingTimeoutMillis = InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; + inputWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE; return inputWindowHandle; } @@ -169,5 +169,4 @@ class ActivityRecordInputSink { finishInputEvent(event, true); } } - } diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index 00380bb6e84e1..c47d778c60bc3 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -44,6 +44,7 @@ import android.hardware.input.InputManager; import android.os.Binder; import android.os.Build; import android.os.IBinder; +import android.os.InputConfig; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; @@ -127,7 +128,7 @@ class DragState { @Nullable private ValueAnimator mAnimator; private final Interpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f); - private Point mDisplaySize = new Point(); + private final Point mDisplaySize = new Point(); // A surface used to catch input events for the drag-and-drop operation. SurfaceControl mInputSurface; @@ -160,8 +161,7 @@ class DragState { private void showInputSurface() { if (mInputSurface == null) { - mInputSurface = mService.makeSurfaceBuilder( - mService.mRoot.getDisplayContent(mDisplayContent.getDisplayId()).getSession()) + mInputSurface = mService.makeSurfaceBuilder(mDisplayContent.getSession()) .setContainerLayer() .setName("Drag and Drop Input Consumer") .setCallsite("DragState.showInputSurface") @@ -174,17 +174,18 @@ class DragState { return; } - mTransaction.show(mInputSurface); - mTransaction.setInputWindowInfo(mInputSurface, h); - mTransaction.setLayer(mInputSurface, Integer.MAX_VALUE); - + // Crop the input surface to the display size. mTmpClipRect.set(0, 0, mDisplaySize.x, mDisplaySize.y); - mTransaction.setWindowCrop(mInputSurface, mTmpClipRect); + + mTransaction.show(mInputSurface) + .setInputWindowInfo(mInputSurface, h) + .setLayer(mInputSurface, Integer.MAX_VALUE) + .setCrop(mInputSurface, mTmpClipRect); // syncInputWindows here to ensure the input window info is sent before the // transferTouchFocus is called. - mTransaction.syncInputWindows(); - mTransaction.apply(true); + mTransaction.syncInputWindows() + .apply(true /*sync*/); } /** @@ -361,29 +362,20 @@ class DragState { display.getDisplayId()); mDragWindowHandle.name = "drag"; mDragWindowHandle.token = mClientChannel.getToken(); - mDragWindowHandle.layoutParamsFlags = 0; mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG; mDragWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; - mDragWindowHandle.visible = true; - // Allows the system to consume keys when dragging is active. This can also be used to - // modify the drag state on key press. Example, cancel drag on escape key. - mDragWindowHandle.focusable = true; - mDragWindowHandle.hasWallpaper = false; - mDragWindowHandle.paused = false; mDragWindowHandle.ownerPid = Process.myPid(); mDragWindowHandle.ownerUid = Process.myUid(); - mDragWindowHandle.inputFeatures = 0; mDragWindowHandle.scaleFactor = 1.0f; + // Keep the default behavior of this window to be focusable, which allows the system + // to consume keys when dragging is active. This can also be used to modify the drag + // state on key press. For example, cancel drag on escape key. + mDragWindowHandle.inputConfig = InputConfig.PREVENT_SPLITTING; + // The drag window cannot receive new touches. mDragWindowHandle.touchableRegion.setEmpty(); - // The drag window covers the entire display - mDragWindowHandle.frameLeft = 0; - mDragWindowHandle.frameTop = 0; - mDragWindowHandle.frameRight = mDisplaySize.x; - mDragWindowHandle.frameBottom = mDisplaySize.y; - // Pause rotations before a drag. ProtoLog.d(WM_DEBUG_ORIENTATION, "Pausing rotation during drag"); mService.mRoot.forAllDisplays(dc -> { diff --git a/services/core/java/com/android/server/wm/InputConfigAdapter.java b/services/core/java/com/android/server/wm/InputConfigAdapter.java new file mode 100644 index 0000000000000..2dcde4ee2ba8a --- /dev/null +++ b/services/core/java/com/android/server/wm/InputConfigAdapter.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import android.os.InputConfig; +import android.view.InputWindowHandle.InputConfigFlags; +import android.view.WindowManager.LayoutParams; + +import java.util.List; + +/** + * A helper to determine the {@link InputConfigFlags} that control the behavior of an input window + * from several WM attributes. + */ +class InputConfigAdapter { + private InputConfigAdapter() {} + + /** Describes a mapping from a flag value to a {@link InputConfigFlags} value. */ + private static class FlagMapping { + final int mFlag; + final int mInputConfig; + final boolean mInverted; + + FlagMapping(int flag, int inputConfig, boolean inverted) { + mFlag = flag; + mInputConfig = inputConfig; + mInverted = inverted; + } + } + + /** + * A mapping from {@link LayoutParams.InputFeatureFlags} to {@link InputConfigFlags} for + * input configurations that can be mapped directly from a corresponding LayoutParams input + * feature. + */ + private static final List INPUT_FEATURE_TO_CONFIG_MAP = List.of( + new FlagMapping( + LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL, + InputConfig.NO_INPUT_CHANNEL, false /* inverted */), + new FlagMapping( + LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY, + InputConfig.DISABLE_USER_ACTIVITY, false /* inverted */), + new FlagMapping( + LayoutParams.INPUT_FEATURE_SPY, + InputConfig.SPY, false /* inverted */)); + + @InputConfigFlags + private static final int INPUT_FEATURE_TO_CONFIG_MASK = + computeMask(INPUT_FEATURE_TO_CONFIG_MAP); + + /** + * A mapping from {@link LayoutParams.Flags} to {@link InputConfigFlags} for input + * configurations that can be mapped directly from a corresponding LayoutParams flag. + * + * NOTE: The layout params flag {@link LayoutParams#FLAG_NOT_FOCUSABLE} is not handled by this + * adapter, and must be handled explicitly. + */ + private static final List LAYOUT_PARAM_FLAG_TO_CONFIG_MAP = List.of( + new FlagMapping( + LayoutParams.FLAG_NOT_TOUCHABLE, + InputConfig.NOT_TOUCHABLE, false /* inverted */), + new FlagMapping( + LayoutParams.FLAG_SPLIT_TOUCH, + InputConfig.PREVENT_SPLITTING, true /* inverted */), + new FlagMapping( + LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, + InputConfig.WATCH_OUTSIDE_TOUCH, false /* inverted */), + new FlagMapping( + LayoutParams.FLAG_SLIPPERY, + InputConfig.SLIPPERY, false /* inverted */)); + + @InputConfigFlags + private static final int LAYOUT_PARAM_FLAG_TO_CONFIG_MASK = + computeMask(LAYOUT_PARAM_FLAG_TO_CONFIG_MAP); + + /** + * Returns a mask of all the input config flags configured by + * {@link #getInputConfigFromWindowParams(int, int, int)}. + */ + @InputConfigFlags + static int getMask() { + return LAYOUT_PARAM_FLAG_TO_CONFIG_MASK | INPUT_FEATURE_TO_CONFIG_MASK + | InputConfig.IS_WALLPAPER; + } + + /** + * Get the {@link InputConfigFlags} value that provides the input window behavior specified by + * the given WindowManager attributes. + * + * Use {@link #getMask()} to get the mask of all the input config flags set by this method. + * + * @param type the window type + * @param flags the window flags + * @param inputFeatures the input feature flags + */ + @InputConfigFlags + static int getInputConfigFromWindowParams(@LayoutParams.WindowType int type, + @LayoutParams.Flags int flags, @LayoutParams.InputFeatureFlags int inputFeatures) { + return (type == LayoutParams.TYPE_WALLPAPER ? InputConfig.IS_WALLPAPER : 0) + | applyMapping(flags, LAYOUT_PARAM_FLAG_TO_CONFIG_MAP) + | applyMapping(inputFeatures, INPUT_FEATURE_TO_CONFIG_MAP); + } + + @InputConfigFlags + private static int applyMapping(int flags, List flagToConfigMap) { + int inputConfig = 0; + for (final FlagMapping mapping : flagToConfigMap) { + final boolean flagSet = (flags & mapping.mFlag) != 0; + if (flagSet != mapping.mInverted) { + inputConfig |= mapping.mInputConfig; + } + } + return inputConfig; + } + + @InputConfigFlags + private static int computeMask(List flagToConfigMap) { + int mask = 0; + for (final FlagMapping mapping : flagToConfigMap) { + mask |= mapping.mInputConfig; + } + return mask; + } +} diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java index cbd5646968d76..59be3e05f2c05 100644 --- a/services/core/java/com/android/server/wm/InputConsumerImpl.java +++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java @@ -22,6 +22,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; +import android.os.InputConfig; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; @@ -70,19 +71,14 @@ class InputConsumerImpl implements IBinder.DeathRecipient { mWindowHandle.name = name; mWindowHandle.token = mClientChannel.getToken(); mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; - mWindowHandle.layoutParamsFlags = 0; 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 = 0; mWindowHandle.scaleFactor = 1.0f; - mWindowHandle.trustedOverlay = true; + mWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE | InputConfig.TRUSTED_OVERLAY; - mInputSurface = mService.makeSurfaceBuilder(mService.mRoot.getDisplayContent(displayId).getSession()) + mInputSurface = mService.makeSurfaceBuilder( + mService.mRoot.getDisplayContent(displayId).getSession()) .setContainerLayer() .setName("Input Consumer " + name) .setCallsite("InputConsumerImpl") diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 31ae864fc0909..29d9531f95192 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -21,7 +21,6 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.WindowManager.INPUT_CONSUMER_PIP; import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION; import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER; -import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 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.INPUT_FEATURE_NO_INPUT_CHANNEL; @@ -53,6 +52,7 @@ import android.annotation.Nullable; import android.graphics.Region; import android.os.Handler; import android.os.IBinder; +import android.os.InputConfig; import android.os.Trace; import android.os.UserHandle; import android.util.ArrayMap; @@ -61,6 +61,7 @@ import android.util.Slog; import android.view.InputChannel; import android.view.InputWindowHandle; import android.view.SurfaceControl; +import android.view.WindowManager; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; @@ -221,15 +222,13 @@ final class InputMonitor { inputChannel, clientPid, clientUser, mDisplayId); switch (name) { case INPUT_CONSUMER_WALLPAPER: - consumer.mWindowHandle.hasWallpaper = true; + consumer.mWindowHandle.inputConfig |= InputConfig.DUPLICATE_TOUCH_TO_WALLPAPER; break; case INPUT_CONSUMER_PIP: - // The touchable region of the Pip input window is cropped to the bounds of the - // stack, and we need FLAG_NOT_TOUCH_MODAL to ensure other events fall through - consumer.mWindowHandle.layoutParamsFlags |= FLAG_NOT_TOUCH_MODAL; + // This is a valid consumer type, but we don't need any additional configurations. break; case INPUT_CONSUMER_RECENTS_ANIMATION: - consumer.mWindowHandle.focusable = true; + consumer.mWindowHandle.inputConfig &= ~InputConfig.NOT_FOCUSABLE; break; default: throw new IllegalArgumentException("Illegal input consumer : " + name @@ -247,11 +246,24 @@ final class InputMonitor { inputWindowHandle.setToken(w.mInputChannelToken); inputWindowHandle.setDispatchingTimeoutMillis(w.getInputDispatchingTimeoutMillis()); inputWindowHandle.setTouchOcclusionMode(w.getTouchOcclusionMode()); - inputWindowHandle.setInputFeatures(w.mAttrs.inputFeatures); inputWindowHandle.setPaused(w.mActivityRecord != null && w.mActivityRecord.paused); - inputWindowHandle.setVisible(w.isVisible()); inputWindowHandle.setWindowToken(w.mClient); + // Update layout params flags to force the window to be not touch modal. We do this to + // restrict the window's touchable region to the task even if it requests touches outside + // its window bounds. An example is a dialog in primary split should get touches outside its + // window within the primary task but should not get any touches going to the secondary + // task. + int flags = w.mAttrs.flags; + if (w.mAttrs.isModal()) { + flags = flags | FLAG_NOT_TOUCH_MODAL; + } + inputWindowHandle.setLayoutParamsFlags(flags); + inputWindowHandle.setInputConfigMasked( + InputConfigAdapter.getInputConfigFromWindowParams( + w.mAttrs.type, flags, w.mAttrs.inputFeatures), + InputConfigAdapter.getMask()); + final boolean focusable = w.canReceiveKeys() && (mService.mPerDisplayFocusEnabled || mDisplayContent.isOnTop()); inputWindowHandle.setFocusable(focusable); @@ -270,17 +282,6 @@ final class InputMonitor { // what is on screen to what is actually being touched in the UI. inputWindowHandle.setScaleFactor(w.mGlobalScale != 1f ? (1f / w.mGlobalScale) : 1f); - // Update layout params flags to force the window to be not touch modal. We do this to - // restrict the window's touchable region to the task even if it request touches outside its - // window bounds. An example is a dialog in primary split should get touches outside its - // window within the primary task but should not get any touches going to the secondary - // task. - int flags = w.mAttrs.flags; - if (w.mAttrs.isModal()) { - flags = flags | FLAG_NOT_TOUCH_MODAL; - } - inputWindowHandle.setLayoutParamsFlags(flags); - boolean useSurfaceBoundsAsTouchRegion = false; SurfaceControl touchableRegionCrop = null; final Task task = w.getTask(); @@ -588,6 +589,8 @@ final class InputMonitor { if (mAddWallpaperInputConsumerHandle) { if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisible()) { + mWallpaperInputConsumer.mWindowHandle + .replaceTouchableRegionWithCrop(null /* use this surface's bounds */); // Add the wallpaper input consumer above the first visible wallpaper. mWallpaperInputConsumer.show(mInputTransaction, w); mAddWallpaperInputConsumerHandle = false; @@ -629,24 +632,27 @@ final class InputMonitor { static void populateOverlayInputInfo(InputWindowHandleWrapper inputWindowHandle, WindowState w) { - populateOverlayInputInfo(inputWindowHandle, w.isVisible()); + populateOverlayInputInfo(inputWindowHandle); inputWindowHandle.setTouchOcclusionMode(w.getTouchOcclusionMode()); } // This would reset InputWindowHandle fields to prevent it could be found by input event. // We need to check if any new field of InputWindowHandle could impact the result. @VisibleForTesting - static void populateOverlayInputInfo(InputWindowHandleWrapper inputWindowHandle, - boolean isVisible) { + static void populateOverlayInputInfo(InputWindowHandleWrapper inputWindowHandle) { inputWindowHandle.setDispatchingTimeoutMillis(0); // It should never receive input. - inputWindowHandle.setVisible(isVisible); inputWindowHandle.setFocusable(false); - inputWindowHandle.setInputFeatures(INPUT_FEATURE_NO_INPUT_CHANNEL); // The input window handle without input channel must not have a token. inputWindowHandle.setToken(null); inputWindowHandle.setScaleFactor(1f); - inputWindowHandle.setLayoutParamsFlags( - FLAG_NOT_TOUCH_MODAL | FLAG_NOT_TOUCHABLE | FLAG_NOT_FOCUSABLE); + final int defaultType = WindowManager.LayoutParams.TYPE_APPLICATION; + inputWindowHandle.setLayoutParamsType(defaultType); + inputWindowHandle.setInputConfigMasked( + InputConfigAdapter.getInputConfigFromWindowParams( + defaultType, + FLAG_NOT_TOUCHABLE, + INPUT_FEATURE_NO_INPUT_CHANNEL), + InputConfigAdapter.getMask()); inputWindowHandle.clearTouchableRegion(); inputWindowHandle.setTouchableRegionCrop(null); } @@ -664,7 +670,7 @@ final class InputMonitor { inputWindowHandle.setName(name); inputWindowHandle.setLayoutParamsType(TYPE_SECURE_SYSTEM_OVERLAY); inputWindowHandle.setTrustedOverlay(true); - populateOverlayInputInfo(inputWindowHandle, true /* isVisible */); + populateOverlayInputInfo(inputWindowHandle); setInputWindowInfoIfNeeded(t, sc, inputWindowHandle); } diff --git a/services/core/java/com/android/server/wm/InputWindowHandleWrapper.java b/services/core/java/com/android/server/wm/InputWindowHandleWrapper.java index 142d2933f0467..301c1846249ff 100644 --- a/services/core/java/com/android/server/wm/InputWindowHandleWrapper.java +++ b/services/core/java/com/android/server/wm/InputWindowHandleWrapper.java @@ -20,10 +20,13 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Region; import android.os.IBinder; +import android.os.InputConfig; import android.view.IWindow; import android.view.InputApplicationHandle; import android.view.InputWindowHandle; +import android.view.InputWindowHandle.InputConfigFlags; import android.view.SurfaceControl; +import android.view.WindowManager; import java.util.Objects; @@ -31,8 +34,10 @@ import java.util.Objects; * The wrapper of {@link InputWindowHandle} with field change detection to reduce unnecessary * updates to surface, e.g. if there are no changes, then skip invocation of * {@link SurfaceControl.Transaction#setInputWindowInfo(SurfaceControl, InputWindowHandle)}. + * It also sets the {@link InputConfigFlags} values for the input window. */ class InputWindowHandleWrapper { + /** The wrapped handle should not be directly exposed to avoid untracked changes. */ private final @NonNull InputWindowHandle mHandle; @@ -65,7 +70,20 @@ class InputWindowHandleWrapper { } boolean isFocusable() { - return mHandle.focusable; + return (mHandle.inputConfig & InputConfig.NOT_FOCUSABLE) == 0; + } + + boolean isPaused() { + return (mHandle.inputConfig & InputConfig.PAUSE_DISPATCHING) != 0; + } + + boolean isTrustedOverlay() { + return (mHandle.inputConfig & InputConfig.TRUSTED_OVERLAY) != 0; + } + + boolean hasWallpaper() { + return (mHandle.inputConfig & InputConfig.DUPLICATE_TOUCH_TO_WALLPAPER) + != 0; } InputApplicationHandle getInputApplicationHandle() { @@ -96,7 +114,7 @@ class InputWindowHandleWrapper { mChanged = true; } - void setLayoutParamsFlags(int flags) { + void setLayoutParamsFlags(@WindowManager.LayoutParams.Flags int flags) { if (mHandle.layoutParamsFlags == flags) { return; } @@ -136,19 +154,11 @@ class InputWindowHandleWrapper { mChanged = true; } - void setVisible(boolean visible) { - if (mHandle.visible == visible) { - return; - } - mHandle.visible = visible; - mChanged = true; - } - void setFocusable(boolean focusable) { - if (mHandle.focusable == focusable) { + if (isFocusable() == focusable) { return; } - mHandle.focusable = focusable; + mHandle.setInputConfig(InputConfig.NOT_FOCUSABLE, !focusable); mChanged = true; } @@ -161,26 +171,27 @@ class InputWindowHandleWrapper { } void setHasWallpaper(boolean hasWallpaper) { - if (mHandle.hasWallpaper == hasWallpaper) { + if (this.hasWallpaper() == hasWallpaper) { return; } - mHandle.hasWallpaper = hasWallpaper; + mHandle.setInputConfig(InputConfig.DUPLICATE_TOUCH_TO_WALLPAPER, + hasWallpaper); mChanged = true; } void setPaused(boolean paused) { - if (mHandle.paused == paused) { + if (isPaused() == paused) { return; } - mHandle.paused = paused; + mHandle.setInputConfig(InputConfig.PAUSE_DISPATCHING, paused); mChanged = true; } void setTrustedOverlay(boolean trustedOverlay) { - if (mHandle.trustedOverlay == trustedOverlay) { + if (isTrustedOverlay() == trustedOverlay) { return; } - mHandle.trustedOverlay = trustedOverlay; + mHandle.setInputConfig(InputConfig.TRUSTED_OVERLAY, trustedOverlay); mChanged = true; } @@ -208,14 +219,6 @@ class InputWindowHandleWrapper { mChanged = true; } - void setInputFeatures(int features) { - if (mHandle.inputFeatures == features) { - return; - } - mHandle.inputFeatures = features; - mChanged = true; - } - void setDisplayId(int displayId) { if (mHandle.displayId == displayId) { return; @@ -276,8 +279,14 @@ class InputWindowHandleWrapper { mChanged = true; } - boolean isTrustedOverlay() { - return mHandle.trustedOverlay; + void setInputConfigMasked(@InputConfigFlags int inputConfig, @InputConfigFlags int mask) { + final int inputConfigMasked = inputConfig & mask; + if (inputConfigMasked == (mHandle.inputConfig & mask)) { + return; + } + mHandle.inputConfig &= ~mask; + mHandle.inputConfig |= inputConfigMasked; + mChanged = true; } @Override diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java index 4b98013a99cc1..40df02c176e59 100644 --- a/services/core/java/com/android/server/wm/Letterbox.java +++ b/services/core/java/com/android/server/wm/Letterbox.java @@ -24,6 +24,7 @@ import android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; import android.os.IBinder; +import android.os.InputConfig; import android.os.Process; import android.view.GestureDetector; import android.view.InputChannel; @@ -290,16 +291,12 @@ public class Letterbox { win.getDisplayId()); mWindowHandle.name = name; mWindowHandle.token = mToken; - mWindowHandle.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH - | WindowManager.LayoutParams.FLAG_SLIPPERY; mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; - mWindowHandle.visible = true; mWindowHandle.ownerPid = Process.myPid(); mWindowHandle.ownerUid = Process.myUid(); mWindowHandle.scaleFactor = 1.0f; + mWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE | InputConfig.SLIPPERY; } void updateTouchableRegion(Rect frame) { diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java index 348cfb62582eb..47c397d12720a 100644 --- a/services/core/java/com/android/server/wm/TaskPositioner.java +++ b/services/core/java/com/android/server/wm/TaskPositioner.java @@ -40,6 +40,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; +import android.os.InputConfig; import android.os.Process; import android.os.RemoteException; import android.os.Trace; @@ -219,30 +220,17 @@ class TaskPositioner implements IBinder.DeathRecipient { displayContent.getDisplayId()); mDragWindowHandle.name = TAG; mDragWindowHandle.token = mClientChannel.getToken(); - mDragWindowHandle.layoutParamsFlags = 0; mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG; mDragWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; - mDragWindowHandle.visible = true; - // When dragging the window around, we do not want to steal focus for the window. - mDragWindowHandle.focusable = false; - mDragWindowHandle.hasWallpaper = false; - mDragWindowHandle.paused = false; mDragWindowHandle.ownerPid = Process.myPid(); mDragWindowHandle.ownerUid = Process.myUid(); - mDragWindowHandle.inputFeatures = 0; mDragWindowHandle.scaleFactor = 1.0f; + // When dragging the window around, we do not want to steal focus for the window. + mDragWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE; // The drag window cannot receive new touches. mDragWindowHandle.touchableRegion.setEmpty(); - // The drag window covers the entire display. - final Rect displayBounds = mTmpRect; - displayContent.getBounds(mTmpRect); - mDragWindowHandle.frameLeft = displayBounds.left; - mDragWindowHandle.frameTop = displayBounds.top; - mDragWindowHandle.frameRight = displayBounds.right; - mDragWindowHandle.frameBottom = displayBounds.bottom; - // Pause rotations before a drag. ProtoLog.d(WM_DEBUG_ORIENTATION, "Pausing rotation during re-position"); mDisplayContent.getDisplayRotation().pause(); @@ -250,6 +238,8 @@ class TaskPositioner implements IBinder.DeathRecipient { // Notify InputMonitor to take mDragWindowHandle. mService.mTaskPositioningController.showInputSurface(win.getDisplayId()); + final Rect displayBounds = mTmpRect; + displayContent.getBounds(displayBounds); final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics(); mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics); mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics); diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java index 8f24f2615fac0..68bf2b2424e72 100644 --- a/services/core/java/com/android/server/wm/TaskPositioningController.java +++ b/services/core/java/com/android/server/wm/TaskPositioningController.java @@ -83,17 +83,18 @@ class TaskPositioningController { return; } - mTransaction.show(mInputSurface); - mTransaction.setInputWindowInfo(mInputSurface, h); - mTransaction.setLayer(mInputSurface, Integer.MAX_VALUE); - final Display display = dc.getDisplay(); final Point p = new Point(); display.getRealSize(p); - mTmpClipRect.set(0, 0, p.x, p.y); - mTransaction.setWindowCrop(mInputSurface, mTmpClipRect); - mTransaction.syncInputWindows().apply(); + + mTransaction.show(mInputSurface) + .setInputWindowInfo(mInputSurface, h) + .setLayer(mInputSurface, Integer.MAX_VALUE) + .setPosition(mInputSurface, 0, 0) + .setCrop(mInputSurface, mTmpClipRect) + .syncInputWindows() + .apply(); } boolean startMovingTask(IWindow window, float startX, float startY) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 555128bc1374e..b703cdb38fde0 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -191,6 +191,7 @@ import android.os.Handler; import android.os.HandlerExecutor; import android.os.IBinder; import android.os.IRemoteCallback; +import android.os.InputConfig; import android.os.Looper; import android.os.Message; import android.os.Parcel; @@ -8447,43 +8448,48 @@ public class WindowManagerService extends IWindowManager.Stub } private void updateInputChannel(IBinder channelToken, int callingUid, int callingPid, - int displayId, SurfaceControl surface, String name, - InputApplicationHandle applicationHandle, int flags, - int privateFlags, int type, Region region, IWindow window) { - InputWindowHandle h = new InputWindowHandle(applicationHandle, displayId); + int displayId, SurfaceControl surface, String name, + InputApplicationHandle applicationHandle, int flags, + int privateFlags, int type, Region region, IWindow window) { + final InputWindowHandle h = new InputWindowHandle(applicationHandle, displayId); h.token = channelToken; h.setWindowToken(window); h.name = name; flags = sanitizeFlagSlippery(flags, name, callingUid, callingPid); - final int sanitizedFlags = flags & (FLAG_NOT_TOUCHABLE - | FLAG_SLIPPERY | LayoutParams.FLAG_NOT_FOCUSABLE); - h.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | sanitizedFlags; + final int sanitizedLpFlags = + (flags & (FLAG_NOT_TOUCHABLE | FLAG_SLIPPERY | LayoutParams.FLAG_NOT_FOCUSABLE)) + | LayoutParams.FLAG_NOT_TOUCH_MODAL; h.layoutParamsType = type; - h.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; - h.focusable = (flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0; - h.hasWallpaper = false; - h.paused = false; - - h.ownerUid = callingUid; - h.ownerPid = callingPid; + h.layoutParamsFlags = sanitizedLpFlags; // Do not allow any input features to be set without sanitizing them first. - h.inputFeatures = 0; + h.inputConfig = InputConfigAdapter.getInputConfigFromWindowParams( + type, sanitizedLpFlags, 0 /*inputFeatures*/); - if (region == null) { - h.replaceTouchableRegionWithCrop(null); - } else { - h.touchableRegion.set(region); - h.replaceTouchableRegionWithCrop = false; - h.setTouchableRegionCrop(surface); + + if ((flags & LayoutParams.FLAG_NOT_FOCUSABLE) != 0) { + h.inputConfig |= InputConfig.NOT_FOCUSABLE; } // Check private trusted overlay flag to set trustedOverlay field of input window handle. - h.trustedOverlay = (privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0; + if ((privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0) { + h.inputConfig |= InputConfig.TRUSTED_OVERLAY; + } - SurfaceControl.Transaction t = mTransactionFactory.get(); + h.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; + h.ownerUid = callingUid; + h.ownerPid = callingPid; + + if (region == null) { + h.replaceTouchableRegionWithCrop = true; + } else { + h.touchableRegion.set(region); + } + h.setTouchableRegionCrop(null /* use the input surface's bounds */); + + final SurfaceControl.Transaction t = mTransactionFactory.get(); t.setInputWindowInfo(surface, h); t.apply(); t.close(); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index ccd42364f6a39..b3ae72e02a883 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1190,6 +1190,7 @@ class WindowState extends WindowContainer implements WindowManagerP mActivityRecord != null ? mActivityRecord.getInputApplicationHandle(false /* update */) : null, getDisplayId())); + mInputWindowHandle.setFocusable(false); mInputWindowHandle.setOwnerPid(s.mPid); mInputWindowHandle.setOwnerUid(s.mUid); mInputWindowHandle.setName(getName()); diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java index 46ef7ed092dee..5ea8fd373f0b0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java +++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java @@ -17,6 +17,7 @@ package com.android.server.wm; import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.ColorSpace; import android.graphics.GraphicBuffer; import android.graphics.Matrix; @@ -134,6 +135,12 @@ public class StubTransaction extends SurfaceControl.Transaction { return this; } + @Override + @NonNull + public SurfaceControl.Transaction setCrop(@NonNull SurfaceControl sc, @Nullable Rect crop) { + return this; + } + @Override public SurfaceControl.Transaction setCornerRadius(SurfaceControl sc, float cornerRadius) { return this; diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index a554fab76c2b8..d442407735629 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -29,6 +29,8 @@ import static android.view.Surface.ROTATION_90; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; +import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; +import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; @@ -80,6 +82,7 @@ import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.os.IBinder; +import android.os.InputConfig; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import android.util.ArraySet; @@ -733,10 +736,15 @@ public class WindowStateTests extends WindowTestsBase { assertFalse(win0.canReceiveTouchInput()); } + private boolean testFlag(int flags, int test) { + return (flags & test) == test; + } + @Test public void testUpdateInputWindowHandle() { final WindowState win = createWindow(null, TYPE_APPLICATION, "win"); win.mAttrs.inputFeatures = WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY; + win.mAttrs.flags = FLAG_WATCH_OUTSIDE_TOUCH | FLAG_SPLIT_TOUCH; final InputWindowHandle handle = new InputWindowHandle( win.mInputWindowHandle.getInputApplicationHandle(), win.getDisplayId()); final InputWindowHandleWrapper handleWrapper = new InputWindowHandleWrapper(handle); @@ -746,13 +754,14 @@ public class WindowStateTests extends WindowTestsBase { mDisplayContent.getInputMonitor().populateInputWindowHandle(handleWrapper, win); assertTrue(handleWrapper.isChanged()); + assertTrue(testFlag(handle.inputConfig, InputConfig.WATCH_OUTSIDE_TOUCH)); + assertFalse(testFlag(handle.inputConfig, InputConfig.PREVENT_SPLITTING)); + assertTrue(testFlag(handle.inputConfig, InputConfig.DISABLE_USER_ACTIVITY)); // The window of standard resizable task should not use surface crop as touchable region. assertFalse(handle.replaceTouchableRegionWithCrop); assertEquals(inputChannelToken, handle.token); assertEquals(win.mActivityRecord.getInputApplicationHandle(false /* update */), handle.inputApplicationHandle); - assertEquals(win.mAttrs.inputFeatures, handle.inputFeatures); - assertEquals(win.isVisible(), handle.visible); final SurfaceControl sc = mock(SurfaceControl.class); final SurfaceControl.Transaction transaction = mSystemServicesTestRule.mTransaction; @@ -778,15 +787,13 @@ public class WindowStateTests extends WindowTestsBase { assertEquals(rotatedBounds, handle.touchableRegion.getBounds()); // Populate as an overlay to disable the input of window. - InputMonitor.populateOverlayInputInfo(handleWrapper, false /* isVisible */); + InputMonitor.populateOverlayInputInfo(handleWrapper); // The overlay attributes should be set. assertTrue(handleWrapper.isChanged()); - assertFalse(handle.focusable); - assertFalse(handle.visible); + assertFalse(handleWrapper.isFocusable()); assertNull(handle.token); assertEquals(0L, handle.dispatchingTimeoutMillis); - assertEquals(WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL, - handle.inputFeatures); + assertTrue(testFlag(handle.inputConfig, InputConfig.NO_INPUT_CHANNEL)); } @Test