1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.telephony; 18 19import android.os.Parcel; 20import android.os.Parcelable; 21 22/** 23 * Parcelable object containing a received cell broadcast message. There are four different types 24 * of Cell Broadcast messages: 25 * 26 * <ul> 27 * <li>opt-in informational broadcasts, e.g. news, weather, stock quotes, sports scores</li> 28 * <li>cell information messages, broadcast on channel 50, indicating the current cell name for 29 * roaming purposes (required to display on the idle screen in Brazil)</li> 30 * <li>emergency broadcasts for the Japanese Earthquake and Tsunami Warning System (ETWS)</li> 31 * <li>emergency broadcasts for the American Commercial Mobile Alert Service (CMAS)</li> 32 * </ul> 33 * 34 * <p>There are also four different CB message formats: GSM, ETWS Primary Notification (GSM only), 35 * UMTS, and CDMA. Some fields are only applicable for some message formats. Other fields were 36 * unified under a common name, avoiding some names, such as "Message Identifier", that refer to 37 * two completely different concepts in 3GPP and CDMA. 38 * 39 * <p>The GSM/UMTS Message Identifier field is available via {@link #getServiceCategory}, the name 40 * of the equivalent field in CDMA. In both cases the service category is a 16-bit value, but 3GPP 41 * and 3GPP2 have completely different meanings for the respective values. For ETWS and CMAS, the 42 * application should 43 * 44 * <p>The CDMA Message Identifier field is available via {@link #getSerialNumber}, which is used 45 * to detect the receipt of a duplicate message to be discarded. In CDMA, the message ID is 46 * unique to the current PLMN. In GSM/UMTS, there is a 16-bit serial number containing a 2-bit 47 * Geographical Scope field which indicates whether the 10-bit message code and 4-bit update number 48 * are considered unique to the PLMN, to the current cell, or to the current Location Area (or 49 * Service Area in UMTS). The relevant values are concatenated into a single String which will be 50 * unique if the messages are not duplicates. 51 * 52 * <p>The SMS dispatcher does not detect duplicate messages. However, it does concatenate the 53 * pages of a GSM multi-page cell broadcast into a single SmsCbMessage object. 54 * 55 * <p>Interested applications with {@code RECEIVE_SMS_PERMISSION} can register to receive 56 * {@code SMS_CB_RECEIVED_ACTION} broadcast intents for incoming non-emergency broadcasts. 57 * Only system applications such as the CellBroadcastReceiver may receive notifications for 58 * emergency broadcasts (ETWS and CMAS). This is intended to prevent any potential for delays or 59 * interference with the immediate display of the alert message and playing of the alert sound and 60 * vibration pattern, which could be caused by poorly written or malicious non-system code. 61 * 62 * @hide 63 */ 64public class SmsCbMessage implements Parcelable { 65 66 protected static final String LOG_TAG = "SMSCB"; 67 68 /** Cell wide geographical scope with immediate display (GSM/UMTS only). */ 69 public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE = 0; 70 71 /** PLMN wide geographical scope (GSM/UMTS and all CDMA broadcasts). */ 72 public static final int GEOGRAPHICAL_SCOPE_PLMN_WIDE = 1; 73 74 /** Location / service area wide geographical scope (GSM/UMTS only). */ 75 public static final int GEOGRAPHICAL_SCOPE_LA_WIDE = 2; 76 77 /** Cell wide geographical scope (GSM/UMTS only). */ 78 public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE = 3; 79 80 /** GSM or UMTS format cell broadcast. */ 81 public static final int MESSAGE_FORMAT_3GPP = 1; 82 83 /** CDMA format cell broadcast. */ 84 public static final int MESSAGE_FORMAT_3GPP2 = 2; 85 86 /** Normal message priority. */ 87 public static final int MESSAGE_PRIORITY_NORMAL = 0; 88 89 /** Interactive message priority. */ 90 public static final int MESSAGE_PRIORITY_INTERACTIVE = 1; 91 92 /** Urgent message priority. */ 93 public static final int MESSAGE_PRIORITY_URGENT = 2; 94 95 /** Emergency message priority. */ 96 public static final int MESSAGE_PRIORITY_EMERGENCY = 3; 97 98 /** Format of this message (for interpretation of service category values). */ 99 private final int mMessageFormat; 100 101 /** Geographical scope of broadcast. */ 102 private final int mGeographicalScope; 103 104 /** 105 * Serial number of broadcast (message identifier for CDMA, geographical scope + message code + 106 * update number for GSM/UMTS). The serial number plus the location code uniquely identify 107 * a cell broadcast for duplicate detection. 108 */ 109 private final int mSerialNumber; 110 111 /** 112 * Location identifier for this message. It consists of the current operator MCC/MNC as a 113 * 5 or 6-digit decimal string. In addition, for GSM/UMTS, if the Geographical Scope of the 114 * message is not binary 01, the Location Area is included for comparison. If the GS is 115 * 00 or 11, the Cell ID is also included. LAC and Cell ID are -1 if not specified. 116 */ 117 private final SmsCbLocation mLocation; 118 119 /** 120 * 16-bit CDMA service category or GSM/UMTS message identifier. For ETWS and CMAS warnings, 121 * the information provided by the category is also available via {@link #getEtwsWarningInfo()} 122 * or {@link #getCmasWarningInfo()}. 123 */ 124 private final int mServiceCategory; 125 126 /** Message language, as a two-character string, e.g. "en". */ 127 private final String mLanguage; 128 129 /** Message body, as a String. */ 130 private final String mBody; 131 132 /** Message priority (including emergency priority). */ 133 private final int mPriority; 134 135 /** ETWS warning notification information (ETWS warnings only). */ 136 private final SmsCbEtwsInfo mEtwsWarningInfo; 137 138 /** CMAS warning notification information (CMAS warnings only). */ 139 private final SmsCbCmasInfo mCmasWarningInfo; 140 141 /** 142 * Create a new SmsCbMessage with the specified data. 143 */ 144 public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber, 145 SmsCbLocation location, int serviceCategory, String language, String body, 146 int priority, SmsCbEtwsInfo etwsWarningInfo, SmsCbCmasInfo cmasWarningInfo) { 147 mMessageFormat = messageFormat; 148 mGeographicalScope = geographicalScope; 149 mSerialNumber = serialNumber; 150 mLocation = location; 151 mServiceCategory = serviceCategory; 152 mLanguage = language; 153 mBody = body; 154 mPriority = priority; 155 mEtwsWarningInfo = etwsWarningInfo; 156 mCmasWarningInfo = cmasWarningInfo; 157 } 158 159 /** Create a new SmsCbMessage object from a Parcel. */ 160 public SmsCbMessage(Parcel in) { 161 mMessageFormat = in.readInt(); 162 mGeographicalScope = in.readInt(); 163 mSerialNumber = in.readInt(); 164 mLocation = new SmsCbLocation(in); 165 mServiceCategory = in.readInt(); 166 mLanguage = in.readString(); 167 mBody = in.readString(); 168 mPriority = in.readInt(); 169 int type = in.readInt(); 170 switch (type) { 171 case 'E': 172 // unparcel ETWS warning information 173 mEtwsWarningInfo = new SmsCbEtwsInfo(in); 174 mCmasWarningInfo = null; 175 break; 176 177 case 'C': 178 // unparcel CMAS warning information 179 mEtwsWarningInfo = null; 180 mCmasWarningInfo = new SmsCbCmasInfo(in); 181 break; 182 183 default: 184 mEtwsWarningInfo = null; 185 mCmasWarningInfo = null; 186 } 187 } 188 189 /** 190 * Flatten this object into a Parcel. 191 * 192 * @param dest The Parcel in which the object should be written. 193 * @param flags Additional flags about how the object should be written (ignored). 194 */ 195 @Override 196 public void writeToParcel(Parcel dest, int flags) { 197 dest.writeInt(mMessageFormat); 198 dest.writeInt(mGeographicalScope); 199 dest.writeInt(mSerialNumber); 200 mLocation.writeToParcel(dest, flags); 201 dest.writeInt(mServiceCategory); 202 dest.writeString(mLanguage); 203 dest.writeString(mBody); 204 dest.writeInt(mPriority); 205 if (mEtwsWarningInfo != null) { 206 // parcel ETWS warning information 207 dest.writeInt('E'); 208 mEtwsWarningInfo.writeToParcel(dest, flags); 209 } else if (mCmasWarningInfo != null) { 210 // parcel CMAS warning information 211 dest.writeInt('C'); 212 mCmasWarningInfo.writeToParcel(dest, flags); 213 } else { 214 // no ETWS or CMAS warning information 215 dest.writeInt('0'); 216 } 217 } 218 219 public static final Parcelable.Creator<SmsCbMessage> CREATOR 220 = new Parcelable.Creator<SmsCbMessage>() { 221 @Override 222 public SmsCbMessage createFromParcel(Parcel in) { 223 return new SmsCbMessage(in); 224 } 225 226 @Override 227 public SmsCbMessage[] newArray(int size) { 228 return new SmsCbMessage[size]; 229 } 230 }; 231 232 /** 233 * Return the geographical scope of this message (GSM/UMTS only). 234 * 235 * @return Geographical scope 236 */ 237 public int getGeographicalScope() { 238 return mGeographicalScope; 239 } 240 241 /** 242 * Return the broadcast serial number of broadcast (message identifier for CDMA, or 243 * geographical scope + message code + update number for GSM/UMTS). The serial number plus 244 * the location code uniquely identify a cell broadcast for duplicate detection. 245 * 246 * @return the 16-bit CDMA message identifier or GSM/UMTS serial number 247 */ 248 public int getSerialNumber() { 249 return mSerialNumber; 250 } 251 252 /** 253 * Return the location identifier for this message, consisting of the MCC/MNC as a 254 * 5 or 6-digit decimal string. In addition, for GSM/UMTS, if the Geographical Scope of the 255 * message is not binary 01, the Location Area is included. If the GS is 00 or 11, the 256 * cell ID is also included. The {@link SmsCbLocation} object includes a method to test 257 * if the location is included within another location area or within a PLMN and CellLocation. 258 * 259 * @return the geographical location code for duplicate message detection 260 */ 261 public SmsCbLocation getLocation() { 262 return mLocation; 263 } 264 265 /** 266 * Return the 16-bit CDMA service category or GSM/UMTS message identifier. The interpretation 267 * of the category is radio technology specific. For ETWS and CMAS warnings, the information 268 * provided by the category is available via {@link #getEtwsWarningInfo()} or 269 * {@link #getCmasWarningInfo()} in a radio technology independent format. 270 * 271 * @return the radio technology specific service category 272 */ 273 public int getServiceCategory() { 274 return mServiceCategory; 275 } 276 277 /** 278 * Get the ISO-639-1 language code for this message, or null if unspecified 279 * 280 * @return Language code 281 */ 282 public String getLanguageCode() { 283 return mLanguage; 284 } 285 286 /** 287 * Get the body of this message, or null if no body available 288 * 289 * @return Body, or null 290 */ 291 public String getMessageBody() { 292 return mBody; 293 } 294 295 /** 296 * Get the message format ({@link #MESSAGE_FORMAT_3GPP} or {@link #MESSAGE_FORMAT_3GPP2}). 297 * @return an integer representing 3GPP or 3GPP2 message format 298 */ 299 public int getMessageFormat() { 300 return mMessageFormat; 301 } 302 303 /** 304 * Get the message priority. Normal broadcasts return {@link #MESSAGE_PRIORITY_NORMAL} 305 * and emergency broadcasts return {@link #MESSAGE_PRIORITY_EMERGENCY}. CDMA also may return 306 * {@link #MESSAGE_PRIORITY_INTERACTIVE} or {@link #MESSAGE_PRIORITY_URGENT}. 307 * @return an integer representing the message priority 308 */ 309 public int getMessagePriority() { 310 return mPriority; 311 } 312 313 /** 314 * If this is an ETWS warning notification then this method will return an object containing 315 * the ETWS warning type, the emergency user alert flag, and the popup flag. If this is an 316 * ETWS primary notification (GSM only), there will also be a 7-byte timestamp and 43-byte 317 * digital signature. As of Release 10, 3GPP TS 23.041 states that the UE shall ignore the 318 * ETWS primary notification timestamp and digital signature if received. 319 * 320 * @return an SmsCbEtwsInfo object, or null if this is not an ETWS warning notification 321 */ 322 public SmsCbEtwsInfo getEtwsWarningInfo() { 323 return mEtwsWarningInfo; 324 } 325 326 /** 327 * If this is a CMAS warning notification then this method will return an object containing 328 * the CMAS message class, category, response type, severity, urgency and certainty. 329 * The message class is always present. Severity, urgency and certainty are present for CDMA 330 * warning notifications containing a type 1 elements record and for GSM and UMTS warnings 331 * except for the Presidential-level alert category. Category and response type are only 332 * available for CDMA notifications containing a type 1 elements record. 333 * 334 * @return an SmsCbCmasInfo object, or null if this is not a CMAS warning notification 335 */ 336 public SmsCbCmasInfo getCmasWarningInfo() { 337 return mCmasWarningInfo; 338 } 339 340 /** 341 * Return whether this message is an emergency (PWS) message type. 342 * @return true if the message is a public warning notification; false otherwise 343 */ 344 public boolean isEmergencyMessage() { 345 return mPriority == MESSAGE_PRIORITY_EMERGENCY; 346 } 347 348 /** 349 * Return whether this message is an ETWS warning alert. 350 * @return true if the message is an ETWS warning notification; false otherwise 351 */ 352 public boolean isEtwsMessage() { 353 return mEtwsWarningInfo != null; 354 } 355 356 /** 357 * Return whether this message is a CMAS warning alert. 358 * @return true if the message is a CMAS warning notification; false otherwise 359 */ 360 public boolean isCmasMessage() { 361 return mCmasWarningInfo != null; 362 } 363 364 @Override 365 public String toString() { 366 return "SmsCbMessage{geographicalScope=" + mGeographicalScope + ", serialNumber=" 367 + mSerialNumber + ", location=" + mLocation + ", serviceCategory=" 368 + mServiceCategory + ", language=" + mLanguage + ", body=" + mBody 369 + ", priority=" + mPriority 370 + (mEtwsWarningInfo != null ? (", " + mEtwsWarningInfo.toString()) : "") 371 + (mCmasWarningInfo != null ? (", " + mCmasWarningInfo.toString()) : "") + '}'; 372 } 373 374 /** 375 * Describe the kinds of special objects contained in the marshalled representation. 376 * @return a bitmask indicating this Parcelable contains no special objects 377 */ 378 @Override 379 public int describeContents() { 380 return 0; 381 } 382} 383