Fields Summary |
---|
static final int | PDU_HEADER_LENGTHLength of SMS-CB header |
static final int | FORMAT_GSMGSM pdu format, as defined in 3gpp TS 23.041, section 9.4.1 |
static final int | FORMAT_UMTSUMTS pdu format, as defined in 3gpp TS 23.041, section 9.4.2 |
static final int | FORMAT_ETWS_PRIMARYGSM pdu format, as defined in 3gpp TS 23.041, section 9.4.1.3 |
private static final int | MESSAGE_TYPE_CBS_MESSAGEMessage type value as defined in 3gpp TS 25.324, section 11.1. |
private static final int | PDU_LENGTH_GSMLength of GSM pdus |
private static final int | PDU_LENGTH_ETWSMaximum length of ETWS primary message GSM pdus |
private final int | mGeographicalScope |
private final int | mSerialNumberThe serial number combines geographical scope, message code, and update number. |
private final int | mMessageIdentifierThe Message Identifier in 3GPP is the same as the Service Category in CDMA. |
private final int | mDataCodingScheme |
private final int | mPageIndex |
private final int | mNrOfPages |
private final int | mFormat |
private final android.telephony.SmsCbEtwsInfo | mEtwsInfoETWS warning notification info. |
private final android.telephony.SmsCbCmasInfo | mCmasInfoCMAS warning notification info. |
Constructors Summary |
---|
public SmsCbHeader(byte[] pdu)
if (pdu == null || pdu.length < PDU_HEADER_LENGTH) {
throw new IllegalArgumentException("Illegal PDU");
}
if (pdu.length <= PDU_LENGTH_GSM) {
// can be ETWS or GSM format.
// Per TS23.041 9.4.1.2 and 9.4.1.3.2, GSM and ETWS format both
// contain serial number which contains GS, Message Code, and Update Number
// per 9.4.1.2.1, and message identifier in same octets
mGeographicalScope = (pdu[0] & 0xc0) >>> 6;
mSerialNumber = ((pdu[0] & 0xff) << 8) | (pdu[1] & 0xff);
mMessageIdentifier = ((pdu[2] & 0xff) << 8) | (pdu[3] & 0xff);
if (isEtwsMessage() && pdu.length <= PDU_LENGTH_ETWS) {
mFormat = FORMAT_ETWS_PRIMARY;
mDataCodingScheme = -1;
mPageIndex = -1;
mNrOfPages = -1;
boolean emergencyUserAlert = (pdu[4] & 0x1) != 0;
boolean activatePopup = (pdu[5] & 0x80) != 0;
int warningType = (pdu[4] & 0xfe) >>> 1;
byte[] warningSecurityInfo;
// copy the Warning-Security-Information, if present
if (pdu.length > PDU_HEADER_LENGTH) {
warningSecurityInfo = Arrays.copyOfRange(pdu, 6, pdu.length);
} else {
warningSecurityInfo = null;
}
mEtwsInfo = new SmsCbEtwsInfo(warningType, emergencyUserAlert, activatePopup,
warningSecurityInfo);
mCmasInfo = null;
return; // skip the ETWS/CMAS initialization code for regular notifications
} else {
// GSM pdus are no more than 88 bytes
mFormat = FORMAT_GSM;
mDataCodingScheme = pdu[4] & 0xff;
// Check for invalid page parameter
int pageIndex = (pdu[5] & 0xf0) >>> 4;
int nrOfPages = pdu[5] & 0x0f;
if (pageIndex == 0 || nrOfPages == 0 || pageIndex > nrOfPages) {
pageIndex = 1;
nrOfPages = 1;
}
mPageIndex = pageIndex;
mNrOfPages = nrOfPages;
}
} else {
// UMTS pdus are always at least 90 bytes since the payload includes
// a number-of-pages octet and also one length octet per page
mFormat = FORMAT_UMTS;
int messageType = pdu[0];
if (messageType != MESSAGE_TYPE_CBS_MESSAGE) {
throw new IllegalArgumentException("Unsupported message type " + messageType);
}
mMessageIdentifier = ((pdu[1] & 0xff) << 8) | pdu[2] & 0xff;
mGeographicalScope = (pdu[3] & 0xc0) >>> 6;
mSerialNumber = ((pdu[3] & 0xff) << 8) | (pdu[4] & 0xff);
mDataCodingScheme = pdu[5] & 0xff;
// We will always consider a UMTS message as having one single page
// since there's only one instance of the header, even though the
// actual payload may contain several pages.
mPageIndex = 1;
mNrOfPages = 1;
}
if (isEtwsMessage()) {
boolean emergencyUserAlert = isEtwsEmergencyUserAlert();
boolean activatePopup = isEtwsPopupAlert();
int warningType = getEtwsWarningType();
mEtwsInfo = new SmsCbEtwsInfo(warningType, emergencyUserAlert, activatePopup, null);
mCmasInfo = null;
} else if (isCmasMessage()) {
int messageClass = getCmasMessageClass();
int severity = getCmasSeverity();
int urgency = getCmasUrgency();
int certainty = getCmasCertainty();
mEtwsInfo = null;
mCmasInfo = new SmsCbCmasInfo(messageClass, SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN,
SmsCbCmasInfo.CMAS_RESPONSE_TYPE_UNKNOWN, severity, urgency, certainty);
} else {
mEtwsInfo = null;
mCmasInfo = null;
}
|
Methods Summary |
---|
private int | getCmasCertainty()Returns the certainty for a CMAS warning notification. This is only available for extreme
and severe alerts, not for other types such as Presidential Level and AMBER alerts.
This method assumes that the message ID has already been checked for CMAS type.
switch (mMessageIdentifier) {
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED:
return SmsCbCmasInfo.CMAS_CERTAINTY_OBSERVED;
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY:
return SmsCbCmasInfo.CMAS_CERTAINTY_LIKELY;
default:
return SmsCbCmasInfo.CMAS_CERTAINTY_UNKNOWN;
}
|
android.telephony.SmsCbCmasInfo | getCmasInfo()
return mCmasInfo;
|
private int | getCmasMessageClass()Returns the message class for a CMAS warning notification.
This method assumes that the message ID has already been checked for CMAS type.
switch (mMessageIdentifier) {
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL:
return SmsCbCmasInfo.CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT;
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY:
return SmsCbCmasInfo.CMAS_CLASS_EXTREME_THREAT;
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY:
return SmsCbCmasInfo.CMAS_CLASS_SEVERE_THREAT;
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY:
return SmsCbCmasInfo.CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY;
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST:
return SmsCbCmasInfo.CMAS_CLASS_REQUIRED_MONTHLY_TEST;
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXERCISE:
return SmsCbCmasInfo.CMAS_CLASS_CMAS_EXERCISE;
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE:
return SmsCbCmasInfo.CMAS_CLASS_OPERATOR_DEFINED_USE;
default:
return SmsCbCmasInfo.CMAS_CLASS_UNKNOWN;
}
|
private int | getCmasSeverity()Returns the severity for a CMAS warning notification. This is only available for extreme
and severe alerts, not for other types such as Presidential Level and AMBER alerts.
This method assumes that the message ID has already been checked for CMAS type.
switch (mMessageIdentifier) {
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY:
return SmsCbCmasInfo.CMAS_SEVERITY_EXTREME;
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY:
return SmsCbCmasInfo.CMAS_SEVERITY_SEVERE;
default:
return SmsCbCmasInfo.CMAS_SEVERITY_UNKNOWN;
}
|
private int | getCmasUrgency()Returns the urgency for a CMAS warning notification. This is only available for extreme
and severe alerts, not for other types such as Presidential Level and AMBER alerts.
This method assumes that the message ID has already been checked for CMAS type.
switch (mMessageIdentifier) {
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY:
return SmsCbCmasInfo.CMAS_URGENCY_IMMEDIATE;
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED:
case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY:
return SmsCbCmasInfo.CMAS_URGENCY_EXPECTED;
default:
return SmsCbCmasInfo.CMAS_URGENCY_UNKNOWN;
}
|
int | getDataCodingScheme()
return mDataCodingScheme;
|
android.telephony.SmsCbEtwsInfo | getEtwsInfo()
return mEtwsInfo;
|
private int | getEtwsWarningType()Returns the warning type for an ETWS warning notification.
This method assumes that the message ID has already been checked for ETWS type.
return mMessageIdentifier - SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_WARNING;
|
int | getGeographicalScope()
return mGeographicalScope;
|
int | getNumberOfPages()
return mNrOfPages;
|
int | getPageIndex()
return mPageIndex;
|
int | getSerialNumber()
return mSerialNumber;
|
int | getServiceCategory()
return mMessageIdentifier;
|
private boolean | isCmasMessage()Return whether this message is a CMAS emergency message type.
return mMessageIdentifier >= SmsCbConstants.MESSAGE_ID_CMAS_FIRST_IDENTIFIER
&& mMessageIdentifier <= SmsCbConstants.MESSAGE_ID_CMAS_LAST_IDENTIFIER;
|
boolean | isEmergencyMessage()Return whether this broadcast is an emergency (PWS) message type.
return mMessageIdentifier >= SmsCbConstants.MESSAGE_ID_PWS_FIRST_IDENTIFIER
&& mMessageIdentifier <= SmsCbConstants.MESSAGE_ID_PWS_LAST_IDENTIFIER;
|
private boolean | isEtwsEmergencyUserAlert()Return whether the emergency user alert flag is set for an ETWS warning notification.
This method assumes that the message ID has already been checked for ETWS type.
return (mSerialNumber & SmsCbConstants.SERIAL_NUMBER_ETWS_EMERGENCY_USER_ALERT) != 0;
|
private boolean | isEtwsMessage()Return whether this broadcast is an ETWS emergency message type.
return (mMessageIdentifier & SmsCbConstants.MESSAGE_ID_ETWS_TYPE_MASK)
== SmsCbConstants.MESSAGE_ID_ETWS_TYPE;
|
private boolean | isEtwsPopupAlert()Return whether the popup alert flag is set for an ETWS warning notification.
This method assumes that the message ID has already been checked for ETWS type.
return (mSerialNumber & SmsCbConstants.SERIAL_NUMBER_ETWS_ACTIVATE_POPUP) != 0;
|
boolean | isEtwsPrimaryNotification()Return whether this broadcast is an ETWS primary notification.
return mFormat == FORMAT_ETWS_PRIMARY;
|
boolean | isUmtsFormat()Return whether this broadcast is in UMTS format.
return mFormat == FORMAT_UMTS;
|
public java.lang.String | toString()
return "SmsCbHeader{GS=" + mGeographicalScope + ", serialNumber=0x" +
Integer.toHexString(mSerialNumber) +
", messageIdentifier=0x" + Integer.toHexString(mMessageIdentifier) +
", DCS=0x" + Integer.toHexString(mDataCodingScheme) +
", page " + mPageIndex + " of " + mNrOfPages + '}";
|