CarrierMessagingService.java revision a8c9c6c593d603a84aa164410b91e2399ceb41ce
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     * 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_ENCRYPTED_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_ENCRYPTED_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_ENCRYPTED_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_ENCRYPTED_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