Android Input概念

442 阅读30分钟

基于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的xdevice的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 来确认,例如DOWNUP事件;

我们分析几种场景的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:用于记录已分发给目标窗口且目标窗口尚未响应完成的输入事件;

Input超时机制.jpg

    -   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