Android 自定义功能按键实现

我们在做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);
                 }
         }

你可能感兴趣的:(android-6)