Android Telephony分析(四) ---- TelephonyManager详解
前言
 TelephonyManager主要提供Telephony相關(guān)信息的查詢/修改功能,以及Phone狀態(tài)監(jiān)聽功能,封裝的方法主要是提供給APP上層使用。?
 TelephonyManager.java 在frameworks\base\telephony\java\Android\telephony目錄下。
1. TelephonyManager整體結(jié)構(gòu)
從TelephonyManager導(dǎo)入的文件中可以發(fā)現(xiàn)有四個(gè)接口
import com.android.internal.telecom.ITelecomService; import com.android.internal.telephony.IPhoneSubInfo; import com.android.internal.telephony.ITelephony; import com.android.internal.telephony.ITelephonyRegistry;- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
分別對(duì)應(yīng)下面這幾個(gè)AIDL接口:
\frameworks\base\telecomm\java\com\android\internal\telecom\ITelecomService.aidl \frameworks\base\telephony\java\com\android\internal\telephony\IPhoneSubInfo.aidl \frameworks\base\telephony\java\com\android\internal\telephony\ITelephony.aidl \frameworks\base\telephony\java\com\android\internal\telephony\ITelephonyRegistry.aidl- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
 所以可以猜測(cè)到,在TelephonyManager中可以得到這四種Service。?
 通過所有文件中搜索”extends 接口名.Stub”,如”extends ITelephony.Stub”,可以找到是哪些類實(shí)現(xiàn)了上面四個(gè)AIDL接口中的方法,整理可得:?
 
 在TelephonyManager中搜索”接口名.Stub.asInterface”,如”ITelephony.Stub.asInterface”,可以找到這四個(gè)Service的名字,整理可得:
| ITelecomService.aidl | TelecomServiceImpl.java | telecom (TELECOM_SERVICE) | 
| IPhoneSubInfo.aidl | PhoneSubInfoController.java | iphonesubinfo | 
| ITelephony.aidl | PhoneInterfaceManager.java | phone (TELEPHONY_SERVICE) | 
| ITelephonyRegistry.aidl | TelephonyRegistry.java | telephony.registry | 
好了,下面分別對(duì)這四種Service進(jìn)行分析:
本文來自http://blog.csdn.net/linyongan?,轉(zhuǎn)載請(qǐng)務(wù)必注明出處。
1.1 TelecomServiceImpl—Telecom Service
服務(wù)端TelecomServiceImpl中有mBinderImpl實(shí)現(xiàn)了ITelecomService接口中的方法
public class TelecomServiceImpl {private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub() {...} }- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
在TelecomLoaderService.java中,TelecomServiceImpl把自己注冊(cè)到ServiceManager中,
ServiceManager.addService(Context.TELECOM_SERVICE, service);- 1
- 1
所以在TelephonyManager中可以通過ServiceManager得到Telecom Service
private ITelecomService getTelecomService() {//得到TelecomServiceImpl的代理對(duì)象return ITelecomService.Stub.asInterface(ServiceManager.getService(Context.TELECOM_SERVICE));}- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
其實(shí)Telecom Service的最常用客戶端是TelecomManager.java。而在TelephonyManager中由于無法得到CallManager對(duì)象,所以只能依賴Telecom Service獲取Call State。
/*** Returns one of the following constants that represents the current state of all* phone calls.** {@link TelephonyManager#CALL_STATE_RINGING}* {@link TelephonyManager#CALL_STATE_OFFHOOK}* {@link TelephonyManager#CALL_STATE_IDLE}*/public int getCallState() {try {ITelecomService telecom = getTelecomService();if (telecom != null) {return telecom.getCallState();}} catch (RemoteException e) {Log.e(TAG, "Error calling ITelecomService#getCallState", e);}return CALL_STATE_IDLE;}- 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
所以,總體上來說,雖然TelecomManager得到了Telecom Service,但其實(shí)作用不大。相反,Telecom Service中會(huì)反過來得到TelephonyManager對(duì)象,進(jìn)一步實(shí)現(xiàn)自己的方法,如在TelecomServiceImpl.java中:
public String getVoiceMailNumber(PhoneAccountHandle accountHandle, String callingPackage) {...return getTelephonyManager().getVoiceMailNumber(subId);...}private TelephonyManager getTelephonyManager() {return (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
1.2 PhoneSubInfoController— “iphonesubinfo” Service
服務(wù)端PhoneSubInfoController繼承自IPhoneSubInfo.Stub
public class PhoneSubInfoController extends IPhoneSubInfo.Stub {- 1
- 1
在創(chuàng)建Default Phone對(duì)象之后,ProxyController對(duì)象在PhoneFactory.java的makeDefaultPhone()中被初始化
public static void makeDefaultPhone(Context context) {...//先初始化ProxyControllermProxyController = ProxyController.getInstance(context, sProxyPhones,mUiccController, sCommandsInterfaces);...}private ProxyController(Context context, PhoneProxy[] phoneProxy, UiccController uiccController,CommandsInterface[] ci) {...//在ProxyController的構(gòu)造方法中初始化了PhoneSubInfoController對(duì)象mPhoneSubInfoController = new PhoneSubInfoController(mContext, mPhones);... }public PhoneSubInfoController(Context context, Phone[] phone) {mPhone = phone;if (ServiceManager.getService("iphonesubinfo") == null) {//將PhoneSubInfoController實(shí)例注冊(cè)到ServiceManager中ServiceManager.addService("iphonesubinfo", this);}mContext = context;mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);}- 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
- 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
所以在TelephonyManager中可以通過ServiceManager得到”iphonesubinfo” Service
private IPhoneSubInfo getSubscriberInfo() {// get it each time because that process crashes a lotreturn IPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));}- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
 通過”iphonesubinfo” Service可以得到software version、deviceID、VoiceMail Number等信息,TelephonyManager在這里只是對(duì)這些方法進(jìn)一步封裝,這些方法具體的實(shí)現(xiàn),最后還是通過Phone實(shí)例和IsimRecords實(shí)例來完成的。?
 以getMsisdn()方法為例,最常見的調(diào)用方式如下:?
 ?
 備注:在Android N中已刪除PhoneSubInfo.java和PhoneSubInfoProxy.java,所以流程變得簡(jiǎn)單了。
1.3 PhoneInterfaceManager—Telephony Service
 TelephonyManager依賴Telephony Service實(shí)現(xiàn)了大部分的方法。?
 PhoneInterfaceManager繼承自ITelephony.Stub
- 1
- 1
 PhoneInterfaceManager.java在 packages\services\telephony\src\com\android\phone目錄下,顯然它是運(yùn)行在Phone進(jìn)程中的。?
 在Phone進(jìn)程啟動(dòng)時(shí),Default Phone對(duì)象創(chuàng)建完之后,PhoneInterfaceManager對(duì)象在PhoneGlobals的onCreate()中被初始化:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
在PhoneInterfaceManager的構(gòu)造方法中:
private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {//得到一些關(guān)鍵類mApp = app;mPhone = phone;mCM = PhoneGlobals.getInstance().mCM;mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);mMainThreadHandler = new MainThreadHandler();mTelephonySharedPreferences =PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());mSubscriptionController = SubscriptionController.getInstance();publish();}private void publish() {//將PhoneInterfaceManager實(shí)例注冊(cè)到ServiceManager中ServiceManager.addService("phone", this);}- 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
在PhoneInterfaceManager初始化的時(shí)候,把自己注冊(cè)成SystemServer,這樣客戶端(如TelephonyManager)則可以通過ServiceManager把它取出來。
private ITelephony getITelephony() {//得到PhoneInterfaceManager的代理對(duì)象return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));}- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
 PhoneInterfaceManager中的方法,最后還是通過Phone實(shí)例來實(shí)現(xiàn)。?
 以isImsRegistered()方法為例,最常見的調(diào)用方式如下:?
 
1.4 TelephonyRegistry—“telephony.registry” Service
TelephonyRegistry繼承自ITelephonyRegistry.Stub
class TelephonyRegistry extends ITelephonyRegistry.Stub {- 1
- 1
在SystemServer.java中,
telephonyRegistry = new TelephonyRegistry(context); //將TelephonyRegistry實(shí)例注冊(cè)到ServiceManager中ServiceManager.addService("telephony.registry", telephonyRegistry);- 1
- 2
- 3
- 1
- 2
- 3
所以在TelephonyManager中可以通過ServiceManager得到”telephony.registry” Service
if (sRegistry == null) {sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService("telephony.registry"));}- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
TelephonyManager主要利用”telephony.registry” Service實(shí)現(xiàn)listen()方法,實(shí)現(xiàn)對(duì)Phone狀態(tài)的監(jiān)聽的功能
public void listen(PhoneStateListener listener, int events) {if (mContext == null) return;try {Boolean notifyNow = (getITelephony() != null);sRegistry.listenForSubscriber(listener.mSubId, getOpPackageName(),listener.callback, events, notifyNow);} catch (RemoteException ex) {// system process dead} catch (NullPointerException ex) {// system process dead}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
關(guān)于TelephonyRegistry,后續(xù)的文章會(huì)詳細(xì)講,目前先不用太關(guān)注。
2. 如何得到TelephonyManager對(duì)象
1、 假如沒有Context,可以通過:
private static TelephonyManager sInstance = new TelephonyManager(); public static TelephonyManager getDefault() { return sInstance; }- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
2、如果能得到Context對(duì)象,可以通過:
//注意,這是從SystemService中取 TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); //或者 TelephonyManager mTelephonyManager = TelephonyManager.from(context);- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
3. 其他重要方法
TelephonyManager還提供了兩個(gè)其他比較重要的方法:
/*** Gets the telephony property.** @hide*/public static String getTelephonyProperty(int phoneId, String property, String defaultVal) {String propVal = null;//根據(jù)key獲取到valueString prop = SystemProperties.get(property);if ((prop != null) && (prop.length() > 0)) {//將value分割成字符串?dāng)?shù)組String values[] = prop.split(",");if ((phoneId >= 0) && (phoneId < values.length) && (values[phoneId] != null)) {//取出phoneId對(duì)應(yīng)的valuepropVal = values[phoneId];}}return propVal == null ? defaultVal : propVal;}/*** Sets the telephony property with the value specified.** @hide*/public static void setTelephonyProperty(int phoneId, String property, String value) {...}- 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
- 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
這樣子就可以實(shí)現(xiàn)對(duì)于同一個(gè)key,不同phoneId可以存儲(chǔ)不同的值。
 
 
原文地址: http://blog.csdn.net/linyongan/article/details/52104394
總結(jié)
以上是生活随笔為你收集整理的Android Telephony分析(四) ---- TelephonyManager详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Android Telephony分析(
- 下一篇: Android Telephony分析(
