use of com.android.internal.telephony.GsmAlphabet.TextEncodingDetails in project android_frameworks_opt_telephony by LineageOS.
the class SMSDispatcher method sendMultipartText.
/**
* Send a multi-part text based SMS.
* @param destAddr the address to send the message to
* @param scAddr is the service center address or null to use
* the current default SMSC
* @param parts an <code>ArrayList</code> of strings that, in order,
* comprise the original message
* @param sentIntents if not null, an <code>ArrayList</code> of
* <code>PendingIntent</code>s (one for each message part) that is
* broadcast when the corresponding message part has been sent.
* The result code will be <code>Activity.RESULT_OK<code> for success,
* or one of these errors:
* <code>RESULT_ERROR_GENERIC_FAILURE</code>
* <code>RESULT_ERROR_RADIO_OFF</code>
* <code>RESULT_ERROR_NULL_PDU</code>
* <code>RESULT_ERROR_NO_SERVICE</code>.
* The per-application based SMS control checks sentIntent. If sentIntent
* is NULL the caller will be checked against all unknown applications,
* which cause smaller number of SMS to be sent in checking period.
* @param deliveryIntents if not null, an <code>ArrayList</code> of
* <code>PendingIntent</code>s (one for each message part) that is
* broadcast when the corresponding message part has been delivered
* to the recipient. The raw pdu of the status report is in the
* @param messageUri optional URI of the message if it is already stored in the system
* @param callingPkg the calling package name
* @param persistMessage whether to save the sent message into SMS DB for a
* non-default SMS app.
* @param priority Priority level of the message
* Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1
* ---------------------------------
* PRIORITY | Level of Priority
* ---------------------------------
* '00' | Normal
* '01' | Interactive
* '10' | Urgent
* '11' | Emergency
* ----------------------------------
* Any Other values included Negative considered as Invalid Priority Indicator of the message.
* @param expectMore is a boolean to indicate the sending messages through same link or not.
* @param validityPeriod Validity Period of the message in mins.
* Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1.
* Validity Period(Minimum) -> 5 mins
* Validity Period(Maximum) -> 635040 mins(i.e.63 weeks).
* Any Other values included Negative considered as Invalid Validity Period of the message.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
public void sendMultipartText(String destAddr, String scAddr, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg, boolean persistMessage, int priority, boolean expectMore, int validityPeriod, long messageId) {
final String fullMessageText = getMultipartMessageText(parts);
int refNumber = getNextConcatenatedRef() & 0x00FF;
int encoding = SmsConstants.ENCODING_UNKNOWN;
int msgCount = parts.size();
if (msgCount < 1) {
triggerSentIntentForFailure(sentIntents);
return;
}
TextEncodingDetails[] encodingForParts = new TextEncodingDetails[msgCount];
for (int i = 0; i < msgCount; i++) {
TextEncodingDetails details = calculateLength(parts.get(i), false);
if (encoding != details.codeUnitSize && (encoding == SmsConstants.ENCODING_UNKNOWN || encoding == SmsConstants.ENCODING_7BIT)) {
encoding = details.codeUnitSize;
}
encodingForParts[i] = details;
}
SmsTracker[] trackers = new SmsTracker[msgCount];
// States to track at the message level (for all parts)
final AtomicInteger unsentPartCount = new AtomicInteger(msgCount);
final AtomicBoolean anyPartFailed = new AtomicBoolean(false);
for (int i = 0; i < msgCount; i++) {
SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
concatRef.refNumber = refNumber;
// 1-based sequence
concatRef.seqNumber = i + 1;
concatRef.msgCount = msgCount;
// TODO: We currently set this to true since our messaging app will never
// send more than 255 parts (it converts the message to MMS well before that).
// However, we should support 3rd party messaging apps that might need 16-bit
// references
// Note: It's not sufficient to just flip this bit to true; it will have
// ripple effects (several calculations assume 8-bit ref).
concatRef.isEightBits = true;
SmsHeader smsHeader = new SmsHeader();
smsHeader.concatRef = concatRef;
// Set the national language tables for 3GPP 7-bit encoding, if enabled.
if (encoding == SmsConstants.ENCODING_7BIT) {
smsHeader.languageTable = encodingForParts[i].languageTable;
smsHeader.languageShiftTable = encodingForParts[i].languageShiftTable;
}
PendingIntent sentIntent = null;
if (sentIntents != null && sentIntents.size() > i) {
sentIntent = sentIntents.get(i);
}
PendingIntent deliveryIntent = null;
if (deliveryIntents != null && deliveryIntents.size() > i) {
deliveryIntent = deliveryIntents.get(i);
}
trackers[i] = getNewSubmitPduTracker(callingPkg, destAddr, scAddr, parts.get(i), smsHeader, encoding, sentIntent, deliveryIntent, (i == (msgCount - 1)), unsentPartCount, anyPartFailed, messageUri, fullMessageText, priority, expectMore, validityPeriod, messageId);
if (trackers[i] == null) {
triggerSentIntentForFailure(sentIntents);
return;
}
trackers[i].mPersistMessage = persistMessage;
}
String carrierPackage = getCarrierAppPackageName();
if (carrierPackage != null) {
Rlog.d(TAG, "Found carrier package." + " id: " + getMultiTrackermessageId(trackers));
MultipartSmsSender smsSender = new MultipartSmsSender(parts, trackers);
smsSender.sendSmsByCarrierApp(carrierPackage, new MultipartSmsSenderCallback(smsSender));
} else {
Rlog.v(TAG, "No carrier package." + " id: " + getMultiTrackermessageId(trackers));
sendSubmitPdu(trackers);
}
}
use of com.android.internal.telephony.GsmAlphabet.TextEncodingDetails in project android_frameworks_opt_telephony by LineageOS.
the class CdmaSmsTest method testFragmentText.
@SmallTest
public void testFragmentText() throws Exception {
boolean isCdmaPhone = (TelephonyManager.getDefault().getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA);
// Valid 160 character ASCII text.
String text1 = "123456789012345678901234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890123456789012345678901234567890" + "12345678901234567890123456789[";
TextEncodingDetails ted = SmsMessage.calculateLength(text1, false, true);
assertEquals(ted.msgCount, 1);
assertEquals(ted.codeUnitCount, 160);
assertEquals(ted.codeUnitSize, 1);
if (isCdmaPhone) {
ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text1);
assertEquals(fragments.size(), 1);
}
/*
This is not a valid test: we will never encode a single-segment
EMS message. Leaving this here, since we may try to support
this in the future.
// Valid 160 character GSM text -- the last character is
// non-ASCII, and so this will currently generate a singleton
// EMS message, which is not necessarily supported by Verizon.
String text2 = "123456789012345678901234567890123456789012345678901234567890" +
"1234567890123456789012345678901234567890123456789012345678901234567890" +
"12345678901234567890123456789\u00a3"; // Trailing pound-currency sign.
ted = SmsMessage.calculateLength(text2, false);
assertEquals(ted.msgCount, 1);
assertEquals(ted.codeUnitCount, 160);
assertEquals(ted.codeUnitSize, 1);
if (isCdmaPhone) {
ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text2);
assertEquals(fragments.size(), 1);
}
*/
// *IF* we supported single-segment EMS, this text would result in a
// single fragment with 7-bit encoding. But we don't, so this text
// results in three fragments of 16-bit encoding.
String text2 = "123456789012345678901234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890123456789012345678901234567890" + // Trailing pound-currency sign.
"12345678901234567890123456789\u00a3";
ted = SmsMessage.calculateLength(text2, false, true);
assertEquals(3, ted.msgCount);
assertEquals(160, ted.codeUnitCount);
assertEquals(3, ted.codeUnitSize);
if (isCdmaPhone) {
ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text2);
assertEquals(3, fragments.size());
for (int i = 0; i < 3; i++) {
SmsHeader header = getConcatUserDataHeader(i + 1, 3);
SmsHeader header2 = getOddLengthUserDataHeader();
encodeDecodeAssertEquals(fragments.get(i), header, -1);
encodeDecodeAssertEquals(fragments.get(i), header2, -1);
}
}
// Test case for multi-part UTF-16 message.
String text3 = sUnicodeChars + sUnicodeChars + sUnicodeChars;
ted = SmsMessage.calculateLength(text3, false, true);
assertEquals(3, ted.msgCount);
assertEquals(189, ted.codeUnitCount);
assertEquals(3, ted.codeUnitSize);
if (isCdmaPhone) {
ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text3);
assertEquals(3, fragments.size());
for (int i = 0; i < 3; i++) {
SmsHeader header = getConcatUserDataHeader(i + 1, 3);
SmsHeader header2 = getOddLengthUserDataHeader();
encodeDecodeAssertEquals(fragments.get(i), header, -1);
encodeDecodeAssertEquals(fragments.get(i), header2, -1);
}
}
}
use of com.android.internal.telephony.GsmAlphabet.TextEncodingDetails in project android_frameworks_opt_telephony by LineageOS.
the class SMSDispatcher method sendMultipartText.
/**
* Send a multi-part text based SMS.
* @param destAddr the address to send the message to
* @param scAddr is the service center address or null to use
* the current default SMSC
* @param parts an <code>ArrayList</code> of strings that, in order,
* comprise the original message
* @param sentIntents if not null, an <code>ArrayList</code> of
* <code>PendingIntent</code>s (one for each message part) that is
* broadcast when the corresponding message part has been sent.
* The result code will be <code>Activity.RESULT_OK<code> for success,
* or one of these errors:
* <code>RESULT_ERROR_GENERIC_FAILURE</code>
* <code>RESULT_ERROR_RADIO_OFF</code>
* <code>RESULT_ERROR_NULL_PDU</code>
* <code>RESULT_ERROR_NO_SERVICE</code>.
* The per-application based SMS control checks sentIntent. If sentIntent
* is NULL the caller will be checked against all unknown applications,
* which cause smaller number of SMS to be sent in checking period.
* @param deliveryIntents if not null, an <code>ArrayList</code> of
* <code>PendingIntent</code>s (one for each message part) that is
* broadcast when the corresponding message part has been delivered
* to the recipient. The raw pdu of the status report is in the
* @param messageUri optional URI of the message if it is already stored in the system
* @param callingPkg the calling package name
* @param persistMessage whether to save the sent message into SMS DB for a
* non-default SMS app.
*/
protected void sendMultipartText(String destAddr, String scAddr, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg, boolean persistMessage) {
final String fullMessageText = getMultipartMessageText(parts);
int refNumber = getNextConcatenatedRef() & 0x00FF;
int msgCount = parts.size();
int encoding = SmsConstants.ENCODING_UNKNOWN;
TextEncodingDetails[] encodingForParts = new TextEncodingDetails[msgCount];
for (int i = 0; i < msgCount; i++) {
TextEncodingDetails details = calculateLength(parts.get(i), false);
if (encoding != details.codeUnitSize && (encoding == SmsConstants.ENCODING_UNKNOWN || encoding == SmsConstants.ENCODING_7BIT)) {
encoding = details.codeUnitSize;
}
encodingForParts[i] = details;
}
SmsTracker[] trackers = new SmsTracker[msgCount];
// States to track at the message level (for all parts)
final AtomicInteger unsentPartCount = new AtomicInteger(msgCount);
final AtomicBoolean anyPartFailed = new AtomicBoolean(false);
for (int i = 0; i < msgCount; i++) {
SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
concatRef.refNumber = refNumber;
// 1-based sequence
concatRef.seqNumber = i + 1;
concatRef.msgCount = msgCount;
// TODO: We currently set this to true since our messaging app will never
// send more than 255 parts (it converts the message to MMS well before that).
// However, we should support 3rd party messaging apps that might need 16-bit
// references
// Note: It's not sufficient to just flip this bit to true; it will have
// ripple effects (several calculations assume 8-bit ref).
concatRef.isEightBits = true;
SmsHeader smsHeader = new SmsHeader();
smsHeader.concatRef = concatRef;
// Set the national language tables for 3GPP 7-bit encoding, if enabled.
if (encoding == SmsConstants.ENCODING_7BIT) {
smsHeader.languageTable = encodingForParts[i].languageTable;
smsHeader.languageShiftTable = encodingForParts[i].languageShiftTable;
}
PendingIntent sentIntent = null;
if (sentIntents != null && sentIntents.size() > i) {
sentIntent = sentIntents.get(i);
}
PendingIntent deliveryIntent = null;
if (deliveryIntents != null && deliveryIntents.size() > i) {
deliveryIntent = deliveryIntents.get(i);
}
trackers[i] = getNewSubmitPduTracker(destAddr, scAddr, parts.get(i), smsHeader, encoding, sentIntent, deliveryIntent, (i == (msgCount - 1)), unsentPartCount, anyPartFailed, messageUri, fullMessageText);
trackers[i].mPersistMessage = persistMessage;
}
if (parts == null || trackers == null || trackers.length == 0 || trackers[0] == null) {
Rlog.e(TAG, "Cannot send multipart text. parts=" + parts + " trackers=" + trackers);
return;
}
String carrierPackage = getCarrierAppPackageName();
if (carrierPackage != null) {
Rlog.d(TAG, "Found carrier package.");
MultipartSmsSender smsSender = new MultipartSmsSender(parts, trackers);
smsSender.sendSmsByCarrierApp(carrierPackage, new MultipartSmsSenderCallback(smsSender));
} else {
Rlog.v(TAG, "No carrier package.");
for (SmsTracker tracker : trackers) {
if (tracker != null) {
sendSubmitPdu(tracker);
} else {
Rlog.e(TAG, "Null tracker.");
}
}
}
}
Aggregations