diff options
author | Jake Hamby <jhamby@google.com> | 2012-07-24 15:39:45 -0700 |
---|---|---|
committer | Jake Hamby <jhamby@google.com> | 2012-07-25 15:06:26 -0700 |
commit | b8a13d300b245e0080aa01275e232f54d5d0e09c (patch) | |
tree | 53f57001744896fda9f51366bffbc1888ed3b34b | |
parent | 34661b1e9381d56b168777e3f18f6f9f2ad305c1 (diff) | |
download | frameworks_opt_telephony-b8a13d300b245e0080aa01275e232f54d5d0e09c.zip frameworks_opt_telephony-b8a13d300b245e0080aa01275e232f54d5d0e09c.tar.gz frameworks_opt_telephony-b8a13d300b245e0080aa01275e232f54d5d0e09c.tar.bz2 |
Implement CMAS service category program results.
Correctly handle CDMA Service Category Program Data requests,
and send the SCPT response to the message center. Parcel SCPD
operations as an ArrayList instead of an array (current version
will throw ClassCastException when the array is cast).
Bug: 6853691
Change-Id: I949ea68891c78306059248832e59a593ab606e11
5 files changed, 134 insertions, 16 deletions
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java index 4a6c5dc..76afbd0 100644 --- a/src/java/com/android/internal/telephony/SMSDispatcher.java +++ b/src/java/com/android/internal/telephony/SMSDispatcher.java @@ -354,6 +354,22 @@ public abstract class SMSDispatcher extends Handler { } /** + * Grabs a wake lock and sends intent as an ordered broadcast. + * Used for setting a custom result receiver for CDMA SCPD. + * + * @param intent intent to broadcast + * @param permission Receivers are required to have this permission + * @param resultReceiver the result receiver to use + */ + public void dispatch(Intent intent, String permission, BroadcastReceiver resultReceiver) { + // 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, resultReceiver, + this, Activity.RESULT_OK, null, null); + } + + /** * Called when SMS send completes. Broadcasts a sentIntent on success. * On failure, either sets up retries or broadcasts a sentIntent with * the failure in the result code. diff --git a/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java index 0f64e1d..1a49db9 100755 --- a/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java +++ b/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java @@ -20,19 +20,25 @@ package com.android.internal.telephony.cdma; import android.app.Activity; import android.app.PendingIntent; import android.app.PendingIntent.CanceledException; +import android.content.BroadcastReceiver; import android.content.ContentValues; +import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.res.Resources; import android.database.Cursor; import android.database.SQLException; +import android.os.Bundle; import android.os.Message; import android.os.SystemProperties; import android.preference.PreferenceManager; import android.provider.Telephony; import android.provider.Telephony.Sms.Intents; +import android.telephony.PhoneNumberUtils; import android.telephony.SmsCbMessage; import android.telephony.SmsManager; import android.telephony.cdma.CdmaSmsCbProgramData; +import android.telephony.cdma.CdmaSmsCbProgramResults; import android.util.Log; import com.android.internal.telephony.CommandsInterface; @@ -45,16 +51,17 @@ import com.android.internal.telephony.SmsStorageMonitor; import com.android.internal.telephony.SmsUsageMonitor; import com.android.internal.telephony.TelephonyProperties; import com.android.internal.telephony.WspTypeDecoder; +import com.android.internal.telephony.cdma.sms.BearerData; +import com.android.internal.telephony.cdma.sms.CdmaSmsAddress; import com.android.internal.telephony.cdma.sms.SmsEnvelope; import com.android.internal.telephony.cdma.sms.UserData; -import com.android.internal.util.HexDump; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.List; - -import android.content.res.Resources; final class CdmaSMSDispatcher extends SMSDispatcher { @@ -107,15 +114,16 @@ final class CdmaSMSDispatcher extends SMSDispatcher { * {@link android.telephony.cdma.CdmaSmsCbProgramData} objects. */ private void handleServiceCategoryProgramData(SmsMessage sms) { - List<CdmaSmsCbProgramData> programDataList = sms.getSmsCbProgramData(); + ArrayList<CdmaSmsCbProgramData> programDataList = sms.getSmsCbProgramData(); if (programDataList == null) { Log.e(TAG, "handleServiceCategoryProgramData: program data list is null!"); return; } Intent intent = new Intent(Intents.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION); - intent.putExtra("program_data_list", (CdmaSmsCbProgramData[]) programDataList.toArray()); - dispatch(intent, RECEIVE_SMS_PERMISSION); + intent.putExtra("sender", sms.getOriginatingAddress()); + intent.putParcelableArrayListExtra("program_data", programDataList); + dispatch(intent, RECEIVE_SMS_PERMISSION, mScpResultsReceiver); } /** {@inheritDoc} */ @@ -425,4 +433,72 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } return false; } + + // Receiver for Service Category Program Data results. + // We already ACK'd the original SCPD SMS, so this sends a new response SMS. + // TODO: handle retries if the RIL returns an error. + private final BroadcastReceiver mScpResultsReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + int rc = getResultCode(); + boolean success = (rc == Activity.RESULT_OK) || (rc == Intents.RESULT_SMS_HANDLED); + if (!success) { + Log.e(TAG, "SCP results error: result code = " + rc); + return; + } + Bundle extras = getResultExtras(false); + if (extras == null) { + Log.e(TAG, "SCP results error: missing extras"); + return; + } + String sender = extras.getString("sender"); + if (sender == null) { + Log.e(TAG, "SCP results error: missing sender extra."); + return; + } + ArrayList<CdmaSmsCbProgramResults> results + = extras.getParcelableArrayList("results"); + if (results == null) { + Log.e(TAG, "SCP results error: missing results extra."); + return; + } + + BearerData bData = new BearerData(); + bData.messageType = BearerData.MESSAGE_TYPE_SUBMIT; + bData.messageId = SmsMessage.getNextMessageId(); + bData.serviceCategoryProgramResults = results; + byte[] encodedBearerData = BearerData.encode(bData); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(100); + DataOutputStream dos = new DataOutputStream(baos); + try { + dos.writeInt(SmsEnvelope.TELESERVICE_SCPT); + dos.writeInt(0); //servicePresent + dos.writeInt(0); //serviceCategory + CdmaSmsAddress destAddr = CdmaSmsAddress.parse( + PhoneNumberUtils.cdmaCheckAndProcessPlusCode(sender)); + dos.write(destAddr.digitMode); + dos.write(destAddr.numberMode); + dos.write(destAddr.ton); // number_type + dos.write(destAddr.numberPlan); + dos.write(destAddr.numberOfDigits); + dos.write(destAddr.origBytes, 0, destAddr.origBytes.length); // digits + // Subaddress is not supported. + dos.write(0); //subaddressType + dos.write(0); //subaddr_odd + dos.write(0); //subaddr_nbr_of_digits + dos.write(encodedBearerData.length); + dos.write(encodedBearerData, 0, encodedBearerData.length); + // Ignore the RIL response. TODO: implement retry if SMS send fails. + mCm.sendCdmaSms(baos.toByteArray(), null); + } catch (IOException e) { + Log.e(TAG, "exception creating SCP results PDU", e); + } finally { + try { + dos.close(); + } catch (IOException ignored) { + } + } + } + }; } diff --git a/src/java/com/android/internal/telephony/cdma/SmsMessage.java b/src/java/com/android/internal/telephony/cdma/SmsMessage.java index fc61bae..617a328 100644 --- a/src/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/src/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -44,6 +44,7 @@ import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.ArrayList; import java.util.List; /** @@ -782,7 +783,7 @@ public class SmsMessage extends SmsMessageBase { * binder-call, and hence should be thread-safe, it has been * synchronized. */ - private synchronized static int getNextMessageId() { + synchronized static int getNextMessageId() { // Testing and dialog with partners has indicated that // msgId==0 is (sometimes?) treated specially by lower levels. // Specifically, the ID is not preserved for delivery ACKs. @@ -998,7 +999,7 @@ public class SmsMessage extends SmsMessageBase { * Returns the list of service category program data, if present. * @return a list of CdmaSmsCbProgramData objects, or null if not present */ - List<CdmaSmsCbProgramData> getSmsCbProgramData() { + ArrayList<CdmaSmsCbProgramData> getSmsCbProgramData() { return mBearerData.serviceCategoryProgramData; } } diff --git a/src/java/com/android/internal/telephony/cdma/sms/BearerData.java b/src/java/com/android/internal/telephony/cdma/sms/BearerData.java index 7e7347f..7ff9e50 100755 --- a/src/java/com/android/internal/telephony/cdma/sms/BearerData.java +++ b/src/java/com/android/internal/telephony/cdma/sms/BearerData.java @@ -20,6 +20,7 @@ import android.content.res.Resources; import android.telephony.SmsCbCmasInfo; import android.telephony.SmsCbMessage; import android.telephony.cdma.CdmaSmsCbProgramData; +import android.telephony.cdma.CdmaSmsCbProgramResults; import android.text.format.Time; import android.util.Log; @@ -32,8 +33,6 @@ import com.android.internal.util.BitwiseInputStream; import com.android.internal.util.BitwiseOutputStream; import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import java.util.TimeZone; /** @@ -349,7 +348,14 @@ public final class BearerData { * {@link android.telephony.cdma.CdmaSmsCbProgramData} objects containing the * operation(s) to perform. */ - public List<CdmaSmsCbProgramData> serviceCategoryProgramData; + public ArrayList<CdmaSmsCbProgramData> serviceCategoryProgramData; + + /** + * The Service Category Program Results subparameter informs the message center + * of the results of a Service Category Program Data request. + */ + public ArrayList<CdmaSmsCbProgramResults> serviceCategoryProgramResults; + private static class CodingException extends Exception { public CodingException(String s) { @@ -853,6 +859,21 @@ public final class BearerData { outStream.skip(6); } + private static void encodeScpResults(BearerData bData, BitwiseOutputStream outStream) + throws BitwiseOutputStream.AccessException + { + ArrayList<CdmaSmsCbProgramResults> results = bData.serviceCategoryProgramResults; + outStream.write(8, (results.size() * 4)); // 4 octets per program result + for (CdmaSmsCbProgramResults result : results) { + int category = result.getCategory(); + outStream.write(8, category >> 8); + outStream.write(8, category); + outStream.write(8, result.getLanguage()); + outStream.write(4, result.getCategoryResult()); + outStream.skip(4); + } + } + /** * Create serialized representation for BearerData object. * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details) @@ -912,6 +933,10 @@ public final class BearerData { outStream.write(8, SUBPARAM_MESSAGE_STATUS); encodeMsgStatus(bData, outStream); } + if (bData.serviceCategoryProgramResults != null) { + outStream.write(8, SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS); + encodeScpResults(bData, outStream); + } return outStream.toByteArray(); } catch (BitwiseOutputStream.AccessException ex) { Log.e(LOG_TAG, "BearerData encode failed: " + ex); @@ -1634,7 +1659,7 @@ public final class BearerData { while (paramBits >= CATEGORY_FIELD_MIN_SIZE) { int operation = inStream.read(4); int category = (inStream.read(8) << 8) | inStream.read(8); - String language = getLanguageCodeForValue(inStream.read(8)); + int language = inStream.read(8); int maxMessages = inStream.read(8); int alertOption = inStream.read(4); int numFields = inStream.read(8); diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java index d2faceb..a95f60c 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java @@ -635,7 +635,7 @@ public class CdmaSmsCbTest extends AndroidTestCase { assertEquals(CdmaSmsCbProgramData.OPERATION_ADD_CATEGORY, programData.getOperation()); assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT, programData.getCategory()); assertEquals(CAT_EXTREME_THREAT, programData.getCategoryName()); - assertEquals("en", programData.getLanguageCode()); + assertEquals(BearerData.LANGUAGE_ENGLISH, programData.getLanguage()); assertEquals(100, programData.getMaxMessages()); assertEquals(CdmaSmsCbProgramData.ALERT_OPTION_DEFAULT_ALERT, programData.getAlertOption()); } @@ -692,7 +692,7 @@ public class CdmaSmsCbTest extends AndroidTestCase { assertEquals(CdmaSmsCbProgramData.OPERATION_DELETE_CATEGORY, programData.getOperation()); assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT, programData.getCategory()); assertEquals(CAT_SEVERE_THREAT, programData.getCategoryName()); - assertEquals("en", programData.getLanguageCode()); + assertEquals(BearerData.LANGUAGE_ENGLISH, programData.getLanguage()); assertEquals(0, programData.getMaxMessages()); assertEquals(CdmaSmsCbProgramData.ALERT_OPTION_NO_ALERT, programData.getAlertOption()); @@ -701,7 +701,7 @@ public class CdmaSmsCbTest extends AndroidTestCase { assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY, programData.getCategory()); assertEquals(CAT_AMBER_ALERTS, programData.getCategoryName()); - assertEquals("en", programData.getLanguageCode()); + assertEquals(BearerData.LANGUAGE_ENGLISH, programData.getLanguage()); assertEquals(0, programData.getMaxMessages()); assertEquals(CdmaSmsCbProgramData.ALERT_OPTION_NO_ALERT, programData.getAlertOption()); } |