(O)Telephony分析之通话流程分析(三)拨打电话流程分析(下)

拨打电话流程分析:从CallsManager的startOutgoingCall方法入手
本文深入探讨了电话流程,重点解析了 CallsManager 的 startOutgoingCall 方法,揭示拨打电话过程的关键步骤,涉及 Telephony 模块的技术细节。

三.Call的建立和传送

先来看下代码

static void processOutgoingCallIntent(
        Context context,
        CallsManager callsManager,
        Intent intent) {
    ......
    // 拨打电话状态依旧为语音通话
    final int videoState = intent.getIntExtra( TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
            VideoProfile.STATE_AUDIO_ONLY);
    clientExtras.putInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState);

    // 是否是系统默认电话应用
    final boolean isPrivilegedDialer = intent.getBooleanExtra(KEY_IS_PRIVILEGED_DIALER, false);

    boolean fixedInitiatingUser = fixInitiatingUserIfNecessary(context, intent);
    ......
    UserHandle initiatingUser = intent.getParcelableExtra(KEY_INITIATING_USER);

    // Send to CallsManager to ensure the InCallUI gets kicked off before the broadcast returns
    // 调用CallsManager的startOutgoingCall方法,初始化Call对象
    Call call = callsManager
            .startOutgoingCall(handle, phoneAccountHandle, clientExtras, initiatingUser);

    if (call != null) {
        // Asynchronous calls should not usually be made inside a BroadcastReceiver because once
        // onReceive is complete, the BroadcastReceiver's process runs the risk of getting
        // killed if memory is scarce. However, this is OK here because the entire Telecom
        // process will be running throughout the duration of the phone call and should never
        // be killed.
        NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster(
                context, callsManager, call, intent, callsManager.getPhoneNumberUtilsAdapter(),
                isPrivilegedDialer);
        final int result = broadcaster.processIntent();
				......
    }
}
此处主要是做了两件事
1)调用CallsManager的startOutgoingCall方法,初始化或者复用Call
2)初始化NewOutgoingCallIntentBroadcaster对象,并调用其processIntent方法

(一)CallsManager的startOutgoingCall方法分析
先查看一下其代码

Call startOutgoingCall(Uri handle, PhoneAccountHandle phoneAccountHandle, Bundle extras,
        UserHandle initiatingUser) {
    boolean isReusedCall = true;
    Call call = reuseOutgoingCall(handle);

    // Create a call with original handle. The handle may be changed when the call is attached
    // to a connection service, but in most cases will remain the same.
    if (call == null) {
        call = new Call(getNextCallId(), mContext,
                this,
                mLock,
                mConnectionServiceRepository,
                mContactsAsyncHelper,
                mCallerInfoAsyncQueryFactory,
                mPhoneNumberUtilsAdapter,
                handle,
                null /* gatewayInfo */,
                null /* connectionManagerPhoneAccount */,
                null /* phoneAccountHandle */,
                Call.CALL_DIRECTION_OUTGOING /* callDirection */,
                false /* forceAttachToExistingConnection */,
                false /* isConference */
        );
        call.initAnalytics();

        call.setInitiatingUser(initiatingUser);

        isReusedCall = false;
    }
		......

    List<PhoneAccountHandle> accounts = constructPossiblePhoneAccounts(handle, initiatingUser);
    Log.v(this, "startOutgoingCall found accounts = " + accounts);
		......

    if (phoneAccountHandle == null && accounts.size() > 0) {
        // No preset account, check if default exists that supports the URI scheme for the
        // handle and verify it can be used.
        if(accounts.size() > 1) {
            PhoneAccountHandle defaultPhoneAccountHandle =
                    mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(handle.getScheme(), initiatingUser);
            if (defaultPhoneAccountHandle != null &&
                    accounts.contains(defaultPhoneAccountHandle)) {
                phoneAccountHandle = defaultPhoneAccountHandle;
            }
        } else {
            // Use the only PhoneAccount that is available
            phoneAccountHandle = accounts.get(0);
        }

    }

    call.setTargetPhoneAccount(phoneAccountHandle);
    ......
    // Do not support any more live calls.  Our options are to move a call to hold, disconnect
    // a call, or cancel this call altogether. If a call is being reused, then it has already
    // passed the makeRoomForOutgoingCall check once and will fail the second time due to the
    // call transitioning into the CONNECTING state.
    if (!isPotentialInCallMMICode && (!isReusedCall &&
            !makeRoomForOutgoingCall(call, call.isEmergencyCall()))) {
        // just cancel at this point.
        Log.i(this, "No remaining room for outgoing call: %s", call);
        if (mCalls.contains(call)) {
            // This call can already exist if it is a reused call,
            // See {@link #reuseOutgoingCall}.
            call.disconnect();
        }
        return null;
    }

    boolean needsAccountSelection = phoneAccountHandle == null && accounts.size() > 1 &&
            !call.isE
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值