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 17 package android.telephony; 18 19 import android.os.Parcel; 20 import 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 */ 64 public 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 */ SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber, SmsCbLocation location, int serviceCategory, String language, String body, int priority, SmsCbEtwsInfo etwsWarningInfo, SmsCbCmasInfo cmasWarningInfo)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. */ SmsCbMessage(Parcel in)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 writeToParcel(Parcel dest, int flags)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 */ getGeographicalScope()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 */ getSerialNumber()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 */ getLocation()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 */ getServiceCategory()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 */ getLanguageCode()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 */ getMessageBody()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 */ getMessageFormat()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 */ getMessagePriority()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 */ getEtwsWarningInfo()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 */ getCmasWarningInfo()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 */ isEmergencyMessage()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 */ isEtwsMessage()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 */ isCmasMessage()360 public boolean isCmasMessage() { 361 return mCmasWarningInfo != null; 362 } 363 364 @Override toString()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 describeContents()379 public int describeContents() { 380 return 0; 381 } 382 } 383