Android平台 短信接送流程剖析(含编码)

Android平台 短信接送流程剖析(含编码)

Android平台 短信接送流程剖析(含编码)_第1张图片

 

//框架层分析:
//GsmSMSDispatcher.java
    /** {@inheritDoc} */
    @Override
    protected int dispatchMessage(SmsMessageBase smsb) { //该函数的返回值会在handleMessage里进行判断是否为Activity.RESULT_OK。要注意该返回值不为Activity.RESULT_OK的情况。

        // If sms is null, means there was a parsing error.
        if (smsb == null) {
            return Intents.RESULT_SMS_GENERIC_ERROR;
        }
        SmsMessage sms = (SmsMessage) smsb;
        boolean handled = false;

        if (sms.isTypeZero()) { //0x0100 0000 Short Message Type 0 The MS does not indicate the receipt of the type 0 short message to the user,and the message is not stored in the(U)SIM or ME.
            // As per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not be
            // Displayed/Stored/Notified. They should only be acknowledged.
            Log.d(TAG, "Received short message type 0, Don't display or store it. Send Ack");
            return Intents.RESULT_SMS_HANDLED;
        }

        if (mSmsReceiveDisabled) {
            // Device doesn't support SMS service,
            Log.d(TAG, "Received short message on device which doesn't support "
                    + "SMS service. Ignored.");
            return Intents.RESULT_SMS_HANDLED;
        }

        // Special case the message waiting indicator messages
        if (sms.isMWISetMessage()) {
            updateMessageWaitingIndicator(true);
            handled = sms.isMwiDontStore();
            if (Config.LOGD) {
                Log.d(TAG, "Received voice mail indicator set SMS shouldStore=" + !handled);
            }
        } else if (sms.isMWIClearMessage()) {
            updateMessageWaitingIndicator(false);
            handled = sms.isMwiDontStore();
            if (Config.LOGD) {
                Log.d(TAG, "Received voice mail indicator clear SMS shouldStore=" + !handled);
            }
        }

        if (handled) {
            return Intents.RESULT_SMS_HANDLED;
        }

        if (!mStorageAvailable && (sms.getMessageClass() != MessageClass.CLASS_0)) {
            // It's a storable message and there's no storage available.  Bail.
            // (See TS 23.038 for a description of class 0 messages.)
            return Intents.RESULT_SMS_OUT_OF_MEMORY;
        }

        SmsHeader smsHeader = sms.getUserDataHeader();
         // See if message is partial or port addressed.
        if ((smsHeader == null) || (smsHeader.concatRef == null)) {
            // Message is not partial (not part of concatenated sequence).
            byte[][] pdus = new byte[1][];
            pdus[0] = sms.getPdu();

            if (smsHeader != null && smsHeader.portAddrs != null) {
                if (smsHeader.portAddrs.destPort == SmsHeader.PORT_WAP_PUSH) {
                    return mWapPush.dispatchWapPdu(sms.getUserData());
                } else {
                    // The message was sent to a port, so concoct a URI for it.
                    dispatchPortAddressedPdus(pdus, smsHeader.portAddrs.destPort);
                }
            } else {
                // Normal short and non-port-addressed message, dispatch it.
                dispatchPdus(pdus);  //注意该处
            }
            return Activity.RESULT_OK;
        } else {
            // Process the message part.
            return processMessagePart(sms, smsHeader.concatRef, smsHeader.portAddrs);
        }
}

//SMSDispatcher.java
protected void dispatchPdus(byte[][] pdus) {
        Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION);
        intent.putExtra("pdus", pdus);  //pdu数据
        intent.putExtra("encoding", getEncoding());
        dispatch(intent, "android.permission.RECEIVE_SMS");
    }



//应用层分析:
<!-- Require sender permissions to prevent SMS spoofing -->
        <receiver android:name=".transaction.PrivilegedSmsReceiver"
            android:permission="android.permission.BROADCAST_SMS">
            <intent-filter>
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>
//PrivilegedSmsReceiver类从SmsReceiver派生。在SmsReceiver(extends BroadcastReceiver)类中的onReceiveWithPrivilege 会将服务SmsReceiverService启动,然后在handleSmsReceived函数中对接收的消息进行处理。

//SmsReceiverService.java
//入口
  private void handleSmsReceived(Intent intent, int error) {
SmsMessage[] msgs = Intents.getMessagesFromIntent(intent); //解析intent,获取SmsMessage转①分析
    Uri messageUri = insertMessage(this, msgs, error); //插入数据 转②分析
        if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
            SmsMessage sms = msgs[0];
            Log.v(TAG, "handleSmsReceived" + (sms.isReplace() ? "(replace)" : "") +
                    " messageUri: " + messageUri +
                    ", address: " + sms.getOriginatingAddress() +
                    ", body: " + sms.getMessageBody());
        }

        if (messageUri != null) {
            // Called off of the UI thread so ok to block.
            MessagingNotification.blockingUpdateNewMessageIndicator(this, true, false);
        }
}


//①分析
//Telephony.java
public static final SmsMessage[] getMessagesFromIntent(Intent intent) {
Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
byte[][] pduObjs = new byte[messages.length][];

int encoding = intent.getIntExtra("encoding", -1);

for (int i = 0; i < messages.length; i++) {
                    pduObjs[i] = (byte[]) messages[i];
                }
                byte[][] pdus = new byte[pduObjs.length][];
                int pduCount = pdus.length;
                SmsMessage[] msgs = new SmsMessage[pduCount];
                for (int i = 0; i < pduCount; i++) {
                    pdus[i] = pduObjs[i];
                    if (-1 != encoding) {
                        msgs[i] = SmsMessage.createFromPdu(pdus[i], encoding);
                    } else {
                        msgs[i] = SmsMessage.createFromPdu(pdus[i]);  //创建PDU
                    }
                }
                return msgs;
            }
        }

//②分析:
private Uri insertMessage(Context context, SmsMessage[] msgs, int error) {
        // Build the helper classes to parse the messages.
        SmsMessage sms = msgs[0];

        if (sms.getMessageClass() == SmsMessage.MessageClass.CLASS_0) {
            displayClassZeroMessage(context, sms); //直接显示
            return null;
        } else if (sms.isReplace()) {
            return replaceMessage(context, msgs, error);  
        } else {
            return storeMessage(context, msgs, error);//存储短信 转③分析
        }
    }

//③分析
  private Uri storeMessage(Context context, SmsMessage[] msgs, int error) {
        SmsMessage sms = msgs[0];

        // Store the message in the content provider.
        ContentValues values = extractContentValues(sms); //提取信息
        values.put(Sms.ERROR_CODE, error);
        int pduCount = msgs.length;

        if (pduCount == 1) {
            // There is only one part, so grab the body directly.
            values.put(Inbox.BODY, replaceFormFeeds(sms.getDisplayMessageBody()));
        } else {
            // Build up the body from the parts.
            StringBuilder body = new StringBuilder();
            for (int i = 0; i < pduCount; i++) {
                sms = msgs[i];
                body.append(sms.getDisplayMessageBody());
            }
            values.put(Inbox.BODY, replaceFormFeeds(body.toString()));
        }

        // Make sure we've got a thread id so after the insert we'll be able to delete
        // excess messages.
        Long threadId = values.getAsLong(Sms.THREAD_ID);
        String address = values.getAsString(Sms.ADDRESS);  //注意对地址的处理
        if (!TextUtils.isEmpty(address)) {
            Contact cacheContact = Contact.get(address,true);
            if (cacheContact != null) {
                address = cacheContact.getNumber();
            }
        } else {
            address = getString(R.string.unknown_sender);
            values.put(Sms.ADDRESS, address);
        }

        if (((threadId == null) || (threadId == 0)) && (address != null)) {
            threadId = Threads.getOrCreateThreadId(context, address);
            values.put(Sms.THREAD_ID, threadId);
        }

        ContentResolver resolver = context.getContentResolver();

        Uri insertedUri = SqliteWrapper.insert(context, resolver, Inbox.CONTENT_URI, values);

        // Now make sure we're not over the limit in stored messages
        Recycler.getSmsRecycler().deleteOldMessagesByThreadId(getApplicationContext(), threadId);

        return insertedUri;
    }

 

你可能感兴趣的:(android)