Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Telephony Phone詳解

Android Telephony Phone詳解

編輯:關於Android編程

前言

本文主要講解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等)
    }

本文來自http://blog.csdn.net/linyongan ,轉載請務必注明出處。


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中有三種PhoneFactZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcnmjujxiciAvPg0KUGhvbmVGYWN0b3J5LmphdmEgJm1kYXNoOyZtZGFzaDsmbmRhc2g7Jmd0O9PD09q0tL2oR1NNUGhvbmWhokNETUFQaG9uZaGiQ0RNQUxURVBob25lttTP86O7PGJyIC8+DQpJbXNQaG9uZUZhY3RvcnkuamF2YSAmbWRhc2g7Jm1kYXNoOyZuZGFzaDsmZ3Q708PT2rS0vahJbXNQaG9uZbbUz/OjuzxiciAvPg0KU2lwUGhvbmVGYWN0b3J5LmphdmEgJm1kYXNoOyZtZGFzaDsmbmRhc2g7Jmd0O9PD09q0tL2oU2lwUGhvbmW21M/zoaM8YnIgLz4NCsbk1tCjrEdTTVBob25loaJDRE1BUGhvbmWhokNETUFMVEVQaG9uZbbUz/PKx9TaUGhvbmW9+LPMxvS2r9auuvO0tL2otcSjqLK91ugxfjejqaO7PGJyIC8+DQrWrrrzo6y1yLW9SW1zU2VydmljZcb0tq/Wrrrzo6y+zbvhtLS9qEltc1Bob25lo6iyvdboOH4xM6OpoaM8L3A+DQo8aDMgaWQ9"21-phone進程的啟動">2.1 Phone進程的啟動

在Android中進程名一般對應的是該APP的包名,所以我們可以在源碼中找package=”com.android.phone”。
接著你就會在/packages/services/Telephony/AndroidManifest.xml文件中看到:

再往下翻翻,你就會看到application的名字是PhoneApp,application是最早被創建的,所以PhoneApp.java就是Phone進程啟動的入口。

    

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 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) {}
    ......

好了,本文就暫時寫到這裡。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved