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

来源:互联网 发布:淘宝卖家论坛首页 编辑:程序博客网 时间:2024/05/22 13:23

上篇博客分析到调用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}. */@VisibleForTestingpublic 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的调用去获取底层的服务以创建一个连接通道。

原创粉丝点击