What happens at the system level on an incoming call?
Asked Answered
F

3

9

I've downloaded the entire source code for the master branch from https://android.googlesource.com/platform/frameworks/base/+/master, and am trying to decipher the chain of events on an incoming call.

I assume that the ACTION_ANSWER intent is started but beyond that don't know what happens before or after.

Can anyone help?

Folio answered 10/1, 2014 at 20:44 Comment(2)
At what system level? There is a huge chain of things involved: netmite.com/android/mydroid/development/pdk/docs/telephony.htmlClinic
yes I'm familiar with the RIL. Primarily concerned with the ApplicationFramework layer and up since that is all Java and easily modded.Folio
D
5

Let's begin by looking at CallNotifier:

/** * Phone app module that listens for phone state changes and various other * events from the telephony layer, and triggers any resulting UI behavior * (like starting the Ringer and Incoming Call UI, playing in-call tones, * updating notifications, writing call log entries, etc.) */

One of the messages that this Handler responds to is: CallStateMonitor.PHONE_NEW_RINGING_CONNECTION:

case CallStateMonitor.PHONE_NEW_RINGING_CONNECTION:
    log("RINGING... (new)");
    onNewRingingConnection((AsyncResult) msg.obj);
    mSilentRingerRequested = false;
    break;

onNewRingingConnection(AsyncResult) eventually (and, in general case) calls 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) (Link) notifies attached listeners:

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

These listeners implement CallModeler.Listener interface. CallHandlerServiceProxy is one such listener, and its onIncoming(Call) callback fires CallHandlerServiceProxy.processIncoming(Call):

private void processIncoming(Call call) {
    ....
    // ICallHandlerService
    mCallHandlerServiceGuarded.onIncoming(call,
                   RejectWithTextMessageManager.loadCannedResponses());
    ....
}

CallHandlerService defines a ICallHandlerService.Stub member and its onIncoming(Call, List<String>) method looks like:

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

This is how mMainHandler handles case 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 keeps a list of listeners that implement CallList.Listener, and fires their onIncomingCall(Call) event from its CallList.onIncoming(Call, List<String>) method.

Now, let's look at InCallPresenter:

/** * Takes updates from the CallList and notifies the InCallActivity (UI) * of the changes. * Responsible for starting the activity for a new call and finishing the activity when all calls * are disconnected. * Creates and manages the in-call state and provides a listener pattern for the presenters * that want to listen in on the in-call state changes. * TODO: This class has become more of a state machine at this point. Consider renaming. */

InCallPresenter implements CallList.Listener interface, and is responsible for launching InCallActivity that provides the UI for all phone related operations. The following comment (taken from InCallPresenter.startOrFinishUi(InCallState)) brings the above-mentioned chain of events together:

/* 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! ] */

I hope this answers your question, or at the very least, shows you where to look. Feel free to correct anything I overlooked/misinterpreted.

Discarnate answered 1/2, 2014 at 13:30 Comment(0)
I
1

have a look at this Grep code InCallScreen.java

   else if (action.equals(Intent.ACTION_ANSWER)) {
        internalAnswerCall();
        app.setRestoreMuteOnInCallResume(false);
        return InCallInitStatus.SUCCESS;
Illusionary answered 30/1, 2014 at 4:49 Comment(1)
Thanks. That is a much older version of Android. What about KitKat? It seems that the InCall Screen has been changedFolio
H
1

Hope below Code Help you.

    @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;

         }            
    }

The google reference is
http://developer.android.com/reference/android/telephony/TelephonyManager.html

Halliday answered 31/1, 2014 at 17:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.