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

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

2016-07-22 23:05 507 查看

前言

本文主要讲解Telephony中Phone相关的知识,主要想讲明白三件事情:

Phone是什么?

Phone从哪里来?

Phone有什么作用?

1. Phone是什么

1.1 Phone是一个接口

Phone.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)

public interface Phone {
//包含了大量的register/unregister的方法。(监听能力)
void registerForXXX(Handler h, int what, Object obj);
void unregisterForXXX(Handler h);
//大量的get/set的方法。(读取和修改的能力)
//定义Telephony基础功能的方法(如dial、acceptCall等)
}


本文来自\color{red}{本文来自}http://blog.csdn.net/linyongan ,转载请务必注明出处。\color{red}{,转载请务必注明出处。}

1.2 Phone家族



由上面类图可以看出,PhoneBase是处于一个最重要最关键的位置,是所有关系的中心枢纽。

public abstract class PhoneBase extends Handler implements Phone {


PhoneBase只实现了Phone接口中部分的抽象方法,所以PhoneBase也还是抽象类,它本质上是Handler。

我们常常用到的GSMPhone、CDMAPhone等继承于PhoneBase,并且实现了Phone接口中还未被PhoneBase实现的抽象方法,同样,PhoneBase的子类也都是Handler。

至于PhoneProxy,它是一个代理对象:

public PhoneProxy(PhoneBase phone) {
//得到PhoneBase对象
mActivePhone = phone;
......
}
//举个例子:
@Override
public String getPhoneName() {
//直接调PhoneBase对象或者它子类的同名方法
return mActivePhone.getPhoneName();
}


代理的好处是安全,我在PhoneProxy中定义了哪几个方法,你就只能调用那几个方法,而不会给你得到PhoneBase或者其子类对象,进而操纵所有东西;还有就是对外接口一致,调用方式一致,不用区分是GSMPhone?还是CDMAPhone?或者是IMSPhone?

2. Phone从哪里来



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

Android中有三种PhoneFactory:

PhoneFactory.java ——–>用于创建GSMPhone、CDMAPhone、CDMALTEPhone对象;

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

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

其中,GSMPhone、CDMAPhone、CDMALTEPhone对象是在Phone进程启动之后创建的(步骤1~7);

之后,等到ImsService启动之后,就会创建ImsPhone(步骤8~13)。

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对象的初始化

为了创建Phone对象,为了实现Phone接口中所有的抽象方法,有两个问题需要考虑:

创建Phone对象前,需要先准备什么?

创建Phone对象后,如何让Phone对象正常工作?

2.2.1 创建Phone对象前,需要先准备什么

我们回过头继续看Phone接口:

public interface Phone {
//包含了大量的register/unregister的方法。
void registerForXXX(Handler h, int what, Object obj);
void unregisterForXXX(Handler h);
//大量的get/set的方法。
//定义Telephony基础功能的方法(如dial、acceptCall等)
}


所以,Phone对象必须拥有的能力:与RIL交互的能力(为了实现Telephony基础功能和大量的get/set的方法),通知上层APP的能力(监听到事件之后,需要继续上报该消息)。

如何拥有这两种能力?最简单的方法当然把拥有这两种能力的对象传递进来!

看看PhoneBase参数最少的构造方法:

protected PhoneBase(String name, PhoneNotifier notifier, Context context, CommandsInterface ci) {
this(name, notifier, context, ci, false);
}


可以看出,创建GSMPhone、CDMAPhone、ImsPhone等PhoneBase子类对象时,需要先得到两个比较重要的对象:DefaultPhoneNotifier(实现了PhoneNotifier接口中大量notify的方法)和RIL(实现了CommandsInterface,RILJ拥有跟Qcril、modem交互的能力)。

GSMPhone/CDMALTEPhone具体的创建过程:

在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];
sProxyPhones = new PhoneProxy[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++) {
PhoneBase phone = null;
//先得到Phone的类型
int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
//根据不用的类型,创建不同的Phone对象
if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
phone = new GSMPhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i);
} else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
phone = new CDMALTEPhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i);
}
Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " sub = " + i);
//创建Phone对象后也要对应地创建一个PhoneProxy对象
sProxyPhones[i] = new PhoneProxy(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对象
sProxyPhones[i].startMonitoringImsService();
}
}


2.2.2 创建Phone对象后,如何让它正常工作

从Phone接口就可以看到,每一个Phone对象都拥有大量的register方法,所以每创建一个Phone对象之后,都用把Phone对象传递进CallManager.java的registerPhone()方法中。

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对象并且为它们注册监听事件(步骤7和13)。

// 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有什么作用

在第二小节已经讲了Phone拥有跟RIl交互的能力和上报消息的能力,所以Phone的作用就是:

1.及时上报消息给APP(Call状态变化、Service状态变化、新来电等等)

void notifyPhoneStateChanged(){}
void notifyNewRingingConnection(Connection c) {}
void notifyDisconnect(Connection cn) {}
void notifyUnknownConnection(Connection cn) {}
void notifySuppServiceFailed(SuppService code) {}
void notifyServiceStateChanged(ServiceState ss) {}
void notifyLocationChanged() {}
void notifyCallForwardingIndicator() {}
......


2.间接地为APP提供跟RIL交互的服务。

public void getCallWaiting(Message onComplete) {}

public void setCallWaiting(boolean enable, Message onComplete) {}
......


好了,本文就暂时写到这里。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: