按键事件,大概由3部分,
1.底层调用input.h中的键值(如果新定义按键可以自行加入键值,反正在.kl文件做个映射就行)
2.一个映射到framework的映射文件在system/usr/keylayout/*.kl文件
3.具体按键功能的事件和功能拓展在frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
项目中的情况,正常情况下在线控耳机上MUSIC的情况下是MEDIA_NEXT(下一首)和MEDIA_PREVIOUS(上一首),这个本身android是支持的,现在需要支持在电话状态下是音量加减的功能.
1.如果遇到硬件采集电压不稳,软件上的解决办法。底层按键驱动采集ADC电压不稳的解决办法,采集是使用定时器轮询的方式
解决办法:
a.加大定时器的采集密度,并做状态统计,在同一状态下采集5次,就上报按键//加大采集密度,必然导致消耗cpu,所以在没有按键事件的时候保持原来的采集密度,只有当满足按键条件的时候再加大采集频率
static void lradc1_data_function(unsigned long data)
{
volatile unsigned int reg_val;
static int key_pressed = -1, count = 0;
int delay = HZ/40; //默认在为HZ/40采集,程序后面reg_val>0x34时,按键时为HZ/4,降低了采集频率,节省cpu资源,当有按键按下时采集HZ/40
+ if (reg_val >=0 && reg_val < 0x5 ) + { + // hook key + if (key_pressed == 0) //按物理键是按了0,如果相等的话,就计数加一 + count++; + else { + key_pressed = 0; //如果按物理键0,但不相等(为了防止误触的可能)强制赋值0 ,并且计数清0 + count = 0; + } + + if (count > 5) + { + sw_pressed[0] = 1; + input_report_key(sun4ikbd_dev, HOOK_KEY, 1); + input_sync(sun4ikbd_dev); + printk("[lkj] input key sw1 down \n"); + count = 0; + } + + + + } + else if( reg_val >= 0x6 && reg_val <= 0xb ) + { + // sw2 + if (key_pressed == 1) + count++; + else { + key_pressed = 1; + count = 0; + } + + if (count > 5) + { + sw_pressed[1] = 1; + input_report_key(sun4ikbd_dev, SW2_KEY, 1); + input_sync(sun4ikbd_dev); + printk("[lkj] input key sw2 down \n"); + count = 0; + } + + } else if ( reg_val >= 0xf && reg_val < 0x1f ) + { + // sw3 + if (key_pressed == 2) + count++; + else { + key_pressed = 2; + count = 0; + } + + if (count > 5) + { + sw_pressed[2] = 1; + input_report_key(sun4ikbd_dev, SW3_KEY, 1); + input_sync(sun4ikbd_dev); + printk("[lkj] input key sw3 down \n"); + count = 0; + } + + } + else if ( reg_val >= 0x34) { + key_pressed = -1; + count = 0; + if (sw_pressed[0]) + { + sw_pressed[0] = 0; + input_report_key(sun4ikbd_dev, HOOK_KEY, 0); + input_sync(sun4ikbd_dev); + printk("[lkj] input key sw1 up \n"); + } + if (sw_pressed[1]) + { + sw_pressed[1] = 0; + input_report_key(sun4ikbd_dev, SW2_KEY, 0); + input_sync(sun4ikbd_dev); + printk("[lkj] input key sw2 up \n"); + } + if (sw_pressed[2]) + { + sw_pressed[2] = 0; + input_report_key(sun4ikbd_dev, SW3_KEY, 0); + input_sync(sun4ikbd_dev); + printk("[lkj] input key sw3 up \n"); + } + delay = HZ/4; }
mod_timer(&mic_data->timer, jiffies + delay);
}
2.写个映射就可以
3.找到MEDIA_NEXT和MEDIA_PREVIOUS,区分2个状态,music和in_call,
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 8badbdd..1f4b785 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -2982,11 +2982,32 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } } + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + if (down) { + AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);//实例化这个audioManager,并用文件中的mContext + + ITelephony telephonyService = getTelephonyService(); + try { + if (telephonyService.isOffhook()) { + Log.d(TAG, "++++++++---+++++telephonyService.isOffhook="+telephonyService.isOffhook());//isOffhook ==true 为通话状态下 + audioManager.adjustSuggestedStreamVolume( + keyCode == KeyEvent.KEYCODE_MEDIA_NEXT ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER, + AudioManager.STREAM_RING, + AudioManager.FLAG_SHOW_UI);//调用AudioManager在in_call情况下调整音量并出现音量状态栏 + + break; + }//如果不在in_call状态下,就走下面源代码的线路 + } catch (RemoteException ex) { + Log.w(TAG, "ITelephony threw RemoteException", ex); + } + } case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_MUTE: case KeyEvent.KEYCODE_MEDIA_STOP: - case KeyEvent.KEYCODE_MEDIA_NEXT: - case KeyEvent.KEYCODE_MEDIA_PREVIOUS: case KeyEvent.KEYCODE_MEDIA_REWIND: case KeyEvent.KEYCODE_MEDIA_RECORD: case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: { (END)