Android 8.0来电流程分析(三)

Telecomm Service
这里我们可以看出CallsManager的管理作用,创建Calls并添加监听,在完成Call的相关初始化后进行进一步处理,其实就是传递消息到别的的地方去。
1.那么继续到CallsManager中跟进

    @Override
    public void onSuccessfulIncomingCall(Call incomingCall) {
        Log.d(this, "onSuccessfulIncomingCall");
        if (incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE)) {
            Log.i(this, "Skipping call filtering due to ECBM");
            onCallFilteringComplete(incomingCall, new CallFilteringResult(true, false, true, true));
            return;
        }

        //迭代器模式
        List filters = new ArrayList<>();
        filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
        filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter()));
        filters.add(new CallScreeningServiceFilter(mContext, this, mPhoneAccountRegistrar,
                mDefaultDialerCache, new ParcelableCallUtils.Converter(), mLock));

        //IncomingCallFilter创建并执行 performFiltering
        new IncomingCallFilter(mContext, this, incomingCall, mLock,
                mTimeoutsAdapter, filters).performFiltering();
    }

2.这里用到了迭代器模式,一个来电触发三个对象的处理,
最后创建一个IncomingCallFilter并调用performFiltering

    public void performFiltering() {
        Log.addEvent(mCall, LogUtils.Events.FILTERING_INITIATED);
        for (CallFilter filter : mFilters) {
            //遍历调用,依次执行异步查询方法
            filter.startFilterLookup(mCall, this);
        }
        // synchronized to prevent a race on mResult and to enter into Telecom.
        mHandler.postDelayed(new Runnable("ICF.pFTO", mTelecomLock) { // performFiltering time-out
            @Override
            public void loggedRun() {
                if (mIsPending) {
                    //超时处理的方法
                    Log.i(IncomingCallFilter.this, "Call filtering has timed out.");
                    Log.addEvent(mCall, LogUtils.Events.FILTERING_TIMED_OUT);
                    //回CallsManager中的监听事件
                    mListener.onCallFilteringComplete(mCall, mResult);
                    mIsPending = false;
                }
            }
        }.prepare(), mTimeoutsAdapter.getCallScreeningTimeoutMillis(mContext.getContentResolver()));
    }

3.如果没有超时则在异步查询结束后,会通过回调方法将CallFilterResult传回onCallFilteringComplete.

    public void onCallFilteringComplete(Call call, CallFilteringResult result) {
        synchronized (mTelecomLock) { // synchronizing to prevent race on mResult
            mNumPendingFilters--;
            //对之前三种过滤查询结果进行运算,满足条件才可以通话
            //这里不对三种过滤器具体分析,有兴趣的可以进一步分析
            mResult = result.combine(mResult);
            if (mNumPendingFilters == 0) {
                // synchronized on mTelecomLock to enter into Telecom.
                mHandler.post(new Runnable("ICF.oCFC", mTelecomLock) {
                    @Override
                    public void loggedRun() {
                        if (mIsPending) {
                            Log.addEvent(mCall, LogUtils.Events.FILTERING_COMPLETED, mResult);
                            //继续回调
                            mListener.onCallFilteringComplete(mCall, mResult);
                            mIsPending = false;
                        }
                    }
                }.prepare());
            }
        }
    }

4.回到CallsManager中进行onCallFilteringComplete处理

    @Override
    public void onCallFilteringComplete(Call incomingCall, CallFilteringResult result) {
        ...
        if (incomingCall.getState() != CallState.DISCONNECTED &&
                incomingCall.getState() != CallState.DISCONNECTING &&
                incomingCall.getState() != CallState.ACTIVE) {
            //设置Call状态为Ring
            setCallState(incomingCall, CallState.RINGING,
                    result.shouldAllowCall ? "successful incoming call" : "blocking call");
        } else {
            Log.i(this, "onCallFilteringCompleted: call already disconnected.");
            return;
        }

        if (result.shouldAllowCall) {
            if (MtkUtil.isInSingleVideoCallMode(incomingCall)) {
                ...
            }

            if (hasMaximumManagedRingingCalls(incomingCall)) {
                if (shouldSilenceInsteadOfReject(incomingCall)) {
                    incomingCall.silence();
                } else {
                    Log.i(this, "onCallFilteringCompleted: Call rejected! " +
                            "Exceeds maximum number of ringing calls.");
                    rejectCallAndLog(incomingCall);
                }

            } else {
                //添加Call
                addCall(incomingCall);
            }
        } else {
            if (result.shouldReject) {
                Log.i(this, "onCallFilteringCompleted: blocked call, rejecting.");
                incomingCall.reject(false, null);
            }
            if (result.shouldAddToCallLog) {
                Log.i(this, "onCallScreeningCompleted: blocked call, adding to call log.");
                if (result.shouldShowNotification) {
                    Log.w(this, "onCallScreeningCompleted: blocked call, showing notification.");
                }
                //添加通话记录
                mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE,
                        result.shouldShowNotification);
            } else if (result.shouldShowNotification) {
                Log.i(this, "onCallScreeningCompleted: blocked call, showing notification.");
                mMissedCallNotifier.showMissedCallNotification(
                        new MissedCallNotifier.CallInfo(incomingCall));
            }
        }
    }

5.正常的话会将Call状态置为ring,并且添加Call,继续跟进addCall

    private void addCall(Call call) {

        call.addListener(this);
        mCalls.add(call);

        // Specifies the time telecom finished routing the call. This is used by the dialer for
        // analytics.
        Bundle extras = call.getIntentExtras();
        extras.putLong(TelecomManager.EXTRA_CALL_TELECOM_ROUTING_END_TIME_MILLIS,
                SystemClock.elapsedRealtime());

        updateCanAddCall();
        // onCallAdded for calls which immediately take the foreground (like the first call).
        for (CallsManagerListener listener : mListeners) {
            //通知监听Call添加的观察者
            listener.onCallAdded(call);
        }

        /// M: single video call mode
        if (MtkUtil.isInSingleVideoCallMode(call)) {
            for (Call c : mCalls) {
                c.refreshConnectionCapabilities();
            }
        }

    }

6.查看监听Call添加的观察者
在CallsManager构造函数初始化的时候添加了一些列观察者,还有就是通过addListener去添加的。

        mListeners.add(mInCallWakeLockController);
        mListeners.add(statusBarNotifier);
        mListeners.add(mCallLogManager);
        mListeners.add(mPhoneStateBroadcaster);
        mListeners.add(mInCallController);
        mListeners.add(mCallAudioManager);
        mListeners.add(missedCallNotifier);
        mListeners.add(mHeadsetMediaButton);
        mListeners.add(mProximitySensorManager);
        ...
        mListeners.add(new CallConnectedVibrator(mContext));

这里我们继续跟进mInCallController,

    @Override
    public void onCallAdded(Call call) {
        if (!isBoundAndConnectedToServices()) {
            bindToServices(call);
        } else {
            // We are bound, and we are connected.
            adjustServiceBindingsForEmergency();

            // This is in case an emergency call is added while there is an existing call.
            mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(call,
                    mCallsManager.getCurrentUserHandle());

            //添加Call
            addCall(call);

            List componentsUpdated = new ArrayList<>();
            for (Map.Entry entry : mInCallServices.entrySet()) {
                InCallServiceInfo info = entry.getKey();

                if (call.isExternalCall() && !info.isExternalCallsSupported()) {
                    continue;
                }

                if (call.isSelfManaged() && !info.isSelfManagedCallsSupported()) {
                    continue;
                }

                // Only send the RTT call if it's a UI in-call service
                boolean includeRttCall = info.equals(mInCallServiceConnection.getInfo());

                componentsUpdated.add(info.getComponentName());
                IInCallService inCallService = entry.getValue();

                ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
                        true /* includeVideoProvider */, mCallsManager.getPhoneAccountRegistrar(),
                        info.isExternalCallsSupported(), includeRttCall);
                try {
                    //AIDL调用远程的addCall方法
                    inCallService.addCall(parcelableCall);
                } catch (RemoteException ignored) {
                }
            }
            Log.i(this, "Call added to components: %s", componentsUpdated);
        }
    }

Telecomm Framework
7.继续查找IInCallService的实现,跟进addCall方法

    /** Manages the binder calls so that the implementor does not need to deal with it. */
    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();
        }

8.继续跟进MSG_SET_IN_CALL_ADAPTER消息的处理

        public void handleMessage(Message msg) {

            switch (msg.what) {
                ...
                case MSG_ADD_CALL:
                    mPhone.internalAddCall((ParcelableCall) msg.obj);
                ...

9.继续跟进internalAddCall

    final void internalAddCall(ParcelableCall parcelableCall) {
        //创建Call
        Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,
                parcelableCall.getState(), mCallingPackage, mTargetSdkVersion);

        mCallByTelecomCallId.put(parcelableCall.getId(), call);
        //添加到列表中
        mCalls.add(call);
        checkCallTree(parcelableCall);
        call.internalUpdate(parcelableCall, mCallByTelecomCallId);
        //调用phone的监听者的onCallAdded
        fireCallAdded(call);
     }

    private void fireCallAdded(Call call) {
        for (Listener listener : mListeners) {
            listener.onCallAdded(this, call);
        }
    }    

10.在 InCallService 中handleMessage处理MSG_SET_IN_CALL_ADAPTER消息的时候就注册了监听,这里继续跟进到InCallService中的实现去

private Phone.Listener mPhoneListener = new Phone.Listener()
        ...
        @Override
        public void onCallAdded(Phone phone, Call call) {
            //调用InCallService对象的onCallAdded方法
            InCallService.this.onCallAdded(call);
        }
        ...

可以看到这其实是个空实现,具体实现是在子类中,继续跟进到子类中分析

Dialer
11.查找InCallService的子类

public class InCallServiceImpl extends InCallService 

  @Override
  public void onCallAdded(Call call) {

    if ((CallList.getInstance().getVideoUpgradeRequestCall() != null ||
            CallList.getInstance().getSendingVideoUpgradeRequestCall() != null ||
            /// M: When is cancel upgrade progress,we can't add another call in calllist. @{
            CallList.getInstance().getSendingCancelUpgradeRequestCall() != null)
            ///@}
            && !isEmergency(call)) {
       ...
    } else {
        InCallPresenter.getInstance().onCallAdded(call);
    }
  }

跟踪到这里可以看到其所在目录是Dialer下的inCallUI了,这就到dialer层了,如果查看Diler的清单文件可以发现其有android.telecom.InCallService声明

12.InCallPresenter是InCallUI用于处理通话逻辑的核心类,继续跟进查看onCallAdded方法

  public void onCallAdded(final android.telecom.Call call) {
    LatencyReport latencyReport = new LatencyReport(call);
    if (shouldAttemptBlocking(call)) {
      maybeBlockCall(call, latencyReport);
    } else {
      if (call.getDetails().hasProperty(CallCompat.Details.PROPERTY_IS_EXTERNAL_CALL)) {
        mExternalCallList.onCallAdded(call);
      } else {
        latencyReport.onCallBlockingDone();
        //CallList(Call的维护列表)调用onCallAdded
        mCallList.onCallAdded(mContext, call, latencyReport);
      }
    }

    // Since a call has been added we are no longer waiting for Telecom to send us a call.
    setBoundAndWaitingForOutgoingCall(false, null);
    call.registerCallback(mCallCallback);
  }

13.继续跟进mCallList

  public void onCallAdded(
      final Context context, final android.telecom.Call telecomCall, LatencyReport latencyReport) {
    Trace.beginSection("onCallAdded");
    ...
     if (call.getState() == DialerCall.State.INCOMING
            || call.getState() == DialerCall.State.CALL_WAITING) {
          //来电调用
          onIncoming(call);
        } else {
          dialerCallListener.onDialerCallUpdate();
    }
    ...
}

最终调用其InCall的来电界面,这里就不再继续详细分析了。

本系列的来电显示流程参考了以下博客,
https://www.cnblogs.com/lance2016/p/6035351.html,
结合自己的理解做了一些分析,有错误和缺漏的欢迎指出,可以看到android O对于RIL层往上的Telephony架构的修改不大。
来电流程时序图
Android 8.0来电流程分析(三)_第1张图片

你可能感兴趣的:(Telephony,Telephony源码分析)