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

本文來自http://blog.csdn.net/linyongan ,轉載請務必註明出處。本文主要講解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!");
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

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"
>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

再往下翻翻,你就會看到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">
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

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);
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

由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);
        ......
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

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());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

先初始化了DefaultPhoneNotifier和RIL對象,將它們作爲參數,再創建GsmCdmaPhone。
所以在GsmCdmaPhone中可以直接操縱這兩個對象的方法。
DefaultPhoneNotifier實現了PhoneNotifier接口,PhoneNotifier接口中定義了很多notifyXXX的接口,所以DefaultPhoneNotifier主要的作用就是上報消息

public interface PhoneNotifier {

    public void notifyPhoneState(Phone sender);
    public void notifyServiceState(Phone sender);
    ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

而RIL對象主要作用是跟modem交互。
因此,Phone實例就間接地擁有了跟modem交互的能力和上報消息的能力,再加上Phone實例自身就有監聽事件的能力,所以Phone的作用就是:
1.註冊監聽事件,及時上報消息(Call狀態變化、Service狀態變化、新來電等等)
2.間接地爲其他類提供跟modem交互的服務。

(function () { ('pre.prettyprint code').each(function () { var lines = (this).text().split(\n).length;var numbering = $('
    ').addClass('pre-numbering').hide(); (this).addClass(hasnumbering).parent().append( numbering); for (i = 1; i
    發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章