zoukankan      html  css  js  c++  java
  • 深度分析:Android4.3下MMS发送到附件为音频文件(音频为系统内置音频)的彩信给自己,添加音频-发送彩信-接收彩信-下载音频附件-预览-播放(三,接收彩信<1,接收短信>)

    在Android中,彩信的接收分为两部分。彩信通知通过短信的方式接收。彩信数据的下载在应用层中处理。

    接收短信(!前提是发送彩信而不是短信):

    分析代码之前,首先分享一张在网络上很流行的顺序图。


    调用 Ril.java类中内部类RILReceiver的run()方法,代码如下《TAG 1-1》:

     public void
            run() {
                int retryCount = 0;
                String rilSocket = "rild";

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

                    if (mInstanceId == null || mInstanceId == 0 ) {
                        rilSocket = SOCKET_NAME_RIL[0];
                    } else {
                        rilSocket = SOCKET_NAME_RIL[mInstanceId];
                    }

                    try {
                        s = new LocalSocket();
                        l = new LocalSocketAddress(rilSocket,
                                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 '" + rilSocket
                                + "' socket after " + retryCount
                                + " times, continuing to retry silently");
                        } else if (retryCount > 0 && retryCount < 8) {
                            Rlog.i (RILJ_LOG_TAG,
                                "Couldn't find '" + rilSocket
                                + "' 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 '" + rilSocket + "' socket");

                    int length = 0;
                    try {
                        InputStream is = mSocket.getInputStream();

                        for (;;) {
                            Parcel p;

                            length = readRilMessage(is, buffer);

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

                            p = Parcel.obtain();
                            p.unmarshall(buffer, 0, length);
                            p.setDataPosition(0);

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

                            processResponse(p);
                            p.recycle();
                        }
                    } catch (java.io.IOException ex) {
                        Rlog.i(RILJ_LOG_TAG, "'" + rilSocket + "' 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 '" + rilSocket
                          + "' 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);
            }

    从上述代码《TAG 1-1》中,RILReceiver接收到短信后,会转到processResponse()--> processUnsolicited()进行处理.其事件类型为RIL_UNSOL_RESPONSE_NEW_SMS/RIL_UNSOL_RESPONSE_CDMA_NEW_SMS ,先调用responseString()从Parcel中获取数据,再使用newFromCMT()方法获取SmsMessage对象《TAG1-2》;

        private void
        processResponse (Parcel p) {
            int type;

            type = p.readInt();

            if (type == RESPONSE_UNSOLICITED) {
                processUnsolicited (p);
            } else if (type == RESPONSE_SOLICITED) {
                processSolicited (p);
            }

            releaseWakeLockIfDone();
        }

    private 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;
                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_ON_SS: ret =  responseSsData(p); break;
                case RIL_UNSOL_STK_CC_ALPHA_NOTIFY: ret =  responseString(p); break;

            //dewen.feng@20140426 add     hongxing add
                case RIL_UNSOL_FACTORY_AT_TEST: ret = responseRaw(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);

                    mImsNetworkStateChangedRegistrants
                        .notifyRegistrants(new AsyncResult(null, null, null));
                break;
                case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
                    if (RILJ_LOGD) unsljLog(response);

                    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;
                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);
                    if (mGsmSmsRegistrant != null) {
                        mGsmSmsRegistrant
                            .notifyRegistrant(new AsyncResult(null, sms, null));
                    }
                break;
                }

                case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mSmsStatusRegistrant != null) {
                        mSmsStatusRegistrant.notifyRegistrant(
                                new AsyncResult(null, ret, null));
                    }
                break;
                case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    int[] smsIndex = (int[])ret;

                    if(smsIndex.length == 1) {
                        if (mSmsOnSimRegistrant != null) {
                            mSmsOnSimRegistrant.
                                    notifyRegistrant(new AsyncResult(null, smsIndex, null));
                        }
                    } else {
                        if (RILJ_LOGD) riljLog(" NEW_SMS_ON_SIM ERROR with wrong length "
                                + smsIndex.length);
                    }
                break;
                case RIL_UNSOL_ON_USSD:
                    String[] resp = (String[])ret;

                    if (resp.length < 2) {
                        resp = new String[2];
                        resp[0] = ((String[])ret)[0];
                        resp[1] = null;
                    }
                    if (RILJ_LOGD) unsljLogMore(response, resp[0]);
                    if (mUSSDRegistrant != null) {
                        mUSSDRegistrant.notifyRegistrant(
                            new AsyncResult (null, resp, null));
                    }
                break;
                case RIL_UNSOL_NITZ_TIME_RECEIVED:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    // has bonus long containing milliseconds since boot that the NITZ
                    // time was received
                    long nitzReceiveTime = p.readLong();

                    Object[] result = new Object[2];

                    result[0] = ret;
                    result[1] = Long.valueOf(nitzReceiveTime);

                    boolean ignoreNitz = SystemProperties.getBoolean(
                            TelephonyProperties.PROPERTY_IGNORE_NITZ, false);

                    if (ignoreNitz) {
                        if (RILJ_LOGD) riljLog("ignoring UNSOL_NITZ_TIME_RECEIVED");
                    } else {
                        if (mNITZTimeRegistrant != null) {

                            mNITZTimeRegistrant
                                .notifyRegistrant(new AsyncResult (null, result, null));
                        } else {
                            // in case NITZ time registrant isnt registered yet
                            mLastNITZTimeInfo = result;
                        }
                    }
                break;

                case RIL_UNSOL_SIGNAL_STRENGTH:
                    // Note this is set to "verbose" because it happens
                    // frequently
                    if (RILJ_LOGV) unsljLogvRet(response, ret);

                    if (mSignalStrengthRegistrant != null) {
                        mSignalStrengthRegistrant.notifyRegistrant(
                                            new AsyncResult (null, ret, null));
                    }
                break;
                case RIL_UNSOL_DATA_CALL_LIST_CHANGED:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    mDataNetworkStateRegistrants.notifyRegistrants(new AsyncResult(null, ret, null));
                break;

                case RIL_UNSOL_SUPP_SVC_NOTIFICATION:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mSsnRegistrant != null) {
                        mSsnRegistrant.notifyRegistrant(
                                            new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOL_STK_SESSION_END:
                    if (RILJ_LOGD) unsljLog(response);

                    if (mCatSessionEndRegistrant != null) {
                        mCatSessionEndRegistrant.notifyRegistrant(
                                            new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOL_STK_PROACTIVE_COMMAND:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mCatProCmdRegistrant != null) {
                        mCatProCmdRegistrant.notifyRegistrant(
                                            new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOL_STK_EVENT_NOTIFY:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mCatEventRegistrant != null) {
                        mCatEventRegistrant.notifyRegistrant(
                                            new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOL_STK_CALL_SETUP:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mCatCallSetUpRegistrant != null) {
                        mCatCallSetUpRegistrant.notifyRegistrant(
                                            new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOL_SIM_SMS_STORAGE_FULL:
                    if (RILJ_LOGD) unsljLog(response);

                    if (mIccSmsFullRegistrant != null) {
                        mIccSmsFullRegistrant.notifyRegistrant();
                    }
                    break;

                case RIL_UNSOL_SIM_REFRESH:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mIccRefreshRegistrants != null) {
                        mIccRefreshRegistrants.notifyRegistrants(
                                new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOL_CALL_RING:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mRingRegistrant != null) {
                        mRingRegistrant.notifyRegistrant(
                                new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOL_RESTRICTED_STATE_CHANGED:
                    if (RILJ_LOGD) unsljLogvRet(response, ret);
                    if (mRestrictedStateRegistrant != null) {
                        mRestrictedStateRegistrant.notifyRegistrant(
                                            new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED:
                    if (RILJ_LOGD) unsljLog(response);

                    if (mIccStatusChangedRegistrants != null) {
                        mIccStatusChangedRegistrants.notifyRegistrants();
                    }
                    break;

                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));
                    }
                    break;

                case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS:
                    if (RILJ_LOGD) unsljLog(response);

                    if (mGsmBroadcastSmsRegistrant != null) {
                        mGsmBroadcastSmsRegistrant
                            .notifyRegistrant(new AsyncResult(null, ret, null));
                    }
                    break;

                case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL:
                    if (RILJ_LOGD) unsljLog(response);

                    if (mIccSmsFullRegistrant != null) {
                        mIccSmsFullRegistrant.notifyRegistrant();
                    }
                    break;

                case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE:
                    if (RILJ_LOGD) unsljLog(response);

                    if (mEmergencyCallbackModeRegistrant != null) {
                        mEmergencyCallbackModeRegistrant.notifyRegistrant();
                    }
                    break;

                case RIL_UNSOL_CDMA_CALL_WAITING:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mCallWaitingInfoRegistrants != null) {
                        mCallWaitingInfoRegistrants.notifyRegistrants(
                                            new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mOtaProvisionRegistrants != null) {
                        mOtaProvisionRegistrants.notifyRegistrants(
                                            new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOL_CDMA_INFO_REC:
                    ArrayList<CdmaInformationRecords> listInfoRecs;

                    try {
                        listInfoRecs = (ArrayList<CdmaInformationRecords>)ret;
                    } catch (ClassCastException e) {
                        Rlog.e(RILJ_LOG_TAG, "Unexpected exception casting to listInfoRecs", e);
                        break;
                    }

                    for (CdmaInformationRecords rec : listInfoRecs) {
                        if (RILJ_LOGD) unsljLogRet(response, rec);
                        notifyRegistrantsCdmaInfoRec(rec);
                    }
                    break;

                case RIL_UNSOL_OEM_HOOK_RAW:
                    if (RILJ_LOGD) unsljLogvRet(response, IccUtils.bytesToHexString((byte[]) ret));
                    ByteBuffer oemHookResponse = ByteBuffer.wrap((byte[]) ret);
                    oemHookResponse.order(ByteOrder.nativeOrder());
                    if (isQcUnsolOemHookResp(oemHookResponse)) {
                        Rlog.d(RILJ_LOG_TAG, "OEM ID check Passed");
                        processUnsolOemhookResponse(oemHookResponse);
                    } else if (mUnsolOemHookRawRegistrant != null) {
                        Rlog.d(RILJ_LOG_TAG, "External OEM message, to be notified");
                        mUnsolOemHookRawRegistrant.notifyRegistrant(new AsyncResult(null, ret, null));
                    }
                    break;
                    
                //dewen.feng @20140426 add hongxing add
                case RIL_UNSOL_FACTORY_AT_TEST:
            Rlog.d(RILJ_LOG_TAG, "##########RIL_UNSOL_FACTORY_AT_TEST################");
                    if (RILJ_LOGD) unsljLogvRet(response, IccUtils.bytesToHexString((byte[])ret));
                    ByteBuffer factoryAtResponse = ByteBuffer.wrap((byte[])ret);
                    factoryAtResponse.order(ByteOrder.nativeOrder());
                    processFactoryAtResponse(factoryAtResponse);
                    break;
                //end
                
                case RIL_UNSOL_RINGBACK_TONE:
                    if (RILJ_LOGD) unsljLogvRet(response, ret);
                    if (mRingbackToneRegistrants != null) {
                        boolean playtone = (((int[])ret)[0] == 1);
                        mRingbackToneRegistrants.notifyRegistrants(
                                            new AsyncResult (null, playtone, null));
                    }
                    break;

                case RIL_UNSOL_RESEND_INCALL_MUTE:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mResendIncallMuteRegistrants != null) {
                        mResendIncallMuteRegistrants.notifyRegistrants(
                                            new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mVoiceRadioTechChangedRegistrants != null) {
                        mVoiceRadioTechChangedRegistrants.notifyRegistrants(
                                new AsyncResult(null, ret, null));
                    }
                    break;

                case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mCdmaSubscriptionChangedRegistrants != null) {
                        mCdmaSubscriptionChangedRegistrants.notifyRegistrants(
                                            new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOL_ON_SS:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mSsRegistrant != null) {
                        mSsRegistrant.notifyRegistrant(
                                            new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOL_STK_CC_ALPHA_NOTIFY:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mCatCcAlphaRegistrant != null) {
                        mCatCcAlphaRegistrant.notifyRegistrant(
                                            new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOl_CDMA_PRL_CHANGED:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mCdmaPrlChangedRegistrants != null) {
                        mCdmaPrlChangedRegistrants.notifyRegistrants(
                                            new AsyncResult (null, ret, null));
                    }
                    break;

                case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE:
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mExitEmergencyCallbackModeRegistrants != null) {
                        mExitEmergencyCallbackModeRegistrants.notifyRegistrants(
                                            new AsyncResult (null, null, null));
                    }
                    break;

                case RIL_UNSOL_RIL_CONNECTED: {
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    // Initial conditions
                    setRadioPower(false, null);
                    setPreferredNetworkType(mPreferredNetworkType, null);
                    setCdmaSubscriptionSource(mCdmaSubscription, null);
                    setCellInfoListRate(Integer.MAX_VALUE, null);
                    notifyRegistrantsRilConnectionChanged(((int[])ret)[0]);
                    break;
                }
                case RIL_UNSOL_CELL_INFO_LIST: {
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mRilCellInfoListRegistrants != null) {
                        mRilCellInfoListRegistrants.notifyRegistrants(
                                            new AsyncResult (null, ret, null));
                    }
                    break;
                }

                case RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED: {
                    if (RILJ_LOGD) unsljLogRet(response, ret);

                    if (mSubscriptionStatusRegistrants != null) {
                        mSubscriptionStatusRegistrants.notifyRegistrants(
                                            new AsyncResult (null, ret, null));
                    }
                    break;
                }
            }
        }

    上述代码《TAG1-2》中,调用Registrant.java类中的mSMSRegistrant的notifyRegistrant()方法设置消息类型(what属性为EVENT_NEW_SMS),internalNotifyRegistrant()-->h.sendMessage(msg),并转到SMSDispatcher进行处理。代码如下:

        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);
            }

        }                 

    调用SMSDispatcher类中的<! GSM><EVENT_NEW_SMS>handlerMessage()  -->得到AsyncResult的对象ar

     public void handleMessage(Message msg) {
            AsyncResult ar;

            switch (msg.what) {
            case EVENT_NEW_SMS:
                // A new SMS has been received by the device
                if (DBG) Rlog.d(TAG, "New SMS Message Received");

                SmsMessage sms;

                ar = (AsyncResult) msg.obj;

                if (ar.exception != null) {
                    Rlog.e(TAG, "Exception processing incoming SMS. Exception:" + ar.exception);
                    return;
                }

                sms = (SmsMessage) ar.result;
                try {
                    int result = dispatchMessage(sms.mWrappedSmsMessage);
                    if (result != Activity.RESULT_OK) {
                        // RESULT_OK means that message was broadcast for app(s) to handle.
                        // Any other result, we should ack here.
                        boolean handled = (result == Intents.RESULT_SMS_HANDLED);
                        notifyAndAcknowledgeLastIncomingSms(handled, result, null);
                    }
                } catch (RuntimeException ex) {
                    Rlog.e(TAG, "Exception dispatching message", ex);
                    notifyAndAcknowledgeLastIncomingSms(false, Intents.RESULT_SMS_GENERIC_ERROR, null);
                }

                break;

    调用GSMSmsDispatcher.java类中的dispatchMessage() 方法再调用SMSDispatcher.javadispatchNormalMessage()方法,,  首先获取<SmsHeader smsHeader = sms.getUserDataHeader();>。如果 if ((smsHeader == null) || (smsHeader.concatRef == null))成立,而且 if (smsHeader != null && smsHeader.portAddrs != null) 成立,则调用<WapPushOverSms.java> dispatchWapPdu(),再调用<SMSDispatcher.java>  mSmsDispatcher.dispatch(intent, permission, appOp)<其中permission为android.permission.RECEIVE_MMS> ------>sendOrderedBroadcast();这里的Action为Intents.WAP_PUSH_RECEIVED_ACTION。接下来进入彩信的接收,由PushReceiver开始。

    public int dispatchWapPdu(byte[] pdu, String address) {

            if (DBG) Rlog.d(LOG_TAG, "Rx: " + IccUtils.bytesToHexString(pdu));

            int index = 0;
            int transactionId = pdu[index++] & 0xFF;
            int pduType = pdu[index++] & 0xFF;
            int headerLength = 0;

            if ((pduType != WspTypeDecoder.PDU_TYPE_PUSH) &&
                    (pduType != WspTypeDecoder.PDU_TYPE_CONFIRMED_PUSH)) {
                if (DBG) Rlog.w(LOG_TAG, "Received non-PUSH WAP PDU. Type = " + pduType);
                return Intents.RESULT_SMS_HANDLED;
            }

            pduDecoder = new WspTypeDecoder(pdu);

            /**
             * Parse HeaderLen(unsigned integer).
             * From wap-230-wsp-20010705-a section 8.1.2
             * The maximum size of a uintvar is 32 bits.
             * So it will be encoded in no more than 5 octets.
             */
            if (pduDecoder.decodeUintvarInteger(index) == false) {
                if (DBG) Rlog.w(LOG_TAG, "Received PDU. Header Length error.");
                return Intents.RESULT_SMS_GENERIC_ERROR;
            }
            headerLength = (int)pduDecoder.getValue32();
            index += pduDecoder.getDecodedDataLength();

            int headerStartIndex = index;

            /**
             * Parse Content-Type.
             * From wap-230-wsp-20010705-a section 8.4.2.24
             *
             * Content-type-value = Constrained-media | Content-general-form
             * Content-general-form = Value-length Media-type
             * Media-type = (Well-known-media | Extension-Media) *(Parameter)
             * Value-length = Short-length | (Length-quote Length)
             * Short-length = <Any octet 0-30>   (octet <= WAP_PDU_SHORT_LENGTH_MAX)
             * Length-quote = <Octet 31>         (WAP_PDU_LENGTH_QUOTE)
             * Length = Uintvar-integer
             */
            if (pduDecoder.decodeContentType(index) == false) {
                if (DBG) Rlog.w(LOG_TAG, "Received PDU. Header Content-Type error.");
                return Intents.RESULT_SMS_GENERIC_ERROR;
            }

            String mimeType = pduDecoder.getValueString();
            long binaryContentType = pduDecoder.getValue32();
            index += pduDecoder.getDecodedDataLength();

            byte[] header = new byte[headerLength];
            System.arraycopy(pdu, headerStartIndex, header, 0, header.length);

            byte[] intentData;

            if (mimeType != null && mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) {
                intentData = pdu;
            } else {
                int dataIndex = headerStartIndex + headerLength;
                intentData = new byte[pdu.length - dataIndex];
                System.arraycopy(pdu, dataIndex, intentData, 0, intentData.length);
            }

            /**
             * Seek for application ID field in WSP header.
             * If application ID is found, WapPushManager substitute the message
             * processing. Since WapPushManager is optional module, if WapPushManager
             * is not found, legacy message processing will be continued.
             */
            if (pduDecoder.seekXWapApplicationId(index, index + headerLength - 1)) {
                index = (int) pduDecoder.getValue32();
                pduDecoder.decodeXWapApplicationId(index);
                String wapAppId = pduDecoder.getValueString();
                if (wapAppId == null) {
                    wapAppId = Integer.toString((int) pduDecoder.getValue32());
                }

                String contentType = ((mimeType == null) ?
                                      Long.toString(binaryContentType) : mimeType);
                if (DBG) Rlog.v(LOG_TAG, "appid found: " + wapAppId + ":" + contentType);

                try {
                    boolean processFurther = true;
                    IWapPushManager wapPushMan = mWapConn.getWapPushManager();

                    if (wapPushMan == null) {
                        if (DBG) Rlog.w(LOG_TAG, "wap push manager not found!");
                    } else {
                        Intent intent = new Intent();
                        intent.putExtra("transactionId", transactionId);
                        intent.putExtra("pduType", pduType);
                        intent.putExtra("header", header);
                        intent.putExtra("data", intentData);
                        intent.putExtra("contentTypeParameters",
                                pduDecoder.getContentParameters());
                        intent.putExtra(MSimConstants.SUBSCRIPTION_KEY,
                                mSmsDispatcher.mPhone.getSubscription());
                        if (!TextUtils.isEmpty(address)){
                            intent.putExtra("address", address);
                        }

                        int procRet = wapPushMan.processMessage(wapAppId, contentType, intent);
                        if (DBG) Rlog.v(LOG_TAG, "procRet:" + procRet);
                        if ((procRet & WapPushManagerParams.MESSAGE_HANDLED) > 0
                            && (procRet & WapPushManagerParams.FURTHER_PROCESSING) == 0) {
                            processFurther = false;
                        }
                    }
                    if (!processFurther) {
                        return Intents.RESULT_SMS_HANDLED;
                    }
                } catch (RemoteException e) {
                    if (DBG) Rlog.w(LOG_TAG, "remote func failed...");
                }
            }
            if (DBG) Rlog.v(LOG_TAG, "fall back to existing handler");

            if (mimeType == null) {
                if (DBG) Rlog.w(LOG_TAG, "Header Content-Type error.");
                return Intents.RESULT_SMS_GENERIC_ERROR;
            }

            String permission;
            int appOp;

            if (mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_MMS)) {
                permission = android.Manifest.permission.RECEIVE_MMS;
                appOp = AppOpsManager.OP_RECEIVE_MMS;
            } else {
                permission = android.Manifest.permission.RECEIVE_WAP_PUSH;
                appOp = AppOpsManager.OP_RECEIVE_WAP_PUSH;
            }

            Intent intent = new Intent(Intents.WAP_PUSH_RECEIVED_ACTION);
            intent.setType(mimeType);
            intent.putExtra("transactionId", transactionId);
            intent.putExtra("pduType", pduType);
            intent.putExtra("header", header);
            intent.putExtra("data", intentData);
            intent.putExtra("contentTypeParameters", pduDecoder.getContentParameters());
            intent.putExtra(MSimConstants.SUBSCRIPTION_KEY, mSmsDispatcher.mPhone.getSubscription());
            if (!TextUtils.isEmpty(address)){
                intent.putExtra("address", address);
            }

            mSmsDispatcher.dispatch(intent, permission, appOp);

            return Activity.RESULT_OK;
        }

        public void dispatch(Intent intent, String permission, int appOp) {
            // Hold a wake lock for WAKE_LOCK_TIMEOUT seconds, enough to give any
            // receivers time to take their own wake locks.
            mWakeLock.acquire(WAKE_LOCK_TIMEOUT);
            mContext.sendOrderedBroadcast(intent, permission, appOp, mResultReceiver,
                    this, Activity.RESULT_OK, null, null);
        }

                      GSM和CDMA的短信接收有很大一部分是相同的,只是CDMA由于标准定义的不同,需要进行一些其他的处理,因为工作上没有对这部分进行测试,这里不作研究了。
  • 相关阅读:
    添加事件(jquery)
    闭包导致的问题
    学习之js绑定事件
    第二条 一个类如果有多个参数,考虑用Builder构造者模式
    用Intellij IDEA 创建第一个maven项目!
    OrderSessionHelper查看订单在session是否存在的辅助类
    css——overflow
    css——盒子
    css——外部样式
    css——权重叠加
  • 原文地址:https://www.cnblogs.com/bill-technology/p/4130918.html
Copyright © 2011-2022 走看看