11年下半年一直在做RIL的移植,主要解决第三方库的一些bug,使之能更好的工作在公司的PAD上。但是后来发现远远不够,有好多问题出现在Framework层。比方说我们想让PAD支持热插拔,尽管底层做好了,但上层还会出现很多问题,如PIN/PUK解锁功能,用户把解锁PIN/PUK的界面打开但同时他把卡拔掉了,此时是无法解锁的,系统该如何响应此时的情况,我们该怎么做,这都是需要了解Telephony Framework之后才知道如何实现的。
于是研究了一番Telephony的Java框架,刚开始接触时感觉挺复杂很混乱,现在理清了关系,所以希望能帮到那些还在纠结中的同志。
我想大致以网络连接为例分析Android Telephony Framework层,关于ril及其移植的文章有很多所以就不赘述了。
以下部分内容引自前段时期我关于Telephony的总结做的PPT,参考了不少前辈的文章,用英文写的,懒得再译回来了,凑合着看吧(当时为了翻译成英文还煞费苦心- -!),需要PPT原件可以在此 http://wenku.baidu.com/view/bfe5361afad6195f312ba61c.html 下载,重要的和难理解的地方会做些解释,文章较长,一篇日志不让保存所以共分为四部分。
先来个整体结构图,有个大致印象,看完本文回头再看应该会有更深的理解。
1.Telephony Framework
Telephony framework contains a set of telephony API for applications. There are two categaries of JAVA pacakges in telephony framework:
1.The internal telephony packages -
com.android.internal.telephony.*,
source code: frameworks/base/telephony/java/com/android/internal/telephony
2.The open telephony packages -
android.telephony.*.
source code: frameworks/base/telephony/java/android/telephony
The internal packages are used for Android default telephony application - Phone.apk, and the open packages are for any 3rd party telephony applications.
Internal Telephony Packages:
frameworks/base/telephony/java/com/android/internal/telephony
The public interface Phone is used to control the phone. The abstract class PhoneBase implements this interface. And the class GSMPhone extends this abstract class.
Phone.java
44 public interface Phone{ 326 String getPhoneName(); 332 int getPhoneType(); 1118 void setPreferredNetworkType(int networkType, Message response); 1125 void getPreferredNetworkType(Message response); ...
The default telephony application could use makeDefaultPhones() and getDefaultPhone() in the class PhoneFactory to obtain the unique instance of Phone. The code below shows how this be done.
packages/apps/Phone/src/com/android/phone/PhoneApp.java
410 public void onCreate() { ... 425 if (phone == null) { 426 // Initialize the telephonyframework 427 PhoneFactory.makeDefaultPhones(this); 428 429 // Get the default phone 430 phone = PhoneFactory.getDefaultPhone();
PhoneFactory.java
56 public static void makeDefaultPhone(Context context) { ... 130 sCommandsInterface = new RIL(context, networkMode, cdmaSubscription); 132 int phoneType = getPhoneType(networkMode); if (phoneType == Phone.PHONE_TYPE_GSM) { 135 sProxyPhone = new PhoneProxy(new GSMPhone(context, sCommandsInterface, sPhoneNotifier)); 137 } else if (phoneType == Phone.PHONE_TYPE_CDMA) {
Let’s suppose the current network mode is in GSM/GPRS, so the default telephony application could obtain a PhoneProxy to a GSMPhone, and use its API to achieve telephony functionalities. ProxyPhone is also extended from Phone. It is used to abstract the specific instance of a specific network mode.
PhoneProxy.java
57 public PhoneProxy(Phone phone) {
58 mActivePhone = phone;
...
66 mCommandsInterface = ((PhoneBase)mActivePhone).mCM;
67 mCommandsInterface.registerForRadioTechnologyChanged(
68 this, EVENT_RADIO_TECHNOLOGY_CHANGED, null);
69 }
...
549 public void getPreferredNetworkType(Message response) {
550 mActivePhone.getPreferredNetworkType(response);
551 }
The class PhoneBase has a member mCM of the type CommandsInterface. And this is assigned in the constructor of GSMPhone.
GSMPhone.java
130 GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier,
boolean unitTestMode) {
131 super(notifier, context, ci, unitTestMode);
...
PhoneBase.java
114 public CommandsInterface mCM;
...
203 protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci,
204 boolean unitTestMode) {
207 mLooper = Looper.myLooper();
...
757 public void getPreferredNetworkType(Message response) {
758 mCM.getPreferredNetworkType(response);
759 }