Advertisement

(O)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.isEmergencyCall();
    
  
    
     if (needsAccountSelection) {
    
     // 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.setState(
    
             CallState.CONNECTING,
    
             phoneAccountHandle == null ? "no-handle" : phoneAccountHandle.toString());
    
     }
    
  
    
     setIntentExtrasAndStartTime(call, extras);
    
  
    
     // Do not add the call if it is a potential MMI code.
    
     if ((isPotentialMMICode(handle) || isPotentialInCallMMICode) && !needsAccountSelection) {
    
     ......
    
     } else if (!mCalls.contains(call)) {
    
     ......
    
     addCall(call);
    
     }
    
  
    
     return call;
    
 }
    
    
    
    

从这个方法中,可以看到
1)先调用reuseOutgoingCall方法确认是否有可以直接使用的Call,由于分析的是第一次通话,因此,此处为null,无可用的Call
2)初始化一个Call对象,并且设置一些必要的参数
3)由于传入的参数phoneAccountHandle为null(此前都没有设置过),因此会设置其值为默认的defaultPhoneAccountHandle或者为accounts.get(0)
4)调用addCall方法
从如上的分析中,可以看到,目前有几个问题需要解决
第一,需要由于phoneAccountHandle被设置为默认的defaultPhoneAccountHandle或者accounts.get(0),这个取决于accounts的数量,那么这个值是什么
第二,addCall方法中具体做了什么
下面,就对这两个问题进行分析一下
i)phoneAccountHandle是被设置为什么了?
从上述的代码中看,它是由accounts决定的,如果accounts的数量大于1的话,则为默认的defaultPhoneAccountHandle,如果其数量为1的话,则为accounts中所包含的PhoneAccountHandle
那么,accounts是什么?通过代码查看,了解其是由constructPossiblePhoneAccounts方法得到的

复制代码
 private List<PhoneAccountHandle> constructPossiblePhoneAccounts(Uri handle, UserHandle user) {

    
     ......
    
     List<PhoneAccountHandle> allAccounts =
    
         mPhoneAccountRegistrar.getCallCapablePhoneAccounts(handle.getScheme(), false, user);
    
     ......
    
     return allAccounts;
    
 }
    
    
    
    

可以看到,是调用PhoneAccountRegistrarD的getCallCapablePhoneAccounts方法返回的

复制代码
 public List<PhoneAccountHandle> getCallCapablePhoneAccounts(

    
     String uriScheme, boolean includeDisabledAccounts, UserHandle userHandle) {
    
     return getPhoneAccountHandles(
    
         PhoneAccount.CAPABILITY_CALL_PROVIDER,
    
         PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY /*excludedCapabilities*/,
    
         uriScheme, null, includeDisabledAccounts, userHandle);
    
 }
    
    
    
    
复制代码
 private List<PhoneAccountHandle> getPhoneAccountHandles(

    
     int capabilities,
    
     int excludedCapabilities,
    
     String uriScheme,
    
     String packageName,
    
     boolean includeDisabledAccounts,
    
     UserHandle userHandle) {
    
     List<PhoneAccountHandle> handles = new ArrayList<>();
    
  
    
     for (PhoneAccount account : getPhoneAccounts(
    
         capabilities, excludedCapabilities, uriScheme, packageName,
    
         includeDisabledAccounts, userHandle)) {
    
     handles.add(account.getAccountHandle());
    
     }
    
     return handles;
    
 }
    
    
    
    

OK,是通过getPhoneAccounts的getAccountHandle得到的

复制代码
 private List<PhoneAccount> getPhoneAccounts(

    
     int capabilities,
    
     int excludedCapabilities,
    
     String uriScheme,
    
     String packageName,
    
     boolean includeDisabledAccounts,
    
     UserHandle userHandle) {
    
     List<PhoneAccount> accounts = new ArrayList<>(mState.accounts.size());
    
     for (PhoneAccount m : mState.accounts) {
    
     ......
    
     accounts.add(m);
    
     }
    
     return accounts;
    
 }
    
    
    
    

mState是什么?查看整个PhoneAccountRegistrar的代码,发现,这个mState是在PhoneAccountRegistrar的初始化的时候写入的,来看它的代码

复制代码
 public PhoneAccountRegistrar(Context context, String fileName,

    
         DefaultDialerCache defaultDialerCache, AppLabelProxy appLabelProxy) {
    
     mAtomicFile = new AtomicFile(new File(context.getFilesDir(), fileName));
    
  
    
     mState = new State();
    
     mContext = context;
    
     mUserManager = UserManager.get(context);
    
     mDefaultDialerCache = defaultDialerCache;
    
     mSubscriptionManager = SubscriptionManager.from(mContext);
    
     mAppLabelProxy = appLabelProxy;
    
     mCurrentUserHandle = Process.myUserHandle();
    
     read();
    
 }
    
    
    
    

read方法

复制代码
 private void read() {

    
     final InputStream is;
    
     try {
    
     is = mAtomicFile.openRead();
    
     } catch (FileNotFoundException ex) {
    
     return;
    
     }
    
  
    
     boolean versionChanged = false;
    
  
    
     XmlPullParser parser;
    
     try {
    
     parser = Xml.newPullParser();
    
     parser.setInput(new BufferedInputStream(is), null);
    
     parser.nextTag();
    
     mState = readFromXml(parser, mContext);
    
     versionChanged = mState.versionNumber < EXPECTED_STATE_VERSION;
    
  
    
     } catch (IOException | XmlPullParserException e) {
    
     Log.e(this, e, "Reading state from XML file");
    
     mState = new State();
    
     } finally {
    
     try {
    
         is.close();
    
     } catch (IOException e) {
    
         Log.e(this, e, "Closing InputStream");
    
     }
    
     }
    
  
    
     // Verify all of the UserHandles.
    
     List<PhoneAccount> badAccounts = new ArrayList<>();
    
     for (PhoneAccount phoneAccount : mState.accounts) {
    
     UserHandle userHandle = phoneAccount.getAccountHandle().getUserHandle();
    
     if (userHandle == null) {
    
         Log.w(this, "Missing UserHandle for %s", phoneAccount);
    
         badAccounts.add(phoneAccount);
    
     } else if (mUserManager.getSerialNumberForUser(userHandle) == -1) {
    
         Log.w(this, "User does not exist for %s", phoneAccount);
    
         badAccounts.add(phoneAccount);
    
     }
    
     }
    
     mState.accounts.removeAll(badAccounts);
    
  
    
     // If an upgrade occurred, write out the changed data.
    
     if (versionChanged || !badAccounts.isEmpty()) {
    
     write();
    
     }
    
 }
    
    
    
    

原来,它是读取xml文件得到的数据,那么xml文件里面有哪些数据呢?下面是我从高通的某平台的O版本的项目中导出的phone-account-registrar-state.xml

复制代码
 <phone_account_registrar_state version="9">

    
 	<default_outgoing>
    
 		<default_outgoing_phone_account_handle>
    
 			<user_serial_number>0</user_serial_number>
    
 			<group_id></group_id>
    
 			<account_handle>
    
 				<phone_account_handle>
    
 					<component_name>com.android.phone/com.android.services.telephony.TelephonyConnectionService</component_name>
    
 					<id>89860081101750717452</id>
    
 					<user_serial_number>0</user_serial_number>
    
 				</phone_account_handle>
    
 			</account_handle>
    
 		</default_outgoing_phone_account_handle>
    
 	</default_outgoing>
    
 	<accounts>
    
 		<phone_account>
    
 			<account_handle>
    
 				<phone_account_handle>
    
 					<component_name>com.android.phone/com.android.services.telephony.TelephonyConnectionService</component_name>
    
 					<id>E</id>
    
 					<user_serial_number>0</user_serial_number>
    
 				</phone_account_handle>
    
 			</account_handle>
    
 			<handle>tel:</handle>
    
 			<subscription_number>tel:</subscription_number>
    
 			<capabilities>182</capabilities>
    
 			<icon>AAAAAQGJUE5HDQoaCgAAAA1JSERSAAAAJgAAADAIBgAAAH2yCCgAAAAEc0JJVAgICAh8CGSIAAAB
    
 6UlEQVRYhe2YO47TUBRAz72JRMEvMkJQ0iGlBQmQEIqABigonOcsgWWQhi0wQ5WgNGgspoCCNhuY
    
 BWS2gESbgsSXwjZxJgPkoWT8Cp/Gha2ro/OebdmCB865VpqmyyRJEjP7CFwqTonPnHPIgFMz+yAi
    
 79M0/bn1wF6v155Op4t+v/9aRCbAlR1JrSEio06n86a1zcXD4VDH4/HSOfdKRI6Ay3uQMmAJ3JvP
    
 59//ObgslSTJSzP7BFwlT687lCrJiuPsr8Odc61i+V6YWVpI2Z6kKOYqcPePxSqlnpvZZ+Aa+yt1
    
 ruEGlVLPKlL7LLXBRrGylHPuKXAMXCfflFvdKLtirUBZyjn3GEgLqeyipaBSrLKnnpjZMXCDGkqV
    
 KKyVelSRqqVUiZSlBoPBwyzLvgA3qbHUbzGAOI7vq+pX4Db53bfT18z/oHEcP6hILQlACkBV9Yhc
    
 qtY9dRYFbnGBT/RtUWBBYFKQCwWxp84SXKmSRsyXRswXZfUJFhRKQE/7KkEvZZA0Yr40Yr40Yr40
    
 Yr40Yr40Yr40Yr40Yr4oq3/rIZEpMCOXC0Gw9JipmR2wKmc1SlnhoGZ2oFEUHYrICGhT7w8WAdoi
    
 Moqi6LB1cnJi3W73m5n9EJE7QFSDYAbMzOwd8HYymSx+ASOfrdnny/IjAAAAAElFTkSuQmCC
    
 </icon>
    
 			<highlight_color>0</highlight_color>
    
 			<label>Emergency calls</label>
    
 			<short_description>Emergency calling only</short_description>
    
 			<supported_uri_schemes length="2">
    
 				<value>tel</value>
    
 				<value>voicemail</value>
    
 			</supported_uri_schemes>
    
 			<extras>
    
 				<value key="android.telecom.extra.SORT_ORDER" type="string">-1</value>
    
 				<value key="codeaurora.org.extra.ALWAYS_USE_VOIP_AUDIO_MODE" type="boolean">false</value>
    
 			</extras>
    
 			<enabled>true</enabled>
    
 			<supported_audio_routes>15</supported_audio_routes>
    
 		</phone_account>
    
 	</accounts>
    
 </phone_account_registrar_state>
    
    
    
    

分析其读取的过程,可以知道,mState的defaultOutgoingAccountHandles/accounts/versionNumber均在其中有所规定,那么接下来就按照这份xml文件中的内容分析其流程
从上面可以看到,accounts只有一个PhoneAccountHandle,因此
phoneAccountHandle被设置为上述accounts的唯一值了,即三个参数分别为
mComponentName为com.android.phone/com.android.services.telephony.TelephonyConnectionService
mId为E
mUserHandle为UserManager.get(context).getUserForSerialNumber(0)
ii)addCall方法做了什么
直接看其代码

复制代码
 private void addCall(Call call) {

    
     ......
    
     call.addListener(this);
    
     mCalls.add(call);
    
     .....
    
     for (CallsManagerListener listener : mListeners) {
    
     ......
    
     listener.onCallAdded(call);
    
     ......
    
     }
    
     ......
    
 }
    
    
    
    

可以看到,主要是将刚刚初始化的Call对象加入到mCalls中进行管理,并且调用mListers中所有的Listener对象的onCallAdded方法,那么mListeners是什么?
查找代码,发现在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);
    
    
    
    

因此,会分别调用添加到mListeners中的所有对象的onCallAdded方法
这个部分,具体的不再分析,只需要知道,分别会启动相关的应用程序
如InCallController启动InCallUi应用,用于展示通话界面,CallLogManager对象启动添加通话历史记录等,不再赘述
接下来,分析下Call的建立和传递的第二个部分
(二)初始化NewOutgoingCallIntentBroadcaster对象,并调用其processIntent方法
一样,先看其代码

复制代码
 public NewOutgoingCallIntentBroadcaster(Context context, CallsManager callsManager, Call call,

    
     Intent intent, PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
    
     boolean isDefaultPhoneApp) {
    
     mContext = context;
    
     mCallsManager = callsManager;
    
     mCall = call;
    
     mIntent = intent;
    
     mPhoneNumberUtilsAdapter = phoneNumberUtilsAdapter;
    
     mIsDefaultOrSystemPhoneApp = isDefaultPhoneApp;
    
     mLock = mCallsManager.getLock();
    
 }
    
    
    
    

初始化,没啥说的

复制代码
 public int processIntent() {

    
     Intent intent = mIntent;
    
     String action = intent.getAction();
    
     final Uri handle = intent.getData();
    
     ......
    
     String number = mPhoneNumberUtilsAdapter.getNumberFromIntent(intent, mContext);
    
     ......
    
     UserHandle targetUser = mCall.getInitiatingUser();
    
     Log.i(this, "Sending NewOutgoingCallBroadcast for %s to %s", mCall, targetUser);
    
     broadcastIntent(intent, number, !callImmediately, targetUser);
    
     return DisconnectCause.NOT_DISCONNECTED;
    
 }
    
    
    
    

调用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);
    
  
    
     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
    
 }
    
    
    
    

发送广播,在NewOutgoingCallBroadcastIntentReceiver中进行处理

复制代码
 public class NewOutgoingCallBroadcastIntentReceiver extends BroadcastReceiver {

    
  
    
     @Override
    
     public void onReceive(Context context, Intent intent) {
    
     try {
    
         ......
    
             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));
    
         }
    
     }
    
     .....
    
     }
    
 }
    
    
    
    

回到CallsManager中,调用placeOutgoingCall方法

复制代码
 public void placeOutgoingCall(Call call, Uri handle, GatewayInfo gatewayInfo,

    
     boolean speakerphoneOn, int videoState) {
    
     ......
    
     call.startCreateConnection(mPhoneAccountRegistrar);
    
     ......
    
 }
    
    
    
    
复制代码
 void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar) {

    
     ......
    
     mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this,
    
         phoneAccountRegistrar, mContext);
    
     mCreateConnectionProcessor.process();
    
 }
    
    
    
    
复制代码
 public void process() {

    
     ......
    
     attemptNextPhoneAccount();
    
 }
    
    
    
    
复制代码
 private void attemptNextPhoneAccount() {

    
     ......
    
     PhoneAccountHandle phoneAccount = attempt.connectionManagerPhoneAccount;
    
     mService = mRepository.getService(phoneAccount.getComponentName(), phoneAccount.getUserHandle());
    
     ......
    
     mService.createConnection(mCall, this);
    
     ......
    
 }
    
    
    
    

从上面的分析,知道,这边的PhoneAccountHandle对象是在phone-account-registrar-state.xml文件中读取出来的,那么分析一下ConnectionServiceRepository的getService方法,我们知道
mService就是PhoneAccountHandle的Component对应的类的对象,即TelephonyConnectionService对象
看其createConnection方法,父类ConnectionService

复制代码
 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);
    
     ......
    
 }
    
    
    
    

调用onCreateOutgoingConnection方法

复制代码
 public Connection onCreateOutgoingConnection(

    
     PhoneAccountHandle connectionManagerPhoneAccount,
    
     final ConnectionRequest request) {
    
 				......
    
     placeOutgoingConnection((TelephonyConnection) resultConnection, phone, request);
    
     ......
    
 }
    
    
    
    

调用placeOutgoingConnection方法

复制代码
 private void placeOutgoingConnection(

    
     TelephonyConnection connection, Phone phone, ConnectionRequest request) {
    
     placeOutgoingConnection(connection, phone, request.getVideoState(), request.getExtras());
    
 }
    
    
    
    
复制代码
 private void placeOutgoingConnection(

    
     TelephonyConnection connection, Phone phone, int videoState, Bundle extras) {
    
     .....
    
     originalConnection = phone.dial(number, null, videoState, extras);
    
 		......
    
 }
    
    
    
    

调用Phone对象的dial方法

复制代码
 public Connection dial(String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)

    
     throws CallStateException {
    
     ......
    
     if (isPhoneTypeGsm()) {
    
     return dialInternal(dialString, null, VideoProfile.STATE_AUDIO_ONLY, intentExtras);
    
     } else {
    
     return dialInternal(dialString, null, videoState, intentExtras);
    
     }
    
 }
    
    
    
    

调用dialInternal方法

复制代码
 protected Connection dialInternal(String dialString, UUSInfo uusInfo, int videoState,

    
                               Bundle intentExtras)
    
     throws CallStateException {
    
     return dialInternal(dialString, uusInfo, videoState, intentExtras, null);
    
 }
    
    
    
    
复制代码
 protected Connection dialInternal(String dialString, UUSInfo uusInfo, int videoState,

    
                               Bundle intentExtras, ResultReceiver wrappedCallback)
    
     throws CallStateException {
    
  
    
     // Need to make sure dialString gets parsed properly
    
     String newDialString = PhoneNumberUtils.stripSeparators(dialString);
    
  
    
     if (isPhoneTypeGsm()) {
    
     // handle in-call MMI first if applicable
    
     if (handleInCallMmiCommands(newDialString)) {
    
         return null;
    
     }
    
  
    
     // Only look at the Network portion for mmi
    
     String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString);
    
     GsmMmiCode mmi = GsmMmiCode.newFromDialString(networkPortion, this,
    
                                                   mUiccApplication.get(), wrappedCallback);
    
     if (DBG) logd("dialing w/ mmi '" + mmi + "'...");
    
  
    
     if (mmi == null) {
    
         return mCT.dial(newDialString, uusInfo, intentExtras);
    
     } else if (mmi.isTemporaryModeCLIR()) {
    
         return mCT.dial(mmi.mDialingNumber, mmi.getCLIRMode(), uusInfo, intentExtras);
    
     } else {
    
         mPendingMMIs.add(mmi);
    
         mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
    
         try {
    
             mmi.processCode();
    
         } catch (CallStateException e) {
    
             //do nothing
    
         }
    
  
    
         // FIXME should this return null or something else?
    
         return null;
    
     }
    
     } else {
    
     return mCT.dial(newDialString);
    
     }
    
 }
    
    
    
    

可以看到,会调用GsmCdmaCallTracker的dial方法

复制代码
 public Connection dial(String dialString) throws CallStateException {

    
     if (isPhoneTypeGsm()) {
    
     return dial(dialString, CommandsInterface.CLIR_DEFAULT, null);
    
     } else {
    
     return dial(dialString, CommandsInterface.CLIR_DEFAULT);
    
     }
    
 }
    
    
    
    

以Gsm Phone来看

复制代码
 public Connection dial(String dialString, UUSInfo uusInfo, Bundle intentExtras)

    
     throws CallStateException {
    
     return dial(dialString, CommandsInterface.CLIR_DEFAULT, uusInfo, intentExtras);
    
 }
    
    
    
    
复制代码
 public synchronized Connection dial(String dialString, int clirMode, UUSInfo uusInfo,

    
                                 Bundle intentExtras)
    
     throws CallStateException {
    
     ......
    
     if ( mPendingMO.getAddress() == null || mPendingMO.getAddress().length() == 0
    
         || mPendingMO.getAddress().indexOf(PhoneNumberUtils.WILD) >= 0) {
    
     // Phone number is invalid
    
     mPendingMO.mCause = DisconnectCause.INVALID_NUMBER;
    
  
    
     // handlePollCalls() will notice this call not present
    
     // and will mark it as dropped.
    
     pollCallsWhenSafe();
    
     } else {
    
     // Always unmute when initiating a new call
    
     setMute(false);
    
  
    
     mCi.dial(mPendingMO.getAddress(), clirMode, uusInfo, obtainCompleteMessage());
    
     }
    
  
    
     if (mNumberConverted) {
    
     mPendingMO.setConverted(origNumber);
    
     mNumberConverted = false;
    
     }
    
  
    
     updatePhoneState();
    
     mPhone.notifyPreciseCallStateChanged();
    
  
    
     return mPendingMO;
    
 }
    
    
    
    

这边调用RIL的dial方法,最终会传入RIL层,进行处理

全部评论 (0)

还没有任何评论哟~