相信很多Android手机用户都用过手机安全软件的“电话拦截”功能,不管您用的是360安全卫士、腾讯手机管家,还是金山毒霸…,它们的共同特点就是您在设置来电拦截黑名单或开启/关闭来电等待时,界面并不友好(如下图所示),比如:会有拨号界面弹出再消失,或者手机会拨打一个号码,需要用户手动挂断或直到连接自动挂断。 第三方应用(即使具有root权限)在完成这两个功能时,无法避免拨号界面的出现。原因是这两个功能需要利用SIM卡呼叫转移、呼叫等待功能,拨打某个特定号码,所以设置该功能时会出现拨号界面。 以GSM为例,现在的实现中: 来电拦截返回音是通过拨以下特定号码实现的: String BUSY_NUMBER = "%23%2367%23"; String EMPTY_NUMBER = "**67*13800000000%23"; String POWEROFF_NUMBER = "**67*13810538911%23"; String OUT_OF_SERVICE_NUMBER = "**67*13701110216%23"; 呼叫等待开启和关闭是通过拨以下号码实现的: String GSM_CALL_WAIT_OPEN = "*43%23"; String GSM_CALL_WAIT_CLOSE = "%2343%23"; 所以通过一个第三方应用(即使它有root权限)去设置来电拦截返回音或开启/关闭呼叫等待时,就会出现拨号界面,用户体验不好。 一、原理分析 1、Android去电流程 下图右边蓝色框中粗略的给出了Android拨打电话的流程,其中蓝色填充的部分表示的App层phone应用,粉色填充部分表示的是framework层。从图中可看出,当拨出电话流程走到CallController的placeCall()后,会做两件事情:1),call CallManager的dial()方法拨打电话;2),不管拨打成功与否,都会将InCallScreen(拨号界面)展示到前端。当通过第三方应用设置来电拦截返回音时,根据来电拦截原理,会拨打某个特殊的号码,因此通过正常的Outgoing call流程一定不可避免拨打界面的出现。 二、改进和优化 我们从系统入手,彻底解决这个不友好的界面。完整的拨号流程会从app层->framework层,拨号界面的出现是在app层,因此我们避开拨号流程中app层的流程,通过我们自己的service直接调用framework层的拨号方法,从而避免了拨号界面的出现,消除了不好的用户体验。 i) 在init.rc中添加一个service(上图左边Service绿色方框所示),并授予它root权限。该service起来之后,等待client端的请求。并对client端暴露了一套SDK API接口(上图左边SDK API绿色方框所示),app应用通过调用这套API接口,设置、查询来电拦截返回音。我们提供的SDK 接口有:
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课