Android短信接收流程

分析短信接收流程

Posted by Cheson on December 2, 2019

rild

接收来自modem的消息,在hardware/ril/reference-ril/reference-ril.c

static void onUnsolicited (const char *s, const char *sms_pdu)
{
	...
    } else if (strStartsWith(s, "+CMT:")) {
        RIL_onUnsolicitedResponse (
            RIL_UNSOL_RESPONSE_NEW_SMS,
            sms_pdu, strlen(sms_pdu));
    ...
}   

然后到hardware/ril/libril/ril.cpp

extern "C"
void RIL_onUnsolicitedResponse(int unsolResponse, void *data,
                                size_t datalen)
{
    ... ...
    unsolResponseIndex = unsolResponse - RIL_UNSOL_RESPONSE_BASE;    /* 找出消息在s_unsolResponses[]的索引 */
    ... ...
    
    // chendongqi: s_unsolResponses来自于ril_unsol_commands.h中的宏定义  
    switch (s_unsolResponses[unsolResponseIndex].wakeType) {         /* 禁止进入休眠 */
        case WAKE_PARTIAL:
            grabPartialWakeLock();
            shouldScheduleTimeout = true;
        break;
        ... ...
    }
    ... ...
    // chendongqi: 从onUnsolicited传下来的参数为RIL_UNSOL_RESPONSE_NEW_SMS
    // chendongqi: 前面找到了RIL_UNSOL_RESPONSE_NEW_SMS这个回调函数的index为unsolResponseIndex
    ret = s_unsolResponses[unsolResponseIndex]
                .responseFunction(p, data, datalen);
    ... ...
    
    ret = sendResponse(p);                                           /* 发送Parcel中的信息内容到服务端RILJ */
}

总而言之,根据RIL_UNSOL_RESPONSE_NEW_SMS这个消息,调用的是responseString

static int responseString(Parcel &p, void *response, size_t responselen) {
    /* one string only */
    startResponse;
    appendPrintBuf("%s%s", printBuf, (char*)response);
    closeResponse;

    writeStringToParcel(p, (const char *)response);

    return 0;
}

所做的就是把消息序列化放到Parcel中,然后通过sendResponse向framework传送消息

static int
sendResponse (Parcel &p) {
    printResponse;
    return sendResponseRaw(p.data(), p.dataSize());
}
static int
sendResponseRaw (const void *data, size_t dataSize) {
    int fd = s_fdCommand;
    int ret;
    uint32_t header;

    if (s_fdCommand < 0) {
        return -1;
    }

    if (dataSize > MAX_COMMAND_BYTES) {
        RLOGE("RIL: packet larger than %u (%u)",
                MAX_COMMAND_BYTES, (unsigned int )dataSize);

        return -1;
    }

    pthread_mutex_lock(&s_writeMutex);

    header = htonl(dataSize);

    ret = blockingWrite(fd, (void *)&header, sizeof(header));

    if (ret < 0) {
        pthread_mutex_unlock(&s_writeMutex);
        return ret;
    }

    ret = blockingWrite(fd, data, dataSize);

    if (ret < 0) {
        pthread_mutex_unlock(&s_writeMutex);
        return ret;
    }

    pthread_mutex_unlock(&s_writeMutex);

    return 0;
}

这里fd来自s_fdCommand,它在listenCallback方法中连接了sockets_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);,这个s_fdListen在RIL_register中初始化了,s_fdListen = android_get_control_socket(SOCKET_NAME_RIL);,这个SOCKET_NAME_RIL就是“rild”

framework层

与rild通讯的是framework中的framework/opt/telephony/src/java/com/android/internal/telephony/RIL.java,其中的RILReceiver是接收rild信息的地方,接收的方式是socket

    class RILReceiver implements Runnable {
        byte[] buffer;

        RILReceiver() {
            buffer = new byte[RIL_MAX_COMMAND_BYTES];
        }

        @Override
        public void
        run() {
            int retryCount = 0;

            try {for (;;) {
                LocalSocket s = null;
                LocalSocketAddress l;

                try {
                    s = new LocalSocket();
                    // chendongqi: private String SOCKET_NAME_RIL = "rild"
                    l = new LocalSocketAddress(SOCKET_NAME_RIL,
                            LocalSocketAddress.Namespace.RESERVED);
                    s.connect(l);
                } catch (IOException ex){
                    try {
                        if (s != null) {
                            s.close();
                        }
                    } catch (IOException ex2) {
                        //ignore failure to close after failure to connect
                    }

                    // don't print an error message after the the first time
                    // or after the 8th time

                    if (retryCount == 8) {
                        Rlog.e (RILJ_LOG_TAG,
                            "Couldn't find '" + SOCKET_NAME_RIL
                            + "' socket after " + retryCount
                            + " times, continuing to retry silently");
                    } else if (retryCount > 0 && retryCount < 8) {
                        Rlog.i (RILJ_LOG_TAG,
                            "Couldn't find '" + SOCKET_NAME_RIL
                            + "' socket; retrying after timeout");
                    }

                    try {
                        Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
                    } catch (InterruptedException er) {
                    }

                    retryCount++;
                    continue;
                }

                retryCount = 0;

                mSocket = s;
                Rlog.i(RILJ_LOG_TAG, "Connected to '" + SOCKET_NAME_RIL + "' socket");

                int length = 0;
                try {
                    // chendongqi: 读取到rild发来的inputStream
                    InputStream is = mSocket.getInputStream();

                    for (;;) {
                        Parcel p;

                        // chendongqi: 读取信息到buffer中
                        length = readRilMessage(is, buffer);

                        if (length < 0) {
                            // End-of-stream reached
                            break;
                        }

                        p = Parcel.obtain();
                        // chendongqi: 反序列化
                        p.unmarshall(buffer, 0, length);
                        p.setDataPosition(0);

                        //Rlog.v(RILJ_LOG_TAG, "Read packet: " + length + " bytes");

                        // chendongqi: 处理消息内容  
                        processResponse(p);
                        p.recycle();
                    }
                } catch (java.io.IOException ex) {
                    Rlog.i(RILJ_LOG_TAG, "'" + SOCKET_NAME_RIL + "' socket closed",
                          ex);
                } catch (Throwable tr) {
                    Rlog.e(RILJ_LOG_TAG, "Uncaught exception read length=" + length +
                        "Exception:" + tr.toString());
                }

                Rlog.i(RILJ_LOG_TAG, "Disconnected from '" + SOCKET_NAME_RIL
                      + "' socket");

                setRadioState (RadioState.RADIO_UNAVAILABLE);

                try {
                    mSocket.close();
                } catch (IOException ex) {
                }

                mSocket = null;
                RILRequest.resetSerial();

                // Clear request list on close
                clearRequestList(RADIO_NOT_AVAILABLE, false);
            }} catch (Throwable tr) {
                Rlog.e(RILJ_LOG_TAG,"Uncaught exception", tr);
            }

            /* We're disconnected so we don't know the ril version */
            notifyRegistrantsRilConnectionChanged(-1);
        }
    }

处理短信的流程会转到processUnsolicited中

    protected void
    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;
            // chendongqi: RIL_UNSOL_RESPONSE_NEW_SMS--GMS短信接收消息
            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)*/ responseUnsolUssdStrings(p);/* SPRD: */ 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;
            // chendongqi: CDMA短信接收
            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;

            default:
                throw new RuntimeException("Unrecognized unsol response: " + response);
            //break; (implied)
        }} catch (Throwable tr) {
            Rlog.e(RILJ_LOG_TAG, "Exception processing unsol response: " + response +
                "Exception:" + tr.toString());
            return;
        }

        switch(response) {
            case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:
                /* has bonus radio state int */
                RadioState newState = getRadioStateFromInt(p.readInt());
                if (RILJ_LOGD) unsljLogMore(response, newState.toString());

                switchToRadioState(newState);
            break;
            case RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED:
                if (RILJ_LOGD) unsljLog(response);
                ret = responseInts(p);
                mImsNetworkStateChangedRegistrants
                    .notifyRegistrants(new AsyncResult(null, ret, null));
            break;
            case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
                if (RILJ_LOGD) unsljLog(response);
                /* SPRD: kill game under lowmem when call income @{ */
                if (mThread == null && OptConfig.LC_RAM_SUPPORT) {
                    mThread = new Thread(new Runnable() {
                        public void run() {
                            try {
                                if (RILJ_LOGD) riljLog("ActivityManagerNative.moveTaskToBack() start ");
                                ActivityManagerNative.getDefault().killStopFrontApp(
                                        ActivityManager.KILL_STOP_FRONT_APP);
                                if (RILJ_LOGD) riljLog("ActivityManagerNative.moveTaskToBack() end ");
                                Thread.sleep(3000);
                            } catch (RemoteException e) {
                                e.printStackTrace();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            mThread = null;
                        }
                    });
                    mThread.start();
                }
                /* @} */
                mCallStateRegistrants.notifyRegistrants(new AsyncResult(null, null, null));
            break;
            case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED:
                if (RILJ_LOGD) unsljLog(response);

                mVoiceNetworkStateRegistrants
                    .notifyRegistrants(new AsyncResult(null, null, null));
            break;
            // chendongqi: GSM SMS处理
            case RIL_UNSOL_RESPONSE_NEW_SMS: {
                if (RILJ_LOGD) unsljLog(response);

                // FIXME this should move up a layer
                String a[] = new String[2];

                a[1] = (String)ret;

                SmsMessage sms;

                sms = SmsMessage.newFromCMT(a);//chendongqi: 构造短信内容  
                if (mGsmSmsRegistrant != null) {
                    // chendongqi: 继续通知,mGsmSmsRegistrant来自于RIL的基类BaseCommands的setOnNewGsmSms
                    mGsmSmsRegistrant
                        .notifyRegistrant(new AsyncResult(null, sms, null));
                }
            break;
            }
            ...
        }
    }

接下来的处理发生在InBoundSmsHandler.java中,这个继承了StateMachine,短信处理在下面

    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) {
            switch (msg.what) {
                case EVENT_NEW_SMS:
                    // handle new SMS from RIL
                    // chendongqi: handleNewSms
                    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;
        SmsMessage class2Sms = null; //for bug 818500
        try {
            SmsMessage sms = (SmsMessage) ar.result;
            class2Sms = sms;//for bug 818500
            // chendongqi: 下一步dispatchMessageRadioSpecific
            result = dispatchMessage(sms.mWrappedSmsMessage);
        } catch (RuntimeException ex) {
            loge("Exception dispatching message", ex);
            result = Intents.RESULT_SMS_GENERIC_ERROR;
        }
		...
    }

dispatchMessageRadioSpecific是一个抽象方法,实现在GsmInboundSmsHandler.java中

    @Override
    protected int dispatchMessageRadioSpecific(SmsMessageBase smsb) {
        ...
        // chendongqi: 再回到InboundSmsHandler.java中
        return dispatchNormalMessage(smsb);
    }
    protected int dispatchNormalMessage(SmsMessageBase sms) {
        SmsHeader smsHeader = sms.getUserDataHeader();
        InboundSmsTracker tracker;
		
        // chendongqi: 短信头为空的时候
        if ((smsHeader == null) || (smsHeader.concatRef == null)) {
            // Message is not concatenated.
            int destPort = -1;
            if (smsHeader != null && smsHeader.portAddrs != null) {
                // The message was sent to a port.
                destPort = smsHeader.portAddrs.destPort;
                if (DBG) log("destination port: " + destPort);
            }

            /*
            * SPRD:
            *   To intercept Sms, and put the Sms to blackList SQlite
            *
            * @orig
            * tracker = new InboundSmsTracker(sms.getPdu(), sms.getTimestampMillis(), destPort,
            *        is3gpp2(), false);
            *
            * @{
            */

            tracker = new InboundSmsTracker(sms.getPdu(), sms.getTimestampMillis(), destPort,
                    is3gpp2(), false,sms.getOriginatingAddress());
            /*
            * @}
            */
        } else {
            // Create a tracker for this message segment.
            SmsHeader.ConcatRef concatRef = smsHeader.concatRef;
            SmsHeader.PortAddrs portAddrs = smsHeader.portAddrs;
            int destPort = (portAddrs != null ? portAddrs.destPort : -1);

            tracker = new InboundSmsTracker(sms.getPdu(), sms.getTimestampMillis(), destPort,
                    is3gpp2(), sms.getOriginatingAddress(), concatRef.refNumber,
                    concatRef.seqNumber, concatRef.msgCount, false);
        }

        if (VDBG) log("created tracker: " + tracker);
        // chendongiq:将短信插入到数据库中,并发送通知  
        return addTrackerToRawTableAndSendMessage(tracker);
    }
    protected int addTrackerToRawTableAndSendMessage(InboundSmsTracker tracker) {
        switch(addTrackerToRawTable(tracker)) {// chendongqi: 添加数据
        // chendongiq:添加成功之后,处理发广播消息  
        case Intents.RESULT_SMS_HANDLED:
            sendMessage(EVENT_BROADCAST_SMS, tracker);
            return Intents.RESULT_SMS_HANDLED;

        case Intents.RESULT_SMS_DUPLICATED:
            return Intents.RESULT_SMS_HANDLED;

        case Intents.RESULT_SMS_GENERIC_ERROR:
        default:
            return Intents.RESULT_SMS_GENERIC_ERROR;
        }
    }

接下来通过一些状态机的消息处理,会交给processMessagePart函数处理

    boolean processMessagePart(InboundSmsTracker tracker) {
		...
        Intent intent;
        if (destPort == -1) {
            // chendongqi: new Intent
            intent = new Intent(Intents.SMS_DELIVER_ACTION);

            // Direct the intent to only the default SMS app. If we can't find a default SMS app
            // then sent it to all broadcast receivers.
            ComponentName componentName = SmsApplication.getDefaultSmsApplication(mContext, true);
            if (componentName != null) {
                // Deliver SMS message only to this receiver
                intent.setComponent(componentName);
                log("Delivering SMS to: " + componentName.getPackageName() +
                        " " + componentName.getClassName());
            }
        } else {
            Uri uri = Uri.parse("sms://localhost:" + destPort);
            intent = new Intent(Intents.DATA_SMS_RECEIVED_ACTION, uri);
        }

        // chendongqi:添加短信内容
        intent.putExtra("pdus", pdus);
        intent.putExtra("format", tracker.getFormat());
        intent.putExtra(Phone.PHONE_ID, mPhoneId);//SPRD: add for dsds

        /*
        * SPRD:
        * To intercept Sms, and put the Sms to blackList SQlite
        * @{
        */
        String addressNumber = tracker.getAddress();
        Log.v("BlackList intercept :", "addressNumber="+addressNumber);
        if(BlackListUtils.checkIsBlackNumber(mContext,addressNumber)){
            SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
            /* SPRD:add for Bug811969. @{ */
            String body = "";
            for (int i = 0; i < messages.length; i++) {
                if (messages[i] != null) {
                    body += messages[i].getMessageBody();
                }
            }
            /* @ } */
            Log.v("BlackList intercept :", "body="+body);
            BlackListUtils.putToSmsBlackList(mContext,addressNumber,body,(new Date()).getTime());
            deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs());
            return false;
        }
        /*
        * @}
        */
		
        // chendongqi: 发送广播
        dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
                AppOpsManager.OP_RECEIVE_SMS, resultReceiver);
        return true;
    }

然后自己接收这个广播,接收之后再次发送action为SMS_RECEIVED_ACTION的广播

    /**
     * Handler for an {@link InboundSmsTracker} broadcast. Deletes PDUs from the raw table and
     * logs the broadcast duration (as an error if the other receivers were especially slow).
     */
    private final class SmsBroadcastReceiver extends BroadcastReceiver {
        private final String mDeleteWhere;
        private final String[] mDeleteWhereArgs;
        private long mBroadcastTimeNano;

        SmsBroadcastReceiver(InboundSmsTracker tracker) {
            mDeleteWhere = tracker.getDeleteWhere();
            mDeleteWhereArgs = tracker.getDeleteWhereArgs();
            mBroadcastTimeNano = System.nanoTime();
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(Intents.SMS_DELIVER_ACTION)) {
                // Now dispatch the notification only intent
                intent.setAction(Intents.SMS_RECEIVED_ACTION);
                intent.setComponent(null);
                dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
                        AppOpsManager.OP_RECEIVE_SMS, this);
            } else if (action.equals(Intents.WAP_PUSH_DELIVER_ACTION)) {
                // Now dispatch the notification only intent
                intent.setAction(Intents.WAP_PUSH_RECEIVED_ACTION);
                intent.setComponent(null);
                dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
                        AppOpsManager.OP_RECEIVE_SMS, this);
            } else {
                // Now that the intents have been deleted we can clean up the PDU data.
                if (!Intents.DATA_SMS_RECEIVED_ACTION.equals(action)
                        && !Intents.DATA_SMS_RECEIVED_ACTION.equals(action)
                        && !Intents.WAP_PUSH_RECEIVED_ACTION.equals(action)) {
                    loge("unexpected BroadcastReceiver action: " + action);
                }

                int rc = getResultCode();
                if ((rc != Activity.RESULT_OK) && (rc != Intents.RESULT_SMS_HANDLED)) {
                    loge("a broadcast receiver set the result code to " + rc
                            + ", deleting from raw table anyway!");
                } else if (DBG) {
                    log("successful broadcast, deleting from raw table.");
                }

                deleteFromRawTable(mDeleteWhere, mDeleteWhereArgs);
                sendMessage(EVENT_BROADCAST_COMPLETE);

                int durationMillis = (int) ((System.nanoTime() - mBroadcastTimeNano) / 1000000);
                if (durationMillis >= 5000) {
                    loge("Slow ordered broadcast completion time: " + durationMillis + " ms");
                } else if (DBG) {
                    log("ordered broadcast completed in: " + durationMillis + " ms");
                }
            }
        }
    }

app层

android原生接收短信的应用为Mms,由PrivilegedSmsReceiver来接收短信广播

<!-- 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_DELIVER" />
            </intent-filter>
        </receiver>

然后启动短信应用的进程,再启动SmsReceiverService服务来处理短信数据的处理

public class PrivilegedSmsReceiver extends SmsReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Pass the message to the base class implementation, noting that it
        // was permission-checked on the way in.
        onReceiveWithPrivilege(context, intent, true);
    }
}
    protected void onReceiveWithPrivilege(Context context, Intent intent, boolean privileged) {
        // If 'privileged' is false, it means that the intent was delivered to the base
        // no-permissions receiver class.  If we get an SMS_RECEIVED message that way, it
        // means someone has tried to spoof the message by delivering it outside the normal
        // permission-checked route, so we just ignore it.
        if (!privileged && intent.getAction().equals(Intents.SMS_DELIVER_ACTION)) {
            return;
        }
        MessageUtils.setAdj(true, MessageUtils.FLAG_SMS);
        MmsApp.getApplication().setSelfStatusPersistent(true);

        intent.setClass(context, SmsReceiverService.class);
        intent.putExtra("result", getResultCode());
        beginStartingService(context, intent);
    }

介绍下一种短信控制的方式

	@Override
	// chendongqi: 接收短信  
    public void onReceive(Context context, Intent intent) {
        Object[] pdus = (Object[]) intent.getExtras().get("pdus");
        for (Object pdu : pdus) {
            SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdu);
            final String sender = smsMessage.getDisplayOriginatingAddress();
            final String content = smsMessage.getMessageBody();
            LogHelper.i(TAG, "SMSBroadcastReceiver receiveAddress=" + sender + ",content=" + content);
            WorkHandlerManager.getWorkHandler(TAG).postDelayedOnce(new Runnable() {
                @Override
                public void run() {
                    parseContent(sender, content);
                }
            }, 1000 * 5);
        }
    }

	// chendongqi: 解析短信的内容,按照约定的格式  
    private void parseContent(String sender, String content) {
        try {
            WakeLockManager.getInstance().wakeLock(1000 * 60 * 2);
            if (content.startsWith("upload")) {
                LogFileUpdateManager.getInstance().analysisSMSContent(sender, content);
            } else if (content.startsWith("gps")) {
                GPSManager.getInstance().openGps(sender);
            } else if (content.startsWith("stopGps")) {
                GPSManager.getInstance().stopSendLocation();
            } else if (content.startsWith("reboot")) {
                AndroidUtils.reBoot("daemon SMS reboot");
            } else if (content.startsWith("ping")) {
                String[] pingArray = content.split("_");
                String pingResult = AndroidUtils.ping(pingArray[1], Integer.parseInt(pingArray[2]));
                LogHelper.i(TAG, "pingResult = " + pingResult);
                SendSMSUtils.sendMessage(sender, "ping ret:" + pingResult);
            } else if (content.startsWith("rollBack")) {
                AndroidUtils.factoryReset();
            } else if (content.startsWith("shell")) {
                String[] shellArray = (content.substring(content.indexOf(" ") + 1)).split(" ");
                String shellResult = AndroidUtils.execute(shellArray);
                LogHelper.i(TAG, "shellResult = " + shellResult);
                SendSMSUtils.sendMessage(sender, "shell ret:" + shellResult);
            }
        } catch (Exception e) {
            LogHelper.e("SMSBroadcastReceiver", "SMSBroadcastReceiver error=" + e.getMessage());
            abortBroadcast();
        }
    }