diff options
author | Jake Hamby <jhamby@google.com> | 2011-06-02 19:52:23 -0700 |
---|---|---|
committer | Jake Hamby <jhamby@google.com> | 2011-06-06 18:56:20 -0700 |
commit | 66040bbb087b04c4bbac8429f91bbff1029e1440 (patch) | |
tree | 81be72248bde2e89b3cf14e46b92161113567492 /telephony | |
parent | d6ce6791f26fd0a7cf89ded2847011a4894013e1 (diff) | |
download | frameworks_base-66040bbb087b04c4bbac8429f91bbff1029e1440.zip frameworks_base-66040bbb087b04c4bbac8429f91bbff1029e1440.tar.gz frameworks_base-66040bbb087b04c4bbac8429f91bbff1029e1440.tar.bz2 |
Fixes for SMS Cell Broadcast support.
Add support for ETWS primary notification messages.
Add method for easy concatenation of GSM multi-part broadcasts.
Add test cases for SmsCbHeader, SmsCbMessage and IntRangeManager.
Change-Id: Ifc646a011e79ad6c7eace9afcf84b1216eb42b7a
Diffstat (limited to 'telephony')
6 files changed, 1320 insertions, 72 deletions
diff --git a/telephony/java/android/telephony/SmsCbConstants.java b/telephony/java/android/telephony/SmsCbConstants.java index 1ac9ae3..a1b4adf 100644 --- a/telephony/java/android/telephony/SmsCbConstants.java +++ b/telephony/java/android/telephony/SmsCbConstants.java @@ -22,18 +22,6 @@ package android.telephony; * {@hide} */ public interface SmsCbConstants { - /** Cell wide immediate geographical scope */ - public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE = 0; - - /** PLMN wide geographical scope */ - public static final int GEOGRAPHICAL_SCOPE_PLMN_WIDE = 1; - - /** Location / service area wide geographical scope */ - public static final int GEOGRAPHICAL_SCOPE_LA_WIDE = 2; - - /** Cell wide geographical scope */ - public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE = 3; - /** Start of PWS Message Identifier range (includes ETWS and CMAS). */ public static final int MESSAGE_ID_PWS_FIRST_IDENTIFIER = 0x1100; @@ -111,4 +99,19 @@ public interface SmsCbConstants { /** ETWS message code flag to activate the emergency user alert. */ public static final int MESSAGE_CODE_ETWS_EMERGENCY_USER_ALERT = 0x200; + + /** ETWS warning type value for earthquake. */ + public static final int ETWS_WARNING_TYPE_EARTHQUAKE = 0x00; + + /** ETWS warning type value for tsunami. */ + public static final int ETWS_WARNING_TYPE_TSUNAMI = 0x01; + + /** ETWS warning type value for earthquake and tsunami. */ + public static final int ETWS_WARNING_TYPE_EARTHQUAKE_AND_TSUNAMI = 0x02; + + /** ETWS warning type value for test broadcast. */ + public static final int ETWS_WARNING_TYPE_TEST = 0x03; + + /** ETWS warning type value for other notifications. */ + public static final int ETWS_WARNING_TYPE_OTHER = 0x04; } diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java index 6da48d6..383e0f9 100644 --- a/telephony/java/android/telephony/SmsCbMessage.java +++ b/telephony/java/android/telephony/SmsCbMessage.java @@ -16,9 +16,11 @@ package android.telephony; +import android.text.format.Time; import android.util.Log; import com.android.internal.telephony.GsmAlphabet; +import com.android.internal.telephony.IccUtils; import com.android.internal.telephony.gsm.SmsCbHeader; import java.io.UnsupportedEncodingException; @@ -93,9 +95,26 @@ public class SmsCbMessage { private String mBody; + /** Timestamp of ETWS primary notification with security. */ + private long mPrimaryNotificationTimestamp; + + /** 43 byte digital signature of ETWS primary notification with security. */ + private byte[] mPrimaryNotificationDigitalSignature; + private SmsCbMessage(byte[] pdu) throws IllegalArgumentException { mHeader = new SmsCbHeader(pdu); - parseBody(pdu); + if (mHeader.format == SmsCbHeader.FORMAT_ETWS_PRIMARY) { + mBody = "ETWS"; + // ETWS primary notification with security is 56 octets in length + if (pdu.length >= SmsCbHeader.PDU_LENGTH_ETWS) { + mPrimaryNotificationTimestamp = getTimestampMillis(pdu); + mPrimaryNotificationDigitalSignature = new byte[43]; + // digital signature starts after 6 byte header and 7 byte timestamp + System.arraycopy(pdu, 13, mPrimaryNotificationDigitalSignature, 0, 43); + } + } else { + parseBody(pdu); + } } /** @@ -157,6 +176,55 @@ public class SmsCbMessage { } /** + * Get the format of this message. + * @return {@link SmsCbHeader#FORMAT_GSM}, {@link SmsCbHeader#FORMAT_UMTS}, or + * {@link SmsCbHeader#FORMAT_ETWS_PRIMARY} + */ + public int getMessageFormat() { + return mHeader.format; + } + + /** + * For ETWS primary notifications, return the emergency user alert flag. + * @return true to notify terminal to activate emergency user alert; false otherwise + */ + public boolean getEtwsEmergencyUserAlert() { + return mHeader.etwsEmergencyUserAlert; + } + + /** + * For ETWS primary notifications, return the popup flag. + * @return true to notify terminal to activate display popup; false otherwise + */ + public boolean getEtwsPopup() { + return mHeader.etwsPopup; + } + + /** + * For ETWS primary notifications, return the warning type. + * @return a value such as {@link SmsCbConstants#ETWS_WARNING_TYPE_EARTHQUAKE} + */ + public int getEtwsWarningType() { + return mHeader.etwsWarningType; + } + + /** + * For ETWS primary notifications, return the Warning-Security-Information timestamp. + * @return a timestamp in System.currentTimeMillis() format. + */ + public long getEtwsSecurityTimestamp() { + return mPrimaryNotificationTimestamp; + } + + /** + * For ETWS primary notifications, return the 43 byte digital signature. + * @return a byte array containing a copy of the digital signature + */ + public byte[] getEtwsSecuritySignature() { + return mPrimaryNotificationDigitalSignature.clone(); + } + + /** * Parse and unpack the body text according to the encoding in the DCS. * After completing successfully this method will have assigned the body * text into mBody, and optionally the language code into mLanguage @@ -334,6 +402,55 @@ public class SmsCbMessage { return body; } + /** + * Parses an ETWS primary notification timestamp and returns a currentTimeMillis()-style + * timestamp. Copied from com.android.internal.telephony.gsm.SmsMessage. + * @param pdu the ETWS primary notification PDU to decode + * @return the UTC timestamp from the Warning-Security-Information parameter + */ + private long getTimestampMillis(byte[] pdu) { + // Timestamp starts after CB header, in pdu[6] + int year = IccUtils.gsmBcdByteToInt(pdu[6]); + int month = IccUtils.gsmBcdByteToInt(pdu[7]); + int day = IccUtils.gsmBcdByteToInt(pdu[8]); + int hour = IccUtils.gsmBcdByteToInt(pdu[9]); + int minute = IccUtils.gsmBcdByteToInt(pdu[10]); + int second = IccUtils.gsmBcdByteToInt(pdu[11]); + + // For the timezone, the most significant bit of the + // least significant nibble is the sign byte + // (meaning the max range of this field is 79 quarter-hours, + // which is more than enough) + + byte tzByte = pdu[12]; + + // Mask out sign bit. + int timezoneOffset = IccUtils.gsmBcdByteToInt((byte) (tzByte & (~0x08))); + + timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset : -timezoneOffset; + + Time time = new Time(Time.TIMEZONE_UTC); + + // It's 2006. Should I really support years < 2000? + time.year = year >= 90 ? year + 1900 : year + 2000; + time.month = month - 1; + time.monthDay = day; + time.hour = hour; + time.minute = minute; + time.second = second; + + // Timezone offset is in quarter hours. + return time.toMillis(true) - (timezoneOffset * 15 * 60 * 1000); + } + + /** + * Append text to the message body. This is used to concatenate multi-page GSM broadcasts. + * @param body the text to append to this message + */ + public void appendToBody(String body) { + mBody = mBody + body; + } + @Override public String toString() { return "SmsCbMessage{" + mHeader.toString() + ", language=" + mLanguage + diff --git a/telephony/java/com/android/internal/telephony/IntRangeManager.java b/telephony/java/com/android/internal/telephony/IntRangeManager.java index 889e2b1..970bc44 100644 --- a/telephony/java/com/android/internal/telephony/IntRangeManager.java +++ b/telephony/java/com/android/internal/telephony/IntRangeManager.java @@ -290,54 +290,53 @@ public abstract class IntRangeManager { return true; } else { // find last range that can coalesce into the new combined range - for (int endIndex = startIndex+1; endIndex < len; endIndex++) { - IntRange endRange = mRanges.get(endIndex); - if ((endId + 1) < endRange.startId) { - // add range from range.endId+1 to endId, - // values from startId to range.endId are already enabled - if (tryAddSingleRange(range.endId + 1, endId, true)) { - range.endId = endId; - // insert new ClientRange in place - range.insert(new ClientRange(startId, endId, client)); - // coalesce range with following ranges up to endIndex-1 - // remove each range after adding its elements, so the index - // of the next range to join is always startIndex+1. - // i is the index if no elements were removed: we only care - // about the number of loop iterations, not the value of i. - int joinIndex = startIndex + 1; - for (int i = joinIndex; i < endIndex; i++) { - IntRange joinRange = mRanges.get(joinIndex); - range.clients.addAll(joinRange.clients); - mRanges.remove(joinRange); - } - return true; - } else { - return false; // failed to update radio - } - } else if (endId <= endRange.endId) { - // add range from range.endId+1 to start of last overlapping range, - // values from endRange.startId to endId are already enabled - if (tryAddSingleRange(range.endId + 1, endRange.startId - 1, true)) { - range.endId = endRange.endId; - // insert new ClientRange in place - range.insert(new ClientRange(startId, endId, client)); - // coalesce range with following ranges up to endIndex - // remove each range after adding its elements, so the index - // of the next range to join is always startIndex+1. - // i is the index if no elements were removed: we only care - // about the number of loop iterations, not the value of i. - int joinIndex = startIndex + 1; - for (int i = joinIndex; i <= endIndex; i++) { - IntRange joinRange = mRanges.get(joinIndex); - range.clients.addAll(joinRange.clients); - mRanges.remove(joinRange); - } - return true; - } else { - return false; // failed to update radio - } + int endIndex = startIndex; + for (int testIndex = startIndex+1; testIndex < len; testIndex++) { + IntRange testRange = mRanges.get(testIndex); + if ((endId + 1) < testRange.startId) { + break; + } else { + endIndex = testIndex; + } + } + // no adjacent IntRanges to combine + if (endIndex == startIndex) { + // add range from range.endId+1 to endId, + // values from startId to range.endId are already enabled + if (tryAddSingleRange(range.endId + 1, endId, true)) { + range.endId = endId; + range.insert(new ClientRange(startId, endId, client)); + return true; + } else { + return false; // failed to update radio } } + // get last range to coalesce into start range + IntRange endRange = mRanges.get(endIndex); + // Values from startId to range.endId have already been enabled. + // if endId > endRange.endId, then enable range from range.endId+1 to endId, + // else enable range from range.endId+1 to endRange.startId-1, because + // values from endRange.startId to endId have already been added. + int newRangeEndId = (endId <= endRange.endId) ? endRange.startId - 1 : endId; + if (tryAddSingleRange(range.endId + 1, newRangeEndId, true)) { + range.endId = endId; + // insert new ClientRange in place + range.insert(new ClientRange(startId, endId, client)); + // coalesce range with following ranges up to endIndex-1 + // remove each range after adding its elements, so the index + // of the next range to join is always startIndex+1 (joinIndex). + // i is the index if no elements had been removed: we only care + // about the number of loop iterations, not the value of i. + int joinIndex = startIndex + 1; + for (int i = joinIndex; i < endIndex; i++) { + IntRange joinRange = mRanges.get(joinIndex); + range.clients.addAll(joinRange.clients); + mRanges.remove(joinRange); + } + return true; + } else { + return false; // failed to update radio + } } } } @@ -435,6 +434,8 @@ public abstract class IntRangeManager { addRange(range.startId, nextStartId - 1, false); rangeCopy.startId = nextStartId; } + // init largestEndId + largestEndId = clients.get(1).endId; } // go through remaining ClientRanges, creating new IntRanges when @@ -442,7 +443,6 @@ public abstract class IntRangeManager { // remove the original IntRange and append newRanges to mRanges. // Otherwise, leave the original IntRange in mRanges and return false. ArrayList<IntRange> newRanges = new ArrayList<IntRange>(); - newRanges.add(rangeCopy); IntRange currentRange = rangeCopy; for (int nextIndex = crIndex + 1; nextIndex < crLength; nextIndex++) { @@ -454,6 +454,7 @@ public abstract class IntRangeManager { } addRange(largestEndId + 1, nextCr.startId - 1, false); currentRange.endId = largestEndId; + newRanges.add(currentRange); currentRange = new IntRange(nextCr); } else { currentRange.clients.add(nextCr); @@ -463,18 +464,25 @@ public abstract class IntRangeManager { } } - if (updateStarted) { - if (!finishUpdate()) { - return false; // failed to update radio - } else { - // remove the original IntRange and insert newRanges in place. - mRanges.remove(crIndex); - mRanges.addAll(crIndex, newRanges); - return true; + // remove any channels between largestEndId and endId + if (largestEndId < endId) { + if (!updateStarted) { + startUpdate(); + updateStarted = true; } - } else { - return true; + addRange(largestEndId + 1, endId, false); + currentRange.endId = largestEndId; + } + newRanges.add(currentRange); + + if (updateStarted && !finishUpdate()) { + return false; // failed to update radio } + + // replace the original IntRange with newRanges + mRanges.remove(i); + mRanges.addAll(i, newRanges); + return true; } else { // not the ClientRange to remove; save highest end ID seen so far if (cr.endId > largestEndId) { diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java index ea4d684..8e6b79b 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java @@ -35,6 +35,11 @@ public class SmsCbHeader implements SmsCbConstants { public static final int FORMAT_UMTS = 2; /** + * GSM pdu format, as defined in 3gpp TS 23.041, section 9.4.1.3 + */ + public static final int FORMAT_ETWS_PRIMARY = 3; + + /** * Message type value as defined in 3gpp TS 25.324, section 11.1. */ private static final int MESSAGE_TYPE_CBS_MESSAGE = 1; @@ -42,7 +47,12 @@ public class SmsCbHeader implements SmsCbConstants { /** * Length of GSM pdus */ - private static final int PDU_LENGTH_GSM = 88; + public static final int PDU_LENGTH_GSM = 88; + + /** + * Maximum length of ETWS primary message GSM pdus + */ + public static final int PDU_LENGTH_ETWS = 56; public final int geographicalScope; @@ -60,12 +70,30 @@ public class SmsCbHeader implements SmsCbConstants { public final int format; + public final boolean etwsEmergencyUserAlert; + + public final boolean etwsPopup; + + public final int etwsWarningType; + public SmsCbHeader(byte[] pdu) throws IllegalArgumentException { if (pdu == null || pdu.length < PDU_HEADER_LENGTH) { throw new IllegalArgumentException("Illegal PDU"); } - if (pdu.length <= PDU_LENGTH_GSM) { + if (pdu.length <= PDU_LENGTH_ETWS) { + format = FORMAT_ETWS_PRIMARY; + geographicalScope = -1; //not applicable + messageCode = -1; + updateNumber = -1; + messageIdentifier = ((pdu[2] & 0xff) << 8) | (pdu[3] & 0xff); + dataCodingScheme = -1; + pageIndex = -1; + nrOfPages = -1; + etwsEmergencyUserAlert = (pdu[4] & 0x1) != 0; + etwsPopup = (pdu[5] & 0x80) != 0; + etwsWarningType = (pdu[4] & 0xfe) >> 1; + } else if (pdu.length <= PDU_LENGTH_GSM) { // GSM pdus are no more than 88 bytes format = FORMAT_GSM; geographicalScope = (pdu[0] & 0xc0) >> 6; @@ -85,6 +113,9 @@ public class SmsCbHeader implements SmsCbConstants { this.pageIndex = pageIndex; this.nrOfPages = nrOfPages; + etwsEmergencyUserAlert = false; + etwsPopup = false; + etwsWarningType = -1; } else { // UMTS pdus are always at least 90 bytes since the payload includes // a number-of-pages octet and also one length octet per page @@ -107,6 +138,9 @@ public class SmsCbHeader implements SmsCbConstants { // actual payload may contain several pages. pageIndex = 1; nrOfPages = 1; + etwsEmergencyUserAlert = false; + etwsPopup = false; + etwsWarningType = -1; } } diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsCbTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsCbTest.java new file mode 100644 index 0000000..417aac4 --- /dev/null +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsCbTest.java @@ -0,0 +1,712 @@ +/* + * Copyright (C) 2010 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 com.android.internal.telephony; + +import android.telephony.SmsCbMessage; +import android.test.AndroidTestCase; +import android.util.Log; + +/** + * Test cases for basic SmsCbMessage operations + */ +public class GsmSmsCbTest extends AndroidTestCase { + + private void doTestGeographicalScopeValue(byte[] pdu, byte b, int expectedGs) { + pdu[0] = b; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected geographical scope decoded", expectedGs, msg + .getGeographicalScope()); + } + + public void testCreateNullPdu() { + SmsCbMessage msg = SmsCbMessage.createFromPdu(null); + + assertNull("createFromPdu(byte[] with null pdu should return null", msg); + } + + public void testCreateTooShortPdu() { + byte[] pdu = new byte[4]; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertNull("createFromPdu(byte[] with too short pdu should return null", msg); + } + + public void testGetGeographicalScope() { + byte[] pdu = { + (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x40, (byte)0x11, (byte)0x41, + (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6, + (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70, + (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, + (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, + (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9, + (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75, + (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69, + (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00 + }; + + doTestGeographicalScopeValue(pdu, (byte)0x00, + SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE); + doTestGeographicalScopeValue(pdu, (byte)0x40, SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE); + doTestGeographicalScopeValue(pdu, (byte)0x80, SmsCbMessage.GEOGRAPHICAL_SCOPE_LA_WIDE); + doTestGeographicalScopeValue(pdu, (byte)0xC0, SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE); + } + + public void testGetGeographicalScopeUmts() { + byte[] pdu = { + (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x40, + + (byte)0x01, + + (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, + (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, + (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C, + (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C, + (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A, + (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9, + (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, + (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, + (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, + (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, + (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, + (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, + (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00, + + (byte)0x34 + }; + + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected geographical scope decoded", + SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE, msg.getGeographicalScope()); + } + + public void testGetMessageBody7Bit() { + byte[] pdu = { + (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x40, (byte)0x11, (byte)0x41, + (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6, + (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70, + (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, + (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, + (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9, + (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75, + (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69, + (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00 + }; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected 7-bit string decoded", + "A GSM default alphabet message with carriage return padding", + msg.getMessageBody()); + } + + public void testGetMessageBody7BitUmts() { + byte[] pdu = { + (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x40, + + (byte)0x01, + + (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, + (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, + (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C, + (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C, + (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A, + (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9, + (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, + (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, + (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, + (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, + (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, + (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, + (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00, + + (byte)0x34 + }; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected 7-bit string decoded", + "A GSM default alphabet message with carriage return padding", + msg.getMessageBody()); + } + + public void testGetMessageBody7BitMultipageUmts() { + byte[] pdu = { + (byte)0x01, (byte)0x00, (byte)0x01, (byte)0xC0, (byte)0x00, (byte)0x40, + + (byte)0x02, + + (byte)0xC6, (byte)0xB4, (byte)0x7C, (byte)0x4E, (byte)0x07, (byte)0xC1, + (byte)0xC3, (byte)0xE7, (byte)0xF2, (byte)0xAA, (byte)0xD1, (byte)0x68, + (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, + (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, + (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, + (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, + (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, + (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, + (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, + (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, + (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, + (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00, + + (byte)0x0A, + + (byte)0xD3, (byte)0xF2, (byte)0xF8, (byte)0xED, (byte)0x26, (byte)0x83, + (byte)0xE0, (byte)0xE1, (byte)0x73, (byte)0xB9, (byte)0xD1, (byte)0x68, + (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, + (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, + (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, + (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, + (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, + (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, + (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, + (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, + (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, + (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00, + + (byte)0x0A + }; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected multipage 7-bit string decoded", + "First page+Second page", + msg.getMessageBody()); + } + + public void testGetMessageBody7BitFull() { + byte[] pdu = { + (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x40, (byte)0x11, (byte)0x41, + (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6, + (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70, + (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, + (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xC4, (byte)0xE5, + (byte)0xB4, (byte)0xFB, (byte)0x0C, (byte)0x2A, (byte)0xE3, (byte)0xC3, (byte)0x63, + (byte)0x3A, (byte)0x3B, (byte)0x0F, (byte)0xCA, (byte)0xCD, (byte)0x40, (byte)0x63, + (byte)0x74, (byte)0x58, (byte)0x1E, (byte)0x1E, (byte)0xD3, (byte)0xCB, (byte)0xF2, + (byte)0x39, (byte)0x88, (byte)0xFD, (byte)0x76, (byte)0x9F, (byte)0x59, (byte)0xA0, + (byte)0x76, (byte)0x39, (byte)0xEC, (byte)0x4E, (byte)0xBB, (byte)0xCF, (byte)0x20, + (byte)0x3A, (byte)0xBA, (byte)0x2C, (byte)0x2F, (byte)0x83, (byte)0xD2, (byte)0x73, + (byte)0x90, (byte)0xFB, (byte)0x0D, (byte)0x82, (byte)0x87, (byte)0xC9, (byte)0xE4, + (byte)0xB4, (byte)0xFB, (byte)0x1C, (byte)0x02 + }; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals( + "Unexpected 7-bit string decoded", + "A GSM default alphabet message being exactly 93 characters long, " + + "meaning there is no padding!", + msg.getMessageBody()); + } + + public void testGetMessageBody7BitFullUmts() { + byte[] pdu = { + (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x40, + + (byte)0x01, + + (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, + (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, + (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C, + (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C, + (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xC4, (byte)0xE5, (byte)0xB4, + (byte)0xFB, (byte)0x0C, (byte)0x2A, (byte)0xE3, (byte)0xC3, (byte)0x63, + (byte)0x3A, (byte)0x3B, (byte)0x0F, (byte)0xCA, (byte)0xCD, (byte)0x40, + (byte)0x63, (byte)0x74, (byte)0x58, (byte)0x1E, (byte)0x1E, (byte)0xD3, + (byte)0xCB, (byte)0xF2, (byte)0x39, (byte)0x88, (byte)0xFD, (byte)0x76, + (byte)0x9F, (byte)0x59, (byte)0xA0, (byte)0x76, (byte)0x39, (byte)0xEC, + (byte)0x4E, (byte)0xBB, (byte)0xCF, (byte)0x20, (byte)0x3A, (byte)0xBA, + (byte)0x2C, (byte)0x2F, (byte)0x83, (byte)0xD2, (byte)0x73, (byte)0x90, + (byte)0xFB, (byte)0x0D, (byte)0x82, (byte)0x87, (byte)0xC9, (byte)0xE4, + (byte)0xB4, (byte)0xFB, (byte)0x1C, (byte)0x02, + + (byte)0x52 + }; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals( + "Unexpected 7-bit string decoded", + "A GSM default alphabet message being exactly 93 characters long, " + + "meaning there is no padding!", + msg.getMessageBody()); + } + + public void testGetMessageBody7BitWithLanguage() { + byte[] pdu = { + (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x04, (byte)0x11, (byte)0x41, + (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6, + (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70, + (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, + (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, + (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9, + (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75, + (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69, + (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00 + }; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected 7-bit string decoded", + "A GSM default alphabet message with carriage return padding", + msg.getMessageBody()); + + assertEquals("Unexpected language indicator decoded", "es", msg.getLanguageCode()); + } + + public void testGetMessageBody7BitWithLanguageInBody() { + byte[] pdu = { + (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x10, (byte)0x11, (byte)0x73, + (byte)0x7B, (byte)0x23, (byte)0x08, (byte)0x3A, (byte)0x4E, (byte)0x9B, (byte)0x20, + (byte)0x72, (byte)0xD9, (byte)0x1C, (byte)0xAE, (byte)0xB3, (byte)0xE9, (byte)0xA0, + (byte)0x30, (byte)0x1B, (byte)0x8E, (byte)0x0E, (byte)0x8B, (byte)0xCB, (byte)0x74, + (byte)0x50, (byte)0xBB, (byte)0x3C, (byte)0x9F, (byte)0x87, (byte)0xCF, (byte)0x65, + (byte)0xD0, (byte)0x3D, (byte)0x4D, (byte)0x47, (byte)0x83, (byte)0xC6, (byte)0x61, + (byte)0xB9, (byte)0x3C, (byte)0x1D, (byte)0x3E, (byte)0x97, (byte)0x41, (byte)0xF2, + (byte)0x32, (byte)0xBD, (byte)0x2E, (byte)0x77, (byte)0x83, (byte)0xE0, (byte)0x61, + (byte)0x32, (byte)0x39, (byte)0xED, (byte)0x3E, (byte)0x37, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00 + }; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected 7-bit string decoded", + "A GSM default alphabet message with carriage return padding", + msg.getMessageBody()); + + assertEquals("Unexpected language indicator decoded", "sv", msg.getLanguageCode()); + } + + public void testGetMessageBody7BitWithLanguageInBodyUmts() { + byte[] pdu = { + (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x10, + + (byte)0x01, + + (byte)0x73, (byte)0x7B, (byte)0x23, (byte)0x08, (byte)0x3A, (byte)0x4E, + (byte)0x9B, (byte)0x20, (byte)0x72, (byte)0xD9, (byte)0x1C, (byte)0xAE, + (byte)0xB3, (byte)0xE9, (byte)0xA0, (byte)0x30, (byte)0x1B, (byte)0x8E, + (byte)0x0E, (byte)0x8B, (byte)0xCB, (byte)0x74, (byte)0x50, (byte)0xBB, + (byte)0x3C, (byte)0x9F, (byte)0x87, (byte)0xCF, (byte)0x65, (byte)0xD0, + (byte)0x3D, (byte)0x4D, (byte)0x47, (byte)0x83, (byte)0xC6, (byte)0x61, + (byte)0xB9, (byte)0x3C, (byte)0x1D, (byte)0x3E, (byte)0x97, (byte)0x41, + (byte)0xF2, (byte)0x32, (byte)0xBD, (byte)0x2E, (byte)0x77, (byte)0x83, + (byte)0xE0, (byte)0x61, (byte)0x32, (byte)0x39, (byte)0xED, (byte)0x3E, + (byte)0x37, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, + (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, + (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, + (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00, + + (byte)0x37 + }; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected 7-bit string decoded", + "A GSM default alphabet message with carriage return padding", + msg.getMessageBody()); + + assertEquals("Unexpected language indicator decoded", "sv", msg.getLanguageCode()); + } + + public void testGetMessageBody8Bit() { + byte[] pdu = { + (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x44, (byte)0x11, (byte)0x41, + (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41, + (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41, + (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41, + (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41, + (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41, + (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41, + (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41, + (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41, + (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41, + (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41, + (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41, + (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45 + }; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("8-bit message body should be empty", "", msg.getMessageBody()); + } + + public void testGetMessageBodyUcs2() { + byte[] pdu = { + (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x48, (byte)0x11, (byte)0x00, + (byte)0x41, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x55, (byte)0x00, (byte)0x43, + (byte)0x00, (byte)0x53, (byte)0x00, (byte)0x32, (byte)0x00, (byte)0x20, (byte)0x00, + (byte)0x6D, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x73, + (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x65, (byte)0x00, + (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x6F, (byte)0x00, (byte)0x6E, + (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x69, (byte)0x00, + (byte)0x6E, (byte)0x00, (byte)0x69, (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x67, + (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x20, (byte)0x04, + (byte)0x34, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x68, + (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x61, (byte)0x00, + (byte)0x63, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x72, + (byte)0x00, (byte)0x0D, (byte)0x00, (byte)0x0D + }; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected 7-bit string decoded", + "A UCS2 message containing a \u0434 character", msg.getMessageBody()); + } + + public void testGetMessageBodyUcs2Umts() { + byte[] pdu = { + (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x48, + + (byte)0x01, + + (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x55, + (byte)0x00, (byte)0x43, (byte)0x00, (byte)0x53, (byte)0x00, (byte)0x32, + (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x6D, (byte)0x00, (byte)0x65, + (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x61, + (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x20, + (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x6F, (byte)0x00, (byte)0x6E, + (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x69, + (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x69, (byte)0x00, (byte)0x6E, + (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x61, + (byte)0x00, (byte)0x20, (byte)0x04, (byte)0x34, (byte)0x00, (byte)0x20, + (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x68, (byte)0x00, (byte)0x61, + (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x63, + (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x72, + (byte)0x00, (byte)0x0D, (byte)0x00, (byte)0x0D, + + (byte)0x4E + }; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected 7-bit string decoded", + "A UCS2 message containing a \u0434 character", msg.getMessageBody()); + } + + public void testGetMessageBodyUcs2MultipageUmts() { + byte[] pdu = { + (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x48, + + (byte)0x02, + + (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x41, + (byte)0x00, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + + (byte)0x06, + + (byte)0x00, (byte)0x42, (byte)0x00, (byte)0x42, (byte)0x00, (byte)0x42, + (byte)0x00, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, + + (byte)0x06 + }; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected multipage UCS2 string decoded", + "AAABBB", msg.getMessageBody()); + } + + public void testGetMessageBodyUcs2WithLanguageInBody() { + byte[] pdu = { + (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x11, (byte)0x11, (byte)0x78, + (byte)0x3C, (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x55, + (byte)0x00, (byte)0x43, (byte)0x00, (byte)0x53, (byte)0x00, (byte)0x32, (byte)0x00, + (byte)0x20, (byte)0x00, (byte)0x6D, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x73, + (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x67, (byte)0x00, + (byte)0x65, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x6F, + (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x61, (byte)0x00, + (byte)0x69, (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x69, (byte)0x00, (byte)0x6E, + (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x61, (byte)0x00, + (byte)0x20, (byte)0x04, (byte)0x34, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63, + (byte)0x00, (byte)0x68, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x72, (byte)0x00, + (byte)0x61, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x65, + (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x0D + }; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected 7-bit string decoded", + "A UCS2 message containing a \u0434 character", msg.getMessageBody()); + + assertEquals("Unexpected language indicator decoded", "xx", msg.getLanguageCode()); + } + + public void testGetMessageBodyUcs2WithLanguageInBodyUmts() { + byte[] pdu = { + (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x11, + + (byte)0x01, + + (byte)0x78, (byte)0x3C, (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x20, + (byte)0x00, (byte)0x55, (byte)0x00, (byte)0x43, (byte)0x00, (byte)0x53, + (byte)0x00, (byte)0x32, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x6D, + (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x73, + (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x65, + (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x6F, + (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x61, + (byte)0x00, (byte)0x69, (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x69, + (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x20, + (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x20, (byte)0x04, (byte)0x34, + (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x68, + (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x61, + (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x65, + (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x0D, + + (byte)0x50 + }; + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected 7-bit string decoded", + "A UCS2 message containing a \u0434 character", msg.getMessageBody()); + + assertEquals("Unexpected language indicator decoded", "xx", msg.getLanguageCode()); + } + + public void testGetMessageIdentifier() { + byte[] pdu = { + (byte)0xC0, (byte)0x00, (byte)0x30, (byte)0x39, (byte)0x40, (byte)0x11, (byte)0x41, + (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6, + (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70, + (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, + (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, + (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9, + (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75, + (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69, + (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00 + }; + + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected message identifier decoded", 12345, msg.getMessageIdentifier()); + } + + public void testGetMessageIdentifierUmts() { + byte[] pdu = { + (byte)0x01, (byte)0x30, (byte)0x39, (byte)0x2A, (byte)0xA5, (byte)0x40, + + (byte)0x01, + + (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, + (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, + (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C, + (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C, + (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A, + (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9, + (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, + (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, + (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, + (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, + (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, + (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, + (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00, + + (byte)0x34 + }; + + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected message identifier decoded", 12345, msg.getMessageIdentifier()); + } + + public void testGetMessageCode() { + byte[] pdu = { + (byte)0x2A, (byte)0xA5, (byte)0x30, (byte)0x39, (byte)0x40, (byte)0x11, (byte)0x41, + (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6, + (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70, + (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, + (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, + (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9, + (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75, + (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69, + (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00 + }; + + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected message code decoded", 682, msg.getMessageCode()); + } + + public void testGetMessageCodeUmts() { + byte[] pdu = { + (byte)0x01, (byte)0x30, (byte)0x39, (byte)0x2A, (byte)0xA5, (byte)0x40, + + (byte)0x01, + + (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, + (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, + (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C, + (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C, + (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A, + (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9, + (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, + (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, + (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, + (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, + (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, + (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, + (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00, + + (byte)0x34 + }; + + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected message code decoded", 682, msg.getMessageCode()); + } + + public void testGetUpdateNumber() { + byte[] pdu = { + (byte)0x2A, (byte)0xA5, (byte)0x30, (byte)0x39, (byte)0x40, (byte)0x11, (byte)0x41, + (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6, + (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70, + (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, + (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, + (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9, + (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75, + (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69, + (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00 + }; + + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected update number decoded", 5, msg.getUpdateNumber()); + } + + public void testGetUpdateNumberUmts() { + byte[] pdu = { + (byte)0x01, (byte)0x30, (byte)0x39, (byte)0x2A, (byte)0xA5, (byte)0x40, + + (byte)0x01, + + (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, + (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, + (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C, + (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C, + (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A, + (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9, + (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, + (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, + (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, + (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, + (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, + (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, + (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, + (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00, + + (byte)0x34 + }; + + SmsCbMessage msg = SmsCbMessage.createFromPdu(pdu); + + assertEquals("Unexpected update number decoded", 5, msg.getUpdateNumber()); + } + + /* ETWS Test message including header */ + private static final byte[] etwsMessageNormal = IccUtils.hexStringToBytes("000011001101" + + "0D0A5BAE57CE770C531790E85C716CBF3044573065B930675730" + + "9707767A751F30025F37304463FA308C306B5099304830664E0B30553044FF086C178C615E81FF09" + + "0000000000000000000000000000"); + + private static final byte[] etwsMessageCancel = IccUtils.hexStringToBytes("000011001101" + + "0D0A5148307B3069002800310030003A0035" + + "00320029306E7DCA602557309707901F5831309253D66D883057307E3059FF086C178C615E81FF09" + + "00000000000000000000000000000000000000000000"); + + private static final byte[] etwsMessageTest = IccUtils.hexStringToBytes("000011031101" + + "0D0A5BAE57CE770C531790E85C716CBF3044" + + "573065B9306757309707300263FA308C306B5099304830664E0B30553044FF086C178C615E81FF09" + + "00000000000000000000000000000000000000000000"); + + // FIXME: add example of ETWS primary notification PDU + + public void testEtwsMessageNormal() { + SmsCbMessage msg = SmsCbMessage.createFromPdu(etwsMessageNormal); + Log.d("GsmSmsCbTest", msg.toString()); + assertEquals("GS mismatch", 0, msg.getGeographicalScope()); + assertEquals("message code mismatch", 0, msg.getMessageCode()); + assertEquals("update number mismatch", 0, msg.getUpdateNumber()); + assertEquals("message ID mismatch", 0x1100, msg.getMessageIdentifier()); + } + + public void testEtwsMessageCancel() { + SmsCbMessage msg = SmsCbMessage.createFromPdu(etwsMessageCancel); + Log.d("GsmSmsCbTest", msg.toString()); + assertEquals("GS mismatch", 0, msg.getGeographicalScope()); + assertEquals("message code mismatch", 0, msg.getMessageCode()); + assertEquals("update number mismatch", 0, msg.getUpdateNumber()); + assertEquals("message ID mismatch", 0x1100, msg.getMessageIdentifier()); + } + + public void testEtwsMessageTest() { + SmsCbMessage msg = SmsCbMessage.createFromPdu(etwsMessageTest); + Log.d("GsmSmsCbTest", msg.toString()); + assertEquals("GS mismatch", 0, msg.getGeographicalScope()); + assertEquals("message code mismatch", 0, msg.getMessageCode()); + assertEquals("update number mismatch", 0, msg.getUpdateNumber()); + assertEquals("message ID mismatch", 0x1103, msg.getMessageIdentifier()); + } +} diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java new file mode 100644 index 0000000..79dca39 --- /dev/null +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java @@ -0,0 +1,374 @@ +/* + * Copyright (C) 2011 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 com.android.internal.telephony; + +import android.test.AndroidTestCase; + +import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; + +import java.util.ArrayList; + +/** + * Test cases for the IntRangeManager class. + */ +public class IntRangeManagerTest extends AndroidTestCase { + + private static final int SMS_CB_CODE_SCHEME_MIN = 0; + private static final int SMS_CB_CODE_SCHEME_MAX = 255; + + private static final int FLAG_START_UPDATE_CALLED = 0x01; + private static final int FLAG_ADD_RANGE_CALLED = 0x02; + private static final int FLAG_FINISH_UPDATE_CALLED = 0x04; + + private static final int ALL_FLAGS_SET = FLAG_START_UPDATE_CALLED | FLAG_ADD_RANGE_CALLED | + FLAG_FINISH_UPDATE_CALLED; + + /** Dummy IntRangeManager for testing. */ + class TestIntRangeManager extends IntRangeManager { + ArrayList<SmsBroadcastConfigInfo> mConfigList = + new ArrayList<SmsBroadcastConfigInfo>(); + + int flags; + boolean finishUpdateReturnValue = true; + + /** + * Called when the list of enabled ranges has changed. This will be + * followed by zero or more calls to {@link #addRange} followed by + * a call to {@link #finishUpdate}. + */ + protected void startUpdate() { + mConfigList.clear(); + flags |= FLAG_START_UPDATE_CALLED; + } + + /** + * Called after {@link #startUpdate} to indicate a range of enabled + * values. + * @param startId the first id included in the range + * @param endId the last id included in the range + */ + protected void addRange(int startId, int endId, boolean selected) { + mConfigList.add(new SmsBroadcastConfigInfo(startId, endId, + SMS_CB_CODE_SCHEME_MIN, SMS_CB_CODE_SCHEME_MAX, selected)); + flags |= FLAG_ADD_RANGE_CALLED; + } + + /** + * Called to indicate the end of a range update started by the + * previous call to {@link #startUpdate}. + */ + protected boolean finishUpdate() { + flags |= FLAG_FINISH_UPDATE_CALLED; + return finishUpdateReturnValue; + } + + /** Reset the object for the next test case. */ + void reset() { + flags = 0; + mConfigList.clear(); + } + } + + public void testEmptyRangeManager() { + TestIntRangeManager testManager = new TestIntRangeManager(); + assertEquals("expecting empty configlist", 0, testManager.mConfigList.size()); + } + + private void checkConfigInfo(SmsBroadcastConfigInfo info, int fromServiceId, + int toServiceId, int fromCodeScheme, int toCodeScheme, boolean selected) { + assertEquals("fromServiceId", fromServiceId, info.getFromServiceId()); + assertEquals("toServiceId", toServiceId, info.getToServiceId()); + assertEquals("fromCodeScheme", fromCodeScheme, info.getFromCodeScheme()); + assertEquals("toCodeScheme", toCodeScheme, info.getToCodeScheme()); + assertEquals("selected", selected, info.isSelected()); + } + + public void testAddSingleChannel() { + TestIntRangeManager testManager = new TestIntRangeManager(); + assertEquals("flags before test", 0, testManager.flags); + assertTrue("enabling range", testManager.enableRange(123, 123, "client1")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 123, 123, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("updating ranges", testManager.updateRanges()); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 123, 123, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + } + + public void testRemoveSingleChannel() { + TestIntRangeManager testManager = new TestIntRangeManager(); + assertTrue("enabling range", testManager.enableRange(123, 123, "client1")); + assertEquals("flags after enable", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + testManager.reset(); + assertTrue("disabling range", testManager.disableRange(123, 123, "client1")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 123, 123, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, false); + testManager.reset(); + assertTrue("updating ranges", testManager.updateRanges()); + assertEquals("flags after test", FLAG_START_UPDATE_CALLED | FLAG_FINISH_UPDATE_CALLED, + testManager.flags); + assertEquals("configlist size", 0, testManager.mConfigList.size()); + } + + public void testRemoveBadChannel() { + TestIntRangeManager testManager = new TestIntRangeManager(); + assertFalse("disabling missing range", testManager.disableRange(123, 123, "client1")); + assertEquals("flags after test", 0, testManager.flags); + assertEquals("configlist size", 0, testManager.mConfigList.size()); + } + + public void testAddTwoChannels() { + TestIntRangeManager testManager = new TestIntRangeManager(); + assertEquals("flags before test", 0, testManager.flags); + assertTrue("enabling range 1", testManager.enableRange(100, 120, "client1")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 100, 120, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("enabling range 2", testManager.enableRange(200, 250, "client2")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 200, 250, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("updating ranges", testManager.updateRanges()); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 2, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 100, 120, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + checkConfigInfo(testManager.mConfigList.get(1), 200, 250, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + } + + public void testOverlappingChannels() { + TestIntRangeManager testManager = new TestIntRangeManager(); + assertEquals("flags before test", 0, testManager.flags); + assertTrue("enabling range 1", testManager.enableRange(100, 200, "client1")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 100, 200, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("enabling range 2", testManager.enableRange(150, 250, "client2")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 201, 250, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("updating ranges", testManager.updateRanges()); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 100, 250, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("disabling range 1", testManager.disableRange(100, 200, "client1")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 100, 149, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, false); + testManager.reset(); + assertTrue("disabling range 2", testManager.disableRange(150, 250, "client2")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 150, 250, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, false); + testManager.reset(); + assertTrue("updating ranges", testManager.updateRanges()); + assertEquals("flags after test", FLAG_START_UPDATE_CALLED | FLAG_FINISH_UPDATE_CALLED, + testManager.flags); + assertEquals("configlist size", 0, testManager.mConfigList.size()); + } + + public void testOverlappingChannels2() { + TestIntRangeManager testManager = new TestIntRangeManager(); + assertEquals("flags before test", 0, testManager.flags); + assertTrue("enabling range 1", testManager.enableRange(100, 200, "client1")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 100, 200, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("enabling range 2", testManager.enableRange(150, 250, "client2")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 201, 250, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("disabling range 2", testManager.disableRange(150, 250, "client2")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 201, 250, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, false); + testManager.reset(); + assertTrue("updating ranges", testManager.updateRanges()); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 100, 200, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("disabling range 1", testManager.disableRange(100, 200, "client1")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 100, 200, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, false); + } + + public void testMultipleOverlappingChannels() { + TestIntRangeManager testManager = new TestIntRangeManager(); + assertEquals("flags before test", 0, testManager.flags); + assertTrue("enabling range 1", testManager.enableRange(67, 9999, "client1")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 67, 9999, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("enabling range 2", testManager.enableRange(150, 250, "client2")); + assertEquals("flags after test", 0, testManager.flags); + assertEquals("configlist size", 0, testManager.mConfigList.size()); + testManager.reset(); + assertTrue("enabling range 3", testManager.enableRange(25, 75, "client3")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 25, 66, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("enabling range 4", testManager.enableRange(12, 500, "client4")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 12, 24, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("enabling range 5", testManager.enableRange(8000, 9998, "client5")); + assertEquals("flags after test", 0, testManager.flags); + assertEquals("configlist size", 0, testManager.mConfigList.size()); + testManager.reset(); + assertTrue("enabling range 6", testManager.enableRange(50000, 65535, "client6")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 50000, 65535, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("updating ranges", testManager.updateRanges()); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 2, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 12, 9999, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + checkConfigInfo(testManager.mConfigList.get(1), 50000, 65535, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("disabling range 1", testManager.disableRange(67, 9999, "client1")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 2, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 501, 7999, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, false); + checkConfigInfo(testManager.mConfigList.get(1), 9999, 9999, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, false); + testManager.reset(); + assertTrue("updating ranges", testManager.updateRanges()); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 3, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 12, 500, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + checkConfigInfo(testManager.mConfigList.get(1), 8000, 9998, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + checkConfigInfo(testManager.mConfigList.get(2), 50000, 65535, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("disabling range 4", testManager.disableRange(12, 500, "client4")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 3, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 12, 24, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, false); + checkConfigInfo(testManager.mConfigList.get(1), 76, 149, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, false); + checkConfigInfo(testManager.mConfigList.get(2), 251, 500, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, false); + testManager.reset(); + assertTrue("updating ranges", testManager.updateRanges()); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 4, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 25, 75, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + checkConfigInfo(testManager.mConfigList.get(1), 150, 250, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + checkConfigInfo(testManager.mConfigList.get(2), 8000, 9998, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + checkConfigInfo(testManager.mConfigList.get(3), 50000, 65535, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("disabling range 5", testManager.disableRange(8000, 9998, "client5")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 8000, 9998, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, false); + testManager.reset(); + assertTrue("updating ranges", testManager.updateRanges()); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 3, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 25, 75, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + checkConfigInfo(testManager.mConfigList.get(1), 150, 250, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + checkConfigInfo(testManager.mConfigList.get(2), 50000, 65535, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("disabling range 6", testManager.disableRange(50000, 65535, "client6")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 50000, 65535, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, false); + testManager.reset(); + assertTrue("updating ranges", testManager.updateRanges()); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 2, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 25, 75, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + checkConfigInfo(testManager.mConfigList.get(1), 150, 250, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("disabling range 2", testManager.disableRange(150, 250, "client2")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 150, 250, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, false); + testManager.reset(); + assertTrue("updating ranges", testManager.updateRanges()); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 25, 75, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, true); + testManager.reset(); + assertTrue("disabling range 3", testManager.disableRange(25, 75, "client3")); + assertEquals("flags after test", ALL_FLAGS_SET, testManager.flags); + assertEquals("configlist size", 1, testManager.mConfigList.size()); + checkConfigInfo(testManager.mConfigList.get(0), 25, 75, SMS_CB_CODE_SCHEME_MIN, + SMS_CB_CODE_SCHEME_MAX, false); + testManager.reset(); + assertTrue("updating ranges", testManager.updateRanges()); + assertEquals("flags after test", FLAG_START_UPDATE_CALLED | FLAG_FINISH_UPDATE_CALLED, + testManager.flags); + assertEquals("configlist size", 0, testManager.mConfigList.size()); + } +} |