Home | History | Annotate | Download | only in carrier
      1 /*
      2  * Copyright (C) 2014 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.service.carrier;
     18 
     19 import android.annotation.NonNull;
     20 import android.annotation.Nullable;
     21 import android.annotation.SdkConstant;
     22 import android.app.Service;
     23 import android.content.Intent;
     24 import android.net.Uri;
     25 import android.os.IBinder;
     26 import android.os.RemoteException;
     27 
     28 import java.util.List;
     29 
     30 /**
     31  * A service that receives calls from the system when new SMS and MMS are
     32  * sent or received.
     33  * <p>To extend this class, you must declare the service in your manifest file with
     34  * the {@link android.Manifest.permission#BIND_CARRIER_SERVICES} permission
     35  * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
     36  * <pre>
     37  * &lt;service android:name=".MyMessagingService"
     38  *          android:label="&#64;string/service_name"
     39  *          android:permission="android.permission.BIND_CARRIER_SERVICES">
     40  *     &lt;intent-filter>
     41  *         &lt;action android:name="android.service.carrier.CarrierMessagingService" />
     42  *     &lt;/intent-filter>
     43  * &lt;/service></pre>
     44  */
     45 public abstract class CarrierMessagingService extends Service {
     46     /**
     47      * The {@link android.content.Intent} that must be declared as handled by the service.
     48      */
     49     @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
     50     public static final String SERVICE_INTERFACE
     51             = "android.service.carrier.CarrierMessagingService";
     52 
     53     /**
     54      * The default bitmask value passed to the callback of {@link #onReceiveTextSms} with all
     55      * {@code RECEIVE_OPTIONS_x} flags cleared to indicate that the message should be kept and a
     56      * new message notification should be shown.
     57      *
     58      * @see #RECEIVE_OPTIONS_DROP
     59      * @see #RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE
     60      */
     61     public static final int RECEIVE_OPTIONS_DEFAULT = 0;
     62 
     63     /**
     64      * Used to set the flag in the bitmask passed to the callback of {@link #onReceiveTextSms} to
     65      * indicate that the inbound SMS should be dropped.
     66      */
     67     public static final int RECEIVE_OPTIONS_DROP = 0x1;
     68 
     69     /**
     70      * Used to set the flag in the bitmask passed to the callback of {@link #onReceiveTextSms} to
     71      * indicate that a new message notification should not be shown to the user when the
     72      * credential-encrypted storage of the device is not available before the user unlocks the
     73      * phone. It is only applicable to devices that support file-based encryption.
     74      */
     75     public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE = 0x2;
     76 
     77     /**
     78      * Indicates that an SMS or MMS message was successfully sent.
     79      */
     80     public static final int SEND_STATUS_OK = 0;
     81 
     82     /**
     83      * SMS/MMS sending failed. We should retry via the carrier network.
     84      */
     85     public static final int SEND_STATUS_RETRY_ON_CARRIER_NETWORK = 1;
     86 
     87     /**
     88      * SMS/MMS sending failed. We should not retry via the carrier network.
     89      */
     90     public static final int SEND_STATUS_ERROR = 2;
     91 
     92     /**
     93      * Successfully downloaded an MMS message.
     94      */
     95     public static final int DOWNLOAD_STATUS_OK = 0;
     96 
     97     /**
     98      * MMS downloading failed. We should retry via the carrier network.
     99      */
    100     public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1;
    101 
    102     /**
    103      * MMS downloading failed. We should not retry via the carrier network.
    104      */
    105     public static final int DOWNLOAD_STATUS_ERROR = 2;
    106 
    107     /**
    108      * Flag to request SMS delivery status report.
    109      */
    110     public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1;
    111 
    112     private final ICarrierMessagingWrapper mWrapper = new ICarrierMessagingWrapper();
    113 
    114     /**
    115      * Override this method to filter inbound SMS messages.
    116      *
    117      * @param pdu the PDUs of the message
    118      * @param format the format of the PDUs, typically "3gpp" or "3gpp2"
    119      * @param destPort the destination port of a binary SMS, this will be -1 for text SMS
    120      * @param subId SMS subscription ID of the SIM
    121      * @param callback result callback. Call with {@code true} to keep an inbound SMS message and
    122      *        deliver to SMS apps, and {@code false} to drop the message.
    123      * @deprecated Use {@link #onReceiveTextSms} instead.
    124      */
    125     @Deprecated
    126     public void onFilterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort,
    127             int subId, @NonNull ResultCallback<Boolean> callback) {
    128         // optional
    129         try {
    130             callback.onReceiveResult(true);
    131         } catch (RemoteException ex) {
    132         }
    133     }
    134 
    135     /**
    136      * Override this method to filter inbound SMS messages.
    137      *
    138      * <p>This method will be called once for every incoming text SMS. You can invoke the callback
    139      * with a bitmask to tell the platform how to handle the SMS. For a SMS received on a
    140      * file-based encryption capable device while the credential-encrypted storage is not available,
    141      * this method will be called for the second time when the credential-encrypted storage becomes
    142      * available after the user unlocks the phone, if the bit {@link #RECEIVE_OPTIONS_DROP} is not
    143      * set when invoking the callback.
    144      *
    145      * @param pdu the PDUs of the message
    146      * @param format the format of the PDUs, typically "3gpp" or "3gpp2"
    147      * @param destPort the destination port of a binary SMS, this will be -1 for text SMS
    148      * @param subId SMS subscription ID of the SIM
    149      * @param callback result callback. Call with a bitmask integer to indicate how the incoming
    150      *        text SMS should be handled by the platform. Use {@link #RECEIVE_OPTIONS_DROP} and
    151      *        {@link #RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE}
    152      *        to set the flags in the bitmask.
    153      */
    154     public void onReceiveTextSms(@NonNull MessagePdu pdu, @NonNull String format,
    155             int destPort, int subId, @NonNull final ResultCallback<Integer> callback) {
    156         onFilterSms(pdu, format, destPort, subId, new ResultCallback<Boolean>() {
    157             @Override
    158             public void onReceiveResult(Boolean result) throws RemoteException {
    159                 callback.onReceiveResult(result ? RECEIVE_OPTIONS_DEFAULT : RECEIVE_OPTIONS_DROP
    160                     | RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE);
    161             }
    162         });
    163     }
    164 
    165     /**
    166      * Override this method to intercept text SMSs sent from the device.
    167      * @deprecated Override {@link #onSendTextSms} below instead.
    168      *
    169      * @param text the text to send
    170      * @param subId SMS subscription ID of the SIM
    171      * @param destAddress phone number of the recipient of the message
    172      * @param callback result callback. Call with a {@link SendSmsResult}.
    173      */
    174     @Deprecated
    175     public void onSendTextSms(
    176             @NonNull String text, int subId, @NonNull String destAddress,
    177             @NonNull ResultCallback<SendSmsResult> callback) {
    178         // optional
    179         try {
    180             callback.onReceiveResult(new SendSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0));
    181         } catch (RemoteException ex) {
    182         }
    183     }
    184 
    185     /**
    186      * Override this method to intercept text SMSs sent from the device.
    187      *
    188      * @param text the text to send
    189      * @param subId SMS subscription ID of the SIM
    190      * @param destAddress phone number of the recipient of the message
    191      * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and
    192      *        {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}.
    193      * @param callback result callback. Call with a {@link SendSmsResult}.
    194      */
    195     public void onSendTextSms(
    196             @NonNull String text, int subId, @NonNull String destAddress,
    197             int sendSmsFlag, @NonNull ResultCallback<SendSmsResult> callback) {
    198         // optional
    199         onSendTextSms(text, subId, destAddress, callback);
    200     }
    201 
    202     /**
    203      * Override this method to intercept binary SMSs sent from the device.
    204      * @deprecated Override {@link #onSendDataSms} below instead.
    205      *
    206      * @param data the binary content
    207      * @param subId SMS subscription ID of the SIM
    208      * @param destAddress phone number of the recipient of the message
    209      * @param destPort the destination port
    210      * @param callback result callback. Call with a {@link SendSmsResult}.
    211      */
    212     @Deprecated
    213     public void onSendDataSms(@NonNull byte[] data, int subId,
    214             @NonNull String destAddress, int destPort,
    215             @NonNull ResultCallback<SendSmsResult> callback) {
    216         // optional
    217         try {
    218             callback.onReceiveResult(new SendSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0));
    219         } catch (RemoteException ex) {
    220         }
    221     }
    222 
    223     /**
    224      * Override this method to intercept binary SMSs sent from the device.
    225      *
    226      * @param data the binary content
    227      * @param subId SMS subscription ID of the SIM
    228      * @param destAddress phone number of the recipient of the message
    229      * @param destPort the destination port
    230      * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and
    231      *        {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}.
    232      * @param callback result callback. Call with a {@link SendSmsResult}.
    233      */
    234     public void onSendDataSms(@NonNull byte[] data, int subId,
    235             @NonNull String destAddress, int destPort, int sendSmsFlag,
    236             @NonNull ResultCallback<SendSmsResult> callback) {
    237         // optional
    238         onSendDataSms(data, subId, destAddress, destPort, callback);
    239     }
    240 
    241     /**
    242      * Override this method to intercept long SMSs sent from the device.
    243      * @deprecated Override {@link #onSendMultipartTextSms} below instead.
    244      *
    245      * @param parts a {@link List} of the message parts
    246      * @param subId SMS subscription ID of the SIM
    247      * @param destAddress phone number of the recipient of the message
    248      * @param callback result callback. Call with a {@link SendMultipartSmsResult}.
    249      */
    250     @Deprecated
    251     public void onSendMultipartTextSms(@NonNull List<String> parts,
    252             int subId, @NonNull String destAddress,
    253             @NonNull ResultCallback<SendMultipartSmsResult> callback) {
    254         // optional
    255         try {
    256             callback.onReceiveResult(
    257                     new SendMultipartSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, null));
    258         } catch (RemoteException ex) {
    259         }
    260     }
    261 
    262     /**
    263      * Override this method to intercept long SMSs sent from the device.
    264      *
    265      * @param parts a {@link List} of the message parts
    266      * @param subId SMS subscription ID of the SIM
    267      * @param destAddress phone number of the recipient of the message
    268      * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and
    269      *        {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}.
    270      * @param callback result callback. Call with a {@link SendMultipartSmsResult}.
    271      */
    272     public void onSendMultipartTextSms(@NonNull List<String> parts,
    273             int subId, @NonNull String destAddress, int sendSmsFlag,
    274             @NonNull ResultCallback<SendMultipartSmsResult> callback) {
    275         // optional
    276         onSendMultipartTextSms(parts, subId, destAddress, callback);
    277     }
    278 
    279     /**
    280      * Override this method to intercept MMSs sent from the device.
    281      *
    282      * @param pduUri the content provider URI of the PDU to send
    283      * @param subId SMS subscription ID of the SIM
    284      * @param location the optional URI to send this MMS PDU. If this is {code null},
    285      *        the PDU should be sent to the default MMSC URL.
    286      * @param callback result callback. Call with a {@link SendMmsResult}.
    287      */
    288     public void onSendMms(@NonNull Uri pduUri, int subId,
    289             @Nullable Uri location, @NonNull ResultCallback<SendMmsResult> callback) {
    290         // optional
    291         try {
    292             callback.onReceiveResult(new SendMmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, null));
    293         } catch (RemoteException ex) {
    294         }
    295     }
    296 
    297     /**
    298      * Override this method to download MMSs received.
    299      *
    300      * @param contentUri the content provider URI of the PDU to be downloaded.
    301      * @param subId SMS subscription ID of the SIM
    302      * @param location the URI of the message to be downloaded.
    303      * @param callback result callback. Call with a status code which is one of
    304      *        {@link #DOWNLOAD_STATUS_OK},
    305      *        {@link #DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK}, or {@link #DOWNLOAD_STATUS_ERROR}.
    306      */
    307     public void onDownloadMms(@NonNull Uri contentUri, int subId, @NonNull Uri location,
    308             @NonNull ResultCallback<Integer> callback) {
    309         // optional
    310         try {
    311             callback.onReceiveResult(DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK);
    312         } catch (RemoteException ex) {
    313         }
    314     }
    315 
    316     @Override
    317     public @Nullable IBinder onBind(@NonNull Intent intent) {
    318         if (!SERVICE_INTERFACE.equals(intent.getAction())) {
    319             return null;
    320         }
    321         return mWrapper;
    322     }
    323 
    324     /**
    325      * The result of sending an MMS.
    326      */
    327     public static final class SendMmsResult {
    328         private int mSendStatus;
    329         private byte[] mSendConfPdu;
    330 
    331         /**
    332          * Constructs a SendMmsResult with the MMS send result, and the SendConf PDU.
    333          *
    334          * @param sendStatus send status, one of {@link #SEND_STATUS_OK},
    335          *        {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and
    336          *        {@link #SEND_STATUS_ERROR}
    337          * @param sendConfPdu a possibly {code null} SendConf PDU, which confirms that the message
    338          *        was sent. sendConfPdu is ignored if the {@code result} is not
    339          *        {@link #SEND_STATUS_OK}.
    340          */
    341         public SendMmsResult(int sendStatus, @Nullable byte[] sendConfPdu) {
    342             mSendStatus = sendStatus;
    343             mSendConfPdu = sendConfPdu;
    344         }
    345 
    346         /**
    347          * Returns the send status of the just-sent MMS.
    348          *
    349          * @return the send status which is one of {@link #SEND_STATUS_OK},
    350          *         {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR}
    351          */
    352         public int getSendStatus() {
    353             return mSendStatus;
    354         }
    355 
    356         /**
    357          * Returns the SendConf PDU, which confirms that the message was sent.
    358          *
    359          * @return the SendConf PDU
    360          */
    361         public @Nullable byte[] getSendConfPdu() {
    362             return mSendConfPdu;
    363         }
    364     }
    365 
    366     /**
    367      * The result of sending an SMS.
    368      */
    369     public static final class SendSmsResult {
    370         private final int mSendStatus;
    371         private final int mMessageRef;
    372 
    373         /**
    374          * Constructs a SendSmsResult with the send status and message reference for the
    375          * just-sent SMS.
    376          *
    377          * @param sendStatus send status, one of {@link #SEND_STATUS_OK},
    378          *        {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR}.
    379          * @param messageRef message reference of the just-sent SMS. This field is applicable only
    380          *        if send status is {@link #SEND_STATUS_OK}.
    381          */
    382         public SendSmsResult(int sendStatus, int messageRef) {
    383             mSendStatus = sendStatus;
    384             mMessageRef = messageRef;
    385         }
    386 
    387         /**
    388          * Returns the message reference of the just-sent SMS.
    389          *
    390          * @return the message reference
    391          */
    392         public int getMessageRef() {
    393             return mMessageRef;
    394         }
    395 
    396         /**
    397          * Returns the send status of the just-sent SMS.
    398          *
    399          * @return the send status
    400          */
    401         public int getSendStatus() {
    402             return mSendStatus;
    403         }
    404     }
    405 
    406     /**
    407      * The result of sending a multipart SMS.
    408      */
    409     public static final class SendMultipartSmsResult {
    410         private final int mSendStatus;
    411         private final int[] mMessageRefs;
    412 
    413         /**
    414          * Constructs a SendMultipartSmsResult with the send status and message references for the
    415          * just-sent multipart SMS.
    416          *
    417          * @param sendStatus send status, one of {@link #SEND_STATUS_OK},
    418          *        {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR}.
    419          * @param messageRefs an array of message references, one for each part of the
    420          *        multipart SMS. This field is applicable only if send status is
    421          *        {@link #SEND_STATUS_OK}.
    422          */
    423         public SendMultipartSmsResult(int sendStatus, @Nullable int[] messageRefs) {
    424             mSendStatus = sendStatus;
    425             mMessageRefs = messageRefs;
    426         }
    427 
    428         /**
    429          * Returns the message references of the just-sent multipart SMS.
    430          *
    431          * @return the message references, one for each part of the multipart SMS
    432          */
    433         public @Nullable int[] getMessageRefs() {
    434             return mMessageRefs;
    435         }
    436 
    437         /**
    438          * Returns the send status of the just-sent SMS.
    439          *
    440          * @return the send status
    441          */
    442         public int getSendStatus() {
    443             return mSendStatus;
    444         }
    445     }
    446 
    447     /**
    448      * A callback interface used to provide results asynchronously.
    449      */
    450     public interface ResultCallback<T> {
    451         /**
    452          * Invoked when the result is available.
    453          *
    454          * @param result the result
    455          */
    456         public void onReceiveResult(@NonNull T result) throws RemoteException;
    457     };
    458 
    459     /**
    460      * A wrapper around ICarrierMessagingService to enable the carrier messaging app to implement
    461      * methods it cares about in the {@link ICarrierMessagingService} interface.
    462      */
    463     private class ICarrierMessagingWrapper extends ICarrierMessagingService.Stub {
    464         @Override
    465         public void filterSms(MessagePdu pdu, String format, int destPort,
    466                               int subId, final ICarrierMessagingCallback callback) {
    467             onReceiveTextSms(pdu, format, destPort, subId,
    468                 new ResultCallback<Integer>() {
    469                     @Override
    470                     public void onReceiveResult(Integer options) throws RemoteException {
    471                         callback.onFilterComplete(options);
    472                     }
    473                 });
    474         }
    475 
    476         @Override
    477         public void sendTextSms(String text, int subId, String destAddress,
    478                 int sendSmsFlag, final ICarrierMessagingCallback callback) {
    479             onSendTextSms(text, subId, destAddress, sendSmsFlag,
    480                     new ResultCallback<SendSmsResult>() {
    481                     @Override
    482                     public void onReceiveResult(final SendSmsResult result) throws RemoteException {
    483                         callback.onSendSmsComplete(result.getSendStatus(), result.getMessageRef());
    484                     }
    485                 });
    486         }
    487 
    488         @Override
    489         public void sendDataSms(byte[] data, int subId, String destAddress, int destPort,
    490                 int sendSmsFlag, final ICarrierMessagingCallback callback) {
    491             onSendDataSms(data, subId, destAddress, destPort, sendSmsFlag,
    492                     new ResultCallback<SendSmsResult>() {
    493                     @Override
    494                     public void onReceiveResult(final SendSmsResult result) throws RemoteException {
    495                         callback.onSendSmsComplete(result.getSendStatus(), result.getMessageRef());
    496                     }
    497                 });
    498         }
    499 
    500         @Override
    501         public void sendMultipartTextSms(List<String> parts, int subId, String destAddress,
    502                 int sendSmsFlag, final ICarrierMessagingCallback callback) {
    503             onSendMultipartTextSms(parts, subId, destAddress, sendSmsFlag,
    504                         new ResultCallback<SendMultipartSmsResult>() {
    505                                 @Override
    506                                 public void onReceiveResult(final SendMultipartSmsResult result)
    507                                         throws RemoteException {
    508                                     callback.onSendMultipartSmsComplete(
    509                                             result.getSendStatus(), result.getMessageRefs());
    510                                 }
    511                             });
    512         }
    513 
    514         @Override
    515         public void sendMms(Uri pduUri, int subId, Uri location,
    516                 final ICarrierMessagingCallback callback) {
    517             onSendMms(pduUri, subId, location, new ResultCallback<SendMmsResult>() {
    518                     @Override
    519                     public void onReceiveResult(final SendMmsResult result) throws RemoteException {
    520                         callback.onSendMmsComplete(result.getSendStatus(), result.getSendConfPdu());
    521                     }
    522                 });
    523         }
    524 
    525         @Override
    526         public void downloadMms(Uri pduUri, int subId, Uri location,
    527                 final ICarrierMessagingCallback callback) {
    528             onDownloadMms(pduUri, subId, location, new ResultCallback<Integer>() {
    529                     @Override
    530                     public void onReceiveResult(Integer result) throws RemoteException {
    531                         callback.onDownloadMmsComplete(result);
    532                     }
    533                 });
    534         }
    535     }
    536 }
    537