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