Android7.0去电流程源码分析(二)

上篇博客分析到调用broadcastIntent,这里接着分析
1.接着查看NewOutgoingCallIntentBroadcaster.java文件中的broadcastIntent方法:

    private void broadcastIntent(
            Intent originalCallIntent,
            String number,
            boolean receiverRequired,
            UserHandle targetUser) {
        //要发送的广播
        Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
        if (number != null) {
            broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
        }

        // Force receivers of this broadcast intent to run at foreground priority because we
        // want to finish processing the broadcast intent as soon as possible.
        broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        Log.v(this, "Broadcasting intent: %s.", broadcastIntent);
        Log.p(TAG, "broadcastIntent(): EXTRA_PHONE_NUMBER " + number);

        checkAndCopyProviderExtras(originalCallIntent, broadcastIntent);


        mContext.sendOrderedBroadcastAsUser(
                broadcastIntent,
                targetUser,
                android.Manifest.permission.PROCESS_OUTGOING_CALLS,
                AppOpsManager.OP_PROCESS_OUTGOING_CALLS,
                receiverRequired ? new NewOutgoingCallBroadcastIntentReceiver() : null,
                null,  // scheduler
                Activity.RESULT_OK,  // initialCode
                number,  // initialData: initial value for the result data (number to be modified)
                null);  // initialExtras
    }

2.这里看到发送一个Intent.ACTION_NEW_OUTGOING_CALL广播,对于非紧急拨号,才会生成一个
NewOutgoingCallBroadcastIntentReceive 实例来接收该广播,我们跟进onReceive方法

    public class NewOutgoingCallBroadcastIntentReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            try {
                    ...


                    GatewayInfo gatewayInfo = getGateWayInfoFromIntent(intent, resultHandleUri);
                    mCall.setNewOutgoingCallIntentBroadcastIsDone();
                    mCallsManager.placeOutgoingCall(mCall, resultHandleUri, gatewayInfo,
                            mIntent.getBooleanExtra(
                                    TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false),
                            mIntent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
                                    VideoProfile.STATE_AUDIO_ONLY));
                }
            } 
        }
    }

3.NewOutgoingCallBroadcastIntentReceiver内部做了一些处理后最后还是调用到CallsManager的placeOutgoingCall方法,所以该方法是去电的关键方法继续看callManager.placeOutgoingCall方法

    public void placeOutgoingCall(Call call, Uri handle, GatewayInfo gatewayInfo,
            boolean speakerphoneOn, int videoState) {
        ...

        call.setHandle(uriHandle);
        call.setGatewayInfo(gatewayInfo);

        final boolean useSpeakerWhenDocked = mContext.getResources().getBoolean(
                R.bool.use_speaker_when_docked);
        final boolean useSpeakerForDock = isSpeakerphoneEnabledForDock();
        final boolean useSpeakerForVideoCall = isSpeakerphoneAutoEnabledForVideoCalls(videoState);

        // Auto-enable speakerphone if the originating intent specified to do so, if the call
        // is a video call, of if using speaker when docked
        call.setStartWithSpeakerphoneOn(speakerphoneOn || useSpeakerForVideoCall
                || (useSpeakerWhenDocked && useSpeakerForDock));
        call.setVideoState(videoState);


        if (call.isEmergencyCall()) {
            new AsyncEmergencyContactNotifier(mContext).execute();
        }

        final boolean requireCallCapableAccountByHandle = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_requireCallCapableAccountForHandle);

        if (call.getTargetPhoneAccount() != null || call.isEmergencyCall()) {
            if (!call.isEmergencyCall()) {
                updateLchStatus(call.getTargetPhoneAccount().getId());
            }
            //Block to initiate Emregency call now as the current active call
            //is not yet disconnected.
            if (mPendingMOEmerCall == null) {
            // If the account has been set, proceed to place the outgoing call.
            // Otherwise the connection will be initiated when the account is set by the user.
                // +++ Delay 1500 ms to speed up launch inCallUI
                int time = android.os.SystemProperties.getInt("persist.asus.tellril", 0);
                Log.d(TAG, "placeOutgoingCall(): persist.asus.tellril time = " + time);
                if (time == 0 ||call.isEmergencyCall()) {
                    Log.d(TAG, "placeOutgoingCall(): no delay to startCreateConnection");
                    //创建连接
                    call.startCreateConnection(mPhoneAccountRegistrar);
                } else {
                    new android.os.CountDownTimer(time, time) {
                        @Override
                        public void onTick(long millisUntilFinished) {
                        }

                        @Override
                        public void onFinish() {
                            Log.d(TAG, "placeOutgoingCall(): delay time to startCreateConnection");
                            call.startCreateConnection(mPhoneAccountRegistrar);
                        }
                    }.start();
                }
            }
                // --- Delay 1500 ms to speed up launch inCallUI
        } else if (mPhoneAccountRegistrar.getCallCapablePhoneAccounts(
                requireCallCapableAccountByHandle ? call.getHandle().getScheme() : null, false,
                call.getInitiatingUser()).isEmpty()) {
            // If there are no call capable accounts, disconnect the call.
            markCallAsDisconnected(call, new DisconnectCause(DisconnectCause.CANCELED,
                    "No registered PhoneAccounts"));
            markCallAsRemoved(call);
        }
    }

4.如果是Video Call或者是紧急呼叫的话会做一些额外操作,如果条件满足的话会调用到startCreateConnection建立连接

    void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar) {
        Log.d(TAG, "startCreateConnection(): phoneAccountRegistrar " + phoneAccountRegistrar);
        if (mCreateConnectionProcessor != null) {
            Log.w(this, "mCreateConnectionProcessor in startCreateConnection is not null. This is" +
                    " due to a race between NewOutgoingCallIntentBroadcaster and " +
                    "phoneAccountSelected, but is harmlessly resolved by ignoring the second " +
                    "invocation.");
            return;
        }
        mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this,
                phoneAccountRegistrar, mContext);
        mCreateConnectionProcessor.process();
    }

5.新建了一个CreateConnectionProcessor对象,处理连接请求

    @VisibleForTesting
    public void process() {
        Log.v(this, "process");
        clearTimeout();
        mAttemptRecords = new ArrayList<>();
        if (mCall.getTargetPhoneAccount() != null) {
            Log.d(this, "process mCall.getTargetPhoneAccount() = " + mCall.getTargetPhoneAccount());
            mAttemptRecords.add(new CallAttemptRecord(
                    mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount()));
        } else {
            Log.d(this, "process mCall.getTargetPhoneAccount() is null");
        }
        adjustAttemptsForConnectionManager();
        adjustAttemptsForEmergency(mCall.getTargetPhoneAccount());
        mAttemptRecordIterator = mAttemptRecords.iterator();
        attemptNextPhoneAccount();
    }

6.进入attemptNextPhoneAccount方法

    private void attemptNextPhoneAccount() {
        Log.v(this, "attemptNextPhoneAccount");
        CallAttemptRecord attempt = null;
        if (mAttemptRecordIterator.hasNext()) {
            attempt = mAttemptRecordIterator.next();

            if (!mPhoneAccountRegistrar.phoneAccountRequiresBindPermission(
                    attempt.connectionManagerPhoneAccount)) {
                Log.w(this,
                        "Connection mgr does not have BIND_TELECOM_CONNECTION_SERVICE for "
                                + "attempt: %s", attempt);
                attemptNextPhoneAccount();
                return;
            }

            // If the target PhoneAccount differs from the ConnectionManager phone acount, ensure it
            // also requires the BIND_TELECOM_CONNECTION_SERVICE permission.
            if (!attempt.connectionManagerPhoneAccount.equals(attempt.targetPhoneAccount) &&
                    !mPhoneAccountRegistrar.phoneAccountRequiresBindPermission(
                            attempt.targetPhoneAccount)) {
                Log.w(this,
                        "Target PhoneAccount does not have BIND_TELECOM_CONNECTION_SERVICE for "
                                + "attempt: %s", attempt);
                attemptNextPhoneAccount();
                return;
            }
        }

        if (mCallResponse != null && attempt != null) {
            Log.i(this, "Trying attempt %s", attempt);
            PhoneAccountHandle phoneAccount = attempt.connectionManagerPhoneAccount;
              // 获取ConnectionServiceWrapper对象 
            mService = mRepository.getService(phoneAccount.getComponentName(),
                    phoneAccount.getUserHandle());
            if (mService == null) {
                Log.i(this, "Found no connection service for attempt %s", attempt);
                attemptNextPhoneAccount();
            } else {
                mConnectionAttempt++;
                mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount);
                mCall.setTargetPhoneAccount(attempt.targetPhoneAccount);
                mCall.setConnectionService(mService);
                setTimeoutIfNeeded(mService, attempt);
                  // 已成功获取ConnectionServiceWrapper对象,创建连接
                mService.createConnection(mCall, this);
            }
        } else {
            Log.v(this, "attemptNextPhoneAccount, no more accounts, failing");
            DisconnectCause disconnectCause = mLastErrorDisconnectCause != null ?
                    mLastErrorDisconnectCause : new DisconnectCause(DisconnectCause.ERROR);
            notifyCallConnectionFailure(disconnectCause);
        }
    }

这里主要的两步操作是获取ConnectionServiceWrapper对象,并调用createConnection方法创建连接。那么我们继续跟进 ConnectionServiceWrapper。

/**
 * Wrapper for {@link IConnectionService}s, handles binding to {@link IConnectionService} and keeps
 * track of when the object can safely be unbound. Other classes should not use
 * {@link IConnectionService} directly and instead should use this class to invoke methods of
 * {@link IConnectionService}.
 */
@VisibleForTesting
public class ConnectionServiceWrapper extends ServiceBinder {
实际上就是一个包装了绑定远程服务的代理类,看看它的构造方法
    ConnectionServiceWrapper(
            ComponentName componentName,
            ConnectionServiceRepository connectionServiceRepository,
            PhoneAccountRegistrar phoneAccountRegistrar,
            CallsManager callsManager,
            Context context,
            TelecomSystem.SyncRoot lock,
            UserHandle userHandle) {
        super(ConnectionService.SERVICE_INTERFACE, componentName, context, lock, userHandle);
        mConnectionServiceRepository = connectionServiceRepository;
        phoneAccountRegistrar.addListener(new PhoneAccountRegistrar.Listener() {
            // TODO -- Upon changes to PhoneAccountRegistrar, need to re-wire connections
            // To do this, we must proxy remote ConnectionService objects
        });
        mPhoneAccountRegistrar = phoneAccountRegistrar;
        mCallsManager = callsManager;
        mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
    }

这里的ConnectionService.SERVICE_INTERFACE就是”android.telecom.ConnectionService”也就是它所绑定的远程服务的action,获取该对象后调用createConnection方法

7.继续跟进createConnection方法

    /**
     * Creates a new connection for a new outgoing call or to attach to an existing incoming call.
     */
    @VisibleForTesting
    public void createConnection(final Call call, final CreateConnectionResponse response) {
        Log.d(this, "createConnection(%s) via %s.", call, getComponentName());
        BindCallback callback = new BindCallback() {
            @Override
            public void onSuccess() {//最终创建成功后会回到这里的回调方法
                String callId = mCallIdMapper.getCallId(call);
                mPendingResponses.put(callId, response);

                GatewayInfo gatewayInfo = call.getGatewayInfo();
                Bundle extras = call.getIntentExtras();
                if (gatewayInfo != null && gatewayInfo.getGatewayProviderPackageName() != null &&
                        gatewayInfo.getOriginalAddress() != null) {
                    extras = (Bundle) extras.clone();
                    extras.putString(
                            TelecomManager.GATEWAY_PROVIDER_PACKAGE,
                            gatewayInfo.getGatewayProviderPackageName());
                    extras.putParcelable(
                            TelecomManager.GATEWAY_ORIGINAL_ADDRESS,
                            gatewayInfo.getOriginalAddress());
                }

                Log.event(call, Log.Events.START_CONNECTION, Log.piiHandle(call.getHandle()));
                try {
                    mServiceInterface.createConnection(
                            call.getConnectionManagerPhoneAccount(),
                            callId,
                            new ConnectionRequest(
                                    call.getTargetPhoneAccount(),
                                    call.getHandle(),
                                    extras,
                                    call.getVideoState(),
                                    callId),
                            call.shouldAttachToExistingConnection(),
                            call.isUnknown());
                } catch (RemoteException e) {
                    Log.e(this, e, "Failure to createConnection -- %s", getComponentName());
                    mPendingResponses.remove(callId).handleCreateConnectionFailure(
                            new DisconnectCause(DisconnectCause.ERROR, e.toString()));
                }
            }

            @Override
            public void onFailure() {
                Log.e(this, new Exception(), "Failure to call %s", getComponentName());
                response.handleCreateConnectionFailure(new DisconnectCause(DisconnectCause.ERROR));
            }
        };
        //将callback和call传入
        mBinder.bind(callback, call);
    }

8.我们看到其创建了BindCallback ,然后使用mBinder调用bind方法。这里的mBinder对象是ConnectionServiceWrapper的父类ServiceBinder里的一个内部类,继续查看其bind调用。

        void bind(BindCallback callback, Call call) {
            Log.d(ServiceBinder.this, "bind()");

            // Reset any abort request if we're asked to bind again.
            clearAbort();

            if (!mCallbacks.isEmpty()) {
                // Binding already in progress, append to the list of callbacks and bail out.
                mCallbacks.add(callback);
                return;
            }

            mCallbacks.add(callback);
            if (mServiceConnection == null) {
                Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);
                //创建ServiceConnection服务
                ServiceConnection connection = new ServiceBinderConnection(call);

                Log.event(call, Log.Events.BIND_CS, mComponentName);
                final int bindingFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
                final boolean isBound;
                //绑定服务
                if (mUserHandle != null) {
                    isBound = mContext.bindServiceAsUser(serviceIntent, connection, bindingFlags,
                            mUserHandle);
                } else {
                    isBound = mContext.bindService(serviceIntent, connection, bindingFlags);
                }
                if (!isBound) {
                    handleFailedConnection();
                    return;
                }
            } else {
                Log.d(ServiceBinder.this, "Service is already bound.");
                Preconditions.checkNotNull(mBinder);
                handleSuccessfulConnection();
            }
        }

9.这里我们看到主要是创建一个服务,然后调用mContext.bindService进行绑定服务,
10.跟进ServiceBinderConnection继续分析onServiceConnected。

    private final class ServiceBinderConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder binder) {
            try {
                Log.startSession("SBC.oSC");
                synchronized (mLock) {
                    Log.i(this, "Service bound %s", componentName);

                    Log.event(mCall, Log.Events.CS_BOUND, componentName);
                    mCall = null;

                    // Unbind request was queued so unbind immediately.
                    if (mIsBindingAborted) {
                        clearAbort();
                        logServiceDisconnected("onServiceConnected");
                        mContext.unbindService(this);
                        handleFailedConnection();
                        return;
                    }

                    mServiceConnection = this;
                    //
                    setBinder(binder);
                    handleSuccessfulConnection();
                }
            } finally {
                Log.endSession();
            }
        }

11.看到设置了binder,设置成功后调用handleSucessfulCOnnection方法,继续根据setBinder看看。

    private void setBinder(IBinder binder) {
        if (mBinder != binder) {
            if (binder == null) {
                removeServiceInterface();
                mBinder = null;
                for (Listener l : mListeners) {
                    l.onUnbind(this);
                }
            } else {
                mBinder = binder;
                setServiceInterface(binder);
            }
        }
    }

12.这里我们看到setServiceInterface只是个接口,回到其子类ConnectionServiceWrapper.java中查看具体实现

    /** {@inheritDoc} */
    @Override
    protected void setServiceInterface(IBinder binder) {
        Log.d(TAG, "setServiceInterface(): binder " + binder);
        mServiceInterface = IConnectionService.Stub.asInterface(binder);
        Log.v(this, "Adding Connection Service Adapter.");
        addConnectionServiceAdapter(mAdapter);
    }

13.看到其获取远程IConnectionService服务的aidl接口,然后我们继续回到10跟踪handleSuccessfulConnection方法

     private void handleSuccessfulConnection() {
        for (BindCallback callback : mCallbacks) {
            callback.onSuccess();
        }
        mCallbacks.clear();
    }

14.我们看到其调用了callback.onSuccess(),而这个callback其实是我们之前传参带入后进行初始化的,就回到7的onSucess方法中继续调用。

总结7-14的分析, mBinder.bind(callback, call)该方法调用时会创建一个连接,封装了绑定远程服务的一些操作,若当前还未绑定服务,则直接调用bindService获取远程服务的aidl接口,成功获取到aidl接口后将其赋值给mServiceInterface,当绑定完成后会调用handleSuccessFulConnection方法,其回调了CallBack的onSuccess方法。至此就完成了服务的创建及连接

接下来的流程就到了远程服务的createConnection实现了。

根据以上源码分析的流程整理的时序图如下,如果不清楚可以另存为到本地查看。
这里写图片描述

结合上一章的分析的第五步进入telecomManager到这章的末尾分析来看
其实在telecomManager中获取(ITelecomService.aidl)TelecomService后一路调用,期间有进行一些过滤等操作,最终其实主要做的就是是通过AIDL的调用去获取底层的服务以创建一个连接通道。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值