基于Android RIL层实现来电拦截的技术原理(二)

来源:互联网 发布:oracle数据库启动 编辑:程序博客网 时间:2024/05/13 04:23

原文相续,书接上一回。

在《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

Handler.handleMessage

CallNotifier.handleMessage

Ringer.ring(响铃)

...





之前提到的三个可注入点,这次我们选择第二个注入点,即替换CallManager.mHandler中的Handler,这样所有Phone的事件响应,都会经过我们的ProxyHandler(即蓝色的部分的流程),示意代码如下:



CallManager callmanager = CallManager.getInstance();


try{

     Field field = CallManager.class.getDeclaredField("mHandler");

     field.setAccessible(true);

     List phones = new ArrayList(callmanager.getAllPhones()); //第一步,必须先拿到各个phone的引用



//第二步,然后遍历unregister。必须先unregister,然后才能进行第三步

//如果反过来操作,那unregister以及重新register都会有问题

for(Phone phone : phones){ 

   Log.i("NNNN""unregister phone: " + phone.toString());

   callmanager.unregisterPhone(phone);

}



//第三步,通过反射,把CallManager中的mHandler替换到我们的ProxyHandler

Handler handler = (Handler) field.get(callmanager);

Log.i("NNNN""org: " + handler.toString());


handler = new ProxyHandler(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(Phone phone : phones){

  Log.i("NNNN""register phone: " + phone.toString());

  callmanager.registerPhone(phone);

}



}catch(Exception e){

  e.printStackTrace();

}



  接下来是Demo的主要代码,主要是把各种事件打印出来,并且实现了一个很简单的“全拦截”功能,效果是手机没有任何闪屏、响铃或者振动现象。下面是修改后的ProxyHandler完整代码:

public final class ProxyHandler extends Handler {

  private SparseArray mTable = new SparseArray();

  private Handler mInnterHandler;


  public ProxyHandler(Handler handler){

    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

public void handleMessage(Message msg) {

if(msg.what >= 100 && msg.what <= 119){

  Log.i("ProxyPhone""Event: " + mTable.get(msg.what));

}


Phone phone = CallManager.getInstance().getAllPhones().get(0);

Call ringingCall = phone.getRingingCall();

String incomingNumber = null;

if (ringingCall != null && ringingCall.getEarliestConnection() != null) {

  incomingNumber = ringingCall.getEarliestConnection().getAddress();

}


Log.i("ProxyPhone""incomingNumber: " + incomingNumber);

if(incomingNumber != null){ //遇到有号码则直接返回

  return;

}


mInnterHandler.handleMessage(msg);

}


@Override

public String toString() {

  return "Proxy " + mInnterHandler.toString();

}


}


代码很简单,在此不做详细分析。



下面进行日志分析



来电,对方挂断:

10-31 10:54:03.748: I/ProxyPhone(5339): Event: EVENT_SERVICE_STATE_CHANGED

10-31 10:54:13.838: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:13.898: I/ProxyPhone(5339): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 10:54:13.898: I/ProxyPhone(5339): Event: EVENT_NEW_RINGING_CONNECTION

10-31 10:54:13.898: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 10:54:14.338: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:14.548: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 10:54:14.678: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:14.888: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:15.078: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:15.408: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:15.598: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:15.888: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:16.078: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:16.398: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:16.608: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:21.568: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:21.728: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:22.058: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:22.208: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:22.588: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:22.668: I/ProxyPhone(5339): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 10:54:22.758: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:54:23.008: I/ProxyPhone(5339): Event: EVENT_DISCONNECT

10-31 10:54:23.358: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED



来电,我方挂断:

10-31 10:57:12.478: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:12.568: I/ProxyPhone(5339): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 10:57:12.568: I/ProxyPhone(5339): Event: EVENT_NEW_RINGING_CONNECTION

10-31 10:57:12.568: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 10:57:13.198: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 10:57:13.228: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:13.228: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:13.758: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:13.758: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:14.238: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:14.238: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:14.748: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:14.748: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:15.268: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:15.268: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:15.788: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:15.788: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:16.328: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:16.328: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:16.548: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 10:57:16.678: I/ProxyPhone(5339): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 10:57:16.688: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 10:57:16.808: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:16.808: I/ProxyPhone(5339): Event: EVENT_INCOMING_RING

10-31 10:57:16.998: I/ProxyPhone(5339): Event: EVENT_DISCONNECT

10-31 10:57:17.248: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED



去电,我方挂断:

10-31 11:01:02.648: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 11:01:02.648: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 11:01:02.918: I/ProxyPhone(5339): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 11:01:02.918: I/ProxyPhone(5339): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 11:01:02.938: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 11:01:02.938: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 11:01:08.588: I/ProxyPhone(5339): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 11:01:08.588: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 11:01:15.068: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 11:01:15.158: I/ProxyPhone(5339): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 11:01:15.158: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 11:01:15.468: I/ProxyPhone(5339): Event: EVENT_DISCONNECT

10-31 11:01:15.788: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED



去电,对方挂断:

10-31 11:03:21.258: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 11:03:21.258: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 11:03:21.528: I/ProxyPhone(5339): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 11:03:21.528: I/ProxyPhone(5339): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 11:03:21.548: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 11:03:21.548: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 11:03:27.298: I/ProxyPhone(5339): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 11:03:27.298: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 11:03:34.088: I/ProxyPhone(5339): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 11:03:34.798: I/ProxyPhone(5339): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 11:03:35.658: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 11:03:35.758: I/ProxyPhone(5339): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 11:03:35.758: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 11:03:36.088: I/ProxyPhone(5339): Event: EVENT_DISCONNECT

10-31 11:03:36.438: I/ProxyPhone(5339): Event: EVENT_PRECISE_CALL_STATE_CHANGED



来电日志(打印incomingNumber):

10-31 14:42:17.829: I/ProxyPhone(13253): Event: EVENT_SERVICE_STATE_CHANGED

10-31 14:42:17.829: I/ProxyPhone(13253): incomingNumber: null

10-31 14:42:30.789: I/ProxyPhone(13253): Event: EVENT_INCOMING_RING

10-31 14:42:30.789: I/ProxyPhone(13253): incomingNumber: null

10-31 14:42:30.839: I/ProxyPhone(13253): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 14:42:30.839: I/ProxyPhone(13253): incomingNumber: null

10-31 14:42:30.859: I/ProxyPhone(13253): Event: EVENT_NEW_RINGING_CONNECTION

10-31 14:42:30.859: I/ProxyPhone(13253): incomingNumber: 13512720516

10-31 14:42:30.859: I/ProxyPhone(13253): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 14:42:30.859: I/ProxyPhone(13253): incomingNumber: 13512720516

10-31 14:42:31.289: I/ProxyPhone(13253): Event: EVENT_INCOMING_RING

10-31 14:42:31.289: I/ProxyPhone(13253): incomingNumber: 13512720516

10-31 14:42:31.349: I/ProxyPhone(13253): Event: EVENT_INCOMING_RING

10-31 14:42:37.889: I/ProxyPhone(13253): incomingNumber: 13512720516

10-31 14:42:38.109: I/ProxyPhone(13253): Event: EVENT_DISCONNECT

10-31 14:42:38.109: I/ProxyPhone(13253): incomingNumber: 13512720516

10-31 14:42:46.669: I/ProxyPhone(13253): Event: EVENT_INCOMING_RING

10-31 14:42:46.669: I/ProxyPhone(13253): incomingNumber: 13512720516

10-31 14:42:46.729: I/ProxyPhone(13253): Event: EVENT_IN_CALL_VOICE_PRIVACY_OFF

10-31 14:42:46.729: I/ProxyPhone(13253): incomingNumber: 13512720516

10-31 14:42:46.749: I/ProxyPhone(13253): Event: EVENT_NEW_RINGING_CONNECTION

10-31 14:42:46.749: I/ProxyPhone(13253): incomingNumber: 13512720516

10-31 14:42:46.749: I/ProxyPhone(13253): Event: EVENT_PRECISE_CALL_STATE_CHANGED

10-31 14:42:46.749: I/ProxyPhone(13253): incomingNumber: 13512720516

10-31 14:42:47.189: I/ProxyPhone(13253): Event: EVENT_INCOMING_RING

10-31 14:42:52.189: I/ProxyPhone(13253): incomingNumber: 13512720516

10-31 14:42:52.259: I/ProxyPhone(13253): Event: EVENT_INCOMING_RING

10-31 14:42:52.259: I/ProxyPhone(13253): incomingNumber: 13512720516

10-31 14:42:52.489: I/ProxyPhone(13253): Event: EVENT_DISCONNECT

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