系统环境
博主已在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.java
index 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.xml
index 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.h
index 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.h
index 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.java
index 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.kl
index 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.h
index 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_defconfig
index 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/Kco