android接收短信——framework处理流程(android 5.1)

Posted 勤能补拙,熟能生巧,宁静致远

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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应用处理。 

 





 

以上是关于android接收短信——framework处理流程(android 5.1)的主要内容,如果未能解决你的问题,请参考以下文章

Android5.0框架层短信接收过程分析

Android5.0框架层短信接收过程分析

OpenHarmerny 短彩信之Framework系统源码解析

Android 服务在应用程序处于后台时接收短信

如何在没有 SMS_READ 或 Android 中的类似权限的情况下发送短信并接收结果

android 6.0为啥接收不到短信广播