Let's first look at the general process of 7.0 calls:
Framework
After the modem receives the incoming call notification message, it reports to the RIL layer in the form of AT commands, and the RIL layer sends the message to RILJ through sokcet, and reports the event ID: RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
- frameworks/opt/telephony – RIL
private void processUnsolicited (Parcel p, int type) {
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
if (RILJ_LOGD) unsljLog(response);
mCallStateRegistrants
.notifyRegistrants(new AsyncResult(null, null, null));
break;
- frameworks/opt/telephony – BaseCommands
@Override public void registerForCallStateChanged(Handler h, int what, Object obj) { Registrant r = new Registrant (h, what, obj); mCallStateRegistrants.add(r); }
- frameworks/opt/telephony – GsmCdmaCallTracker
public GsmCdmaCallTracker (GsmCdmaPhone phone) {
mCi = phone.mCi;
mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
Then find the EVENT_CALL_STATE_CHANGE message:
case EVENT_CALL_STATE_CHANGE:
pollCallsWhenSafe();
break;
- frameworks/opt/telephony – CallTracker
protected void pollCallsWhenSafe() { mNeedsPoll = true; if (checkNoOperationsPending ()) { mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT); mCi.getCurrentCalls(mLastRelevantPoll); } }
- frameworks/opt/telephony – RIL
EVENT_POLL_CALLS_RESULT:
@Override public void getCurrentCalls (Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS, result); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); send(rr); }
- frameworks/opt/telephony – GsmCdmaCallTracker
case EVENT_POLL_CALLS_RESULT: Rlog.d(LOG_TAG, "Event EVENT_POLL_CALLS_RESULT Received"); if (msg == mLastRelevantPoll) { if (DBG_POLL) log( "handle EVENT_POLL_CALL_RESULT: set needsPoll=F"); mNeedsPoll = false; mLastRelevantPoll = null; handlePollCalls((AsyncResult)msg.obj); }Update state, send call state change notifications, etc.:
if (newRinging != null) { mPhone.notifyNewRingingConnection(newRinging); } updatePhoneState(); if (hasNonHangupStateChanged || newRinging != null || hasAnyCallDisconnected) { mPhone.notifyPreciseCallStateChanged(); }
- frameworks/opt/telephony – Phone
/**
* Notify registrants of a new ringing Connection.
* Subclasses of Phone probably want to replace this with a
* version scoped to their packages
*/
public void notifyNewRingingConnectionP(Connection cn) {
if (!mIsVoiceCapable)
return;
AsyncResult ar = new AsyncResult(null, cn, null);
mNewRingingConnectionRegistrants.notifyRegistrants(ar);
}
Telephony
- packages/service/Telephony – PstnIncomingCallNotifier
Find the registration registerForNewRingingConnection,
The message EVENT_NEW_RINGING_CONNECTION calls handleNewRingingConnection:
mPhone.registerForNewRingingConnection(mHandler, EVENT_NEW_RINGING_CONNECTION, null); case EVENT_NEW_RINGING_CONNECTION: handleNewRingingConnection((AsyncResult) msg.obj); break;Framework
- frameworks/base/telecomm – TelecomManager
addNewIncomingCall方法
public void addNewIncomingCall(PhoneAccountHandle phoneAccount, Bundle extras) {
try {
if (isServiceConnected()) {
getTelecomService().addNewIncomingCall(
phoneAccount, extras == null ? new Bundle() : extras);
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException adding a new incoming call: " + phoneAccount, e);
}
}
Telecom
- packages/services/Telecom – TelecomServiceImpl
private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub() { @Override public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) { Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL); intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, true); if (extras != null) { extras.setDefusable(true); intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras); } mCallIntentProcessorAdapter.processIncomingCallIntent( mCallsManager, intent);
- packages/services/Telecom – CallIntentProcessor
static void processIncomingCallIntent(CallsManager callsManager, Intent intent) {
callsManager.processIncomingCallIntent(phoneAccountHandle, clientExtras);
}
- packages/services/Telecom – CallsManager
void processIncomingCallIntent(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
Call call = new Call(
getNextCallId(),
mContext,
this,
mLock,
mConnectionServiceRepository,
mContactsAsyncHelper,
mCallerInfoAsyncQueryFactory,
handle,
null /* gatewayInfo */,
null /* connectionManagerPhoneAccount */,
phoneAccountHandle,
Call.CALL_DIRECTION_INCOMING /* callDirection */,
false /* forceAttachToExistingConnection */,
false /* isConference */
);
call.addListener(this);
call.startCreateConnection(mPhoneAccountRegistrar);
}
- packages/services/Telecom – Call
void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar) {
mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this,
phoneAccountRegistrar, mContext);
mCreateConnectionProcessor.process();
}
- packages/services/Telecom – CreateConnectionProcessor
@VisibleForTesting
public void process() {
Log.v(this, "process");
clearTimeout();
mAttemptRecords = new ArrayList<>();
if (mCall.getTargetPhoneAccount() != null) {
mAttemptRecords.add(new CallAttemptRecord(
mCall.getTargetPhoneAccount (), mCall.getTargetPhoneAccount ()));
}
adjustAttemptsForConnectionManager();
adjustAttemptsForEmergency();
mAttemptRecordIterator = mAttemptRecords.iterator();
attemptNextPhoneAccount();
}
- packages/services/Telecom – ConnectionServiceWrapper
mServiceInterface.createConnection(
call.getConnectionManagerPhoneAccount(),
callId,
new ConnectionRequest(
call.getTargetPhoneAccount(),
call.getHandle(),
extras,
call.getVideoState(),
callId),
call.shouldAttachToExistingConnection(),
call.isUnknown());
Frameworks
- frameworks/base/telecomm -- ConnectionService
When calling out, onCreateOutgoingConnection is called. This article is calling in. You need to check onCreateIncomingConnection .
Connection connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
: isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
: onCreateOutgoingConnection(callManagerAccount, request);
Telecom
- packages/services/Telecom – Call
public void handleCreateConnectionSuccess(
switch (mCallDirection) {
case CALL_DIRECTION_INCOMING:
// Listeners (just CallsManager for now) will be responsible for checking whether
// the call should be blocked.
for (Listener l : mListeners) {
l.onSuccessfulIncomingCall(this);
}
break;
- packages/services/Telecom – CallsManager
@Override
public void onSuccessfulIncomingCall(Call incomingCall) {
Log.d(this, "onSuccessfulIncomingCall");
List<IncomingCallFilter.CallFilter> filters = new ArrayList<>();
filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter()));
filters.add(new CallScreeningServiceFilter(mContext, this, mPhoneAccountRegistrar,
mDefaultDialerManagerAdapter,
new ParcelableCallUtils.Converter(), mLock));
new IncomingCallFilter(mContext, this, incomingCall, mLock,
mTimeoutsAdapter, filters).performFiltering();
}
- packages/services/Telecom – IncomingCallFilter
It mainly implements information about intercepting incoming calls, whether it is a blacklist, etc. This article does not focus on the process here:
public void performFiltering() {
mHandler.postDelayed(new Runnable("ICF.pFTO") { // performFiltering time-out
@Override
public void loggedRun() {
// synchronized to prevent a race on mResult and to enter into Telecom.
synchronized (mTelecomLock) {
if (mIsPending) {
Log.i(IncomingCallFilter.this, "Call filtering has timed out.");
Log.event(mCall, Log.Events.FILTERING_TIMED_OUT);
mListener.onCallFilteringComplete(mCall, mResult);
mIsPending = false;
}
}
}
}.prepare(), mTimeoutsAdapter.getCallScreeningTimeoutMillis(mContext.getContentResolver()));
}
- packages/services/Telecom – CallsManager
@Override public void onCallFilteringComplete(Call incomingCall, CallFilteringResult result) { addCall(incomingCall); }
private void addCall(Call call) { for (CallsManagerListener listener : mListeners) { listener.onCallAdded(call);}
- packages/services/Telecom – InCallController
Similar to the inbound article, with the relevant code:
@Override public void onCallAdded(Call call) { if (!isBoundToServices()) { bindToServices(call); } else { addCall(call); inCallService.addCall(parcelableCall); }Frameworks
- frameworks/base/telecomm – InCallService
Implement the aidl method addCall and find the message MSG_ADD_CALL:
private final class InCallServiceBinder extends IInCallService.Stub { @Override public void setInCallAdapter(IInCallAdapter inCallAdapter) { mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget(); }
@Override public void addCall(ParcelableCall call) { mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget(); }
case MSG_ADD_CALL:
mPhone.internalAddCall((ParcelableCall) msg.obj);
break;
- frameworks/base/telecomm -- Phone
final void internalAddCall(ParcelableCall parcelableCall) {
Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,
parcelableCall.getState());
mCallByTelecomCallId.put(parcelableCall.getId(), call);
mCalls.add(call);
checkCallTree(parcelableCall);
call.internalUpdate(parcelableCall, mCallByTelecomCallId);
fireCallAdded(call);
}
private void fireCallAdded(Call call) {
for (Listener listener : mListeners) {
listener.onCallAdded(this, call);
}
}
- frameworks/base/telecomm – InCallService
@Override public void onCallAdded(Phone phone, Call call) { InCallService.this.onCallAdded(call); }
Dialer
- packages/app/Dialer -- InCallServiceImpl
@Override public void onCallAdded(Call call) { InCallPresenter.getInstance().onCallAdded(call);}
- packages/app/Dialer -- InCallPresenter
public void onCallAdded(final android.telecom.Call call) {
if (shouldAttemptBlocking(call)) {
maybeBlockCall(call);
} else {
mCallList.onCallAdded(call);
}
}
@Override public void onIncomingCall(Call call) { InCallState newState = startOrFinishUi(InCallState.INCOMING); InCallState oldState = mInCallState; for (IncomingCallListener listener : mIncomingCallListeners) { listener.onIncomingCall(oldState, mInCallState, call); } }
The above is the general process of 7.0 incoming calls. The next article will explain the incoming call UI display process.