這兩天準備寫一下input子系統的分析,過程中發現了兩個好工具,呵呵,就是本文介紹的主角:getevent用于擷取目前系統input裝置的一些參數和實時事件的資料;sendevent用于發送input事件,這樣在調試的時候遇到有的樣機按鍵壞了或者觸摸屏壞了就友善了,工具的源碼位于Android SDK的system/core/toolbox下面。
一、getevent
首先看一下指令的用法說明:
# getevent -h
Usage: getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-p] [-q] [-c count] [-r] [device]
-t: show time stamps
-n: don't print newlines
-s: print switch states for given bits
-S: print all switch states
-v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32)
-p: show possible events (errs, dev, name, pos. events)
-q: quiet (clear verbosity mask)
-c: print given number of events then exit
-r: print rate events are received
其中 [-t] 參數顯示事件的時間戳,[-n] 取消事件顯示時的換行符,[-s switchmask] 得到指定位的開關狀态,[-S] 得到所有開關的狀态,[-v [mask]] 根據mask的值顯示相關資訊,後面詳細介紹mask的使用方法,[-p] 顯示每個裝置支援的事件類型和編碼,[-q] 隻顯示事件資料,[-c count] 隻顯示count次事件的資料,[-r] 顯示事件接收頻率。下面看一下指令以及相關參數的使用結果:
1、getevent -p
# getevent -p
add device 1: /dev/input/event4
name: "tempsensor"
events:
SYN (0000): 0000 0003
ABS (0003): 0010 value 0, min 0, max 100, fuzz 0 flat 0
add device 2: /dev/input/event3
name: "accsensor"
events:
SYN (0000): 0000 0003
ABS (0003): 0000 value -23, min 0, max 0, fuzz 0 flat 0
0001 value -8, min 0, max 0, fuzz 0 flat 0
0002 value -966, min 0, max 0, fuzz 0 flat 0
add device 3: /dev/input/event2
name: "xx_keypad"
events:
SYN (0000): 0000 0001
KEY (0001): 0000 0001 0002 0003 0004 0005 0006 0007
0008 0009 000a 000b 000c 000d 000e 000f
0010 0011 0012 0013 0014 0015 0016 0017
0018 0019 001a 001b 001c 001d 001e 001f
0020 0021 0022 0023 0024 0025 0026 0027
0028 0029 002a 002b 002c 002d 002e 002f
0030 0031 0032 0033 0034 0035 0036 0037
0038 0039 003a 003b 003c 003d 003e 003f
0074
add device 4: /dev/input/event1
name: "xx_ts"
events:
SYN (0000): 0000 0001 0003
KEY (0001): 0066 008b 009e 00d9
ABS (0003): 0030 value 0, min 0, max 255, fuzz 0 flat 0
0035 value 0, min 0, max 320, fuzz 0 flat 0
0036 value 0, min 0, max 480, fuzz 0 flat 0
可以看到 [-p] 參數顯示出來目前系統存在的所有input裝置,并且把每個裝置支援的事件類型以及編碼都列舉了出來,比如xx_ts:
SYN (0000): 0000 0001 0003
表示xx_ts支援的事件類型有: EV_SYN [0000] (同步事件), EV_KEY [0001] (按鍵事件), EV_ABS [0003] (絕對值事件);
KEY (0001): 0066 008b 009e 00d9
表示xx_ts支援的按鍵編碼有:KEY_HOME [0066] (HOME鍵),KEY_MENU [008b] (MENU鍵)
KEY_BACK [009e] (BACK鍵),KEY_SEARCH [00d9] (SEARCH鍵)
ABS (0003): 0030 value 0, min 0, max 255, fuzz 0 flat 0
0035 value 0, min 0, max 320, fuzz 0 flat 0
0036 value 0, min 0, max 480, fuzz 0 flat 0
表示xx_ts支援的絕對值編碼有:ABS_MT_TOUCH_MAJOR [0030] (接觸面長軸值) {有效值範圍[0, 255]}
ABS_MT_POSITION_X [0035] (x軸坐标) {有效值範圍[0, 320]}
ABS_MT_POSITION_Y [0036] (y軸坐标) {有效值範圍[0, 480]}
2、getevent -v [mask]
[-v] 參數會根據mask的值決定顯示内容,在源碼中可以找到相應位的定義:
enum {
PRINT_DEVICE_ERRORS = 1U << 0,
PRINT_DEVICE = 1U << 1,
PRINT_DEVICE_NAME = 1U << 2,
PRINT_DEVICE_INFO = 1U << 3,
PRINT_VERSION = 1U << 4,
PRINT_POSSIBLE_EVENTS = 1U << 5,
};
其中 PRINT_DEVICE_ERRORS 顯示錯誤資訊,PRINT_DEVICE 顯示裝置個數,PRINT_DEVICE_NAME 顯示裝置名稱,PRINT_DEVICE_INFO 顯示裝置資訊,PRINT_VERSION 顯示裝置版本号,PRINT_POSSIBLE_EVENTS 顯示裝置支援的事件類型及編碼。唯一覺得有缺憾的是 [-v] 參數執行後會一直顯示事件的資料,而沒有mask決定是否顯示這些資料,不過可以通過grep過濾掉。在輸入指令時根據相應的位決定mask值:
# getevent -v 63
add device 1: /dev/input/event4
bus: 0000
vendor 0000
product 0000
version 0000
name: "tempsensor"
location: ""
id: ""
version: 1.0.0
events:
SYN (0000): 0000 0003
ABS (0003): 0010 value 0, min 0, max 100, fuzz 0 flat 0
...
這樣就顯示出了所有的資訊。
二、sendevent
sendevent就比較有用了,首先看一下它的用法說明:
# sendevent
use: sendevent device type code value
可以看到sendevent需要4個參數即:device,type,code,value。這些值可以由input子系統定義,也可以從getevent裡面擷取,比如我們要模拟一次 BACK 事件,根據前面的資訊可知BACK的編碼為0x9e即158,那我們輸入如下指令即可模拟一次BACK鍵的按下和彈起:
# sendevent /dev/input/event1 1 158 1
# sendevent /dev/input/event1 1 158 0
device需要是支援該按鍵的裝置這裡是xx_ts;type為1表示是按鍵事件;value為1表示按下,為0表示彈起,一次按鍵事件由按下和彈起兩個操作組成。另外Android還在framework層提供了輸入鍵值的工具input,這些我們後面再詳細分析。