按键事件,大概由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)