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详解相关推荐
- Android Telephony分析(五) ---- TelephonyRegistry详解
本文紧接着上一篇文章<Android Telephony分析(四) -- TelephonyManager详解 >的1.4小节. 从TelephonyRegistry的大部分方法中: ...
- Android Telephony分析(三) ---- RILJ详解
前言 本文主要讲解RILJ工作原理,以便更好地分析代码,分析业务的流程. 这里说的RILJ指的是RIL.java (frameworks\opt\telephony\src\java\com\And ...
- Android Telephony分析(二) ---- RegistrantList详解
前言 本文主要讲解RegistrantList的原理,以及如何快速分析RegistrantList相关的代码流程. 在Telephony模块中,在RIL.Tracker(ServiceStateTr ...
- Android Telephony分析(一) ---- Phone详解
本文主要讲解Telephony中Phone相关的知识. 1. Android N中Phone的改变 Android 6.0时,Phone的继承关系: 在Android N中,Phone的继承关系: 变 ...
- Android Telephony分析(六) ---- 接口扩展(实践篇)
本文将结合前面五篇文章所讲解的知识,综合起来,实现一个接口扩展的功能. 如果还没有阅读过前面五篇文章的内容,请先阅读: <Android Telephony分析(一) - Phone详解 & ...
- Android面试基础之BroadcastReceiver详解(斗帝养成系列四)
斗帝养成 大斗师,一至九星,斗气铠甲,斗气外放,聚气化固态,呈菱形.别说自己尽力了,那只是自欺欺人的假话. Android面试基础之Activity详解(斗帝养成系列一) Android面试基础之Se ...
- Android Telephony分析(七) ---- 接口扩展(异步转同步)
本文是基于上一篇<Android Telephony分析(六) -- 接口扩展(实践篇)>来写的. 上一篇介绍的接口扩展的方法需要实现两部分代码: 1. 从APP至RIL,发送请求: ...
- 【Android 应用开发】Ubuntu 下 Android Studio 开发工具使用详解 (旧版本 | 仅作参考)
. 基本上可以导入项目开始使用了 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21035637 ...
- Android 动画之ScaleAnimation应用详解
本节讲解ScaleAnimation 动画在应用中的实现,有需要的朋友可以参考下 android中提供了4中动画: AlphaAnimation 透明度动画效果 ScaleAnimation 缩放动画 ...
最新文章
- C++11中头文件type_traits介绍
- 修改value_Java 反射修改String引发的思考?
- morphologyEx 形态学
- java程序经过编译后会产生byte code_学习廖雪峰的JAVA教程---异常处理(Java的异常)...
- 常用的 Web Service 服务汇总(天气预报,列车时刻表)
- 硬件知识:串口通讯的起始、数据、停止位是怎么分配的?
- Python02期(北京)课程笔记索引
- 【今日CS 视觉论文速览】Mon, 7 Jan 2019
- 学习笔记04:《产品经理白皮书》
- dos命令窗口光标闪烁_10 分钟上手 Vim,常用命令大盘点
- ​苏宁回应股权质押给淘宝:正常合作;苹果App Store被越狱商店指控垄断;Docker 20.10.0发布|极客日报...
- [RN] React Native 解决 使用 阿里巴巴 矢量图标库 iconfont 图标不垂直居中问题
- a星算法的优缺点_轻松理解机器学习算法:C4.5算法
- qgis中加载矢量切片
- 问卷java_Java 问卷调查
- Ribbon详解与实例
- Android开发,app多种语言包
- 从小白的角度理解二项分布、几何分布和泊松分布
- 1.8.8 配置防盗链
- 苹果CMS根据有无播放组输出不同的内容