日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android Telephony分析(四) ---- TelephonyManager详解

發布時間:2025/3/15 Android 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Telephony分析(四) ---- TelephonyManager详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

TelephonyManager主要提供Telephony相關信息的查詢/修改功能,以及Phone狀態監聽功能,封裝的方法主要是提供給APP上層使用。?
TelephonyManager.java 在frameworks\base\telephony\java\Android\telephony目錄下。

1. TelephonyManager整體結構

從TelephonyManager導入的文件中可以發現有四個接口

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

分別對應下面這幾個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

所以可以猜測到,在TelephonyManager中可以得到這四種Service。?
通過所有文件中搜索”extends 接口名.Stub”,如”extends ITelephony.Stub”,可以找到是哪些類實現了上面四個AIDL接口中的方法,整理可得:?

在TelephonyManager中搜索”接口名.Stub.asInterface”,如”ITelephony.Stub.asInterface”,可以找到這四個Service的名字,整理可得:

接口 服務端 Service Name
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

好了,下面分別對這四種Service進行分析:


http://blog.csdn.net/linyongan?


1.1 TelecomServiceImpl—Telecom Service

服務端TelecomServiceImpl中有mBinderImpl實現了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把自己注冊到ServiceManager中,

ServiceManager.addService(Context.TELECOM_SERVICE, service);
  • 1
  • 1

所以在TelephonyManager中可以通過ServiceManager得到Telecom Service

private ITelecomService getTelecomService() {//得到TelecomServiceImpl的代理對象return ITelecomService.Stub.asInterface(ServiceManager.getService(Context.TELECOM_SERVICE));}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

其實Telecom Service的最常用客戶端是TelecomManager.java。而在TelephonyManager中由于無法得到CallManager對象,所以只能依賴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,但其實作用不大。相反,Telecom Service中會反過來得到TelephonyManager對象,進一步實現自己的方法,如在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

服務端PhoneSubInfoController繼承自IPhoneSubInfo.Stub

public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
  • 1
  • 1

在創建Default Phone對象之后,ProxyController對象在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的構造方法中初始化了PhoneSubInfoController對象mPhoneSubInfoController = new PhoneSubInfoController(mContext, mPhones);... }public PhoneSubInfoController(Context context, Phone[] phone) {mPhone = phone;if (ServiceManager.getService("iphonesubinfo") == null) {//將PhoneSubInfoController實例注冊到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在這里只是對這些方法進一步封裝,這些方法具體的實現,最后還是通過Phone實例和IsimRecords實例來完成的。?
以getMsisdn()方法為例,最常見的調用方式如下:?
?
備注:在Android N中已刪除PhoneSubInfo.java和PhoneSubInfoProxy.java,所以流程變得簡單了。

1.3 PhoneInterfaceManager—Telephony Service

TelephonyManager依賴Telephony Service實現了大部分的方法。?
PhoneInterfaceManager繼承自ITelephony.Stub

public class PhoneInterfaceManager extends ITelephony.Stub {
  • 1
  • 1

PhoneInterfaceManager.java在 packages\services\telephony\src\com\android\phone目錄下,顯然它是運行在Phone進程中的。?
在Phone進程啟動時,Default Phone對象創建完之后,PhoneInterfaceManager對象在PhoneGlobals的onCreate()中被初始化:

public void onCreate() {...phoneMgr = PhoneInterfaceManager.init(this, PhoneFactory.getDefaultPhone());...}/* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {synchronized (PhoneInterfaceManager.class) {if (sInstance == null) {//初始化PhoneInterfaceManagersInstance = new PhoneInterfaceManager(app, phone);} else {Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);}return sInstance;}}
  • 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的構造方法中:

private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {//得到一些關鍵類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實例注冊到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初始化的時候,把自己注冊成SystemServer,這樣客戶端(如TelephonyManager)則可以通過ServiceManager把它取出來。

private ITelephony getITelephony() {//得到PhoneInterfaceManager的代理對象return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

PhoneInterfaceManager中的方法,最后還是通過Phone實例來實現。?
以isImsRegistered()方法為例,最常見的調用方式如下:?

1.4 TelephonyRegistry—“telephony.registry” Service

TelephonyRegistry繼承自ITelephonyRegistry.Stub

class TelephonyRegistry extends ITelephonyRegistry.Stub {
  • 1
  • 1

在SystemServer.java中,

telephonyRegistry = new TelephonyRegistry(context); //將TelephonyRegistry實例注冊到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實現listen()方法,實現對Phone狀態的監聽的功能

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

關于TelephonyRegistry,后續的文章會詳細講,目前先不用太關注。


2. 如何得到TelephonyManager對象

1、 假如沒有Context,可以通過:

private static TelephonyManager sInstance = new TelephonyManager(); public static TelephonyManager getDefault() { return sInstance; }
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

2、如果能得到Context對象,可以通過:

//注意,這是從SystemService中取 TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); //或者 TelephonyManager mTelephonyManager = TelephonyManager.from(context);
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

3. 其他重要方法

TelephonyManager還提供了兩個其他比較重要的方法:

/*** Gets the telephony property.** @hide*/public static String getTelephonyProperty(int phoneId, String property, String defaultVal) {String propVal = null;//根據key獲取到valueString prop = SystemProperties.get(property);if ((prop != null) && (prop.length() > 0)) {//將value分割成字符串數組String values[] = prop.split(",");if ((phoneId >= 0) && (phoneId < values.length) && (values[phoneId] != null)) {//取出phoneId對應的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

這樣子就可以實現對于同一個key,不同phoneId可以存儲不同的值。


原文地址: http://blog.csdn.net/linyongan/article/details/52104394

總結

以上是生活随笔為你收集整理的Android Telephony分析(四) ---- TelephonyManager详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。