系统环境

博主已在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上多进程中使用webview的问题
  2. Android系统编译系统分析大全(二)
  3. 在 Android 系统源码中自定义系统服务(Custom System Service in
  4. Android app中调用启动其他应用(系统应用和第三方应用)2016.10.25
  5. Android 获取系统音量
  6. ubuntu系统下,搭建Android开发环境!!

随机推荐

  1. IT牛人进阶的必经之路
  2. Java项目发布之基础知识准备
  3. Linux Centos7安装 jdk
  4. Mongodb笔记之(Java中操作Mongodb)
  5. Oracle建立表空间和用户
  6. spring cloud准备linux常用命令
  7. CDH5 完美手动配置过程改进版
  8. 同样是爬天气,凭什么他能撩到妹?!
  9. position和float属性详解
  10. Hadoop学习笔记之Hadoop伪分布式环境搭建