1. 程式人生 > >Android Telephony分析(一) ---- Phone詳解

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

本文主要講解Telephony中Phone相關的知識。

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介面變得更加精簡;

http://blog.csdn.net/linyongan

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互動的服務。

相關推薦

Android Telephony分析() ---- Phone

本文主要講解Telephony中Phone相關的知識。 1. Android N中Phone的改變 Android 6.0時,Phone的繼承關係: 在Android N中,Phone的繼承關係: 變化1: GSMPhone和CDMAPhone

Android觸控式螢幕事件派發機制與原始碼分析(View篇)

【工匠若水 http://blog.csdn.net/yanbober】 Notice:閱讀完該篇之後如果想繼續深入閱讀Android觸控式螢幕事件派發機制詳解與原始碼分析下一篇請點選《Android觸控式螢幕事件派發機制詳解與原始碼分析二(ViewGroup篇)》檢視。 1

Android Call分析() ---- Call物件

Call(通話)相關的內容也是屬於Telephony模組,Call整體上可以分成兩類: 1. CS call,其中CS全稱是Circuit Switch,我們平常打電話走的就是CS的流程。 2. IMS PS call,其中PS全稱是Packet Switc

Android 學習之《第一行程式碼》第二版 筆記(十廣播機制(

一、廣播機制簡介 1. 四大元件之一 2. Android 提供了一套完整的API,允許應用程式自由地傳送和接收廣播。 A. 傳送廣播藉助Intent B. 接收廣播藉助廣播接收器(Broadcast Receiver) 3. 廣播型別: A. 標準廣播: 完全非同步執行

Android非同步訊息處理機制及原始碼分析

PS一句:最終還是選擇CSDN來整理髮表這幾年的知識點,該文章平行遷移到CSDN。因為CSDN也支援MarkDown語法了,牛逼啊! 【工匠若水 http://blog.csdn.net/yanbober 轉載煩請註明出處,尊重分享成果】 最近相對來說比較閒,加上養病,所

Java定時任務Timer排程器【】 原始碼分析(圖文版)

就以鬧鐘的例子開頭吧(後續小節皆以鬧鐘為例,所有原始碼只列關鍵部分)。 public class ScheduleDemo { public static void main(String[] args) throws InterruptedException {

Android觸控式螢幕事件派發機制與原始碼分析三(Activity篇)

PS一句:最終還是選擇CSDN來整理髮表這幾年的知識點,該文章平行遷移到CSDN。因為CSDN也支援MarkDown語法了,牛逼啊! 【工匠若水 http://blog.csdn.net/yanbober】 該篇承接上一篇《Android觸控式螢幕事件派發機制詳解與原始碼分析

Android觸控式螢幕事件派發機制與原始碼分析二(ViewGroup篇)

【工匠若水 http://blog.csdn.net/yanbober】 該篇承接上一篇《Android觸控式螢幕事件派發機制詳解與原始碼分析一(View篇)》,閱讀本篇之前建議先閱讀。當然,閱讀完這一篇之後可以閱讀繼續進階的下一篇《Android觸控式螢幕事件派發機制詳解與原始碼

C#詞法分析器之詞法分析的使用()

雖然文章的標題是詞法分析,但首先還是要從編譯原理說開來。編譯原理應該很多人都聽說過,雖然不一定會有多麼瞭解。 簡單的說,編譯原理就是研究如何進行編譯——也就如何從程式碼(*.cs 檔案)轉換為計算機可以執行的程式(*.exe 檔案)。當然也有些語言如 JavaScrip

Java效能分析神器-JProfiler)(轉)

前段時間在給公司專案做效能分析,從簡單的分析Log(GC log, postgrep log, hibernate statitistic),到通過AOP蒐集軟體執行資料,再到PET測試,感覺時間花了不少,效能也有一定的提升,但總感覺像是工作在原始時代,無法簡單順暢,又無比清

Android 動畫】View Animation

安卓平臺目前提供了兩大類動畫,在Android 3.0之前,一大類是View Animation,包括Tween animation(補間動畫),Frame animation(幀動畫),在android3.0中又引入了一個新的動畫系統:property ani

Android 5.X 新特性)——主題、Palette、陰影、著色和裁剪

Android 5.X 系列開始使用新的設計風格Material Design來統一整個Android系統的介面設計風格。 Material Design 主題 Material Design 現在有三種預設的主題可以設定,程式碼如下: @andr

Android開發之藍芽()

一.概述 這篇文章是我學習Android開發官網以及網上一些其他文章總結而來,主要就是為了好好研究一下藍芽開發,看完這篇文章以後,我們就知道了怎樣使用藍芽API完成建立藍芽連線的必要四步:1.開啟藍芽;2.查詢附近已配對或可用的裝置;3.連線裝置;4.裝置間資

Android程式設計之DialogFragment原始碼

DialogFragment是Fragment家族成員之一,如果你把它簡單的理解成Dialog,那就錯了。它的確可以做作dialog顯示,還可以顯示出自己定義的Dialog或者AlertDialog,但它同時也是一個Fragment。 按照官方的話來理解就是,你既可以把它當

Android開發之自定義控制元件()---onMeasure

         話說一個有十年的程式設計經驗的老漢,決定改行書法,在一個熱火炎炎的中午,老漢拿著毛筆,在一張白紙上寫了個“Hello World!”,從此開啟了他的書法旅程。那麼問題來了請問自定義一個控制元件需要怎樣的流程?我們經常說自定義控制元件,那麼究竟怎樣去自定義一

Android活動條(actionbar)使用()

    活動條(ActionBar)是Android3.0的重要更新之一,ActionBar位於傳統標題的位置,其主要提供瞭如下功能:     >顯示選項選單的選單項,即激昂選單項顯示在Action Item;     >使用程式圖示作為返回Home主屏或向上的

Android開發學習之SQLite

一.SQLite的介紹 1.SQLite簡介  SQLite是一款輕型的資料庫,是遵守ACID的關聯式資料庫管理系統,它的設計目標是嵌入 式的,而且目前已經在很多嵌入式產品中使用了它,它佔用資源非常的低,在嵌入式裝置中,可能只需要幾百K的記憶體就夠了。它能夠支援 Windo

Android Studio使用教程圖文

識別 由於 group 之前 而是 ces doc java代碼 風格 Android Studio是一款非常專業的Android集成開發環境工具,那麽,Android Studio怎麽用呢?針對不知道Android Studio怎麽使用的朋友們,本文就為大家圖文詳細介紹A

Android中的windowSoftInputMode屬性

stun -h oid 中文意思 ecif andro 標題 進行 模式 如何實現軟鍵盤不自動彈出,使用的方法是設置android:windowSoftInputMode屬性。那麽,這個屬性到底是幹什麽的,他有什麽作用呢?今天這篇文章,就是探索android:win

Android之build.prop屬性

lin logs generated reg dconf hostname product att make 註:本篇文章是基於MSD648項目(AndroidTV)的prop進行說明。 Android版本:4.4.4 內核版本:3.10.86 1.生成build.