基于Android R版本分析
getevent -ltr
getevent -ltr:查看屏幕报点情况,可以理解为屏幕触摸情况。 “-ltr” :滑动查看屏幕触控报点是否正常和均匀
add device 1: /dev/input/event0
name: "Power Button"
add device 2: /dev/input/event11
name: "virtio_input_multi_touch_10"
add device 3: /dev/input/event2
name: "virtio_input_multi_touch_1"
add device 4: /dev/input/event8
name: "virtio_input_multi_touch_7"
add device 5: /dev/input/event5
name: "virtio_input_multi_touch_4"
add device 6: /dev/input/event12
name: "virtio_input_multi_touch_11"
add device 7: /dev/input/event9
name: "virtio_input_multi_touch_8"
add device 8: /dev/input/event13
name: "qwerty2"
add device 9: /dev/input/event7
name: "virtio_input_multi_touch_6"
add device 10: /dev/input/event4
name: "virtio_input_multi_touch_3"
add device 11: /dev/input/event6
name: "virtio_input_multi_touch_5"
add device 12: /dev/input/event3
name: "virtio_input_multi_touch_2"
add device 13: /dev/input/event10
name: "virtio_input_multi_touch_9"
add device 14: /dev/input/event1
name: "AT Translated Set 2 keyboard"
[ 62.807777] /dev/input/event2: EV_ABS ABS_MT_TRACKING_ID 00000000
[ 62.807777] /dev/input/event2: EV_ABS ABS_MT_TOUCH_MAJOR 00000003
[ 62.807777] /dev/input/event2: EV_ABS ABS_MT_PRESSURE 00000081
[ 62.807777] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 00003888
[ 62.807777] /dev/input/event2: EV_ABS ABS_MT_POSITION_Y 000030dd
[ 62.807777] /dev/input/event2: EV_SYN SYN_REPORT 00000000
[ 63.052725] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 000038e3
[ 63.052725] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 4
[ 63.060639] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 0000391f
[ 63.060639] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 126
[ 63.068818] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 0000395c
[ 63.068818] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 122
[ 63.076632] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 00003999
[ 63.076632] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 127
[ 63.085879] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 00003a30
[ 63.085879] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 108
[ 63.092674] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 00003a6d
[ 63.092674] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 147
[ 63.100632] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 00003aaa
[ 63.100632] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 125
[ 63.108705] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 00003ae6
[ 63.108705] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 123
[ 63.116653] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 00003b41
[ 63.116653] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 125
[ 63.124668] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 00003b7e
[ 63.124668] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 124
[ 63.132577] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 00003bbb
[ 63.132577] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 126
[ 63.348752] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 00003bf7
[ 63.348752] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 4
[ 63.356656] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 00003c34
[ 63.356656] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 126
[ 63.365029] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 00003c8f
[ 63.365029] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 119
[ 63.612830] /dev/input/event2: EV_ABS ABS_MT_PRESSURE 00000000
[ 63.612830] /dev/input/event2: EV_ABS ABS_MT_TRACKING_ID ffffffff
[ 63.612830] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 4
[ 64.989199] /dev/input/event3: EV_ABS ABS_MT_TRACKING_ID 00000000
[ 64.989199] /dev/input/event3: EV_ABS ABS_MT_TOUCH_MAJOR 00000004
[ 64.989199] /dev/input/event3: EV_ABS ABS_MT_PRESSURE 00000081
[ 64.989199] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 00003d09
[ 64.989199] /dev/input/event3: EV_ABS ABS_MT_POSITION_Y 00003677
[ 64.989199] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 0
[ 65.436772] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 00003da0
[ 65.436772] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 2
[ 65.452627] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 00003ddd
[ 65.452627] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 63
[ 65.460646] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 00003e56
[ 65.460646] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 124
[ 65.468654] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 00003f2b
[ 65.468654] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 124
[ 65.476663] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 00003f67
[ 65.476663] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 124
[ 65.652995] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 00003fff
[ 65.652995] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 5
[ 65.660641] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 0000403c
[ 65.660641] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 130
[ 65.668570] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 00004078
[ 65.668570] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 126
[ 65.684582] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 000040b5
[ 65.684582] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 62
[ 65.692600] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 000040f2
[ 65.692600] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 124
[ 65.988779] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 0000414d
[ 65.988779] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 3
[ 65.996845] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 000041c6
[ 65.996845] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 123
[ 66.004659] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 00004203
[ 66.004659] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 127
[ 66.012600] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 0000425e
[ 66.012600] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 125
[ 66.284756] /dev/input/event3: EV_ABS ABS_MT_PRESSURE 00000000
[ 66.284756] /dev/input/event3: EV_ABS ABS_MT_TRACKING_ID ffffffff
[ 66.284756] /dev/input/event3: EV_SYN SYN_REPORT 00000000 rate 3
- device x:代表了input设备,x代表了device添加的顺序,也代表了device Id;
- /dev/input/eventx:代表了input设备在驱动层的节点,event的x和device的x不一定是相等的;
- name:节点name;
屏幕信息在代码中使用input_event结构体进行定义;
struct input_event {
// 事件发生的时间戳,单位是微秒
struct timeval time;
// 事件的类型,可以是EV_SYN(同步事件)、EV_KEY(按键事件)、EV_REL(相对位置事件)、EV_ABS(绝对位置事件)等
__u16 type;
// 事件的代码,用于指定具体的按键、鼠标事件等
__u16 code;
// 事件的值,表示按键的状态、鼠标移动的量等
__s32 value;
};
type
EV_XXX:其中包括了EV_ABS和EV_SYN,代表了Event的type;
/*
* Event types
*/
// 事件间的分割标志,有些事件可能会在时间和空间上产生延续,比如持续按住一个按键,为了更好地管理这些持续的事件,EV_SYN用以将他们分割成一个个的小的数据包
#define EV_SYN 0x00
// 用以描述键盘,按键或者类似键盘的设备的状态变化(在Android R中,电源开关、按键也属于该类型)
#define EV_KEY 0x01
// 相对位移,比如鼠标的移动,滚轮的转动等
#define EV_REL 0x02
// 绝对位移,比如触摸屏上的坐标值
#define EV_ABS 0x03
// 不能匹配现有的类型,这相当于当前暂不识别的事件
#define EV_MSC 0x04
// 软件
#define EV_SW 0x05
// 用于控制设备上的LED灯的开关,比如按下键盘的大写锁定键 会同时产生 ”EV_KEY” 和 ”EV_LED” 两个事件
#define EV_LED 0x11
// 声音
#define EV_SND 0x12
// repeat、会自动发出重复按键
#define EV_REP 0x14
#define EV_FF 0x15
#define EV_PWR 0x16
#define EV_FF_STATUS 0x17
#define EV_MAX 0x1f
#define EV_CNT (EV_MAX+1)
code & value
event code用于对事件的类型作进一步的描述,比如:当发生 EV_KEY事件时,则可能是键盘被按下了,也有可能是Android设备的电源键和音量键,此时查看 code 就知道了;当发生 EV_REL 事件时,也许是鼠标动了,也许是滚轮动了;
event value用于描述当code都不足以区分事件的性质的时候,可以用 value 来确认,例如DOWN和UP事件;
我们分析几种场景的Event code;
EV_SYN code
// 用于同步和分割事件到不同的数据包,当一组操作Event执行完成之后,需要使用该code表明该组操作已完成,后续Input系统也是通过这个标志来分割事件的
#define SYN_REPORT 0
#define SYN_CONFIG 1
// 用于同步和分割触摸事件
#define SYN_MT_REPORT 2
// 用于指示evdev客户端的事件队列中的缓冲区溢出。客户端应忽略直到下一个SYN_REPORT事件的所有事件,并查询设备(使用EVIOCG * ioctls)以获取其当前状态
#define SYN_DROPPED 3
EV_ABS code
ABS_MT_:用于描述多点触输入事件,现在基本上Android设备上报的都是ABS_MT_XXX类型事件了;
#define ABS_MISC 0x28
// 本质代表者不同手指,它的value代表手指id
#define ABS_MT_SLOT 0x2f /* MT slot being modified */
// 接触部分的长轴长度。相当于椭圆的长轴
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
// 接触部分的短轴长度。相当于椭圆的短轴
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
// 相对于屏幕中心的x,y坐标
#define ABS_MT_POSITION_X 0x35 /* Center X touch position */
#define ABS_MT_POSITION_Y 0x36 /* Center Y touch position */
#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
// 类型B特有的,实际上,每个slot会和一个ID相对应,一个非负数的表示一次接触,-1表示这是一个无用的slot(或者理解为一次接触的结束) 。无论在接触的类型相对应的slot发生了改变,驱动都应该通过改变这个值来使这个slot失效。并且下一次触摸的ID值会是这次的值加1
#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
// 代表按下压力,有的设备不一定有
#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */
#define ABS_MT_DISTANCE 0x3b /* Contact hover distance */
#define ABS_MT_TOOL_X 0x3c /* Center X tool position */
#define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */
EV_KEY code
// 按键的是finger,并且其值是DOWN或者UP
#define BTN_TOOL_FINGER 0x145
// 触碰按键,其值是DOWN或者UP
#define BTN_TOUCH 0x14a
Device properties
设备特性,正常情况下,用户空间基于设备发出的数据(比如事件的types)来建立一个输入设备,当两个设备都发出相同的事件types时,这时设备特性就可以提供额外的识别信息;
针对Android设备,核心的两个特性:INPUT_PROP_DIRECT + INPUT_PROP_POINTER;
INPUT_PROP_DIRECT + INPUT_PROP_POINTER
INPUT_PROP_DIRECT属性表示设备坐标系应该直接被映射为屏幕坐标系(不考虑琐碎的变换,例如缩放,翻转和旋转)
- 典型的direct输入设备有:触摸屏、绘画平板;
Non-direct输入设备需要特殊的变换,例如触摸板的绝对向相对的变换
- non-direct输入设备有:触摸板、鼠标。
INPUT_PROP_POINTER属性表示设备没有在屏幕上移动,因此需要使用屏幕指针来追踪用户的移动
- 典型的pointer设备有:触摸屏板、笔记本电脑、鼠标;
- non-pointer设备有:触摸屏;
如果INPUT_PROP_POINTER或者INPUT_PROP_DIRECT均没有被设置,则认为属性是未定义的 ,设备类型应通过发送的事件类型这传统的方式进行推断;
INPUT_PROP_BUTTONPAD
对于表面下方有按键的触摸板,按下触摸板后会产生一个按键单击,这种情况下这个属性需要被设置;这属性通常存在于2009年以来的笔记本和macbook的触摸板中;
起初,buttonpad属性被编码在bcm5974驱动版本字段中,名称为集成按键。为了确保向前兼容,在用户空间中这两种方式都需要进行检验;
INPUT_PROP_SEMI_MT
略;
INPUT_PROP_TOPBUTTONPAD
略;
INPUT_PROP_ACCELEROMETER
略;
dumpsys input
INPUT MANAGER (dumpsys input)
Input Manager State:
Interactive: false
System UI Visibility: 0x8008
Pointer Speed: 0
// 全局Pointer事件
Pointer Gestures Enabled: true
// 屏幕触摸小白点
Show Touches: false
Pointer Capture Enabled: false
// Event HUB状态信息
Event Hub State:
BuiltInKeyboardId: 1
// device id的值,代表的就是input设备进行add的顺序,和匹配的event Id是对应不上的
Devices:
-1: Virtual
Classes: 0x40000023
Path: <virtual>
Enabled: true
Descriptor: a718a782d34bc767f4689c232d64d527998ea7fd
Location:
ControllerNumber: 0
UniqueId: <virtual>
Identifier: bus=0x0000, vendor=0x0000, product=0x0000, version=0x0000
KeyLayoutFile: /system/usr/keylayout/Generic.kl
KeyCharacterMapFile: /system/usr/keychars/Virtual.kcm
ConfigurationFile:
HaveKeyboardLayoutOverlay: false
VideoDevice: <none>
1: uinput-fpc (aka device 0 - built-in keyboard)
Classes: 0x00000001
Path: /dev/input/event3
Enabled: true
Descriptor: 0a2365ce4f51162539f3bf91469900de3a450172
Location:
ControllerNumber: 0
UniqueId:
Identifier: bus=0x0006, vendor=0x0000, product=0x0000, version=0x0000
KeyLayoutFile: /vendor/usr/keylayout/uinput-fpc.kl
KeyCharacterMapFile: /system/usr/keychars/Generic.kcm
ConfigurationFile: /vendor/usr/idc/uinput-fpc.idc
HaveKeyboardLayoutOverlay: false
VideoDevice: <none>
// 触摸屏设备
2: sec_touchscreen
Classes: 0x00000095
// 对应设备节点的路径
Path: /dev/input/event2
Enabled: true
Descriptor: 0fa9d3d0d40f7f5b316320876742e00ad5eb1ba9
Location: sec_touchscreen/input1
ControllerNumber: 0
UniqueId:
Identifier: bus=0x0018, vendor=0x0000, product=0x0000, version=0x0000
KeyLayoutFile: /system/usr/keylayout/Generic.kl
KeyCharacterMapFile: /system/usr/keychars/Generic.kcm
ConfigurationFile:
HaveKeyboardLayoutOverlay: false
VideoDevice: <none>
// 高通平台按键设备(已知的:power按键、音量键)
3: qpnp_pon
Classes: 0x00000001
Path: /dev/input/event0
Enabled: true
Descriptor: fb60d4f4370f5dbe8267b63d38dea852987571ab
Location: qpnp_pon/input0
ControllerNumber: 0
UniqueId:
Identifier: bus=0x0000, vendor=0x0000, product=0x0000, version=0x0000
KeyLayoutFile: /system/usr/keylayout/Generic.kl
KeyCharacterMapFile: /system/usr/keychars/Generic.kcm
ConfigurationFile:
HaveKeyboardLayoutOverlay: false
VideoDevice: <none>
4: gpio-keys
Classes: 0x00000001
Path: /dev/input/event1
Enabled: true
Descriptor: 485d69228e24f5e46da1598745890b214130dbc4
Location: gpio-keys/input0
ControllerNumber: 0
UniqueId:
Identifier: bus=0x0019, vendor=0x0001, product=0x0001, version=0x0100
KeyLayoutFile: /system/usr/keylayout/Generic.kl
KeyCharacterMapFile: /system/usr/keychars/Generic.kcm
ConfigurationFile:
HaveKeyboardLayoutOverlay: false
VideoDevice: <none>
Unattached video devices:
<none>
Input Reader State (Nums of device: 5):
// 设备名称
Device 4: sec_touchscreen
// Input Reader和Event Hub的映射关系
EventHub Devices: [ 2 ]
Generation: 478
IsExternal: false
AssociatedDisplayPort: <none>
HasMic: false
Sources: 0x80001103
KeyboardType: 1
ControllerNum: 0
Motion Ranges:
X: source=0x00001002, min=0.000, max=1439.000, flat=0.000, fuzz=0.000, resolution=0.000
Y: source=0x00001002, min=0.000, max=2959.000, flat=0.000, fuzz=0.000, resolution=0.000
PRESSURE: source=0x00001002, min=0.000, max=1.000, flat=0.000, fuzz=0.000, resolution=0.000
SIZE: source=0x00001002, min=0.000, max=1.000, flat=0.000, fuzz=0.000, resolution=0.000
TOUCH_MAJOR: source=0x00001002, min=0.000, max=3291.687, flat=0.000, fuzz=0.000, resolution=0.000
TOUCH_MINOR: source=0x00001002, min=0.000, max=3291.687, flat=0.000, fuzz=0.000, resolution=0.000
TOOL_MAJOR: source=0x00001002, min=0.000, max=3291.687, flat=0.000, fuzz=0.000, resolution=0.000
TOOL_MINOR: source=0x00001002, min=0.000, max=3291.687, flat=0.000, fuzz=0.000, resolution=0.000
Switch Input Mapper:
SwitchValues: 0
Keyboard Input Mapper:
Parameters:
OrientationAware: false
HandlesKeyRepeat: false
KeyboardType: 1
Orientation: 0
KeyDowns: 0 keys currently down
MetaState: 0x0
DownTime: 0
Touch Input Mapper (mode - direct):
Parameters:
// 手势模式:多屏触摸
GestureMode: multi-touch
DeviceType: touchScreen
// 这里面的displayId属性值也是比较核心的,也关联着当前屏幕是否支持触摸事件
// hasAssociatedDisplay:是否有相关显示
AssociatedDisplay: hasAssociatedDisplay=true, isExternal=false, displayId=''
OrientationAware: true
Raw Touch Axes:
X: min=0, max=1439, flat=0, fuzz=0, resolution=0
Y: min=0, max=2959, flat=0, fuzz=0, resolution=0
Pressure: min=0, max=63, flat=0, fuzz=0, resolution=0
TouchMajor: min=0, max=255, flat=0, fuzz=0, resolution=0
TouchMinor: min=0, max=255, flat=0, fuzz=0, resolution=0
ToolMajor: unknown range
ToolMinor: unknown range
Orientation: unknown range
Distance: unknown range
TiltX: unknown range
TiltY: unknown range
TrackingId: min=0, max=65535, flat=0, fuzz=0, resolution=0
Slot: min=0, max=9, flat=0, fuzz=0, resolution=0
Calibration:
touch.size.calibration: geometric
touch.pressure.calibration: physical
touch.orientation.calibration: none
touch.distance.calibration: none
touch.coverage.calibration: none
Affine Transformation:
X scale: 1.000
X ymix: 0.000
X offset: 0.000
Y xmix: 0.000
Y scale: 1.000
Y offset: 0.000
// 这里最核心的一个点:displayId属性值,它有可能决定了该屏幕的触摸是否有效
Viewport INTERNAL: displayId=0, uniqueId=local:0, port=0, orientation=0, logicalFrame=[0, 0, 1440, 2960], physicalFrame=[0, 0, 1440, 2960], deviceSize=[1440, 2960], isActive=[0]
// 分辨率像素点
RawSurfaceWidth: 1440px
RawSurfaceHeight: 2960px
SurfaceLeft: 0
SurfaceTop: 0
SurfaceRight: 1440
SurfaceBottom: 2960
PhysicalWidth: 1440px
PhysicalHeight: 2960px
PhysicalLeft: 0
PhysicalTop: 0
SurfaceOrientation: 0
Translation and Scaling Factors:
XTranslate: 0.000
YTranslate: 0.000
XScale: 1.000
YScale: 1.000
XPrecision: 1.000
YPrecision: 1.000
GeometricScale: 1.000
PressureScale: 0.016
SizeScale: 0.004
OrientationScale: 0.000
DistanceScale: 0.000
HaveTilt: false
TiltXCenter: 0.000
TiltXScale: 0.000
TiltYCenter: 0.000
TiltYScale: 0.000
Last Raw Button State: 0x00000000
Last Raw Touch: pointerCount=0
Last Cooked Button State: 0x00000000
Last Cooked Touch: pointerCount=0
Stylus Fusion:
ExternalStylusConnected: false
External Stylus ID: -1
External Stylus Data Timeout: 9223372036854775807
External Stylus State:
When: 9223372036854775807
Pressure: 0.000000
Button State: 0x00000000
Tool Type: 0
Device 0: uinput-fpc
EventHub Devices: [ 0 ]
Generation: 15
IsExternal: false
AssociatedDisplayPort: <none>
HasMic: false
Sources: 0x00000101
KeyboardType: 1
ControllerNum: 0
Keyboard Input Mapper:
Parameters:
OrientationAware: true
HandlesKeyRepeat: false
KeyboardType: 1
Orientation: 0
KeyDowns: 0 keys currently down
MetaState: 0x0
DownTime: 188597038214000
Device 3: qpnp_pon
EventHub Devices: [ 3 ]
Generation: 9
IsExternal: false
AssociatedDisplayPort: <none>
HasMic: false
Sources: 0x00000101
KeyboardType: 1
ControllerNum: 0
Keyboard Input Mapper:
Parameters:
OrientationAware: false
HandlesKeyRepeat: false
KeyboardType: 1
Orientation: 0
KeyDowns: 0 keys currently down
MetaState: 0x0
DownTime: 220205942702000
Device 2: gpio-keys
EventHub Devices: [ 4 ]
Generation: 6
IsExternal: false
AssociatedDisplayPort: <none>
HasMic: false
Sources: 0x00000101
KeyboardType: 1
ControllerNum: 0
Keyboard Input Mapper:
Parameters:
OrientationAware: false
HandlesKeyRepeat: false
KeyboardType: 1
Orientation: 0
KeyDowns: 0 keys currently down
MetaState: 0x0
DownTime: 217336178555000
Device -1: Virtual
EventHub Devices: [ -1 ]
Generation: 3
IsExternal: false
AssociatedDisplayPort: <none>
HasMic: false
Sources: 0x00000301
KeyboardType: 2
ControllerNum: 0
Keyboard Input Mapper:
Parameters:
OrientationAware: false
HandlesKeyRepeat: false
KeyboardType: 2
Orientation: 0
KeyDowns: 0 keys currently down
MetaState: 0x0
DownTime: 0
Configuration:
ExcludedDeviceNames: []
VirtualKeyQuietTime: 0.0ms
PointerVelocityControlParameters: scale=1.000, lowThreshold=500.000, highThreshold=3000.000, acceleration=3.000
WheelVelocityControlParameters: scale=1.000, lowThreshold=15.000, highThreshold=50.000, acceleration=4.000
PointerGesture:
Enabled: true
QuietInterval: 100.0ms
DragMinSwitchSpeed: 50.0px/s
TapInterval: 150.0ms
TapDragInterval: 300.0ms
TapSlop: 20.0px
MultitouchSettleInterval: 100.0ms
MultitouchMinDistance: 15.0px
SwipeTransitionAngleCosine: 0.3
SwipeMaxWidthRatio: 0.2
MovementSpeedRatio: 0.8
ZoomSpeedRatio: 0.3
Viewports:
Viewport INTERNAL: displayId=0, uniqueId=local:0, port=0, orientation=0, logicalFrame=[0, 0, 1440, 2960], physicalFrame=[0, 0, 1440, 2960], deviceSize=[1440, 2960], isActive=[0]
Input Classifier State:
Motion Classifier:
<nullptr>
Input Dispatcher State:
// Dispatch是否可用
DispatchEnabled: true
DispatchFrozen: false
InputFilterEnabled: false
// 持有焦点的displayId
FocusedDisplayId: 0
// 持有焦点的Application进程
FocusedApplications:
// 其中包含了displayId信息,同时还包含了dispatchingTimeout属性值,这个代表的就是dispatch Event的超时时长定义,也就是我们常见的ANR类型中的屏幕触摸5s无响应ANR
displayId=0, name='ActivityRecord{cd5e7da u0 com.android.launcher3/.uioverrides.QuickstepLauncher t1126}', dispatchingTimeout=5000ms
// 持有焦点的窗口
FocusedWindows:
displayId=0, name='Window{4f0df6 u0 NotificationShade}'
TouchStates: <no displays touched>
Display: 0
Windows:
// displayId:窗口对应所在的display
// portalToDisplayId:用于表述用户窗口,一般情况下为-1,不会使用到,但是在不为-1的情况下,可以理解为真正响应Touch事件所对应的display
// frame:窗口范围大小
// windowScale:窗口缩放比例
// touchableRegion:窗口对应的可响应Touch的区域大小
// dispatchingTimeout:超时时长
0: name='Window{164b93e u0 ScreenDecorOverlay}', displayId=0, portalToDisplayId=-1, paused=false, hasFocus=false, hasWallpaper=false, visible=true, canReceiveKeys=false, flags=0x20800128, type=0x000007e8, frame=[0,0][1440,171], globalScale=1.000000, windowScale=(1.000000,1.000000), touchableRegion=[462,0][978,171], inputFeatures=0x00000000, ownerPid=21883, ownerUid=10128, dispatchingTimeout=5000ms
1: name='ColorFade#0', displayId=0, portalToDisplayId=-1, paused=false, hasFocus=false, hasWallpaper=false, visible=true, canReceiveKeys=false, flags=0x00000020, type=0x00000000, frame=[0,0][1440,2960], globalScale=1.000000, windowScale=(1.000000,1.000000), touchableRegion=<empty>, inputFeatures=0x00000002, ownerPid=1504, ownerUid=1000, dispatchingTimeout=0ms
2: name='Window{131986e u0 NavigationBar0}', displayId=0, portalToDisplayId=-1, paused=false, hasFocus=false, hasWallpaper=false, visible=false, canReceiveKeys=false, flags=0x21840068, type=0x000007e3, frame=[0,2792][1440,2960], globalScale=1.000000, windowScale=(1.000000,1.000000), touchableRegion=[0,2792][1440,2960], inputFeatures=0x00000000, ownerPid=21883, ownerUid=10128, dispatchingTimeout=5000ms
3: name='Window{4f0df6 u0 NotificationShade}', displayId=0, portalToDisplayId=-1, paused=false, hasFocus=true, hasWallpaper=false, visible=true, canReceiveKeys=true, flags=0x81860060, type=0x000007f8, frame=[0,0][1440,2960], globalScale=1.000000, windowScale=(1.000000,1.000000), touchableRegion=[-1440,-2960][2880,5920], inputFeatures=0x00000004, ownerPid=21883, ownerUid=10128, dispatchingTimeout=5000ms
4: name='Window{e2a4ad0 u0 StatusBar}', displayId=0, portalToDisplayId=-1, paused=false, hasFocus=false, hasWallpaper=false, visible=true, canReceiveKeys=false, flags=0x81800008, type=0x000007d0, frame=[0,0][1440,171], globalScale=1.000000, windowScale=(1.000000,1.000000), touchableRegion=[0,0][1440,171], inputFeatures=0x00000000, ownerPid=21883, ownerUid=10128, dispatchingTimeout=5000ms
5: name='Window{bdf915 u0 com.android.systemui.ImageWallpaper}', displayId=0, portalToDisplayId=-1, paused=false, hasFocus=false, hasWallpaper=false, visible=false, canReceiveKeys=false, flags=0x00014318, type=0x000007dd, frame=[-72,-148][2091,3108], globalScale=1.000000, windowScale=(0.909091,0.909091), touchableRegion=[-72,-148][2091,3108], inputFeatures=0x00000000, ownerPid=21883, ownerUid=10128, dispatchingTimeout=5000ms
// Global moitors是每个屏幕基本上都必须支持的
Global monitors in display 0:
0: 'PointerEventDispatcher0 (server)',
// 最近处理的MotionEvent
RecentQueue: length=10
MotionEvent(deviceId=4, source=0x00001002, displayId=0, action=MOVE, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=nan, yCursorPosition=nan, pointers=[0: (768.0, 2022.0)]), policyFlags=0x62000000, age=132082ms
MotionEvent(deviceId=4, source=0x00001002, displayId=0, action=MOVE, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=nan, yCursorPosition=nan, pointers=[0: (767.0, 2022.0)]), policyFlags=0x62000000, age=132073ms
MotionEvent(deviceId=4, source=0x00001002, displayId=0, action=MOVE, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=nan, yCursorPosition=nan, pointers=[0: (766.0, 2022.0)]), policyFlags=0x62000000, age=132065ms
MotionEvent(deviceId=4, source=0x00001002, displayId=0, action=MOVE, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=nan, yCursorPosition=nan, pointers=[0: (765.0, 2022.0)]), policyFlags=0x62000000, age=132056ms
MotionEvent(deviceId=4, source=0x00001002, displayId=0, action=MOVE, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=nan, yCursorPosition=nan, pointers=[0: (764.0, 2023.0)]), policyFlags=0x62000000, age=132048ms
MotionEvent(deviceId=4, source=0x00001002, displayId=0, action=MOVE, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=nan, yCursorPosition=nan, pointers=[0: (765.0, 2028.0)]), policyFlags=0x62000000, age=132040ms
MotionEvent(deviceId=4, source=0x00001002, displayId=0, action=UP, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=nan, yCursorPosition=nan, pointers=[0: (765.0, 2028.0)]), policyFlags=0x62000000, age=132032ms
DeviceResetEvent(deviceId=4), policyFlags=0x00000000, age=99924ms
FocusEvent(hasFocus=false), age=99754ms
FocusEvent(hasFocus=true), age=99651ms
PendingEvent: <none>
InboundQueue: <empty>
ReplacedKeys: <empty>
// 这个算是比较核心的概念,每一个InputChannel都会对应一个Connection实例
Connections:
325: channelName='9dae881 com.android.settings/com.android.settings.SubSettings (server)', windowName='9dae881 com.android.settings/com.android.settings.SubSettings (server)', status=NORMAL, monitor=false, responsive=true
// 用于存放从InputReader中读取出来的InputEvent集合
OutboundQueue: <empty>
// 用于存放需要等待应用进程反馈的InputEvent集合
WaitQueue: <empty>
310: channelName='b7337a8 com.android.settings/com.android.settings.SubSettings (server)', windowName='b7337a8 com.android.settings/com.android.settings.SubSettings (server)', status=NORMAL, monitor=false, responsive=true
OutboundQueue: <empty>
WaitQueue: <empty>
224: channelName='b11c66d AssistPreviewPanel (server)', windowName='b11c66d AssistPreviewPanel (server)', status=NORMAL, monitor=false, responsive=true
OutboundQueue: <empty>
WaitQueue: <empty>
261: channelName='d4c6420 com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher (server)', windowName='d4c6420 com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher (server)', status=NORMAL, monitor=false, responsive=true
OutboundQueue: <empty>
WaitQueue: <empty>
273: channelName='bdf915 com.android.systemui.ImageWallpaper (server)', windowName='bdf915 com.android.systemui.ImageWallpaper (server)', status=NORMAL, monitor=false, responsive=true
OutboundQueue: <empty>
WaitQueue: <empty>
311: channelName='48da2ea com.android.settings/com.android.settings.Settings (server)', windowName='48da2ea com.android.settings/com.android.settings.Settings (server)', status=NORMAL, monitor=false, responsive=true
OutboundQueue: <empty>
WaitQueue: <empty>
264: channelName='164b93e ScreenDecorOverlay (server)', windowName='164b93e ScreenDecorOverlay (server)', status=NORMAL, monitor=false, responsive=true
OutboundQueue: <empty>
WaitQueue: <empty>
351: channelName='33a15f8 pip-dismiss-overlay (server)', windowName='33a15f8 pip-dismiss-overlay (server)', status=NORMAL, monitor=false, responsive=true
OutboundQueue: <empty>
WaitQueue: <empty>
257: channelName='e2a4ad0 StatusBar (server)', windowName='e2a4ad0 StatusBar (server)', status=NORMAL, monitor=false, responsive=true
OutboundQueue: <empty>
WaitQueue: <empty>
256: channelName='4f0df6 NotificationShade (server)', windowName='4f0df6 NotificationShade (server)', status=NORMAL, monitor=false, responsive=true
OutboundQueue: <empty>
WaitQueue: <empty>
245: channelName='131986e NavigationBar0 (server)', windowName='131986e NavigationBar0 (server)', status=NORMAL, monitor=false, responsive=true
OutboundQueue: <empty>
WaitQueue: <empty>
225: channelName='recents_animation_input_consumer (server)', windowName='recents_animation_input_consumer (server)', status=NORMAL, monitor=false, responsive=true
OutboundQueue: <empty>
WaitQueue: <empty>
319: channelName='3b6c494 InputMethod (server)', windowName='3b6c494 InputMethod (server)', status=NORMAL, monitor=false, responsive=true
OutboundQueue: <empty>
WaitQueue: <empty>
138: channelName='PointerEventDispatcher0 (server)', windowName='PointerEventDispatcher0 (server)', status=NORMAL, monitor=true, responsive=true
OutboundQueue: <empty>
WaitQueue: <empty>
AppSwitch: not pending
Configuration:
KeyRepeatDelay: 50ms
KeyRepeatTimeout: 400ms
Event Queue
参考:Android应用无响应机制;
在Input系统中,我们知道存在ANR超时的可能,这个超时机制中涉及到了几个Queue概念:
- InBoundQueue:用于记录InputReader发送过来的输入事件;
- OutBoundQueue:用于记录InputDispatcher即将分发给目标窗口的输入事件;
- waitQueue:用于记录已分发给目标窗口且目标窗口尚未响应完成的输入事件;
- InputReader线程通过EventHub监听底层上报的输入事件,一旦收到输入事件则将其放至mInBoundQueue队列,并唤醒InputDispatcher线程
-
InputDispatcher开始分发输入事件,设置埋雷的起点时间;先检测是否有正在处理的事件(mPendingEvent),如果没有则取出mInBoundQueue队头的事件,并将其赋值给mPendingEvent,且重置ANR的timeout;否则不会从mInBoundQueue中取出事件,也不会重置timeout;
-
然后检查窗口是否就绪(checkWindowReadyForMoreInputLocked),满足以下任一情况,则会进入扫雷状态(检测前一个正在处理的事件是否超时),终止本轮事件分发,否则继续执行下一步骤;
- 对于按键类型的输入事件,则outboundQueue或者waitQueue不为空;
- 对于非按键的输入事件,则waitQueue不为空,且等待队头时间超时500ms;
-
当应用窗口准备就绪,则将mPendingEvent转移到outBoundQueue队列;
-
当outBoundQueue不为空,且应用管道对端连接状态正常,则将数据从outboundQueue中取出事件,放入waitQueue队列;
-
InputDispatcher通过socket告知目标应用所在进程可以准备开始干活;
-
App在初始化时默认已创建跟中控系统双向通信的socketpair,此时App的main线程(ActivityThread)收到输入事件后,会层层转发到目标窗口来处理;
-
App的main线程完成工作后,会通过socket向中控系统汇报工作完成,则中控系统会将该事件从waitQueue队列中移除;
InputWindow
这个过程中,涉及到两个概念:
- InputWindowInfo
- InputWindowHandle
这两个在Java层和native层都有定义,我们主要关注native层的定义,native层定义在InputWindow.h中;
InputWindowInfo
这个概念在InputFlinger和SurfaceFlinger中都有涉及到;
例如在WindowState层级发生了变化的时候,SurfaceFlinger也会同步进行变化。针对Window Layer的变化,SurfaceFlinger中的Layer同步进行变化,而在Layer进行变化的时候,会updateInputWindow,更新InputWindowInfo信息;
所以,我们需要切记,Input Window信息不是在WMS中进行变化的,而是在SurfaceFlinger中执行的,对应的函数为fillInputInfo();
在fillInputInfo()函数中会根据SurfaceFlinger中Layer中定义的DrawingState结构体信息创建对应的InputWindowInfo实例,并通过跨进程的方式传递到InputManager中;
struct InputWindowInfo {
InputWindowInfo() = default;
InputWindowInfo(const Parcel& from);
// Window flags from WindowManager.LayoutParams
enum {
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
FLAG_DIM_BEHIND = 0x00000002,
FLAG_BLUR_BEHIND = 0x00000004,
FLAG_NOT_FOCUSABLE = 0x00000008,
FLAG_NOT_TOUCHABLE = 0x00000010,
FLAG_NOT_TOUCH_MODAL = 0x00000020,
FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
FLAG_KEEP_SCREEN_ON = 0x00000080,
FLAG_LAYOUT_IN_SCREEN = 0x00000100,
FLAG_LAYOUT_NO_LIMITS = 0x00000200,
FLAG_FULLSCREEN = 0x00000400,
FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
FLAG_DITHER = 0x00001000,
FLAG_SECURE = 0x00002000,
FLAG_SCALED = 0x00004000,
FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
FLAG_LAYOUT_INSET_DECOR = 0x00010000,
FLAG_ALT_FOCUSABLE_IM = 0x00020000,
FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
FLAG_SHOW_WHEN_LOCKED = 0x00080000,
FLAG_SHOW_WALLPAPER = 0x00100000,
FLAG_TURN_SCREEN_ON = 0x00200000,
FLAG_DISMISS_KEYGUARD = 0x00400000,
FLAG_SPLIT_TOUCH = 0x00800000,
FLAG_SLIPPERY = 0x20000000,
};
// Window types from WindowManager.LayoutParams
enum {
FIRST_APPLICATION_WINDOW = 1,
TYPE_BASE_APPLICATION = 1,
TYPE_APPLICATION = 2,
TYPE_APPLICATION_STARTING = 3,
LAST_APPLICATION_WINDOW = 99,
FIRST_SUB_WINDOW = 1000,
TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1,
TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2,
TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3,
TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4,
LAST_SUB_WINDOW = 1999,
FIRST_SYSTEM_WINDOW = 2000,
TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW + 1,
TYPE_PHONE = FIRST_SYSTEM_WINDOW + 2,
TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW + 3,
TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW + 4,
TYPE_TOAST = FIRST_SYSTEM_WINDOW + 5,
TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 6,
TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW + 7,
TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW + 8,
TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW + 9,
TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW + 10,
TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW + 11,
TYPE_INPUT_METHOD_DIALOG = FIRST_SYSTEM_WINDOW + 12,
TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW + 13,
TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW + 14,
TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 15,
TYPE_DRAG = FIRST_SYSTEM_WINDOW + 16,
TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW + 17,
TYPE_POINTER = FIRST_SYSTEM_WINDOW + 18,
TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW + 19,
TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW + 20,
TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW + 21,
TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW + 22,
TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW + 24,
TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 27,
TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW + 32,
TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW + 34,
TYPE_NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40,
TYPE_TRUSTED_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 42,
LAST_SYSTEM_WINDOW = 2999,
};
enum {
INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES = 0x00000001,
INPUT_FEATURE_NO_INPUT_CHANNEL = 0x00000002,
INPUT_FEATURE_DISABLE_USER_ACTIVITY = 0x00000004,
};
/* These values are filled in by the WM and passed through SurfaceFlinger
* unless specified otherwise.
*/
// This value should NOT be used to uniquely identify the window. There may be different
// input windows that have the same token.
// 这个值不应该用来唯一地标识窗口。可能有不同的输入窗口具有相同的令牌。
// 例如在应用共享的场景下
sp<IBinder> token;
// This uniquely identifies the input window.
int32_t id = -1;
std::string name;
int32_t layoutParamsFlags = 0;
int32_t layoutParamsType = 0;
nsecs_t dispatchingTimeout = -1;
/* These values are filled in by SurfaceFlinger. */
int32_t frameLeft = -1;
int32_t frameTop = -1;
int32_t frameRight = -1;
int32_t frameBottom = -1;
/*
* SurfaceFlinger consumes this value to shrink the computed frame. This is
* different from shrinking the touchable region in that it DOES shift the coordinate
* space where-as the touchable region does not and is more like "cropping". This
* is used for window shadows.
*/
int32_t surfaceInset = 0;
// A global scaling factor for all windows. Unlike windowScaleX/Y this results
// in scaling of the TOUCH_MAJOR/TOUCH_MINOR axis.
float globalScaleFactor = 1.0f;
// Scaling factors applied to individual windows.
float windowXScale = 1.0f;
float windowYScale = 1.0f;
/*
* This is filled in by the WM relative to the frame and then translated
* to absolute coordinates by SurfaceFlinger once the frame is computed.
*/
// 可响应touch的范围
// 后续在InputDispatcher中,会根据该touchableRegion属性值来获取对应适配的window(InputWindowHandle)
Region touchableRegion;
bool visible = false;
bool canReceiveKeys = false;
bool hasFocus = false;
bool hasWallpaper = false;
bool paused = false;
int32_t ownerPid = -1;
int32_t ownerUid = -1;
int32_t inputFeatures = 0;
int32_t displayId = ADISPLAY_ID_NONE;
int32_t portalToDisplayId = ADISPLAY_ID_NONE;
InputApplicationInfo applicationInfo;
bool replaceTouchableRegionWithCrop = false;
wp<IBinder> touchableRegionCropHandle;
void addTouchableRegion(const Rect& region);
bool touchableRegionContainsPoint(int32_t x, int32_t y) const;
bool frameContainsPoint(int32_t x, int32_t y) const;
/* Returns true if the window is of a trusted type that is allowed to silently
* overlay other windows for the purpose of implementing the secure views feature.
* Trusted overlays, such as IME windows, can partly obscure other windows without causing
* motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
*/
bool isTrustedOverlay() const;
bool supportsSplitTouch() const;
bool overlaps(const InputWindowInfo* other) const;
status_t write(Parcel& output) const;
static InputWindowInfo read(const Parcel& from);
};
InputWindowHandle
本质上就是InputWindowInfo在Input系统中的一个封装,句柄;
class InputWindowHandle : public RefBase {
public:
inline const InputWindowInfo* getInfo() const {
return &mInfo;
}
sp<IBinder> getToken() const;
int32_t getId() const { return mInfo.id; }
sp<IBinder> getApplicationToken() {
return mInfo.applicationInfo.token;
}
inline std::string getName() const {
return !mInfo.name.empty() ? mInfo.name : "<invalid>";
}
inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const {
return mInfo.token ? mInfo.dispatchingTimeout : defaultValue;
}
inline std::chrono::nanoseconds getDispatchingTimeout(
std::chrono::nanoseconds defaultValue) const {
return mInfo.token ? std::chrono::nanoseconds(mInfo.dispatchingTimeout) : defaultValue;
}
/**
* Requests that the state of this object be updated to reflect
* the most current available information about the application.
*
* This method should only be called from within the input dispatcher's
* critical section.
*
* Returns true on success, or false if the handle is no longer valid.
*/
virtual bool updateInfo() = 0;
/**
* Updates from another input window handle.
*/
void updateFrom(const sp<InputWindowHandle> handle);
/**
* Releases the channel used by the associated information when it is
* no longer needed.
*/
void releaseChannel();
protected:
explicit InputWindowHandle();
virtual ~InputWindowHandle();
// 在InputWindowHandle中包含了InputWindowInfo变量
// 实际上InputWindowHandle才是最核心的部分
InputWindowInfo mInfo;
};
} // namespace androi