代码改变世界

来电振铃时按音量键静音

2012-10-24 22:58  Kevin-wang  阅读(1066)  评论(0编辑  收藏  举报

所以的键盘输入事件都是由PhoneWindowManager这个类来处理,最终是由interceptKeyBeforeQueueing方法处理

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

主要是调用了ITelephony接口的silenceRinger()方法,ITelephony接口是由Phone进程中的PhoneInterfaceManager这个类实现并在Phone进程启动的时候向SystemManager(系统服务大总管)注册名称为“phone”的系统服务。silenceRinger这个方法就是发送了一个名为“CMD_SILENCE_RINGER”的message。

   1:      public void silenceRinger() {
   2:          if (DBG) log("silenceRinger...");
   3:          // TODO: find a more appropriate permission to check here.
   4:          // (That can probably wait till the big TelephonyManager API overhaul.
   5:          // For now, protect this call with the MODIFY_PHONE_STATE permission.)
   6:          enforceModifyPermission();
   7:          sendRequestAsync(CMD_SILENCE_RINGER);
   8:      }
处理CMD_SILENCE_RINGER消息如下:
   1:    case CMD_SILENCE_RINGER:
   2:          silenceRingerInternal();
   3:          break;

最终是调用了silenceRingerInternal()方法。

   1:      private void silenceRingerInternal() {
   2:          if ((mCM.getState() == Phone.State.RINGING)
   3:              && mApp.notifier.isRinging()) {
   4:              // Ringer is actually playing, so silence it.
   5:              if (DBG) log("silenceRingerInternal: silencing...");
   6:              mApp.notifier.silenceRinger();
   7:          }
   8:      }

会调用mApp.notifier.silenceRinger()方法,mApp就是PhoneApp实例,notifier就是CallNotifier的实例,在silenceRinger方法中的实现其实就是调用了Ringer的stopRing()方法停止响铃的。

   1:      void silenceRinger() {
   2:          mSilentRingerRequested = true;
   3:          if (DBG) log("stopRing()... (silenceRinger)");
   4:          mRinger.stopRing();
   5:      }

根据上面的分析再看一下当有来电振铃时按电源键时会做什么呢

   1:  ......
   2:  case KeyEvent.KEYCODE_POWER: {
   3:  result &= ~ACTION_PASS_TO_USER;
   4:  if (down) {
   5:      if (isScreenOn && !mPowerKeyTriggered
   6:              && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
   7:          mPowerKeyTriggered = true;
   8:          mPowerKeyTime = event.getDownTime();
   9:          interceptScreenshotChord();
  10:      }
  11:   
  12:      ITelephony telephonyService = getTelephonyService();
  13:      boolean hungUp = false;
  14:      if (telephonyService != null) {
  15:          try {
  16:              if (telephonyService.isRinging()) {
  17:                  // Pressing Power while there's a ringing incoming
  18:                  // call should silence the ringer.
  19:                  telephonyService.silenceRinger();
  20:  .....
可以看到加粗的部分也是调用了ITelephony.silenceRinger()方法静音。