分析过Phone源码的人知道,在Phone去电过程中会调用到phone.dial()方法,而此处的Phone可以为GSMPhone或者CDMALTEPhone。对于Phone的适配,android采用了工厂模式。本文主要分析Phone的适配过程,重要的类主要有PhoneApp, PhoneFactory,PhoneGlobals等。
在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。
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的准备工作已经结束。
在去电过程(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,最后实现去电。