系统环境

博主已在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,谢谢。

更多相关文章

  1. Android事件处理
  2. [Android]aidl命令
  3. Android——类型转换 时间处理
  4. 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
  5. 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
  6. Android3.0自带天气例子
  7. Android(安卓)Display System
  8. android 编译过程及错误处理
  9. android 从matrix获取处理过的图片的实际宽度

随机推荐

  1. Android xmlns 的作用及其自定义
  2. Android Handler机制1之Thread
  3. 对于android中自定义组件属性的理解
  4. 知识梳理之Android进程
  5. 我的Android心得(7)--TabActivity
  6. 让android支持RTSP(live555分析)
  7. android进阶
  8. android之4.0的系统主题style修改android
  9. android:gravity
  10. Android渗透测试虚拟机环境(VM)—AppUse