您的位置:首页 > 移动开发 > Android开发

Android Telephony分析(一)--- Phone 详解

2017-08-03 16:13 387 查看
本文出处:http://blog.csdn.net/linyongan/article/details/51994817

1. Android N 中 Phone 的改变

Android 6.0时,Phone的继承关系:



在Android N中,Phone的继承关系:



变化1: GSMPhone和CDMAPhone合并成了GsmCdmaPhone,合并之后,某些方法当然需要对GSM Phone和CDMA Phone进行分别处理,举个例子:
@Override
public void setCallWaiting(boolean enable, Message onComplete) {
//如果是GSM Phone
if (isPhoneTypeGsm()) {
Phone imsPhone = mImsPhone;
//对IMS的处理
if ((imsPhone != null)
&& ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
|| imsPhone.isUtEnabled())) {
//走IMS流程
imsPhone.setCallWaiting(enable, onComplete);
return;
}
mCi.setCallWaiting(enable, CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
} else {
//如果是CDMA Phone
loge("method setCallWaiting is NOT supported in CDMA!");
}
}

GSMPhone和CDMAPhone合并之后,PhoneProxy的作用就不大了,所以在Android N中PhoneProxy被删除了。

变化2:Phone.Java取代了以前的PhoneBase.java(内部的方法有小部分修改),Phone.java变成了所有关系的中心枢纽。

变化3:接口变成了PhoneInternalInterface,因为PhoneProxy已不存在了,实现了PhoneInternalInterface接口的只剩下Phone.java,所以删掉了PhoneInternalInterface中大量的register/unregister的接口,这些register/unregister的方法留在Phone.java中即可,PhoneInternalInterface接口变得更加精简

2. Phone从哪里来



(备注:上面时序图中的是谷歌原生的流程,跟高通的有点不一样)

Android中有三种PhoneFactory:

PhoneFactory.java ——–> 用于创建GsmCdmaPhone对象;

ImsPhoneFactory.java ——–> 用于创建ImsPhone对象;

SipPhoneFactory.java ——–> 用于创建SipPhone对象。

其中,GsmCdmaPhone对象是在Phone进程启动之后创建的(步骤1~6);之后,等到ImsService启动之后,就会创建ImsPhone(步骤7~11)。

2.1 Phone进程的启动

在Android中进程名一般对应的是该APP的包名,所以我们可以在源码中找package=”com.android.phone”。

接着你就会在/packages/services/Telephony/AndroidManifest.xml文件中看到:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.android.phone"
coreApp="true"
android:sharedUserId="android.uid.phone"
android:sharedUserLabel="@string/phoneAppLabel"
>

再往下翻翻,你就会看到application的名字是PhoneApp,application是最早被创建的,所以PhoneApp.java就是Phone进程启动的入口。

<application android:name="PhoneApp"
//在系统启动之时,ActivityManagerService的systemReady()
//会加载所有persistent为true的应用
android:persistent="true"
android:label="@string/phoneAppLabel"
android:icon="@mipmap/ic_launcher_phone"
android:allowBackup="false"
android:supportsRtl="true"
android:usesCleartextTraffic="true">

2.2 Phone对象的初始化

在PhoneFactory.java的makeDefaultPhone方法中(时序图中的步骤3)

public static void makeDefaultPhone(Context context) {
......
//创建DefaultPhoneNotifier对象。
sPhoneNotifier = new DefaultPhoneNotifier();

//根据待机模式计算出要创建Phone对象的数量
int numPhones = TelephonyManager.getDefault().getPhoneCount();
//创建networkMode、PhoneProxy、RIL的数组,用于存储对应的对象
int[] networkModes = new int[numPhones];
//Android 6.0
//sProxyPhones = new PhoneProxy[numPhones];
//Android N中没有了PhoneProxy,所以通过getDefaultPhone()得到的就是Phone实例
sPhones = new Phone[numPhones];
sCommandsInterfaces = new RIL[numPhones];

for (int i = 0; i < numPhones; i++) {
// reads the system properties and makes commandsinterface
// Get preferred network type.
networkModes[i] = RILConstants.PREFERRED_NETWORK_MODE;
Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkModes[i]));
//创建RIL,此时的i对应的是PhoneID。
sCommandsInterfaces[i] = new RIL(context, networkModes[i],
cdmaSubscription, i);
}
......
for (int i = 0; i < numPhones; i++) {
Phone phone = null;
//根据不用的类型,创建不同的Phone对象
int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
phone = new GsmCdmaPhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i,
PhoneConstants.PHONE_TYPE_GSM,
//Android N中新增TelephonyComponentFactory类,主要用来
//初始化CallTracker、ServiceStateTracker、DcTracker等对象
TelephonyComponentFactory.getInstance());
} else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
phone = new GsmCdmaPhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i,
PhoneConstants.PHONE_TYPE_CDMA_LTE,
TelephonyComponentFactory.getInstance());
}
Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " sub = " + i);

sPhones[i] = phone;
}
.....
// Start monitoring after defaults have been made.
// Default phone must be ready before ImsPhone is created
// because ImsService might need it when it is being opened.
for (int i = 0; i < numPhones; i++) {
//开始监听ImsService,如果ImsService已启动,进而执行创建ImsPhone对象
sPhones[i].startMonitoringImsService();
}
}

2.3 为Phone实例注册监听事件

PhoneGlobals.java的onCreate()方法中

public void onCreate() {
if (mCM == null) {
// Initialize the telephony framework
//先创建Phone实例
PhoneFactory.makeDefaultPhones(this);
mCM = CallManager.getInstance();
for (Phone phone : PhoneFactory.getPhones()) {
//把新创建的Phone实例传递进来
mCM.registerPhone(phone);
}
}
}

由CallManager来管理这些Phone实例并且为它们注册监听事件。

// list of registered phones, which are PhoneBase objs
private final ArrayList<Phone> mPhones;

public boolean registerPhone(Phone phone) {
Phone basePhone = getPhoneBase(phone);

if (basePhone != null && !mPhones.contains(basePhone)) {

if (DBG) {
Rlog.d(LOG_TAG, "registerPhone(" +
phone.getPhoneName() + " " + phone + ")");
}

if (mPhones.isEmpty()) {
mDefaultPhone = basePhone;
}
//管理Phone实例
mPhones.add(basePhone);
mRingingCalls.add(basePhone.getRingingCall());
mBackgroundCalls.add(basePhone.getBackgroundCall());
mForegroundCalls.add(basePhone.getForegroundCall());
//为Phone实例注册监听事件
registerForPhoneStates(basePhone);
return true;
}
return false;
}

private void registerForPhoneStates(Phone phone) {
......
phone.registerForDisconnect(handler, EVENT_DISCONNECT,mRegistrantidentifier);
phone.registerForIncomingRing(handler, EVENT_INCOMING_RING,mRegistrantidentifier);
......
}

3. Phone有什么作用

回忆第2小节创建GsmCdmaPhone对象时

sPhoneNotifier = new DefaultPhoneNotifier();
sCommandsInterfaces[i] = new RIL(context, networkModes[i],
cdmaSubscription, i);

phone = new GsmCdmaPhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i,
PhoneConstants.PHONE_TYPE_GSM,
TelephonyComponentFactory.getInstance());

先初始化了DefaultPhoneNotifier和RIL对象,将它们作为参数,再创建GsmCdmaPhone。

所以在GsmCdmaPhone中可以直接操纵这两个对象的方法。

DefaultPhoneNotifier实现了PhoneNotifier接口,PhoneNotifier接口中定义了很多notifyXXX的接口,所以DefaultPhoneNotifier主要的作用就是上报消息

public interface PhoneNotifier {

public void notifyPhoneState(Phone sender);
public void notifyServiceState(Phone sender);
...
}

而RIL对象主要作用是跟modem交互。

因此,Phone实例就间接地拥有了跟modem交互的能力和上报消息的能力,再加上Phone实例自身就有监听事件的能力,所以Phone的作用就是:

1.注册监听事件,及时上报消息(Call状态变化、Service状态变化、新来电等等)

2.间接地为其他类提供跟modem交互的服务。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: