Android 来电静音键拦截流程

最开始以为按键处理会在InCallScreen.java里面的

   1:  public boolean onKeyDown(int keyCode, KeyEvent event):
   2:  case KeyEvent.KEYCODE_VOLUME_UP:
   3:  case KeyEvent.KEYCODE_VOLUME_DOWN:
   4:   
   5:  Phone phone = PhoneApp.getInstance().getPhoneInCall();
   6:  if (phone.getState() == Phone.State.RINGING) {
   7:  // If an incoming call is ringing, the VOLUME buttons are
   8:  // actually handled by the PhoneWindowManager. (We do
   9:  // this to make sure that we'll respond to them even if
  10:  // the InCallScreen hasn't come to the foreground yet.)
  11:  //
  12:  // We'd only ever get here in the extremely rare case that the
  13:  // incoming call started ringing *after*
  14:  // PhoneWindowManager.interceptKeyTq() but before the event
  15:  // got here, or else if the PhoneWindowManager had some
  16:  // problem connecting to the ITelephony service.
  17:  Log.w(LOG_TAG, "VOLUME key: incoming call is ringing!"
  18:  + " (PhoneWindowManager should have handled this key.)");
  19:  // But go ahead and handle the key as normal, since the
  20:  // PhoneWindowManager presumably did NOT handle it:
  21:   
  22:  //TODO DSDS get the subscription from Phone
  23:  //int subscription = mPhone.getSubscriptionInfo();
  24:  final CallNotifier notifier;
  25:  if (TelephonyManager.isDsdsEnabled()) {
  26:  // Get the CallNotifier associated with the phone.
  27:  notifier = PhoneApp.getInstance().getCallNotifier(phone.getSubscription());
  28:  } else {
  29:  notifier = PhoneApp.getInstance().notifier;
  30:  }
  31:  if (notifier.isRinging()) {
  32:  // ringer is actually playing, so silence it.
  33:  PhoneUtils.setAudioControlState(PhoneUtils.AUDIO_IDLE);
  34:  if (DBG) log("VOLUME key: silence ringer");
  35:  notifier.silenceRinger();
  36:  }
  37:   
  38:  // As long as an incoming call is ringing, we always
  39:  // consume the VOLUME keys.
  40:  return true;
  41:  }
  42:  break;

后来发现了这行注释
// Note there's no KeyEvent.KEYCODE_ENDCALL case here.
// The standard system-wide handling of the ENDCALL key
// (see PhoneWindowManager's handling of KEYCODE_ENDCALL)
// already implements exactly what the UI spec wants,
// namely (1) "hang up" if there's a current active call,
// or (2) "don't answer" if there's a current ringing call.

原来在WindowManagerService会有一个 int actions = mPolicy.interceptKeyTq(event, !screenIsOff);
对应的PhoneWindowManager里会有一个

   1:  public int interceptKeyTq(RawInputEvent event, boolean screenIsOn);

方法
此方法可以在最初的位置进行拦截事件处理!

 

   1:  // If an incoming call is ringing, either VOLUME key means
   2:  // "silence ringer". We handle these keys here, rather than
   3:  // in the InCallScreen, to make sure we'll respond to them
   4:  // even if the InCallScreen hasn't come to the foreground yet.
   5:   
   6:  // Look for the DOWN event here, to agree with the "fallback"
   7:  // behavior in the InCallScreen.
   8:  if (down) {
   9:  try {
  10:  ITelephony phoneServ = getPhoneInterface();
  11:  if (phoneServ != null) {
  12:  if (phoneServ.isRinging()) {
  13:  Log.i(TAG, "interceptKeyTq:"
  14:  + " VOLUME key-down while ringing: Silence ringer!");
  15:  // Silence the ringer. (It's safe to call this
  16:  // even if the ringer has already been silenced.)
  17:  phoneServ.silenceRinger();
  18:   
  19:  // And *don't* pass this key thru to the current activity
  20:  // (which is probably the InCallScreen.)
  21:  result &= ~ACTION_PASS_TO_USER;
  22:  }
  23:  } else {
  24:  Log.w(TAG, "VOLUME button: Unable to find ITelephony interface");
  25:  }
  26:  } catch (RemoteException ex) {
  27:  Log.w(TAG, "VOLUME button: RemoteException from getPhoneInterface()", ex);
  28:  }
  29:  }

最终调用的是
   1:  PhoneUtils.setAudioControlState(PhoneUtils.AUDIO_IDLE);
   2:  mApp.getCallNotifier(i).silenceRinger();

以此来电时按声音键会静音!
当然在InCallScreen.java里面那个是个候补!呵呵呵!这样做的好处就是当你在任何界面做为前台进程时都可以按声音键关掉你的来电铃声!
当然在InCallScreen.java里面的也对按键进行了拦截
比如

   1:  public boolean dispatchKeyEvent(KeyEvent event) {
   2:  // if (DBG) log("dispatchKeyEvent(event " + event + ")...");
   3:   
   4:  // Intercept some events before they get dispatched to our views.
   5:  switch (event.getKeyCode()) {
   6:  case KeyEvent.KEYCODE_DPAD_CENTER:
   7:  case KeyEvent.KEYCODE_DPAD_UP:
   8:  case KeyEvent.KEYCODE_DPAD_DOWN:
   9:  case KeyEvent.KEYCODE_DPAD_LEFT:
  10:  case KeyEvent.KEYCODE_DPAD_RIGHT:
  11:  // Disable DPAD keys and trackball clicks if the touch lock
  12:  // overlay is up, since "touch lock" really means "disable
  13:  // the DTMF dialpad" (rather than only disabling touch events.)
  14:  if (mDialer.isOpened() && isTouchLocked()) {
  15:  if (DBG) log("- ignoring DPAD event while touch-locked...");
  16:  return true;
  17:  }
  18:  break;
  19:   
  20:  default:
  21:  break;
  22:  }
  23:   
  24:  return super.dispatchKeyEvent(event);
  25:  }

这样做是为了区别某哥界面的状态对应的按键事件!比如Incallscreen接了电话和没接电话几个按键的事件就不同!

转载于:https://www.cnblogs.com/kevin-wang/archive/2012/10/21/2733045.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值