原文相续,书接上一回。
在《Android RIL层实现来电拦截的技术原理(一)》(以下简称《一》),已经详细分析了来电的在RIL层的逻辑走向,但缺少了一个强有力的DEMO作为验证。于是花了些时间,把DEMO也弄出来了,也验证了这个方案的技术可性性。在DEMO的开发过程中,也发现了一些在《一》中错误,等下会说明。
在《一》中,通过JAVA的反射机制,取出位于CallManager中的mIncomingRingRegistrants字段,再通过自定义的ProxyHandler,把定义在mIncomingRingRegistrants里的Handler替换掉,以实现“截获”这个动作。再回顾一下之前的代码实现:
class ProxyHandler extends Handler {
private Handler mInnter;
public ProxyHandler(Handler h){
mInnter = h;
}
@Override
public void handleMessage(Message msg) {
//做爱做的事
// ......
// ......
mInnter.handlerMessage(msg);
}
}
CallManager instance = CallManager.getInstance();
//通过反射,拿到其字段mIncomingRingRegistrants
RegistrantList mIncomingRingRegistrants = instance.mIncomingRingRegistrants;
for(int i=0; i<mIncomingRingRegistrants.size(); i++){
Registrant item = mIncomingRingRegistrants.get(i);
Handler handler = item.getHandler();
//通过反射,拿到其字段refH
item.refH = new WeakReference(new ProxyHandler(handler)); //完成注入
}
这里存在三个问题,如下:
1. ProxyHandler的构造函数,由于是在一个非Looper线程上执行,因为会发生异常,应该改 为
public ProxyHandler(Handler h){
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