Telephony之PhoneInterfaceManager

来源:互联网 发布:南京雨花台区网络问政 编辑:程序博客网 时间:2024/05/01 11:49

一、概述


        PhoneInterfaceManager是一个Service,在被创建时通过ServiceManager注册自己,他作为Telephony对外的接口,可以接受其他进程向Telephony的请求,我们通过该Service所继承的AIDL文件就能看到他所提供的具体功能:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @ITelephony.aidl  
  2. interface ITelephony {  
  3.     //发起通话  
  4.     void dial(String number);  
  5.     void call(String callingPackage, String number);  
  6.     boolean showCallScreen();  
  7.     boolean showCallScreenWithDialpad(boolean showDialpad);  
  8.     //挂断通话  
  9.     boolean endCall();  
  10.     //接听通话  
  11.     void answerRingingCall();  
  12.     void silenceRinger();  
  13.     //通话状态判断  
  14.     boolean isOffhook();  
  15.     boolean isRinging();  
  16.     boolean isIdle();  
  17.     boolean isRadioOn();  
  18.     boolean isSimPinEnabled();  
  19.     void cancelMissedCallsNotification();  
  20.     //Pin/Puk码查询  
  21.     boolean supplyPin(String pin);  
  22.     int getIccPin1RetryCount();  
  23.     boolean supplyPuk(String puk, String pin);  
  24.     int[] supplyPinReportResult(String pin);  
  25.     int[] supplyPukReportResult(String puk, String pin);  
  26.     boolean handlePinMmi(String dialString);  
  27.     void toggleRadioOnOff();  
  28.     boolean setRadio(boolean turnOn);  
  29.     boolean setRadioPower(boolean turnOn);  
  30.     void updateServiceLocation();  
  31.     void enableLocationUpdates();  
  32.     void disableLocationUpdates();  
  33.     //数据连接业务  
  34.     int enableApnType(String type);  
  35.     int disableApnType(String type);  
  36.     boolean enableDataConnectivity();  
  37.     boolean disableDataConnectivity();  
  38.     boolean isDataConnectivityPossible();  
  39.     Bundle getCellLocation();  
  40.     List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg);  
  41.     //通话状态获取  
  42.     int getCallState();  
  43.     int getDataActivity();  
  44.     int getDataState();  
  45.     int getActivePhoneType();  
  46.     int getCdmaEriIconIndex();  
  47.     int getCdmaEriIconMode();  
  48.     String getCdmaEriText();  
  49.     boolean needsOtaServiceProvisioning();  
  50.     int getVoiceMessageCount();  
  51.     //网络、数据类型  
  52.     int getNetworkType();  
  53.     int getDataNetworkType();  
  54.     int getVoiceNetworkType();  
  55.     boolean hasIccCard();  
  56.     int getLteOnCdmaMode();  
  57.     List<CellInfo> getAllCellInfo();  
  58.     void setCellInfoListRate(int rateInMillis);  
  59.     String transmitIccLogicalChannel(int cla, int command, int channel, int p1, int p2, int p3, String data);  
  60.     String transmitIccBasicChannel(int cla, int command, int p1, int p2, int p3, String data);  
  61.     int openIccLogicalChannel(String AID);  
  62.     boolean closeIccLogicalChannel(int channel);  
  63.     int getLastError();  
  64.     byte[] transmitIccSimIO(int fileID, int command, int p1, int p2, int p3, String filePath);  
  65.     byte[] getATR();  
  66.     //通话中合并、切换、静音、Dtmf处理  
  67.     void toggleHold();  
  68.     void merge();  
  69.     void swap();  
  70.     void mute(boolean mute);  
  71.     void playDtmfTone(char digit, boolean timedShortCode);  
  72.     void stopDtmfTone();  
  73.     //添加、删除监听器  
  74.     void addListener(ITelephonyListener listener);  
  75.     void removeListener(ITelephonyListener listener);  
  76. }  

        从他所提供的接口来看,其提供了Telephony比较全面的功能,包括:通话、Pin/Puk、Radio状态、数据连接业务等功能的查询或控制


二、PhoneInterfaceManager的创建及注册过程


        PhoneInterfaceManager是在PhoneGlobals的onCreate()中被创建的:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. phoneMgr = PhoneInterfaceManager.init(this, phone, callHandlerServiceProxy);  
        我们来看具体的创建过程:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @PhoneInterfaceManager.java  
  2. static PhoneInterfaceManager init(PhoneGlobals app, Phone phone, CallHandlerServiceProxy callHandlerService) {  
  3.     synchronized (PhoneInterfaceManager.class) {  
  4.         if (sInstance == null) {  
  5.             //创建对象  
  6.             sInstance = new PhoneInterfaceManager(app, phone, callHandlerService);  
  7.         } else {  
  8.             Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);  
  9.         }  
  10.         return sInstance;  
  11.     }  
  12. }  
        继续看构造方法:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private PhoneInterfaceManager(PhoneGlobals app, Phone phone, CallHandlerServiceProxy callHandlerService) {  
  2.     mApp = app;  
  3.     mPhone = phone;  
  4.     mCM = PhoneGlobals.getInstance().mCM;  
  5.     mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);  
  6.     mMainThreadHandler = new MainThreadHandler();  
  7.     mCallHandlerService = callHandlerService;  
  8.     publish();  
  9. }  
        在构造方法中除了将PhoneGlobals中初始化的Phone、CallManager等信息传递给PhoneInterfaceManager外,还将PhoneInterfaceManager通过publish()注册给ServiceManager:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private void publish() {  
  2.     //注册给ServiceManager,名字是“phone”  
  3.     ServiceManager.addService("phone"this);  
  4. }  

        这里看到,PhoneInterfaceManager将自己注册为SystemServer,其他模块可以通过ServiceManager来获取他的服务


三、PhoneInterfaceManager对客户端请求的处理


        客户端通过ServiceManager获取到PhoneInterfaceManager的代理对象后,就可以对其发起各种请求,我们挑选几个比较重要的事务来简要分析。


3.1、拨号


        当通过PhoneInterfaceManager拨号时,会进入以下流程:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public void dial(String number) {  
  2.     String url = createTelUrl(number);  
  3.     if (url == null) {  
  4.         return;  
  5.     }  
  6.     PhoneConstants.State state = mCM.getState();  
  7.     if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {  
  8.         //发送Intent实现拨号  
  9.         Intent  intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));  
  10.         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  11.         mApp.startActivity(intent);  
  12.     }  
  13. }  

        这里可以看到,PhoneInterfaceManager会通过Intent的形式发起拨号的任务


3.2、挂断电话


        现在来看挂断电话的操作:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public boolean endCall() {  
  2.     //权限检查  
  3.     enforceCallPermission();  
  4.     //发送CMD_END_CALL的Message  
  5.     return (Boolean) sendRequest(CMD_END_CALL, null);  
  6. }  
  7. private final class MainThreadHandler extends Handler {  
  8.     @Override  
  9.     public void handleMessage(Message msg) {  
  10.         switch (msg.what) {  
  11.             case CMD_END_CALL:  
  12.                 request = (MainThreadRequest) msg.obj;  
  13.                 boolean hungUp = false;  
  14.                 int phoneType = mPhone.getPhoneType();  
  15.                 if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {  
  16.                     //通过PhoneUtils挂断电话  
  17.                     hungUp = PhoneUtils.hangupRingingAndActive(mPhone);  
  18.                 } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {  
  19.                     //通过PhoneUtils挂断电话  
  20.                     hungUp = PhoneUtils.hangup(mCM);  
  21.                 } else {  
  22.                     throw new IllegalStateException("Unexpected phone type: " + phoneType);  
  23.                 }  
  24.                 request.result = hungUp;  
  25.                 synchronized (request) {  
  26.                     request.notifyAll();  
  27.                 }  
  28.                 break;  
  29.             default:  
  30.                 break;  
  31.         }  
  32.     }  
  33. }  

        在这里,PhoneInterfaceManager又将请求传给了PhoneUtils来处理结束通话的操作


3.3、查询Pin码


        下面看Pin码的操作:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public boolean supplyPin(String pin) {  
  2.     //权限检查  
  3.     enforceModifyPermission();  
  4.     //通过IccCard来操作  
  5.     final UnlockSim checkSimPin = new UnlockSim(mPhone.getIccCard());  
  6.     //启用查询线程  
  7.     checkSimPin.start();  
  8.     return checkSimPin.unlockSim(null, pin);  
  9. }  
        看以下线程内部的操作:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. synchronized boolean unlockSim(String puk, String pin) {  
  2.     Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);  
  3.     //通过IccCard来查询Pin、Puk  
  4.     if (puk == null) {  
  5.         mSimCard.supplyPin(pin, callback);  
  6.     } else {  
  7.         mSimCard.supplyPuk(puk, pin, callback);  
  8.     }  
  9.     return mResult;  
  10. }  

        可以看到,最终是通过IccCard来实现Pin、Puk的查询


3.4、数据连接业务


        数据连接的开启:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public boolean disableDataConnectivity() {  
  2.     enforceModifyPermission();  
  3.     //通过ConnectivityManager来禁用数据连接  
  4.     ConnectivityManager cm = (ConnectivityManager)mApp.getSystemService(Context.CONNECTIVITY_SERVICE);  
  5.     cm.setMobileDataEnabled(false);  
  6.     return true;  
  7. }  

        这里又通过ConnectivityManager来禁用数据连接业务


3.5、小结


        经过以上几个请求的解析,我们发现,PhoneInterfaceManager自身并没有完成请求的功能,而是把客户端的请求分配给相应领域的管理者,也可以这样理解,PhoneInterfaceManager作为Telephony框架对外的“接口人”,接收客户的请求后,将请求发送给真正的“主人”去实现。

        如图所示:

        

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小孩爱动怎么办补什么 初中孩子下午上课总犯困怎么办 孩子上课精神不集中怎么办 孩子玩兴奋了就打人怎么办 婴儿兴奋白天不睡觉怎么办 小孩读书精神不集中怎么办 小孩上课精神不集中怎么办 小孩学习精神不集中怎么办 孩子暑假天天看电视不出门怎么办 七个月宝宝缺铁怎么办 天天运动为什么还便秘怎么办 小孩学习注意力不集中怎么办 8个月宝贝太好动怎么办 学生在校受伤家长该怎么办 多动症小孩爱动手指怎么办 孩子大了不听话该怎么办 流产后吹了风怎么办 怀孕1周内喝酒了怎么办 怀孕6周喝酒了怎么办 怀孕后喝了酒怎么办 不知道怀孕喝酒了怎么办 不知道怀孕了喝酒了怎么办 怀孕5天喝酒了怎么办 打孩子耳光后脸肿了怎么办 老师说上课不专心怎么办 孩子不专心好动马虎怎么办 学生上课不认真听讲怎么办 一年级孩子上课不注意听讲怎么办 一年级孩子上课说话不听课怎么办 一年级孩子上课不听课怎么办 小学一年级学生上课不专心怎么办? 小孩听课注意力不集中怎么办 小孩子上课精神不集中怎么办 孩子说我不画了怎么办 幼儿园小朋友上课不专心怎么办 孩子写作业不专心怎么办 小孩做作业不专心怎么办 孩子上课精力不集中怎么办 四岁宝宝吃饭慢怎么办 5岁宝宝吃饭慢怎么办 小学一年级上课不专心怎么办