Android 来电静音键拦截流程 接电话时按键后无声

转载 2012年03月30日 17:43:19

http://yelinsen.iteye.com/blog/834866

 

 

现在在做双卡双待的项目!作为主要核心Phone遇到的问题也是千奇百怪! 
今天就被一个问题困扰了一下午--来电后按声音按键需要静音!因为是双Phone对象所以对应的RINGER也有两个! 
分析一下解BUG流程! 
最开始以为按键处理会在InCallScreen.java里面的 

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;  

    public boolean onKeyDown(int keyCode, KeyEvent event):
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_DOWN:

                Phone phone = PhoneApp.getInstance().getPhoneInCall();
                if (phone.getState() == Phone.State.RINGING) {
                    // If an incoming call is ringing, the VOLUME buttons are
                    // actually handled by the PhoneWindowManager.  (We do
                    // this to make sure that we'll respond to them even if
                    // the InCallScreen hasn't come to the foreground yet.)
                    //
                    // We'd only ever get here in the extremely rare case that the
                    // incoming call started ringing *after*
                    // PhoneWindowManager.interceptKeyTq() but before the event
                    // got here, or else if the PhoneWindowManager had some
                    // problem connecting to the ITelephony service.
                    Log.w(LOG_TAG, "VOLUME key: incoming call is ringing!"
                          + " (PhoneWindowManager should have handled this key.)");
                    // But go ahead and handle the key as normal, since the
                    // PhoneWindowManager presumably did NOT handle it:

                    //TODO DSDS get the subscription from Phone
                    //int subscription = mPhone.getSubscriptionInfo();
                    final CallNotifier notifier;
                    if (TelephonyManager.isDsdsEnabled()) {
                        // Get the CallNotifier associated with the phone.
                        notifier = PhoneApp.getInstance().getCallNotifier(phone.getSubscription());
                    } else {
                        notifier = PhoneApp.getInstance().notifier;
                    }
                    if (notifier.isRinging()) {
                        // ringer is actually playing, so silence it.
                        PhoneUtils.setAudioControlState(PhoneUtils.AUDIO_IDLE);
                        if (DBG) log("VOLUME key: silence ringer");
                        notifier.silenceRinger();
                    }

                    // As long as an incoming call is ringing, we always
                    // consume the VOLUME keys.
                    return true;
                }
                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里会有一个 

Java代码  
1.public int interceptKeyTq(RawInputEvent event, boolean screenIsOn);  
public int interceptKeyTq(RawInputEvent event, boolean screenIsOn);

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

Java代码  
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.                }  
// If an incoming call is ringing, either VOLUME key means
                // "silence ringer".  We handle these keys here, rather than
                // in the InCallScreen, to make sure we'll respond to them
                // even if the InCallScreen hasn't come to the foreground yet.

                // Look for the DOWN event here, to agree with the "fallback"
                // behavior in the InCallScreen.
                if (down) {
                    try {
                        ITelephony phoneServ = getPhoneInterface();
                        if (phoneServ != null) {
                            if (phoneServ.isRinging()) {
                                Log.i(TAG, "interceptKeyTq:"
                                      + " VOLUME key-down while ringing: Silence ringer!");
                                // Silence the ringer.  (It's safe to call this
                                // even if the ringer has already been silenced.)
                                phoneServ.silenceRinger();

                                // And *don't* pass this key thru to the current activity
                                // (which is probably the InCallScreen.)
                                result &= ~ACTION_PASS_TO_USER;
                            }
                        } else {
                            Log.w(TAG, "VOLUME button: Unable to find ITelephony interface");
                        }
                    } catch (RemoteException ex) {
                        Log.w(TAG, "VOLUME button: RemoteException from getPhoneInterface()", ex);
                    }
                }

phoneServ.silenceRinger(); 

Java代码  
1.PhoneInterfaceManager.java   
2.public void silenceRinger() {   
3.        if (DBG)   
4.            log("silenceRinger...");   
5.        // TODO: find a more appropriate permission to check here.   
6.        // (That can probably wait till the big TelephonyManager API overhaul.   
7.        // For now, protect this call with the MODIFY_PHONE_STATE permission.)   
8.        enforceModifyPermission();   
9.        sendRequestAsync(CMD_SILENCE_RINGER);   
10.    }  
PhoneInterfaceManager.java
public void silenceRinger() {
		if (DBG)
			log("silenceRinger...");
		// TODO: find a more appropriate permission to check here.
		// (That can probably wait till the big TelephonyManager API overhaul.
		// For now, protect this call with the MODIFY_PHONE_STATE permission.)
		enforceModifyPermission();
		sendRequestAsync(CMD_SILENCE_RINGER);
	}

最终调用的是 

Java代码  
1.PhoneUtils.setAudioControlState(PhoneUtils.AUDIO_IDLE);   
2.                mApp.getCallNotifier(i).silenceRinger();  
PhoneUtils.setAudioControlState(PhoneUtils.AUDIO_IDLE);
				mApp.getCallNotifier(i).silenceRinger();

以此来电时按声音键会静音! 

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

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.   }  
 public boolean dispatchKeyEvent(KeyEvent event) {
        // if (DBG) log("dispatchKeyEvent(event " + event + ")...");

        // Intercept some events before they get dispatched to our views.
        switch (event.getKeyCode()) {
            case KeyEvent.KEYCODE_DPAD_CENTER:
            case KeyEvent.KEYCODE_DPAD_UP:
            case KeyEvent.KEYCODE_DPAD_DOWN:
            case KeyEvent.KEYCODE_DPAD_LEFT:
            case KeyEvent.KEYCODE_DPAD_RIGHT:
                // Disable DPAD keys and trackball clicks if the touch lock
                // overlay is up, since "touch lock" really means "disable
                // the DTMF dialpad" (rather than only disabling touch events.)
                if (mDialer.isOpened() && isTouchLocked()) {
                    if (DBG) log("- ignoring DPAD event while touch-locked...");
                    return true;
                }
                break;

            default:
                break;
        }

        return super.dispatchKeyEvent(event);
    }

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

相关文章推荐

Android 事件捕捉和处理流程

1.    InputManagerService(IMS) 1.1     IMS初始化           在系统启动的时...

Android 来电翻转静音实现源码

1.添加实现文件: alps\packages\apps\InCallUI\src\com\android\incallui\SensorFunctionServiceIncall.java ...

android L平台增加来电翻转静音菜单、功能

来电翻转静音原理:监听phone状态,来电时启动一个服务监听Gsensor 当检测到手机从向上翻转到向下(Z值5以上翻到到-5以下),设置ringtone音量为0 来电接通或挂断后恢复rington...

让Android手机黑名单来电实现自动静音

当呼叫者属于黑名单列表 自动静音 [代码 步骤] 本着先易后难的原则 先介绍黑名单列表的制作:其会列出所有联系人列表 以CheckBox形式 可以添加/移除 黑名单 1. 定义所需布局:list...

android 5.1中添加来电翻转静音的功能

网上关于来电翻转静音的功能有很多实现,但大同小以异,下面主要记录以下几点: 1.settting中添加控制。 2.Dialer中添加具体的功能实现。 3.AudioManager实现完成静音。 ...

Android接电话流程、Phone来电过程、phone上层来电话解析 接通电话

汇聚下,别人对来电的分析:   http://blog.csdn.net/ninedays/article/details/5969215 接电话的基本流程(java层): 首先,通过dd...

Android 4.0系统打电话和接电话系统流程时序图详解

鄙人初学Android系统源码还不到半载,之前一段时间由于工作原因,稍微研究了一下Android4.0系统打电话和接电话的大致流程。现将自己的研究结果以时序图奉上,由于经验有限,若有错误还请见谅。 打...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)