Android(安卓)Input系统添加自定义键值上报实现(from Linux to Android)
系统环境
博主已在Android 7.0上验证成功,其他后6.0,8.0,9.0应该改动不大,可以直接拿过来使用,底层基本不变,上层Android可能会有些接口调整,不过万变不离其中,也是可以参考的。
Demo原理
博主实现的Demo主要是通过外部串口来发送音量调整数据,给到Android,Android端的serial_comm进程会不断处理串口接收到的信息,然后再通过驱动进行InputEvent上报,触发PhoneWindowManager对上报的自定义按键进行处理,从而调整音量数据。这样处理通过InputEvent上报处理比较及时迅速。
Android系统层
Android上层需要修改这些文件,我直接diff出来了,其中我们新增的键值要注意不要跟系统的重复:KEYCODE_SPECIFIC_VOLUME = 280
diff --git a/android/frameworks/base/core/java/android/view/KeyEvent.java b/android/frameworks/base/core/java/android/view/KeyEvent.javaindex b003f00..fabce16 100755--- a/android/frameworks/base/core/java/android/view/KeyEvent.java+++ b/android/frameworks/base/core/java/android/view/KeyEvent.java@@ -809,6 +809,9 @@ public class KeyEvent extends InputEvent implements Parcelable { public static final int KEYCODE_COPY = 278; /** Key code constant: Paste key. */ public static final int KEYCODE_PASTE = 279;++ public static final int KEYCODE_SPECIFIC_VOLUME = 280;+ /** Key code constant: a shortcut key for mouse */ public static final int KEYCODE_MOUSE = 10009; public static final int KEYCODE_TV_SYSTEM = 10000;diff --git a/android/frameworks/base/core/res/res/values/attrs.xml b/android/frameworks/base/core/res/res/values/attrs.xmlindex b61d6cf..4330802 100644--- a/android/frameworks/base/core/res/res/values/attrs.xml+++ b/android/frameworks/base/core/res/res/values/attrs.xml@@ -1832,6 +1832,7 @@ i <enum name="KEYCODE_CUT" value="277" /> <enum name="KEYCODE_COPY" value="278" /> <enum name="KEYCODE_PASTE" value="279" />+ <enum name="KEYCODE_SPECIFIC_VOLUME" value="280" /> </attr> <!-- ***************************************************************** -->diff --git a/android/frameworks/native/include/android/keycodes.h b/android/frameworks/native/include/android/keycodes.hindex 4687b85..9fd76d5 100755--- a/android/frameworks/native/include/android/keycodes.h+++ b/android/frameworks/native/include/android/keycodes.h@@ -758,6 +758,9 @@ enum { AKEYCODE_COPY = 278, /** Paste key. */ AKEYCODE_PASTE = 279,++ AKEYCODE_SPECIFIC_VOLUME = 280,+ // add for karaok by linjunqian AKEYCODE_MIC_VOLUME_UP = 370, AKEYCODE_MIC_VOLUME_DOWN = 371,diff --git a/android/frameworks/native/include/input/InputEventLabels.h b/android/frameworks/native/include/input/InputEventLabels.hindex 911c568..78ed509 100755--- a/android/frameworks/native/include/input/InputEventLabels.h+++ b/android/frameworks/native/include/input/InputEventLabels.h@@ -319,6 +319,7 @@ static const InputEventLabel KEYCODES[] = { DEFINE_KEYCODE(CUT), DEFINE_KEYCODE(COPY), DEFINE_KEYCODE(PASTE),+ DEFINE_KEYCODE(SPECIFIC_VOLUME), DEFINE_KEYCODE(MIC_VOLUME_UP), DEFINE_KEYCODE(MIC_VOLUME_DOWN), DEFINE_KEYCODE(KOUT_VOLUME_UP),diff --git a/android/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java b/android/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.javaindex a4408fc..fbcd7e0 100644--- a/android/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java+++ b/android/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java@@ -5530,6 +5530,20 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; } + case KeyEvent.KEYCODE_SPECIFIC_VOLUME: {+ if (down) {+ Log.d(TAG, "KeyEvent.KEYCODE_SPECIFIC_VOLUME down");+ AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);+ audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,+ Integer.parseInt(SystemProperties.get("persist.sys.specific_volume")),+ AudioManager.FLAG_SHOW_UI);+ Log.d(TAG, "setStreamVolume " + SystemProperties.get("persist.sys.specific_volume"));+ } else {+ Log.d(TAG, "KeyEvent.KEYCODE_SPECIFIC_VOLUME up");+ }+ break;+ }+ case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_MUTE: {
到这里我们已经把上层的键值配好了,可以make systemimage -j8,烧进去进行测试,利用input keyevent 280,看看修改是否成功。
中间转换(Android - Linux)
Android自己定义了一套键值,Linux上报的键值需要通过kl文件转换才能正常识别。
diff --git a/android/frameworks/base/data/keyboards/Generic.kl b/android/frameworks/base/data/keyboards/Generic.klindex 2a10bdd..ed9e1bd 100644--- a/android/frameworks/base/data/keyboards/Generic.kl+++ b/android/frameworks/base/data/keyboards/Generic.kl@@ -247,6 +247,8 @@ key 224 BRIGHTNESS_DOWN key 225 BRIGHTNESS_UP key 226 HEADSETHOOK +key 249 SPECIFIC_VOLUME+ key 256 BUTTON_1 key 257 BUTTON_2 key 258 BUTTON_3
Linux底层
从下面可以看到,我们再Linux层定义的键值为#define KEY_SPECIFIC_VOLUME 249,这里我写了个虚拟按键的驱动程序,echo 1 > /sys/kernel/virtual_key,在往virtual_key节点写1的时候就会上报KEY_SPECIFIC_VOLUME键,从而通知Android上层进行处理。
diff --git a/lichee/linux-3.10/include/uapi/linux/input.h b/lichee/linux-3.10/include/uapi/linux/input.hindex 74b5a00..5413c97 100644--- a/lichee/linux-3.10/include/uapi/linux/input.h+++ b/lichee/linux-3.10/include/uapi/linux/input.h@@ -473,6 +473,8 @@ struct input_keymap_entry { #define KEY_MICMUTE 248 /* Mute / unmute the microphone */ +#define KEY_SPECIFIC_VOLUME 249+ #define KEY_VOICE_ASSIST 582 /* Code 255 is reserved for special needs of AT keyboard driver */diff --git a/lichee/linux-3.10/arch/arm64/configs/sun50iw6p1smp_android_7.x_defconfig b/lichee/linux-3.10/arch/arm64/configs/sun50iw6p1smp_android_7.x_defconfigindex 6d0ccaa..cc15e9a 100644--- a/lichee/linux-3.10/arch/arm64/configs/sun50iw6p1smp_android_7.x_defconfig+++ b/lichee/linux-3.10/arch/arm64/configs/sun50iw6p1smp_android_7.x_defconfig@@ -1287,6 +1287,7 @@ CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYRESET=y CONFIG_INPUT_KEYCOMBO=y # CONFIG_INPUT_POWERKEY is not set+CONFIG_INPUT_VIRTUALKEY=y CONFIG_INPUT_SW_DEVICE=m #diff --git a/lichee/linux-3.10/drivers/input/Kconfig b/lichee/linux-3.10/drivers/input/Kconfigindex 77a12a9..9c6f668 100755--- a/lichee/linux-3.10/drivers/input/Kconfig+++ b/lichee/linux-3.10/drivers/input/Kconfig@@ -205,6 +205,16 @@ config INPUT_POWERKEY To compile this driver as a module,choose M here: the module will be called sunxi-gpiokey. +config INPUT_VIRTUALKEY+ tristate "virtual key"+ depends on INPUT+ default n+ ---help---+ Say Y here if you want to support go virtual_key;++ To compile this driver as a module,choose M here: the+ module will be called virtual-key.+ config INPUT_SW_DEVICE tristate "i2c device detect support" depends on INPUT && I2Cdiff --git a/lichee/linux-3.10/drivers/input/Makefile b/lichee/linux-3.10/drivers/input/Makefileindex a7203f0..a66231a 100755--- a/lichee/linux-3.10/drivers/input/Makefile+++ b/lichee/linux-3.10/drivers/input/Makefile@@ -18,6 +18,8 @@ obj-$(CONFIG_INPUT_EVDEV) += evdev.o obj-$(CONFIG_INPUT_EVBUG) += evbug.o obj-$(CONFIG_INPUT_POWERKEY) += sunxi-gpiokey.o+obj-$(CONFIG_INPUT_VIRTUALKEY) += virtual-key.o+obj-$(CONFIG_INPUT_VIRTUALKEY) += virtual-key-dev.o obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/ obj-$(CONFIG_INPUT_MOUSE) += mouse/diff --git a/lichee/linux-3.10/drivers/input/virtual-key-dev.c b/lichee/linux-3.10/drivers/input/virtual-key-dev.cnew file mode 100644index 0000000..60c8038--- /dev/null+++ b/lichee/linux-3.10/drivers/input/virtual-key-dev.c@@ -0,0 +1,34 @@+#include +#include +#include +#include ++static struct platform_device virtual_key_dev = {+ .name = "virtual_key",+ .id = -1,+};++static int __init virtual_key_dev_init(void)+{+ printk("%s-%d: enter\n", __FUNCTION__, __LINE__);+ if (platform_device_register(&virtual_key_dev)) {+ pr_err("virtual_key virtual_key_dev_init fail\n");+ return -1;+ }++ return 0;+}++static void __exit virtual_key_dev_exit(void)+{+ platform_device_unregister(&virtual_key_dev);+}++module_init(virtual_key_dev_init);+module_exit(virtual_key_dev_exit);++MODULE_AUTHOR("sweetmilkcake " );+MODULE_DESCRIPTION("virtual key dev");+MODULE_LICENSE("GPL");++diff --git a/lichee/linux-3.10/drivers/input/virtual-key.c b/lichee/linux-3.10/drivers/input/virtual-key.cnew file mode 100644index 0000000..0b951d2--- /dev/null+++ b/lichee/linux-3.10/drivers/input/virtual-key.c@@ -0,0 +1,151 @@+#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include ++static volatile u32 virtual_key_trigger;+static struct mutex virtual_key_mutex;+static struct input_dev *virtual_key_dev;++static ssize_t virtual_key_show(struct kobject *kobj,+ struct kobj_attribute *attr,+ char *buf)+{+ return sprintf(buf, "%d\n", virtual_key_trigger);+}++static ssize_t virtual_key_store(struct kobject *kobj,+ struct kobj_attribute *attr,+ const char *buf, size_t count)+{+ int ret = 0;++ mutex_lock(&virtual_key_mutex);++ switch (buf[0]) {+ case '0':+ virtual_key_trigger = 0;+ break;+ case '1':+ virtual_key_trigger = 1;+ input_report_key(virtual_key_dev, KEY_SPECIFIC_VOLUME, 1);+ input_sync(virtual_key_dev);+ input_report_key(virtual_key_dev, KEY_SPECIFIC_VOLUME, 0);+ input_sync(virtual_key_dev);+ break;+ default:+ ret = -EINVAL;+ break;+ }++ mutex_unlock(&virtual_key_mutex);+ return ret < 0 ? ret : count;+}++static struct kobj_attribute virtual_key_attr = __ATTR(virtual_key,+ 0666, virtual_key_show,+ virtual_key_store);++static int virtual_key_probe(struct platform_device *pdev)+{+ int err = 0;++ printk("%s-%d: enter\n", __FUNCTION__, __LINE__);++ virtual_key_dev = input_allocate_device();+ if (!virtual_key_dev) {+ pr_err("virtual_key: not enough memory for input device\n");+ err = -ENOMEM;+ goto fail1;+ }++ virtual_key_dev->name = "virtual_key";+ //virtual_key_dev->phys = "sunxikbd/input0";+ virtual_key_dev->id.bustype = BUS_HOST;+ virtual_key_dev->id.vendor = 0x0001;+ virtual_key_dev->id.product = 0x0001;+ virtual_key_dev->id.version = 0x0100;++#ifdef REPORT_REPEAT_KEY_BY_INPUT_CORE+ virtual_key_dev->evbit[0] = BIT_MASK(EV_KEY)|BIT_MASK(EV_REP);+ printk(KERN_DEBUG "REPORT_REPEAT_KEY_BY_INPUT_CORE is defined, support report repeat key value. \n");+#else+ virtual_key_dev->evbit[0] = BIT_MASK(EV_KEY);+#endif+ set_bit(KEY_SPECIFIC_VOLUME, virtual_key_dev->keybit);+ mutex_init(&virtual_key_mutex);++ err = input_register_device(virtual_key_dev);+ if (err)+ goto fail2;++ err = sysfs_create_file(kernel_kobj, &virtual_key_attr.attr);+ if (err) {+ printk(KERN_ERR "virtual_key: unable to create sysfs file"+ " virtual_key (%d)\n", err);+ goto fail3;+ }++ return 0;++fail3:+ input_unregister_device(virtual_key_dev);+fail2:+ input_free_device(virtual_key_dev);+fail1:+ printk(KERN_DEBUG "virtual_key_init failed. \n");++ return err;+}++static int virtual_key_remove(struct platform_device *dev)+{++ input_unregister_device(virtual_key_dev);++ return 0;+}++static struct platform_driver virtual_key_driver = {+ .probe = virtual_key_probe,+ .remove = virtual_key_remove,+ .driver = {+ .name = "virtual_key",+ .owner = THIS_MODULE,+ },+};++static int __init virtual_key_init(void)+{+ printk("%s-%d: enter\n", __FUNCTION__, __LINE__);+ if (platform_driver_register(&virtual_key_driver)) {+ pr_err("virtual_key platform_driver_register fail\n");+ return -1;+ }++ return 0;+}++static void __exit virtual_key_exit(void)+{+ platform_driver_unregister(&virtual_key_driver);+}++module_init(virtual_key_init);+module_exit(virtual_key_exit);++MODULE_AUTHOR("sweetmilkcake " );+MODULE_DESCRIPTION("virtual key driver");+MODULE_LICENSE("GPL");++
serial_comm程序
这个程序其实在另一篇文章已经介绍过,这里我把它放到system/core目录,打包到系统中,注意要在device.mk里面定义,不然全编的时候是不会编到系统的。
diff --git a/android/device/softwinner/petrel-p1/device.mk b/android/device/softwinner/petrel-p1/device.mkindex 6cb1831..9696939 100755--- a/android/device/softwinner/petrel-p1/device.mk+++ b/android/device/softwinner/petrel-p1/device.mk@@ -60,6 +60,8 @@ PRODUCT_PACKAGES += \ libip_loader \ iploader_server +PRODUCT_PACKAGES += serial_comm+ PRODUCT_COPY_FILES += \ device/softwinner/petrel-p1/configs/virtual-remote.kl:system/usr/keylayout/virtual-remote.kl \ device/softwinner/petrel-p1/configs/sunxi-keyboard.kl:system/usr/keylayout/sunxi-keyboard.kl \diff --git a/android/system/core/serial_comm/Android.mk b/android/system/core/serial_comm/Android.mknew file mode 100644index 0000000..d7ee151--- /dev/null+++ b/android/system/core/serial_comm/Android.mk@@ -0,0 +1,9 @@+LOCAL_PATH := $(call my-dir)++include $(CLEAR_VARS)+LOCAL_MODULE := serial_comm+LOCAL_SRC_FILES := serial_comm.c+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter+LOCAL_SHARED_LIBRARIES := \+ libcutils+include $(BUILD_EXECUTABLE)diff --git a/android/system/core/serial_comm/serial_comm.c b/android/system/core/serial_comm/serial_comm.cnew file mode 100644index 0000000..f40526f--- /dev/null+++ b/android/system/core/serial_comm/serial_comm.c@@ -0,0 +1,212 @@+#include +#include +#include +#include +#include +#include +#include +#include +#include +#include ++#include ++#include ++// dev control date end+// 02 01 12 7F+#define SERIAL_REC_NUM 4+// VTIME and VMIN is very important.+// VTIME: Time to wait for data (tenths of seconds)+#define SERIAL_VTIME 1+// VMIN: Minimum number of characters to read+#define SERIAL_VMIN SERIAL_REC_NUM++int serial_set(int fd, int speed, int bits, int event, int stop) {+ struct termios ttys;++ memset(&ttys, 0, sizeof(ttys));++ // Enable the receiver and set local mode+ // CLOCAL: Local line - do not change "owner" of port+ // CREAD: Enable receiver+ ttys.c_cflag |= (CLOCAL | CREAD);++ // Mask the character size bits+ // CSIZE: Bit mask for data bits+ ttys.c_cflag &= ~CSIZE;++ switch (speed) {+ case 9600:+ // B9600: 9600 baud+ cfsetispeed(&ttys, B9600);+ cfsetospeed(&ttys, B9600);+ break;+ case 115200:+ // B115200: 115,200 baud+ cfsetispeed(&ttys, B115200);+ cfsetospeed(&ttys, B115200);+ break;+ default:+ cfsetispeed(&ttys, B115200);+ cfsetospeed(&ttys, B115200);+ break;+ }++ switch (bits) {+ case 7:+ // 7 data bits+ ttys.c_cflag |= CS7;+ break;+ case 8:+ // 8 data bits+ ttys.c_cflag |= CS8;+ break;+ default:+ ttys.c_cflag |= CS8;+ break;+ }++ switch (event) {+ case 'o':+ case 'O':+ // PARENB: Enable parity bit+ ttys.c_cflag |= PARENB;+ // INPCK: Enable parity check+ // ISTRIP: Strip parity bits+ ttys.c_cflag |= (INPCK | ISTRIP);+ // PARODD: Use odd parity instead of even+ ttys.c_cflag |= PARODD;+ break;+ case 'e':+ case 'E':+ ttys.c_cflag |= PARENB;+ ttys.c_cflag |= (INPCK | ISTRIP);+ ttys.c_cflag &= ~PARODD;+ break;+ case 'n':+ case 'N':+ ttys.c_cflag &= ~PARENB;+ break;+ default:+ ttys.c_cflag &= ~PARENB;+ break;+ }++ switch (stop) {+ case 1:+ // CSTOPB: 2 stop bits (1 otherwise)+ ttys.c_cflag &= ~CSTOPB;+ break;+ case 2:+ ttys.c_cflag |= CSTOPB;+ break;+ default:+ ttys.c_cflag &= ~CSTOPB;+ break;+ }++ // VTIME: Time to wait for data (tenths of seconds)+ ttys.c_cc[VTIME] = SERIAL_VTIME;+ // VMIN: Minimum number of characters to read+ ttys.c_cc[VMIN] = SERIAL_VMIN;++ // Hardware flow control using the CTS (Clear To Send) and RTS (Request To Send) signal lines+ // CNEW_RTSCTS, CRTSCTS: Enable hardware flow control (not supported on all platforms)+ // CNEW_RTSCTS: Also called CRTSCTS+ //ttys.c_cflag |= CRTSCTS; // Enable hardware flow control+ ttys.c_cflag &= ~CRTSCTS; // Disable hardware flow control++ // Choosing Canonical Input+ // Canonical input is line-oriented. Input characters are put into a buffer+ // which can be edited interactively by the user until a CR (carriage return)+ // or LF (line feed) character is received.+ // When selecting this mode you normally select the ICANON, ECHO, and ECHOE options+ //ttys.c_lflag |= (ICANON | ECHO | ECHOE);++ // Choosing Raw Input+ // Raw input is unprocessed. Input characters are passed through exactly as they are received,+ // when they are received. Generally you'll deselect the ICANON, ECHO, ECHOE, and ISIG options when using raw input+ ttys.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);++ // OPOST: Postprocess output (not set = raw output)+ //ttys.c_oflag |= OPOST; // Choosing Processed Output+ ttys.c_oflag &= ~OPOST; // Choosing Raw Output+++ // Flushes the input and/or output queue.+ // TCIFLUSH: flushes data received but not read.+ // TCOFLUSH: flushes data written but not transmitted.+ // TCIOFLUSH: flushes both data received but not read, and data written but not transmitted.+ tcflush(fd, TCIOFLUSH);++ // Sets the serial port settings immediately.+ // TCSANOW: Make changes now without waiting for data to complete+ // TCSADRAIN: Wait until everything has been transmitted+ // TCSAFLUSH: Flush input and output buffers and make the change+ if (tcsetattr(fd, TCSANOW, &ttys) != 0) {+ perror("serial set fail!\n");+ return -2;+ }++ return 0;+}++int is_data_valid(unsigned char *buf) {+ if (buf[3] != 0x7f) {+ fprintf(stderr, "%s, data is not valid!\n", __FUNCTION__);+ return -1;+ }+ return 0;+}++int main(int argc, char *argv[]) {+ int fd = 0;+ int ret = 0;+ int n = 0;+ unsigned char buf[SERIAL_REC_NUM];+ char str[10];++ printf("serial test start.\n");++ fd = open("/dev/ttyS3", O_RDWR | O_NOCTTY);+ if (fd < 0) {+ fprintf(stderr, "%s, open serial failed!\n", __FUNCTION__);+ return -1;+ }++ // Baud rate: 115200, Data bits: 8, Parity: None, Stop bits: 1+ ret = serial_set(fd, 115200, 8, 'N', 1);+ if (ret) {+ fprintf(stderr, "%s, serial set failed!\n", __FUNCTION__);+ return -1;+ }++ while (1) {+ memset(&buf, 0, sizeof(buf));+ // blocking here+ n = read(fd, &buf, SERIAL_REC_NUM);+ if (n < SERIAL_REC_NUM) {+ fprintf(stderr, "serial read fail!, n = %d\n", n);+ } else {+ printf("buf[0] = 0x%x, buf[1] = 0x%x, buf[2] = 0x%x, buf[3] = 0x%x, \n",+ buf[0], buf[1], buf[2], buf[3]);++ if (!is_data_valid(buf)) {+ // data is ok+ snprintf(str, 3, "%d", buf[2]);+ printf("property_set persist.sys.specific_volume = %s\n", str);+ property_set("persist.sys.specific_volume", str);+ }+ //n = write(fd, &buf, SERIAL_REC_NUM);+ //if (n < SERIAL_REC_NUM) {+ // fprintf(stderr, "serial write fail!, n = %d\n", n);+ //}+ }+ }++ close(fd);++ printf("serial test end.\n");+ return 0;+}
init进程触发逻辑
这里的逻辑是,当serial_comm进程收到串口消息会设置persist.sys.specific_volume属性,然后init进程会往/sys/kernel/virtual_key写1,然后驱动会上报键值,通知Android层,再到PhoneWindowManager进行处理。这里还要注意Selinux规则的报错,并且改了之后要全编system才可以,当时我也是调了好久。。。
petrel-p1:/ # dmesg | grep serial [ 0.000000] Kernel command line: earlyprintk=sunxi-uart,0x05000000 initcall_debug=0 console=ttyS0,115200 loglevel=1 root=/dev/mmcblk0p7 init=/init partitions=bootloader@mmcblk0p2:env@mmcblk0p5:boot@mmcblk0p6:system@mmcblk0p7:verity_block@mmcblk0p8:misc@mmcblk0p9:recovery@mmcblk0p10:sysrecovery@mmcblk0p11:private@mmcblk0p12:alog@mmcblk0p13:Reserve0@mmcblk0p14:Reserve1@mmcblk0p15:Reserve2@mmcblk0p16:cache@mmcblk0p17:UDISK@mmcblk0p1 cma=64M mac_addr=00:00:00:00:00:00 wifi_mac= bt_mac= selinux=1 specialstr= androidboot.selinux=permissive androidboot.serialno=dc000141091d6413078b boot_type=1 androidboot.hardware=sun50iw6p1[ 0.822916] usbcore: registered new interface driver usbserial[ 0.823153] usbserial: USB Serial support registered for GSM modem (1-port)[ 2.700573] usb_serial_number:20080411[ 6.362876] init: Service serial_comm does not have a SELinux domain defined.[ 7.376520] init: Service serial_comm does not have a SELinux domain defined.
diff --git a/android/device/softwinner/petrel-common/sepolicy/file_contexts b/android/device/softwinner/petrel-common/sepolicy/file_contextsindex 07a6984..5414c04 100755--- a/android/device/softwinner/petrel-common/sepolicy/file_contexts+++ b/android/device/softwinner/petrel-common/sepolicy/file_contexts@@ -65,3 +65,4 @@ # optee /dev/opteearmtz00 u:object_r:tee_device:s0 /system/bin/tee_supplicant u:object_r:optee_exec:s0+/system/bin/serial_comm u:object_r:serial_comm_exec:s0diff --git a/android/device/softwinner/petrel-common/sepolicy/serial_comm.te b/android/device/softwinner/petrel-common/sepolicy/serial_comm.tenew file mode 100644index 0000000..fc0caeb--- /dev/null+++ b/android/device/softwinner/petrel-common/sepolicy/serial_comm.te@@ -0,0 +1,5 @@+type serial_comm, domain;+type serial_comm_exec, exec_type, file_type;+init_daemon_domain(serial_comm);+allow serial_comm sysfs:file rw_file_perms;+diff --git a/android/device/softwinner/petrel-p1/init.sun50iw6p1.rc b/android/device/softwinner/petrel-p1/init.sun50iw6p1.rcindex 6d98d7a..7d99616 100755--- a/android/device/softwinner/petrel-p1/init.sun50iw6p1.rc+++ b/android/device/softwinner/petrel-p1/init.sun50iw6p1.rc@@ -113,6 +113,8 @@ on boot write /dev/cpuset/system-background/cpus 0-3 write /dev/cpuset/top-app/cpus 0-3 + start serial_comm+ on property:sys.shutdown.hdmi=1 write /sys/class/hdmi/hdmi/attr/hpd_mask 0x10 @@ -288,3 +290,12 @@ service stop_pppoe /system/bin/pppoe-disconnect service optee /system/bin/tee_supplicant class main oneshot++service serial_comm /system/bin/serial_comm+ class main+ user root+ disabled+ oneshot++on property:persist.sys.specific_volume=*+ write /sys/kernel/virtual_key 1
测试
通过串口发送数据,可以直接修改Android层的音量,大功告成。
完整补丁
补丁放在:https://github.com/sweetmilkcake/AndroidPatches/blob/master/virtual-key/virtual-key.diff
写文章不易,如对您有用,麻烦给个Star,谢谢。
更多相关文章
- Android事件处理
- [Android]aidl命令
- Android——类型转换 时间处理
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
- Android3.0自带天气例子
- Android(安卓)Display System
- android 编译过程及错误处理
- android 从matrix获取处理过的图片的实际宽度