zoukankan      html  css  js  c++  java
  • 腾讯优测优分享 | 双卡双待-工程师难言的痛

    腾讯优测是专业的移动云测试平台,提供全面兼容性测试,远程真机租用,漏洞分析等多维度的测试服务,让测试更简单!
    【引子】
    移动互联网的时代,手机通讯录是天然的强社交关系的关系链,如果打通产品关系链和通讯录关系链的通道,可以极大的丰富产品的关系链(见下图)。
    使用电话本信息、打电话、发短信等功能是许多产品的需求点。Android作为智能手机平台,电话相关模块是系统的重要组成部分。但如果开发电话相关的功能就不得不面对“双卡双待”的问题。

    1. 【双卡双待背景分析】
      用户为了兼顾运营商优势,使用双卡双待手机:
      双卡双待这项技术在发展中国家使用很普遍,因为在发展中国家电信运营商发展不够成熟,相关管理制度不完善。从用户的角度出发,主要考虑资费问题,比如:移动通话信号好,联通3G上网流畅、流量费相对便宜,为了兼顾运营商的优势,用户选择双卡双待手机。
       
      运营商为了争夺原有2G用户,推出双卡双待手机:
      原有国内六大运营商中国移动,中国联通,中国电信,中国网通,中国铁通和中国卫通,经过了整合与拆分,用户在使用制式上各有不同包括GSM、TD-SCDMA、WCDMA、CDMA2000;其中GSM占有量非常大,各运营商在推广新业务时,不得不兼顾原有GSM用户。例如电信如果手机只能使用电信卡,市场上推广会有很多障碍,运营商通过推出双卡双待来解决这个问题。
       
      双卡双待相关技术发展:
      .两套芯片,缺点是耗电量大、硬件成本高。这个相当于是两个手机“粘”在一起。
      .双卡单待,需要手动切换,不是真正的双卡双待,用户只能使用一张卡。相当于加了一个“开关”。
      .双卡双待,使用芯片控制手机在两个网络之间切换,因为切换速度很快用户感觉是两张卡在同时待机。是目前采用的技术手段。
    2. 【双卡双待碎片化现状】
      双卡方案不统一:
      Android本身碎片化问题严重,Google标准API中没有双卡双待的支持,对于双卡双待实现方式业界也没有标准,于是双卡解决方案有了现在百花齐放、百家争鸣的局势。
       
      涉及模块众多:
      作为一个智能手机平台,电话部分是Android系统的重点功能。电话部分主要功能包括:呼叫(Call)、短信(Sms)、数据连接(Data Connection)、Sim卡相关、电话本等。尽管Android整个框架已经使用AIDL机制来解耦,使得各个模块之间尽可能的独立,但对于开发者和产品人员来说,所有涉及到这些模块的功能点都会受到双卡双待的困扰。
       
      已成事实标准的双卡双待逼迫主流厂家开始支持:
      在过去双卡双待是山寨手机的一个代名词,山寨机是最早发现这块需求并快速响应;后面随着用户的普及,很多大手机厂商纷纷推出双卡双待手机,包括一些在国外市场只支持单卡的机型,也会在国内做好了双卡双待,才推向市场。
      最新的HTC One在国内没有单卡机器售卖,原本一体的机身设计,后经改装加入双卡双待功能。三星S系列也逐渐铺开双卡机型,双卡双待已经不是小众用户,也不是低端用户,这个现状对于开发者是个绕不过的坎儿。如果要开发电话模块相关的功能,开发团队必须要解决双卡双待的问题。
    3. 【解决策略】
      双卡双待实现和真机ROM的Framework层实现密切相关,不同的手机实现方式不一样,同一系列的手机实现的策略类似,但是可能有差别。下面介绍分析解决的过程:
      3.1 【准备工作】
      工具准备:smali 和 dex2jar
      详细操作流程请参见工具网站说明
      https://code.google.com/p/dex2jar/
      https://code.google.com/p/smali/downloads/list
      材料准备:需要将适配的双卡手机 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 【架构分析】


    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客户配备了专家团队提供定制化综合测试解决方案。

  • 相关阅读:
    我爱Java系列之---【SpringBoot打成war包部署】
    279. Perfect Squares
    矩阵dfs--走回路
    112. Path Sum
    542. 01 Matrix
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    Invert Binary Tree
    563 Binary Tree Tilt
    145 Binary Tree Postorder Traversal
  • 原文地址:https://www.cnblogs.com/utest/p/5868807.html
Copyright © 2011-2022 走看看