SmsCbHeader.java revision 4980bf4aff8d49ac4e05444a6ef40ea1536f1afb
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 com.android.internal.telephony.gsm; 18 19import android.telephony.SmsCbCmasInfo; 20import android.telephony.SmsCbEtwsInfo; 21 22import java.util.Arrays; 23 24/** 25 * Parses a 3GPP TS 23.041 cell broadcast message header. This class is public for use by 26 * CellBroadcastReceiver test cases, but should not be used by applications. 27 * 28 * All relevant header information is now sent as a Parcelable 29 * {@link android.telephony.SmsCbMessage} object in the "message" extra of the 30 * {@link android.provider.Telephony.Sms.Intents#SMS_CB_RECEIVED_ACTION} or 31 * {@link android.provider.Telephony.Sms.Intents#SMS_EMERGENCY_CB_RECEIVED_ACTION} intent. 32 * The raw PDU is no longer sent to SMS CB applications. 33 */ 34public class SmsCbHeader { 35 36 /** 37 * Length of SMS-CB header 38 */ 39 static final int PDU_HEADER_LENGTH = 6; 40 41 /** 42 * GSM pdu format, as defined in 3gpp TS 23.041, section 9.4.1 43 */ 44 static final int FORMAT_GSM = 1; 45 46 /** 47 * UMTS pdu format, as defined in 3gpp TS 23.041, section 9.4.2 48 */ 49 static final int FORMAT_UMTS = 2; 50 51 /** 52 * GSM pdu format, as defined in 3gpp TS 23.041, section 9.4.1.3 53 */ 54 static final int FORMAT_ETWS_PRIMARY = 3; 55 56 /** 57 * Message type value as defined in 3gpp TS 25.324, section 11.1. 58 */ 59 private static final int MESSAGE_TYPE_CBS_MESSAGE = 1; 60 61 /** 62 * Length of GSM pdus 63 */ 64 private static final int PDU_LENGTH_GSM = 88; 65 66 /** 67 * Maximum length of ETWS primary message GSM pdus 68 */ 69 private static final int PDU_LENGTH_ETWS = 56; 70 71 private final int mGeographicalScope; 72 73 /** The serial number combines geographical scope, message code, and update number. */ 74 private final int mSerialNumber; 75 76 /** The Message Identifier in 3GPP is the same as the Service Category in CDMA. */ 77 private final int mMessageIdentifier; 78 79 private final int mDataCodingScheme; 80 81 private final int mPageIndex; 82 83 private final int mNrOfPages; 84 85 private final int mFormat; 86 87 /** ETWS warning notification info. */ 88 private final SmsCbEtwsInfo mEtwsInfo; 89 90 /** CMAS warning notification info. */ 91 private final SmsCbCmasInfo mCmasInfo; 92 93 public SmsCbHeader(byte[] pdu) throws IllegalArgumentException { 94 if (pdu == null || pdu.length < PDU_HEADER_LENGTH) { 95 throw new IllegalArgumentException("Illegal PDU"); 96 } 97 98 if (pdu.length <= PDU_LENGTH_GSM) { 99 // can be ETWS or GSM format. 100 // Per TS23.041 9.4.1.2 and 9.4.1.3.2, GSM and ETWS format both 101 // contain serial number which contains GS, Message Code, and Update Number 102 // per 9.4.1.2.1, and message identifier in same octets 103 mGeographicalScope = (pdu[0] & 0xc0) >>> 6; 104 mSerialNumber = ((pdu[0] & 0xff) << 8) | (pdu[1] & 0xff); 105 mMessageIdentifier = ((pdu[2] & 0xff) << 8) | (pdu[3] & 0xff); 106 if (isEtwsMessage() && pdu.length <= PDU_LENGTH_ETWS) { 107 mFormat = FORMAT_ETWS_PRIMARY; 108 mDataCodingScheme = -1; 109 mPageIndex = -1; 110 mNrOfPages = -1; 111 boolean emergencyUserAlert = (pdu[4] & 0x1) != 0; 112 boolean activatePopup = (pdu[5] & 0x80) != 0; 113 int warningType = (pdu[4] & 0xfe) >>> 1; 114 byte[] warningSecurityInfo; 115 // copy the Warning-Security-Information, if present 116 if (pdu.length > PDU_HEADER_LENGTH) { 117 warningSecurityInfo = Arrays.copyOfRange(pdu, 6, pdu.length); 118 } else { 119 warningSecurityInfo = null; 120 } 121 mEtwsInfo = new SmsCbEtwsInfo(warningType, emergencyUserAlert, activatePopup, 122 true, warningSecurityInfo); 123 mCmasInfo = null; 124 return; // skip the ETWS/CMAS initialization code for regular notifications 125 } else { 126 // GSM pdus are no more than 88 bytes 127 mFormat = FORMAT_GSM; 128 mDataCodingScheme = pdu[4] & 0xff; 129 130 // Check for invalid page parameter 131 int pageIndex = (pdu[5] & 0xf0) >>> 4; 132 int nrOfPages = pdu[5] & 0x0f; 133 134 if (pageIndex == 0 || nrOfPages == 0 || pageIndex > nrOfPages) { 135 pageIndex = 1; 136 nrOfPages = 1; 137 } 138 139 mPageIndex = pageIndex; 140 mNrOfPages = nrOfPages; 141 } 142 } else { 143 // UMTS pdus are always at least 90 bytes since the payload includes 144 // a number-of-pages octet and also one length octet per page 145 mFormat = FORMAT_UMTS; 146 147 int messageType = pdu[0]; 148 149 if (messageType != MESSAGE_TYPE_CBS_MESSAGE) { 150 throw new IllegalArgumentException("Unsupported message type " + messageType); 151 } 152 153 mMessageIdentifier = ((pdu[1] & 0xff) << 8) | pdu[2] & 0xff; 154 mGeographicalScope = (pdu[3] & 0xc0) >>> 6; 155 mSerialNumber = ((pdu[3] & 0xff) << 8) | (pdu[4] & 0xff); 156 mDataCodingScheme = pdu[5] & 0xff; 157 158 // We will always consider a UMTS message as having one single page 159 // since there's only one instance of the header, even though the 160 // actual payload may contain several pages. 161 mPageIndex = 1; 162 mNrOfPages = 1; 163 } 164 165 if (isEtwsMessage()) { 166 boolean emergencyUserAlert = isEtwsEmergencyUserAlert(); 167 boolean activatePopup = isEtwsPopupAlert(); 168 int warningType = getEtwsWarningType(); 169 mEtwsInfo = new SmsCbEtwsInfo(warningType, emergencyUserAlert, activatePopup, 170 false, null); 171 mCmasInfo = null; 172 } else if (isCmasMessage()) { 173 int messageClass = getCmasMessageClass(); 174 int severity = getCmasSeverity(); 175 int urgency = getCmasUrgency(); 176 int certainty = getCmasCertainty(); 177 mEtwsInfo = null; 178 mCmasInfo = new SmsCbCmasInfo(messageClass, SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN, 179 SmsCbCmasInfo.CMAS_RESPONSE_TYPE_UNKNOWN, severity, urgency, certainty); 180 } else { 181 mEtwsInfo = null; 182 mCmasInfo = null; 183 } 184 } 185 186 int getGeographicalScope() { 187 return mGeographicalScope; 188 } 189 190 int getSerialNumber() { 191 return mSerialNumber; 192 } 193 194 int getServiceCategory() { 195 return mMessageIdentifier; 196 } 197 198 int getDataCodingScheme() { 199 return mDataCodingScheme; 200 } 201 202 int getPageIndex() { 203 return mPageIndex; 204 } 205 206 int getNumberOfPages() { 207 return mNrOfPages; 208 } 209 210 SmsCbEtwsInfo getEtwsInfo() { 211 return mEtwsInfo; 212 } 213 214 SmsCbCmasInfo getCmasInfo() { 215 return mCmasInfo; 216 } 217 218 /** 219 * Return whether this broadcast is an emergency (PWS) message type. 220 * @return true if this message is emergency type; false otherwise 221 */ 222 boolean isEmergencyMessage() { 223 return mMessageIdentifier >= SmsCbConstants.MESSAGE_ID_PWS_FIRST_IDENTIFIER 224 && mMessageIdentifier <= SmsCbConstants.MESSAGE_ID_PWS_LAST_IDENTIFIER; 225 } 226 227 /** 228 * Return whether this broadcast is an ETWS emergency message type. 229 * @return true if this message is ETWS emergency type; false otherwise 230 */ 231 private boolean isEtwsMessage() { 232 return (mMessageIdentifier & SmsCbConstants.MESSAGE_ID_ETWS_TYPE_MASK) 233 == SmsCbConstants.MESSAGE_ID_ETWS_TYPE; 234 } 235 236 /** 237 * Return whether this broadcast is an ETWS primary notification. 238 * @return true if this message is an ETWS primary notification; false otherwise 239 */ 240 boolean isEtwsPrimaryNotification() { 241 return mFormat == FORMAT_ETWS_PRIMARY; 242 } 243 244 /** 245 * Return whether this broadcast is in UMTS format. 246 * @return true if this message is in UMTS format; false otherwise 247 */ 248 boolean isUmtsFormat() { 249 return mFormat == FORMAT_UMTS; 250 } 251 252 /** 253 * Return whether this message is a CMAS emergency message type. 254 * @return true if this message is CMAS emergency type; false otherwise 255 */ 256 private boolean isCmasMessage() { 257 return mMessageIdentifier >= SmsCbConstants.MESSAGE_ID_CMAS_FIRST_IDENTIFIER 258 && mMessageIdentifier <= SmsCbConstants.MESSAGE_ID_CMAS_LAST_IDENTIFIER; 259 } 260 261 /** 262 * Return whether the popup alert flag is set for an ETWS warning notification. 263 * This method assumes that the message ID has already been checked for ETWS type. 264 * 265 * @return true if the message code indicates a popup alert should be displayed 266 */ 267 private boolean isEtwsPopupAlert() { 268 return (mSerialNumber & SmsCbConstants.SERIAL_NUMBER_ETWS_ACTIVATE_POPUP) != 0; 269 } 270 271 /** 272 * Return whether the emergency user alert flag is set for an ETWS warning notification. 273 * This method assumes that the message ID has already been checked for ETWS type. 274 * 275 * @return true if the message code indicates an emergency user alert 276 */ 277 private boolean isEtwsEmergencyUserAlert() { 278 return (mSerialNumber & SmsCbConstants.SERIAL_NUMBER_ETWS_EMERGENCY_USER_ALERT) != 0; 279 } 280 281 /** 282 * Returns the warning type for an ETWS warning notification. 283 * This method assumes that the message ID has already been checked for ETWS type. 284 * 285 * @return the ETWS warning type defined in 3GPP TS 23.041 section 9.3.24 286 */ 287 private int getEtwsWarningType() { 288 return mMessageIdentifier - SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_WARNING; 289 } 290 291 /** 292 * Returns the message class for a CMAS warning notification. 293 * This method assumes that the message ID has already been checked for CMAS type. 294 * @return the CMAS message class as defined in {@link SmsCbCmasInfo} 295 */ 296 private int getCmasMessageClass() { 297 switch (mMessageIdentifier) { 298 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL: 299 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL_LANGUAGE: 300 return SmsCbCmasInfo.CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT; 301 302 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED: 303 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED_LANGUAGE: 304 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY: 305 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY_LANGUAGE: 306 return SmsCbCmasInfo.CMAS_CLASS_EXTREME_THREAT; 307 308 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED: 309 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED_LANGUAGE: 310 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY: 311 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY_LANGUAGE: 312 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED: 313 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED_LANGUAGE: 314 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY: 315 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY_LANGUAGE: 316 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED: 317 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED_LANGUAGE: 318 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY: 319 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY_LANGUAGE: 320 return SmsCbCmasInfo.CMAS_CLASS_SEVERE_THREAT; 321 322 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY: 323 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY_LANGUAGE: 324 return SmsCbCmasInfo.CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY; 325 326 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST: 327 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST_LANGUAGE: 328 return SmsCbCmasInfo.CMAS_CLASS_REQUIRED_MONTHLY_TEST; 329 330 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXERCISE: 331 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXERCISE_LANGUAGE: 332 return SmsCbCmasInfo.CMAS_CLASS_CMAS_EXERCISE; 333 334 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE: 335 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE_LANGUAGE: 336 return SmsCbCmasInfo.CMAS_CLASS_OPERATOR_DEFINED_USE; 337 338 default: 339 return SmsCbCmasInfo.CMAS_CLASS_UNKNOWN; 340 } 341 } 342 343 /** 344 * Returns the severity for a CMAS warning notification. This is only available for extreme 345 * and severe alerts, not for other types such as Presidential Level and AMBER alerts. 346 * This method assumes that the message ID has already been checked for CMAS type. 347 * @return the CMAS severity as defined in {@link SmsCbCmasInfo} 348 */ 349 private int getCmasSeverity() { 350 switch (mMessageIdentifier) { 351 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED: 352 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED_LANGUAGE: 353 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY: 354 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY_LANGUAGE: 355 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED: 356 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED_LANGUAGE: 357 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY: 358 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY_LANGUAGE: 359 return SmsCbCmasInfo.CMAS_SEVERITY_EXTREME; 360 361 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED: 362 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED_LANGUAGE: 363 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY: 364 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY_LANGUAGE: 365 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED: 366 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED_LANGUAGE: 367 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY: 368 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY_LANGUAGE: 369 return SmsCbCmasInfo.CMAS_SEVERITY_SEVERE; 370 371 default: 372 return SmsCbCmasInfo.CMAS_SEVERITY_UNKNOWN; 373 } 374 } 375 376 /** 377 * Returns the urgency for a CMAS warning notification. This is only available for extreme 378 * and severe alerts, not for other types such as Presidential Level and AMBER alerts. 379 * This method assumes that the message ID has already been checked for CMAS type. 380 * @return the CMAS urgency as defined in {@link SmsCbCmasInfo} 381 */ 382 private int getCmasUrgency() { 383 switch (mMessageIdentifier) { 384 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED: 385 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED_LANGUAGE: 386 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY: 387 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY_LANGUAGE: 388 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED: 389 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED_LANGUAGE: 390 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY: 391 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY_LANGUAGE: 392 return SmsCbCmasInfo.CMAS_URGENCY_IMMEDIATE; 393 394 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED: 395 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED_LANGUAGE: 396 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY: 397 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY_LANGUAGE: 398 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED: 399 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED_LANGUAGE: 400 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY: 401 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY_LANGUAGE: 402 return SmsCbCmasInfo.CMAS_URGENCY_EXPECTED; 403 404 default: 405 return SmsCbCmasInfo.CMAS_URGENCY_UNKNOWN; 406 } 407 } 408 409 /** 410 * Returns the certainty for a CMAS warning notification. This is only available for extreme 411 * and severe alerts, not for other types such as Presidential Level and AMBER alerts. 412 * This method assumes that the message ID has already been checked for CMAS type. 413 * @return the CMAS certainty as defined in {@link SmsCbCmasInfo} 414 */ 415 private int getCmasCertainty() { 416 switch (mMessageIdentifier) { 417 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED: 418 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED_LANGUAGE: 419 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED: 420 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED_LANGUAGE: 421 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED: 422 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED_LANGUAGE: 423 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED: 424 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED_LANGUAGE: 425 return SmsCbCmasInfo.CMAS_CERTAINTY_OBSERVED; 426 427 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY: 428 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY_LANGUAGE: 429 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY: 430 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY_LANGUAGE: 431 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY: 432 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY_LANGUAGE: 433 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY: 434 case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY_LANGUAGE: 435 return SmsCbCmasInfo.CMAS_CERTAINTY_LIKELY; 436 437 default: 438 return SmsCbCmasInfo.CMAS_CERTAINTY_UNKNOWN; 439 } 440 } 441 442 @Override 443 public String toString() { 444 return "SmsCbHeader{GS=" + mGeographicalScope + ", serialNumber=0x" + 445 Integer.toHexString(mSerialNumber) + 446 ", messageIdentifier=0x" + Integer.toHexString(mMessageIdentifier) + 447 ", DCS=0x" + Integer.toHexString(mDataCodingScheme) + 448 ", page " + mPageIndex + " of " + mNrOfPages + '}'; 449 } 450}