Android N 拨号流程分析

文章出处:http://blog.csdn.net/xiaoxsen/article/details/73888758

最近一直在赶项目,博客有段时间没更新文章了,今天来看一下Android 7.0的拨号流程分析,先看看拨号的主界面:
这里写图片描述                     这里写图片描述

  拨号主界面为DialtactsActivity,当用户点击拨号键盘按钮(DialtactsActivity的floating_action_button),弹出拨号盘,输入完电话号码,再点击拨号按钮,此时打电话的流程开始,因此打电话流程的入口就在DialpadFragment.Java(packages\apps\dialer\src\com\android\dialer\dialpad)的onClick()方法

public void onClick(View view) {
   switch (view.getId()) {
      case R.id.dialpad_floating_action_button:
      mHaptic.vibrate();//按键震动
      handleDialButtonPressed();//处理拨号
      ...
}

  在handleDialButtonPressed()方法里,会先判断用户是否已输入号码,假如号码为空,则调用handleDialButtonClickWithEmptyDigits()方法显示上一次拨打过的号码。然后第一次获取到要拨打的number,在这里可以对number做一些判断或者自定义处理。

if (isDigitsEmpty()) { // No number entered.
    handleDialButtonClickWithEmptyDigits();
} else {
    inal String number = mDigits.getText().toString();
    ......
    DialerUtils.startActivityWithErrorToast(getActivity(), intent);
}

继续往下走看startActivityWithErrorToast()方法,内部判断了一些是否有拨号权限的判断后,最后调用TelecomManagerCompat的placeCall()方法

 public static void placeCall(@Nullable Activity activity,
            @Nullable TelecomManager telecomManager, @Nullable Intent intent) {
        if (activity == null || telecomManager == null || intent == null) {
            return;
        }
        if (CompatUtils.isMarshmallowCompatible()) {
            telecomManager.placeCall(intent.getData(), intent.getExtras());
            return;
        }
        activity.startActivityForResult(intent, 0);
    }

  该方法里做了一些判空操作,当我们的版本大于等于6.0时就调用telecomManager.placeCall()方法,否则就直接通过startActivity去执行intent。因为我们这里分析7.0的流程,所以继续看telecomManager的placeCall()方法。

public void placeCall(Uri address, Bundle extras) {
        ITelecomService service = getTelecomService();
        ......
            try {
                service.placeCall(address, extras == null ? new Bundle() : extras,
                        mContext.getOpPackageName());
            } catch (RemoteException e) {
                Log.e(TAG, "Error calling ITelecomService#placeCall", e);
            }
        }
    }

  继续调用ITelecomService的placeCall()方法处理流程,这个是aidl调用。TelecomServiceImpl里的mBinderImpl变量是ITelecomService的具体实现类,所以我们继续查看mBinderImpl中的placeCall()方法。

@Override
public void placeCall(Uri handle, Bundle extras, String callingPackage) {
    mUserCallIntentProcessorFactory.create(mContext, userHandle)
        .processIntent(intent, callingPackage, hasCallAppOp && hasCallPermission);
}

  工厂模式创建了一个UserCallIntentProcessor对象,UserCallIntentProcessor类从字面上看应该就是专门用来处理用例的呼叫intent的,并调用其processIntent方法去处理拨号流程,接着查看processIntent()方法。

public void processIntent(Intent intent, String callingPackageName,
            boolean canCallNonEmergency) {
        String action = intent.getAction();
        if (Intent.ACTION_CALL.equals(action) ||
                Intent.ACTION_CALL_PRIVILEGED.equals(action) ||
                Intent.ACTION_CALL_EMERGENCY.equals(action)) {
            processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency);
        }
    }

  继续看processOutgoingCallIntent方法,该方法主要还是判断当前状态以及输入值得合法性,后面直接调用sendBroadcastReceiver

private void processOutgoingCallIntent(Intent intent, String callingPackageName,boolean canCallNonEmergency) {
      ......
      sendBroadcastToReceiver(intent);
    }

发送广播给PrimaryCallReceiver

private boolean sendBroadcastToReceiver(Intent intent) {
        intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, false);
        intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        intent.setClass(mContext, PrimaryCallReceiver.class);
        Log.d(this, "Sending broadcast as user to CallReceiver");
        mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
        return true;
}

PrimaryCallReceiver类接收到了广播会调用onReceive方法。

@Override
public void onReceive(Context context, Intent intent) {
    getTelecomSystem().getCallIntentProcessor().processIntent(intent)
}

  从该方法可以看出,通过调用getTelecomSystem方法返回一个TelecomSystem对象,然后调用了getCallIntentProcessor()返回CallIntentProcessor对象,然后调用processIntent方法来处理我们发出的广播。

public void processIntent(Intent intent) {
    final boolean isUnknownCall = intent.getBooleanExtra(KEY_IS_UNKNOWN_CALL, false);
    if (isUnknownCall) {
        processUnknownCallIntent(mCallsManager, intent);
    } else {
        processOutgoingCallIntent(mContext, mCallsManager, intent);
    }
}

通过isUnknowCall来判断是不是未知的呼叫。

static void processOutgoingCallIntent(
            Context context,
            CallsManager callsManager,
            Intent intent) {
            ......
            Call call = callsManager
            .startOutgoingCall(handle, phoneAccountHandle, clientExtras, initiatingUser);
            NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster(
                    context, callsManager, call, intent, new PhoneNumberUtilsAdapterImpl(),
                    isPrivilegedDialer);
            final int result = broadcaster.processIntent();
            ......
        }
}

  CallIntentProcessor.java的processOutgoingCallIntent()方法里,调用CallsManager.java的startOutgoingCall()方法创建一个Call实例,这就是Call对象的来源,最后传递给NewOutgoingCallIntentBroadcaster,调用processIntent()。我们先来看看startOutgoingCall()方法的

Call startOutgoingCall(Uri handle, PhoneAccountHandle phoneAccountHandle, Bundle extras,
            UserHandle initiatingUser) {
        boolean isReusedCall = true;
        Call call = reuseOutgoingCall(handle);
        // 创建一个call对象
        if (call == null) {
            call = new Call(getNextCallId(), mContext,
                    this,
                    mLock,
                    mConnectionServiceRepository,
                    mContactsAsyncHelper,
                    mCallerInfoAsyncQueryFactory,
                    handle,
                    null /* gatewayInfo */,
                    null /* connectionManagerPhoneAccount */,
                    null /* phoneAccountHandle */,
                    Call.CALL_DIRECTION_OUTGOING /* callDirection */,
                    false /* forceAttachToExistingConnection */,
                    false /* isConference */
            )
        }
        ......
        List<PhoneAccountHandle> accounts = constructPossiblePhoneAccounts(handle, initiatingUser);       // 获取当前激活的卡列表
        if (phoneAccountHandle != null) {
            if (!accounts.contains(phoneAccountHandle)) {
                phoneAccountHandle = null;
            }
        }
        // 获取当前应该使用哪张卡呼出      
         if (phoneAccountHandle == null && accounts.size() > 0 &&         !call.isEmergencyCall()) {
            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); 
         boolean isPotentialInCallMMICode = isPotentialInCallMMICode(handle);
        // 检查当前是否允许呼出该电话,比如当前已有一通电话在正在呼出,
        // 这时候不允许再呼出一路通话(紧急号码除外)
        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.isEmergencyCall();
        if (needsAccountSelection) {
          // 设置当前call状态为等待账户选择
            // This is the state where the user is expected to select an account
            call.setState(CallState.SELECT_PHONE_ACCOUNT, "needs account selection");
            // Create our own instance to modify (since extras may be Bundle.EMPTY)
            extras = new Bundle(extras);
            extras.putParcelableList(android.telecom.Call.AVAILABLE_PHONE_ACCOUNTS, accounts);
        } else {
           // 设置当前call状态为正在连接
            call.setState(CallState.CONNECTING, phoneAccountHandle == null ? "no-handle" : phoneAccountHandle.toString());
        }
        setIntentExtrasAndStartTime(call, extras);
        if((isPotentialMMICode(handle)||isPotentialInCallMMICode)&& !needsAccountSelection){
            call.addListener(this);
         } else if (!mCalls.contains(call)) {
              addCall(call);
            // 添加当前call到call列表
          }
        return call;
}

接着看看addCall方法,调用CallsManagerListener的onCallAdded方法,里面会遍历所有的观察者,并通知回调。

private void addCall(Call call) {
    ......
    listener.onCallAdded(call);
    ......  
    }

CallsManager的构造方法添加所有观察者,其中mInCallController是InCallController对象,InCallController里面封装了与inCallUI相关的方法。

CallsManager(......)
{   ........
    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);
    ......
}

当我们网callManager中添加call时会回调InCallController的onCallAdded()方法:

@Override
public void onCallAdded(Call call) {
    ......    
    if (!isBoundToServices()) {
        bindToServices(call);//正常拨号都走这里
    } else {
        ......
        inCallService.addCall(parcelableCall);//多方通话走这里
        ......
    }
    ...... 
}

我们这里分析正常拨号,继续查看bindToServices()

@VisibleForTesting
public void bindToServices(Call call) {

    dialerInCall = new InCallServiceBindingConnection(defaultDialerComponent);
}

InCallServiceBindingConnection中onServiceConnected会调用onConnected()方法,在
onConnected()中又会调用IncallService的addCall(),然后IncallService的addCall()方法会调用Phone的internalAddCall()方法;

final void internalAddCall(ParcelableCall parcelableCall) {
    ......
    fireCallAdded(call);

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

IncallService中实现了Phone的Listener接口,所以调用IncallService的mPhoneListener对象的onCallAdded()方法,该方法又继续调用IncallService的抽象方法onCallAdded(),IncallServiceImp继承IncallService,实现onCallAdded()方法,具体实现如下:

@Override
public void onCallAdded(Call call) {
    ......
    InCallPresenter.getInstance().onCallAdded(call);
    ......
}

在InCallPresenter的onCallAdded方法中调用了CallList的onCallAdded方法

public void onCallAdded(final android.telecom.Call telecomCall) {

        if (call.getState() == Call.State.INCOMING ||
                call.getState() == Call.State.CALL_WAITING) {
            onIncoming(call, call.getCannedSmsResponses());
        } else {
            onUpdate(call);
        }
    }

  onIncoming()和onUpdate()分别调用CallList.Listener的onIncomingCall()和onCallListChange()方法 IncallPresenter.java和AnswerPresenter继承CallList.Listener接口重写onCallListChange()和onIncomingCall();两个方法都会调用startOrFinishUi()来开启去电和来电的Ui,这样通话界面就会显示出来。继续回到NewOutgoingCallIntentBroadcaster的processIntent()方法看看如何往底层走。

 public int processIntent() {
    ......
    if (isVoicemailNumber) {
        ......
        //如果是语音信箱号码走这里
        mCallsManager.placeOutgoingCall(mCall, handle, null, speakerphoneOn,VideoProfile.STATE_AUDIO_ONLY);
        ......
    }
    ......
    if (Intent.ACTION_CALL.equals(action)) {
        //如果是紧急号码
        if (isPotentialEmergencyNumber) {
        //不是系统电话应用则运行系统系统拨号盘,取消当前拨号,三方应用不能走这里
            if (!mIsDefaultOrSystemPhoneApp) {
                    ......
                    launchSystemDialer(intent.getData());
                    return DisconnectCause.OUTGOING_CANCELED;
                } else {
                    callImmediately = true;
                }
                    ......
            }
    } else if (Intent.ACTION_CALL_EMERGENCY.equals(action)) {
            //如果不是紧急号码则取消拨号
            if (!isPotentialEmergencyNumber) {
                return DisconnectCause.OUTGOING_CANCELED;
            }
            callImmediately = true;
    ......   
    if (callImmediately) {
            ......
            mCallsManager.placeOutgoingCall(mCall, Uri.fromParts(scheme, number, null), null,speakerphoneOn, videoState);
            ......
    }
        //普通电话走这里
        broadcastIntent(intent, number, !callImmediately, targetUser);
        return DisconnectCause.NOT_DISCONNECTED;

}
  broadcastIntent()方法发送一个Intent.ACTION_NEW_OUTGOING_CALL广播,注意传入callImmediately参数,当callImmediately为false的时候才会生成一个NewOutgoingCallBroadcastIntentReceiver实例来接收该广播,也就是非紧急号码,非语音信箱号码就走这里,然后NewOutgoingCallBroadcastIntentReceiver类中还是调用到CallsManager的placeOutgoingCall()方法。继续追踪CallsManager的placeOutgoingCall方法:

public void placeOutgoingCall(Call call, Uri handle, GatewayInfo gatewayInfo,boolean speakerphoneOn, int videoState) {
    .....
    //如果指定了通话账号,或者紧急号码时调用startCreateConnection
    call.startCreateConnection(mPhoneAccountRegistrar);
    //否则断开连接
    .....
}

  在startCreateConnection方法里,主要new了一个专门处理连接的CreateConnectionProcessor对象,然后调用process方法。

void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar) {
        ......
    mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this, phoneAccountRegistrar, mContext);
        mCreateConnectionProcessor.process();
    ......
}

  process方法逻辑也比较简单,主要就是判断call对象中phoneAccount是否为空,然后调用attemptNextPhoneAccount()方法。

void process() {
        ......
        adjustAttemptsForConnectionManager();
        adjustAttemptsForEmergency();
        mAttemptRecordIterator = mAttemptRecords.iterator();
        attemptNextPhoneAccount();
}

  attempNextPhoneAccount方法首先检查是否有BIND_TELECOM_CONNECTION_
SERVICE的权限,紧接着就是通过mRepository.getService方法获取一个ConnectionServiceWrapper类。

 private void attemptNextPhoneAccount() {
        ......
        // 获取ConnectionServiceWrapper对象       
          mService = mRepository.getService(phoneAccount.getComponentName(),
                    phoneAccount.getUserHandle());
        .......
        mService.createConnection(mCall, this);
        .......

}

接着看ConnectionServiceWrapper的createConnection方法

public void createConnection(final Call call, final CreateConnectionResponse response) {
        BindCallback callback = new BindCallback() {
            @Override
            public void onSuccess() {
                ......
                mServiceInterface.createConnection(
                                call.getConnectionManagerPhoneAccount(),
                                callId,
                                new ConnectionRequest(
                                        call.getTargetPhoneAccount(),
                                        call.getHandle(),
                                        extras,
                                        call.getVideoState(),
                                        callId),
                                call.shouldAttachToExistingConnection(),
                                call.isUnknown());
                ......                
            }
            @Override
            public void onFailure() {   
                response.handleCreateConnectionFailure(new DisconnectCause(DisconnectCause.ERROR));
            }
        };
        mBinder.bind(callback, call);
}  

  mBinder是Binder2对象,Binder2是ConnectionServiceWrapper的父类ServiceBinder内部类,所以此处调用的是的ServiceBinder的内部类的Binder2类的bind()方法,先new一个ServiceConnection对象,然后绑定一个远程服务端服务。如果绑定成功的话,在ServiceBinder的内部类ServiceBinderConnection的onServiceConnected()方法就被调用。
在这里做了两件事:
  1).通过setBinder()方法,回调ConnectionServiceWrapper的setServiceInterface()方法,通过mServiceInterface = IConnectionService.Stub.asInterface(binder);
这行代码获取一个远程服务端的对象mServiceInterface 。
  2)、再通过调用handleSuccessfulConnection()方法回调callback 的onSuccess()方法,也就又回到ConnectionServiceWrapper的createConnection()方法里。调用ConnectionService.java里mBinder的createConnection()方法然后通过message传递调用createConnection()方法。

  private void createConnection(
            final PhoneAccountHandle callManagerAccount,
            final String callId,
            final ConnectionRequest request,
            boolean isIncoming,
            boolean isUnknown) {

        Connection connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
                : isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
                : onCreateOutgoingConnection(callManagerAccount, request);
    }

createConnection()方法通过判断是来电还是去电分别创建不同的connection,去电则调用onCreateOutgoingConnection(),TelephonyConnectionService是ConnectionService的实例,所以进入TelephonyConnectionService.java的onCreateOutgoingConnection()方法。

@Override
public Connection onCreateOutgoingConnection(
            PhoneAccountHandle connectionManagerPhoneAccount,
            final ConnectionRequest request) {
        //这里做了很多判断,返回失败的连接(比如拨打号码为空,未指定sim卡,设置为仅4G等)
        ......
        final TelephonyConnection connection =
                createConnectionFor(phone, null, true /* isOutgoing */, request.getAccountHandle(),
                        request.getTelecomCallId(), request.getAddress());
        ......
        //如果上面的都不是则执行这里
        placeOutgoingConnection(connection, phone, request);
}

继续跟踪placeOutgoingConnection()方法处理拨号流程

private void placeOutgoingConnection(
            TelephonyConnection connection, Phone phone, ConnectionRequest request) {
       ......
       originalConnection =
                    phone.dial(number, null, request.getVideoState(), request.getExtras());
       ......

    }

调用Phone的dial()方法后就进入了Telephony Framework层了。Android 7.0中把GSMPhone和CDMAPhone全部集成到GsmCdmaPhone中,继续看GsmCdmaPhone中dial()

 @Override
    public Connection dial(String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)
            throws CallStateException {
                .......
                    //ImsPhone是专门处理VoLTE的一个类
                    if (videoState == VideoProfile.STATE_AUDIO_ONLY) {
                        if (DBG) Rlog.d(LOG_TAG, "Trying IMS PS call");//
                        return imsPhone.dial(dialString, uusInfo, videoState, intentExtras);
                    } else {
                        if (SystemProperties.get("persist.mtk_vilte_support").equals("1")) {
                            //支持VoLTe  Ims ps video call
                            return imsPhone.dial(dialString, uusInfo, videoState, intentExtras);
                        } else {
                            //cs video call
                            return dialInternal(dialString, uusInfo, videoState, intentExtras);
                            /// @}
                        }
                .......
        if (isPhoneTypeGsm()) {
            /// M: CC: For 3G VT only @{
            //return dialInternal(dialString, null, VideoProfile.STATE_AUDIO_ONLY, intentExtras);
            return dialInternal(dialString, null, videoState, intentExtras);
            /// @}
        } else {
            return dialInternal(dialString, null, videoState, intentExtras);
        }
    }

VOLTE通话这里我们先不讨论,继续看dialInternal()

 @Override
    protected Connection dialInternal(String dialString, UUSInfo uusInfo, int videoState,Bundle intentExtras)throws CallStateException {
            ........
            return mCT.dial(newDialString);
            ........
    }

mCT是GsmCdmaCallTracker对象,我们接着看GsmCdmaCallTracker中的dial()

  public synchronized Connection dial(String dialString, int clirMode, UUSInfo uusInfo,Bundle intentExtras)throws CallStateException {
        .......
        //mCi的类型为CommandsInterface,在创建phone的时候作为参数,实际上执行的是RIL.dial()
        mCi.dial(mPendingMO.getAddress(), clirMode, obtainCompleteMessage());
        updatePhoneState();//更新phone状态
        mPhone.notifyPreciseCallStateChanged();//发起phone状态变化通知
        return mPendingMO;
    }

其中mCi就是RIL的实例,mCi是CommandsInterface类型,在GsmCdmaPhone的构建中获取的

public static void makeDefaultPhone(Context context) {
        synchronized (sLockProxyPhones) {
        ......
        sCommandsInterfaces[i] = new RIL(context, networkModes[i],
                            cdmaSubscription, i);
        ......
         phone = new GsmCdmaPhone(context,
                                sCommandsInterfaces[i], sPhoneNotifier, i,
                                PhoneConstants.PHONE_TYPE_CDMA_LTE,
                                TelephonyComponentFactory.getInstance());
        ......
    }

所以我们继续查看RIL中dial(),

 public void
    dial(String address, int clirMode, UUSInfo uusInfo, Message result) {

           //创建了一个RILRequest对象rr,这里的result为之前发送的EVENT_OPERATION_COMPLETE
           RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result);
           ......
           //将rr发送给RILC,此时的rr内部为RIL_REQUEST_DIAL
           //RILC层处理完成后会调用RILJ的processSolicited方法
           send(rr);
           ......

    }

RILJ从名字可以看出他是RILC在java层的实现,负责了Framework层与RIL层的交互,上层发送rr到底层处理,而底层通过RILJ将处理结果上报。RILJ的processSolicited(),此方法负责接收并处理RILC层回传上来的消息。
在RIL层中的数据交互使用基于Socket网络连接的方式,当然这种socket并不是网络socket而是localSocket。消息数据按其处理方式的不同可以分为两类:
1)Solicited消息。这类消息如dial拨号,answer接听电话等主动操作请求。Solicited请求类的RIL消息,根据其动作行为,可再细分为SolicitedRequest和Solicited Response。正常情况下这两类消息成对出现,请求和应答一一对应。
2)UnSolicited消息。这类消息为底层主动上报的消息,如来电,接受短信等等。此消息由于是底层Modem主动上报,因此没有Request只有Response。

 private void
    send(RILRequest rr) {
        Message msg;

        if (mSocket == null) {
            rr.onError(RADIO_NOT_AVAILABLE, null);
            rr.release();
            return;
        }

        msg = mSender.obtainMessage(EVENT_SEND, rr);
        acquireWakeLock(rr, FOR_WAKELOCK);
        msg.sendToTarget();
    }

mSender发送EVENT_SEND消息,在RIL.java中的handleMessage()方法中处理

 switch (msg.what) {
                case EVENT_SEND:
                case EVENT_SEND_ACK:
                        ........
                        LocalSocket s;
                        s = mSocket;
                        s.getOutputStream().write(dataLength);
                        s.getOutputStream().write(data);
                        .......
                }

RIL的构造函数会初始化RILReceiver对象,RILReceiver对象实现了Runnable,在run方法中创建连接:

@Override
public void run() {
            ......
            try {for (;;) {
                LocalSocket s = null;
                LocalSocketAddress l;
                ......
                s = new LocalSocket();//创建Socket
                l = new LocalSocketAddress(rilSocket,
                            LocalSocketAddress.Namespace.RESERVED);
                s.connect(l);连接socket
            }
            .......
            try {
                    InputStream is = mSocket.getInputStream();
                    for (;;) {
                        Parcel p;
                        length = readRilMessage(is, buffer);
                        if (length < 0) {
                            // End-of-stream reached
                            break;
                        }
                        p = Parcel.obtain();//包装返回的数据
                        p.unmarshall(buffer, 0, length);
                        p.setDataPosition(0);
                        //处理请求并返回
                        processResponse(p);
                        p.recycle();
    }

上层下发了一个rr,底层处理接受并处理之后还会回发一个Respose以表明处理结果,其处理结果根据上面的介绍,将在processSolicited()中进行处理:

void processUnsolicited (Parcel p, int type) {
    ......
    case RIL_REQUEST_DIAL: ret =  responseVoid(p); break;
    rr.mResult.sendToTarget();//发送Handler消息通知,此消息将在//GsmCdmaCallTracker中处理,这个message是EVENT_OPERATION_COMPLETE。
    ......
}

所以调用sendToTarget方法,就会把消息发送给GsmCdmaCallTracker,然后在GsmCdmaCallTracker.java的handleMessage方法中有对EVENT_OPERATION_COMPLETE的逻辑处理:然后调用operationComplete()方法;

private void operationComplete() {
        ........
        mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
        mCi.getCurrentCalls(mLastRelevantPoll);
        ........
    }

进入mCi.getCurrentCalls(mLastRelevantPoll);首先获取一个RILRequest对象,再send给RILC。底层查询Call_list状态列表,RILC处理完后,仍然返回到RILJ,同样在processSolicited()中处理,由此可见processSolicited()基本负责了对RILC层返回消息的处理。同样进入GsmCdmaCallTracker中的handleMessage()的Case EVENT_POLL_CALLS_RESULT

@Override
public void handleMessage(Message msg) {
        AsyncResult ar;
        switch (msg.what) {
            case EVENT_POLL_CALLS_RESULT:
                if (msg == mLastRelevantPoll) {
                    ......
                    handlePollCalls((AsyncResult)msg.obj);
                }
            break;

进入handlePollCalls()更新手机状态。然后RILC会上报RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED消息给RILJ,调用RIL的processUnsolicited();

protected synchronized void handlePollCalls(AsyncResult ar) {
    .......
    updatePhoneState();
    .......
    if (hasNonHangupStateChanged || newRinging != null || hasAnyCallDisconnected) {
        mPhone.notifyPreciseCallStateChanged();
    }
    .......
}

最后更新phone状态,注册了该phone电话状态监听的对象将会收到通知,然后RILC会上报RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED消息给RILJ,调用RIL的processUnsolicited()

private void processUnsolicited (Parcel p) {
    ...
    try {switch(response) {
    ...
    case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: 
    ret =  responseVoid(p); break;
    ...
    }
    switch(response) {
    ...
    case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
         if (RILJ_LOGD) 
         unsljLog(response);//打印log日志
         //发出通知(RegistrantList消息处理机制)
         mCallStateRegistrants.notifyRegistrants(new 
         AsyncResult(null, null, null));
    ...
    }
}

GsmCdmaCallTracker.java向RIL注册了一个EVENT_CALL_STATE_CHANGE类型的Handler消息。 然后handleMessage处理。调用了pollCallsWhenSafe();

 @Override
 public void handleMessage(Message msg) {
    .......
    case EVENT_CALL_STATE_CHANGE:
      pollCallsWhenSafe();
            break;
    .......        

pollCallsWhenSafe在CallTracker中实现。

protected void pollCallsWhenSafe() {
        ...
        if (checkNoOperationsPending()) {
        //注意mLastRelevantPoll对象的消息类型,后面会用到
            mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
            mCi.getCurrentCalls(mLastRelevantPoll);
        }
}

又是RILJ请求查询Call List状态列表,查完还是交给 CdmaCallTracker去处理。这时候Call的状态还是DIALING。
等Call的状态变成ACTIVE后,底层又会上报RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED消息给RILJ,然后RILJ又请求查询查询Call List状态列表,GsmCdmaCallTracker又处理,不过这次是modem主动上报的,到这里,电话已接通。

时序图如下(右击选择新标签打开)
这里写图片描述


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值