From d304ae583d862250a21b5949fc3dbdf3af1febac Mon Sep 17 00:00:00 2001 From: Tammo Spalink Date: Thu, 3 Sep 2009 19:05:53 +0800 Subject: Fix CDMA SMS delivery status reporting. CDMA SMS status reports are messages with bearer data message type DELIVERY_ACK. Identify these messages after parsing during demux, update the deliveryPendingList and generate a RESULT_OK intent in the same manner as GSM. Addresses issue: http://buganizer/issue?id=2047571 Change-Id: Ia38718b0bb169a0f3398f50c27a95e8bce7e4c99 --- .../internal/telephony/cdma/CdmaSMSDispatcher.java | 29 ++++++++++++++- .../internal/telephony/cdma/SmsMessage.java | 43 +++++++++++----------- 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java index bf42257..623d985 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java @@ -21,6 +21,7 @@ import android.app.Activity; import android.app.PendingIntent; import android.app.PendingIntent.CanceledException; import android.content.ContentValues; +import android.content.Intent; import android.content.SharedPreferences; import android.database.Cursor; import android.database.SQLException; @@ -73,6 +74,23 @@ final class CdmaSMSDispatcher extends SMSDispatcher { Log.d(TAG, "handleStatusReport is a special GSM function, should never be called in CDMA!"); } + private void handleCdmaStatusReport(SmsMessage sms) { + for (int i = 0, count = deliveryPendingList.size(); i < count; i++) { + SmsTracker tracker = deliveryPendingList.get(i); + if (tracker.mMessageRef == sms.messageRef) { + // Found it. Remove from list and broadcast. + deliveryPendingList.remove(i); + PendingIntent intent = tracker.mDeliveryIntent; + Intent fillIn = new Intent(); + fillIn.putExtra("pdu", sms.getPdu()); + try { + intent.send(mContext, Activity.RESULT_OK, fillIn); + } catch (CanceledException ex) {} + break; // Only expect to see one tracker matching this message. + } + } + } + /** {@inheritDoc} */ protected int dispatchMessage(SmsMessageBase smsb) { @@ -105,6 +123,11 @@ final class CdmaSMSDispatcher extends SMSDispatcher { editor.commit(); ((CDMAPhone) mPhone).updateMessageWaitingIndicator(voicemailCount); handled = true; + } else if (((SmsEnvelope.TELESERVICE_WMT == teleService) || + (SmsEnvelope.TELESERVICE_WEMT == teleService)) && + sms.isStatusReportMessage()) { + handleCdmaStatusReport(sms); + handled = true; } else if ((sms.getUserData() == null)) { if (Config.LOGD) { Log.d(TAG, "Received SMS without user data"); @@ -354,8 +377,12 @@ final class CdmaSMSDispatcher extends SMSDispatcher { uData.payloadStr = parts.get(i); uData.userDataHeader = smsHeader; + /* By setting the statusReportRequested bit only for the + * last message fragment, this will result in only one + * callback to the sender when that last fragment delivery + * has been acknowledged. */ SmsMessage.SubmitPdu submitPdu = SmsMessage.getSubmitPdu(destAddr, - uData, deliveryIntent != null); + uData, (deliveryIntent != null) && (i == (msgCount - 1))); sendSubmitPdu(submitPdu, sentIntent, deliveryIntent); } diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index d17468c..165d583 100755 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -424,12 +424,9 @@ public class SmsMessage extends SmsMessageBase { return (status << 16); } - /** - * Note: This function is a GSM specific functionality which is not supported in CDMA mode. - */ + /** Return true iff the bearer data message type is DELIVERY_ACK. */ public boolean isStatusReportMessage() { - Log.w(LOG_TAG, "isStatusReportMessage: is not supported in CDMA mode."); - return false; + return (mBearerData.messageType == BearerData.MESSAGE_TYPE_DELIVERY_ACK); } /** @@ -548,17 +545,6 @@ public class SmsMessage extends SmsMessageBase { messageBody = mBearerData.userData.payloadStr; } - // TP-Message-Type-Indicator (See 3GPP2 C.S0015-B, v2, 4.5.1) - switch (mBearerData.messageType) { - case BearerData.MESSAGE_TYPE_USER_ACK: - case BearerData.MESSAGE_TYPE_READ_ACK: - case BearerData.MESSAGE_TYPE_DELIVER: - case BearerData.MESSAGE_TYPE_DELIVERY_ACK: - break; - default: - throw new RuntimeException("Unsupported message type: " + mBearerData.messageType); - } - if (originatingAddress != null) { originatingAddress.address = new String(originatingAddress.origBytes); if (Config.LOGV) Log.v(LOG_TAG, "SMS originating address: " @@ -571,11 +557,26 @@ public class SmsMessage extends SmsMessageBase { if (Config.LOGD) Log.d(LOG_TAG, "SMS SC timestamp: " + scTimeMillis); - // TODO(Teleca): do we really want this test to occur only for DELIVERY_ACKs? - if ((mBearerData.messageType == BearerData.MESSAGE_TYPE_DELIVERY_ACK) && - (mBearerData.errorClass != BearerData.ERROR_UNDEFINED)) { - status = mBearerData.errorClass << 8; - status |= mBearerData.messageStatus; + // Message Type (See 3GPP2 C.S0015-B, v2, 4.5.1) + if (mBearerData.messageType == BearerData.MESSAGE_TYPE_DELIVERY_ACK) { + // The BearerData MsgStatus subparameter should only be + // included for DELIVERY_ACK messages. If it occurred for + // other messages, it would be unclear what the status + // being reported refers to. The MsgStatus subparameter + // is primarily useful to indicate error conditions -- a + // message without this subparameter is assumed to + // indicate successful delivery (status == 0). + if (! mBearerData.messageStatusSet) { + Log.d(LOG_TAG, "DELIVERY_ACK message without msgStatus (" + + (userData == null ? "also missing" : "does have") + + " userData)."); + status = 0; + } else { + status = mBearerData.errorClass << 8; + status |= mBearerData.messageStatus; + } + } else if (mBearerData.messageType != BearerData.MESSAGE_TYPE_DELIVER) { + throw new RuntimeException("Unsupported message type: " + mBearerData.messageType); } if (messageBody != null) { -- cgit v1.1