Telephony之PhoneInterfaceManager(原)

一、概述


        PhoneInterfaceManager是一个Service,在被创建时通过ServiceManager注册自己,他作为Telephony对外的接口,可以接受其他进程向Telephony的请求,我们通过该Service所继承的AIDL文件就能看到他所提供的具体功能:
        @ITelephony.aidl
        interface ITelephony {
            //发起通话
            void dial(String number);
            void call(String callingPackage, String number);
            boolean showCallScreen();
            boolean showCallScreenWithDialpad(boolean showDialpad);
            //挂断通话
            boolean endCall();
            //接听通话
            void answerRingingCall();
            void silenceRinger();
            //通话状态判断
            boolean isOffhook();
            boolean isRinging();
            boolean isIdle();
            boolean isRadioOn();
            boolean isSimPinEnabled();
            void cancelMissedCallsNotification();
            //Pin/Puk码查询
            boolean supplyPin(String pin);
            int getIccPin1RetryCount();
            boolean supplyPuk(String puk, String pin);
            int[] supplyPinReportResult(String pin);
            int[] supplyPukReportResult(String puk, String pin);
            boolean handlePinMmi(String dialString);
            void toggleRadioOnOff();
            boolean setRadio(boolean turnOn);
            boolean setRadioPower(boolean turnOn);
            void updateServiceLocation();
            void enableLocationUpdates();
            void disableLocationUpdates();
            //数据连接业务
            int enableApnType(String type);
            int disableApnType(String type);
            boolean enableDataConnectivity();
            boolean disableDataConnectivity();
            boolean isDataConnectivityPossible();
            Bundle getCellLocation();
            List getNeighboringCellInfo(String callingPkg);
            //通话状态获取
            int getCallState();
            int getDataActivity();
            int getDataState();
            int getActivePhoneType();
            int getCdmaEriIconIndex();
            int getCdmaEriIconMode();
            String getCdmaEriText();
            boolean needsOtaServiceProvisioning();
            int getVoiceMessageCount();
            //网络、数据类型
            int getNetworkType();
            int getDataNetworkType();
            int getVoiceNetworkType();
            boolean hasIccCard();
            int getLteOnCdmaMode();
            List getAllCellInfo();
            void setCellInfoListRate(int rateInMillis);
            String transmitIccLogicalChannel(int cla, int command, int channel, int p1, int p2, int p3, String data);
            String transmitIccBasicChannel(int cla, int command, int p1, int p2, int p3, String data);
            int openIccLogicalChannel(String AID);
            boolean closeIccLogicalChannel(int channel);
            int getLastError();
            byte[] transmitIccSimIO(int fileID, int command, int p1, int p2, int p3, String filePath);
            byte[] getATR();
            //通话中合并、切换、静音、Dtmf处理
            void toggleHold();
            void merge();
            void swap();
            void mute(boolean mute);
            void playDtmfTone(char digit, boolean timedShortCode);
            void stopDtmfTone();
            //添加、删除监听器
            void addListener(ITelephonyListener listener);
            void removeListener(ITelephonyListener listener);
        }

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


二、PhoneInterfaceManager的创建及注册过程


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

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


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


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


3.1、拨号


        当通过PhoneInterfaceManager拨号时,会进入以下流程:
        public void dial(String number) {
            String url = createTelUrl(number);
            if (url == null) {
                return;
            }
            PhoneConstants.State state = mCM.getState();
            if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
                //发送Intent实现拨号
                Intent  intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                mApp.startActivity(intent);
            }
        }

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


3.2、挂断电话


        现在来看挂断电话的操作:
        public boolean endCall() {
            //权限检查
            enforceCallPermission();
            //发送CMD_END_CALL的Message
            return (Boolean) sendRequest(CMD_END_CALL, null);
        }
        private final class MainThreadHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case CMD_END_CALL:
                        request = (MainThreadRequest) msg.obj;
                        boolean hungUp = false;
                        int phoneType = mPhone.getPhoneType();
                        if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
                            //通过PhoneUtils挂断电话
                            hungUp = PhoneUtils.hangupRingingAndActive(mPhone);
                        } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
                            //通过PhoneUtils挂断电话
                            hungUp = PhoneUtils.hangup(mCM);
                        } else {
                            throw new IllegalStateException("Unexpected phone type: " + phoneType);
                        }
                        request.result = hungUp;
                        synchronized (request) {
                            request.notifyAll();
                        }
                        break;
                    default:
                        break;
                }
            }
        }

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


3.3、查询Pin码


        下面看Pin码的操作:
        public boolean supplyPin(String pin) {
            //权限检查
            enforceModifyPermission();
            //通过IccCard来操作
            final UnlockSim checkSimPin = new UnlockSim(mPhone.getIccCard());
            //启用查询线程
            checkSimPin.start();
            return checkSimPin.unlockSim(null, pin);
        }
        看以下线程内部的操作:
        synchronized boolean unlockSim(String puk, String pin) {
            Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
            //通过IccCard来查询Pin、Puk
            if (puk == null) {
                mSimCard.supplyPin(pin, callback);
            } else {
                mSimCard.supplyPuk(puk, pin, callback);
            }
            return mResult;
        }

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


3.4、数据连接业务


        数据连接的开启:
        public boolean disableDataConnectivity() {
            enforceModifyPermission();
            //通过ConnectivityManager来禁用数据连接
            ConnectivityManager cm = (ConnectivityManager)mApp.getSystemService(Context.CONNECTIVITY_SERVICE);
            cm.setMobileDataEnabled(false);
            return true;
        }

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


3.5、小结


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

        如图所示:

        Telephony之PhoneInterfaceManager(原)_第1张图片

你可能感兴趣的:(Telephony,Android)