summaryrefslogtreecommitdiffstats
path: root/telephony/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'telephony/java/android')
-rw-r--r--telephony/java/android/telephony/SmsManager.java52
-rw-r--r--telephony/java/android/telephony/SmsMessage.java138
2 files changed, 110 insertions, 80 deletions
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 9395d66..890f930 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -22,7 +22,6 @@ import android.os.ServiceManager;
import android.text.TextUtils;
import com.android.internal.telephony.EncodeException;
-import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.ISms;
import com.android.internal.telephony.IccConstants;
import com.android.internal.telephony.SmsRawData;
@@ -31,14 +30,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import static android.telephony.SmsMessage.ENCODING_7BIT;
-import static android.telephony.SmsMessage.ENCODING_8BIT;
-import static android.telephony.SmsMessage.ENCODING_16BIT;
-import static android.telephony.SmsMessage.ENCODING_UNKNOWN;
-import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES;
-import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;
-import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS;
-import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER;
+/*
+ * TODO(code review): Curious question... Why are a lot of these
+ * methods not declared as static, since they do not seem to require
+ * any local object state? Assumedly this cannot be changed without
+ * interfering with the API...
+ */
/**
* Manages SMS operations such as sending data, text, and pdu SMS messages.
@@ -88,7 +85,7 @@ public final class SmsManager {
}
/**
- * Divide a text message into several messages, none bigger than
+ * Divide a message text into several fragments, none bigger than
* the maximum SMS message size.
*
* @param text the original message. Must not be null.
@@ -96,40 +93,7 @@ public final class SmsManager {
* comprise the original message
*/
public ArrayList<String> divideMessage(String text) {
- int size = text.length();
- int[] params = SmsMessage.calculateLength(text, false);
- /* SmsMessage.calculateLength returns an int[4] with:
- * int[0] being the number of SMS's required,
- * int[1] the number of code units used,
- * int[2] is the number of code units remaining until the next message.
- * int[3] is the encoding type that should be used for the message.
- */
- int messageCount = params[0];
- int encodingType = params[3];
- ArrayList<String> result = new ArrayList<String>(messageCount);
-
- int start = 0;
- int limit;
-
- if (messageCount > 1) {
- limit = (encodingType == ENCODING_7BIT)?
- MAX_USER_DATA_SEPTETS_WITH_HEADER: MAX_USER_DATA_BYTES_WITH_HEADER;
- } else {
- limit = (encodingType == ENCODING_7BIT)?
- MAX_USER_DATA_SEPTETS: MAX_USER_DATA_BYTES;
- }
-
- try {
- while (start < size) {
- int end = GsmAlphabet.findLimitIndex(text, start, limit, encodingType);
- result.add(text.substring(start, end));
- start = end;
- }
- }
- catch (EncodeException e) {
- // ignore it.
- }
- return result;
+ return SmsMessage.fragmentText(text);
}
/**
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index b60da5a..775b034 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -17,12 +17,17 @@
package android.telephony;
import android.os.Parcel;
+import android.util.Log;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.EncodeException;
import com.android.internal.telephony.SmsHeader;
import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.SmsMessageBase.SubmitPduBase;
+import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails;
+
+import java.lang.Math;
+import java.util.ArrayList;
import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
@@ -44,19 +49,41 @@ public class SmsMessage {
UNKNOWN, CLASS_0, CLASS_1, CLASS_2, CLASS_3;
}
- /** Unknown encoding scheme (see TS 23.038) */
+ /**
+ * TODO(cleanup): given that we now have more than one possible
+ * 7bit encoding, this result starts to look rather vague and
+ * maybe confusing... If this is just an indication of code unit
+ * size, maybe that is no problem. Otherwise, should we try to
+ * create an aggregate collection of GSM and CDMA encodings? CDMA
+ * contains a superset of the encodings we use (it does not
+ * support 8-bit GSM, but we also do not use that encoding
+ * currently)... We could get rid of these and directly reference
+ * the CDMA encoding definitions...
+ */
+
+ /** User data text encoding code unit size */
public static final int ENCODING_UNKNOWN = 0;
- /** 7-bit encoding scheme (see TS 23.038) */
public static final int ENCODING_7BIT = 1;
- /** 8-bit encoding scheme (see TS 23.038) */
public static final int ENCODING_8BIT = 2;
- /** 16-bit encoding scheme (see TS 23.038) */
public static final int ENCODING_16BIT = 3;
/** The maximum number of payload bytes per message */
public static final int MAX_USER_DATA_BYTES = 140;
/**
+ * TODO(cleanup): It would be more flexible and less fragile to
+ * rewrite this (meaning get rid of the following constant) such
+ * that an actual UDH is taken into consideration (meaning its
+ * length is measured), allowing for messages that actually
+ * contain other UDH fields... Hence it is actually a shame to
+ * extend the API with this constant. If necessary, maybe define
+ * the size of such a header and let the math for calculating
+ * max_octets/septets be done elsewhere. And, while I am griping,
+ * if we use the word septet, we should use the word octet in
+ * corresponding places, not byte...
+ */
+
+ /**
* The maximum number of payload bytes per message if a user data header
* is present. This assumes the header only contains the
* CONCATENATED_8_BIT_REFERENCE element.
@@ -222,6 +249,15 @@ public class SmsMessage {
}
}
+ /*
+ * TODO(cleanup): It would make some sense if the result of
+ * preprocessing a message to determine the proper encoding (ie
+ * the resulting datastructure from calculateLength) could be
+ * passed as an argument to the actual final encoding function.
+ * This would better ensure that the logic behind size calculation
+ * actually matched the encoding.
+ */
+
/**
* Calculates the number of SMS's required to encode the message body and
* the number of characters remaining until the next message.
@@ -232,46 +268,76 @@ public class SmsMessage {
* space chars. If false, and if the messageBody contains
* non-7-bit encodable characters, length is calculated
* using a 16-bit encoding.
- * @return an int[4] with int[0] being the number of SMS's required, int[1]
- * the number of code units used, and int[2] is the number of code
- * units remaining until the next message. int[3] is the encoding
- * type that should be used for the message.
+ * @return an int[4] with int[0] being the number of SMS's
+ * required, int[1] the number of code units used, and
+ * int[2] is the number of code units remaining until the
+ * next message. int[3] is an indicator of the encoding
+ * code unit size (see the ENCODING_* definitions in this
+ * class).
*/
public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly) {
int activePhone = TelephonyManager.getDefault().getPhoneType();
+ TextEncodingDetails ted = (PHONE_TYPE_CDMA == activePhone) ?
+ com.android.internal.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly) :
+ com.android.internal.telephony.cdma.SmsMessage.calculateLength(msgBody, use7bitOnly);
int ret[] = new int[4];
+ ret[0] = ted.msgCount;
+ ret[1] = ted.codeUnitCount;
+ ret[2] = ted.codeUnitsRemaining;
+ ret[3] = ted.codeUnitSize;
+ return ret;
+ }
- int septets = (PHONE_TYPE_CDMA == activePhone) ?
- com.android.internal.telephony.cdma.SmsMessage.calc7bitEncodedLength(msgBody,
- use7bitOnly) :
- com.android.internal.telephony.gsm.SmsMessage.calc7bitEncodedLength(msgBody,
- use7bitOnly);
- if (septets != -1) {
- ret[1] = septets;
- if (septets > MAX_USER_DATA_SEPTETS) {
- ret[0] = (septets / MAX_USER_DATA_SEPTETS_WITH_HEADER) + 1;
- ret[2] = MAX_USER_DATA_SEPTETS_WITH_HEADER
- - (septets % MAX_USER_DATA_SEPTETS_WITH_HEADER);
- } else {
- ret[0] = 1;
- ret[2] = MAX_USER_DATA_SEPTETS - septets;
- }
- ret[3] = ENCODING_7BIT;
+ /**
+ * Divide a message text into several fragments, none bigger than
+ * the maximum SMS message text size.
+ *
+ * @param text text, must not be null.
+ * @return an <code>ArrayList</code> of strings that, in order,
+ * comprise the original msg text
+ */
+ public static ArrayList<String> fragmentText(String text) {
+ int activePhone = TelephonyManager.getDefault().getPhoneType();
+ TextEncodingDetails ted = (PHONE_TYPE_CDMA == activePhone) ?
+ com.android.internal.telephony.gsm.SmsMessage.calculateLength(text, false) :
+ com.android.internal.telephony.cdma.SmsMessage.calculateLength(text, false);
+
+ // TODO(cleanup): The code here could be rolled into the logic
+ // below cleanly if these MAX_* constants were defined more
+ // flexibly...
+
+ int limit;
+ if (ted.msgCount > 1) {
+ limit = (ted.codeUnitSize == ENCODING_7BIT) ?
+ MAX_USER_DATA_SEPTETS_WITH_HEADER : MAX_USER_DATA_BYTES_WITH_HEADER;
} else {
- int octets = msgBody.length() * 2;
- ret[1] = msgBody.length();
- if (octets > MAX_USER_DATA_BYTES) {
- ret[0] = (octets / MAX_USER_DATA_BYTES_WITH_HEADER) + 1;
- ret[2] = (MAX_USER_DATA_BYTES_WITH_HEADER
- - (octets % MAX_USER_DATA_BYTES_WITH_HEADER))/2;
- } else {
- ret[0] = 1;
- ret[2] = (MAX_USER_DATA_BYTES - octets)/2;
- }
- ret[3] = ENCODING_16BIT;
+ limit = (ted.codeUnitSize == ENCODING_7BIT) ?
+ MAX_USER_DATA_SEPTETS : MAX_USER_DATA_BYTES;
}
- return ret;
+ int pos = 0; // Index in code units.
+ int textLen = text.length();
+ ArrayList<String> result = new ArrayList<String>(ted.msgCount);
+ while (pos < textLen) {
+ int nextPos = 0; // Counts code units.
+ if (ted.codeUnitSize == ENCODING_7BIT) {
+ if (PHONE_TYPE_CDMA == activePhone) {
+ nextPos = pos + Math.min(limit, textLen - pos);
+ } else {
+ nextPos = GsmAlphabet.findGsmSeptetLimitIndex(text, pos, limit);
+ }
+ } else { // Assume unicode.
+ nextPos = pos + Math.min(limit / 2, textLen - pos);
+ }
+ if ((nextPos <= pos) || (nextPos > textLen)) {
+ Log.e(LOG_TAG, "fragmentText failed (" + pos + " >= " + nextPos + " or " +
+ nextPos + " >= " + textLen + ")");
+ break;
+ }
+ result.add(text.substring(pos, nextPos));
+ pos = nextPos;
+ }
+ return result;
}
/**