Android增加一个物理按键检测步骤

Android增加一个物理按键检测步骤
       本文将简要介绍为Android增加一个物理按键的步骤,实现在PhoneWindowManager.java检测到该按键后执行想要的操作,示例中会在检测到预定义按键按下后实现打开照相机应用的功能。
1:背景介绍
       自带按键手机一部,MT6589平台,安卓4.2版本,3.4.5 Linux内核。

2:实现细节

2.1实现kernel层按键事件的上报

首先在KPD_INIT_KEYMAP()中把对应的物理按键定义为KEY_TEST,后面的设置也是根据此表来的。而KEY_TEST在input.h中定义。

文件路径:alps/mediatek/custom/${project}/kernel/dct/dct/cust_kpd.h

/* HW keycode [0 ~ 71] -> Linux keycode*/

#define KPD_INIT_KEYMAP()   \

{     \

       …

        [21] = KEY_TEST,            \

       …

}

Inpu.h中定义KEY_TEST:

路径:alps/kernel/include/linux/input.h

#define KEY_WIMAX		246
#define KEY_RFKILL		247	/* Key that controls all radios */
#define KEY_MICMUTE		248	/* Mute / unmute the microphone */
#define KEY_TEST		249	/* add a test key */

/* Code 255 is reserved for special needs of AT keyboard driver */

Input输入子系统的注册和上报:

输入子系统的注册:

文件路径:/alps/mediatek/platform/mt6589/kernel/drivers/keypad/kpd.c

static int kpd_pdrv_probe(struct platform_device *pdev)
{
	…
    /* initialize and register input device (/dev/input/eventX) */
	kpd_input_dev = input_allocate_device();
…
__set_bit(EV_KEY, kpd_input_dev->evbit); 
for (i = 0; i < KPD_NUM_KEYS; i++) {
		if (kpd_keymap[i] != 0)
			__set_bit(kpd_keymap[i], kpd_input_dev->keybit);
	} 
…
r = input_register_device(kpd_input_dev);
…
r = request_irq(MT6589_KP_IRQ_ID, kpd_irq_handler, IRQF_TRIGGER_FALLING, KPD_NAME, NULL);

}
其中: 
static u16 kpd_keymap[KPD_NUM_KEYS] = KPD_INIT_KEYMAP();//将我们定义的KEY_TEST注册进输入系统.
  r = request_irq(MT6589_KP_IRQ_ID, kpd_irq_handler, IRQF_TRIGGER_FALLING, KPD_NAME, NULL);    // 这里注册了按键中断和对应的处理函数.接下来分析kpd_irq_handler()函数.
static irqreturn_t kpd_irq_handler(int irq, void *dev_id)
{
	/* use _nosync to avoid deadlock */
	disable_irq_nosync(MT6589_KP_IRQ_ID);
	tasklet_schedule(&kpd_keymap_tasklet);
	return IRQ_HANDLED;
}

//由上可知,中断处理函数只简单的调度了一个tasklet.下面我们分析调度的任务:

static DECLARE_TASKLET(kpd_keymap_tasklet, kpd_keymap_handler, 0);
static void kpd_keymap_handler(unsigned long data)
{
	…
	linux_keycode = kpd_keymap[hw_keycode];
	input_report_key(kpd_input_dev, linux_keycode, pressed);
	input_sync(kpd_input_dev);	
…
}

Linux内核注册上报的流程基本就这样.

2.2编译/验证

./mk r k;

./mk bootimage

运行上面两条命令后,在alps/out/target/product/${project}就会生成bootimage文件,将此文件下载到手机重新启动后,用adb连接,并输入命令;

root@android:/ # getevent /dev/input/event0

点击我们设置的按键,就会上报事件:

0001 00f900000001

0000 0000 00000000

0001 00f900000000

0000 0000 00000000

上面的0xF9即为我们在input.h里面定义的249.

3:增加keypad layout文件键盘映射,linux和android key映射

文件路径:alps/mediatek//config/${project}/mtk-kpd.kl

key 212   CAMERA
key 211   FOCUS
key 249   TEST    

4:修改Java识别keycode

路径:/alps/frameworks/base/include/androidfw/keycodelables.h

static const KeycodeLabel KEYCODES[] = {
   …
    { "KANA", 218 },
    { "ASSIST", 219 },
    { "TEST", 220 },

    // 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.

{ NULL, 0 }
…
}

路径:/alps/framework /native/include/android/KeyCodes.h

enum {
…
  AKEYCODE_TEST          = 220,
…
}

5:修改Java键盘事件

路径:alps/frameworks/base/core/java/android/view/KeyEvent.java

public class KeyEvent extends InputEvent implements Parcelable {
 …  
/** Key code constant: Assist key.
     * Launches the global assist activity.  Not delivered to applications. */
    public static final int KEYCODE_ASSIST          = 219;
   public static final int KEYCODE_TEST          = 220;

    private static final int LAST_KEYCODE           = KEYCODE_TEST;
…
}

6:修改xml文件描述符

路径:alps/frameworks/base/core/res/res/values/attrs.xml

7:增加验证在android,在此直接打开摄像头。

路径:/alps/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java

在interceptKeyBeforeDispatching()增加:

if(keyCode==KeyEvent.KEYCODE_TEST&&event.getAction()==KeyEvent.ACTION_DOWN)
{
	Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA)
                .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
                        | Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        mContext.startActivity(intent);
	}
 以上即为在Android系统中实现物理按键的上报及检测到按键后采取不同的操作方法的简要概述.


你可能感兴趣的:(Linux/android驱动)