腾讯优测是专业的移动云测试平台,提供全面兼容性测试,远程真机租用,漏洞分析等多维度的测试服务,让测试更简单!
【引子】
移动互联网的时代,手机通信录是自然的强社交关系的关系链,若是打通产品关系链和通信录关系链的通道,能够极大的丰富产品的关系链(见下图)。
使用电话本信息、打电话、发短信等功能是许多产品的需求点。Android做为智能手机平台,电话相关模块是系统的重要组成部分。但若是开发电话相关的功能就不得不面对“双卡双待”的问题。java
【双卡双待背景分析】
用户为了兼顾运营商优点,使用双卡双待手机:android
双卡双待这项技术在发展中国家使用很广泛,由于在发展中国家电信运营商发展不够成熟,相关管理制度不完善。从用户的角度出发,主要考虑资费问题,好比:移动通话信号好,联通3G上网流畅、流量费相对便宜,为了兼顾运营商的优点,用户选择双卡双待手机。网络
运营商为了争夺原有2G用户,推出双卡双待手机:
原有国内六大运营商中国移动,中国联通,中国电信,中国网通,中国铁通和中国卫通,通过了整合与拆分,用户在使用制式上各有不一样包括GSM、TD-SCDMA、WCDMA、CDMA2000;其中GSM占有量很是大,各运营商在推广新业务时,不得不兼顾原有GSM用户。例如电信若是手机只能使用电信卡,市场上推广会有不少障碍,运营商经过推出双卡双待来解决这个问题。
双卡双待相关技术发展:
.两套芯片,缺点是耗电量大、硬件成本高。这个至关因而两个手机“粘”在一块儿。
.双卡单待,须要手动切换,不是真正的双卡双待,用户只能使用一张卡。至关于加了一个“开关”。
.双卡双待,使用芯片控制手机在两个网络之间切换,由于切换速度很快用户感受是两张卡在同时待机。是目前采用的技术手段。架构
【双卡双待碎片化现状】
双卡方案不统一:app
Android自己碎片化问题严重,Google标准API中没有双卡双待的支持,对于双卡双待实现方式业界也没有标准,因而双卡解决方案有了如今百花齐放、百家争鸣的局势。
涉及模块众多:
做为一个智能手机平台,电话部分是Android系统的重点功能。电话部分主要功能包括:呼叫(Call)、短信(Sms)、数据链接(Data Connection)、Sim卡相关、电话本等。尽管Android整个框架已经使用AIDL机制来解耦,使得各个模块之间尽量的独立,但对于开发者和产品人员来讲,全部涉及到这些模块的功能点都会受到双卡双待的困扰。
已成事实标准的双卡双待逼迫主流厂家开始支持:
在过去双卡双待是山寨手机的一个代名词,山寨机是最先发现这块需求并快速响应;后面随着用户的普及,不少大手机厂商纷纷推出双卡双待手机,包括一些在国外市场只支持单卡的机型,也会在国内作好了双卡双待,才推向市场。
最新的HTC One在国内没有单卡机器售卖,本来一体的机身设计,后经改装加入双卡双待功能。三星S系列也逐渐铺开双卡机型,双卡双待已经不是小众用户,也不是低端用户,这个现状对于开发者是个绕不过的坎儿。若是要开发电话模块相关的功能,开发团队必需要解决双卡双待的问题。框架
【解决策略】
双卡双待实现和真机ROM的Framework层实现密切相关,不一样的手机实现方式不同,同一系列的手机实现的策略相似,可是可能有差异。下面介绍分析解决的过程:socket
3.1 【准备工做】
工具准备:smali 和 dex2jar
详细操做流程请参见工具网站说明
https://code.google.com/p/dex...
https://code.google.com/p/sma...
材料准备:须要将适配的双卡手机 system目录下的framework 和 app目录文件提取出来备作反编译用。
3.2 【分析过程】
经过查看Android源代码和分析真机反编译代码能够看出Android电话模块架构主要核心机制是:一个服务(好比本文提到的电话服务)对应一个Manager管理类,一个Manager管理类对应一个AIDL接口(Android进程通讯接口),每一个AIDL接口会对应一个具体服务功能的实现。
电话服务 —> TelephonyManager —>PhoneInterfaceManager(ITelephony)—>底层具体服务
TelephonyManager(电话服务管理类)
Android框架中有上下文(context)的概念,不少资源和系统服务能够直接从上下文中得到,好比要得到电话管理类(TelephonyManager)能够经过下面方式得到:
context.getSystemService(“phone”);
咱们经过context 的实现类ContextImpl能够获取对电话管理类的访问
@Override
public Object getSystemService(String name) {
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
return fetcher == null ? null : fetcher.getService(this);
}
全部的系统服务管理类,都注册在SYSTEM_SERVICE_MAP中。
从上图源代码中能够看到,getSystemService方法最终是靠传入对应服务的key从SYSTEM_SERVICE_MAP中得到对应的管理类,这里第一个坑爹点会出现,由于key对应的值,厂商会修改为各类值,好比有些手机是”phone2”,有些好比HTC手机是”htctelephony”,
因此须要反编译厂商源码去查找这些key值,下边会详细讲到。
ITelephony(电话相关的AIDL接口)
TelephonyManager中的具体操做大部分是经过ITelephony接口访问的,好比得到电话状态的操做:
public class TelephonyManager {
…
public int getCallState() {
try {
return getITelephony().getCallState();
} catch (RemoteException ex) {
return CALL_STATE_IDLE;
} catch (NullPointerException ex) {
return CALL_STATE_IDLE;
}
}
…
}
ITelephony接口位于com.android.internal.telephony.包中,这个包是支撑android.telephony.对外接口的具体实现。
PhoneInterfaceManager (ITelephony的具体实现类,提供具体服务功能)
TelephonyManager大部分操做是经过ITelephony接口访问的,也就是经过其实现类PhoneInterfaceManager 来实际得到具体相关操做
public class PhoneInterfaceManager extends ITelephony.Stub {
…
public int getCallState() {
return DefaultPhoneNotifier.convertCallState(mCM.getState());
}
…
}
PhoneInterfaceManager 封装了电话相关的具体服务操做,这些操做最终将消息发送到RIL.java中转。
RIL.java和底层通讯
RIL.java是电话相关服务在Java层的信息收发中心。
RIL.java使用socket和rild进程通讯,RILRequest是一个请求的封装,经过RILSender将请求命令发送出去,经过RILReceiver接收命令的响应和主动消息。
进过上述的分析,能够总结出电话相关服务的架构。
3.3 【架构分析】ide
Android电话系统分为四个层次(见上图):
Phone应用程序层:主要包括电话服务和Phone应用程序。
Java Framework层:主要包括两个程序包,其中:android.telephony. 是framework对外沟通的接口,com.android.internal.telephony 是和底层沟通的桥梁(socket )。
Native Framework层: Rild守护进程。
驱动层:与网络进行沟通传输。
为了支持双卡双待功能,厂商实现的Java Framework层在TelephonyManager的节点向下开始自定义API实现对第二张卡的支持,经过反编译并分析真机的framework.jar能够获得自TelephonyManager如下厂商自定义的操做。而后,在App层经过反射调用对应的功能点就能够实现对两张卡的操做。
3.4【解决方案举例】
经过对市面上大部分双卡机型的反编译分析看,双卡双待的解决方案能够总结为3类:
TelephonyManager异化:三星、Moto系列
这类真机中提供了两个电话服务管理类,经过context.getSystemService(”phone2″)能够获得电话服务类中的第二张卡的电话服务管理类。这个方案属于最有节操的,开发成本是最低的。
在android.app.ContextImpl
中注册上下文的各类管理类,如下为Google官方代码中的实现:工具
如下是反编译三星 Node2 framework.jar获得的相关代码块
registerService(“phone“, new ServiceFetcher()
{
public Object createService(ContextImpl paramContextImpl)
{
return new TelephonyManager(paramContextImpl.getOuterContext(), 0);
}
});
registerService(“phone2“, new ServiceFetcher()
{
public Object createService(ContextImpl paramContextImpl)
{
return new TelephonyManager(paramContextImpl.getOuterContext(), 1);
}
});
能够看出经过context.getSystemService(”phone2″),就能够从上文中提到的SYSTEM_SERVICE_MAP拿到第二张卡的管理类,由于只是管理类实例不同,只须要拿到第二张卡的TelephonyManager实例,全部的方法均可以按照标准API正常使用。
方法异化:MTK芯片系列
MTK解决方案普遍用于联想以及中兴厂商中,这类手机没有新建Manager管理类,而是在管理类中新加入xxxGemini(int para)的方法,其中int参数表明卡槽,0为一卡槽,1为二卡槽。开发者须要经过反射来调用和标准API对应的Gemini方法来实现对应的操做。如下为反编译 联想A750 对应的得到Sim卡状态的方法具体实现。
public int getSimState()
{
return getSimStateGemini(getDefaultSim());
}
public int getSimStateGemini(int paramInt)
{……}
调用对应的Gemini方法能够实现对两张卡的操做,好比:经过反射调用getSimStateGemini分别传入0和1做为参数,就能够得到两张卡的SIM卡状态。
新建Manager类:华为系列
这种方案比较隐蔽的,经过修改增长本身实现类完成对双卡的支持,如下为华为C8825D的处理方案:
首先,获得对应的管理类
c = Class.forName(“android.telephony.MSimTelephonyManager“);
//其中MSimTelephonyManager类为厂商自定义的电话服务管理类
而后,经过反射调用对应的方法,能够成功的返回操做结果
method = c.getDeclaredMethod(“getSimState”, int.class);
总结:
双卡双待手机的适配过程主要是分析“异化”点,找到在Framework层中是如何区分卡槽的,不一样的手机实现不一样,对于TelephonyManager相关的解决方案总结有以上三种。对于短信相关的操做位于SmsManager中,解决策略和TelephonyManager相似,再也不详细分析。
通过上面的分析过程能够知道,一个模块的功能点,适配开发过程当中都须要进行下面三个步骤:
.反编译系统framework.jar、phone.apk等找到对应功能不一样卡槽的操做方式。
.在本地代码中经过反射调用该方法。
.验证操做是否成功。
过程相对比较复杂,须要反复的试验和验证,并且每款手机都要这样调查和解决一遍,所以开发成本是至关高的。
大连在Android机型适配上有着丰富的经验,目前已经开发出一套自动化的机型适配扫描工具–腾讯优测机型扫描系统。经过腾讯优测平台去检索代码中关于双卡双待的适配问题,平台自动检测代码可能的机型问题,并提供解决方案,从而能够极大的减轻开发者负担,提升适配开发效率。
目前腾讯优测平台已经接入RDM,在持续集成时能够勾选机型扫描,持续集成完成后项目组会收到机型扫描后的邮件报告,报告详细展现了机型适配的问题、影响的机型数量与型号、影响的用户数评估、相应适配问题的解决方案等;
项目若是想扫描机型问题,能够经过rdm的持续集成启动机型扫描。
_
腾讯优测是专业的移动云测试平台,为应用、游戏、H5混合应用的研发团队提供产品质量检测与问题解决服务。不只在线上平台提供自动化兼容性测试、云手机远程租用与调试、漏洞分析、自动化测试工具Xtest等多种质量检测工具,更为VIP客户配备了专家团队提供定制化综合测试解决方案。测试