原文相续,书接上一回。

在《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的各种流程,以实现更多有趣的功能,大家敬请关注。


更多相关文章

  1. 一个android显示远程txt的代码例子
  2. Android使用GestureDetector实现手势滑动效果
  3. Android中button实现onclicklistener事件的两种方法
  4. 点击事件内部类中使用内部类
  5. 号码归属地查询软件
  6. Android(安卓)listView 中响应Button点击事件
  7. Android自定义TextView中的超链接点击事件处理
  8. Expected receiver of type com.xx.xxxActivity, but got androi
  9. android JS互交图片点击事件

随机推荐

  1. Android官方入门文档[14]停止和重新启动
  2. 安卓编程小tips
  3. 从eclipse中导出项目到android studio。
  4. Android高仿网易新闻客户端之动态添加标
  5. Android 快速将一个Bitmap变成圆形或圆角
  6. android emulator 配置_
  7. Android Jetpack架构组件Navigation管理F
  8. Android(安卓)Multiple Screens Android(
  9. Android ImageView控件的MaxWidth、MaxHe
  10. 实现Android计时与倒计时方法