10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/* 20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2008 The Android Open Source Project 30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License. 60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at 70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * http://www.apache.org/licenses/LICENSE-2.0 90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software 110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS, 120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and 140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License. 150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony.cdma.sms; 180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.res.Resources; 200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.SmsCbCmasInfo; 210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.cdma.CdmaSmsCbProgramData; 22b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hambyimport android.telephony.cdma.CdmaSmsCbProgramResults; 230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.text.format.Time; 24ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog; 250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.GsmAlphabet; 27e472090bda6d8c16975807e37b52e6bb558426bfCheuksan Wangimport com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; 280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.SmsConstants; 290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.SmsHeader; 30e472090bda6d8c16975807e37b52e6bb558426bfCheuksan Wangimport com.android.internal.telephony.SmsMessageBase; 31d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccUtils; 320825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.util.BitwiseInputStream; 330825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.util.BitwiseOutputStream; 340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 350825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList; 360825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.TimeZone; 370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/** 390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * An object to encode and decode CDMA SMS bearer data. 400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 410825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic final class BearerData { 42cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville private final static String LOG_TAG = "BearerData"; 430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Bearer Data Subparameter Identifiers 460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.S0015-B, v2.0, table 4.5-1) 470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * NOTE: Commented subparameter types are not implemented. 480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_MESSAGE_IDENTIFIER = 0x00; 500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_USER_DATA = 0x01; 510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_USER_RESPONSE_CODE = 0x02; 520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_MESSAGE_CENTER_TIME_STAMP = 0x03; 530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_VALIDITY_PERIOD_ABSOLUTE = 0x04; 540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_VALIDITY_PERIOD_RELATIVE = 0x05; 550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_DEFERRED_DELIVERY_TIME_ABSOLUTE = 0x06; 560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_DEFERRED_DELIVERY_TIME_RELATIVE = 0x07; 570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_PRIORITY_INDICATOR = 0x08; 580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_PRIVACY_INDICATOR = 0x09; 590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_REPLY_OPTION = 0x0A; 600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_NUMBER_OF_MESSAGES = 0x0B; 610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_ALERT_ON_MESSAGE_DELIVERY = 0x0C; 620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_LANGUAGE_INDICATOR = 0x0D; 630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_CALLBACK_NUMBER = 0x0E; 640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_MESSAGE_DISPLAY_MODE = 0x0F; 650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville //private final static byte SUBPARAM_MULTIPLE_ENCODING_USER_DATA = 0x10; 660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_MESSAGE_DEPOSIT_INDEX = 0x11; 670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA = 0x12; 680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS = 0x13; 690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final static byte SUBPARAM_MESSAGE_STATUS = 0x14; 700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville //private final static byte SUBPARAM_TP_FAILURE_CAUSE = 0x15; 710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville //private final static byte SUBPARAM_ENHANCED_VMN = 0x16; 720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville //private final static byte SUBPARAM_ENHANCED_VMN_ACK = 0x17; 730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 743de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks // All other values after this are reserved. 753de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks private final static byte SUBPARAM_ID_LAST_DEFINED = 0x17; 763de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks 770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Supported message types for CDMA SMS messages 790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.S0015-B, v2.0, table 4.5.1-1) 800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int MESSAGE_TYPE_DELIVER = 0x01; 820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int MESSAGE_TYPE_SUBMIT = 0x02; 830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int MESSAGE_TYPE_CANCELLATION = 0x03; 840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int MESSAGE_TYPE_DELIVERY_ACK = 0x04; 850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int MESSAGE_TYPE_USER_ACK = 0x05; 860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int MESSAGE_TYPE_READ_ACK = 0x06; 870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int MESSAGE_TYPE_DELIVER_REPORT = 0x07; 880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int MESSAGE_TYPE_SUBMIT_REPORT = 0x08; 890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int messageType; 910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 16-bit value indicating the message ID, which increments modulo 65536. 940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (Special rules apply for WAP-messages.) 950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.S0015-B, v2, 4.5.1) 960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int messageId; 980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Supported priority modes for CDMA SMS messages 1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1) 1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int PRIORITY_NORMAL = 0x0; 1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int PRIORITY_INTERACTIVE = 0x1; 1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int PRIORITY_URGENT = 0x2; 1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int PRIORITY_EMERGENCY = 0x3; 1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean priorityIndicatorSet = false; 1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int priority = PRIORITY_NORMAL; 1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Supported privacy modes for CDMA SMS messages 1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.S0015-B, v2.0, table 4.5.10-1) 1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int PRIVACY_NOT_RESTRICTED = 0x0; 1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int PRIVACY_RESTRICTED = 0x1; 1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int PRIVACY_CONFIDENTIAL = 0x2; 1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int PRIVACY_SECRET = 0x3; 1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean privacyIndicatorSet = false; 1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int privacy = PRIVACY_NOT_RESTRICTED; 1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Supported alert priority modes for CDMA SMS messages 1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.S0015-B, v2.0, table 4.5.13-1) 1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int ALERT_DEFAULT = 0x0; 1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int ALERT_LOW_PRIO = 0x1; 1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int ALERT_MEDIUM_PRIO = 0x2; 1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int ALERT_HIGH_PRIO = 0x3; 1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean alertIndicatorSet = false; 1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int alert = ALERT_DEFAULT; 1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Supported display modes for CDMA SMS messages. Display mode is 1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * a 2-bit value used to indicate to the mobile station when to 1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * display the received message. (See 3GPP2 C.S0015-B, v2, 1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 4.5.16) 1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int DISPLAY_MODE_IMMEDIATE = 0x0; 1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int DISPLAY_MODE_DEFAULT = 0x1; 1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int DISPLAY_MODE_USER = 0x2; 1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean displayModeSet = false; 1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int displayMode = DISPLAY_MODE_DEFAULT; 1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Language Indicator values. NOTE: the spec (3GPP2 C.S0015-B, 1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * v2, 4.5.14) is ambiguous as to the meaning of this field, as it 1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * refers to C.R1001-D but that reference has been crossed out. 1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * It would seem reasonable to assume the values from C.R1001-F 1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (table 9.2-1) are to be used instead. 1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int LANGUAGE_UNKNOWN = 0x00; 1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int LANGUAGE_ENGLISH = 0x01; 1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int LANGUAGE_FRENCH = 0x02; 1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int LANGUAGE_SPANISH = 0x03; 1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int LANGUAGE_JAPANESE = 0x04; 1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int LANGUAGE_KOREAN = 0x05; 1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int LANGUAGE_CHINESE = 0x06; 1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int LANGUAGE_HEBREW = 0x07; 1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean languageIndicatorSet = false; 1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int language = LANGUAGE_UNKNOWN; 1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * SMS Message Status Codes. The first component of the Message 1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * status indicates if an error has occurred and whether the error 1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is considered permanent or temporary. The second component of 1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the Message status indicates the cause of the error (if any). 1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.S0015-B, v2.0, 4.5.21) 1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* no-error codes */ 1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int ERROR_NONE = 0x00; 1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int STATUS_ACCEPTED = 0x00; 1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int STATUS_DEPOSITED_TO_INTERNET = 0x01; 1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int STATUS_DELIVERED = 0x02; 1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int STATUS_CANCELLED = 0x03; 1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* temporary-error and permanent-error codes */ 1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int ERROR_TEMPORARY = 0x02; 1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int STATUS_NETWORK_CONGESTION = 0x04; 1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int STATUS_NETWORK_ERROR = 0x05; 1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int STATUS_UNKNOWN_ERROR = 0x1F; 1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* permanent-error codes */ 1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int ERROR_PERMANENT = 0x03; 1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int STATUS_CANCEL_FAILED = 0x06; 1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int STATUS_BLOCKED_DESTINATION = 0x07; 1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int STATUS_TEXT_TOO_LONG = 0x08; 1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int STATUS_DUPLICATE_MESSAGE = 0x09; 1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int STATUS_INVALID_DESTINATION = 0x0A; 1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int STATUS_MESSAGE_EXPIRED = 0x0D; 1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* undefined-status codes */ 1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int ERROR_UNDEFINED = 0xFF; 1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int STATUS_UNDEFINED = 0xFF; 1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean messageStatusSet = false; 1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int errorClass = ERROR_UNDEFINED; 1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int messageStatus = STATUS_UNDEFINED; 2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 1-bit value that indicates whether a User Data Header (UDH) is present. 2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.S0015-B, v2, 4.5.1) 2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 2050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * NOTE: during encoding, this value will be set based on the 2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * presence of a UDH in the structured data, any existing setting 2070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * will be overwritten. 2080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean hasUserDataHeader; 2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * provides the information for the user data 2130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (e.g. padding bits, user data, user data header, etc) 2140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.S.0015-B, v2, 4.5.2) 2150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public UserData userData; 2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The User Response Code subparameter is used in the SMS User 2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Acknowledgment Message to respond to previously received short 2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * messages. This message center-specific element carries the 2220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * identifier of a predefined response. (See 3GPP2 C.S.0015-B, v2, 2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 4.5.3) 2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean userResponseCodeSet = false; 2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int userResponseCode; 2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 6-byte-field, see 3GPP2 C.S0015-B, v2, 4.5.4 2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static class TimeStamp extends Time { 2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public TimeStamp() { 2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville super(TimeZone.getDefault().getID()); // 3GPP2 timestamps use the local timezone 2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static TimeStamp fromByteArray(byte[] data) { 2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville TimeStamp ts = new TimeStamp(); 2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // C.S0015-B v2.0, 4.5.4: range is 1996-2095 2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int year = IccUtils.cdmaBcdByteToInt(data[0]); 2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (year > 99 || year < 0) return null; 2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ts.year = year >= 96 ? year + 1900 : year + 2000; 2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int month = IccUtils.cdmaBcdByteToInt(data[1]); 2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (month < 1 || month > 12) return null; 2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ts.month = month - 1; 2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int day = IccUtils.cdmaBcdByteToInt(data[2]); 2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (day < 1 || day > 31) return null; 2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ts.monthDay = day; 2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int hour = IccUtils.cdmaBcdByteToInt(data[3]); 2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (hour < 0 || hour > 23) return null; 2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ts.hour = hour; 2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int minute = IccUtils.cdmaBcdByteToInt(data[4]); 2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (minute < 0 || minute > 59) return null; 2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ts.minute = minute; 2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int second = IccUtils.cdmaBcdByteToInt(data[5]); 2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (second < 0 || second > 59) return null; 2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ts.second = second; 2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return ts; 2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public String toString() { 2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville StringBuilder builder = new StringBuilder(); 2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append("TimeStamp "); 2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append("{ year=" + year); 2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", month=" + month); 2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", day=" + monthDay); 2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", hour=" + hour); 2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", minute=" + minute); 2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", second=" + second); 2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(" }"); 2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return builder.toString(); 2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public TimeStamp msgCenterTimeStamp; 2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public TimeStamp validityPeriodAbsolute; 2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public TimeStamp deferredDeliveryTimeAbsolute; 2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Relative time is specified as one byte, the value of which 2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * falls into a series of ranges, as specified below. The idea is 2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * that shorter time intervals allow greater precision -- the 2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * value means minutes from zero until the MINS_LIMIT (inclusive), 2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * upon which it means hours until the HOURS_LIMIT, and so 2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * forth. (See 3GPP2 C.S0015-B, v2, 4.5.6-1) 2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int RELATIVE_TIME_MINS_LIMIT = 143; 2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int RELATIVE_TIME_HOURS_LIMIT = 167; 2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int RELATIVE_TIME_DAYS_LIMIT = 196; 2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int RELATIVE_TIME_WEEKS_LIMIT = 244; 2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int RELATIVE_TIME_INDEFINITE = 245; 2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int RELATIVE_TIME_NOW = 246; 2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int RELATIVE_TIME_MOBILE_INACTIVE = 247; 2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int RELATIVE_TIME_RESERVED = 248; 2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean validityPeriodRelativeSet; 2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int validityPeriodRelative; 2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean deferredDeliveryTimeRelativeSet; 3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int deferredDeliveryTimeRelative; 3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The Reply Option subparameter contains 1-bit values which 3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * indicate whether SMS acknowledgment is requested or not. (See 3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 3GPP2 C.S0015-B, v2, 4.5.11) 3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean userAckReq; 3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean deliveryAckReq; 3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean readAckReq; 3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public boolean reportReq; 3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The Number of Messages subparameter (8-bit value) is a decimal 3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * number in the 0 to 99 range representing the number of messages 3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * stored at the Voice Mail System. This element is used by the 3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Voice Mail Notification service. (See 3GPP2 C.S0015-B, v2, 3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 4.5.12) 3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int numberOfMessages; 3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 3220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The Message Deposit Index subparameter is assigned by the 3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * message center as a unique index to the contents of the User 3240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Data subparameter in each message sent to a particular mobile 3250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * station. The mobile station, when replying to a previously 3260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * received short message which included a Message Deposit Index 3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * subparameter, may include the Message Deposit Index of the 3280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * received message to indicate to the message center that the 3290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * original contents of the message are to be included in the 3300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * reply. (See 3GPP2 C.S0015-B, v2, 4.5.18) 3310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int depositIndex; 3330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 4-bit or 8-bit value that indicates the number to be dialed in reply to a 3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * received SMS message. 3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.S0015-B, v2, 4.5.15) 3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public CdmaSmsAddress callbackNumber; 3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * CMAS warning notification information. 3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @see #decodeCmasUserData(BearerData, int) 3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public SmsCbCmasInfo cmasWarningInfo; 3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The Service Category Program Data subparameter is used to enable and disable 3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * SMS broadcast service categories to display. If this subparameter is present, 3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * this field will contain a list of one or more 3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * {@link android.telephony.cdma.CdmaSmsCbProgramData} objects containing the 3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * operation(s) to perform. 3530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 354b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby public ArrayList<CdmaSmsCbProgramData> serviceCategoryProgramData; 355b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby 356b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby /** 357b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby * The Service Category Program Results subparameter informs the message center 358b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby * of the results of a Service Category Program Data request. 359b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby */ 360b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby public ArrayList<CdmaSmsCbProgramResults> serviceCategoryProgramResults; 361b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby 3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static class CodingException extends Exception { 3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public CodingException(String s) { 3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville super(s); 3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 3700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Returns the language indicator as a two-character ISO 639 string. 3710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return a two character ISO 639 language code 3720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public String getLanguage() { 3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return getLanguageCodeForValue(language); 3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 3780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Converts a CDMA language indicator value to an ISO 639 two character language code. 3790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param languageValue the CDMA language value to convert 3800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return the two character ISO 639 language code for the specified value, or null if unknown 3810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static String getLanguageCodeForValue(int languageValue) { 3830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (languageValue) { 3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case LANGUAGE_ENGLISH: 3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return "en"; 3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case LANGUAGE_FRENCH: 3880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return "fr"; 3890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case LANGUAGE_SPANISH: 3910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return "es"; 3920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case LANGUAGE_JAPANESE: 3940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return "ja"; 3950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case LANGUAGE_KOREAN: 3970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return "ko"; 3980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case LANGUAGE_CHINESE: 4000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return "zh"; 4010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case LANGUAGE_HEBREW: 4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return "he"; 4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville default: 4060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return null; 4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public String toString() { 4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville StringBuilder builder = new StringBuilder(); 4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append("BearerData "); 4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append("{ messageType=" + messageType); 415cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville builder.append(", messageId=" + messageId); 4160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", priority=" + (priorityIndicatorSet ? priority : "unset")); 4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", privacy=" + (privacyIndicatorSet ? privacy : "unset")); 4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", alert=" + (alertIndicatorSet ? alert : "unset")); 4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", displayMode=" + (displayModeSet ? displayMode : "unset")); 4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", language=" + (languageIndicatorSet ? language : "unset")); 4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", errorClass=" + (messageStatusSet ? errorClass : "unset")); 4220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", msgStatus=" + (messageStatusSet ? messageStatus : "unset")); 4230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", msgCenterTimeStamp=" + 4240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ((msgCenterTimeStamp != null) ? msgCenterTimeStamp : "unset")); 4250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", validityPeriodAbsolute=" + 4260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ((validityPeriodAbsolute != null) ? validityPeriodAbsolute : "unset")); 4270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", validityPeriodRelative=" + 4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ((validityPeriodRelativeSet) ? validityPeriodRelative : "unset")); 4290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", deferredDeliveryTimeAbsolute=" + 4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ((deferredDeliveryTimeAbsolute != null) ? deferredDeliveryTimeAbsolute : "unset")); 4310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", deferredDeliveryTimeRelative=" + 4320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ((deferredDeliveryTimeRelativeSet) ? deferredDeliveryTimeRelative : "unset")); 4330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", userAckReq=" + userAckReq); 4340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", deliveryAckReq=" + deliveryAckReq); 4350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", readAckReq=" + readAckReq); 4360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", reportReq=" + reportReq); 4370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", numberOfMessages=" + numberOfMessages); 4380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", callbackNumber=" + callbackNumber); 4390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", depositIndex=" + depositIndex); 4400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", hasUserDataHeader=" + hasUserDataHeader); 4410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(", userData=" + userData); 4420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville builder.append(" }"); 4430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return builder.toString(); 4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodeMessageId(BearerData bData, BitwiseOutputStream outStream) 4470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseOutputStream.AccessException 4480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 4490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, 3); 4500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(4, bData.messageType); 4510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, bData.messageId >> 8); 4520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, bData.messageId); 4530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(1, bData.hasUserDataHeader ? 1 : 0); 4540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.skip(3); 4550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static int countAsciiSeptets(CharSequence msg, boolean force) { 4580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int msgLen = msg.length(); 4590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (force) return msgLen; 4600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < msgLen; i++) { 4610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (UserData.charToAscii.get(msg.charAt(i), -1) == -1) { 4620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return -1; 4630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return msgLen; 4660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 4690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Calculate the message text encoding length, fragmentation, and other details. 4700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 4710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param msg message text 4720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param force7BitEncoding ignore (but still count) illegal characters if true 4733ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan * @param isEntireMsg indicates if this is entire msg or a segment in multipart msg 4740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return septet count, or -1 on failure 4750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 4760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static TextEncodingDetails calcTextEncodingDetails(CharSequence msg, 4773ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan boolean force7BitEncoding, boolean isEntireMsg) { 4780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville TextEncodingDetails ted; 4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int septets = countAsciiSeptets(msg, force7BitEncoding); 4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (septets != -1 && septets <= SmsConstants.MAX_USER_DATA_SEPTETS) { 4810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ted = new TextEncodingDetails(); 4820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ted.msgCount = 1; 4830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ted.codeUnitCount = septets; 4840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ted.codeUnitsRemaining = SmsConstants.MAX_USER_DATA_SEPTETS - septets; 4850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ted.codeUnitSize = SmsConstants.ENCODING_7BIT; 4860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 4870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ted = com.android.internal.telephony.gsm.SmsMessage.calculateLength( 4880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville msg, force7BitEncoding); 4893ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan if (ted.msgCount == 1 && ted.codeUnitSize == SmsConstants.ENCODING_7BIT && 4903ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan isEntireMsg) { 4910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // We don't support single-segment EMS, so calculate for 16-bit 4920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // TODO: Consider supporting single-segment EMS 493e472090bda6d8c16975807e37b52e6bb558426bfCheuksan Wang return SmsMessageBase.calcUnicodeEncodingDetails(msg); 4940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return ted; 4970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static byte[] encode7bitAscii(String msg, boolean force) 5000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException 5010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 5020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 5030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville BitwiseOutputStream outStream = new BitwiseOutputStream(msg.length()); 5040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int msgLen = msg.length(); 5050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < msgLen; i++) { 5060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int charCode = UserData.charToAscii.get(msg.charAt(i), -1); 5070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (charCode == -1) { 5080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (force) { 5090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(7, UserData.UNENCODABLE_7_BIT_CHAR); 5100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 5110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("cannot ASCII encode (" + msg.charAt(i) + ")"); 5120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 5140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(7, charCode); 5150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return outStream.toByteArray(); 5180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (BitwiseOutputStream.AccessException ex) { 5190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("7bit ASCII encode failed: " + ex); 5200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static byte[] encodeUtf16(String msg) 5240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException 5250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 5260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 5270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return msg.getBytes("utf-16be"); 5280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (java.io.UnsupportedEncodingException ex) { 5290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("UTF-16 encode failed: " + ex); 5300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static class Gsm7bitCodingResult { 5340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int septets; 5350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] data; 5360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static Gsm7bitCodingResult encode7bitGsm(String msg, int septetOffset, boolean force) 5390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException 5400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 5410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 5420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* 5430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * TODO(cleanup): It would be nice if GsmAlphabet provided 5440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * an option to produce just the data without prepending 5450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the septet count, as this function is really just a 5460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * wrapper to strip that off. Not to mention that the 5470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * septet count is generally known prior to invocation of 5480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the encoder. Note that it cannot be derived from the 5490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * resulting array length, since that cannot distinguish 5500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * if the last contains either 1 or 8 valid bits. 5510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 5520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * TODO(cleanup): The BitwiseXStreams could also be 5530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * extended with byte-wise reversed endianness read/write 5540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * routines to allow a corresponding implementation of 5550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * stringToGsm7BitPacked, and potentially directly support 5560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * access to the main bitwise stream from encode/decode. 5570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 5580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] fullData = GsmAlphabet.stringToGsm7BitPacked(msg, septetOffset, !force, 0, 0); 5590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Gsm7bitCodingResult result = new Gsm7bitCodingResult(); 5600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville result.data = new byte[fullData.length - 1]; 5610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville System.arraycopy(fullData, 1, result.data, 0, fullData.length - 1); 5620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville result.septets = fullData[0] & 0x00FF; 5630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return result; 5640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (com.android.internal.telephony.EncodeException ex) { 5650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("7bit GSM encode failed: " + ex); 5660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encode7bitEms(UserData uData, byte[] udhData, boolean force) 5700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException 5710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 5720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int udhBytes = udhData.length + 1; // Add length octet. 5730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int udhSeptets = ((udhBytes * 8) + 6) / 7; 5740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Gsm7bitCodingResult gcr = encode7bitGsm(uData.payloadStr, udhSeptets, force); 5750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET; 5760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.msgEncodingSet = true; 5770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.numFields = gcr.septets; 5780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.payload = gcr.data; 5790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.payload[0] = (byte)udhData.length; 5800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville System.arraycopy(udhData, 0, uData.payload, 1, udhData.length); 5810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encode16bitEms(UserData uData, byte[] udhData) 5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException 5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] payload = encodeUtf16(uData.payloadStr); 5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int udhBytes = udhData.length + 1; // Add length octet. 5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int udhCodeUnits = (udhBytes + 1) / 2; 5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int payloadCodeUnits = payload.length / 2; 5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.msgEncoding = UserData.ENCODING_UNICODE_16; 5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.msgEncodingSet = true; 5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.numFields = udhCodeUnits + payloadCodeUnits; 5930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.payload = new byte[uData.numFields * 2]; 5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.payload[0] = (byte)udhData.length; 5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville System.arraycopy(udhData, 0, uData.payload, 1, udhData.length); 596115632cc56f813bd21543f8532c763d7d2968046Jake Hamby System.arraycopy(payload, 0, uData.payload, udhBytes, payload.length); 5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodeEmsUserDataPayload(UserData uData) 6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException 6010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 6020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] headerData = SmsHeader.toByteArray(uData.userDataHeader); 6030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (uData.msgEncodingSet) { 6040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (uData.msgEncoding == UserData.ENCODING_GSM_7BIT_ALPHABET) { 6050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encode7bitEms(uData, headerData, true); 6060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (uData.msgEncoding == UserData.ENCODING_UNICODE_16) { 6070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encode16bitEms(uData, headerData); 6080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 6090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("unsupported EMS user data encoding (" + 6100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.msgEncoding + ")"); 6110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 6130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 6140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encode7bitEms(uData, headerData, false); 6150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CodingException ex) { 6160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encode16bitEms(uData, headerData); 6170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6213de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks private static byte[] encodeShiftJis(String msg) throws CodingException { 6223de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks try { 6233de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks return msg.getBytes("Shift_JIS"); 6243de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks } catch (java.io.UnsupportedEncodingException ex) { 6253de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks throw new CodingException("Shift-JIS encode failed: " + ex); 6263de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks } 6273de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks } 6283de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks 6290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodeUserDataPayload(UserData uData) 6300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException 6310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 6320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((uData.payloadStr == null) && (uData.msgEncoding != UserData.ENCODING_OCTET)) { 633ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "user data with null payloadStr"); 6340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.payloadStr = ""; 6350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (uData.userDataHeader != null) { 6380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodeEmsUserDataPayload(uData); 6390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 6400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (uData.msgEncodingSet) { 6430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (uData.msgEncoding == UserData.ENCODING_OCTET) { 6440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (uData.payload == null) { 645ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "user data with octet encoding but null payload"); 6460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.payload = new byte[0]; 6470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.numFields = 0; 6480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 6490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.numFields = uData.payload.length; 6500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 6520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (uData.payloadStr == null) { 653ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "non-octet user data with null payloadStr"); 6540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.payloadStr = ""; 6550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (uData.msgEncoding == UserData.ENCODING_GSM_7BIT_ALPHABET) { 6570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Gsm7bitCodingResult gcr = encode7bitGsm(uData.payloadStr, 0, true); 6580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.payload = gcr.data; 6590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.numFields = gcr.septets; 6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (uData.msgEncoding == UserData.ENCODING_7BIT_ASCII) { 6610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.payload = encode7bitAscii(uData.payloadStr, true); 6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.numFields = uData.payloadStr.length(); 6630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (uData.msgEncoding == UserData.ENCODING_UNICODE_16) { 6640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.payload = encodeUtf16(uData.payloadStr); 6650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.numFields = uData.payloadStr.length(); 6663de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks } else if (uData.msgEncoding == UserData.ENCODING_SHIFT_JIS) { 6673de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks uData.payload = encodeShiftJis(uData.payloadStr); 6683de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks uData.numFields = uData.payload.length; 6690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 6700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("unsupported user data encoding (" + 6710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.msgEncoding + ")"); 6720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 6750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 6760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.payload = encode7bitAscii(uData.payloadStr, false); 6770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.msgEncoding = UserData.ENCODING_7BIT_ASCII; 6780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CodingException ex) { 6790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.payload = encodeUtf16(uData.payloadStr); 6800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.msgEncoding = UserData.ENCODING_UNICODE_16; 6810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.numFields = uData.payloadStr.length(); 6830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville uData.msgEncodingSet = true; 6840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodeUserData(BearerData bData, BitwiseOutputStream outStream) 6880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseOutputStream.AccessException, CodingException 6890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 6900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* 6910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * TODO(cleanup): Do we really need to set userData.payload as 6920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * a side effect of encoding? If not, we could avoid data 6930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * copies by passing outStream directly. 6940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 6950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodeUserDataPayload(bData.userData); 6960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.hasUserDataHeader = bData.userData.userDataHeader != null; 6970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (bData.userData.payload.length > SmsConstants.MAX_USER_DATA_BYTES) { 6990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("encoded user data too large (" + 7000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userData.payload.length + 7010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " > " + SmsConstants.MAX_USER_DATA_BYTES + " bytes)"); 7020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* 7050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * TODO(cleanup): figure out what the right answer is WRT paddingBits field 7060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 7070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * userData.paddingBits = (userData.payload.length * 8) - (userData.numFields * 7); 7080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * userData.paddingBits = 0; // XXX this seems better, but why? 7090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 7100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 7110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int dataBits = (bData.userData.payload.length * 8) - bData.userData.paddingBits; 7120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = dataBits + 13; 7130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) || 7140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) { 7150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits += 8; 7160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBytes = (paramBits / 8) + ((paramBits % 8) > 0 ? 1 : 0); 7180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paddingBits = (paramBytes * 8) - paramBits; 7190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, paramBytes); 7200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(5, bData.userData.msgEncoding); 7210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) || 7220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) { 7230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, bData.userData.msgType); 7240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, bData.userData.numFields); 7260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.writeByteArray(dataBits, bData.userData.payload); 7270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paddingBits > 0) outStream.write(paddingBits, 0); 7280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodeReplyOption(BearerData bData, BitwiseOutputStream outStream) 7310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseOutputStream.AccessException 7320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 7330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, 1); 7340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(1, bData.userAckReq ? 1 : 0); 7350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(1, bData.deliveryAckReq ? 1 : 0); 7360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(1, bData.readAckReq ? 1 : 0); 7370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(1, bData.reportReq ? 1 : 0); 7380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(4, 0); 7390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static byte[] encodeDtmfSmsAddress(String address) { 7420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int digits = address.length(); 7430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int dataBits = digits * 4; 7440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int dataBytes = (dataBits / 8); 7450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dataBytes += (dataBits % 8) > 0 ? 1 : 0; 7460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] rawData = new byte[dataBytes]; 7470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < digits; i++) { 7480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville char c = address.charAt(i); 7490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int val = 0; 7500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((c >= '1') && (c <= '9')) val = c - '0'; 7510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville else if (c == '0') val = 10; 7520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville else if (c == '*') val = 11; 7530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville else if (c == '#') val = 12; 7540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville else return null; 7550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville rawData[i / 2] |= val << (4 - ((i % 2) * 4)); 7560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return rawData; 7580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* 7610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * TODO(cleanup): CdmaSmsAddress encoding should make use of 7620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * CdmaSmsAddress.parse provided that DTMF encoding is unified, 7630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * and the difference in 4-bit vs. 8-bit is resolved. 7640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 7650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodeCdmaSmsAddress(CdmaSmsAddress addr) throws CodingException { 7670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) { 7680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 7690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville addr.origBytes = addr.address.getBytes("US-ASCII"); 7700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (java.io.UnsupportedEncodingException ex) { 7710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("invalid SMS address, cannot convert to ASCII"); 7720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 7740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville addr.origBytes = encodeDtmfSmsAddress(addr.address); 7750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodeCallbackNumber(BearerData bData, BitwiseOutputStream outStream) 7790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseOutputStream.AccessException, CodingException 7800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 7810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville CdmaSmsAddress addr = bData.callbackNumber; 7820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodeCdmaSmsAddress(addr); 7830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = 9; 7840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int dataBits = 0; 7850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) { 7860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits += 7; 7870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dataBits = addr.numberOfDigits * 8; 7880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 7890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dataBits = addr.numberOfDigits * 4; 7900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits += dataBits; 7920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBytes = (paramBits / 8) + ((paramBits % 8) > 0 ? 1 : 0); 7930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paddingBits = (paramBytes * 8) - paramBits; 7940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, paramBytes); 7950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(1, addr.digitMode); 7960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) { 7970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(3, addr.ton); 7980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(4, addr.numberPlan); 7990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, addr.numberOfDigits); 8010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.writeByteArray(dataBits, addr.origBytes); 8020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paddingBits > 0) outStream.write(paddingBits, 0); 8030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodeMsgStatus(BearerData bData, BitwiseOutputStream outStream) 8060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseOutputStream.AccessException 8070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 8080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, 1); 8090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(2, bData.errorClass); 8100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(6, bData.messageStatus); 8110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodeMsgCount(BearerData bData, BitwiseOutputStream outStream) 8140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseOutputStream.AccessException 8150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 8160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, 1); 8170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, bData.numberOfMessages); 8180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodeValidityPeriodRel(BearerData bData, BitwiseOutputStream outStream) 8210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseOutputStream.AccessException 8220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 8230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, 1); 8240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, bData.validityPeriodRelative); 8250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodePrivacyIndicator(BearerData bData, BitwiseOutputStream outStream) 8280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseOutputStream.AccessException 8290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 8300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, 1); 8310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(2, bData.privacy); 8320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.skip(6); 8330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodeLanguageIndicator(BearerData bData, BitwiseOutputStream outStream) 8360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseOutputStream.AccessException 8370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 8380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, 1); 8390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, bData.language); 8400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodeDisplayMode(BearerData bData, BitwiseOutputStream outStream) 8430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseOutputStream.AccessException 8440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 8450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, 1); 8460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(2, bData.displayMode); 8470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.skip(6); 8480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodePriorityIndicator(BearerData bData, BitwiseOutputStream outStream) 8510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseOutputStream.AccessException 8520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 8530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, 1); 8540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(2, bData.priority); 8550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.skip(6); 8560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void encodeMsgDeliveryAlert(BearerData bData, BitwiseOutputStream outStream) 8590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseOutputStream.AccessException 8600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 8610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, 1); 8620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(2, bData.alert); 8630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.skip(6); 8640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 866b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby private static void encodeScpResults(BearerData bData, BitwiseOutputStream outStream) 867b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby throws BitwiseOutputStream.AccessException 868b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby { 869b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby ArrayList<CdmaSmsCbProgramResults> results = bData.serviceCategoryProgramResults; 870b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby outStream.write(8, (results.size() * 4)); // 4 octets per program result 871b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby for (CdmaSmsCbProgramResults result : results) { 872b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby int category = result.getCategory(); 873b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby outStream.write(8, category >> 8); 874b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby outStream.write(8, category); 875b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby outStream.write(8, result.getLanguage()); 876b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby outStream.write(4, result.getCategoryResult()); 877b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby outStream.skip(4); 878b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby } 879b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby } 880b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby 8810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 8820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Create serialized representation for BearerData object. 8830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details) 8840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 8850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param bData an instance of BearerData. 8860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 8870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return byte array of raw encoded SMS bearer data. 8880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static byte[] encode(BearerData bData) { 8900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.hasUserDataHeader = ((bData.userData != null) && 8910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (bData.userData.userDataHeader != null)); 8920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 8930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville BitwiseOutputStream outStream = new BitwiseOutputStream(200); 8940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, SUBPARAM_MESSAGE_IDENTIFIER); 8950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodeMessageId(bData, outStream); 8960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (bData.userData != null) { 8970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, SUBPARAM_USER_DATA); 8980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodeUserData(bData, outStream); 8990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (bData.callbackNumber != null) { 9010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, SUBPARAM_CALLBACK_NUMBER); 9020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodeCallbackNumber(bData, outStream); 9030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (bData.userAckReq || bData.deliveryAckReq || bData.readAckReq || bData.reportReq) { 9050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, SUBPARAM_REPLY_OPTION); 9060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodeReplyOption(bData, outStream); 9070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (bData.numberOfMessages != 0) { 9090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, SUBPARAM_NUMBER_OF_MESSAGES); 9100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodeMsgCount(bData, outStream); 9110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (bData.validityPeriodRelativeSet) { 9130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, SUBPARAM_VALIDITY_PERIOD_RELATIVE); 9140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodeValidityPeriodRel(bData, outStream); 9150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (bData.privacyIndicatorSet) { 9170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, SUBPARAM_PRIVACY_INDICATOR); 9180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodePrivacyIndicator(bData, outStream); 9190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (bData.languageIndicatorSet) { 9210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, SUBPARAM_LANGUAGE_INDICATOR); 9220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodeLanguageIndicator(bData, outStream); 9230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (bData.displayModeSet) { 9250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, SUBPARAM_MESSAGE_DISPLAY_MODE); 9260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodeDisplayMode(bData, outStream); 9270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (bData.priorityIndicatorSet) { 9290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, SUBPARAM_PRIORITY_INDICATOR); 9300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodePriorityIndicator(bData, outStream); 9310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (bData.alertIndicatorSet) { 9330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, SUBPARAM_ALERT_ON_MESSAGE_DELIVERY); 9340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodeMsgDeliveryAlert(bData, outStream); 9350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (bData.messageStatusSet) { 9370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville outStream.write(8, SUBPARAM_MESSAGE_STATUS); 9380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodeMsgStatus(bData, outStream); 9390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 940b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby if (bData.serviceCategoryProgramResults != null) { 941b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby outStream.write(8, SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS); 942b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby encodeScpResults(bData, outStream); 943b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby } 9440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return outStream.toByteArray(); 9450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (BitwiseOutputStream.AccessException ex) { 946ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "BearerData encode failed: " + ex); 9470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CodingException ex) { 948ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "BearerData encode failed: " + ex); 9490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return null; 9510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeMessageId(BearerData bData, BitwiseInputStream inStream) 954cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 9550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 3 * 8; 9560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 9570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 9580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 9590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 9600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 9610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.messageType = inStream.read(4); 9620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.messageId = inStream.read(8) << 8; 9630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.messageId |= inStream.read(8); 9640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.hasUserDataHeader = (inStream.read(1) == 1); 9650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(3); 9660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 968ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "MESSAGE_IDENTIFIER decode " + 9690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 9700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 9710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 9730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 9740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9763de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks private static boolean decodeReserved( 9773de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks BearerData bData, BitwiseInputStream inStream, int subparamId) 9783de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks throws BitwiseInputStream.AccessException, CodingException 9793de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks { 9803de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks boolean decodeSuccess = false; 9813de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks int subparamLen = inStream.read(8); // SUBPARAM_LEN 9823de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks int paramBits = subparamLen * 8; 9833de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks if (paramBits <= inStream.available()) { 9843de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks decodeSuccess = true; 9853de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks inStream.skip(paramBits); 9863de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks } 9873de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks Rlog.d(LOG_TAG, "RESERVED bearer data subparameter " + subparamId + " decode " 9883de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks + (decodeSuccess ? "succeeded" : "failed") + " (param bits = " + paramBits + ")"); 9893de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks if (!decodeSuccess) { 9903de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks throw new CodingException("RESERVED bearer data subparameter " + subparamId 9913de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks + " had invalid SUBPARAM_LEN " + subparamLen); 9923de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks } 9933de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks 9943de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks return decodeSuccess; 9953de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks } 9963de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks 9970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeUserData(BearerData bData, BitwiseInputStream inStream) 9980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseInputStream.AccessException 9990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 10000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 10010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userData = new UserData(); 10020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userData.msgEncoding = inStream.read(5); 10030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userData.msgEncodingSet = true; 10040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userData.msgType = 0; 10050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int consumedBits = 5; 10060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) || 10070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) { 10080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userData.msgType = inStream.read(8); 10090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville consumedBits += 8; 10100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userData.numFields = inStream.read(8); 10120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville consumedBits += 8; 10130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int dataBits = paramBits - consumedBits; 10140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userData.payload = inStream.readByteArray(dataBits); 10150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return true; 10160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static String decodeUtf8(byte[] data, int offset, int numFields) 10190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException 10200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 1021115632cc56f813bd21543f8532c763d7d2968046Jake Hamby return decodeCharset(data, offset, numFields, 1, "UTF-8"); 10220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static String decodeUtf16(byte[] data, int offset, int numFields) 10250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException 10260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 1027115632cc56f813bd21543f8532c763d7d2968046Jake Hamby // Subtract header and possible padding byte (at end) from num fields. 1028115632cc56f813bd21543f8532c763d7d2968046Jake Hamby int padding = offset % 2; 1029115632cc56f813bd21543f8532c763d7d2968046Jake Hamby numFields -= (offset + padding) / 2; 1030115632cc56f813bd21543f8532c763d7d2968046Jake Hamby return decodeCharset(data, offset, numFields, 2, "utf-16be"); 1031115632cc56f813bd21543f8532c763d7d2968046Jake Hamby } 1032115632cc56f813bd21543f8532c763d7d2968046Jake Hamby 1033115632cc56f813bd21543f8532c763d7d2968046Jake Hamby private static String decodeCharset(byte[] data, int offset, int numFields, int width, 1034115632cc56f813bd21543f8532c763d7d2968046Jake Hamby String charset) throws CodingException 1035115632cc56f813bd21543f8532c763d7d2968046Jake Hamby { 1036115632cc56f813bd21543f8532c763d7d2968046Jake Hamby if (numFields < 0 || (numFields * width + offset) > data.length) { 1037115632cc56f813bd21543f8532c763d7d2968046Jake Hamby // Try to decode the max number of characters in payload 1038115632cc56f813bd21543f8532c763d7d2968046Jake Hamby int padding = offset % width; 1039115632cc56f813bd21543f8532c763d7d2968046Jake Hamby int maxNumFields = (data.length - offset - padding) / width; 1040115632cc56f813bd21543f8532c763d7d2968046Jake Hamby if (maxNumFields < 0) { 1041115632cc56f813bd21543f8532c763d7d2968046Jake Hamby throw new CodingException(charset + " decode failed: offset out of range"); 1042115632cc56f813bd21543f8532c763d7d2968046Jake Hamby } 1043ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, charset + " decode error: offset = " + offset + " numFields = " 1044115632cc56f813bd21543f8532c763d7d2968046Jake Hamby + numFields + " data.length = " + data.length + " maxNumFields = " 1045115632cc56f813bd21543f8532c763d7d2968046Jake Hamby + maxNumFields); 1046115632cc56f813bd21543f8532c763d7d2968046Jake Hamby numFields = maxNumFields; 10470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 1049115632cc56f813bd21543f8532c763d7d2968046Jake Hamby return new String(data, offset, numFields * width, charset); 10500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (java.io.UnsupportedEncodingException ex) { 1051115632cc56f813bd21543f8532c763d7d2968046Jake Hamby throw new CodingException(charset + " decode failed: " + ex); 10520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static String decode7bitAscii(byte[] data, int offset, int numFields) 10560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException 10570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 10580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 10590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville offset *= 8; 10600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville StringBuffer strBuf = new StringBuffer(numFields); 10610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville BitwiseInputStream inStream = new BitwiseInputStream(data); 10620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int wantedBits = (offset * 8) + (numFields * 7); 10630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (inStream.available() < wantedBits) { 10640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("insufficient data (wanted " + wantedBits + 10650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " bits, but only have " + inStream.available() + ")"); 10660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(offset); 10680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < numFields; i++) { 10690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int charCode = inStream.read(7); 10700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((charCode >= UserData.ASCII_MAP_BASE_INDEX) && 10710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (charCode <= UserData.ASCII_MAP_MAX_INDEX)) { 10720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville strBuf.append(UserData.ASCII_MAP[charCode - UserData.ASCII_MAP_BASE_INDEX]); 10730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (charCode == UserData.ASCII_NL_INDEX) { 10740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville strBuf.append('\n'); 10750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (charCode == UserData.ASCII_CR_INDEX) { 10760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville strBuf.append('\r'); 10770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 10780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* For other charCodes, they are unprintable, and so simply use SPACE. */ 10790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville strBuf.append(' '); 10800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return strBuf.toString(); 10830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (BitwiseInputStream.AccessException ex) { 10840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("7bit ASCII decode failed: " + ex); 10850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static String decode7bitGsm(byte[] data, int offset, int numFields) 10890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException 10900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 10910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Start reading from the next 7-bit aligned boundary after offset. 10920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int offsetBits = offset * 8; 10930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int offsetSeptets = (offsetBits + 6) / 7; 10940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville numFields -= offsetSeptets; 10950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paddingBits = (offsetSeptets * 7) - offsetBits; 10960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String result = GsmAlphabet.gsm7BitPackedToString(data, offset, numFields, paddingBits, 10970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 0, 0); 10980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (result == null) { 10990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("7bit GSM decoding failed"); 11000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return result; 11020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static String decodeLatin(byte[] data, int offset, int numFields) 11050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException 11060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 1107115632cc56f813bd21543f8532c763d7d2968046Jake Hamby return decodeCharset(data, offset, numFields, 1, "ISO-8859-1"); 11080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11103de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks private static String decodeShiftJis(byte[] data, int offset, int numFields) 11113de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks throws CodingException 11123de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks { 1113a2ccc4f16ec2f3e26b308d6f25cd4aa6a394a008Jake Hamby return decodeCharset(data, offset, numFields, 1, "Shift_JIS"); 11143de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks } 11153de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks 11160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void decodeUserDataPayload(UserData userData, boolean hasUserDataHeader) 11170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException 11180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 11190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int offset = 0; 11200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (hasUserDataHeader) { 11210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int udhLen = userData.payload[0] & 0x00FF; 11220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville offset += udhLen + 1; 11230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] headerData = new byte[udhLen]; 11240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville System.arraycopy(userData.payload, 1, headerData, 0, udhLen); 11250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville userData.userDataHeader = SmsHeader.fromByteArray(headerData); 11260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (userData.msgEncoding) { 11280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_OCTET: 11290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* 11300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Octet decoding depends on the carrier service. 11310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 11320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodingtypeUTF8 = Resources.getSystem() 11330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .getBoolean(com.android.internal.R.bool.config_sms_utf8_support); 11340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Strip off any padding bytes, meaning any differences between the length of the 11360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // array and the target length specified by numFields. This is to avoid any 11370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // confusion by code elsewhere that only considers the payload array length. 11380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] payload = new byte[userData.numFields]; 11390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int copyLen = userData.numFields < userData.payload.length 11400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ? userData.numFields : userData.payload.length; 11410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville System.arraycopy(userData.payload, 0, payload, 0, copyLen); 11430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville userData.payload = payload; 11440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (!decodingtypeUTF8) { 11460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // There are many devices in the market that send 8bit text sms (latin encoded) as 11470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // octet encoded. 11480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville userData.payloadStr = decodeLatin(userData.payload, offset, userData.numFields); 11490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 11500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville userData.payloadStr = decodeUtf8(userData.payload, offset, userData.numFields); 11510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 11530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_IA5: 11550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_7BIT_ASCII: 11560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville userData.payloadStr = decode7bitAscii(userData.payload, offset, userData.numFields); 11570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 11580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_UNICODE_16: 11590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville userData.payloadStr = decodeUtf16(userData.payload, offset, userData.numFields); 11600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 11610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_GSM_7BIT_ALPHABET: 11620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville userData.payloadStr = decode7bitGsm(userData.payload, offset, userData.numFields); 11630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 11640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_LATIN: 11650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville userData.payloadStr = decodeLatin(userData.payload, offset, userData.numFields); 11660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 11673de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks case UserData.ENCODING_SHIFT_JIS: 11683de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks userData.payloadStr = decodeShiftJis(userData.payload, offset, userData.numFields); 11693de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks break; 11700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville default: 11710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("unsupported user data encoding (" 11720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville + userData.msgEncoding + ")"); 11730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 11770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * IS-91 Voice Mail message decoding 11780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.S0015-A, Table 4.3.1.4.1-1) 11790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (For character encodings, see TIA/EIA/IS-91, Annex B) 11800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 11810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Protocol Summary: The user data payload may contain 3-14 11820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * characters. The first two characters are parsed as a number 11830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * and indicate the number of voicemails. The third character is 11840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * either a SPACE or '!' to indicate normal or urgent priority, 11850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * respectively. Any following characters are treated as normal 11860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * text user data payload. 11870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 11880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Note that the characters encoding is 6-bit packed. 11890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 11900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void decodeIs91VoicemailStatus(BearerData bData) 11910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseInputStream.AccessException, CodingException 11920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 11930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville BitwiseInputStream inStream = new BitwiseInputStream(bData.userData.payload); 11940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int dataLen = inStream.available() / 6; // 6-bit packed character encoding. 11950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int numFields = bData.userData.numFields; 11960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((dataLen > 14) || (dataLen < 3) || (dataLen < numFields)) { 11970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("IS-91 voicemail status decoding failed"); 11980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 12000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville StringBuffer strbuf = new StringBuffer(dataLen); 12010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville while (inStream.available() >= 6) { 12020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville strbuf.append(UserData.ASCII_MAP[inStream.read(6)]); 12030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String data = strbuf.toString(); 12050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.numberOfMessages = Integer.parseInt(data.substring(0, 2)); 12060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville char prioCode = data.charAt(2); 12070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (prioCode == ' ') { 12080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.priority = PRIORITY_NORMAL; 12090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (prioCode == '!') { 12100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.priority = PRIORITY_URGENT; 12110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 12120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("IS-91 voicemail status decoding failed: " + 12130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "illegal priority setting (" + prioCode + ")"); 12140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.priorityIndicatorSet = true; 12160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userData.payloadStr = data.substring(3, numFields - 3); 12170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (java.lang.NumberFormatException ex) { 12180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("IS-91 voicemail status decoding failed: " + ex); 12190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (java.lang.IndexOutOfBoundsException ex) { 12200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("IS-91 voicemail status decoding failed: " + ex); 12210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 12250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * IS-91 Short Message decoding 12260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.S0015-A, Table 4.3.1.4.1-1) 12270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (For character encodings, see TIA/EIA/IS-91, Annex B) 12280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 12290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Protocol Summary: The user data payload may contain 1-14 12300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * characters, which are treated as normal text user data payload. 12310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Note that the characters encoding is 6-bit packed. 12320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 12330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void decodeIs91ShortMessage(BearerData bData) 12340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseInputStream.AccessException, CodingException 12350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 12360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville BitwiseInputStream inStream = new BitwiseInputStream(bData.userData.payload); 12370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int dataLen = inStream.available() / 6; // 6-bit packed character encoding. 12380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int numFields = bData.userData.numFields; 12390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // dataLen may be > 14 characters due to octet padding 12400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((numFields > 14) || (dataLen < numFields)) { 12410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("IS-91 short message decoding failed"); 12420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville StringBuffer strbuf = new StringBuffer(dataLen); 12440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < numFields; i++) { 12450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville strbuf.append(UserData.ASCII_MAP[inStream.read(6)]); 12460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userData.payloadStr = strbuf.toString(); 12480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 12510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * IS-91 CLI message (callback number) decoding 12520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.S0015-A, Table 4.3.1.4.1-1) 12530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 12540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Protocol Summary: The data payload may contain 1-32 digits, 12550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * encoded using standard 4-bit DTMF, which are treated as a 12560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * callback number. 12570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 12580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void decodeIs91Cli(BearerData bData) throws CodingException { 12590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville BitwiseInputStream inStream = new BitwiseInputStream(bData.userData.payload); 12600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int dataLen = inStream.available() / 4; // 4-bit packed DTMF digit encoding. 12610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int numFields = bData.userData.numFields; 12620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((dataLen > 14) || (dataLen < 3) || (dataLen < numFields)) { 12630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("IS-91 voicemail status decoding failed"); 12640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville CdmaSmsAddress addr = new CdmaSmsAddress(); 12660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville addr.digitMode = CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF; 12670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville addr.origBytes = bData.userData.payload; 12680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville addr.numberOfDigits = (byte)numFields; 12690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSmsAddress(addr); 12700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.callbackNumber = addr; 12710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void decodeIs91(BearerData bData) 12740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseInputStream.AccessException, CodingException 12750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 12760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (bData.userData.msgType) { 12770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.IS91_MSG_TYPE_VOICEMAIL_STATUS: 12780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeIs91VoicemailStatus(bData); 12790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 12800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.IS91_MSG_TYPE_CLI: 12810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeIs91Cli(bData); 12820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 12830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.IS91_MSG_TYPE_SHORT_MESSAGE_FULL: 12840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.IS91_MSG_TYPE_SHORT_MESSAGE: 12850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeIs91ShortMessage(bData); 12860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 12870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville default: 12880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("unsupported IS-91 message type (" + 12890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userData.msgType + ")"); 12900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeReplyOption(BearerData bData, BitwiseInputStream inStream) 1294cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 12950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 1 * 8; 12960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 12970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 12980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 12990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 13000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 13010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userAckReq = (inStream.read(1) == 1); 13020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.deliveryAckReq = (inStream.read(1) == 1); 13030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.readAckReq = (inStream.read(1) == 1); 13040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.reportReq = (inStream.read(1) == 1); 13050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(4); 13060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1308ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "REPLY_OPTION decode " + 13090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 13100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 13110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 13130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 13140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 13160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeMsgCount(BearerData bData, BitwiseInputStream inStream) 1317cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 13180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 1 * 8; 13190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 13200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 13210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 13220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 13230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 13240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.numberOfMessages = IccUtils.cdmaBcdByteToInt((byte)inStream.read(8)); 13250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1327ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "NUMBER_OF_MESSAGES decode " + 13280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 13290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 13300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 13320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 13330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 13350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeDepositIndex(BearerData bData, BitwiseInputStream inStream) 1336cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 13370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 2 * 8; 13380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 13390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 13400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 13410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 13420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 13430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.depositIndex = (inStream.read(8) << 8) | inStream.read(8); 13440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1346ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "MESSAGE_DEPOSIT_INDEX decode " + 13470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 13480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 13490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 13510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 13520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 13540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static String decodeDtmfSmsAddress(byte[] rawData, int numFields) 13550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException 13560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 13570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* DTMF 4-bit digit encoding, defined in at 13580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 3GPP2 C.S005-D, v2.0, table 2.7.1.3.2.4-4 */ 13590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville StringBuffer strBuf = new StringBuffer(numFields); 13600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < numFields; i++) { 13610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int val = 0x0F & (rawData[i / 2] >>> (4 - ((i % 2) * 4))); 13620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((val >= 1) && (val <= 9)) strBuf.append(Integer.toString(val, 10)); 13630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville else if (val == 10) strBuf.append('0'); 13640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville else if (val == 11) strBuf.append('*'); 13650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville else if (val == 12) strBuf.append('#'); 13660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville else throw new CodingException("invalid SMS address DTMF code (" + val + ")"); 13670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return strBuf.toString(); 13690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 13710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void decodeSmsAddress(CdmaSmsAddress addr) throws CodingException { 13720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) { 13730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 13740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* As specified in 3GPP2 C.S0015-B, v2, 4.5.15 -- actually 13750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * just 7-bit ASCII encoding, with the MSB being zero. */ 13760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville addr.address = new String(addr.origBytes, 0, addr.origBytes.length, "US-ASCII"); 13770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (java.io.UnsupportedEncodingException ex) { 13780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("invalid SMS address ASCII code"); 13790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 13810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville addr.address = decodeDtmfSmsAddress(addr.origBytes, addr.numberOfDigits); 13820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 13850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeCallbackNumber(BearerData bData, BitwiseInputStream inStream) 13860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseInputStream.AccessException, CodingException 13870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 1388dbb088ab146d2fcb435e75e4ca70f2ff7d00d2c7Alex Yakavenka final int EXPECTED_PARAM_SIZE = 1 * 8; //at least 13890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 1390dbb088ab146d2fcb435e75e4ca70f2ff7d00d2c7Alex Yakavenka if (paramBits < EXPECTED_PARAM_SIZE) { 1391dbb088ab146d2fcb435e75e4ca70f2ff7d00d2c7Alex Yakavenka inStream.skip(paramBits); 1392dbb088ab146d2fcb435e75e4ca70f2ff7d00d2c7Alex Yakavenka return false; 1393dbb088ab146d2fcb435e75e4ca70f2ff7d00d2c7Alex Yakavenka } 13940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville CdmaSmsAddress addr = new CdmaSmsAddress(); 13950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville addr.digitMode = inStream.read(1); 13960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte fieldBits = 4; 13970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte consumedBits = 1; 13980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) { 13990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville addr.ton = inStream.read(3); 14000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville addr.numberPlan = inStream.read(4); 14010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville fieldBits = 8; 14020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville consumedBits += 7; 14030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville addr.numberOfDigits = inStream.read(8); 14050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville consumedBits += 8; 14060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int remainingBits = paramBits - consumedBits; 14070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int dataBits = addr.numberOfDigits * fieldBits; 14080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paddingBits = remainingBits - dataBits; 14090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (remainingBits < dataBits) { 14100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("CALLBACK_NUMBER subparam encoding size error (" + 14110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "remainingBits + " + remainingBits + ", dataBits + " + 14120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville dataBits + ", paddingBits + " + paddingBits + ")"); 14130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville addr.origBytes = inStream.readByteArray(dataBits); 14150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paddingBits); 14160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSmsAddress(addr); 14170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.callbackNumber = addr; 14180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return true; 14190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 14210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeMsgStatus(BearerData bData, BitwiseInputStream inStream) 1422cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 14230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 1 * 8; 14240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 14250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 14260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 14270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 14280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 14290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.errorClass = inStream.read(2); 14300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.messageStatus = inStream.read(6); 14310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1433ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "MESSAGE_STATUS decode " + 14340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 14350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 14360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 14380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.messageStatusSet = decodeSuccess; 14390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 14400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 14420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeMsgCenterTimeStamp(BearerData bData, BitwiseInputStream inStream) 1443cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 14440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 6 * 8; 14450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 14460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 14470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 14480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 14490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 14500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.msgCenterTimeStamp = TimeStamp.fromByteArray(inStream.readByteArray(6 * 8)); 14510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1453ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "MESSAGE_CENTER_TIME_STAMP decode " + 14540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 14550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 14560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 14580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 14590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 14610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeValidityAbs(BearerData bData, BitwiseInputStream inStream) 1462cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 14630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 6 * 8; 14640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 14650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 14660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 14670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 14680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 14690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.validityPeriodAbsolute = TimeStamp.fromByteArray(inStream.readByteArray(6 * 8)); 14700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1472ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "VALIDITY_PERIOD_ABSOLUTE decode " + 14730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 14740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 14750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 14770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 14780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 14800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeDeferredDeliveryAbs(BearerData bData, BitwiseInputStream inStream) 1481cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 14820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 6 * 8; 14830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 14840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 14850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 14860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 14870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 14880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.deferredDeliveryTimeAbsolute = TimeStamp.fromByteArray( 14890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.readByteArray(6 * 8)); 14900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1492ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "DEFERRED_DELIVERY_TIME_ABSOLUTE decode " + 14930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 14940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 14950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 14970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 14980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 14990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 15000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeValidityRel(BearerData bData, BitwiseInputStream inStream) 1501cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 15020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 1 * 8; 15030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 15040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 15050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 15060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 15070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 15080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.deferredDeliveryTimeRelative = inStream.read(8); 15090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1511ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "VALIDITY_PERIOD_RELATIVE decode " + 15120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 15130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 15140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 15160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.deferredDeliveryTimeRelativeSet = decodeSuccess; 15170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 15180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 15200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeDeferredDeliveryRel(BearerData bData, BitwiseInputStream inStream) 1521cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 15220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 1 * 8; 15230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 15240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 15250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 15260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 15270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 15280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.validityPeriodRelative = inStream.read(8); 15290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1531ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "DEFERRED_DELIVERY_TIME_RELATIVE decode " + 15320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 15330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 15340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 15360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.validityPeriodRelativeSet = decodeSuccess; 15370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 15380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 15400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodePrivacyIndicator(BearerData bData, BitwiseInputStream inStream) 1541cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 15420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 1 * 8; 15430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 15440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 15450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 15460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 15470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 15480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.privacy = inStream.read(2); 15490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(6); 15500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1552ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "PRIVACY_INDICATOR decode " + 15530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 15540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 15550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 15570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.privacyIndicatorSet = decodeSuccess; 15580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 15590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 15610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeLanguageIndicator(BearerData bData, BitwiseInputStream inStream) 1562cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 15630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 1 * 8; 15640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 15650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 15660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 15670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 15680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 15690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.language = inStream.read(8); 15700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1572ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "LANGUAGE_INDICATOR decode " + 15730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 15740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 15750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 15770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.languageIndicatorSet = decodeSuccess; 15780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 15790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 15810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeDisplayMode(BearerData bData, BitwiseInputStream inStream) 1582cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 15830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 1 * 8; 15840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 15850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 15860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 15870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 15880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 15890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.displayMode = inStream.read(2); 15900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(6); 15910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1593ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "DISPLAY_MODE decode " + 15940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 15950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 15960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 15980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.displayModeSet = decodeSuccess; 15990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 16000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 16020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodePriorityIndicator(BearerData bData, BitwiseInputStream inStream) 1603cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 16040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 1 * 8; 16050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 16060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 16070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 16080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 16090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 16100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.priority = inStream.read(2); 16110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(6); 16120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1614ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "PRIORITY_INDICATOR decode " + 16150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 16160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 16170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 16190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.priorityIndicatorSet = decodeSuccess; 16200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 16210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 16230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeMsgDeliveryAlert(BearerData bData, BitwiseInputStream inStream) 1624cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 16250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 1 * 8; 16260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 16270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 16280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 16290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 16300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 16310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.alert = inStream.read(2); 16320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(6); 16330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1635ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "ALERT_ON_MESSAGE_DELIVERY decode " + 16360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 16370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 16380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 16400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.alertIndicatorSet = decodeSuccess; 16410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 16420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 16440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeUserResponseCode(BearerData bData, BitwiseInputStream inStream) 1645cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville throws BitwiseInputStream.AccessException { 16460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int EXPECTED_PARAM_SIZE = 1 * 8; 16470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 16480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 16490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits >= EXPECTED_PARAM_SIZE) { 16500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= EXPECTED_PARAM_SIZE; 16510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 16520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userResponseCode = inStream.read(8); 16530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1655ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "USER_RESPONSE_CODE decode " + 16560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 16570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ")"); 16580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 16600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userResponseCodeSet = decodeSuccess; 16610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 16620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 16640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean decodeServiceCategoryProgramData(BearerData bData, 16650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville BitwiseInputStream inStream) throws BitwiseInputStream.AccessException, CodingException 16660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 16670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (inStream.available() < 13) { 16680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("SERVICE_CATEGORY_PROGRAM_DATA decode failed: only " 16690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville + inStream.available() + " bits available"); 16700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 16720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int paramBits = inStream.read(8) * 8; 16730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int msgEncoding = inStream.read(5); 16740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= 5; 16750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 16760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (inStream.available() < paramBits) { 16770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("SERVICE_CATEGORY_PROGRAM_DATA decode failed: only " 16780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville + inStream.available() + " bits available (" + paramBits + " bits expected)"); 16790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 16810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<CdmaSmsCbProgramData> programDataList = new ArrayList<CdmaSmsCbProgramData>(); 16820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 16830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final int CATEGORY_FIELD_MIN_SIZE = 6 * 8; 16840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess = false; 16850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville while (paramBits >= CATEGORY_FIELD_MIN_SIZE) { 16860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int operation = inStream.read(4); 16870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int category = (inStream.read(8) << 8) | inStream.read(8); 1688b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby int language = inStream.read(8); 16890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int maxMessages = inStream.read(8); 16900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int alertOption = inStream.read(4); 16910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int numFields = inStream.read(8); 16920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= CATEGORY_FIELD_MIN_SIZE; 16930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 16940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int textBits = getBitsForNumFields(msgEncoding, numFields); 16950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (paramBits < textBits) { 16960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("category name is " + textBits + " bits in length," 16970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville + " but there are only " + paramBits + " bits available"); 16980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville UserData userData = new UserData(); 17010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville userData.msgEncoding = msgEncoding; 17020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville userData.msgEncodingSet = true; 17030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville userData.numFields = numFields; 17040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville userData.payload = inStream.readByteArray(textBits); 17050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville paramBits -= textBits; 17060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeUserDataPayload(userData, false); 17080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String categoryName = userData.payloadStr; 17090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville CdmaSmsCbProgramData programData = new CdmaSmsCbProgramData(operation, category, 17100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville language, maxMessages, alertOption, categoryName); 17110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville programDataList.add(programData); 17120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = true; 17140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 17150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((! decodeSuccess) || (paramBits > 0)) { 1717ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, "SERVICE_CATEGORY_PROGRAM_DATA decode " + 17180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (decodeSuccess ? "succeeded" : "failed") + 17190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville " (extra bits = " + paramBits + ')'); 17200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 17210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(paramBits); 17230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.serviceCategoryProgramData = programDataList; 17240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decodeSuccess; 17250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 17260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static int serviceCategoryToCmasMessageClass(int serviceCategory) { 17280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (serviceCategory) { 17290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT: 17300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return SmsCbCmasInfo.CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT; 17310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT: 17330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return SmsCbCmasInfo.CMAS_CLASS_EXTREME_THREAT; 17340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT: 17360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return SmsCbCmasInfo.CMAS_CLASS_SEVERE_THREAT; 17370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY: 17390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return SmsCbCmasInfo.CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY; 17400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE: 17420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return SmsCbCmasInfo.CMAS_CLASS_REQUIRED_MONTHLY_TEST; 17430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville default: 17450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return SmsCbCmasInfo.CMAS_CLASS_UNKNOWN; 17460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 17470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 17480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 17500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Calculates the number of bits to read for the specified number of encoded characters. 17510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param msgEncoding the message encoding to use 17520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param numFields the number of characters to read. For Shift-JIS and Korean encodings, 17530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * this is the number of bytes to read. 17540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return the number of bits to read from the stream 17550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @throws CodingException if the specified encoding is not supported 17560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 17570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static int getBitsForNumFields(int msgEncoding, int numFields) 17580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws CodingException { 17590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (msgEncoding) { 17600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_OCTET: 17610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_SHIFT_JIS: 17620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_KOREAN: 17630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_LATIN: 17640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_LATIN_HEBREW: 17650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return numFields * 8; 17660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_IA5: 17680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_7BIT_ASCII: 17690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_GSM_7BIT_ALPHABET: 17700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return numFields * 7; 17710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_UNICODE_16: 17730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return numFields * 16; 17740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville default: 17760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("unsupported message encoding (" + msgEncoding + ')'); 17770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 17780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 17790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 17810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * CMAS message decoding. 17820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See TIA-1149-0-1, CMAS over CDMA) 17830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 17840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param serviceCategory is the service category from the SMS envelope 17850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 17860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static void decodeCmasUserData(BearerData bData, int serviceCategory) 17870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throws BitwiseInputStream.AccessException, CodingException { 17880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville BitwiseInputStream inStream = new BitwiseInputStream(bData.userData.payload); 17890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (inStream.available() < 8) { 17900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("emergency CB with no CMAE_protocol_version"); 17910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 17920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int protocolVersion = inStream.read(8); 17930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (protocolVersion != 0) { 17940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("unsupported CMAE_protocol_version " + protocolVersion); 17950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 17960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 17970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int messageClass = serviceCategoryToCmasMessageClass(serviceCategory); 17980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int category = SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN; 17990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int responseType = SmsCbCmasInfo.CMAS_RESPONSE_TYPE_UNKNOWN; 18000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int severity = SmsCbCmasInfo.CMAS_SEVERITY_UNKNOWN; 18010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int urgency = SmsCbCmasInfo.CMAS_URGENCY_UNKNOWN; 18020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int certainty = SmsCbCmasInfo.CMAS_CERTAINTY_UNKNOWN; 18030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 18040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville while (inStream.available() >= 16) { 18050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int recordType = inStream.read(8); 18060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int recordLen = inStream.read(8); 18070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (recordType) { 18080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 0: // Type 0 elements (Alert text) 18090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville UserData alertUserData = new UserData(); 18100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville alertUserData.msgEncoding = inStream.read(5); 18110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville alertUserData.msgEncodingSet = true; 18120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville alertUserData.msgType = 0; 18130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 18140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int numFields; // number of chars to decode 18150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (alertUserData.msgEncoding) { 18160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_OCTET: 18170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_LATIN: 18180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville numFields = recordLen - 1; // subtract 1 byte for encoding 18190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 18200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 18210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_IA5: 18220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_7BIT_ASCII: 18230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_GSM_7BIT_ALPHABET: 18240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville numFields = ((recordLen * 8) - 5) / 7; // subtract 5 bits for encoding 18250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 18260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 18270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case UserData.ENCODING_UNICODE_16: 18280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville numFields = (recordLen - 1) / 2; 18290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 18300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 18310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville default: 18320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville numFields = 0; // unsupported encoding 18330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 18340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 18350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville alertUserData.numFields = numFields; 18360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville alertUserData.payload = inStream.readByteArray(recordLen * 8 - 5); 18370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeUserDataPayload(alertUserData, false); 18380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.userData = alertUserData; 18390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 18400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 18410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case 1: // Type 1 elements 18420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville category = inStream.read(8); 18430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville responseType = inStream.read(8); 18440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville severity = inStream.read(4); 18450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville urgency = inStream.read(4); 18460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville certainty = inStream.read(4); 18470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(recordLen * 8 - 28); 18480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 18490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 18500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville default: 1851ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.w(LOG_TAG, "skipping unsupported CMAS record type " + recordType); 18520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville inStream.skip(recordLen * 8); 18530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 18540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 18550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 18560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 18570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville bData.cmasWarningInfo = new SmsCbCmasInfo(messageClass, category, responseType, severity, 18580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville urgency, certainty); 18590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 18600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 18610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 18620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Create BearerData object from serialized representation. 18630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details) 18640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 18650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param smsData byte array of raw encoded SMS bearer data. 18660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return an instance of BearerData. 18670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 18680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static BearerData decode(byte[] smsData) { 18690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return decode(smsData, 0); 18700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 18710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 18720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean isCmasAlertCategory(int category) { 18730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return category >= SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT 18740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville && category <= SmsEnvelope.SERVICE_CATEGORY_CMAS_LAST_RESERVED_VALUE; 18750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 18760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 18770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 18780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Create BearerData object from serialized representation. 18790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details) 18800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 18810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param smsData byte array of raw encoded SMS bearer data. 18820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param serviceCategory the envelope service category (for CMAS alert handling) 18830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return an instance of BearerData. 18840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 18850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static BearerData decode(byte[] smsData, int serviceCategory) { 18860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 18870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville BitwiseInputStream inStream = new BitwiseInputStream(smsData); 18880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville BearerData bData = new BearerData(); 18890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int foundSubparamMask = 0; 18900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville while (inStream.available() > 0) { 18910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int subparamId = inStream.read(8); 18920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int subparamIdBit = 1 << subparamId; 18933de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks // int is 4 bytes. This duplicate check has a limit to Id number up to 32 (4*8) 18943de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks // as 32th bit is the max bit in int. 18953de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks // Per 3GPP2 C.S0015-B Table 4.5-1 Bearer Data Subparameter Identifiers: 18963de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks // last defined subparam ID is 23 (00010111 = 0x17 = 23). 18973de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks // Only do duplicate subparam ID check if subparam is within defined value as 18983de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks // reserved subparams are just skipped. 18993de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks if ((foundSubparamMask & subparamIdBit) != 0 && 19003de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks (subparamId >= SUBPARAM_MESSAGE_IDENTIFIER && 19013de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks subparamId <= SUBPARAM_ID_LAST_DEFINED)) { 19020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("illegal duplicate subparameter (" + 19030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville subparamId + ")"); 19040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 19050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean decodeSuccess; 19060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (subparamId) { 19070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_MESSAGE_IDENTIFIER: 19080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeMessageId(bData, inStream); 19090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_USER_DATA: 19110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeUserData(bData, inStream); 19120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_USER_RESPONSE_CODE: 19140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeUserResponseCode(bData, inStream); 19150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_REPLY_OPTION: 19170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeReplyOption(bData, inStream); 19180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_NUMBER_OF_MESSAGES: 19200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeMsgCount(bData, inStream); 19210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_CALLBACK_NUMBER: 19230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeCallbackNumber(bData, inStream); 19240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_MESSAGE_STATUS: 19260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeMsgStatus(bData, inStream); 19270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_MESSAGE_CENTER_TIME_STAMP: 19290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeMsgCenterTimeStamp(bData, inStream); 19300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_VALIDITY_PERIOD_ABSOLUTE: 19320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeValidityAbs(bData, inStream); 19330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_VALIDITY_PERIOD_RELATIVE: 19350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeValidityRel(bData, inStream); 19360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_DEFERRED_DELIVERY_TIME_ABSOLUTE: 19380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeDeferredDeliveryAbs(bData, inStream); 19390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_DEFERRED_DELIVERY_TIME_RELATIVE: 19410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeDeferredDeliveryRel(bData, inStream); 19420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_PRIVACY_INDICATOR: 19440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodePrivacyIndicator(bData, inStream); 19450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_LANGUAGE_INDICATOR: 19470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeLanguageIndicator(bData, inStream); 19480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_MESSAGE_DISPLAY_MODE: 19500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeDisplayMode(bData, inStream); 19510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_PRIORITY_INDICATOR: 19530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodePriorityIndicator(bData, inStream); 19540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_ALERT_ON_MESSAGE_DELIVERY: 19560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeMsgDeliveryAlert(bData, inStream); 19570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_MESSAGE_DEPOSIT_INDEX: 19590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeDepositIndex(bData, inStream); 19600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA: 19620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeSuccess = decodeServiceCategoryProgramData(bData, inStream); 19630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 19640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville default: 19653de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks decodeSuccess = decodeReserved(bData, inStream, subparamId); 19663de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks } 19673de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks if (decodeSuccess && 19683de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks (subparamId >= SUBPARAM_MESSAGE_IDENTIFIER && 19693de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks subparamId <= SUBPARAM_ID_LAST_DEFINED)) { 19703de1a7e5535f36e86d82da12df2b17aeeafabdc6Rika Brooks foundSubparamMask |= subparamIdBit; 19710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 19720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 19730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((foundSubparamMask & (1 << SUBPARAM_MESSAGE_IDENTIFIER)) == 0) { 19740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville throw new CodingException("missing MESSAGE_IDENTIFIER subparam"); 19750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 19760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (bData.userData != null) { 19770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (isCmasAlertCategory(serviceCategory)) { 19780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeCmasUserData(bData, serviceCategory); 19790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) { 19800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if ((foundSubparamMask ^ 19810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (1 << SUBPARAM_MESSAGE_IDENTIFIER) ^ 19820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville (1 << SUBPARAM_USER_DATA)) 19830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville != 0) { 1984ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "IS-91 must occur without extra subparams (" + 19850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville foundSubparamMask + ")"); 19860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 19870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeIs91(bData); 19880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 19890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville decodeUserDataPayload(bData.userData, bData.hasUserDataHeader); 19900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 19910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 19920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return bData; 19930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (BitwiseInputStream.AccessException ex) { 1994ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "BearerData decode failed: " + ex); 19950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CodingException ex) { 1996ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "BearerData decode failed: " + ex); 19970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 19980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return null; 19990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 20000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville} 2001