Merge changes from topic "merge-input-config-feature-tm" into tm-dev am: d7a879e665

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17050822

Change-Id: I569d13e950298a8fd9c35c664d39ac6814f6fd3c
This commit is contained in:
TreeHugger Robot
2022-03-05 04:15:37 +00:00
committed by Automerger Merge Worker
19 changed files with 409 additions and 333 deletions

View File

@@ -16,20 +16,57 @@
package android.view; package android.view;
import android.annotation.IntDef;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.graphics.Region; import android.graphics.Region;
import android.gui.TouchOcclusionMode; import android.gui.TouchOcclusionMode;
import android.os.IBinder; import android.os.IBinder;
import android.os.InputConfig;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
/** /**
* Functions as a handle for a window that can receive input. * Functions as a handle for a window that can receive input, and allows for the behavior of the
* Enables the native input dispatcher to refer indirectly to the window manager's window state. * input window to be configured.
* @hide * @hide
*/ */
public final class InputWindowHandle { 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. // Pointer to the native input window handle.
// This field is lazily initialized via JNI. // This field is lazily initialized via JNI.
@SuppressWarnings("unused") @SuppressWarnings("unused")
@@ -56,7 +93,8 @@ public final class InputWindowHandle {
// The window name. // The window name.
public String 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 layoutParamsFlags;
public int layoutParamsType; public int layoutParamsType;
@@ -78,20 +116,9 @@ public final class InputWindowHandle {
// Window touchable region. // Window touchable region.
public final Region touchableRegion = new Region(); public final Region touchableRegion = new Region();
// Window is visible. // Flags that specify the behavior of this input window. See {@link #InputConfigFlags}.
public boolean visible; @InputConfigFlags
public int inputConfig;
// 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;
// What effect this window has on touch occlusion if it lets touches pass through // 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 // By default windows will block touches if they are untrusted and from a different UID due to
@@ -105,25 +132,21 @@ public final class InputWindowHandle {
// Owner package of the window // Owner package of the window
public String packageName; public String packageName;
// Window input features. // Display this input window is on.
public int inputFeatures;
// Display this input is on.
public int displayId; 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 * This can be used in cases where the window should be constrained to the bounds of a parent
* {@link android.view.WindowManager#FLAG_NOT_TOUCH_MODAL} but should be constrained to the * window. That is, the window should receive touch events outside its window frame, but be
* bounds of a parent window. That is the window should receive touch events outside its * limited to its stack bounds, such as in the case of split screen.
* window but be limited to its stack bounds, such as in the case of split screen.
*/ */
public WeakReference<SurfaceControl> touchableRegionSurfaceControl = new WeakReference<>(null); public WeakReference<SurfaceControl> touchableRegionSurfaceControl = new WeakReference<>(null);
/** /**
* Replace {@link touchableRegion} with the bounds of {@link touchableRegionSurfaceControl}. If * Replace {@link #touchableRegion} with the bounds of {@link #touchableRegionSurfaceControl}.
* the handle is {@code null}, the bounds of the surface associated with this window is used * If the handle is {@code null}, the bounds of the surface associated with this window is used
* as the touchable region. * as the touchable region.
*/ */
public boolean replaceTouchableRegionWithCrop; public boolean replaceTouchableRegionWithCrop;
@@ -147,7 +170,6 @@ public final class InputWindowHandle {
.append(", frame=[").append(frameLeft).append(",").append(frameTop).append(",") .append(", frame=[").append(frameLeft).append(",").append(frameTop).append(",")
.append(frameRight).append(",").append(frameBottom).append("]") .append(frameRight).append(",").append(frameBottom).append("]")
.append(", touchableRegion=").append(touchableRegion) .append(", touchableRegion=").append(touchableRegion)
.append(", visible=").append(visible)
.append(", scaleFactor=").append(scaleFactor) .append(", scaleFactor=").append(scaleFactor)
.append(", transform=").append(transform) .append(", transform=").append(transform)
.append(", windowToken=").append(windowToken) .append(", windowToken=").append(windowToken)
@@ -165,11 +187,11 @@ public final class InputWindowHandle {
} }
/** /**
* Set the window touchable region to the bounds of {@link touchableRegionBounds} ignoring any * Set the window's touchable region to the bounds of {@link #touchableRegionSurfaceControl}
* touchable region provided. * and ignore the value of {@link #touchableRegion}.
* *
* @param bounds surface to set the touchable region to. Set to {@code null} to set the bounds * @param bounds surface to set the touchable region to. Set to {@code null} to set the
* to the current surface. * touchable region as the current surface bounds.
*/ */
public void replaceTouchableRegionWithCrop(@Nullable SurfaceControl bounds) { public void replaceTouchableRegionWithCrop(@Nullable SurfaceControl bounds) {
setTouchableRegionCrop(bounds); setTouchableRegionCrop(bounds);
@@ -195,4 +217,17 @@ public final class InputWindowHandle {
window = IWindow.Stub.asInterface(windowToken); window = IWindow.Stub.asInterface(windowToken);
return window; 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;
}
} }

View File

@@ -106,7 +106,6 @@ import android.graphics.Region;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.IInputConstants;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.text.TextUtils; import android.text.TextUtils;
@@ -3360,8 +3359,7 @@ public interface WindowManager extends ViewManager {
* *
* @hide * @hide
*/ */
public static final int INPUT_FEATURE_NO_INPUT_CHANNEL = public static final int INPUT_FEATURE_NO_INPUT_CHANNEL = 1 << 0;
IInputConstants.InputFeature.NO_INPUT_CHANNEL;
/** /**
* When this window has focus, does not call user activity for all input events so * When this window has focus, does not call user activity for all input events so
@@ -3374,58 +3372,43 @@ public interface WindowManager extends ViewManager {
* @hide * @hide
*/ */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final int INPUT_FEATURE_DISABLE_USER_ACTIVITY = public static final int INPUT_FEATURE_DISABLE_USER_ACTIVITY = 1 << 1;
IInputConstants.InputFeature.DISABLE_USER_ACTIVITY;
/** /**
* An input spy window. This window will receive all pointer events within its touchable * 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 * An input event will be dispatched to all spy windows above the top non-spy window at the
* event's coordinates. * event's coordinates.
* @hide
*/
public static final int INPUT_FEATURE_SPY =
IInputConstants.InputFeature.SPY;
/**
* 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 * @hide
*/ */
public static final int INPUT_FEATURE_INTERCEPTS_STYLUS = @RequiresPermission(permission.MONITOR_INPUT)
IInputConstants.InputFeature.INTERCEPTS_STYLUS; public static final int INPUT_FEATURE_SPY = 1 << 2;
/** /**
* An internal annotation for flags that can be specified to {@link #inputFeatures}. * 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 * @hide
*/ */
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef(flag = true, prefix = { "INPUT_FEATURE_" }, value = { @IntDef(flag = true, prefix = {"INPUT_FEATURE_"}, value = {
INPUT_FEATURE_NO_INPUT_CHANNEL, INPUT_FEATURE_NO_INPUT_CHANNEL,
INPUT_FEATURE_DISABLE_USER_ACTIVITY, INPUT_FEATURE_DISABLE_USER_ACTIVITY,
INPUT_FEATURE_SPY, INPUT_FEATURE_SPY,
INPUT_FEATURE_INTERCEPTS_STYLUS,
}) })
public @interface InputFeatureFlags {} public @interface InputFeatureFlags {
}
/** /**
* Control special features of the input subsystem. * Control a set of features of the input subsystem that are exposed to the app process.
*
* WARNING: Do NOT use {@link android.os.InputConfig} flags! This must be set to flag values
* included in {@link InputFeatureFlags}.
* *
* @see #INPUT_FEATURE_NO_INPUT_CHANNEL
* @see #INPUT_FEATURE_DISABLE_USER_ACTIVITY
* @see #INPUT_FEATURE_SPY
* @see #INPUT_FEATURE_INTERCEPTS_STYLUS
* @hide * @hide
* @see InputFeatureFlags
*/ */
@InputFeatureFlags @InputFeatureFlags
@UnsupportedAppUsage @UnsupportedAppUsage
@@ -4845,10 +4828,6 @@ public interface WindowManager extends ViewManager {
inputFeatures &= ~INPUT_FEATURE_SPY; inputFeatures &= ~INPUT_FEATURE_SPY;
features.add("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) { if (inputFeatures != 0) {
features.add(Integer.toHexString(inputFeatures)); features.add(Integer.toHexString(inputFeatures));
} }

View File

@@ -23,6 +23,7 @@
#include <android_runtime/AndroidRuntime.h> #include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h> #include <android_runtime/Log.h>
#include <binder/IPCThreadState.h> #include <binder/IPCThreadState.h>
#include <ftl/cast.h>
#include <gui/SurfaceControl.h> #include <gui/SurfaceControl.h>
#include <gui/WindowInfo.h> #include <gui/WindowInfo.h>
#include <nativehelper/JNIHelp.h> #include <nativehelper/JNIHelp.h>
@@ -63,16 +64,11 @@ static struct {
jfieldID surfaceInset; jfieldID surfaceInset;
jfieldID scaleFactor; jfieldID scaleFactor;
jfieldID touchableRegion; jfieldID touchableRegion;
jfieldID visible;
jfieldID focusable;
jfieldID hasWallpaper;
jfieldID paused;
jfieldID trustedOverlay;
jfieldID touchOcclusionMode; jfieldID touchOcclusionMode;
jfieldID ownerPid; jfieldID ownerPid;
jfieldID ownerUid; jfieldID ownerUid;
jfieldID packageName; jfieldID packageName;
jfieldID inputFeatures; jfieldID inputConfig;
jfieldID displayId; jfieldID displayId;
jfieldID replaceTouchableRegionWithCrop; jfieldID replaceTouchableRegionWithCrop;
WeakRefHandleField touchableRegionSurfaceControl; WeakRefHandleField touchableRegionSurfaceControl;
@@ -162,64 +158,8 @@ bool NativeInputWindowHandle::updateInfo() {
mInfo.layoutParamsFlags = flags; mInfo.layoutParamsFlags = flags;
mInfo.layoutParamsType = type; mInfo.layoutParamsType = type;
using InputConfig = gui::WindowInfo::InputConfig; mInfo.inputConfig = static_cast<gui::WindowInfo::InputConfig>(
// Determine the value for each of the InputConfig flags. We rely on a switch statement and env->GetIntField(obj, gInputWindowHandleClassInfo.inputConfig));
// -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;
switch (enumerationStart) {
case InputConfig::NONE:
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;
}
}
mInfo.touchOcclusionMode = static_cast<TouchOcclusionMode>( mInfo.touchOcclusionMode = static_cast<TouchOcclusionMode>(
env->GetIntField(obj, gInputWindowHandleClassInfo.touchOcclusionMode)); env->GetIntField(obj, gInputWindowHandleClassInfo.touchOcclusionMode));
@@ -228,8 +168,6 @@ bool NativeInputWindowHandle::updateInfo() {
mInfo.ownerUid = env->GetIntField(obj, mInfo.ownerUid = env->GetIntField(obj,
gInputWindowHandleClassInfo.ownerUid); gInputWindowHandleClassInfo.ownerUid);
mInfo.packageName = getStringField(env, obj, gInputWindowHandleClassInfo.packageName, "<null>"); mInfo.packageName = getStringField(env, obj, gInputWindowHandleClassInfo.packageName, "<null>");
mInfo.inputFeatures = static_cast<WindowInfo::Feature>(
env->GetIntField(obj, gInputWindowHandleClassInfo.inputFeatures));
mInfo.displayId = env->GetIntField(obj, mInfo.displayId = env->GetIntField(obj,
gInputWindowHandleClassInfo.displayId); gInputWindowHandleClassInfo.displayId);
@@ -359,17 +297,6 @@ jobject android_view_InputWindowHandle_fromWindowInfo(JNIEnv* env, gui::WindowIn
env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.touchableRegion, env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.touchableRegion,
regionObj.get()); 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, env->SetIntField(inputWindowHandle, gInputWindowHandleClassInfo.touchOcclusionMode,
static_cast<int32_t>(windowInfo.touchOcclusionMode)); static_cast<int32_t>(windowInfo.touchOcclusionMode));
env->SetIntField(inputWindowHandle, gInputWindowHandleClassInfo.ownerPid, windowInfo.ownerPid); env->SetIntField(inputWindowHandle, gInputWindowHandleClassInfo.ownerPid, windowInfo.ownerPid);
@@ -377,8 +304,11 @@ jobject android_view_InputWindowHandle_fromWindowInfo(JNIEnv* env, gui::WindowIn
ScopedLocalRef<jstring> packageName(env, env->NewStringUTF(windowInfo.packageName.data())); ScopedLocalRef<jstring> packageName(env, env->NewStringUTF(windowInfo.packageName.data()));
env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.packageName, env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.packageName,
packageName.get()); packageName.get());
env->SetIntField(inputWindowHandle, gInputWindowHandleClassInfo.inputFeatures,
static_cast<int32_t>(windowInfo.inputFeatures.get())); 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]; float transformVals[9];
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++) {
@@ -481,19 +411,6 @@ int register_android_view_InputWindowHandle(JNIEnv* env) {
GET_FIELD_ID(gInputWindowHandleClassInfo.touchableRegion, clazz, GET_FIELD_ID(gInputWindowHandleClassInfo.touchableRegion, clazz,
"touchableRegion", "Landroid/graphics/Region;"); "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.touchOcclusionMode, clazz, "touchOcclusionMode", "I");
GET_FIELD_ID(gInputWindowHandleClassInfo.ownerPid, clazz, GET_FIELD_ID(gInputWindowHandleClassInfo.ownerPid, clazz,
@@ -505,8 +422,7 @@ int register_android_view_InputWindowHandle(JNIEnv* env) {
GET_FIELD_ID(gInputWindowHandleClassInfo.packageName, clazz, "packageName", GET_FIELD_ID(gInputWindowHandleClassInfo.packageName, clazz, "packageName",
"Ljava/lang/String;"); "Ljava/lang/String;");
GET_FIELD_ID(gInputWindowHandleClassInfo.inputFeatures, clazz, GET_FIELD_ID(gInputWindowHandleClassInfo.inputConfig, clazz, "inputConfig", "I");
"inputFeatures", "I");
GET_FIELD_ID(gInputWindowHandleClassInfo.displayId, clazz, GET_FIELD_ID(gInputWindowHandleClassInfo.displayId, clazz,
"displayId", "I"); "displayId", "I");

View File

@@ -19,6 +19,7 @@ package com.android.server.input;
import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
import android.os.IBinder; import android.os.IBinder;
import android.os.InputConfig;
import android.view.InputApplicationHandle; import android.view.InputApplicationHandle;
import android.view.InputChannel; import android.view.InputChannel;
import android.view.InputMonitor; import android.view.InputMonitor;
@@ -56,18 +57,13 @@ class GestureMonitorSpyWindow {
mWindowHandle.name = name; mWindowHandle.name = name;
mWindowHandle.token = mClientChannel.getToken(); mWindowHandle.token = mClientChannel.getToken();
mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
mWindowHandle.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
mWindowHandle.visible = true;
mWindowHandle.focusable = false;
mWindowHandle.hasWallpaper = false;
mWindowHandle.paused = false;
mWindowHandle.ownerPid = pid; mWindowHandle.ownerPid = pid;
mWindowHandle.ownerUid = uid; mWindowHandle.ownerUid = uid;
mWindowHandle.inputFeatures = WindowManager.LayoutParams.INPUT_FEATURE_SPY;
mWindowHandle.scaleFactor = 1.0f; mWindowHandle.scaleFactor = 1.0f;
mWindowHandle.trustedOverlay = true;
mWindowHandle.replaceTouchableRegionWithCrop(null /* use this surface's bounds */); 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(); final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
t.setInputWindowInfo(mInputSurface, mWindowHandle); t.setInputWindowInfo(mInputSurface, mWindowHandle);

View File

@@ -19,6 +19,7 @@ package com.android.server.inputmethod;
import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.os.InputConfig;
import android.os.Process; import android.os.Process;
import android.view.InputApplicationHandle; import android.view.InputApplicationHandle;
import android.view.InputChannel; import android.view.InputChannel;
@@ -56,20 +57,17 @@ final class HandwritingEventReceiverSurface {
mWindowHandle.name = name; mWindowHandle.name = name;
mWindowHandle.token = mClientChannel.getToken(); mWindowHandle.token = mClientChannel.getToken();
mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
mWindowHandle.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
mWindowHandle.visible = true;
mWindowHandle.focusable = false;
mWindowHandle.hasWallpaper = false;
mWindowHandle.paused = false;
mWindowHandle.ownerPid = Process.myPid(); mWindowHandle.ownerPid = Process.myPid();
mWindowHandle.ownerUid = Process.myUid(); mWindowHandle.ownerUid = Process.myUid();
mWindowHandle.inputFeatures = WindowManager.LayoutParams.INPUT_FEATURE_SPY
| WindowManager.LayoutParams.INPUT_FEATURE_INTERCEPTS_STYLUS;
mWindowHandle.scaleFactor = 1.0f; mWindowHandle.scaleFactor = 1.0f;
mWindowHandle.trustedOverlay = true;
mWindowHandle.replaceTouchableRegionWithCrop(null /* use this surface's bounds */); 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(); final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
t.setInputWindowInfo(mInputSurface, mWindowHandle); t.setInputWindowInfo(mInputSurface, mWindowHandle);
@@ -85,7 +83,7 @@ final class HandwritingEventReceiverSurface {
void startIntercepting(int imePid, int imeUid) { void startIntercepting(int imePid, int imeUid) {
mWindowHandle.ownerPid = imePid; mWindowHandle.ownerPid = imePid;
mWindowHandle.ownerUid = imeUid; mWindowHandle.ownerUid = imeUid;
mWindowHandle.inputFeatures &= ~WindowManager.LayoutParams.INPUT_FEATURE_SPY; mWindowHandle.inputConfig &= ~InputConfig.SPY;
new SurfaceControl.Transaction() new SurfaceControl.Transaction()
.setInputWindowInfo(mInputSurface, mWindowHandle) .setInputWindowInfo(mInputSurface, mWindowHandle)

View File

@@ -27,6 +27,7 @@ import android.graphics.RectF;
import android.graphics.Region; import android.graphics.Region;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.InputConfig;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.util.Slog; import android.util.Slog;
@@ -153,7 +154,8 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener {
final List<InputWindowHandle> tempVisibleWindows = new ArrayList<>(); final List<InputWindowHandle> tempVisibleWindows = new ArrayList<>();
for (InputWindowHandle window : windowHandles) { 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); tempVisibleWindows.add(window);
} }
} }
@@ -641,7 +643,8 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener {
final RecentsAnimationController controller = service.getRecentsAnimationController(); final RecentsAnimationController controller = service.getRecentsAnimationController();
instance.mIgnoreDuetoRecentsAnimation = windowState != null && controller != null instance.mIgnoreDuetoRecentsAnimation = windowState != null && controller != null
&& controller.shouldIgnoreForAccessibility(windowState); && 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. // TODO (b/199358388) : gets the letterbox bounds of the window from other way.
if (windowState != null && windowState.areAppWindowBoundsLetterboxed()) { if (windowState != null && windowState.areAppWindowBoundsLetterboxed()) {

View File

@@ -19,6 +19,7 @@ package com.android.server.wm;
import android.app.compat.CompatChanges; import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId; import android.compat.annotation.ChangeId;
import android.os.IBinder; import android.os.IBinder;
import android.os.InputConfig;
import android.os.InputConstants; import android.os.InputConstants;
import android.os.Looper; import android.os.Looper;
import android.os.Process; import android.os.Process;
@@ -111,13 +112,12 @@ class ActivityRecordInputSink {
mActivityRecord.getDisplayId()); mActivityRecord.getDisplayId());
inputWindowHandle.replaceTouchableRegionWithCrop = true; inputWindowHandle.replaceTouchableRegionWithCrop = true;
inputWindowHandle.name = mName; inputWindowHandle.name = mName;
inputWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
inputWindowHandle.ownerUid = Process.myUid(); inputWindowHandle.ownerUid = Process.myUid();
inputWindowHandle.ownerPid = Process.myPid(); inputWindowHandle.ownerPid = Process.myPid();
inputWindowHandle.layoutParamsFlags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
inputWindowHandle.dispatchingTimeoutMillis = inputWindowHandle.dispatchingTimeoutMillis =
InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
inputWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE;
return inputWindowHandle; return inputWindowHandle;
} }
@@ -169,5 +169,4 @@ class ActivityRecordInputSink {
finishInputEvent(event, true); finishInputEvent(event, true);
} }
} }
} }

View File

@@ -44,6 +44,7 @@ import android.hardware.input.InputManager;
import android.os.Binder; import android.os.Binder;
import android.os.Build; import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.os.InputConfig;
import android.os.Process; import android.os.Process;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.UserHandle; import android.os.UserHandle;
@@ -127,7 +128,7 @@ class DragState {
@Nullable private ValueAnimator mAnimator; @Nullable private ValueAnimator mAnimator;
private final Interpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f); 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. // A surface used to catch input events for the drag-and-drop operation.
SurfaceControl mInputSurface; SurfaceControl mInputSurface;
@@ -160,8 +161,7 @@ class DragState {
private void showInputSurface() { private void showInputSurface() {
if (mInputSurface == null) { if (mInputSurface == null) {
mInputSurface = mService.makeSurfaceBuilder( mInputSurface = mService.makeSurfaceBuilder(mDisplayContent.getSession())
mService.mRoot.getDisplayContent(mDisplayContent.getDisplayId()).getSession())
.setContainerLayer() .setContainerLayer()
.setName("Drag and Drop Input Consumer") .setName("Drag and Drop Input Consumer")
.setCallsite("DragState.showInputSurface") .setCallsite("DragState.showInputSurface")
@@ -174,17 +174,18 @@ class DragState {
return; return;
} }
mTransaction.show(mInputSurface); // Crop the input surface to the display size.
mTransaction.setInputWindowInfo(mInputSurface, h);
mTransaction.setLayer(mInputSurface, Integer.MAX_VALUE);
mTmpClipRect.set(0, 0, mDisplaySize.x, mDisplaySize.y); 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 // syncInputWindows here to ensure the input window info is sent before the
// transferTouchFocus is called. // transferTouchFocus is called.
mTransaction.syncInputWindows(); mTransaction.syncInputWindows()
mTransaction.apply(true); .apply(true /*sync*/);
} }
/** /**
@@ -361,29 +362,20 @@ class DragState {
display.getDisplayId()); display.getDisplayId());
mDragWindowHandle.name = "drag"; mDragWindowHandle.name = "drag";
mDragWindowHandle.token = mClientChannel.getToken(); mDragWindowHandle.token = mClientChannel.getToken();
mDragWindowHandle.layoutParamsFlags = 0;
mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG; mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
mDragWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; 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.ownerPid = Process.myPid();
mDragWindowHandle.ownerUid = Process.myUid(); mDragWindowHandle.ownerUid = Process.myUid();
mDragWindowHandle.inputFeatures = 0;
mDragWindowHandle.scaleFactor = 1.0f; 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. // The drag window cannot receive new touches.
mDragWindowHandle.touchableRegion.setEmpty(); 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. // Pause rotations before a drag.
ProtoLog.d(WM_DEBUG_ORIENTATION, "Pausing rotation during drag"); ProtoLog.d(WM_DEBUG_ORIENTATION, "Pausing rotation during drag");
mService.mRoot.forAllDisplays(dc -> { mService.mRoot.forAllDisplays(dc -> {

View File

@@ -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;
}
}

View File

@@ -22,6 +22,7 @@ import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Binder; import android.os.Binder;
import android.os.IBinder; import android.os.IBinder;
import android.os.InputConfig;
import android.os.Process; import android.os.Process;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.UserHandle; import android.os.UserHandle;
@@ -70,19 +71,14 @@ class InputConsumerImpl implements IBinder.DeathRecipient {
mWindowHandle.name = name; mWindowHandle.name = name;
mWindowHandle.token = mClientChannel.getToken(); mWindowHandle.token = mClientChannel.getToken();
mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
mWindowHandle.layoutParamsFlags = 0;
mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
mWindowHandle.visible = true;
mWindowHandle.focusable = false;
mWindowHandle.hasWallpaper = false;
mWindowHandle.paused = false;
mWindowHandle.ownerPid = Process.myPid(); mWindowHandle.ownerPid = Process.myPid();
mWindowHandle.ownerUid = Process.myUid(); mWindowHandle.ownerUid = Process.myUid();
mWindowHandle.inputFeatures = 0;
mWindowHandle.scaleFactor = 1.0f; 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() .setContainerLayer()
.setName("Input Consumer " + name) .setName("Input Consumer " + name)
.setCallsite("InputConsumerImpl") .setCallsite("InputConsumerImpl")

View File

@@ -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_PIP;
import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION; import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER; 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_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; 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.graphics.Region;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.InputConfig;
import android.os.Trace; import android.os.Trace;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.ArrayMap; import android.util.ArrayMap;
@@ -61,6 +61,7 @@ import android.util.Slog;
import android.view.InputChannel; import android.view.InputChannel;
import android.view.InputWindowHandle; import android.view.InputWindowHandle;
import android.view.SurfaceControl; import android.view.SurfaceControl;
import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog; import com.android.internal.protolog.common.ProtoLog;
@@ -221,15 +222,13 @@ final class InputMonitor {
inputChannel, clientPid, clientUser, mDisplayId); inputChannel, clientPid, clientUser, mDisplayId);
switch (name) { switch (name) {
case INPUT_CONSUMER_WALLPAPER: case INPUT_CONSUMER_WALLPAPER:
consumer.mWindowHandle.hasWallpaper = true; consumer.mWindowHandle.inputConfig |= InputConfig.DUPLICATE_TOUCH_TO_WALLPAPER;
break; break;
case INPUT_CONSUMER_PIP: case INPUT_CONSUMER_PIP:
// The touchable region of the Pip input window is cropped to the bounds of the // This is a valid consumer type, but we don't need any additional configurations.
// stack, and we need FLAG_NOT_TOUCH_MODAL to ensure other events fall through
consumer.mWindowHandle.layoutParamsFlags |= FLAG_NOT_TOUCH_MODAL;
break; break;
case INPUT_CONSUMER_RECENTS_ANIMATION: case INPUT_CONSUMER_RECENTS_ANIMATION:
consumer.mWindowHandle.focusable = true; consumer.mWindowHandle.inputConfig &= ~InputConfig.NOT_FOCUSABLE;
break; break;
default: default:
throw new IllegalArgumentException("Illegal input consumer : " + name throw new IllegalArgumentException("Illegal input consumer : " + name
@@ -247,11 +246,24 @@ final class InputMonitor {
inputWindowHandle.setToken(w.mInputChannelToken); inputWindowHandle.setToken(w.mInputChannelToken);
inputWindowHandle.setDispatchingTimeoutMillis(w.getInputDispatchingTimeoutMillis()); inputWindowHandle.setDispatchingTimeoutMillis(w.getInputDispatchingTimeoutMillis());
inputWindowHandle.setTouchOcclusionMode(w.getTouchOcclusionMode()); inputWindowHandle.setTouchOcclusionMode(w.getTouchOcclusionMode());
inputWindowHandle.setInputFeatures(w.mAttrs.inputFeatures);
inputWindowHandle.setPaused(w.mActivityRecord != null && w.mActivityRecord.paused); inputWindowHandle.setPaused(w.mActivityRecord != null && w.mActivityRecord.paused);
inputWindowHandle.setVisible(w.isVisible());
inputWindowHandle.setWindowToken(w.mClient); 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() final boolean focusable = w.canReceiveKeys()
&& (mService.mPerDisplayFocusEnabled || mDisplayContent.isOnTop()); && (mService.mPerDisplayFocusEnabled || mDisplayContent.isOnTop());
inputWindowHandle.setFocusable(focusable); inputWindowHandle.setFocusable(focusable);
@@ -270,17 +282,6 @@ final class InputMonitor {
// what is on screen to what is actually being touched in the UI. // what is on screen to what is actually being touched in the UI.
inputWindowHandle.setScaleFactor(w.mGlobalScale != 1f ? (1f / w.mGlobalScale) : 1f); 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; boolean useSurfaceBoundsAsTouchRegion = false;
SurfaceControl touchableRegionCrop = null; SurfaceControl touchableRegionCrop = null;
final Task task = w.getTask(); final Task task = w.getTask();
@@ -590,6 +591,8 @@ final class InputMonitor {
if (mAddWallpaperInputConsumerHandle) { if (mAddWallpaperInputConsumerHandle) {
if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisible()) { 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. // Add the wallpaper input consumer above the first visible wallpaper.
mWallpaperInputConsumer.show(mInputTransaction, w); mWallpaperInputConsumer.show(mInputTransaction, w);
mAddWallpaperInputConsumerHandle = false; mAddWallpaperInputConsumerHandle = false;
@@ -631,24 +634,27 @@ final class InputMonitor {
static void populateOverlayInputInfo(InputWindowHandleWrapper inputWindowHandle, static void populateOverlayInputInfo(InputWindowHandleWrapper inputWindowHandle,
WindowState w) { WindowState w) {
populateOverlayInputInfo(inputWindowHandle, w.isVisible()); populateOverlayInputInfo(inputWindowHandle);
inputWindowHandle.setTouchOcclusionMode(w.getTouchOcclusionMode()); inputWindowHandle.setTouchOcclusionMode(w.getTouchOcclusionMode());
} }
// This would reset InputWindowHandle fields to prevent it could be found by input event. // 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. // We need to check if any new field of InputWindowHandle could impact the result.
@VisibleForTesting @VisibleForTesting
static void populateOverlayInputInfo(InputWindowHandleWrapper inputWindowHandle, static void populateOverlayInputInfo(InputWindowHandleWrapper inputWindowHandle) {
boolean isVisible) {
inputWindowHandle.setDispatchingTimeoutMillis(0); // It should never receive input. inputWindowHandle.setDispatchingTimeoutMillis(0); // It should never receive input.
inputWindowHandle.setVisible(isVisible);
inputWindowHandle.setFocusable(false); inputWindowHandle.setFocusable(false);
inputWindowHandle.setInputFeatures(INPUT_FEATURE_NO_INPUT_CHANNEL);
// The input window handle without input channel must not have a token. // The input window handle without input channel must not have a token.
inputWindowHandle.setToken(null); inputWindowHandle.setToken(null);
inputWindowHandle.setScaleFactor(1f); inputWindowHandle.setScaleFactor(1f);
inputWindowHandle.setLayoutParamsFlags( final int defaultType = WindowManager.LayoutParams.TYPE_APPLICATION;
FLAG_NOT_TOUCH_MODAL | FLAG_NOT_TOUCHABLE | FLAG_NOT_FOCUSABLE); inputWindowHandle.setLayoutParamsType(defaultType);
inputWindowHandle.setInputConfigMasked(
InputConfigAdapter.getInputConfigFromWindowParams(
defaultType,
FLAG_NOT_TOUCHABLE,
INPUT_FEATURE_NO_INPUT_CHANNEL),
InputConfigAdapter.getMask());
inputWindowHandle.clearTouchableRegion(); inputWindowHandle.clearTouchableRegion();
inputWindowHandle.setTouchableRegionCrop(null); inputWindowHandle.setTouchableRegionCrop(null);
} }
@@ -666,7 +672,7 @@ final class InputMonitor {
inputWindowHandle.setName(name); inputWindowHandle.setName(name);
inputWindowHandle.setLayoutParamsType(TYPE_SECURE_SYSTEM_OVERLAY); inputWindowHandle.setLayoutParamsType(TYPE_SECURE_SYSTEM_OVERLAY);
inputWindowHandle.setTrustedOverlay(true); inputWindowHandle.setTrustedOverlay(true);
populateOverlayInputInfo(inputWindowHandle, true /* isVisible */); populateOverlayInputInfo(inputWindowHandle);
setInputWindowInfoIfNeeded(t, sc, inputWindowHandle); setInputWindowInfoIfNeeded(t, sc, inputWindowHandle);
} }

View File

@@ -20,10 +20,13 @@ import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.graphics.Region; import android.graphics.Region;
import android.os.IBinder; import android.os.IBinder;
import android.os.InputConfig;
import android.view.IWindow; import android.view.IWindow;
import android.view.InputApplicationHandle; import android.view.InputApplicationHandle;
import android.view.InputWindowHandle; import android.view.InputWindowHandle;
import android.view.InputWindowHandle.InputConfigFlags;
import android.view.SurfaceControl; import android.view.SurfaceControl;
import android.view.WindowManager;
import java.util.Objects; import java.util.Objects;
@@ -31,8 +34,10 @@ import java.util.Objects;
* The wrapper of {@link InputWindowHandle} with field change detection to reduce unnecessary * 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 * updates to surface, e.g. if there are no changes, then skip invocation of
* {@link SurfaceControl.Transaction#setInputWindowInfo(SurfaceControl, InputWindowHandle)}. * {@link SurfaceControl.Transaction#setInputWindowInfo(SurfaceControl, InputWindowHandle)}.
* It also sets the {@link InputConfigFlags} values for the input window.
*/ */
class InputWindowHandleWrapper { class InputWindowHandleWrapper {
/** The wrapped handle should not be directly exposed to avoid untracked changes. */ /** The wrapped handle should not be directly exposed to avoid untracked changes. */
private final @NonNull InputWindowHandle mHandle; private final @NonNull InputWindowHandle mHandle;
@@ -65,7 +70,20 @@ class InputWindowHandleWrapper {
} }
boolean isFocusable() { 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() { InputApplicationHandle getInputApplicationHandle() {
@@ -96,7 +114,7 @@ class InputWindowHandleWrapper {
mChanged = true; mChanged = true;
} }
void setLayoutParamsFlags(int flags) { void setLayoutParamsFlags(@WindowManager.LayoutParams.Flags int flags) {
if (mHandle.layoutParamsFlags == flags) { if (mHandle.layoutParamsFlags == flags) {
return; return;
} }
@@ -136,19 +154,11 @@ class InputWindowHandleWrapper {
mChanged = true; mChanged = true;
} }
void setVisible(boolean visible) {
if (mHandle.visible == visible) {
return;
}
mHandle.visible = visible;
mChanged = true;
}
void setFocusable(boolean focusable) { void setFocusable(boolean focusable) {
if (mHandle.focusable == focusable) { if (isFocusable() == focusable) {
return; return;
} }
mHandle.focusable = focusable; mHandle.setInputConfig(InputConfig.NOT_FOCUSABLE, !focusable);
mChanged = true; mChanged = true;
} }
@@ -161,26 +171,27 @@ class InputWindowHandleWrapper {
} }
void setHasWallpaper(boolean hasWallpaper) { void setHasWallpaper(boolean hasWallpaper) {
if (mHandle.hasWallpaper == hasWallpaper) { if (this.hasWallpaper() == hasWallpaper) {
return; return;
} }
mHandle.hasWallpaper = hasWallpaper; mHandle.setInputConfig(InputConfig.DUPLICATE_TOUCH_TO_WALLPAPER,
hasWallpaper);
mChanged = true; mChanged = true;
} }
void setPaused(boolean paused) { void setPaused(boolean paused) {
if (mHandle.paused == paused) { if (isPaused() == paused) {
return; return;
} }
mHandle.paused = paused; mHandle.setInputConfig(InputConfig.PAUSE_DISPATCHING, paused);
mChanged = true; mChanged = true;
} }
void setTrustedOverlay(boolean trustedOverlay) { void setTrustedOverlay(boolean trustedOverlay) {
if (mHandle.trustedOverlay == trustedOverlay) { if (isTrustedOverlay() == trustedOverlay) {
return; return;
} }
mHandle.trustedOverlay = trustedOverlay; mHandle.setInputConfig(InputConfig.TRUSTED_OVERLAY, trustedOverlay);
mChanged = true; mChanged = true;
} }
@@ -208,14 +219,6 @@ class InputWindowHandleWrapper {
mChanged = true; mChanged = true;
} }
void setInputFeatures(int features) {
if (mHandle.inputFeatures == features) {
return;
}
mHandle.inputFeatures = features;
mChanged = true;
}
void setDisplayId(int displayId) { void setDisplayId(int displayId) {
if (mHandle.displayId == displayId) { if (mHandle.displayId == displayId) {
return; return;
@@ -276,8 +279,14 @@ class InputWindowHandleWrapper {
mChanged = true; mChanged = true;
} }
boolean isTrustedOverlay() { void setInputConfigMasked(@InputConfigFlags int inputConfig, @InputConfigFlags int mask) {
return mHandle.trustedOverlay; final int inputConfigMasked = inputConfig & mask;
if (inputConfigMasked == (mHandle.inputConfig & mask)) {
return;
}
mHandle.inputConfig &= ~mask;
mHandle.inputConfig |= inputConfigMasked;
mChanged = true;
} }
@Override @Override

View File

@@ -24,6 +24,7 @@ import android.graphics.Color;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.IBinder; import android.os.IBinder;
import android.os.InputConfig;
import android.os.Process; import android.os.Process;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.InputChannel; import android.view.InputChannel;
@@ -290,16 +291,12 @@ public class Letterbox {
win.getDisplayId()); win.getDisplayId());
mWindowHandle.name = name; mWindowHandle.name = name;
mWindowHandle.token = mToken; 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.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
mWindowHandle.visible = true;
mWindowHandle.ownerPid = Process.myPid(); mWindowHandle.ownerPid = Process.myPid();
mWindowHandle.ownerUid = Process.myUid(); mWindowHandle.ownerUid = Process.myUid();
mWindowHandle.scaleFactor = 1.0f; mWindowHandle.scaleFactor = 1.0f;
mWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE | InputConfig.SLIPPERY;
} }
void updateTouchableRegion(Rect frame) { void updateTouchableRegion(Rect frame) {

View File

@@ -40,6 +40,7 @@ import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Binder; import android.os.Binder;
import android.os.IBinder; import android.os.IBinder;
import android.os.InputConfig;
import android.os.Process; import android.os.Process;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.Trace; import android.os.Trace;
@@ -219,30 +220,17 @@ class TaskPositioner implements IBinder.DeathRecipient {
displayContent.getDisplayId()); displayContent.getDisplayId());
mDragWindowHandle.name = TAG; mDragWindowHandle.name = TAG;
mDragWindowHandle.token = mClientChannel.getToken(); mDragWindowHandle.token = mClientChannel.getToken();
mDragWindowHandle.layoutParamsFlags = 0;
mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG; mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
mDragWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; 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.ownerPid = Process.myPid();
mDragWindowHandle.ownerUid = Process.myUid(); mDragWindowHandle.ownerUid = Process.myUid();
mDragWindowHandle.inputFeatures = 0;
mDragWindowHandle.scaleFactor = 1.0f; 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. // The drag window cannot receive new touches.
mDragWindowHandle.touchableRegion.setEmpty(); 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. // Pause rotations before a drag.
ProtoLog.d(WM_DEBUG_ORIENTATION, "Pausing rotation during re-position"); ProtoLog.d(WM_DEBUG_ORIENTATION, "Pausing rotation during re-position");
mDisplayContent.getDisplayRotation().pause(); mDisplayContent.getDisplayRotation().pause();
@@ -250,6 +238,8 @@ class TaskPositioner implements IBinder.DeathRecipient {
// Notify InputMonitor to take mDragWindowHandle. // Notify InputMonitor to take mDragWindowHandle.
mService.mTaskPositioningController.showInputSurface(win.getDisplayId()); mService.mTaskPositioningController.showInputSurface(win.getDisplayId());
final Rect displayBounds = mTmpRect;
displayContent.getBounds(displayBounds);
final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics(); final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics); mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics);
mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics); mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics);

View File

@@ -83,17 +83,18 @@ class TaskPositioningController {
return; return;
} }
mTransaction.show(mInputSurface);
mTransaction.setInputWindowInfo(mInputSurface, h);
mTransaction.setLayer(mInputSurface, Integer.MAX_VALUE);
final Display display = dc.getDisplay(); final Display display = dc.getDisplay();
final Point p = new Point(); final Point p = new Point();
display.getRealSize(p); display.getRealSize(p);
mTmpClipRect.set(0, 0, p.x, p.y); 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) { boolean startMovingTask(IWindow window, float startX, float startY) {

View File

@@ -192,6 +192,7 @@ import android.os.Handler;
import android.os.HandlerExecutor; import android.os.HandlerExecutor;
import android.os.IBinder; import android.os.IBinder;
import android.os.IRemoteCallback; import android.os.IRemoteCallback;
import android.os.InputConfig;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.Parcel; import android.os.Parcel;
@@ -8452,43 +8453,48 @@ public class WindowManagerService extends IWindowManager.Stub
} }
private void updateInputChannel(IBinder channelToken, int callingUid, int callingPid, private void updateInputChannel(IBinder channelToken, int callingUid, int callingPid,
int displayId, SurfaceControl surface, String name, int displayId, SurfaceControl surface, String name,
InputApplicationHandle applicationHandle, int flags, InputApplicationHandle applicationHandle, int flags,
int privateFlags, int type, Region region, IWindow window) { int privateFlags, int type, Region region, IWindow window) {
InputWindowHandle h = new InputWindowHandle(applicationHandle, displayId); final InputWindowHandle h = new InputWindowHandle(applicationHandle, displayId);
h.token = channelToken; h.token = channelToken;
h.setWindowToken(window); h.setWindowToken(window);
h.name = name; h.name = name;
flags = sanitizeFlagSlippery(flags, name, callingUid, callingPid); flags = sanitizeFlagSlippery(flags, name, callingUid, callingPid);
final int sanitizedFlags = flags & (FLAG_NOT_TOUCHABLE final int sanitizedLpFlags =
| FLAG_SLIPPERY | LayoutParams.FLAG_NOT_FOCUSABLE); (flags & (FLAG_NOT_TOUCHABLE | FLAG_SLIPPERY | LayoutParams.FLAG_NOT_FOCUSABLE))
h.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | sanitizedFlags; | LayoutParams.FLAG_NOT_TOUCH_MODAL;
h.layoutParamsType = type; h.layoutParamsType = type;
h.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; h.layoutParamsFlags = sanitizedLpFlags;
h.focusable = (flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0;
h.hasWallpaper = false;
h.paused = false;
h.ownerUid = callingUid;
h.ownerPid = callingPid;
// Do not allow any input features to be set without sanitizing them first. // 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); if ((flags & LayoutParams.FLAG_NOT_FOCUSABLE) != 0) {
} else { h.inputConfig |= InputConfig.NOT_FOCUSABLE;
h.touchableRegion.set(region);
h.replaceTouchableRegionWithCrop = false;
h.setTouchableRegionCrop(surface);
} }
// Check private trusted overlay flag to set trustedOverlay field of input window handle. // 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.setInputWindowInfo(surface, h);
t.apply(); t.apply();
t.close(); t.close();

View File

@@ -1190,6 +1190,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mActivityRecord != null mActivityRecord != null
? mActivityRecord.getInputApplicationHandle(false /* update */) : null, ? mActivityRecord.getInputApplicationHandle(false /* update */) : null,
getDisplayId())); getDisplayId()));
mInputWindowHandle.setFocusable(false);
mInputWindowHandle.setOwnerPid(s.mPid); mInputWindowHandle.setOwnerPid(s.mPid);
mInputWindowHandle.setOwnerUid(s.mUid); mInputWindowHandle.setOwnerUid(s.mUid);
mInputWindowHandle.setName(getName()); mInputWindowHandle.setName(getName());

View File

@@ -17,6 +17,7 @@
package com.android.server.wm; package com.android.server.wm;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.ColorSpace; import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer; import android.graphics.GraphicBuffer;
import android.graphics.Matrix; import android.graphics.Matrix;
@@ -134,6 +135,12 @@ public class StubTransaction extends SurfaceControl.Transaction {
return this; return this;
} }
@Override
@NonNull
public SurfaceControl.Transaction setCrop(@NonNull SurfaceControl sc, @Nullable Rect crop) {
return this;
}
@Override @Override
public SurfaceControl.Transaction setCornerRadius(SurfaceControl sc, float cornerRadius) { public SurfaceControl.Transaction setCornerRadius(SurfaceControl sc, float cornerRadius) {
return this; return this;

View File

@@ -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.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 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_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;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -81,6 +83,7 @@ import android.graphics.Matrix;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.IBinder; import android.os.IBinder;
import android.os.InputConfig;
import android.os.RemoteException; import android.os.RemoteException;
import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.Presubmit;
import android.util.ArraySet; import android.util.ArraySet;
@@ -754,10 +757,15 @@ public class WindowStateTests extends WindowTestsBase {
assertFalse(win0.canReceiveTouchInput()); assertFalse(win0.canReceiveTouchInput());
} }
private boolean testFlag(int flags, int test) {
return (flags & test) == test;
}
@Test @Test
public void testUpdateInputWindowHandle() { public void testUpdateInputWindowHandle() {
final WindowState win = createWindow(null, TYPE_APPLICATION, "win"); final WindowState win = createWindow(null, TYPE_APPLICATION, "win");
win.mAttrs.inputFeatures = WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY; 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( final InputWindowHandle handle = new InputWindowHandle(
win.mInputWindowHandle.getInputApplicationHandle(), win.getDisplayId()); win.mInputWindowHandle.getInputApplicationHandle(), win.getDisplayId());
final InputWindowHandleWrapper handleWrapper = new InputWindowHandleWrapper(handle); final InputWindowHandleWrapper handleWrapper = new InputWindowHandleWrapper(handle);
@@ -767,13 +775,14 @@ public class WindowStateTests extends WindowTestsBase {
mDisplayContent.getInputMonitor().populateInputWindowHandle(handleWrapper, win); mDisplayContent.getInputMonitor().populateInputWindowHandle(handleWrapper, win);
assertTrue(handleWrapper.isChanged()); 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. // The window of standard resizable task should not use surface crop as touchable region.
assertFalse(handle.replaceTouchableRegionWithCrop); assertFalse(handle.replaceTouchableRegionWithCrop);
assertEquals(inputChannelToken, handle.token); assertEquals(inputChannelToken, handle.token);
assertEquals(win.mActivityRecord.getInputApplicationHandle(false /* update */), assertEquals(win.mActivityRecord.getInputApplicationHandle(false /* update */),
handle.inputApplicationHandle); handle.inputApplicationHandle);
assertEquals(win.mAttrs.inputFeatures, handle.inputFeatures);
assertEquals(win.isVisible(), handle.visible);
final SurfaceControl sc = mock(SurfaceControl.class); final SurfaceControl sc = mock(SurfaceControl.class);
final SurfaceControl.Transaction transaction = mSystemServicesTestRule.mTransaction; final SurfaceControl.Transaction transaction = mSystemServicesTestRule.mTransaction;
@@ -799,15 +808,13 @@ public class WindowStateTests extends WindowTestsBase {
assertEquals(rotatedBounds, handle.touchableRegion.getBounds()); assertEquals(rotatedBounds, handle.touchableRegion.getBounds());
// Populate as an overlay to disable the input of window. // Populate as an overlay to disable the input of window.
InputMonitor.populateOverlayInputInfo(handleWrapper, false /* isVisible */); InputMonitor.populateOverlayInputInfo(handleWrapper);
// The overlay attributes should be set. // The overlay attributes should be set.
assertTrue(handleWrapper.isChanged()); assertTrue(handleWrapper.isChanged());
assertFalse(handle.focusable); assertFalse(handleWrapper.isFocusable());
assertFalse(handle.visible);
assertNull(handle.token); assertNull(handle.token);
assertEquals(0L, handle.dispatchingTimeoutMillis); assertEquals(0L, handle.dispatchingTimeoutMillis);
assertEquals(WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL, assertTrue(testFlag(handle.inputConfig, InputConfig.NO_INPUT_CHANNEL));
handle.inputFeatures);
} }
@Test @Test