1. 程式人生 > 其它 >Android S短訊息接收流程

Android S短訊息接收流程

1 入口

該BroadcastReceiver配置了對intent: SMS_DELIVER_ACTION的接收:
/packages/apps/Messaging/AndroidManifest.xml

        <receiver android:name=".receiver.SmsDeliverReceiver"
                  android:exported="true"
                  android:permission="android.permission.BROADCAST_SMS">
            <intent-filter>
                <action android:name="android.provider.Telephony.SMS_DELIVER" />
            </intent-filter>
        </receiver>

Telephony對該intent的定義:
/frameworks/base/core/java/android/provider/Telephony.java

            public static final String SMS_DELIVER_ACTION =
                    "android.provider.Telephony.SMS_DELIVER";

2 Framework流程

2.1 流程圖

這裡以普通接收到的GSM SMS(其他CDMA和IMS SMS可檢視程式碼)為例:

2.2 原始碼

2.2.1 註冊New SMS

在GsmInboundSmsHandler這個Handler中註冊EVENT_NEW_SMS事件,設定RIL_UNSOL_RESPONSE_NEW_SMS的監聽者為mGsmSmsRegistrant:
/frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java

    /**
     * Create a new GSM inbound SMS handler.
     */
    private GsmInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
            Phone phone) {
        super("GsmInboundSmsHandler", context, storageMonitor, phone);
        phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null);
        mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi, phone.getPhoneId());
        mCellBroadcastServiceManager.enable();

        if (TEST_MODE) {
            if (sTestBroadcastReceiver == null) {
                sTestBroadcastReceiver = new GsmCbTestBroadcastReceiver();
                IntentFilter filter = new IntentFilter();
                filter.addAction(TEST_ACTION);
                context.registerReceiver(sTestBroadcastReceiver, filter);
            }
        }
    }

RILJ方法:

    public void setOnNewGsmSms(Handler h, int what, Object obj) {
        mGsmSmsRegistrant = new Registrant (h, what, obj);
    }

2.2.2 接收New SMS

RadioIndication通過newSms()上報新簡訊,最終通過mRil.mGsmSmsRegistrant.notifyRegistrant()傳送訊息EVENT_NEW_SMS事件給GsmInboundSmsHandler:
/frameworks/opt/telephony/src/java/com/android/internal/telephony/RadioIndication.java

    public void newSms(int indicationType, ArrayList<Byte> pdu) {
        mRil.processIndication(indicationType);

        byte[] pduArray = RIL.arrayListToPrimitiveArray(pdu);
        if (RIL.RILJ_LOGD) mRil.unsljLog(RIL_UNSOL_RESPONSE_NEW_SMS);

        SmsMessageBase smsb = com.android.internal.telephony.gsm.SmsMessage.createFromPdu(pduArray);
        if (mRil.mGsmSmsRegistrant != null) {
            mRil.mGsmSmsRegistrant.notifyRegistrant(
                    new AsyncResult(null, smsb == null ? null : new SmsMessage(smsb), null));
        }
    }

GsmInboundSmsHandler最終會發送intent: SMS_DELIVER_ACTION給相關app。

2.2.3 傳送Delivery Report

對於普通短訊息,會在GsmInboundSmsHandler中傳送Delivery Report給網路。

3 RILD流程

3.1 接收New SMS流程

3.1.1 流程圖

3.1.2 原始碼

vendor_ril收到RIL_onUnsolicitedResponse(),會呼叫radio::newSmsInd()方法:
/hardware/ril/libril/ril_unsol_commands.h

    {RIL_UNSOL_RESPONSE_NEW_SMS, radio::newSmsInd, WAKE_PARTIAL},

該方法直接呼叫RadioIndication的newSms()方法通知Framework:
/hardware/ril/libril/ril_service.cpp

int radio::newSmsInd(int slotId, int indicationType,
                     int token, RIL_Errno e, void *response, size_t responseLen) {
    if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) {
        if (response == NULL || responseLen == 0) {
            RLOGE("newSmsInd: invalid response");
            return 0;
        }

        uint8_t *bytes = convertHexStringToBytes(response, responseLen);
        if (bytes == NULL) {
            RLOGE("newSmsInd: convertHexStringToBytes failed");
            return 0;
        }

        hidl_vec<uint8_t> pdu;
        pdu.setToExternal(bytes, responseLen/2);
#if VDBG
        RLOGD("newSmsInd");
#endif
        Return<void> retStatus = radioService[slotId]->mRadioIndication->newSms(
                convertIntToRadioIndicationType(indicationType), pdu);
        radioService[slotId]->checkReturnStatus(retStatus);
        free(bytes);
    } else {
        RLOGE("newSmsInd: radioService[%d]->mRadioIndication == NULL", slotId);
    }

    return 0;
}

3.2 傳送Delivery Report流程

3.2.1 流程圖

3.2.2 原始碼

4 命令+CMT和AT+CNMA

3GPP 27.005介紹了這兩個AT命令:
3 Text Mode
3.4 Message Receiving and Reading Commands
3.4.1 New Message Indications to TE +CNMI
+CMT: [], (PDU mode enabled); or
+CMT: ,[],[,,,,,,,] (text mode enabled; about parameters in italics, refer command Show Text Mode Parameters +CSDH)
4 PDU Mode
4.6 New Message Acknowledgement to ME/TA +CNMA

< +CMT: ,30
0891683110808805F0040BA13142166977F10000223061713590230CC9531B642FCBF3A0F7DA05
> AT+CNMA=1, 2, "0000"
< OK

5 Modem流程

3GPP 24.011,以LTE S1 mode下接收SMS為例:

協議分層 Step1(NW->MS) Step2(MS->NW) Step3(MS->NW) Step4(NW->MS)
SM_AL SMS-DELIVER SMS-DELIVER REPORT
SM_TL
SM_RL RP-DATA RP-ACK
CM_sublayer CP-DATA CP-ACK CP-DATA CP-ACK
EMM_sublayer Downlink NAS transport Uplink NAS Transport Uplink NAS Transport Downlink NAS Transport
ERRC dlInformationTransfer ulInformationTransfer ulInformationTransfer dlInformationTransfer

PDU訊息:

Step1: SMS DELIVER
Downlink NAS transport: 07 62 2e 09 01 2b 01 00 08 91 68 31 10 80 88 05 f0 00 1e 04 0b a1 31 42 16 69 77 f1 00 00 22 30 61 71 35 90 23 0c c9 53 1b 64 2f cb f3 a0 f7 da 05
Step2: CP-ACK
Uplink NAS Transport:   07 63 02 89 04
Step3: SMS DELIVER REPORT
Uplink NAS Transport:   07 63 09 89 01 06 02 00 41 02 00 00
Step4: CP-ACK
Downlink NAS transport: 07 62 02 09 04

6 參考文件

Android6.0的SMS(簡訊)原始碼分析--簡訊傳送
https://blog.csdn.net/a34140974/article/details/50964080
Android6.0的SMS(簡訊)原始碼分析--簡訊接收
https://blog.csdn.net/a34140974/article/details/50963617
Android原始碼
http://aospxref.com/android-12.0.0_r3/
http://aosp.opersys.com/xref/android-12.0.0_r2/

版權宣告:本文為 無痕1024 原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連結和本宣告。
本文連結:https://www.cnblogs.com/wuhen1024/p/16018666.html