步骤记录:基于Android 5.1添加硬按键

 

该按键值硬件(驱动)层已支持上报。

硬件(驱动)层到应用层的转化,这层可以理解为SCANCODE->KEYCODE的转化。

在代码中,打印Keyevent.toString,能看得到scanCode值,如果keyCode= UNKNOW值,便说明了硬件(驱动)层到应用层还没有完成。

KeyEvent { action=ACTION_UP, keyCode=KEYCODE_VOLUME_DOWN, scanCode=114, metaState=0, flags=0xc, repeatCount=0, eventTime=7488809, downTime=7488760, deviceId=3, source=0x701 }

对于scanCode的定议一般在framework/base/data/keyboards/Generic.kl

key 114   VOLUME_DOWN       WAKE_DROPPED
key 115   VOLUME_UP         WAKE_DROPPED

格式 key scanCode keyName ,最后这个貌似可加可不加(具体还有待验证,WAKE_DROPPED  是指设备睡眠时,按下此按键会唤醒设备,但是该key消息不会发送给应用,而WAKE 一样会唤醒设备且key消息会发送给应用)

转化时,会通过scanCode 找到keyCodeName,再通过keyCodeName 去转化成keyCode,而后面一层的定义在

frameworks/native/include/input/InputEventLabels.h

static const InputEventLabel KEYCODES[] = {
    // 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.
    DEFINE_KEYCODE(UNKNOWN),
    DEFINE_KEYCODE(SOFT_LEFT),
    DEFINE_KEYCODE(SOFT_RIGHT),
    DEFINE_KEYCODE(HOME),
    DEFINE_KEYCODE(BACK),
    ……
    DEFINE_KEYCODE(VOLUME_UP),
    DEFINE_KEYCODE(VOLUME_DOWN),
    ……
    { NULL, 0 }
};

在数组后面加上新的key。不在要中间添加,保待在队尾添加。

到了这里,后面的事情就很简单了,因为你会看到这边有个很好的提醒,提醒我们去KeyEvent.java添加新的key值

frameworks/base/core/java/android/view/KeyEvent.java

public static final int KEYCODE_VOLUME_DOWN     = 25;
public static final int KEYCODE_POWER           = 26;
……
private static final int LAST_KEYCODE = KEYCODE_HELP;

    // NOTE: If you add a new keycode here you must also add it to:
    //  isSystem()
    //  isWakeKey()
    //  frameworks/native/include/android/keycodes.h
    //  frameworks/native/include/input/InputEventLabels.h
    //  frameworks/base/core/res/res/values/attrs.xml
    //  emulator?
    //  LAST_KEYCODE

建议在队尾添keycode的定义,且递增,这个我们后面再说.

这边的NOTE也很好我帮我们把需要的修改都提到了。

因为我们是在队尾添加的,所以需要将LAST_KEYCODE指向最后的key。

接着是两个方法isSystem()和isWakeKey();

这两个是根据你的需求来解决是否添加,具体也待定。

InputEventLabels.h我们在上面已经修改过了。

frameworks/native/include/android/keycodes.h

/*
 * Key codes.
 */
enum {
    AKEYCODE_UNKNOWN         = 0,
    AKEYCODE_SOFT_LEFT       = 1,
    AKEYCODE_SOFT_RIGHT      = 2,
    ……
    AKEYCODE_VOLUME_UP       = 24,
    AKEYCODE_VOLUME_DOWN     = 25,
    ……
    // 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.
};

一样在队尾添加key的定义

frameworks/base/core/res/res/values/attrs.xml

 
        
        
        
        ……
        
        
        ……
 

到此,已基本完成了。

 

接着我们来说为什么key要在队尾加,且递增。这个并不是强制性要求,至少还没看到哪里有强制性的说明。如果跳着增加,如当前最大的key值为259,下一个我就定为300,400也可以,并没有什么异常。

其实也就是一个小小提示问题。

打印KeyEvent时,可以看到keyCode 已转成 keyName,我们更好辨认。而不是纯粹的数字。

KeyEvent { action=ACTION_UP, keyCode=KEYCODE_VOLUME_DOWN, scanCode=114, metaState=0, flags=0xc, repeatCount=0, eventTime=7488809, downTime=7488760, deviceId=3, source=0x701 }

 而小问题就出现在这里,如果你跳着增加,keyCode 就是直接的数字了,因为他找不到对应用keyName.

 @Override
    public String toString() {
        StringBuilder msg = new StringBuilder();
        msg.append("KeyEvent { action=").append(actionToString(mAction));
        msg.append(", keyCode=").append(keyCodeToString(mKeyCode));
        msg.append(", scanCode=").append(mScanCode);
        if (mCharacters != null) {
            msg.append(", characters=\"").append(mCharacters).append("\"");
        }
        msg.append(", metaState=").append(metaStateToString(mMetaState));
        msg.append(", flags=0x").append(Integer.toHexString(mFlags));
        msg.append(", repeatCount=").append(mRepeatCount);
        msg.append(", eventTime=").append(mEventTime);
        msg.append(", downTime=").append(mDownTime);
        msg.append(", deviceId=").append(mDeviceId);
        msg.append(", source=0x").append(Integer.toHexString(mSource));
        msg.append(" }");
        return msg.toString();
    }

keyCodeToString

 public static String keyCodeToString(int keyCode) {
        String symbolicName = nativeKeyCodeToString(keyCode);
        return symbolicName != null ? LABEL_PREFIX + symbolicName :       Integer.toString(keyCode);
    }

nativeKeyCodeToString找不到时,就会直接打印keyCode了。

这里的原理很简单,上面添加keyCode时,我们会发现都是数组这样的储存方式,也就是说keyCode相当于你的inde值,你将keyCode跳着写,那index自然找不到了,数组越界面。

看下代码

nativeKeyCodeToString的实现在framework/base/core/jni/android_view_KeyEvent.cpp

static jstring android_view_KeyEvent_nativeKeyCodeToString(JNIEnv* env, jobject clazz,
        jint keyCode) {
    return env->NewStringUTF(KeyEvent::getLabel(keyCode));
}

getLable方法在framework/native/libs/input/input.cpp

const char* KeyEvent::getLabel(int32_t keyCode) {
    return getLabelByKeyCode(keyCode);
}

最后来到frameworks/native/include/input/InputEventLabels.h

static const char* getLabelByKeyCode(int32_t keyCode) {
    if (keyCode >= 0 && keyCode < size(KEYCODES)) {
        return KEYCODES[keyCode].literal;
    }
    return NULL;
}

没错,这个就是我们刚才添加定义的数组。而keyCode相当于index。将keyCode跳着写,会导致keyCode无法转成相应用keyName。

问题不算大,但是也算多一点了解了系统。

 

你可能感兴趣的:(android,源码)