基於Android RIL層實現來電攔截的技術原理(二)

原文相續,書接上一回。

在《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的各種流程,以實現更多有趣的功能,大家敬請關注。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章