android6.0 Phone源码分析之Phone适配过程
Posted 古冥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android6.0 Phone源码分析之Phone适配过程相关的知识,希望对你有一定的参考价值。
android6.0 Phone源码分析之Phone适配过程
分析过Phone源码的人知道,在Phone去电过程中会调用到phone.dial()方法,而此处的Phone可以为GSMPhone或者CDMALTEPhone。对于Phone的适配,android采用了工厂模式。本文主要分析Phone的适配过程,重要的类主要有PhoneApp, PhoneFactory,PhoneGlobals等。
1.Phone进程的初始化
在android系统中,有许多永久存在的应用,它们对应的设置是androidmanifest.xml文件的persistent属性,若属性值为true,则此应用为永久性应用,系统开机启动时会自动加载。此外,若应用因某种原因退出,系统会再次自动启动此应用。而在Phone应用中的PhoneApp类在androidmanifest.xml中的persistent属性为true。
<application android:name="PhoneApp"
android:persistent="true"
android:label="@string/phoneAppLabel"
android:icon="@mipmap/ic_launcher_phone"
android:allowBackup="false"
android:supportsRtl="true"
android:usesCleartextTraffic="true">
<provider android:name="IccProvider"
分析PhoneApp类:
@Override
public void onCreate()
if (UserHandle.myUserId() == 0)
// We are running as the primary user, so should bring up
// the global phone state.
mPhoneGlobals = new PhoneGlobals(this);
mPhoneGlobals.onCreate();
mTelephonyGlobals = new TelephonyGlobals(this);
mTelephonyGlobals.onCreate();
在PhoneApp类启动后,会在onCreate()中初始化PhoneGlobals和TelephonyGlobals两个类。PhoneGlobals类用来初始化phone,以及获取phone,而TelephonyGlobals类主要用来处理PSTN呼叫,它是5.0新添加的类,先分析PhoneGlobals。
2.PhoneGlobals类分析
public void onCreate()
...
if (mCM == null)
// Initialize the telephony framework
PhoneFactory.makeDefaultPhones(this);
// Start TelephonyDebugService After the default
// phone is created.
Intent intent = new Intent(this,
TelephonyDebugService.class);
startService(intent);
//获取CallManager实例
mCM = CallManager.getInstance();
for (Phone phone : PhoneFactory.getPhones())
//将phone注册到CallManager中
mCM.registerPhone(phone);
...
// Create the CallController singleton, which is the
//interface to the telephony layer for user-initiated
//telephony functionality(like making outgoing calls)
//初始化callController
callController = CallController.init(this,
callLogger, callGatewayManager);
...
由以上代码可知,PhoneGlobals类先通过PhoneFactory初始化Phone,然后将所有的Phone注册到CallManager,此时就可以通过PhoneFactory的getPhone(int phoneId)方法,通过phoneId来获取相应的Phone.接着先分析makeDefaultPhones()方法。
public static void makeDefaultPhone(Context context)
...
//获取Phone的sim数量
int numPhones =
TelephonyManager.getDefault().getPhoneCount();
...
//循环对所有的Sim卡进行Phone类型的初始化
for (int i = 0; i < numPhones; i++)
PhoneBase phone = null;
//获取Phone的类型
int phoneType =TelephonyManager
.getPhoneType(networkModes[i]);
if (phoneType == PhoneConstants.PHONE_TYPE_GSM)
//初始化为GSM模式
phone = new GSMPhone(context,
sCommandsInterfaces[i],sPhoneNotifier, i);
phone.startMonitoringImsService();
else if (phoneType ==
PhoneConstants.PHONE_TYPE_CDMA)
//初始化为CMDALTE模式
phone = new CDMALTEPhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i);
phone.startMonitoringImsService();
//生成Phone代理,并放入PhoneFactory的工厂
sProxyPhones[i] = new PhoneProxy(phone);
//将PhoneFactory的所有Phone代码交给ProxyController管理
mProxyController = ProxyController.getInstance(context,
sProxyPhones,mUiccController, sCommandsInterfaces);
...
首先获取Phone中sim卡的数量,然后分别对对应的Sim卡进行Phone的初始化,可以初始化为GSMPhone和CDMALTEPhone两种。接着将其加入到PhoneFactory的ProxyPhones数组中进行,最后再将其交给ProxyController进行控制管理,至此,Phone的准备工作已经结束。
3.Phone适配
在去电过程(MO)中,会调用onCreateOutgoingConnection()创建去电Connection
@Override
public Connection onCreateOutgoingConnection(
PhoneAccountHandle connectionManagerPhoneAccount,
final ConnectionRequest request)
//根据请求获取tel
Uri handle = request.getAddress();
...
//获取PhoneAccount的类型
String scheme = handle.getScheme();
...
//获取Phone
final Phone phone = getPhoneForAccount(
request.getAccountHandle(), false);
...
//创建连接
final TelephonyConnection connection =
createConnectionFor(phone, null, true /* isOutgoing */, request.getAccountHandle());
...
//设置tel
connection.setAddress(handle,
PhoneConstants.PRESENTATION_ALLOWED);
//初始化
connection.setInitializing();
connection.setVideoState(request.getVideoState());
if (useEmergencyCallHelper) //紧急号码
...
else//非紧急号码,根据初始化好的connection创建连接
placeOutgoingConnection(connection, phone, request);
return connection;
由以上代码可知,根据请求通过getPhoneForAccount()方法来获取Phone.
private Phone getPhoneForAccount(PhoneAccountHandle
accountHandle, boolean isEmergency)
if (isEmergency) //紧急号码
return PhoneFactory.getDefaultPhone();
//获取subId
int subId = PhoneUtils.
getSubIdForPhoneAccountHandle(accountHandle);
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) //有效ID
//获取phoneId
int phoneId = SubscriptionController.
getInstance().getPhoneId(subId);
//根据phoneId从PhoneFactory获取Phone
return PhoneFactory.getPhone(phoneId);
return null;
首先通过PhoneUtils获取subId,然后再从SubscriptionController中获取相应的phoneId,最后再根据phoneId从PhoneFactory中获取phone.
public static int getSubIdForPhoneAccountHandle(
PhoneAccountHandle handle)
if (handle != null && handle.getComponentName().
equals(getPstnConnectionServiceName()))
Phone phone = getPhoneFromIccId(handle.getId());
if (phone != null)
return phone.getSubId();
return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
接着分析getPhoneFromIccId()方法.
private static Phone getPhoneFromIccId(String iccId)
if (!TextUtils.isEmpty(iccId))
for (Phone phone : PhoneFactory.getPhones())
String phoneIccId = phone.getIccSerialNumber();
if (iccId.equals(phoneIccId))
return phone;
return null;
由代码可知,通过比较所有Phone与此Account的iccId来获取相应的phone.最后会通过得到的phone来创建相应的Connection,最后实现去电。
以上是关于android6.0 Phone源码分析之Phone适配过程的主要内容,如果未能解决你的问题,请参考以下文章
android6.0源码分析之Camera API2.0下的video流程分析
android6.0源码分析之Camera API2.0下的Capture流程分析