Android(安卓)Input子系统-含实例源码
1 Input子系统作用
Android很多外设都是用到输入输出设备,比如touchscreen,键盘,音量键等,输入设备对应Android 框架是Android input子系统,像我们定制类比较多的,很多 需要用到输入子系统,比如一键打开相机,一键唤醒,实体按键等。
2 Android input子系统框架
Android Input框架讲解最好的一篇文章
https://blog.csdn.net/mmmccc000/article/details/49756059
Android input框架主要分为三个部分,一个是kernel,一个是kl文件,kl也可
以划分为框架层,Framework层主要做监听、过滤、分发的工作,Android App部
分主要是接收Input子系统发上来的键值做对应的操作。
3 kernel input框架
Kernel主要是涉及Input设备节点的生成,proc文件系统的生成
有一个文章写Kernel框架非常好的,我就不再讲了,给几个链接
https://blog.csdn.net/u013604527/article/details/53432623/
https://blog.csdn.net/jscese/article/details/42123673
https://blog.csdn.net/xubin341719/article/details/7881735
4 如何在kernel添加一个新的键值
4.1 先在头文件里面添加
找个共用的头文件添加要的key值,正常是在include下面的,我的代码是在这个位
置
diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.hindex 87cf351..45a33ab 100644--- a/include/uapi/linux/input-event-codes.h+++ b/include/uapi/linux/input-event-codes.h@@ -335,7 +335,7 @@ #define KEY_RFKILL 247 /* Key that controls all radios */ #define KEY_MICMUTE 248 /* Mute / unmute the microphone */-+#define KEY_WEIQIFA_TEST 249 /* Code 255 is reserved for special needs of AT keyboard driver */
4.2 在kernel对应的位置注册和发送键值
注册的位置
/*包含头文件*/ #include /*声明input设备*/ struct input_dev *button_dev; /*注册input 子设备*/ printk(KERN_ERR " xxxx_wake_init\n"); if (!(button_dev= input_allocate_device())) { printk(KERN_ERR "input_dev: not enough memory\n"); return -ENOMEM; } button_dev->name = "xxxx"; button_dev->phys = "xxxx/event0"; button_dev->id.bustype = BUS_HOST; button_dev->id.vendor = 0x0001; button_dev->id.product = 0x0002; button_dev->id.version = 0x0100; button_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_SYN); set_bit(KEY_WEIQIFA_TEST,button_dev->keybit); err = input_register_device(button_dev); if (err) { printk(KERN_ERR " fail to input_register_device\n"); input_free_device(button_dev); return err; } printk(KERN_ERR "xxxx_wake_init success!!!\n"); return 0;
发送键值的位置
input_report_key(button_dev, KEY_WEIQIFA_TEST, 1); input_sync(button_dev); input_report_key(button_dev, KEY_WEIQIFA_TEST, 0); input_sync(button_dev);
4.3 写一个对应这个kl文件
kl文件简单介绍
Kl文件主要是起到了承上启下的作用,kernel发过来的键值主要通过kl文件来映
射,我们来看看kl文件里面的内容把。左边的是对应kernel上报上来的键值,后
面是对应Android Framework上的键值。
22 key 399 GRAVE 23 key 2 1 ... 49 key 103 DPAD_UP 50 key 102 HOME 51 key 105 DPAD_LEFT 52 key 106 DPAD_RIGHT 53 key 115 VOLUME_UP
kl文件哪里来的呢
我们看项目配置下面,有很多kl文件,那么是每个input子系统对应一个kl文件,
还是所有的项目共用一个kl文件?
kl源码位置在
./frameworks/base/data/keyboards/AVRCP.kl./frameworks/base/data/keyboards/G./frameworks/base/data/keyboards/Vendor_0079_Product_0011.kl./frameworks/base/data/keyboards/Vendor_045e_Product_028e.kl...
在运行的设备里,它的位置如下
rk3399_mid:/ # busybox find / -iname *.kl/system/usr/keylayout/Generic.kl/system/usr/keylayout/Vendor_0079_Product_0011.kl/system/usr/keylayout/qwerty.kl/system/usr/keylayout/rk29-keypad.kl/system/usr/keylayout/rtkbt_virtual_hid.kl...rk3399_mid:/ #
kl是跟input设备如何对应起来的呢
我们可以用这个命令来看看 cat /proc/bus/input/devices
kl文件里面的vendor和product分别对应下面的vendor和product
rk3399_mid:/ # cat /proc/bus/input/devicesI: Bus=0019 Vendor=0001 Product=0002 Version=0100N: Name="xxxx"P: Phys=iflytek/event0S: Sysfs=/devices/virtual/input/input0U: Uniq=H: Handlers=event0 cpufreqB: PROP=0B: EV=bB: KEY=100000 0 0 0B: ABS=0
添加我们对应的kl文件
文件命名跟你申请的vendor和product对应 上面的input设备对应的kl文件应该是:Vendor_0001_Product_0002.kl
里面的内容如下,当然如果你没有配置kl文件,默认会去Generic.kl找键值映
射,如果里面也没有,就会去其他kl文件继续找。
# OnLive, Inc. OnLive Wireless Controllerkey 249 BUTTON_A
4.4 mtk平台的一个input 子系统驱动例子
上面写的是在rockchip平台做的例子,下面给出一个mtk平台的例子
[mkt平台的input子系统例子]
(https://blog.csdn.net/weiqifa0/article/details/50387504)
5 Framework input系统介绍
Framework 主要做的事情是监听底层的input,然后分发给上层
下面的这个说的框架非常好,可以看看,我介绍完主要说明如何添加一个新的key
到系统里面
https://blog.csdn.net/wangkaiblog/article/details/12085183
https://blog.csdn.net/mmmccc000/article/details/49756059
6 添加一个新的键值
主要涉及到几个文件位置
下面列出需要修改的文件还有修改的差异点
base/api/current.txt
base/api/system-current.txt
base/core/java/android/view/KeyEvent.java
base/core/res/res/values/attrs.xml
/Generic.kl这里也可以根据驱动添加/
base/data/keyboards/Generic.kl
base/policy/src/com/android/internal/policy/impl/PhoneFallbackEventHandler.java
native/include/android/keycodes.h
native/include/input/InputEventLabels.h
diff --git a/api/current.txt b/api/current.txtindex 63fa997..a7a4a2b 100644--- a/api/current.txt+++ b/api/current.txt@@ -41599,6 +41599,7 @@ package android.view { field public static final int KEYCODE_ASSIST = 219; // 0xdb field public static final int KEYCODE_AT = 77; // 0x4d field public static final int KEYCODE_AUDIO = 314; // 0x13a+ field public static final int KEYCODE_WEIQIFA = 315; // 0x13B field public static final int KEYCODE_AVR_INPUT = 182; // 0xb6 field public static final int KEYCODE_AVR_POWER = 181; // 0xb5 field public static final int KEYCODE_B = 30; // 0x1ediff --git a/api/system-current.txt b/api/system-current.txtindex 19135aa..956ea3e 100644--- a/api/system-current.txt+++ b/api/system-current.txt@@ -44781,6 +44781,7 @@ package android.view { field public static final int KEYCODE_ASSIST = 219; // 0xdb field public static final int KEYCODE_AT = 77; // 0x4d field public static final int KEYCODE_AUDIO = 314; // 0x13a+ field public static final int KEYCODE_WEIQIFA = 315; // 0x13b field public static final int KEYCODE_AVR_INPUT = 182; // 0xb6 field public static final int KEYCODE_AVR_POWER = 181; // 0xb5 field public static final int KEYCODE_B = 30; // 0x1ediff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.javaindex 056f2c9..f2d5235 100755--- a/core/java/android/view/KeyEvent.java+++ b/core/java/android/view/KeyEvent.java@@ -832,6 +832,7 @@ public class KeyEvent extends InputEvent implements Parcelable { public static final int KEYCODE_TV_MEDIA_PAUSE = 304; public static final int KEYCODE_WLAN = 313; public static final int KEYCODE_AUDIO = 314;+ public static final int KEYCODE_WEIQIFA = 315; //$_rbox_$_modify_$ end private static final int LAST_KEYCODE = KEYCODE_TV_MEDIA_PAUSE;diff --git a/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.javaindex e6635a1..366790c 100755--- a/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java+++ b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java@@ -141,7 +141,12 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler { } case KeyEvent.KEYCODE_AUDIO: { Log.i(TAG, "---KEYCODE_AUDIO DOWN---");+ }+ case KeyEvent.KEYCODE_WEIQIFA: {+ Log.i(TAG,"KEYCODE_WEIQIFA");+ }+ case KeyEvent.KEYCODE_CAMERA: { if (getKeyguardManager().inKeyguardRestrictedInputMode() || dispatcher == null) {diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xmlindex 93743df..094e6c2 100755--- a/core/res/res/values/attrs.xml+++ b/core/res/res/values/attrs.xml@@ -1861,6 +1861,7 @@ i <enum name="KEYCODE_MICMUTE" value="312" /> <enum name="KEYCODE_WLAN" value="313" /> <enum name="KEYCODE_AUDIO" value="314" />+ <enum name="KEYCODE_WEIQIFA" value="315" /> diff --git a/include/android/keycodes.h b/include/android/keycodes.hindex e3586b2..b657424 100755--- a/include/android/keycodes.h+++ b/include/android/keycodes.h@@ -777,6 +777,7 @@ enum { AKEYCODE_MICMUTE = 312, AKEYCODE_WLAN = 313, AKEYCODE_AUDIO = 314+ AKEYCODE_WEIQIFA = 315 // NOTE: If you add a new keycode here you must also add it to several other files. // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.hindex fabf912..1cd69a2 100755--- a/include/input/InputEventLabels.h+++ b/include/input/InputEventLabels.h@@ -68,6 +68,7 @@ static const InputEventLabel KEYCODES[] = { DEFINE_KEYCODE(POWER), DEFINE_KEYCODE(WLAN), DEFINE_KEYCODE(AUDIO),+ DEFINE_KEYCODE(WEIQIFA), DEFINE_KEYCODE(CAMERA), DEFINE_KEYCODE(CLEAR), DEFINE_KEYCODE(A),
如果出现以下编译错误
out/target/common/obj/PACKAGING/test-api.txt:41961: error 5: Added public field android.view.KeyEvent.KEYCODE_WEIQIFA******************************You have tried to change the API from what has been previously approved.To make these errors go away, you have two choices: 1) You can add "@hide" javadoc comments to the methods, etc. listed in the errors above. 2) You can update current.txt by executing the following command: make update-api To submit the revised current.txt to the main Android repository, you will need approval.******************************
提示你运行make update-api,但是要先回退current.txt 和system-current.txt,因为这两个文件就是make update-api生成出来的
git checkout api/current.txt git checkout api/system-current.txtmake update-api
关于make update-api详细看这个https://blog.csdn.net/u010229714/article/details/73840014
如果需要调试,可以打开下面的调试文件
--- a/services/core/java/com/android/server/input/InputManagerService.java+++ b/services/core/java/com/android/server/input/InputManagerService.java@@ -125,7 +125,7 @@ import libcore.util.Objects; public class InputManagerService extends IInputManager.Stub implements Watchdog.Monitor { static final String TAG = "InputManager";- static final boolean DEBUG = false;+ static final boolean DEBUG = true; private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java@@ -172,7 +172,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final String TAG = "WindowManager"; static final boolean DEBUG = false; static final boolean localLOGV = false;- static final boolean DEBUG_INPUT = false;+ static final boolean DEBUG_INPUT = true; static final boolean DEBUG_KEYGUARD = false; static final boolean DEBUG_LAYOUT = false; static final boolean DEBUG_STARTING_WINDOW = false;--- a/services/inputflinger/InputDispatcher.cpp+++ b/services/inputflinger/InputDispatcher.cpp@@ -17,31 +17,31 @@ #define LOG_TAG "InputDispatcher" #define ATRACE_TAG ATRACE_TAG_INPUT-//#define LOG_NDEBUG 0+#define LOG_NDEBUG 1 // Log detailed debug messages about each inbound event notification to the dispatcher.-#define DEBUG_INBOUND_EVENT_DETAILS 0+#define DEBUG_INBOUND_EVENT_DETAILS 1 // Log detailed debug messages about each outbound event processed by the dispatcher.-#define DEBUG_OUTBOUND_EVENT_DETAILS 0+#define DEBUG_OUTBOUND_EVENT_DETAILS 1 // Log debug messages about the dispatch cycle.-#define DEBUG_DISPATCH_CYCLE 0+#define DEBUG_DISPATCH_CYCLE 1 // Log debug messages about registrations.-#define DEBUG_REGISTRATION 0+#define DEBUG_REGISTRATION 1 // Log debug messages about input event injection.-#define DEBUG_INJECTION 0+#define DEBUG_INJECTION 1 // Log debug messages about input focus tracking.-#define DEBUG_FOCUS 0+#define DEBUG_FOCUS 1 // Log debug messages about the app switch latency optimization.-#define DEBUG_APP_SWITCH 0+#define DEBUG_APP_SWITCH 1 // Log debug messages about hover events.-#define DEBUG_HOVER 0+#define DEBUG_HOVER 1 #include "InputDispatcher.h"diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cppindex c8dc454..3a622fc 100644--- a/services/inputflinger/InputReader.cpp+++ b/services/inputflinger/InputReader.cpp@@ -16,10 +16,10 @@ #define LOG_TAG "InputReader"-//#define LOG_NDEBUG 0+#define LOG_NDEBUG 1 // Log debug messages for each raw event received from the EventHub.-#define DEBUG_RAW_EVENTS 0+#define DEBUG_RAW_EVENTS 1 // Log debug messages about touch screen filtering hacks. #define DEBUG_HACKS 0diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cppindex 2dff4e0..977aa22 100644--- a/libs/input/InputTransport.cpp+++ b/libs/input/InputTransport.cpp@@ -5,19 +5,19 @@ // #define LOG_TAG "InputTransport"-//#define LOG_NDEBUG 0+#define LOG_NDEBUG 1 // Log debug messages about channel messages (send message, receive message)-#define DEBUG_CHANNEL_MESSAGES 0+#define DEBUG_CHANNEL_MESSAGES 1 // Log debug messages whenever InputChannel objects are created/destroyed-#define DEBUG_CHANNEL_LIFECYCLE 0+#define DEBUG_CHANNEL_LIFECYCLE 1 // Log debug messages about transport actions-#define DEBUG_TRANSPORT_ACTIONS 0+#define DEBUG_TRANSPORT_ACTIONS 1 // Log debug messages about touch event resampling-#define DEBUG_RESAMPLING 0+#define DEBUG_RESAMPLING 1
7 App接收键值
主要参照这个链接来写
https://www.cnblogs.com/zhujiabin/p/5915802.html
例程Android studio源码
链接:https://pan.baidu.com/s/1hzhQ-dLSRnAbg2Q8w5qKPw 密码:944g
@Override public boolean dispatchKeyEvent(KeyEvent event) { if(event.getKeyCode() == KeyEvent.KEYCODE_ENTER){ /*隐藏软键盘*/ InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); if(inputMethodManager.isActive()){ inputMethodManager.hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), 0); } edittext.setText("success"); webview.loadUrl(URL); return true; } return super.dispatchKeyEvent(event); }
8 命令调试
8.1 测试上报时间
触发Input上报的时间点
rk3399_mid:/ $ logcat -s "CAE_LOG"|grep -E CAEIvwCb09-06 14:10:13.502 327 436 D CAE_LOG : CAEIvwCb angle = 23 ,beam = 0 CMScore = 1643
APK接收到键值的时间点
09-06 14:10:13.518 5693-5693/com.hu.audiotest D/audiotest_MainActivity: KeyEvent.KEYCODE_ENTER KeyCode009-06 14:10:13.522 5693-5693/com.hu.audiotest D/audiotest_MainActivity: KeyEvent.KEYCODE_ENTER KeyCode0
消耗的时间大概需要16MS,但是触发是通过HAL层触发的,如果从Kerne触发事间会更短一些
8.2 设备文件调试
我们kernel下面正常用 getevent 来调试
getevent -l
cat /proc/bus/input/devices
rk3399_mid:/ # getevent -ladd device 1: /dev/input/event2 name: "rk29-keypad"add device 2: /dev/input/event1 name: "as9102 Touchscreen"add device 3: /dev/input/event0 name: "iflytek"/dev/input/event0: EV_KEY 00f9 DOWN/dev/input/event0: EV_SYN SYN_REPORT 00000000/dev/input/event0: EV_KEY 00f9 UP/dev/input/event0: EV_SYN SYN_REPORT 00000000
8.3 adb 上报键值调试
我们正常用adb shell input keyevent xx xx代表键值
可以用input来触发touchscreen也是可以的
有个比较好的文章
https://blog.csdn.net/jlminghui/article/details/39268419
大部分支持的键值如下
0 --> "KEYCODE_UNKNOWN"1 --> "KEYCODE_MENU"2 --> "KEYCODE_SOFT_RIGHT"3 --> "KEYCODE_HOME"4 --> "KEYCODE_BACK"5 --> "KEYCODE_CALL"6 --> "KEYCODE_ENDCALL"7 --> "KEYCODE_0"8 --> "KEYCODE_1"9 --> "KEYCODE_2"10 --> "KEYCODE_3"11 --> "KEYCODE_4"12 --> "KEYCODE_5"13 --> "KEYCODE_6"14 --> "KEYCODE_7"15 --> "KEYCODE_8"16 --> "KEYCODE_9"17 --> "KEYCODE_STAR"18 --> "KEYCODE_POUND"19 --> "KEYCODE_DPAD_UP"20 --> "KEYCODE_DPAD_DOWN"21 --> "KEYCODE_DPAD_LEFT"22 --> "KEYCODE_DPAD_RIGHT"23 --> "KEYCODE_DPAD_CENTER"24 --> "KEYCODE_VOLUME_UP"25 --> "KEYCODE_VOLUME_DOWN"26 --> "KEYCODE_POWER"27 --> "KEYCODE_CAMERA"28 --> "KEYCODE_CLEAR"29 --> "KEYCODE_A"30 --> "KEYCODE_B"31 --> "KEYCODE_C"32 --> "KEYCODE_D"33 --> "KEYCODE_E"34 --> "KEYCODE_F"35 --> "KEYCODE_G"36 --> "KEYCODE_H"37 --> "KEYCODE_I"38 --> "KEYCODE_J"39 --> "KEYCODE_K"40 --> "KEYCODE_L"41 --> "KEYCODE_M"42 --> "KEYCODE_N"43 --> "KEYCODE_O"44 --> "KEYCODE_P"45 --> "KEYCODE_Q"46 --> "KEYCODE_R"47 --> "KEYCODE_S"48 --> "KEYCODE_T"49 --> "KEYCODE_U"50 --> "KEYCODE_V"51 --> "KEYCODE_W"52 --> "KEYCODE_X"53 --> "KEYCODE_Y"54 --> "KEYCODE_Z"55 --> "KEYCODE_COMMA"56 --> "KEYCODE_PERIOD"57 --> "KEYCODE_ALT_LEFT"58 --> "KEYCODE_ALT_RIGHT"59 --> "KEYCODE_SHIFT_LEFT"60 --> "KEYCODE_SHIFT_RIGHT"61 --> "KEYCODE_TAB"62 --> "KEYCODE_SPACE"63 --> "KEYCODE_SYM"64 --> "KEYCODE_EXPLORER"65 --> "KEYCODE_ENVELOPE"66 --> "KEYCODE_ENTER"67 --> "KEYCODE_DEL"68 --> "KEYCODE_GRAVE"69 --> "KEYCODE_MINUS"70 --> "KEYCODE_EQUALS"71 --> "KEYCODE_LEFT_BRACKET"72 --> "KEYCODE_RIGHT_BRACKET"73 --> "KEYCODE_BACKSLASH"74 --> "KEYCODE_SEMICOLON"75 --> "KEYCODE_APOSTROPHE"76 --> "KEYCODE_SLASH"77 --> "KEYCODE_AT"78 --> "KEYCODE_NUM"79 --> "KEYCODE_HEADSETHOOK"80 --> "KEYCODE_FOCUS"81 --> "KEYCODE_PLUS"82 --> "KEYCODE_MENU"83 --> "KEYCODE_NOTIFICATION"84 --> "KEYCODE_SEARCH"85 --> "TAG_LAST_KEYCODE"
更多相关文章
- NPM 和webpack 的基础使用
- 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
- Android彩信存储
- Android(安卓)boot.img介绍
- Android开源项目解析:PullToRefresh
- Android应用程序中应用图标和名字的设置
- Android(安卓)上移植 ghostscript-9.04 静态编译
- Android(安卓)SDK Manager:Failed to fetch URL http://dl-ssl.go
- Android平台软件体系浅注