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