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) {} ......
好了,本文就暂时写到这里。
相关文章推荐
- 如何自定义圆角dialog
- Android-BroadCastReceive广播小练习
- 使用Android Studio运行Android程序,出现错误:Error:java.lang.UnsupportedClassVersionError: com/android/dx/comman
- Android——ListView控件(Android Studio)
- android中listview分页加载数据
- 八个造成 Android 应用内存泄露的原因
- Android-Activity生命周期小记
- Android学习笔记18:自定义Seekbar拖动条式样
- Android混淆心得
- 关于Android Studio里的Gradle
- Android之多线程生成GIF
- Android基础总结(4)——广播接收器
- Android 自定义带刻度的seekbar
- Notification,PendingIntent和Intent区别,Phone联系人数据表,存放地址
- Android使用SeekBar时动态显示进度且随SeekBar一起移动
- Android 计步功能-简单实现
- Android--圆形进度条对话框
- 解决Jetbrains旗下产品的插件下载失败问题(IntelliJ IDEA、RubyMine、WebStorm、PhpStorm、PyCharm、AppCode、Android Studio等)
- Android原生SQLite操作以及greenDao框架操作SQLite
- Android 拖动条(SeekBar)实例 附完整demo项目代码