Merge changes from topic "merge-input-config-feature-tm" into tm-dev
* changes: Use InputConfig flags in InputWindowHandle API WindowInfo: Merge InputConfig and Feature flags
This commit is contained in:
committed by
Android (Google) Code Review
commit
d7a879e665
@@ -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,25 +132,21 @@ public final class InputWindowHandle {
|
||||
// Owner package of the window
|
||||
public String packageName;
|
||||
|
||||
// Window input features.
|
||||
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;
|
||||
@@ -147,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)
|
||||
@@ -165,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);
|
||||
@@ -195,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,6 @@ import android.graphics.Region;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.IInputConstants;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
@@ -3360,8 +3359,7 @@ public interface WindowManager extends ViewManager {
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int INPUT_FEATURE_NO_INPUT_CHANNEL =
|
||||
IInputConstants.InputFeature.NO_INPUT_CHANNEL;
|
||||
public static final int INPUT_FEATURE_NO_INPUT_CHANNEL = 1 << 0;
|
||||
|
||||
/**
|
||||
* When this window has focus, does not call user activity for all input events so
|
||||
@@ -3374,58 +3372,43 @@ public interface WindowManager extends ViewManager {
|
||||
* @hide
|
||||
*/
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||||
public static final int INPUT_FEATURE_DISABLE_USER_ACTIVITY =
|
||||
IInputConstants.InputFeature.DISABLE_USER_ACTIVITY;
|
||||
public static final int INPUT_FEATURE_DISABLE_USER_ACTIVITY = 1 << 1;
|
||||
|
||||
/**
|
||||
* An input spy window. This window will receive all pointer events within its touchable
|
||||
* area, but will will not stop events from being sent to other windows below it in z-order.
|
||||
* area, but will not stop events from being sent to other windows below it in z-order.
|
||||
* An input event will be dispatched to all spy windows above the top non-spy window at the
|
||||
* event's coordinates.
|
||||
* @hide
|
||||
*/
|
||||
public static final int INPUT_FEATURE_SPY =
|
||||
IInputConstants.InputFeature.SPY;
|
||||
|
||||
/**
|
||||
* 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 =
|
||||
IInputConstants.InputFeature.INTERCEPTS_STYLUS;
|
||||
@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
|
||||
@@ -4845,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));
|
||||
}
|
||||
|
||||
@@ -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,64 +158,8 @@ bool NativeInputWindowHandle::updateInfo() {
|
||||
mInfo.layoutParamsFlags = flags;
|
||||
mInfo.layoutParamsType = type;
|
||||
|
||||
using InputConfig = gui::WindowInfo::InputConfig;
|
||||
// Determine the value for each of the InputConfig flags. We rely on a switch statement and
|
||||
// -Wswitch-enum to give us a build error if we forget to explicitly handle an InputConfig flag.
|
||||
mInfo.inputConfig = InputConfig::NONE;
|
||||
InputConfig enumerationStart = InputConfig::NONE;
|
||||
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.inputConfig = static_cast<gui::WindowInfo::InputConfig>(
|
||||
env->GetIntField(obj, gInputWindowHandleClassInfo.inputConfig));
|
||||
|
||||
mInfo.touchOcclusionMode = static_cast<TouchOcclusionMode>(
|
||||
env->GetIntField(obj, gInputWindowHandleClassInfo.touchOcclusionMode));
|
||||
@@ -228,8 +168,6 @@ bool NativeInputWindowHandle::updateInfo() {
|
||||
mInfo.ownerUid = env->GetIntField(obj,
|
||||
gInputWindowHandleClassInfo.ownerUid);
|
||||
mInfo.packageName = getStringField(env, obj, gInputWindowHandleClassInfo.packageName, "<null>");
|
||||
mInfo.inputFeatures = static_cast<WindowInfo::Feature>(
|
||||
env->GetIntField(obj, gInputWindowHandleClassInfo.inputFeatures));
|
||||
mInfo.displayId = env->GetIntField(obj,
|
||||
gInputWindowHandleClassInfo.displayId);
|
||||
|
||||
@@ -359,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);
|
||||
@@ -377,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());
|
||||
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];
|
||||
for (int i = 0; i < 9; i++) {
|
||||
@@ -481,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,
|
||||
@@ -505,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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 -> {
|
||||
|
||||
138
services/core/java/com/android/server/wm/InputConfigAdapter.java
Normal file
138
services/core/java/com/android/server/wm/InputConfigAdapter.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
|
||||
@@ -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();
|
||||
@@ -590,6 +591,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;
|
||||
@@ -631,24 +634,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);
|
||||
}
|
||||
@@ -666,7 +672,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -192,6 +192,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;
|
||||
@@ -8452,43 +8453,48 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
|
||||
private void updateInputChannel(IBinder channelToken, int callingUid, int callingPid,
|
||||
int displayId, SurfaceControl surface, String name,
|
||||
InputApplicationHandle applicationHandle, int flags,
|
||||
int privateFlags, int type, Region region, IWindow window) {
|
||||
InputWindowHandle h = new InputWindowHandle(applicationHandle, displayId);
|
||||
int displayId, SurfaceControl surface, String name,
|
||||
InputApplicationHandle applicationHandle, int flags,
|
||||
int privateFlags, int type, Region region, IWindow window) {
|
||||
final InputWindowHandle h = new InputWindowHandle(applicationHandle, displayId);
|
||||
h.token = channelToken;
|
||||
h.setWindowToken(window);
|
||||
h.name = name;
|
||||
|
||||
flags = sanitizeFlagSlippery(flags, name, callingUid, callingPid);
|
||||
|
||||
final int sanitizedFlags = flags & (FLAG_NOT_TOUCHABLE
|
||||
| FLAG_SLIPPERY | LayoutParams.FLAG_NOT_FOCUSABLE);
|
||||
h.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | sanitizedFlags;
|
||||
final int sanitizedLpFlags =
|
||||
(flags & (FLAG_NOT_TOUCHABLE | FLAG_SLIPPERY | LayoutParams.FLAG_NOT_FOCUSABLE))
|
||||
| LayoutParams.FLAG_NOT_TOUCH_MODAL;
|
||||
h.layoutParamsType = type;
|
||||
h.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
|
||||
h.focusable = (flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0;
|
||||
h.hasWallpaper = false;
|
||||
h.paused = false;
|
||||
|
||||
h.ownerUid = callingUid;
|
||||
h.ownerPid = callingPid;
|
||||
h.layoutParamsFlags = sanitizedLpFlags;
|
||||
|
||||
// Do not allow any input features to be set without sanitizing them first.
|
||||
h.inputFeatures = 0;
|
||||
h.inputConfig = InputConfigAdapter.getInputConfigFromWindowParams(
|
||||
type, sanitizedLpFlags, 0 /*inputFeatures*/);
|
||||
|
||||
if (region == null) {
|
||||
h.replaceTouchableRegionWithCrop(null);
|
||||
} else {
|
||||
h.touchableRegion.set(region);
|
||||
h.replaceTouchableRegionWithCrop = false;
|
||||
h.setTouchableRegionCrop(surface);
|
||||
|
||||
if ((flags & LayoutParams.FLAG_NOT_FOCUSABLE) != 0) {
|
||||
h.inputConfig |= InputConfig.NOT_FOCUSABLE;
|
||||
}
|
||||
|
||||
// Check private trusted overlay flag to set trustedOverlay field of input window handle.
|
||||
h.trustedOverlay = (privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0;
|
||||
if ((privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0) {
|
||||
h.inputConfig |= InputConfig.TRUSTED_OVERLAY;
|
||||
}
|
||||
|
||||
SurfaceControl.Transaction t = mTransactionFactory.get();
|
||||
h.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
|
||||
h.ownerUid = callingUid;
|
||||
h.ownerPid = callingPid;
|
||||
|
||||
if (region == null) {
|
||||
h.replaceTouchableRegionWithCrop = true;
|
||||
} else {
|
||||
h.touchableRegion.set(region);
|
||||
}
|
||||
h.setTouchableRegionCrop(null /* use the input surface's bounds */);
|
||||
|
||||
final SurfaceControl.Transaction t = mTransactionFactory.get();
|
||||
t.setInputWindowInfo(surface, h);
|
||||
t.apply();
|
||||
t.close();
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.wm;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.ColorSpace;
|
||||
import android.graphics.GraphicBuffer;
|
||||
import android.graphics.Matrix;
|
||||
@@ -134,6 +135,12 @@ public class StubTransaction extends SurfaceControl.Transaction {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public SurfaceControl.Transaction setCrop(@NonNull SurfaceControl sc, @Nullable Rect crop) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceControl.Transaction setCornerRadius(SurfaceControl sc, float cornerRadius) {
|
||||
return this;
|
||||
|
||||
@@ -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;
|
||||
@@ -81,6 +83,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;
|
||||
@@ -754,10 +757,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);
|
||||
@@ -767,13 +775,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;
|
||||
@@ -799,15 +808,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
|
||||
|
||||
Reference in New Issue
Block a user