Some fixes to SMS processing in the framework.
Always process class 0 and other unstored SMS (eg, MWI). We were rejecting all SMS messages in storage full situations, but certain messages do not require storage. Also, notify apps when the framework rejects MT SMS, with new SMS_REJECTED_ACTION intent. b/2066775 b/2015906
This commit is contained in:
@@ -557,6 +557,23 @@ public final class Telephony {
|
|||||||
public static final String SIM_FULL_ACTION =
|
public static final String SIM_FULL_ACTION =
|
||||||
"android.provider.Telephony.SIM_FULL";
|
"android.provider.Telephony.SIM_FULL";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Broadcast Action: An incoming SMS has been rejected by the
|
||||||
|
* telephony framework. This intent is sent in lieu of any
|
||||||
|
* of the RECEIVED_ACTION intents. The intent will have the
|
||||||
|
* following extra value:</p>
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li><em>result</em> - An int result code, eg,
|
||||||
|
* <code>{@link #RESULT_SMS_OUT_OF_MEMORY}</code>,
|
||||||
|
* indicating the error returned to the network.</li>
|
||||||
|
* </ul>
|
||||||
|
|
||||||
|
*/
|
||||||
|
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||||
|
public static final String SMS_REJECTED_ACTION =
|
||||||
|
"android.provider.Telephony.SMS_REJECTED";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a
|
* Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a
|
||||||
* {@link #DATA_SMS_RECEIVED_ACTION} intent.
|
* {@link #DATA_SMS_RECEIVED_ACTION} intent.
|
||||||
|
|||||||
@@ -150,7 +150,8 @@ public abstract class SMSDispatcher extends Handler {
|
|||||||
private static SmsMessage mSmsMessage;
|
private static SmsMessage mSmsMessage;
|
||||||
private static SmsMessageBase mSmsMessageBase;
|
private static SmsMessageBase mSmsMessageBase;
|
||||||
private SmsMessageBase.SubmitPduBase mSubmitPduBase;
|
private SmsMessageBase.SubmitPduBase mSubmitPduBase;
|
||||||
private boolean mStorageAvailable = true;
|
|
||||||
|
protected boolean mStorageAvailable = true;
|
||||||
|
|
||||||
protected static int getNextConcatenatedRef() {
|
protected static int getNextConcatenatedRef() {
|
||||||
sConcatenatedRef += 1;
|
sConcatenatedRef += 1;
|
||||||
@@ -294,19 +295,15 @@ public abstract class SMSDispatcher extends Handler {
|
|||||||
|
|
||||||
sms = (SmsMessage) ar.result;
|
sms = (SmsMessage) ar.result;
|
||||||
try {
|
try {
|
||||||
if (mStorageAvailable) {
|
int result = dispatchMessage(sms.mWrappedSmsMessage);
|
||||||
int result = dispatchMessage(sms.mWrappedSmsMessage);
|
if (result != Activity.RESULT_OK) {
|
||||||
if (result != Activity.RESULT_OK) {
|
// RESULT_OK means that message was broadcast for app(s) to handle.
|
||||||
// RESULT_OK means that message was broadcast for app(s) to handle.
|
// Any other result, we should ack here.
|
||||||
// Any other result, we should ack here.
|
boolean handled = (result == Intents.RESULT_SMS_HANDLED);
|
||||||
boolean handled = (result == Intents.RESULT_SMS_HANDLED);
|
notifyAndAcknowledgeLastIncomingSms(handled, result, null);
|
||||||
acknowledgeLastIncomingSms(handled, result, null);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
acknowledgeLastIncomingSms(false, Intents.RESULT_SMS_OUT_OF_MEMORY, null);
|
|
||||||
}
|
}
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
acknowledgeLastIncomingSms(false, Intents.RESULT_SMS_GENERIC_ERROR, null);
|
notifyAndAcknowledgeLastIncomingSms(false, Intents.RESULT_SMS_GENERIC_ERROR, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -865,6 +862,25 @@ public abstract class SMSDispatcher extends Handler {
|
|||||||
protected abstract void acknowledgeLastIncomingSms(boolean success,
|
protected abstract void acknowledgeLastIncomingSms(boolean success,
|
||||||
int result, Message response);
|
int result, Message response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify interested apps if the framework has rejected an incoming SMS,
|
||||||
|
* and send an acknowledge message to the network.
|
||||||
|
* @param success indicates that last message was successfully received.
|
||||||
|
* @param result result code indicating any error
|
||||||
|
* @param response callback message sent when operation completes.
|
||||||
|
*/
|
||||||
|
private void notifyAndAcknowledgeLastIncomingSms(boolean success,
|
||||||
|
int result, Message response) {
|
||||||
|
if (!success) {
|
||||||
|
// broadcast SMS_REJECTED_ACTION intent
|
||||||
|
Intent intent = new Intent(Intents.SMS_REJECTED_ACTION);
|
||||||
|
intent.putExtra("result", result);
|
||||||
|
mWakeLock.acquire(WAKE_LOCK_TIMEOUT);
|
||||||
|
mContext.sendBroadcast(intent, "android.permission.RECEIVE_SMS");
|
||||||
|
}
|
||||||
|
acknowledgeLastIncomingSms(success, result, response);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a SmsTracker holds multi-part Sms
|
* Check if a SmsTracker holds multi-part Sms
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import android.preference.PreferenceManager;
|
|||||||
import android.util.Config;
|
import android.util.Config;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.telephony.SmsManager;
|
import android.telephony.SmsManager;
|
||||||
|
import android.telephony.SmsMessage.MessageClass;
|
||||||
|
|
||||||
import com.android.internal.telephony.TelephonyProperties;
|
import com.android.internal.telephony.TelephonyProperties;
|
||||||
import com.android.internal.telephony.CommandsInterface;
|
import com.android.internal.telephony.CommandsInterface;
|
||||||
@@ -91,23 +92,8 @@ final class CdmaSMSDispatcher extends SMSDispatcher {
|
|||||||
int teleService = sms.getTeleService();
|
int teleService = sms.getTeleService();
|
||||||
boolean handled = false;
|
boolean handled = false;
|
||||||
|
|
||||||
if ((sms.getUserData() == null) && (SmsEnvelope.TELESERVICE_MWI != teleService) &&
|
if ((SmsEnvelope.TELESERVICE_VMN == teleService) ||
|
||||||
(SmsEnvelope.TELESERVICE_VMN != teleService)) {
|
(SmsEnvelope.TELESERVICE_MWI == teleService)) {
|
||||||
if (Config.LOGD) {
|
|
||||||
Log.d(TAG, "Received SMS without user data");
|
|
||||||
}
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handled) {
|
|
||||||
return Intents.RESULT_SMS_HANDLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SmsEnvelope.TELESERVICE_WAP == teleService) {
|
|
||||||
return processCdmaWapPdu(sms.getUserData(), sms.messageRef,
|
|
||||||
sms.getOriginatingAddress());
|
|
||||||
} else if ((SmsEnvelope.TELESERVICE_VMN == teleService) ||
|
|
||||||
(SmsEnvelope.TELESERVICE_MWI == teleService)) {
|
|
||||||
// handling Voicemail
|
// handling Voicemail
|
||||||
int voicemailCount = sms.getNumOfVoicemails();
|
int voicemailCount = sms.getNumOfVoicemails();
|
||||||
Log.d(TAG, "Voicemail count=" + voicemailCount);
|
Log.d(TAG, "Voicemail count=" + voicemailCount);
|
||||||
@@ -118,9 +104,30 @@ final class CdmaSMSDispatcher extends SMSDispatcher {
|
|||||||
editor.putInt(CDMAPhone.VM_COUNT_CDMA, voicemailCount);
|
editor.putInt(CDMAPhone.VM_COUNT_CDMA, voicemailCount);
|
||||||
editor.commit();
|
editor.commit();
|
||||||
((CDMAPhone) mPhone).updateMessageWaitingIndicator(voicemailCount);
|
((CDMAPhone) mPhone).updateMessageWaitingIndicator(voicemailCount);
|
||||||
|
handled = true;
|
||||||
|
} else if ((sms.getUserData() == null)) {
|
||||||
|
if (Config.LOGD) {
|
||||||
|
Log.d(TAG, "Received SMS without user data");
|
||||||
|
}
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handled) {
|
||||||
return Intents.RESULT_SMS_HANDLED;
|
return Intents.RESULT_SMS_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mStorageAvailable && (sms.getMessageClass() != 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.messageRef,
|
||||||
|
sms.getOriginatingAddress());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO(cleanup): Why are we using a getter method for this
|
* TODO(cleanup): Why are we using a getter method for this
|
||||||
* (and for so many other sms fields)? Trivial getters and
|
* (and for so many other sms fields)? Trivial getters and
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import com.android.internal.telephony.SmsMessageBase;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import static android.telephony.SmsMessage.MessageClass;
|
||||||
|
|
||||||
final class GsmSMSDispatcher extends SMSDispatcher {
|
final class GsmSMSDispatcher extends SMSDispatcher {
|
||||||
private static final String TAG = "GSM";
|
private static final String TAG = "GSM";
|
||||||
@@ -111,6 +112,12 @@ final class GsmSMSDispatcher extends SMSDispatcher {
|
|||||||
return Intents.RESULT_SMS_HANDLED;
|
return Intents.RESULT_SMS_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mStorageAvailable && (sms.getMessageClass() != MessageClass.CLASS_0)) {
|
||||||
|
// It's a storable message and there's no storage available. Bail.
|
||||||
|
// (See TS 23.038 for a description of class 0 messages.)
|
||||||
|
return Intents.RESULT_SMS_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
SmsHeader smsHeader = sms.getUserDataHeader();
|
SmsHeader smsHeader = sms.getUserDataHeader();
|
||||||
// See if message is partial or port addressed.
|
// See if message is partial or port addressed.
|
||||||
if ((smsHeader == null) || (smsHeader.concatRef == null)) {
|
if ((smsHeader == null) || (smsHeader.concatRef == null)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user