zoukankan      html  css  js  c++  java
  • android接收短信——framework处理流程(android 5.1)

    modem层不懂,所以直接从RIL.java开始。以电信卡接收短信为例

    modem通知RIL.java中的 RILReceiver处理接收信息

    class RILReceiver implements Runnable {
            byte[] buffer;
    
            RILReceiver() {
                buffer = new byte[RIL_MAX_COMMAND_BYTES];
            }
    
            @Override
            public void
            run() {
                       ......
                        //建立socked连接,读取数据
        
                        processResponse(p);
                    ......
            }
    }
    private void
        processResponse (Parcel p) {
            int type;
    
            type = p.readInt();
    
            if (type == RESPONSE_UNSOLICITED) {
                processUnsolicited (p); //接收短息会进入这里
            } else if (type == RESPONSE_SOLICITED) {
                RILRequest rr = processSolicited (p);
                if (rr != null) {
                    rr.release();
                    decrementWakeLock();
                }
            }
        }
    
    
    processUnsolicited(Parcel p)方法中,罗列了各种类型的信息,
    processUnsolicited (Parcel p) {
            int response;
            Object ret;
    
            response = p.readInt();        try {switch(response) {
    /*
     cat libs/telephony/ril_unsol_commands.h 
     | egrep "^ *{RIL_" 
     | sed -re 's/{([^,]+),[^,]+,([^}]+).+/case 1: 2(rr, p); break;/'
    */
    
                case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: ret =  responseVoid(p); break;
                case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: ret =  responseVoid(p); break;
                case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: ret =  responseVoid(p); break;
                case RIL_UNSOL_RESPONSE_NEW_SMS: ret =  responseString(p); break;
                case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: ret =  responseString(p); break;
                case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: ret =  responseInts(p); break;
                case RIL_UNSOL_ON_USSD: ret =  responseStrings(p); break;
                case RIL_UNSOL_NITZ_TIME_RECEIVED: ret =  responseString(p); break;
                case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break;
                case RIL_UNSOL_DATA_CALL_LIST_CHANGED: ret = responseDataCallList(p);break;
                case RIL_UNSOL_SUPP_SVC_NOTIFICATION: ret = responseSuppServiceNotification(p); break;
                case RIL_UNSOL_STK_SESSION_END: ret = responseVoid(p); break;
                case RIL_UNSOL_STK_PROACTIVE_COMMAND: ret = responseString(p); break;
                case RIL_UNSOL_STK_EVENT_NOTIFY: ret = responseString(p); break;
                case RIL_UNSOL_STK_CALL_SETUP: ret = responseInts(p); break;
                case RIL_UNSOL_SIM_SMS_STORAGE_FULL: ret =  responseVoid(p); break;
                case RIL_UNSOL_SIM_REFRESH: ret =  responseSimRefresh(p); break;
                case RIL_UNSOL_CALL_RING: ret =  responseCallRing(p); break;
                case RIL_UNSOL_RESTRICTED_STATE_CHANGED: ret = responseInts(p); break;
                case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED:  ret =  responseVoid(p); break;
                case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS:  ret =  responseCdmaSms(p); break;
                case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS:  ret =  responseRaw(p); break;
                case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL:  ret =  responseVoid(p); break;
                case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
                case RIL_UNSOL_CDMA_CALL_WAITING: ret = responseCdmaCallWaiting(p); break;
                case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: ret = responseInts(p); break;
                case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInformationRecord(p); break;
                case RIL_UNSOL_OEM_HOOK_RAW: ret = responseRaw(p); break;
                case RIL_UNSOL_RINGBACK_TONE: ret = responseInts(p); break;
                case RIL_UNSOL_RESEND_INCALL_MUTE: ret = responseVoid(p); break;
                case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: ret = responseInts(p); break;
                case RIL_UNSOl_CDMA_PRL_CHANGED: ret = responseInts(p); break;
                case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
                case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break;
                case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED: ret =  responseInts(p); break;
                case RIL_UNSOL_CELL_INFO_LIST: ret = responseCellInfoList(p); break;
                case RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED: ret =  responseVoid(p); break;
                case RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED: ret =  responseInts(p); break;
                case RIL_UNSOL_SRVCC_STATE_NOTIFY: ret = responseInts(p); break;
                case RIL_UNSOL_HARDWARE_CONFIG_CHANGED: ret = responseHardwareConfig(p); break;
                case RIL_UNSOL_RADIO_CAPABILITY:
                        ret = responseRadioCapability(p); break;
                case RIL_UNSOL_ON_SS: ret =  responseSsData(p); break;
                case RIL_UNSOL_STK_CC_ALPHA_NOTIFY: ret =  responseString(p); break;
                case RIL_UNSOL_LCEDATA_RECV: ret = responseLceData(p); break;

    电信卡接收信息,是 RIL_UNSOL_RESPONSE_CDMA_NEW_SMS

    case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS:
                    if (RILJ_LOGD) unsljLog(response);
    
                    SmsMessage sms = (SmsMessage) ret;
    
                    if (mCdmaSmsRegistrant != null) {
                        mCdmaSmsRegistrant
                            .notifyRegistrant(new AsyncResult(null, sms, null)); //mCdmaSmsRegistrant 在 CdmaInboundSmsHandler 初始化时创建
                    }
                    break;
    public void
        notifyRegistrant(AsyncResult ar)
        {
            internalNotifyRegistrant (ar.result, ar.exception);
        }
    
        /*package*/ void
        internalNotifyRegistrant (Object result, Throwable exception)
        {
            Handler h = getHandler();
    
            if (h == null) {
                clear();
            } else {
                Message msg = Message.obtain();
    
                msg.what = what;
                
                msg.obj = new AsyncResult(userObj, result, exception);
                
                h.sendMessage(msg); //handler来处理接收信息事件
            }
        }
    mCdmaSmsRegistrant.notifyRegistrant(..)就进入状态机(StateMachine)处理了。处理的信息接收的状态机是 InboundSmsHandler extends StateMachine
    InboundSmsHandler是抽象类,对于CDMA信息是 CdmaInboundSmsHandler extends InboundSmsHandler, 对于GSM信息是 GsmInboundSmsHandler extends InboundSmsHandler

    关于CdmaInboundSmsHandler 状态机是何时启动并初始化的,细节没研究。应该是在手机启动后,一系列系统服务启动时完成的。
    看看CdmaInboundSmsHandler 的构造函数  
    /**
         * Create a new inbound SMS handler for CDMA.
         */
        private CdmaInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
                PhoneBase phone, CdmaSMSDispatcher smsDispatcher) {
            super("CdmaInboundSmsHandler", context, storageMonitor, phone,
                    CellBroadcastHandler.makeCellBroadcastHandler(context, phone));
            mSmsDispatcher = smsDispatcher;
            mServiceCategoryProgramHandler = CdmaServiceCategoryProgramHandler.makeScpHandler(context,
                    phone.mCi);
            phone.mCi.setOnNewCdmaSms(getHandler(), EVENT_NEW_SMS, null); //这里构造了RIL中需要的 mCdmaSmsRegistrant
    }
     public void setOnNewCdmaSms(Handler h, int what, Object obj) {
            mCdmaSmsRegistrant = new Registrant (h, what, obj);
     }
    /**
         * Wait for state machine to enter startup state. We can't send any messages until then.
         */
        public static CdmaInboundSmsHandler makeInboundSmsHandler(Context context,
                SmsStorageMonitor storageMonitor, PhoneBase phone, CdmaSMSDispatcher smsDispatcher) {
            CdmaInboundSmsHandler handler = new CdmaInboundSmsHandler(context, storageMonitor,
                    phone, smsDispatcher); //构造CdmaInboudSmsHandler状态机
            handler.start(); //启动 state machine
            return handler;
        }

    在CdmaInboudSmsHandler初始化会调用父类InboundSmsHandler的构造函数,会增加各种状态。

    protected InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor,
                PhoneBase phone, CellBroadcastHandler cellBroadcastHandler) {
            super(name);
            ......
    
            addState(mDefaultState);
            addState(mStartupState, mDefaultState);
            addState(mIdleState, mDefaultState);
            addState(mDeliveringState, mDefaultState);
                addState(mWaitingState, mDeliveringState);
    
            setInitialState(mStartupState);
            if (DBG) log("created InboundSmsHandler");
        }

    综上,RILReceiver接收信息,进入状态机CdmaInboundSmsHandler处理,具体是父类StateMachine中的Hanler传递消息,并切换各状态(state)处理。

    状态: mDefaultState,mStartupState,mIdleState,mDeliveringState,mWaitingState以及默认的QuitSatte, HaltState。
    各状态是如何切换处理的? 没搞明白。有待研究。

    接收信息最终传递处理在 mDeliveringState中 (代码实现在InboundsSmsHandler.java中)
     class DeliveringState extends State {
            @Override
            public void enter() {
                if (DBG) log("entering Delivering state");
            }
    
            @Override
            public void exit() {
                if (DBG) log("leaving Delivering state");
            }
    
            @Override
            public boolean processMessage(Message msg) {
                log("DeliveringState.processMessage:" + msg.what);
                switch (msg.what) {
                    case EVENT_NEW_SMS:
                        // handle new SMS from RIL
                        handleNewSms((AsyncResult) msg.obj); //继续处理新接收的信息
                        sendMessage(EVENT_RETURN_TO_IDLE);
                        return HANDLED;
    void handleNewSms(AsyncResult ar) {
            if (ar.exception != null) {
                loge("Exception processing incoming SMS: " + ar.exception);
                return;
            }
    
            int result;
            try {
                SmsMessage sms = (SmsMessage) ar.result;
                result = dispatchMessage(sms.mWrappedSmsMessage);  //信息传递处理完成,并返回结果
            } catch (RuntimeException ex) {
                loge("Exception dispatching message", ex);
                result = Intents.RESULT_SMS_GENERIC_ERROR;
            }
    
            // RESULT_OK means that the SMS will be acknowledged by special handling,
            // e.g. for SMS-PP data download. Any other result, we should ack here.
            if (result != Activity.RESULT_OK) {  //注意这里的返回结果,一般是 Intents.RESULT_SMS_HANDLED,才可以继续反馈 ack 到 smsc
                boolean handled = (result == Intents.RESULT_SMS_HANDLED);
                notifyAndAcknowledgeLastIncomingSms(handled, result, null);  //这里返回ACK给短信中心(smsc),表示信息已接收。
            }
        }
     void notifyAndAcknowledgeLastIncomingSms(boolean success,
                int result, Message response) {
            if (!success) {
                // broadcast SMS_REJECTED_ACTION intent
                Intent intent = new Intent(Intents.SMS_REJECTED_ACTION);
                intent.putExtra("result", result);
                mContext.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS);
            }
            acknowledgeLastIncomingSms(success, result, response);
        }

    protected abstract void acknowledgeLastIncomingSms(boolean success,
    int result, Message response); //具体实现在 CdmaInboundsSmsHandler 或 GsmInboundSmsHandler中
    CdmaInboundsSmsHandler中处理acknowledgeLastIncomingSms
    @Override
        protected void acknowledgeLastIncomingSms(boolean success, int result, Message response) {
            if (isInEmergencyCallMode()) {
                return;
            }
    
            int causeCode = resultToCause(result);
            mPhone.mCi.acknowledgeLastIncomingCdmaSms(success, causeCode, response); //这里又回到RIL中处理
    
            if (causeCode == 0) {
                mLastAcknowledgedSmsFingerprint = mLastDispatchedSmsFingerprint;
            }
            mLastDispatchedSmsFingerprint = null;
        }

    RIL中用 RILSender 处理返回ACK, 

     public void
        acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message result) {
            RILRequest rr
                    = RILRequest.obtain(RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE, result);
    
            rr.mParcel.writeInt(success ? 0 : 1); //RIL_CDMA_SMS_ErrorClass
            // cause code according to X.S004-550E
            rr.mParcel.writeInt(cause);
    
            if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                    + " " + success + " " + cause);
    
            send(rr);
        }

    再看看信息传递处理dispatchMessage()

    public int dispatchMessage(SmsMessageBase smsb) {
            // If sms is null, there was a parsing error.
            if (smsb == null) {
                loge("dispatchSmsMessage: message is null");
                return Intents.RESULT_SMS_GENERIC_ERROR;
            }
    
            if (mSmsReceiveDisabled) {
                // Device doesn't support receiving SMS,
                log("Received short message on device which doesn't support "
                        + "receiving SMS. Ignored.");
                return Intents.RESULT_SMS_HANDLED;
            }
    
            return dispatchMessageRadioSpecific(smsb);
        }

    protected abstract int dispatchMessageRadioSpecific(SmsMessageBase smsb);
     

    InboundsSmsHandler中的dispatchMessageRadioSpecific(..)是抽象的,具体处理在CdmaInboundSmsHandler 或 GsmInboundSmsHandler中

    然后会将新信息,用广播传递给MMS应用处理。 





  • 相关阅读:
    每日总结:DIV弹层遮盖、DIV设置透明背景色、JS调用SharePoint 中的SP.UI.ModalDialog弹出遮盖层显示
    八、WinForm客户端的配置与使用
    11.1 使用框架应具备哪些知识或技能?
    五、框架的结构
    11.2 如何取得汉字的拼音或者拼音首字母缩写?
    九、IBeamMDAA的Web客户端的配置与使用
    六、框架的应用服务器配置
    十、IBeamUtility的使用
    七、IBeamMDAA在IIS宿主服务器的配置
    三、框架的目标与解决的问题
  • 原文地址:https://www.cnblogs.com/antoon/p/5284793.html
Copyright © 2011-2022 走看看