Skip to content
Browse files

Merge "Implement CMAS service category program results." into jb

  • Loading branch information...
2 parents cc80ba6 + a53f0f6 commit 0e292221195a453979314b31853ff7762310768d @KhasMek KhasMek committed with Gerrit Code Review
View
18 telephony/java/android/telephony/cdma/CdmaSmsCbProgramData.java
@@ -81,8 +81,8 @@
/** Service category to modify. */
private final int mCategory;
- /** Language used for service category name (ISO 639 two character code). */
- private final String mLanguage;
+ /** Language used for service category name (defined in BearerData.LANGUAGE_*). */
+ private final int mLanguage;
/** Maximum number of messages to store for this service category. */
private final int mMaxMessages;
@@ -94,7 +94,7 @@
private final String mCategoryName;
/** Create a new CdmaSmsCbProgramData object with the specified values. */
- public CdmaSmsCbProgramData(int operation, int category, String language, int maxMessages,
+ public CdmaSmsCbProgramData(int operation, int category, int language, int maxMessages,
int alertOption, String categoryName) {
mOperation = operation;
mCategory = category;
@@ -108,7 +108,7 @@ public CdmaSmsCbProgramData(int operation, int category, String language, int ma
CdmaSmsCbProgramData(Parcel in) {
mOperation = in.readInt();
mCategory = in.readInt();
- mLanguage = in.readString();
+ mLanguage = in.readInt();
mMaxMessages = in.readInt();
mAlertOption = in.readInt();
mCategoryName = in.readString();
@@ -124,7 +124,7 @@ public CdmaSmsCbProgramData(int operation, int category, String language, int ma
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mOperation);
dest.writeInt(mCategory);
- dest.writeString(mLanguage);
+ dest.writeInt(mLanguage);
dest.writeInt(mMaxMessages);
dest.writeInt(mAlertOption);
dest.writeString(mCategoryName);
@@ -147,10 +147,10 @@ public int getCategory() {
}
/**
- * Returns the ISO-639-1 language code for the service category name, or null if not present.
- * @return a two-digit ISO-639-1 language code, e.g. "en" for English
+ * Returns the CDMA language code for this service category.
+ * @return one of the language values defined in BearerData.LANGUAGE_*
*/
- public String getLanguageCode() {
+ public int getLanguage() {
return mLanguage;
}
@@ -171,7 +171,7 @@ public int getAlertOption() {
}
/**
- * Returns the service category name, in the language specified by {@link #getLanguageCode()}.
+ * Returns the service category name, in the language specified by {@link #getLanguage()}.
* @return an optional service category name
*/
public String getCategoryName() {
View
144 telephony/java/android/telephony/cdma/CdmaSmsCbProgramResults.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.cdma;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * CDMA Service Category Program Results from SCPT teleservice SMS.
+ *
+ * {@hide}
+ */
+public class CdmaSmsCbProgramResults implements Parcelable {
+
+ /** Program result: success. */
+ public static final int RESULT_SUCCESS = 0;
+
+ /** Program result: memory limit exceeded. */
+ public static final int RESULT_MEMORY_LIMIT_EXCEEDED = 1;
+
+ /** Program result: limit exceeded. */
+ public static final int RESULT_CATEGORY_LIMIT_EXCEEDED = 2;
+
+ /** Program result: category already opted in. */
+ public static final int RESULT_CATEGORY_ALREADY_ADDED = 3;
+
+ /** Program result: category already opted in. */
+ public static final int RESULT_CATEGORY_ALREADY_DELETED = 4;
+
+ /** Program result: invalid MAX_MESSAGES. */
+ public static final int RESULT_INVALID_MAX_MESSAGES = 5;
+
+ /** Program result: invalid ALERT_OPTION. */
+ public static final int RESULT_INVALID_ALERT_OPTION = 6;
+
+ /** Program result: invalid service category name. */
+ public static final int RESULT_INVALID_CATEGORY_NAME = 7;
+
+ /** Program result: unspecified programming failure. */
+ public static final int RESULT_UNSPECIFIED_FAILURE = 8;
+
+ /** Service category to modify. */
+ private final int mCategory;
+
+ /** Language used for service category name (defined in BearerData.LANGUAGE_*). */
+ private final int mLanguage;
+
+ /** Result of service category programming for this category. */
+ private final int mCategoryResult;
+
+ /** Create a new CdmaSmsCbProgramResults object with the specified values. */
+ public CdmaSmsCbProgramResults(int category, int language, int categoryResult) {
+ mCategory = category;
+ mLanguage = language;
+ mCategoryResult = categoryResult;
+ }
+
+ /** Create a new CdmaSmsCbProgramResults object from a Parcel. */
+ CdmaSmsCbProgramResults(Parcel in) {
+ mCategory = in.readInt();
+ mLanguage = in.readInt();
+ mCategoryResult = in.readInt();
+ }
+
+ /**
+ * Flatten this object into a Parcel.
+ *
+ * @param dest The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written (ignored).
+ */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mCategory);
+ dest.writeInt(mLanguage);
+ dest.writeInt(mCategoryResult);
+ }
+
+ /**
+ * Returns the CDMA service category to modify.
+ * @return a 16-bit CDMA service category value
+ */
+ public int getCategory() {
+ return mCategory;
+ }
+
+ /**
+ * Returns the CDMA language code for this service category.
+ * @return one of the language values defined in BearerData.LANGUAGE_*
+ */
+ public int getLanguage() {
+ return mLanguage;
+ }
+
+ /**
+ * Returns the result of service programming for this category
+ * @return the result of service programming for this category
+ */
+ public int getCategoryResult() {
+ return mCategoryResult;
+ }
+
+ @Override
+ public String toString() {
+ return "CdmaSmsCbProgramResults{category=" + mCategory
+ + ", language=" + mLanguage + ", result=" + mCategoryResult + '}';
+ }
+
+ /**
+ * Describe the kinds of special objects contained in the marshalled representation.
+ * @return a bitmask indicating this Parcelable contains no special objects
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Creator for unparcelling objects. */
+ public static final Parcelable.Creator<CdmaSmsCbProgramResults>
+ CREATOR = new Parcelable.Creator<CdmaSmsCbProgramResults>() {
+ @Override
+ public CdmaSmsCbProgramResults createFromParcel(Parcel in) {
+ return new CdmaSmsCbProgramResults(in);
+ }
+
+ @Override
+ public CdmaSmsCbProgramResults[] newArray(int size) {
+ return new CdmaSmsCbProgramResults[size];
+ }
+ };
+}
View
16 telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -339,6 +339,22 @@ public void dispatch(Intent intent, String permission) {
}
/**
+ * 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.
View
92 telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -20,20 +20,23 @@
import android.app.Activity;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
-import android.content.ContentValues;
+import android.content.BroadcastReceiver;
+import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.database.Cursor;
-import android.database.SQLException;
+import android.content.res.Resources;
+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.SmsMessage.MessageClass;
import android.telephony.cdma.CdmaSmsCbProgramData;
+import android.telephony.cdma.CdmaSmsCbProgramResults;
import android.util.Log;
import com.android.internal.telephony.CommandsInterface;
@@ -45,17 +48,19 @@
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.BitwiseInputStream;
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 {
@@ -108,15 +113,16 @@ private void handleCdmaStatusReport(SmsMessage sms) {
* {@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} */
@@ -494,4 +500,72 @@ private static boolean checkDuplicatePortOmadmWappush(byte[] origPdu, int index)
}
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) {
+ }
+ }
+ }
+ };
}
View
5 telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -42,6 +42,7 @@
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
import static android.telephony.SmsMessage.MessageClass;
@@ -781,7 +782,7 @@ public MessageClass getMessageClass() {
* 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.
@@ -997,7 +998,7 @@ private byte convertDtmfToAscii(byte dtmfDigit) {
* 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;
}
}
View
34 telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -18,9 +18,9 @@
import android.content.res.Resources;
import android.telephony.SmsCbCmasInfo;
-import android.telephony.SmsCbMessage;
import android.telephony.SmsMessage;
import android.telephony.cdma.CdmaSmsCbProgramData;
+import android.telephony.cdma.CdmaSmsCbProgramResults;
import android.text.format.Time;
import android.util.Log;
@@ -32,8 +32,6 @@
import com.android.internal.util.BitwiseOutputStream;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
import java.util.TimeZone;
import static android.telephony.SmsMessage.ENCODING_16BIT;
@@ -353,7 +351,14 @@ public String toString() {
* {@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) {
@@ -857,6 +862,21 @@ private static void encodeMsgDeliveryAlert(BearerData bData, BitwiseOutputStream
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)
@@ -916,6 +936,10 @@ private static void encodeMsgDeliveryAlert(BearerData bData, BitwiseOutputStream
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);
@@ -1649,7 +1673,7 @@ private static boolean decodeServiceCategoryProgramData(BearerData bData,
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);
View
6 telephony/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
@@ -635,7 +635,7 @@ public void testServiceCategoryProgramDataAddCategory() throws Exception {
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 void testServiceCategoryProgramDataDeleteTwoCategories() throws Exception
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 void testServiceCategoryProgramDataDeleteTwoCategories() throws Exception
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());
}

0 comments on commit 0e29222

Please sign in to comment.
Something went wrong with that request. Please try again.