CarrierMessagingService.java revision e87e4f077c8f5dc8dc7b1b5cd68cbe8ca51f2396
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
17package android.service.carrier;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.annotation.SdkConstant;
22import android.app.Service;
23import android.content.Intent;
24import android.net.Uri;
25import android.os.IBinder;
26import android.os.Parcel;
27import android.os.Parcelable;
28import android.os.RemoteException;
29
30import java.util.ArrayList;
31import 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 */
48public 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    /**
87     * Flag to request SMS delivery status report.
88     */
89    public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1;
90
91    private final ICarrierMessagingWrapper mWrapper = new ICarrierMessagingWrapper();
92
93    /**
94     * Override this method to filter inbound SMS messages.
95     *
96     * @param pdu the PDUs of the message
97     * @param format the format of the PDUs, typically "3gpp" or "3gpp2"
98     * @param destPort the destination port of a binary SMS, this will be -1 for text SMS
99     * @param subId SMS subscription ID of the SIM
100     * @param callback result callback. Call with {@code true} to keep an inbound SMS message and
101     *        deliver to SMS apps, and {@code false} to drop the message.
102     */
103    public void onFilterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort,
104            int subId, @NonNull ResultCallback<Boolean> callback) {
105        // optional
106        try {
107            callback.onReceiveResult(true);
108        } catch (RemoteException ex) {
109        }
110    }
111
112    /**
113     * Override this method to intercept text SMSs sent from the device.
114     * @deprecated Override {@link #onSendTextSms} below instead.
115     *
116     * @param text the text to send
117     * @param subId SMS subscription ID of the SIM
118     * @param destAddress phone number of the recipient of the message
119     * @param callback result callback. Call with a {@link SendSmsResult}.
120     */
121    @Deprecated
122    public void onSendTextSms(
123            @NonNull String text, int subId, @NonNull String destAddress,
124            @NonNull ResultCallback<SendSmsResult> callback) {
125        // optional
126        try {
127            callback.onReceiveResult(new SendSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0));
128        } catch (RemoteException ex) {
129        }
130    }
131
132    /**
133     * Override this method to intercept text SMSs sent from the device.
134     *
135     * @param text the text to send
136     * @param subId SMS subscription ID of the SIM
137     * @param destAddress phone number of the recipient of the message
138     * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and
139     *        {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}.
140     * @param callback result callback. Call with a {@link SendSmsResult}.
141     */
142    public void onSendTextSms(
143            @NonNull String text, int subId, @NonNull String destAddress,
144            int sendSmsFlag, @NonNull ResultCallback<SendSmsResult> callback) {
145        // optional
146        onSendTextSms(text, subId, destAddress, callback);
147    }
148
149    /**
150     * Override this method to intercept binary SMSs sent from the device.
151     * @deprecated Override {@link #onSendDataSms} below instead.
152     *
153     * @param data the binary content
154     * @param subId SMS subscription ID of the SIM
155     * @param destAddress phone number of the recipient of the message
156     * @param destPort the destination port
157     * @param callback result callback. Call with a {@link SendSmsResult}.
158     */
159    @Deprecated
160    public void onSendDataSms(@NonNull byte[] data, int subId,
161            @NonNull String destAddress, int destPort,
162            @NonNull ResultCallback<SendSmsResult> callback) {
163        // optional
164        try {
165            callback.onReceiveResult(new SendSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0));
166        } catch (RemoteException ex) {
167        }
168    }
169
170    /**
171     * Override this method to intercept binary SMSs sent from the device.
172     *
173     * @param data the binary content
174     * @param subId SMS subscription ID of the SIM
175     * @param destAddress phone number of the recipient of the message
176     * @param destPort the destination port
177     * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and
178     *        {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}.
179     * @param callback result callback. Call with a {@link SendSmsResult}.
180     */
181    public void onSendDataSms(@NonNull byte[] data, int subId,
182            @NonNull String destAddress, int destPort, int sendSmsFlag,
183            @NonNull ResultCallback<SendSmsResult> callback) {
184        // optional
185        onSendDataSms(data, subId, destAddress, destPort, callback);
186    }
187
188    /**
189     * Override this method to intercept long SMSs sent from the device.
190     * @deprecated Override {@link #onSendMultipartTextSms} below instead.
191     *
192     * @param parts a {@link List} of the message parts
193     * @param subId SMS subscription ID of the SIM
194     * @param destAddress phone number of the recipient of the message
195     * @param callback result callback. Call with a {@link SendMultipartSmsResult}.
196     */
197    @Deprecated
198    public void onSendMultipartTextSms(@NonNull List<String> parts,
199            int subId, @NonNull String destAddress,
200            @NonNull ResultCallback<SendMultipartSmsResult> callback) {
201        // optional
202        try {
203            callback.onReceiveResult(
204                    new SendMultipartSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, null));
205        } catch (RemoteException ex) {
206        }
207    }
208
209    /**
210     * Override this method to intercept long SMSs sent from the device.
211     *
212     * @param parts a {@link List} of the message parts
213     * @param subId SMS subscription ID of the SIM
214     * @param destAddress phone number of the recipient of the message
215     * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and
216     *        {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}.
217     * @param callback result callback. Call with a {@link SendMultipartSmsResult}.
218     */
219    public void onSendMultipartTextSms(@NonNull List<String> parts,
220            int subId, @NonNull String destAddress, int sendSmsFlag,
221            @NonNull ResultCallback<SendMultipartSmsResult> callback) {
222        // optional
223        onSendMultipartTextSms(parts, subId, destAddress, callback);
224    }
225
226    /**
227     * Override this method to intercept MMSs sent from the device.
228     *
229     * @param pduUri the content provider URI of the PDU to send
230     * @param subId SMS subscription ID of the SIM
231     * @param location the optional URI to send this MMS PDU. If this is {code null},
232     *        the PDU should be sent to the default MMSC URL.
233     * @param callback result callback. Call with a {@link SendMmsResult}.
234     */
235    public void onSendMms(@NonNull Uri pduUri, int subId,
236            @Nullable Uri location, @NonNull ResultCallback<SendMmsResult> callback) {
237        // optional
238        try {
239            callback.onReceiveResult(new SendMmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, null));
240        } catch (RemoteException ex) {
241        }
242    }
243
244    /**
245     * Override this method to download MMSs received.
246     *
247     * @param contentUri the content provider URI of the PDU to be downloaded.
248     * @param subId SMS subscription ID of the SIM
249     * @param location the URI of the message to be downloaded.
250     * @param callback result callback. Call with a status code which is one of
251     *        {@link #DOWNLOAD_STATUS_OK},
252     *        {@link #DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK}, or {@link #DOWNLOAD_STATUS_ERROR}.
253     */
254    public void onDownloadMms(@NonNull Uri contentUri, int subId, @NonNull Uri location,
255            @NonNull ResultCallback<Integer> callback) {
256        // optional
257        try {
258            callback.onReceiveResult(DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK);
259        } catch (RemoteException ex) {
260        }
261    }
262
263    @Override
264    public @Nullable IBinder onBind(@NonNull Intent intent) {
265        if (!SERVICE_INTERFACE.equals(intent.getAction())) {
266            return null;
267        }
268        return mWrapper;
269    }
270
271    /**
272     * The result of sending an MMS.
273     */
274    public static final class SendMmsResult {
275        private int mSendStatus;
276        private byte[] mSendConfPdu;
277
278        /**
279         * Constructs a SendMmsResult with the MMS send result, and the SendConf PDU.
280         *
281         * @param sendStatus send status, one of {@link #SEND_STATUS_OK},
282         *        {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and
283         *        {@link #SEND_STATUS_ERROR}
284         * @param sendConfPdu a possibly {code null} SendConf PDU, which confirms that the message
285         *        was sent. sendConfPdu is ignored if the {@code result} is not
286         *        {@link #SEND_STATUS_OK}.
287         */
288        public SendMmsResult(int sendStatus, @Nullable byte[] sendConfPdu) {
289            mSendStatus = sendStatus;
290            mSendConfPdu = sendConfPdu;
291        }
292
293        /**
294         * Returns the send status of the just-sent MMS.
295         *
296         * @return the send status which is one of {@link #SEND_STATUS_OK},
297         *         {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR}
298         */
299        public int getSendStatus() {
300            return mSendStatus;
301        }
302
303        /**
304         * Returns the SendConf PDU, which confirms that the message was sent.
305         *
306         * @return the SendConf PDU
307         */
308        public @Nullable byte[] getSendConfPdu() {
309            return mSendConfPdu;
310        }
311    }
312
313    /**
314     * The result of sending an SMS.
315     */
316    public static final class SendSmsResult {
317        private final int mSendStatus;
318        private final int mMessageRef;
319
320        /**
321         * Constructs a SendSmsResult with the send status and message reference for the
322         * just-sent SMS.
323         *
324         * @param sendStatus send status, one of {@link #SEND_STATUS_OK},
325         *        {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR}.
326         * @param messageRef message reference of the just-sent SMS. This field is applicable only
327         *        if send status is {@link #SEND_STATUS_OK}.
328         */
329        public SendSmsResult(int sendStatus, int messageRef) {
330            mSendStatus = sendStatus;
331            mMessageRef = messageRef;
332        }
333
334        /**
335         * Returns the message reference of the just-sent SMS.
336         *
337         * @return the message reference
338         */
339        public int getMessageRef() {
340            return mMessageRef;
341        }
342
343        /**
344         * Returns the send status of the just-sent SMS.
345         *
346         * @return the send status
347         */
348        public int getSendStatus() {
349            return mSendStatus;
350        }
351    }
352
353    /**
354     * The result of sending a multipart SMS.
355     */
356    public static final class SendMultipartSmsResult {
357        private final int mSendStatus;
358        private final int[] mMessageRefs;
359
360        /**
361         * Constructs a SendMultipartSmsResult with the send status and message references for the
362         * just-sent multipart SMS.
363         *
364         * @param sendStatus send status, one of {@link #SEND_STATUS_OK},
365         *        {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR}.
366         * @param messageRefs an array of message references, one for each part of the
367         *        multipart SMS. This field is applicable only if send status is
368         *        {@link #SEND_STATUS_OK}.
369         */
370        public SendMultipartSmsResult(int sendStatus, @Nullable int[] messageRefs) {
371            mSendStatus = sendStatus;
372            mMessageRefs = messageRefs;
373        }
374
375        /**
376         * Returns the message references of the just-sent multipart SMS.
377         *
378         * @return the message references, one for each part of the multipart SMS
379         */
380        public @Nullable int[] getMessageRefs() {
381            return mMessageRefs;
382        }
383
384        /**
385         * Returns the send status of the just-sent SMS.
386         *
387         * @return the send status
388         */
389        public int getSendStatus() {
390            return mSendStatus;
391        }
392    }
393
394    /**
395     * A callback interface used to provide results asynchronously.
396     */
397    public interface ResultCallback<T> {
398        /**
399         * Invoked when the result is available.
400         *
401         * @param result the result
402         */
403        public void onReceiveResult(@NonNull T result) throws RemoteException;
404    };
405
406    /**
407     * A wrapper around ICarrierMessagingService to enable the carrier messaging app to implement
408     * methods it cares about in the {@link ICarrierMessagingService} interface.
409     */
410    private class ICarrierMessagingWrapper extends ICarrierMessagingService.Stub {
411        @Override
412        public void filterSms(MessagePdu pdu, String format, int destPort,
413                              int subId, final ICarrierMessagingCallback callback) {
414            onFilterSms(pdu, format, destPort, subId, new ResultCallback<Boolean>() {
415                    @Override
416                    public void onReceiveResult(final Boolean result) throws RemoteException {
417                        callback.onFilterComplete(result);
418                    }
419                });
420        }
421
422        @Override
423        public void sendTextSms(String text, int subId, String destAddress,
424                int sendSmsFlag, final ICarrierMessagingCallback callback) {
425            onSendTextSms(text, subId, destAddress, sendSmsFlag,
426                    new ResultCallback<SendSmsResult>() {
427                    @Override
428                    public void onReceiveResult(final SendSmsResult result) throws RemoteException {
429                        callback.onSendSmsComplete(result.getSendStatus(), result.getMessageRef());
430                    }
431                });
432        }
433
434        @Override
435        public void sendDataSms(byte[] data, int subId, String destAddress, int destPort,
436                int sendSmsFlag, final ICarrierMessagingCallback callback) {
437            onSendDataSms(data, subId, destAddress, destPort, sendSmsFlag,
438                    new ResultCallback<SendSmsResult>() {
439                    @Override
440                    public void onReceiveResult(final SendSmsResult result) throws RemoteException {
441                        callback.onSendSmsComplete(result.getSendStatus(), result.getMessageRef());
442                    }
443                });
444        }
445
446        @Override
447        public void sendMultipartTextSms(List<String> parts, int subId, String destAddress,
448                int sendSmsFlag, final ICarrierMessagingCallback callback) {
449            onSendMultipartTextSms(parts, subId, destAddress, sendSmsFlag,
450                        new ResultCallback<SendMultipartSmsResult>() {
451                                @Override
452                                public void onReceiveResult(final SendMultipartSmsResult result)
453                                        throws RemoteException {
454                                    callback.onSendMultipartSmsComplete(
455                                            result.getSendStatus(), result.getMessageRefs());
456                                }
457                            });
458        }
459
460        @Override
461        public void sendMms(Uri pduUri, int subId, Uri location,
462                final ICarrierMessagingCallback callback) {
463            onSendMms(pduUri, subId, location, new ResultCallback<SendMmsResult>() {
464                    @Override
465                    public void onReceiveResult(final SendMmsResult result) throws RemoteException {
466                        callback.onSendMmsComplete(result.getSendStatus(), result.getSendConfPdu());
467                    }
468                });
469        }
470
471        @Override
472        public void downloadMms(Uri pduUri, int subId, Uri location,
473                final ICarrierMessagingCallback callback) {
474            onDownloadMms(pduUri, subId, location, new ResultCallback<Integer>() {
475                    @Override
476                    public void onReceiveResult(Integer result) throws RemoteException {
477                        callback.onDownloadMmsComplete(result);
478                    }
479                });
480        }
481    }
482}
483