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.Parcel;
     27 import android.os.Parcelable;
     28 import android.os.RemoteException;
     29 
     30 import java.util.ArrayList;
     31 import java.util.List;
     32 
     33 /**
     34  * A service that receives calls from the system when new SMS and MMS are
     35  * sent or received.
     36  * <p>To extend this class, you must declare the service in your manifest file with
     37  * the {@link android.Manifest.permission#BIND_CARRIER_MESSAGING_SERVICE} permission
     38  * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
     39  * <pre>
     40  * &lt;service android:name=".MyMessagingService"
     41  *          android:label="&#64;string/service_name"
     42  *          android:permission="android.permission.BIND_CARRIER_MESSAGING_SERVICE">
     43  *     &lt;intent-filter>
     44  *         &lt;action android:name="android.service.carrier.CarrierMessagingService" />
     45  *     &lt;/intent-filter>
     46  * &lt;/service></pre>
     47  */
     48 public abstract class CarrierMessagingService extends Service {
     49     /**
     50      * The {@link android.content.Intent} that must be declared as handled by the service.
     51      */
     52     @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
     53     public static final String SERVICE_INTERFACE
     54             = "android.service.carrier.CarrierMessagingService";
     55 
     56     /**
     57      * Indicates that an SMS or MMS message was successfully sent.
     58      */
     59     public static final int SEND_STATUS_OK = 0;
     60 
     61     /**
     62      * SMS/MMS sending failed. We should retry via the carrier network.
     63      */
     64     public static final int SEND_STATUS_RETRY_ON_CARRIER_NETWORK = 1;
     65 
     66     /**
     67      * SMS/MMS sending failed. We should not retry via the carrier network.
     68      */
     69     public static final int SEND_STATUS_ERROR = 2;
     70 
     71     /**
     72      * Successfully downloaded an MMS message.
     73      */
     74     public static final int DOWNLOAD_STATUS_OK = 0;
     75 
     76     /**
     77      * MMS downloading failed. We should retry via the carrier network.
     78      */
     79     public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1;
     80 
     81     /**
     82      * MMS downloading failed. We should not retry via the carrier network.
     83      */
     84     public static final int DOWNLOAD_STATUS_ERROR = 2;
     85 
     86     private final ICarrierMessagingWrapper mWrapper = new ICarrierMessagingWrapper();
     87 
     88     /**
     89      * Override this method to filter inbound SMS messages.
     90      *
     91      * @param pdu the PDUs of the message
     92      * @param format the format of the PDUs, typically "3gpp" or "3gpp2"
     93      * @param destPort the destination port of a binary SMS, this will be -1 for text SMS
     94      * @param subId SMS subscription ID of the SIM
     95      * @param callback result callback. Call with {@code true} to keep an inbound SMS message and
     96      *        deliver to SMS apps, and {@code false} to drop the message.
     97      */
     98     public void onFilterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort,
     99             int subId, @NonNull ResultCallback<Boolean> callback) {
    100         // optional
    101         try {
    102             callback.onReceiveResult(true);
    103         } catch (RemoteException ex) {
    104         }
    105     }
    106 
    107     /**
    108      * Override this method to intercept text SMSs sent from the device.
    109      *
    110      * @param text the text to send
    111      * @param subId SMS subscription ID of the SIM
    112      * @param destAddress phone number of the recipient of the message
    113      * @param callback result callback. Call with a {@link SendSmsResult}.
    114      */
    115     public void onSendTextSms(
    116             @NonNull String text, int subId, @NonNull String destAddress,
    117             @NonNull ResultCallback<SendSmsResult> callback) {
    118         // optional
    119         try {
    120             callback.onReceiveResult(new SendSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0));
    121         } catch (RemoteException ex) {
    122         }
    123     }
    124 
    125     /**
    126      * Override this method to intercept binary SMSs sent from the device.
    127      *
    128      * @param data the binary content
    129      * @param subId SMS subscription ID of the SIM
    130      * @param destAddress phone number of the recipient of the message
    131      * @param destPort the destination port
    132      * @param callback result callback. Call with a {@link SendSmsResult}.
    133      */
    134     public void onSendDataSms(@NonNull byte[] data, int subId,
    135             @NonNull String destAddress, int destPort,
    136             @NonNull ResultCallback<SendSmsResult> callback) {
    137         // optional
    138         try {
    139             callback.onReceiveResult(new SendSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0));
    140         } catch (RemoteException ex) {
    141         }
    142     }
    143 
    144     /**
    145      * Override this method to intercept long SMSs sent from the device.
    146      *
    147      * @param parts a {@link List} of the message parts
    148      * @param subId SMS subscription ID of the SIM
    149      * @param destAddress phone number of the recipient of the message
    150      * @param callback result callback. Call with a {@link SendMultipartSmsResult}.
    151      */
    152     public void onSendMultipartTextSms(@NonNull List<String> parts,
    153             int subId, @NonNull String destAddress,
    154             @NonNull ResultCallback<SendMultipartSmsResult> callback) {
    155         // optional
    156         try {
    157             callback.onReceiveResult(
    158                     new SendMultipartSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, null));
    159         } catch (RemoteException ex) {
    160         }
    161     }
    162 
    163     /**
    164      * Override this method to intercept MMSs sent from the device.
    165      *
    166      * @param pduUri the content provider URI of the PDU to send
    167      * @param subId SMS subscription ID of the SIM
    168      * @param location the optional URI to send this MMS PDU. If this is {code null},
    169      *        the PDU should be sent to the default MMSC URL.
    170      * @param callback result callback. Call with a {@link SendMmsResult}.
    171      */
    172     public void onSendMms(@NonNull Uri pduUri, int subId,
    173             @Nullable Uri location, @NonNull ResultCallback<SendMmsResult> callback) {
    174         // optional
    175         try {
    176             callback.onReceiveResult(new SendMmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, null));
    177         } catch (RemoteException ex) {
    178         }
    179     }
    180 
    181     /**
    182      * Override this method to download MMSs received.
    183      *
    184      * @param contentUri the content provider URI of the PDU to be downloaded.
    185      * @param subId SMS subscription ID of the SIM
    186      * @param location the URI of the message to be downloaded.
    187      * @param callback result callback. Call with a status code which is one of
    188      *        {@link #DOWNLOAD_STATUS_OK},
    189      *        {@link #DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK}, or {@link #DOWNLOAD_STATUS_ERROR}.
    190      */
    191     public void onDownloadMms(@NonNull Uri contentUri, int subId, @NonNull Uri location,
    192             @NonNull ResultCallback<Integer> callback) {
    193         // optional
    194         try {
    195             callback.onReceiveResult(DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK);
    196         } catch (RemoteException ex) {
    197         }
    198     }
    199 
    200     @Override
    201     public @Nullable IBinder onBind(@NonNull Intent intent) {
    202         if (!SERVICE_INTERFACE.equals(intent.getAction())) {
    203             return null;
    204         }
    205         return mWrapper;
    206     }
    207 
    208     /**
    209      * The result of sending an MMS.
    210      */
    211     public static final class SendMmsResult {
    212         private int mSendStatus;
    213         private byte[] mSendConfPdu;
    214 
    215         /**
    216          * Constructs a SendMmsResult with the MMS send result, and the SendConf PDU.
    217          *
    218          * @param sendStatus send status, one of {@link #SEND_STATUS_OK},
    219          *        {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and
    220          *        {@link #SEND_STATUS_ERROR}
    221          * @param sendConfPdu a possibly {code null} SendConf PDU, which confirms that the message
    222          *        was sent. sendConfPdu is ignored if the {@code result} is not
    223          *        {@link #SEND_STATUS_OK}.
    224          */
    225         public SendMmsResult(int sendStatus, @Nullable byte[] sendConfPdu) {
    226             mSendStatus = sendStatus;
    227             mSendConfPdu = sendConfPdu;
    228         }
    229 
    230         /**
    231          * Returns the send status of the just-sent MMS.
    232          *
    233          * @return the send status which is one of {@link #SEND_STATUS_OK},
    234          *         {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR}
    235          */
    236         public int getSendStatus() {
    237             return mSendStatus;
    238         }
    239 
    240         /**
    241          * Returns the SendConf PDU, which confirms that the message was sent.
    242          *
    243          * @return the SendConf PDU
    244          */
    245         public @Nullable byte[] getSendConfPdu() {
    246             return mSendConfPdu;
    247         }
    248     }
    249 
    250     /**
    251      * The result of sending an SMS.
    252      */
    253     public static final class SendSmsResult {
    254         private final int mSendStatus;
    255         private final int mMessageRef;
    256 
    257         /**
    258          * Constructs a SendSmsResult with the send status and message reference for the
    259          * just-sent SMS.
    260          *
    261          * @param sendStatus send status, one of {@link #SEND_STATUS_OK},
    262          *        {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR}.
    263          * @param messageRef message reference of the just-sent SMS. This field is applicable only
    264          *        if send status is {@link #SEND_STATUS_OK}.
    265          */
    266         public SendSmsResult(int sendStatus, int messageRef) {
    267             mSendStatus = sendStatus;
    268             mMessageRef = messageRef;
    269         }
    270 
    271         /**
    272          * Returns the message reference of the just-sent SMS.
    273          *
    274          * @return the message reference
    275          */
    276         public int getMessageRef() {
    277             return mMessageRef;
    278         }
    279 
    280         /**
    281          * Returns the send status of the just-sent SMS.
    282          *
    283          * @return the send status
    284          */
    285         public int getSendStatus() {
    286             return mSendStatus;
    287         }
    288     }
    289 
    290     /**
    291      * The result of sending a multipart SMS.
    292      */
    293     public static final class SendMultipartSmsResult {
    294         private final int mSendStatus;
    295         private final int[] mMessageRefs;
    296 
    297         /**
    298          * Constructs a SendMultipartSmsResult with the send status and message references for the
    299          * just-sent multipart SMS.
    300          *
    301          * @param sendStatus send status, one of {@link #SEND_STATUS_OK},
    302          *        {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR}.
    303          * @param messageRefs an array of message references, one for each part of the
    304          *        multipart SMS. This field is applicable only if send status is
    305          *        {@link #SEND_STATUS_OK}.
    306          */
    307         public SendMultipartSmsResult(int sendStatus, @Nullable int[] messageRefs) {
    308             mSendStatus = sendStatus;
    309             mMessageRefs = messageRefs;
    310         }
    311 
    312         /**
    313          * Returns the message references of the just-sent multipart SMS.
    314          *
    315          * @return the message references, one for each part of the multipart SMS
    316          */
    317         public @Nullable int[] getMessageRefs() {
    318             return mMessageRefs;
    319         }
    320 
    321         /**
    322          * Returns the send status of the just-sent SMS.
    323          *
    324          * @return the send status
    325          */
    326         public int getSendStatus() {
    327             return mSendStatus;
    328         }
    329     }
    330 
    331     /**
    332      * A callback interface used to provide results asynchronously.
    333      */
    334     public interface ResultCallback<T> {
    335         /**
    336          * Invoked when the result is available.
    337          *
    338          * @param result the result
    339          */
    340         public void onReceiveResult(@NonNull T result) throws RemoteException;
    341     };
    342 
    343     /**
    344      * A wrapper around ICarrierMessagingService to enable the carrier messaging app to implement
    345      * methods it cares about in the {@link ICarrierMessagingService} interface.
    346      */
    347     private class ICarrierMessagingWrapper extends ICarrierMessagingService.Stub {
    348         @Override
    349         public void filterSms(MessagePdu pdu, String format, int destPort,
    350                               int subId, final ICarrierMessagingCallback callback) {
    351             onFilterSms(pdu, format, destPort, subId, new ResultCallback<Boolean>() {
    352                     @Override
    353                     public void onReceiveResult(final Boolean result) throws RemoteException {
    354                         callback.onFilterComplete(result);
    355                     }
    356                 });
    357         }
    358 
    359         @Override
    360         public void sendTextSms(String text, int subId, String destAddress,
    361                                 final ICarrierMessagingCallback callback) {
    362             onSendTextSms(text, subId, destAddress, new ResultCallback<SendSmsResult>() {
    363                     @Override
    364                     public void onReceiveResult(final SendSmsResult result) throws RemoteException {
    365                         callback.onSendSmsComplete(result.getSendStatus(), result.getMessageRef());
    366                     }
    367                 });
    368         }
    369 
    370         @Override
    371         public void sendDataSms(byte[] data, int subId, String destAddress, int destPort,
    372                                 final ICarrierMessagingCallback callback) {
    373             onSendDataSms(data, subId, destAddress, destPort, new ResultCallback<SendSmsResult>() {
    374                     @Override
    375                     public void onReceiveResult(final SendSmsResult result) throws RemoteException {
    376                         callback.onSendSmsComplete(result.getSendStatus(), result.getMessageRef());
    377                     }
    378                 });
    379         }
    380 
    381         @Override
    382         public void sendMultipartTextSms(List<String> parts, int subId, String destAddress,
    383                                          final ICarrierMessagingCallback callback) {
    384                 onSendMultipartTextSms(parts, subId, destAddress,
    385                         new ResultCallback<SendMultipartSmsResult>() {
    386                                 @Override
    387                                 public void onReceiveResult(final SendMultipartSmsResult result)
    388                                         throws RemoteException {
    389                                     callback.onSendMultipartSmsComplete(
    390                                             result.getSendStatus(), result.getMessageRefs());
    391                                 }
    392                             });
    393         }
    394 
    395         @Override
    396         public void sendMms(Uri pduUri, int subId, Uri location,
    397                 final ICarrierMessagingCallback callback) {
    398             onSendMms(pduUri, subId, location, new ResultCallback<SendMmsResult>() {
    399                     @Override
    400                     public void onReceiveResult(final SendMmsResult result) throws RemoteException {
    401                         callback.onSendMmsComplete(result.getSendStatus(), result.getSendConfPdu());
    402                     }
    403                 });
    404         }
    405 
    406         @Override
    407         public void downloadMms(Uri pduUri, int subId, Uri location,
    408                 final ICarrierMessagingCallback callback) {
    409             onDownloadMms(pduUri, subId, location, new ResultCallback<Integer>() {
    410                     @Override
    411                     public void onReceiveResult(Integer result) throws RemoteException {
    412                         callback.onDownloadMmsComplete(result);
    413                     }
    414                 });
    415         }
    416     }
    417 }
    418