基于Android(安卓)RIL层实现来电拦截的技术原理(二)
原文相续,书接上一回。
在《AndroidRIL层实现来电拦截的技术原理(一)》(以下简称《一》),已经详细分析了来电的在RIL层的逻辑走向,但缺少了一个强有力的DEMO作为验证。于是花了些时间,把DEMO也弄出来了,也验证了这个方案的技术可性性。在DEMO的开发过程中,也发现了一些在《一》中错误,等下会说明。
在《一》中,通过JAVA的反射机制,取出位于CallManager中的mIncomingRingRegistrants字段,再通过自定义的ProxyHandler,把定义在mIncomingRingRegistrants里的Handler替换掉,以实现“截获”这个动作。再回顾一下之前的代码实现:
classProxyHandlerextendsHandler{
privateHandlermInnter;
publicProxyHandler(Handlerh){
mInnter=h;
}
@Override
publicvoidhandleMessage(Messagemsg){
//做爱做的事
//......
//......
mInnter.handlerMessage(msg);
}
}
CallManagerinstance=CallManager.getInstance();
//通过反射,拿到其字段mIncomingRingRegistrants
RegistrantListmIncomingRingRegistrants=instance.mIncomingRingRegistrants;
for(inti=0;i<mIncomingRingRegistrants.size();i++){
Registrantitem=mIncomingRingRegistrants.get(i);
Handlerhandler=item.getHandler();
//通过反射,拿到其字段refH
item.refH=newWeakReference(newProxyHandler(handler));//完成注入
}
这里存在三个问题,如下:
1.ProxyHandler的构造函数,由于是在一个非Looper线程上执行,因为会发生异常,应该改 为
publicProxyHandler(Handlerh){
super(h.getLooper);
mInnter=h;
}
确保我们的ProxyHandler是挂载到原来Handler的线程上。
2.Registrant中的refH,类型WeakReference,即是说我们的ProxyHandler有可能被回收掉;
3.通过修改mIncomingRingRegistrants只能监控EVENT_INCOMING_RING一种事件,但在整个来电流程中,是涉及多种事件处理的,因此并不能对整个流程进行把控;
因此需要再寻找其它地方进行注入。再回顾一下事件的流程走现,从RIL层开始,如下:
RIL$RILReceiver.run
RIL.readRilMessage
RIL.processResponse
RIL.processUnsolicited
Registrant.notifyRegistrant
Registrant.internalNotifyRegistrant
Handler.sendMessage
Handler.handleMessage
PhoneBase.handleMessage
PhoneBase.notifyIncmoingRing
RegistrantList.notifyRegistrants
RegistrantList.internalNotifyRegistrants
Registrant.internalNotifyRegistrant
Handler.sendMessage
Handler.handleMessage
CallManager.mHandler.handlerMessage(原来是CallManager.handlerMessage,分析有误)
RegistrantList.notifyRegistrants
RegistrantList.internalNotifyRegistrants
Registrant.internalNotifyRegistrant
Handler.sendMessage
Handler.handleMessage
CallNotifier.handleMessage
Ringer.ring(响铃)
...
之前提到的三个可注入点,这次我们选择第二个注入点,即替换CallManager.mHandler中的Handler,这样所有Phone的事件响应,都会经过我们的ProxyHandler(即蓝色的部分的流程),示意代码如下:
CallManagercallmanager=CallManager.getInstance();
try{
Fieldfield=CallManager.class.getDeclaredField("mHandler");
field.setAccessible(true);
Listphones=newArrayList(callmanager.getAllPhones());//第一步,必须先拿到各个phone的引用
//第二步,然后遍历unregister。必须先unregister,然后才能进行第三步
//如果反过来操作,那unregister以及重新register都会有问题
for(Phonephone:phones){
Log.i("NNNN","unregisterphone:"+phone.toString());
callmanager.unregisterPhone(phone);
}
//第三步,通过反射,把CallManager中的mHandler替换到我们的ProxyHandler
Handlerhandler=(Handler)field.get(callmanager);
Log.i("NNNN","org:"+handler.toString());
handler=newProxyHandler(handler);
field.set(callmanager,handler);
handler=(Handler)field.get(callmanager);
Log.i("NNNN","hook:"+handler.toString());
//第四步,重新注册。这里必须用往第一步的phones,而不是通过callmanager.getAllPhones()
//因为unregisterPhone和registerPhone会直接修改callmanager中的mPhones,因此第一步必须先保存各个phone的引用
for(Phonephone:phones){
Log.i("NNNN","registerphone:"+phone.toString());
callmanager.registerPhone(phone);
}
}catch(Exceptione){
e.printStackTrace();
}
接下来是Demo的主要代码,主要是把各种事件打印出来,并且实现了一个很简单的“全拦截”功能,效果是手机没有任何闪屏、响铃或者振动现象。下面是修改后的ProxyHandler完整代码:
publicfinalclassProxyHandlerextendsHandler{
privateSparseArraymTable=newSparseArray();
privateHandlermInnterHandler;
publicProxyHandler(Handlerhandler){
super(handler.getLooper());
mInnterHandler=handler;
mTable.put(100,"EVENT_DISCONNECT");
mTable.put(101,"EVENT_PRECISE_CALL_STATE_CHANGED");
mTable.put(102,"EVENT_NEW_RINGING_CONNECTION");
mTable.put(103,"EVENT_UNKNOWN_CONNECTION");
mTable.put(104,"EVENT_INCOMING_RING");
mTable.put(105,"EVENT_RINGBACK_TONE");
mTable.put(106,"EVENT_IN_CALL_VOICE_PRIVACY_ON");
mTable.put(107,"EVENT_IN_CALL_VOICE_PRIVACY_OFF");
mTable.put(108,"EVENT_CALL_WAITING");
mTable.put(109,"EVENT_DISPLAY_INFO");
mTable.put(110,"EVENT_SIGNAL_INFO");
mTable.put(111,"EVENT_CDMA_OTA_STATUS_CHANGE");
mTable.put(112,"EVENT_RESEND_INCALL_MUTE");
mTable.put(113,"EVENT_MMI_INITIATE");
mTable.put(114,"EVENT_MMI_COMPLETE");
mTable.put(115,"EVENT_ECM_TIMER_RESET");
mTable.put(116,"EVENT_SUBSCRIPTION_INFO_READY");
mTable.put(117,"EVENT_SUPP_SERVICE_FAILED");
mTable.put(118,"EVENT_SERVICE_STATE_CHANGED");
mTable.put(119,"EVENT_POST_DIAL_CHARACTER");
}
@Override
publicvoidhandleMessage(Messagemsg){
if(msg.what>=100&&msg.what<=119){
Log.i("ProxyPhone","Event:"+mTable.get(msg.what));
}
Phonephone=CallManager.getInstance().getAllPhones().get(0);
CallringingCall=phone.getRingingCall();
StringincomingNumber=null;
if(ringingCall!=null&&ringingCall.getEarliestConnection()!=null){
incomingNumber=ringingCall.getEarliestConnection().getAddress();
}
Log.i("ProxyPhone","incomingNumber:"+incomingNumber);
if(incomingNumber!=null){//遇到有号码则直接返回
return;
}
mInnterHandler.handleMessage(msg);
}
@Override
publicStringtoString(){
return"Proxy"+mInnterHandler.toString();
}
}
代码很简单,在此不做详细分析。
下面进行日志分析
来电,对方挂断:
10-3110:54:03.748:I/ProxyPhone(5339):Event:EVENT_SERVICE_STATE_CHANGED
10-3110:54:13.838:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:13.898:I/ProxyPhone(5339):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3110:54:13.898:I/ProxyPhone(5339):Event:EVENT_NEW_RINGING_CONNECTION
10-3110:54:13.898:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3110:54:14.338:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:14.548:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3110:54:14.678:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:14.888:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:15.078:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:15.408:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:15.598:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:15.888:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:16.078:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:16.398:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:16.608:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:21.568:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:21.728:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:22.058:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:22.208:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:22.588:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:22.668:I/ProxyPhone(5339):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3110:54:22.758:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:54:23.008:I/ProxyPhone(5339):Event:EVENT_DISCONNECT
10-3110:54:23.358:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
来电,我方挂断:
10-3110:57:12.478:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:12.568:I/ProxyPhone(5339):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3110:57:12.568:I/ProxyPhone(5339):Event:EVENT_NEW_RINGING_CONNECTION
10-3110:57:12.568:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3110:57:13.198:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3110:57:13.228:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:13.228:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:13.758:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:13.758:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:14.238:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:14.238:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:14.748:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:14.748:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:15.268:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:15.268:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:15.788:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:15.788:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:16.328:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:16.328:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:16.548:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3110:57:16.678:I/ProxyPhone(5339):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3110:57:16.688:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3110:57:16.808:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:16.808:I/ProxyPhone(5339):Event:EVENT_INCOMING_RING
10-3110:57:16.998:I/ProxyPhone(5339):Event:EVENT_DISCONNECT
10-3110:57:17.248:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
去电,我方挂断:
10-3111:01:02.648:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3111:01:02.648:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3111:01:02.918:I/ProxyPhone(5339):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3111:01:02.918:I/ProxyPhone(5339):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3111:01:02.938:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3111:01:02.938:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3111:01:08.588:I/ProxyPhone(5339):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3111:01:08.588:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3111:01:15.068:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3111:01:15.158:I/ProxyPhone(5339):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3111:01:15.158:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3111:01:15.468:I/ProxyPhone(5339):Event:EVENT_DISCONNECT
10-3111:01:15.788:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
去电,对方挂断:
10-3111:03:21.258:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3111:03:21.258:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3111:03:21.528:I/ProxyPhone(5339):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3111:03:21.528:I/ProxyPhone(5339):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3111:03:21.548:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3111:03:21.548:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3111:03:27.298:I/ProxyPhone(5339):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3111:03:27.298:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3111:03:34.088:I/ProxyPhone(5339):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3111:03:34.798:I/ProxyPhone(5339):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3111:03:35.658:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3111:03:35.758:I/ProxyPhone(5339):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3111:03:35.758:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3111:03:36.088:I/ProxyPhone(5339):Event:EVENT_DISCONNECT
10-3111:03:36.438:I/ProxyPhone(5339):Event:EVENT_PRECISE_CALL_STATE_CHANGED
来电日志(打印incomingNumber):
10-3114:42:17.829:I/ProxyPhone(13253):Event:EVENT_SERVICE_STATE_CHANGED
10-3114:42:17.829:I/ProxyPhone(13253):incomingNumber:null
10-3114:42:30.789:I/ProxyPhone(13253):Event:EVENT_INCOMING_RING
10-3114:42:30.789:I/ProxyPhone(13253):incomingNumber:null
10-3114:42:30.839:I/ProxyPhone(13253):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3114:42:30.839:I/ProxyPhone(13253):incomingNumber:null
10-3114:42:30.859:I/ProxyPhone(13253):Event:EVENT_NEW_RINGING_CONNECTION
10-3114:42:30.859:I/ProxyPhone(13253):incomingNumber:13512720516
10-3114:42:30.859:I/ProxyPhone(13253):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3114:42:30.859:I/ProxyPhone(13253):incomingNumber:13512720516
10-3114:42:31.289:I/ProxyPhone(13253):Event:EVENT_INCOMING_RING
10-3114:42:31.289:I/ProxyPhone(13253):incomingNumber:13512720516
10-3114:42:31.349:I/ProxyPhone(13253):Event:EVENT_INCOMING_RING
10-3114:42:37.889:I/ProxyPhone(13253):incomingNumber:13512720516
10-3114:42:38.109:I/ProxyPhone(13253):Event:EVENT_DISCONNECT
10-3114:42:38.109:I/ProxyPhone(13253):incomingNumber:13512720516
10-3114:42:46.669:I/ProxyPhone(13253):Event:EVENT_INCOMING_RING
10-3114:42:46.669:I/ProxyPhone(13253):incomingNumber:13512720516
10-3114:42:46.729:I/ProxyPhone(13253):Event:EVENT_IN_CALL_VOICE_PRIVACY_OFF
10-3114:42:46.729:I/ProxyPhone(13253):incomingNumber:13512720516
10-3114:42:46.749:I/ProxyPhone(13253):Event:EVENT_NEW_RINGING_CONNECTION
10-3114:42:46.749:I/ProxyPhone(13253):incomingNumber:13512720516
10-3114:42:46.749:I/ProxyPhone(13253):Event:EVENT_PRECISE_CALL_STATE_CHANGED
10-3114:42:46.749:I/ProxyPhone(13253):incomingNumber:13512720516
10-3114:42:47.189:I/ProxyPhone(13253):Event:EVENT_INCOMING_RING
10-3114:42:52.189:I/ProxyPhone(13253):incomingNumber:13512720516
10-3114:42:52.259:I/ProxyPhone(13253):Event:EVENT_INCOMING_RING
10-3114:42:52.259:I/ProxyPhone(13253):incomingNumber:13512720516
10-3114:42:52.489:I/ProxyPhone(13253):Event:EVENT_DISCONNECT
10-3114:42:52.489:I/ProxyPhone(13253):incomingNumber:13512720516
通过日志分析得出如下结论:
1.来电过程中不断会有EVENT_INCOMING_RING事件;
2.无论去电还是来电,无论对方还是我方,挂断都是EVENT_DISCONNECT事件;
3.在EVENT_NEW_RINGING_CONNECTION事件发生后,能可以获取incomingNumber;
因此想更一步完善Demo,可以通过根据EVENT_NEW_RINGING_CONNECTION后,才去获取号码。由于Demo
在接下来的《三》里,我会进一步分析RIL的各种流程,以实现更多有趣的功能,大家敬请关注。
更多相关文章
- 一个android显示远程txt的代码例子
- Android使用GestureDetector实现手势滑动效果
- Android中button实现onclicklistener事件的两种方法
- 点击事件内部类中使用内部类
- 号码归属地查询软件
- Android(安卓)listView 中响应Button点击事件
- Android自定义TextView中的超链接点击事件处理
- Expected receiver of type com.xx.xxxActivity, but got androi
- android JS互交图片点击事件