Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ebaffc26 authored by Thomas Nguyen's avatar Thomas Nguyen
Browse files

Enhance SMS error handling

- Report SMS send result, internal send error, and network error code in SMS-outgoing metrics
- Update the mapping from RIL errors to SmsManager#Result

Bug: 250951137
Test: manual

Change-Id: I48c3d998a8f9510e444b773d7eb8391d99f376bf
parent 05230f38
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -277,6 +277,8 @@ message OutgoingSms {
    optional int32 retry_id = 13;
    optional int64 interval_millis = 14;
    optional int32 count = 15;
    optional int32 send_error_code = 16;
    optional int32 network_error_code = 17;

    // Internal use only
    optional int32 hashCode = 10001;
+1 −0
Original line number Diff line number Diff line
@@ -193,6 +193,7 @@ public class ImsSmsDispatcher extends SMSDispatcher {
                        SmsConstants.FORMAT_3GPP2.equals(getFormat()),
                        status == ImsSmsImplBase.SEND_STATUS_ERROR_FALLBACK,
                        reason,
                        networkReasonCode,
                        tracker.mMessageId,
                        tracker.isFromDefaultSmsApplication(mContext),
                        tracker.getInterval());
+71 −0
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -153,6 +156,17 @@ public abstract class SMSDispatcher extends Handler {
    /** Handle SIM loaded  */
    private static final int EVENT_SIM_LOADED = 18;

    /**
     * When this change is enabled, more specific values of SMS sending error code
     * {@link SmsManager#Result} will be returned to the SMS Apps.
     *
     * Refer to {@link SMSDispatcher#rilErrorToSmsManagerResult} fore more details of the new values
     * of SMS sending error code that will be returned.
     */
    @ChangeId
    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
    static final long ADD_MORE_SMS_SENDING_ERROR_CODES = 250017070L;

    @UnsupportedAppUsage
    protected Phone mPhone;
    @UnsupportedAppUsage
@@ -1049,6 +1063,27 @@ public abstract class SMSDispatcher extends Handler {
            SmsTracker tracker) {
        mSmsOutgoingErrorCodes.log("rilError: " + rilError
                + ", MessageId: " + SmsController.formatCrossStackMessageId(tracker.mMessageId));

        ApplicationInfo appInfo = tracker.getAppInfo();
        if (appInfo == null
                || !CompatChanges.isChangeEnabled(ADD_MORE_SMS_SENDING_ERROR_CODES, appInfo.uid)) {
            if (rilError == CommandException.Error.INVALID_RESPONSE
                    || rilError == CommandException.Error.SIM_PIN2
                    || rilError == CommandException.Error.SIM_PUK2
                    || rilError == CommandException.Error.SUBSCRIPTION_NOT_AVAILABLE
                    || rilError == CommandException.Error.SIM_ERR
                    || rilError == CommandException.Error.INVALID_SIM_STATE
                    || rilError == CommandException.Error.NO_SMS_TO_ACK
                    || rilError == CommandException.Error.SIM_BUSY
                    || rilError == CommandException.Error.SIM_FULL
                    || rilError == CommandException.Error.NO_SUBSCRIPTION
                    || rilError == CommandException.Error.NO_NETWORK_FOUND
                    || rilError == CommandException.Error.DEVICE_IN_USE
                    || rilError == CommandException.Error.ABORTED) {
                return SmsManager.RESULT_ERROR_GENERIC_FAILURE;
            }
        }

        switch (rilError) {
            case RADIO_NOT_AVAILABLE:
                return SmsManager.RESULT_RIL_RADIO_NOT_AVAILABLE;
@@ -1098,6 +1133,34 @@ public abstract class SMSDispatcher extends Handler {
                return SmsManager.RESULT_RIL_ACCESS_BARRED;
            case BLOCKED_DUE_TO_CALL:
                return SmsManager.RESULT_RIL_BLOCKED_DUE_TO_CALL;
            case INVALID_SMSC_ADDRESS:
                return SmsManager.RESULT_INVALID_SMSC_ADDRESS;
            case INVALID_RESPONSE:
                return SmsManager.RESULT_RIL_INVALID_RESPONSE;
            case SIM_PIN2:
                return SmsManager.RESULT_RIL_SIM_PIN2;
            case SIM_PUK2:
                return SmsManager.RESULT_RIL_SIM_PUK2;
            case SUBSCRIPTION_NOT_AVAILABLE:
                return SmsManager.RESULT_RIL_SUBSCRIPTION_NOT_AVAILABLE;
            case SIM_ERR:
                return SmsManager.RESULT_RIL_SIM_ERROR;
            case INVALID_SIM_STATE:
                return SmsManager.RESULT_RIL_INVALID_SIM_STATE;
            case NO_SMS_TO_ACK:
                return SmsManager.RESULT_RIL_NO_SMS_TO_ACK;
            case SIM_BUSY:
                return SmsManager.RESULT_RIL_SIM_BUSY;
            case SIM_FULL:
                return SmsManager.RESULT_RIL_SIM_FULL;
            case NO_SUBSCRIPTION:
                return SmsManager.RESULT_RIL_NO_SUBSCRIPTION;
            case NO_NETWORK_FOUND:
                return SmsManager.RESULT_RIL_NO_NETWORK_FOUND;
            case DEVICE_IN_USE:
                return SmsManager.RESULT_RIL_DEVICE_IN_USE;
            case ABORTED:
                return SmsManager.RESULT_RIL_ABORTED;
            default:
                Rlog.d(TAG, "rilErrorToSmsManagerResult: " + rilError + " "
                        + SmsController.formatCrossStackMessageId(tracker.mMessageId));
@@ -2214,6 +2277,14 @@ public abstract class SMSDispatcher extends Handler {
            return mAppInfo != null ? mAppInfo.packageName : null;
        }

        /**
         * Get the calling Application Info
         * @return Application Info
         */
        public ApplicationInfo getAppInfo() {
            return mAppInfo == null ? null : mAppInfo.applicationInfo;
        }

        /** Return if the SMS was originated from the default SMS application. */
        public boolean isFromDefaultSmsApplication(Context context) {
            if (mIsFromDefaultSmsApplication == null) {
+5 −3
Original line number Diff line number Diff line
@@ -29,8 +29,8 @@ import static com.android.internal.telephony.TelephonyStatsLog.IMS_REGISTRATION_
import static com.android.internal.telephony.TelephonyStatsLog.IMS_REGISTRATION_STATS;
import static com.android.internal.telephony.TelephonyStatsLog.IMS_REGISTRATION_TERMINATION;
import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS;
import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS;
import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SHORT_CODE_SMS;
import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS;
import static com.android.internal.telephony.TelephonyStatsLog.PER_SIM_STATUS;
import static com.android.internal.telephony.TelephonyStatsLog.PRESENCE_NOTIFY_EVENT;
import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS;
@@ -69,8 +69,8 @@ import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationStat
import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTermination;
import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.NetworkRequestsV2;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingShortCodeSms;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.PresenceNotifyEvent;
import com.android.internal.telephony.nano.PersistAtomsProto.RcsAcsProvisioningStats;
import com.android.internal.telephony.nano.PersistAtomsProto.RcsClientProvisioningStats;
@@ -829,7 +829,9 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
                sms.messageId,
                sms.retryId,
                sms.intervalMillis,
                sms.count);
                sms.count,
                sms.sendErrorCode,
                sms.networkErrorCode);
    }

    private static StatsEvent buildStatsEvent(DataCallSession dataCallSession) {
+19 −12
Original line number Diff line number Diff line
@@ -58,8 +58,8 @@ import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingShortCodeSms;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
import com.android.telephony.Rlog;

import java.util.Objects;
@@ -156,43 +156,50 @@ public class SmsStats {

    /** Create a new atom when an outgoing SMS is sent. */
    public void onOutgoingSms(boolean isOverIms, boolean is3gpp2, boolean fallbackToCs,
            @SmsManager.Result int errorCode, long messageId, boolean isFromDefaultApp,
            @SmsManager.Result int sendErrorCode, long messageId, boolean isFromDefaultApp,
            long intervalMillis) {
        onOutgoingSms(isOverIms, is3gpp2, fallbackToCs, errorCode, NO_ERROR_CODE,
        onOutgoingSms(isOverIms, is3gpp2, fallbackToCs, sendErrorCode, NO_ERROR_CODE,
                messageId, isFromDefaultApp, intervalMillis);
    }

    /** Create a new atom when an outgoing SMS is sent. */
    public void onOutgoingSms(boolean isOverIms, boolean is3gpp2, boolean fallbackToCs,
            @SmsManager.Result int errorCode, int radioSpecificErrorCode, long messageId,
            @SmsManager.Result int sendErrorCode, int networkErrorCode, long messageId,
            boolean isFromDefaultApp, long intervalMillis) {
        OutgoingSms proto =
                getOutgoingDefaultProto(is3gpp2, isOverIms, messageId, isFromDefaultApp,
                        intervalMillis);

        // The field errorCode is used for up-to-Android-13 devices. From Android 14, sendErrorCode
        // and networkErrorCode will be used. The field errorCode will be deprecated when most
        // devices use Android 14 or higher versions.
        if (isOverIms) {
            // Populate error code and result for IMS case
            proto.errorCode = errorCode;
            proto.errorCode = sendErrorCode;
            if (fallbackToCs) {
                proto.sendResult = OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR_FALLBACK;
            } else if (errorCode == SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY) {
            } else if (sendErrorCode == SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY) {
                proto.sendResult = OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR_RETRY;
            } else if (errorCode != SmsManager.RESULT_ERROR_NONE) {
            } else if (sendErrorCode != SmsManager.RESULT_ERROR_NONE) {
                proto.sendResult = OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR;
            }
        } else {
            // Populate error code and result for CS case
            if (errorCode == SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY) {
            if (sendErrorCode == SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY) {
                proto.sendResult = OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR_RETRY;
            } else if (errorCode != SmsManager.RESULT_ERROR_NONE) {
            } else if (sendErrorCode != SmsManager.RESULT_ERROR_NONE) {
                proto.sendResult = OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR;
            }
            proto.errorCode = radioSpecificErrorCode;
            if (errorCode == SmsManager.RESULT_RIL_RADIO_NOT_AVAILABLE
                    && radioSpecificErrorCode == NO_ERROR_CODE) {
            proto.errorCode = networkErrorCode;
            if (sendErrorCode == SmsManager.RESULT_RIL_RADIO_NOT_AVAILABLE
                    && networkErrorCode == NO_ERROR_CODE) {
                proto.errorCode = is3gpp2 ? NO_NETWORK_ERROR_3GPP2 : NO_NETWORK_ERROR_3GPP;
            }
        }

        proto.sendErrorCode = sendErrorCode;
        proto.networkErrorCode = networkErrorCode;

        mAtomsStorage.addOutgoingSms(proto);
    }