1. ITelephony介面和ISms介面以及AIDL 在我們的Android應用中,當需要實現電話撥號時,我們需要進行如下調用 ITelephony phone = (ITelephony)ITelephony.Stub.asInterface(ServiceManager.getService("phon")) phone.dial("10086"); 對於簡訊應用,我們需要的是調用SmsManager,代碼如下 SmsManager manager = SmsManager.getDefault(); manager.sendTextMessage("10086",null,"hi,this is sms",null,null); 這裡,SmsManager對ISms做了一層封裝,實質上是通過調用 ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); simISms.sendRawPdu.... 可以看到,應用都是採用AIDL來實現IPC的跨進程調度。 對於AIDL應用,調用進程方存在的是一個實現介面的Proxy對象,通過Proxy對象與被調用進程中的Stub對象進行 通訊來實現IPC的跨進程調度,所以,在被調用進程一端必定有一個ITelephony.Stub類以及ISms.Stub類的實現。
2. PhoneInterfaceManager和SimSmsInterfaceManager ITelephony.Stub 的實作類別為com.android.phone.PhoneInterfaceManager ISms.Stub的實作類別為com.android.internal.telephony.gsm.SimSmsInterfaceManager 從這兩個類的構造器的調用代碼裡可以很清楚的看到進行了Service的註冊工作 ServiceManager.addService("phone",this); ServiceManager.addService("isms",this);
3. PhoneApp,InCallScreen,PhoneUtils及其他相關類 從SimSmsInteferManager的相關方法實現中可以看到,具體就是調用GSMPhone的SmsDispatcher執行個體來進行相關操作的。 從PhoneInterfaceManager會維持一個Phone對象的引用,當撥號應用時,PhoneInterfaceManager會將構造好的Intent傳遞給PhoneApp應用,該Intent的className指定則為InCallScreen,從中我們可以看到InCallScreen具體是通過PhoneUtils調用Phone的相關方法來實現。 PhoneInterfaceManager怎麼擷取到對應的Phone對象,然後又怎麼將Phone對象傳遞到InCallScreen中呢? 具體這裡涉及到了PhoneApp這個類,從這個類維護了一個 PhoneInterfaceManager的引用(phoneMgr)以及一個Phone引用(phone),從該類的onCreate方法中我們可以清楚的看到,PhoneApp通過PhoneFactory擷取了一個Phone執行個體,並通過該執行個體實現了PhoneInterfaceManager對象。因此,我們現在只需要關注PhoneFactory具體提供的是一個什麼樣的Phone執行個體了。 另外,PhoneApp類還提供了一個靜態方法getInstance供InCallScreen調用,InCallScreen正是通過調用該方法獲得PhoneApp執行個體從而獲得對應的Phone執行個體的。 接下來,我們通過查看PhoneFactory的方法可以看到,Phone對象對應的就是一個GSMPhone執行個體。
4。GSMPhone與RIL 從GSM的構造器可以看出,他依賴一個CommandInterface介面執行個體,通過PhoneFactory的makeDefaultPhones方法,我們可以看到,根據系統內容變數ro.radio.noril來判斷是否需要採用RIL架構實現,如果該參數不為空白,則採用Simultedcommands(主要是為了測試需要提供的類比實現).否則,採用RIL。 通過Google才知道,RIL其實是智能手機上實現AP與BP之間通訊的一種設計思想,具體大家可以參見這篇文章http://www.eetchina.com/ARTICLES/2006OCT/PDF/CPCOL_2006OCT26_EMB_TA_170.PDF?SOURCES=DOWNLOAD 在RIL.java 中我們很驚喜的看到,RIL對對訊息的處理是將訊息通過LocalSocket發送到以rild為名稱的有名連接埠。這個有名Socket的建立在ril.cpp代碼中。 s_fdListen = android_get_control_socket(SOCKET_NAME_RIL) 原來Android通話和發簡訊的應用是JAVA與C++代碼之間透過Socket串連來傳輸訊息來實現的。
5.關於C代碼與硬體之間的互動 這部分工作其實就是C代碼通過串口發送AT指令來撥號,收發簡訊。今天有點累了,具體的實現下次我再分析。