我们在做Android 系统开发时,可能由于硬件需要,需要加入一些定义功能按键,但是怎么去实现这些按键的功能呢? 下面就是博主的基于rk3288 板子的一些经验
1、实体按键
比如有一些实体按键可能要定义这个按键的功能。入华为V8 上的智灵按键。
在kernel 首先要实现这个按键的驱动,并且注册input 事件。
驱动可以按照硬件的接线,实现gpio 类型或者i2c 类型的驱动。这种实体按键一般是gpio 类型的驱动。
if (button->type == TYPE_GPIO) {
int irq;
error = devm_gpio_request(dev, button->gpio,
button->desc ? : "keys");
if (error < 0) {
pr_err("gpio-keys: failed to request GPIO %d, error %d\n",
button->gpio, error);
goto fail1;
}
error = gpio_direction_input(button->gpio);
if (error < 0) {
pr_err("gpio-keys: failed to configure input direction for GPIO %d, error %d\n",
button->gpio, error);
gpio_free(button->gpio);
goto fail1;
}
irq = gpio_to_irq(button->gpio);
if (irq < 0) {
error = irq;
pr_err("gpio-keys: Unable to get irq number for GPIO %d, error %d\n",
button->gpio, error);
gpio_free(button->gpio);
goto fail1;
}
button->state = !!((gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low);
if (button->state) {
__set_bit(SW_MUTE, input->sw);
}
error = devm_request_irq(dev, irq, keys_isr,
IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
button->desc ? button->desc : "switch",
button);
}
以上是注册gpio驱动和中断的过程,在驱动注册的过程中还需要注册input 事件,由于我的这个按键是要实现静音功能所以需要input_set_capability(input, EV_SW, SW_MUTE); 注册EV_SW 事件也就是swtich 事件。
error = input_register_device(input);
if (error) {
pr_err("gpio-keys: Unable to register input device, error: %d\n",
error);
goto fail0;
}
input_set_capability(input, EV_SW, SW_MUTE);
2、驱动注册完成之后,按键事件会被android 的input 系统接收,并被判断为swtich事件,传递到InputManagerService.中调用notifySwitch 接口,在接口中通过switchMask & SW_MUTE_BIT判断是否是自己的按键
private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
if (DEBUG) {
Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues)
+ ", mask=" + Integer.toHexString(switchMask));
}
if ((switchMask & SW_LID_BIT) != 0) {
final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
}
if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
switchMask);
}
if ((switchMask & SW_MUTE_BIT) != 0) {
final boolean isMute = ((switchValues & SW_MUTE_BIT) != 0);
mWindowManagerCallbacks.notifyMuteSwitchChanged(isMute);
}
}
mWindowManagerCallbacks 中的notifyMuteSwitchChanged接口实现在InputMonitor 中
@Override
public void notifyMuteSwitchChanged(boolean isMute) {
mService.mPolicy.notifyMuteSwitchChanged(isMute);
}
所以最终调用在PhoneWindowManage 中,实现具体功能
public void notifyMuteSwitchChanged(boolean isMute) {
final int newMuteState = isMute ? 1 : 0;
if (newMuteState == mMuteState) {
return;
}
mMuteState = newMuteState;
//TODO:setRingerMode
AudioManager audioManager = (AudioManager) mContext.getSystemService(
Context.AUDIO_SERVICE);
if (mMuteState == 1) {
audioManager.setRingerModeNew(AudioManager.RINGER_MODE_SILENT);
} else if (mMuteState == 0) {
audioManager.setRingerModeNew(AudioManager.RINGER_MODE_NORMAL);
}
}