前言:
電話管理是Android 系統支援的重要的業務之一,提供接聽電話,收發短信、電話薄、網絡事件監聽、
讀取使用者資訊、2G/3G/4G信号切換等功能。由上到下分為4層, PHONE應用層,Telephony架構實作層,
RIL層。本文基于android 5.1,架構圖如下,
整個架構的調用流程圖如下,
整個網絡雖然涉及到的程序也比較多,但是仔細分析起來關鍵點沒有多少。本文的關鍵點在于Framework的幾個程序,
上層的應用以及第三方有關phone的應用都是通過TelephonyManager這個API接口和phone程序進行binder通信,
當然手機中有部分操作本身就運作于phone程序中。
Phone程序一方面通過RIL.java檔案利用socket和hardware中的rild守護程序進行通信;另外一方面通過
NetworkAgent利用AsyncChannel和systemerver程序的ConnectivityService服務進行通信,管理網絡連接配接等等。
與此同時, systemerver程序還通過socket機制和netd守護程序完成網絡的相關操作等等。
在整個android系統中,phone子產品需要處理很多事務,例如電話的接聽/來去電,短信的收發等等,但是本文主要論述
Framework層的Phone服務程序有關2G/3G/4G信号切換流程。
1, Phone服務程序
Phone服務程序 (包名com.android.phone,以下簡稱phone程序)主要代碼位于以下目錄中,
packages/services/Telephony/
frameworks/opt/telephony/
frameworks/base/telephony/
1.1 phone程序啟動
Phone程序并不是在點選Luncher上的圖示啟動的,而是在系統開機啟動時,又ActivityManagerService啟動的。
Phone的AndroidManifest.xml檔案配置了如下屬性:
<application android:name="PhoneApp"
android:persistent="true"
android:label="@string/dialerIconLabel"
android:icon="@drawable/ic_launcher_phone">
對于android:persistent="true" 的應用是在Android開機時啟動的, 在android啟動完成時通過調用systemReady
方法來完成并通知服務啟動。ActivityManagerService服務的systemReady有關啟動android:persistent="true"
應用的代碼如下,
//通過PackageManager查詢到所有android:persistent屬性為true的應用
List apps = AppGlobals.getPackageManager().getPersistentApplications(STOCK_PM_FLAGS);
if (apps != null) {
int N = apps.size();
int i;
//周遊所有應用,并啟動
for (i=0; i<N; i++) {
//得到每個應用的相關資訊
ApplicationInfo info= (ApplicationInfo)apps.get(i);
if (info != null &&!info.packageName.equals("android")) {
//啟動應用
addAppLocked(info, false, null /* ABI override */);
首先查詢apk檔案中android:persistent="true"的應用;
然後調用addAppLocked方法(最後調用startProcessLocked方法)啟動應用。
1.2 初始化
PhoneApp繼承自Application,是以,phone程序的入口方法為PhoneApp的onCreate方法,方法的調用流程圖如下,
初始化主要步驟如下,
1, RIL 初始化,
開啟發送消息的線程:
mSenderThread = new HandlerThread("RILSender" + mInstanceId);
mSenderThread.start();
利用mSenderThread 建構RILSender 對象,這樣就可以向底層發送套接字消息了。
Looper looper = mSenderThread.getLooper();
mSender = new RILSender(looper);
同樣, 建構一個RILReceiver對象,接收底層發送的套接字消息
mReceiver = new RILReceiver();
mReceiverThread = new Thread(mReceiver, "RILReceiver" + mInstanceId);
mReceiverThread.start();
2,狀态/消息的注冊,這樣,底層傳輸上來的消息才可以分發處理。
例如,在GsmCallTracker的構造函數中注冊電話狀态,
mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
3, PhoneProxy相關代理類的初始化、NotificationMgr的初始化等等。