Home | History | Annotate | Download | only in stub
      1 /*
      2  * Copyright (C) 2018 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 
     17 package android.telephony.ims.stub;
     18 
     19 import android.annotation.IntDef;
     20 import android.annotation.SystemApi;
     21 import android.os.RemoteException;
     22 import android.telephony.SmsManager;
     23 import android.telephony.SmsMessage;
     24 import android.telephony.ims.aidl.IImsSmsListener;
     25 import android.util.Log;
     26 
     27 import java.lang.annotation.Retention;
     28 import java.lang.annotation.RetentionPolicy;
     29 
     30 /**
     31  * Base implementation for SMS over IMS.
     32  *
     33  * Any service wishing to provide SMS over IMS should extend this class and implement all methods
     34  * that the service supports.
     35  *
     36  * @hide
     37  */
     38 @SystemApi
     39 public class ImsSmsImplBase {
     40     private static final String LOG_TAG = "SmsImplBase";
     41 
     42     /** @hide */
     43     @IntDef({
     44             SEND_STATUS_OK,
     45             SEND_STATUS_ERROR,
     46             SEND_STATUS_ERROR_RETRY,
     47             SEND_STATUS_ERROR_FALLBACK
     48         })
     49     @Retention(RetentionPolicy.SOURCE)
     50     public @interface SendStatusResult {}
     51     /**
     52      * Message was sent successfully.
     53      */
     54     public static final int SEND_STATUS_OK = 1;
     55 
     56     /**
     57      * IMS provider failed to send the message and platform should not retry falling back to sending
     58      * the message using the radio.
     59      */
     60     public static final int SEND_STATUS_ERROR = 2;
     61 
     62     /**
     63      * IMS provider failed to send the message and platform should retry again after setting TP-RD
     64      * bit to high.
     65      */
     66     public static final int SEND_STATUS_ERROR_RETRY = 3;
     67 
     68     /**
     69      * IMS provider failed to send the message and platform should retry falling back to sending
     70      * the message using the radio.
     71      */
     72     public static final int SEND_STATUS_ERROR_FALLBACK = 4;
     73 
     74     /** @hide */
     75     @IntDef({
     76             DELIVER_STATUS_OK,
     77             DELIVER_STATUS_ERROR_GENERIC,
     78             DELIVER_STATUS_ERROR_NO_MEMORY,
     79             DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED
     80         })
     81     @Retention(RetentionPolicy.SOURCE)
     82     public @interface DeliverStatusResult {}
     83     /**
     84      * Message was delivered successfully.
     85      */
     86     public static final int DELIVER_STATUS_OK = 1;
     87 
     88     /**
     89      * Message was not delivered.
     90      */
     91     public static final int DELIVER_STATUS_ERROR_GENERIC = 2;
     92 
     93     /**
     94      * Message was not delivered due to lack of memory.
     95      */
     96     public static final int DELIVER_STATUS_ERROR_NO_MEMORY = 3;
     97 
     98     /**
     99      * Message was not delivered as the request is not supported.
    100      */
    101     public static final int DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED = 4;
    102 
    103     /** @hide */
    104     @IntDef({
    105             STATUS_REPORT_STATUS_OK,
    106             STATUS_REPORT_STATUS_ERROR
    107         })
    108     @Retention(RetentionPolicy.SOURCE)
    109     public @interface StatusReportResult {}
    110 
    111     /**
    112      * Status Report was set successfully.
    113      */
    114     public static final int STATUS_REPORT_STATUS_OK = 1;
    115 
    116     /**
    117      * Error while setting status report.
    118      */
    119     public static final int STATUS_REPORT_STATUS_ERROR = 2;
    120 
    121     // Lock for feature synchronization
    122     private final Object mLock = new Object();
    123     private IImsSmsListener mListener;
    124 
    125     /**
    126      * Registers a listener responsible for handling tasks like delivering messages.
    127      *
    128      * @param listener listener to register.
    129      *
    130      * @hide
    131      */
    132     public final void registerSmsListener(IImsSmsListener listener) {
    133         synchronized (mLock) {
    134             mListener = listener;
    135         }
    136     }
    137 
    138     /**
    139      * This method will be triggered by the platform when the user attempts to send an SMS. This
    140      * method should be implemented by the IMS providers to provide implementation of sending an SMS
    141      * over IMS.
    142      *
    143      * @param token unique token generated by the platform that should be used when triggering
    144      *             callbacks for this specific message.
    145      * @param messageRef the message reference.
    146      * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
    147      *               {@link SmsMessage#FORMAT_3GPP2}.
    148      * @param smsc the Short Message Service Center address.
    149      * @param isRetry whether it is a retry of an already attempted message or not.
    150      * @param pdu PDUs representing the contents of the message.
    151      */
    152     public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
    153             byte[] pdu) {
    154         // Base implementation returns error. Should be overridden.
    155         try {
    156             onSendSmsResult(token, messageRef, SEND_STATUS_ERROR,
    157                     SmsManager.RESULT_ERROR_GENERIC_FAILURE);
    158         } catch (RuntimeException e) {
    159             Log.e(LOG_TAG, "Can not send sms: " + e.getMessage());
    160         }
    161     }
    162 
    163     /**
    164      * This method will be triggered by the platform after
    165      * {@link #onSmsReceived(int, String, byte[])} has been called to deliver the result to the IMS
    166      * provider.
    167      *
    168      * @param token token provided in {@link #onSmsReceived(int, String, byte[])}
    169      * @param result result of delivering the message. Valid values are:
    170      *  {@link #DELIVER_STATUS_OK},
    171      *  {@link #DELIVER_STATUS_ERROR_GENERIC},
    172      *  {@link #DELIVER_STATUS_ERROR_NO_MEMORY},
    173      *  {@link #DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED}
    174      * @param messageRef the message reference
    175      */
    176     public void acknowledgeSms(int token, @DeliverStatusResult int messageRef, int result) {
    177         Log.e(LOG_TAG, "acknowledgeSms() not implemented.");
    178     }
    179 
    180     /**
    181      * This method will be triggered by the platform after
    182      * {@link #onSmsStatusReportReceived(int, int, String, byte[])} has been called to provide the
    183      * result to the IMS provider.
    184      *
    185      * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
    186      * @param result result of delivering the message. Valid values are:
    187      *  {@link #STATUS_REPORT_STATUS_OK},
    188      *  {@link #STATUS_REPORT_STATUS_ERROR}
    189      * @param messageRef the message reference
    190      */
    191     public void acknowledgeSmsReport(int token, int messageRef, @StatusReportResult int result) {
    192         Log.e(LOG_TAG, "acknowledgeSmsReport() not implemented.");
    193     }
    194 
    195     /**
    196      * This method should be triggered by the IMS providers when there is an incoming message. The
    197      * platform will deliver the message to the messages database and notify the IMS provider of the
    198      * result by calling {@link #acknowledgeSms(int, int, int)}.
    199      *
    200      * This method must not be called before {@link #onReady()} is called or the call will fail. If
    201      * the platform is not available, {@link #acknowledgeSms(int, int, int)} will be called with the
    202      * {@link #DELIVER_STATUS_ERROR_GENERIC} result code.
    203      * @param token unique token generated by IMS providers that the platform will use to trigger
    204      *              callbacks for this message.
    205      * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
    206      * {@link SmsMessage#FORMAT_3GPP2}.
    207      * @param pdu PDUs representing the contents of the message.
    208      * @throws RuntimeException if called before {@link #onReady()} is triggered.
    209      */
    210     public final void onSmsReceived(int token, String format, byte[] pdu) throws RuntimeException {
    211         synchronized (mLock) {
    212             if (mListener == null) {
    213                 throw new RuntimeException("Feature not ready.");
    214             }
    215             try {
    216                 mListener.onSmsReceived(token, format, pdu);
    217             } catch (RemoteException e) {
    218                 Log.e(LOG_TAG, "Can not deliver sms: " + e.getMessage());
    219                 SmsMessage message = SmsMessage.createFromPdu(pdu, format);
    220                 if (message != null && message.mWrappedSmsMessage != null) {
    221                     acknowledgeSms(token, message.mWrappedSmsMessage.mMessageRef,
    222                             DELIVER_STATUS_ERROR_GENERIC);
    223                 } else {
    224                     Log.w(LOG_TAG, "onSmsReceived: Invalid pdu entered.");
    225                     acknowledgeSms(token, 0, DELIVER_STATUS_ERROR_GENERIC);
    226                 }
    227             }
    228         }
    229     }
    230 
    231     /**
    232      * This method should be triggered by the IMS providers to pass the result of the sent message
    233      * to the platform.
    234      *
    235      * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
    236      * @param messageRef the message reference. Should be between 0 and 255 per TS.123.040
    237      * @param status result of sending the SMS. Valid values are:
    238      *  {@link #SEND_STATUS_OK},
    239      *  {@link #SEND_STATUS_ERROR},
    240      *  {@link #SEND_STATUS_ERROR_RETRY},
    241      *  {@link #SEND_STATUS_ERROR_FALLBACK},
    242      * @param reason reason in case status is failure. Valid values are:
    243      *  {@link SmsManager#RESULT_ERROR_NONE},
    244      *  {@link SmsManager#RESULT_ERROR_GENERIC_FAILURE},
    245      *  {@link SmsManager#RESULT_ERROR_RADIO_OFF},
    246      *  {@link SmsManager#RESULT_ERROR_NULL_PDU},
    247      *  {@link SmsManager#RESULT_ERROR_NO_SERVICE},
    248      *  {@link SmsManager#RESULT_ERROR_LIMIT_EXCEEDED},
    249      *  {@link SmsManager#RESULT_ERROR_FDN_CHECK_FAILURE},
    250      *  {@link SmsManager#RESULT_ERROR_SHORT_CODE_NOT_ALLOWED},
    251      *  {@link SmsManager#RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED},
    252      *  {@link SmsManager#RESULT_RADIO_NOT_AVAILABLE},
    253      *  {@link SmsManager#RESULT_NETWORK_REJECT},
    254      *  {@link SmsManager#RESULT_INVALID_ARGUMENTS},
    255      *  {@link SmsManager#RESULT_INVALID_STATE},
    256      *  {@link SmsManager#RESULT_NO_MEMORY},
    257      *  {@link SmsManager#RESULT_INVALID_SMS_FORMAT},
    258      *  {@link SmsManager#RESULT_SYSTEM_ERROR},
    259      *  {@link SmsManager#RESULT_MODEM_ERROR},
    260      *  {@link SmsManager#RESULT_NETWORK_ERROR},
    261      *  {@link SmsManager#RESULT_ENCODING_ERROR},
    262      *  {@link SmsManager#RESULT_INVALID_SMSC_ADDRESS},
    263      *  {@link SmsManager#RESULT_OPERATION_NOT_ALLOWED},
    264      *  {@link SmsManager#RESULT_INTERNAL_ERROR},
    265      *  {@link SmsManager#RESULT_NO_RESOURCES},
    266      *  {@link SmsManager#RESULT_CANCELLED},
    267      *  {@link SmsManager#RESULT_REQUEST_NOT_SUPPORTED}
    268      *
    269      * @throws RuntimeException if called before {@link #onReady()} is triggered or if the
    270      * connection to the framework is not available. If this happens attempting to send the SMS
    271      * should be aborted.
    272      */
    273     public final void onSendSmsResult(int token, int messageRef,  @SendStatusResult int status,
    274             int reason) throws RuntimeException {
    275         synchronized (mLock) {
    276             if (mListener == null) {
    277                 throw new RuntimeException("Feature not ready.");
    278             }
    279             try {
    280                 mListener.onSendSmsResult(token, messageRef, status, reason);
    281             } catch (RemoteException e) {
    282                 e.rethrowFromSystemServer();
    283             }
    284         }
    285     }
    286 
    287     /**
    288      * Sets the status report of the sent message.
    289      *
    290      * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
    291      * @param messageRef the message reference.
    292      * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
    293      * {@link SmsMessage#FORMAT_3GPP2}.
    294      * @param pdu PDUs representing the content of the status report.
    295      * @throws RuntimeException if called before {@link #onReady()} is triggered
    296      */
    297     public final void onSmsStatusReportReceived(int token, int messageRef, String format,
    298             byte[] pdu) throws RuntimeException{
    299         synchronized (mLock) {
    300             if (mListener == null) {
    301                 throw new RuntimeException("Feature not ready.");
    302             }
    303             try {
    304                 mListener.onSmsStatusReportReceived(token, messageRef, format, pdu);
    305             } catch (RemoteException e) {
    306                 Log.e(LOG_TAG, "Can not process sms status report: " + e.getMessage());
    307                 acknowledgeSmsReport(token, messageRef, STATUS_REPORT_STATUS_ERROR);
    308             }
    309         }
    310     }
    311 
    312     /**
    313      * Returns the SMS format. Default is {@link SmsMessage#FORMAT_3GPP} unless overridden by IMS
    314      * Provider.
    315      *
    316      * @return  the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
    317      * {@link SmsMessage#FORMAT_3GPP2}.
    318      */
    319     public String getSmsFormat() {
    320       return SmsMessage.FORMAT_3GPP;
    321     }
    322 
    323     /**
    324      * Called when ImsSmsImpl has been initialized and communication with the framework is set up.
    325      * Any attempt by this class to access the framework before this method is called will return
    326      * with a {@link RuntimeException}.
    327      */
    328     public void onReady() {
    329         // Base Implementation - Should be overridden
    330     }
    331 }
    332