CdmaInboundSmsHandlerpublic class CdmaInboundSmsHandler extends com.android.internal.telephony.InboundSmsHandler Subclass of {@link InboundSmsHandler} for 3GPP2 type messages. |
Fields Summary |
---|
private final CdmaSMSDispatcher | mSmsDispatcher | private final CdmaServiceCategoryProgramHandler | mServiceCategoryProgramHandler | private byte[] | mLastDispatchedSmsFingerprint | private byte[] | mLastAcknowledgedSmsFingerprint | private final boolean | mCheckForDuplicatePortsInOmadmWapPush |
Constructors Summary |
---|
private CdmaInboundSmsHandler(android.content.Context context, com.android.internal.telephony.SmsStorageMonitor storageMonitor, com.android.internal.telephony.PhoneBase phone, CdmaSMSDispatcher smsDispatcher)Create a new inbound SMS handler for CDMA.
super("CdmaInboundSmsHandler", context, storageMonitor, phone,
CellBroadcastHandler.makeCellBroadcastHandler(context, phone));
mSmsDispatcher = smsDispatcher;
mServiceCategoryProgramHandler = CdmaServiceCategoryProgramHandler.makeScpHandler(context,
phone.mCi);
phone.mCi.setOnNewCdmaSms(getHandler(), EVENT_NEW_SMS, null);
|
Methods Summary |
---|
protected void | acknowledgeLastIncomingSms(boolean success, int result, android.os.Message response)Send an acknowledge message.
if (isInEmergencyCallMode()) {
return;
}
int causeCode = resultToCause(result);
mPhone.mCi.acknowledgeLastIncomingCdmaSms(success, causeCode, response);
if (causeCode == 0) {
mLastAcknowledgedSmsFingerprint = mLastDispatchedSmsFingerprint;
}
mLastDispatchedSmsFingerprint = null;
| private static boolean | checkDuplicatePortOmadmWapPush(byte[] origPdu, int index)Optional check to see if the received WapPush is an OMADM notification with erroneous
extra port fields.
- Some carriers make this mistake.
ex: MSGTYPE-TotalSegments-CurrentSegment
-SourcePortDestPort-SourcePortDestPort-OMADM PDU
index += 4;
byte[] omaPdu = new byte[origPdu.length - index];
System.arraycopy(origPdu, index, omaPdu, 0, omaPdu.length);
WspTypeDecoder pduDecoder = new WspTypeDecoder(omaPdu);
int wspIndex = 2;
// Process header length field
if (!pduDecoder.decodeUintvarInteger(wspIndex)) {
return false;
}
wspIndex += pduDecoder.getDecodedDataLength(); // advance to next field
// Process content type field
if (!pduDecoder.decodeContentType(wspIndex)) {
return false;
}
String mimeType = pduDecoder.getValueString();
return (WspTypeDecoder.CONTENT_TYPE_B_PUSH_SYNCML_NOTI.equals(mimeType));
| protected int | dispatchMessageRadioSpecific(com.android.internal.telephony.SmsMessageBase smsb)Process Cell Broadcast, Voicemail Notification, and other 3GPP/3GPP2-specific messages.
if (isInEmergencyCallMode()) {
return Activity.RESULT_OK;
}
SmsMessage sms = (SmsMessage) smsb;
boolean isBroadcastType = (SmsEnvelope.MESSAGE_TYPE_BROADCAST == sms.getMessageType());
// Handle CMAS emergency broadcast messages.
if (isBroadcastType) {
log("Broadcast type message");
SmsCbMessage cbMessage = sms.parseBroadcastSms();
if (cbMessage != null) {
mCellBroadcastHandler.dispatchSmsMessage(cbMessage);
} else {
loge("error trying to parse broadcast SMS");
}
return Intents.RESULT_SMS_HANDLED;
}
// Initialize fingerprint field, and see if we have a network duplicate SMS.
mLastDispatchedSmsFingerprint = sms.getIncomingSmsFingerprint();
if (mLastAcknowledgedSmsFingerprint != null &&
Arrays.equals(mLastDispatchedSmsFingerprint, mLastAcknowledgedSmsFingerprint)) {
return Intents.RESULT_SMS_HANDLED;
}
// Decode BD stream and set sms variables.
sms.parseSms();
int teleService = sms.getTeleService();
switch (teleService) {
case SmsEnvelope.TELESERVICE_VMN:
case SmsEnvelope.TELESERVICE_MWI:
// handle voicemail indication
handleVoicemailTeleservice(sms);
return Intents.RESULT_SMS_HANDLED;
case SmsEnvelope.TELESERVICE_WMT:
case SmsEnvelope.TELESERVICE_WEMT:
if (sms.isStatusReportMessage()) {
mSmsDispatcher.sendStatusReportMessage(sms);
return Intents.RESULT_SMS_HANDLED;
}
break;
case SmsEnvelope.TELESERVICE_SCPT:
mServiceCategoryProgramHandler.dispatchSmsMessage(sms);
return Intents.RESULT_SMS_HANDLED;
case SmsEnvelope.TELESERVICE_WAP:
// handled below, after storage check
break;
default:
loge("unsupported teleservice 0x" + Integer.toHexString(teleService));
return Intents.RESULT_SMS_UNSUPPORTED;
}
if (!mStorageMonitor.isStorageAvailable() &&
sms.getMessageClass() != SmsConstants.MessageClass.CLASS_0) {
// It's a storable message and there's no storage available. Bail.
// (See C.S0015-B v2.0 for a description of "Immediate Display"
// messages, which we represent as CLASS_0.)
return Intents.RESULT_SMS_OUT_OF_MEMORY;
}
if (SmsEnvelope.TELESERVICE_WAP == teleService) {
return processCdmaWapPdu(sms.getUserData(), sms.mMessageRef,
sms.getOriginatingAddress(), sms.getTimestampMillis());
}
return dispatchNormalMessage(smsb);
| private void | handleVoicemailTeleservice(SmsMessage sms)Handle {@link SmsEnvelope#TELESERVICE_VMN} and {@link SmsEnvelope#TELESERVICE_MWI}.
int voicemailCount = sms.getNumOfVoicemails();
if (DBG) log("Voicemail count=" + voicemailCount);
// range check
if (voicemailCount < 0) {
voicemailCount = -1;
} else if (voicemailCount > 99) {
// C.S0015-B v2, 4.5.12
// range: 0-99
voicemailCount = 99;
}
// update voice mail count in phone
mPhone.setVoiceMessageCount(voicemailCount);
// store voice mail count in preferences
storeVoiceMailCount();
| protected boolean | is3gpp2()Return true if this handler is for 3GPP2 messages; false for 3GPP format.
return true;
| private static boolean | isInEmergencyCallMode()Return whether the device is in Emergency Call Mode (only for 3GPP2).
String inEcm = SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
return "true".equals(inEcm);
| public static com.android.internal.telephony.cdma.CdmaInboundSmsHandler | makeInboundSmsHandler(android.content.Context context, com.android.internal.telephony.SmsStorageMonitor storageMonitor, com.android.internal.telephony.PhoneBase phone, CdmaSMSDispatcher smsDispatcher)Wait for state machine to enter startup state. We can't send any messages until then.
CdmaInboundSmsHandler handler = new CdmaInboundSmsHandler(context, storageMonitor,
phone, smsDispatcher);
handler.start();
return handler;
| protected void | onQuitting()Unregister for CDMA SMS.
mPhone.mCi.unSetOnNewCdmaSms(getHandler());
mCellBroadcastHandler.dispose();
if (DBG) log("unregistered for 3GPP2 SMS");
super.onQuitting();
| protected void | onUpdatePhoneObject(com.android.internal.telephony.PhoneBase phone)Called when the phone changes the default method updates mPhone
mStorageMonitor and mCellBroadcastHandler.updatePhoneObject.
Override if different or other behavior is desired.
super.onUpdatePhoneObject(phone);
mCellBroadcastHandler.updatePhoneObject(phone);
| private int | processCdmaWapPdu(byte[] pdu, int referenceNumber, java.lang.String address, long timestamp)Processes inbound messages that are in the WAP-WDP PDU format. See
wap-259-wdp-20010614-a section 6.5 for details on the WAP-WDP PDU format.
WDP segments are gathered until a datagram completes and gets dispatched.
int index = 0;
int msgType = (0xFF & pdu[index++]);
if (msgType != 0) {
log("Received a WAP SMS which is not WDP. Discard.");
return Intents.RESULT_SMS_HANDLED;
}
int totalSegments = (0xFF & pdu[index++]); // >= 1
int segment = (0xFF & pdu[index++]); // >= 0
if (segment >= totalSegments) {
loge("WDP bad segment #" + segment + " expecting 0-" + (totalSegments - 1));
return Intents.RESULT_SMS_HANDLED;
}
// Only the first segment contains sourcePort and destination Port
int sourcePort = 0;
int destinationPort = 0;
if (segment == 0) {
//process WDP segment
sourcePort = (0xFF & pdu[index++]) << 8;
sourcePort |= 0xFF & pdu[index++];
destinationPort = (0xFF & pdu[index++]) << 8;
destinationPort |= 0xFF & pdu[index++];
// Some carriers incorrectly send duplicate port fields in omadm wap pushes.
// If configured, check for that here
if (mCheckForDuplicatePortsInOmadmWapPush) {
if (checkDuplicatePortOmadmWapPush(pdu, index)) {
index = index + 4; // skip duplicate port fields
}
}
}
// Lookup all other related parts
log("Received WAP PDU. Type = " + msgType + ", originator = " + address
+ ", src-port = " + sourcePort + ", dst-port = " + destinationPort
+ ", ID = " + referenceNumber + ", segment# = " + segment + '/" + totalSegments);
// pass the user data portion of the PDU to the shared handler in SMSDispatcher
byte[] userData = new byte[pdu.length - index];
System.arraycopy(pdu, index, userData, 0, pdu.length - index);
InboundSmsTracker tracker = new InboundSmsTracker(userData, timestamp, destinationPort,
true, address, referenceNumber, segment, totalSegments, true);
return addTrackerToRawTableAndSendMessage(tracker);
| private static int | resultToCause(int rc)Convert Android result code to CDMA SMS failure cause.
switch (rc) {
case Activity.RESULT_OK:
case Intents.RESULT_SMS_HANDLED:
// Cause code is ignored on success.
return 0;
case Intents.RESULT_SMS_OUT_OF_MEMORY:
return CommandsInterface.CDMA_SMS_FAIL_CAUSE_RESOURCE_SHORTAGE;
case Intents.RESULT_SMS_UNSUPPORTED:
return CommandsInterface.CDMA_SMS_FAIL_CAUSE_INVALID_TELESERVICE_ID;
case Intents.RESULT_SMS_GENERIC_ERROR:
default:
return CommandsInterface.CDMA_SMS_FAIL_CAUSE_ENCODING_PROBLEM;
}
|
|