summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Prabir Pradhan <prabirmsp@google.com> 2022-02-07 12:34:38 -0800
committer Prabir Pradhan <prabirmsp@google.com> 2022-03-04 13:08:59 +0000
commitbdf0cb726262ea8345cfa6b22e431e93b7062fe3 (patch)
tree92f0f35c6a35579ac4e5e6bf4d8e7b30b7395c99
parented142dcacbf044ab120a205f4736513c0a9277e1 (diff)
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
-rw-r--r--core/java/android/view/InputWindowHandle.java102
-rw-r--r--core/java/android/view/WindowManager.java46
-rw-r--r--core/jni/android_hardware_input_InputWindowHandle.cpp133
-rw-r--r--services/core/java/com/android/server/input/GestureMonitorSpyWindow.java10
-rw-r--r--services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java18
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java7
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecordInputSink.java7
-rw-r--r--services/core/java/com/android/server/wm/DragState.java40
-rw-r--r--services/core/java/com/android/server/wm/InputConfigAdapter.java138
-rw-r--r--services/core/java/com/android/server/wm/InputConsumerImpl.java12
-rw-r--r--services/core/java/com/android/server/wm/InputMonitor.java60
-rw-r--r--services/core/java/com/android/server/wm/InputWindowHandleWrapper.java65
-rw-r--r--services/core/java/com/android/server/wm/Letterbox.java7
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioner.java20
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioningController.java15
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java48
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/StubTransaction.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java21
19 files changed, 404 insertions, 353 deletions
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index 44a0e891e21e..ef0c19c8dc02 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<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;
+ }
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index b4b354bc3243..45169efd7d35 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
- */
- 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)
- @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 0ffeb617690c..db92310f2a26 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -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");
diff --git a/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java b/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java
index dbd3f3529208..d238dae634ad 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 3c454080ef1c..1a19385e71c5 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 f9689a8a2bca..d4648a4f313c 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<InputWindowHandle> 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 19d5449254ff..8622bd32fc68 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 00380bb6e84e..c47d778c60bc 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 000000000000..2dcde4ee2ba8
--- /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<FlagMapping> 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<FlagMapping> 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<FlagMapping> 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<FlagMapping> 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 cbd5646968d7..59be3e05f2c0 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 31ae864fc090..29d9531f9519 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 142d2933f046..301c1846249f 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 4b98013a99cc..40df02c176e5 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 348cfb62582e..47c397d12720 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 8f24f2615fac..68bf2b2424e7 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 555128bc1374..b703cdb38fde 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.layoutParamsFlags = sanitizedLpFlags;
+
+ // Do not allow any input features to be set without sanitizing them first.
+ h.inputConfig = InputConfigAdapter.getInputConfigFromWindowParams(
+ type, sanitizedLpFlags, 0 /*inputFeatures*/);
+
+
+ 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.
+ if ((privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0) {
+ h.inputConfig |= InputConfig.TRUSTED_OVERLAY;
+ }
+ h.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
h.ownerUid = callingUid;
h.ownerPid = callingPid;
- // Do not allow any input features to be set without sanitizing them first.
- h.inputFeatures = 0;
-
if (region == null) {
- h.replaceTouchableRegionWithCrop(null);
+ h.replaceTouchableRegionWithCrop = true;
} else {
h.touchableRegion.set(region);
- h.replaceTouchableRegionWithCrop = false;
- h.setTouchableRegionCrop(surface);
}
+ h.setTouchableRegionCrop(null /* use the input surface's bounds */);
- // Check private trusted overlay flag to set trustedOverlay field of input window handle.
- h.trustedOverlay = (privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0;
-
- SurfaceControl.Transaction t = mTransactionFactory.get();
+ 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 ccd42364f6a3..b3ae72e02a88 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<WindowState> 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 46ef7ed092de..5ea8fd373f0b 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;
@@ -135,6 +136,12 @@ public class StubTransaction extends SurfaceControl.Transaction {
}
@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 a554fab76c2b..d44240773562 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