一个来电会在系统层面上发生什么?

9

在哪个系统级别?涉及到一系列庞大的事情链:http://www.netmite.com/android/mydroid/development/pdk/docs/telephony.html - zapl
是的,我熟悉RIL。主要关注应用程序框架层及以上,因为这些都是Java编写的,易于修改。 - Bachalo
3个回答

5
让我们从查看 CallNotifier 开始:CallNotifier:
/** * Phone 应用程序模块,监听电话状态变化和来自电信层的各种其他事件,并触发任何相关的 UI 行为(例如启动振铃和来电 UI、播放通话提示音、更新通知、编写通话日志条目等) */ 其中这个 Handler 响应的消息之一是:CallStateMonitor.PHONE_NEW_RINGING_CONNECTION:
case CallStateMonitor.PHONE_NEW_RINGING_CONNECTION:
    log("RINGING... (new)");
    onNewRingingConnection((AsyncResult) msg.obj);
    mSilentRingerRequested = false;
    break;

onNewRingingConnection(AsyncResult)最终(在一般情况下)调用ringAndNotifyOfIncomingCall(Connection c)

private void ringAndNotifyOfIncomingCall(Connection c) {
    if (PhoneUtils.isRealIncomingCall(c.getState())) {
        mRinger.ring();
    } else {
        if (VDBG) log("- starting call waiting tone...");
            if (mCallWaitingTonePlayer == null) {
                mCallWaitingTonePlayer = new InCallTonePlayer(
                                         InCallTonePlayer.TONE_CALL_WAITING);
                mCallWaitingTonePlayer.start();
            }
    }

    // CallModeler.onNewRingingConnection(Connection)
    mCallModeler.onNewRingingConnection(c);
}

CallModeler.onNewRingingConnection(Connection) (链接) 通知已附加的监听器:

for (int i = 0; i < mListeners.size(); ++i) {
    mListeners.get(i).onIncoming(call);
}

这些监听器实现了CallModeler.Listener接口。CallHandlerServiceProxy是其中之一的监听器,它的onIncoming(Call)回调触发CallHandlerServiceProxy.processIncoming(Call)
private void processIncoming(Call call) {
    ....
    // ICallHandlerService
    mCallHandlerServiceGuarded.onIncoming(call,
                   RejectWithTextMessageManager.loadCannedResponses());
    ....
}

CallHandlerService定义了一个ICallHandlerService.Stub成员,并且它的onIncoming(Call, List<String>)方法如下:

@Override
public void onIncoming(Call call, List<String> textResponses) {
    ....
    mMainHandler.sendMessage(mMainHandler.obtainMessage(
                   ON_UPDATE_CALL_WITH_TEXT_RESPONSES, incomingCall));
    ....
}

这是 mMainHandler 处理 ON_UPDATE_CALL_WITH_TEXT_RESPONSES 情况的方式:
case ON_UPDATE_CALL_WITH_TEXT_RESPONSES:
    AbstractMap.SimpleEntry<Call, List<String>> entry
                   = (AbstractMap.SimpleEntry<Call, List<String>>) msg.obj;
    Log.i(TAG, "ON_INCOMING_CALL: " + entry.getKey());

    // CallList
    mCallList.onIncoming(entry.getKey(), entry.getValue());
    break;

CallList维护一个实现CallList.Listener接口的监听器列表,并从其CallList.onIncoming(Call, List<String>)方法中触发他们的onIncomingCall(Call)事件。

现在,让我们看看InCallPresenter

/** * 接收来自CallList的更新并通知InCallActivity(UI)进行更改。 * 负责启动新呼叫的Activity并在所有呼叫断开连接时完成该Activity。 * 创建和管理呼叫状态并为想要侦听呼叫状态更改的Presenter提供侦听器模式。 * TODO:此类现在已成为状态机。请考虑重命名。 */

InCallPresenter实现了CallList.Listener接口,负责启动提供所有电话相关操作的UI的InCallActivity。以下注释(取自InCallPresenter.startOrFinishUi(InCallState))将上述一系列事件联系在了一起:

/* A new Incoming call means that the user needs to be notified of the
   the call (since it wasn't them who initiated it).  We do this 
   through full  screen notifications and happens indirectly through {@link 
   StatusBarListener}. The process for incoming calls is as follows:

   1) CallList          - Announces existence of new INCOMING call
   2) InCallPresenter   - Gets announcement and calculates that the new 
                          InCallState should be set to INCOMING.
   3) InCallPresenter   - This method is called to see if we need to 
                          start or finish the app given the new state.
   4) StatusBarNotifier - Listens to InCallState changes. InCallPresenter 
                          calls StatusBarNotifier explicitly to issue a 
                          FullScreen Notification that will either start the
                          InCallActivity or show the user a top-level 
                          notification dialog if the user is in 
                          an immersive app. That notification can also start 
                          the InCallActivity.         
   5) InCallActivity    - Main activity starts up and at the end of its 
                          onCreate will call InCallPresenter::setActivity() 
                          to let the presenter know that start-up is complete.
                  [ AND NOW YOU'RE IN THE CALL. voila! ] */

我希望这回答了你的问题,或者至少给你指明了方向。如果我有遗漏或误解,请随时纠正。


1
希望以下代码能帮到你。
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
         super.onCallStateChanged(state, incomingNumber);
         switch(state){
         case TelephonyManager.CALL_STATE_IDLE:
             //Not in call: Play music

             break;
         case TelephonyManager.CALL_STATE_OFFHOOK:
             //A call is dialing, active or on hold

             break;
         case TelephonyManager.CALL_STATE_RINGING:
             //Incoming call: Pause music

             break;

         }            
    }

谷歌参考文档为
http://developer.android.com/reference/android/telephony/TelephonyManager.html


1

请看这个 Grep code InCallScreen.java

   else if (action.equals(Intent.ACTION_ANSWER)) {
        internalAnswerCall();
        app.setRestoreMuteOnInCallResume(false);
        return InCallInitStatus.SUCCESS;

谢谢。那是一个更旧的Android版本。那么KitKat呢?似乎InCall屏幕已经改变了。 - Bachalo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接