summaryrefslogtreecommitdiff
path: root/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java
blob: de90b94d7535f118c9ea4cd800954e351dae789e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.service.carrier;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.IBinder;
import android.os.RemoteException;

import com.android.internal.util.Preconditions;

import java.util.List;

/**
 * Provides basic structure for platform to connect to the carrier messaging service.
 * <p>
 * <code>
 * CarrierMessagingServiceWrapper carrierMessagingServiceWrapper =
 *     new CarrierMessagingServiceWrapperImpl();
 * if (carrierMessagingServiceWrapper.bindToCarrierMessagingService(context, carrierPackageName)) {
 *   // wait for onServiceReady callback
 * } else {
 *   // Unable to bind: handle error.
 * }
 * </code>
 * <p> Upon completion {@link #disposeConnection} should be called to unbind the
 * CarrierMessagingService.
 * @hide
 */
@SystemApi
public abstract class CarrierMessagingServiceWrapper {
    // Populated by bindToCarrierMessagingService. bindToCarrierMessagingService must complete
    // prior to calling disposeConnection so that mCarrierMessagingServiceConnection is initialized.
    private volatile CarrierMessagingServiceConnection mCarrierMessagingServiceConnection;

    private volatile ICarrierMessagingService mICarrierMessagingService;

    /**
     * Binds to the carrier messaging service under package {@code carrierPackageName}. This method
     * should be called exactly once.
     *
     * @param context the context
     * @param carrierPackageName the carrier package name
     * @return true upon successfully binding to a carrier messaging service, false otherwise
     * @hide
     */
    @SystemApi
    public boolean bindToCarrierMessagingService(@NonNull Context context,
            @NonNull String carrierPackageName) {
        Preconditions.checkState(mCarrierMessagingServiceConnection == null);

        Intent intent = new Intent(CarrierMessagingService.SERVICE_INTERFACE);
        intent.setPackage(carrierPackageName);
        mCarrierMessagingServiceConnection = new CarrierMessagingServiceConnection();
        return context.bindService(intent, mCarrierMessagingServiceConnection,
                Context.BIND_AUTO_CREATE);
    }

    /**
     * Unbinds the carrier messaging service. This method should be called exactly once.
     *
     * @param context the context
     * @hide
     */
    @SystemApi
    public void disposeConnection(@NonNull Context context) {
        Preconditions.checkNotNull(mCarrierMessagingServiceConnection);
        context.unbindService(mCarrierMessagingServiceConnection);
        mCarrierMessagingServiceConnection = null;
    }

    /**
     * Implemented by subclasses to use the carrier messaging service once it is ready.
     * @hide
     */
    @SystemApi
    public abstract void onServiceReady();

    /**
     * Called when connection with service is established.
     *
     * @param carrierMessagingService the carrier messaing service interface
     */
    private void onServiceReady(ICarrierMessagingService carrierMessagingService) {
        mICarrierMessagingService = carrierMessagingService;
        onServiceReady();
    }

    /**
     * Request filtering an incoming SMS message.
     * The service will call callback.onFilterComplete with the filtering result.
     *
     * @param pdu the PDUs of the message
     * @param format the format of the PDUs, typically "3gpp" or "3gpp2"
     * @param destPort the destination port of a data SMS. It will be -1 for text SMS
     * @param subId SMS subscription ID of the SIM
     * @param callback the callback to notify upon completion
     * @hide
     */
    @SystemApi
    public void filterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort,
            int subId, @NonNull final CarrierMessagingCallbackWrapper callback) {
        if (mICarrierMessagingService != null) {
            try {
                mICarrierMessagingService.filterSms(pdu, format, destPort, subId,
                        new CarrierMessagingCallbackWrapperInternal(callback));
            } catch (RemoteException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * Request sending a new text SMS from the device.
     * The service will call {@link ICarrierMessagingCallback#onSendSmsComplete} with the send
     * status.
     *
     * @param text the text to send
     * @param subId SMS subscription ID of the SIM
     * @param destAddress phone number of the recipient of the message
     * @param sendSmsFlag flag for sending SMS
     * @param callback the callback to notify upon completion
     * @hide
     */
    @SystemApi
    public void sendTextSms(@NonNull String text, int subId, @NonNull String destAddress,
            int sendSmsFlag, @NonNull final CarrierMessagingCallbackWrapper callback) {
        if (mICarrierMessagingService != null) {
            try {
                mICarrierMessagingService.sendTextSms(text, subId, destAddress, sendSmsFlag,
                        new CarrierMessagingCallbackWrapperInternal(callback));
            } catch (RemoteException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * Request sending a new data SMS from the device.
     * The service will call {@link ICarrierMessagingCallback#onSendSmsComplete} with the send
     * status.
     *
     * @param data the data to send
     * @param subId SMS subscription ID of the SIM
     * @param destAddress phone number of the recipient of the message
     * @param destPort port number of the recipient of the message
     * @param sendSmsFlag flag for sending SMS
     * @param callback the callback to notify upon completion
     * @hide
     */
    @SystemApi
    public void sendDataSms(@NonNull byte[] data, int subId, @NonNull String destAddress,
            int destPort, int sendSmsFlag,
            @NonNull final CarrierMessagingCallbackWrapper callback) {
        if (mICarrierMessagingService != null) {
            try {
                mICarrierMessagingService.sendDataSms(data, subId, destAddress, destPort,
                        sendSmsFlag, new CarrierMessagingCallbackWrapperInternal(callback));
            } catch (RemoteException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * Request sending a new multi-part text SMS from the device.
     * The service will call {@link ICarrierMessagingCallback#onSendMultipartSmsComplete}
     * with the send status.
     *
     * @param parts the parts of the multi-part text SMS to send
     * @param subId SMS subscription ID of the SIM
     * @param destAddress phone number of the recipient of the message
     * @param sendSmsFlag flag for sending SMS
     * @param callback the callback to notify upon completion
     * @hide
     */
    @SystemApi
    public void sendMultipartTextSms(@NonNull List<String> parts, int subId,
            @NonNull String destAddress, int sendSmsFlag,
            @NonNull final CarrierMessagingCallbackWrapper callback) {
        if (mICarrierMessagingService != null) {
            try {
                mICarrierMessagingService.sendMultipartTextSms(parts, subId, destAddress,
                        sendSmsFlag, new CarrierMessagingCallbackWrapperInternal(callback));
            } catch (RemoteException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * Request sending a new MMS PDU from the device.
     * The service will call {@link ICarrierMessagingCallback#onSendMmsComplete} with the send
     * status.
     *
     * @param pduUri the content provider URI of the PDU to send
     * @param subId SMS subscription ID of the SIM
     * @param location the optional URI to send this MMS PDU. If this is {code null},
     *        the PDU should be sent to the default MMSC URL.
     * @param callback the callback to notify upon completion
     * @hide
     */
    @SystemApi
    public void sendMms(@NonNull Uri pduUri, int subId, @NonNull Uri location,
            @NonNull final CarrierMessagingCallbackWrapper callback) {
        if (mICarrierMessagingService != null) {
            try {
                mICarrierMessagingService.sendMms(pduUri, subId, location,
                        new CarrierMessagingCallbackWrapperInternal(callback));
            } catch (RemoteException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * Request downloading a new MMS.
     * The service will call {@link ICarrierMessagingCallback#onDownloadMmsComplete} with the
     * download status.
     *
     * @param pduUri the content provider URI of the PDU to be downloaded.
     * @param subId SMS subscription ID of the SIM
     * @param location the URI of the message to be downloaded.
     * @param callback the callback to notify upon completion
     * @hide
     */
    @SystemApi
    public void downloadMms(@NonNull Uri pduUri, int subId, @NonNull Uri location,
            @NonNull final CarrierMessagingCallbackWrapper callback) {
        if (mICarrierMessagingService != null) {
            try {
                mICarrierMessagingService.downloadMms(pduUri, subId, location,
                        new CarrierMessagingCallbackWrapperInternal(callback));
            } catch (RemoteException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * A basic {@link ServiceConnection}.
     */
    private final class CarrierMessagingServiceConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            onServiceReady(ICarrierMessagingService.Stub.asInterface(service));
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    }

    /**
     * Callback wrapper used for response to requests exposed by
     * {@link CarrierMessagingServiceWrapper}.
     * @hide
     */
    @SystemApi
    public abstract static class CarrierMessagingCallbackWrapper {

        /**
         * Response callback for {@link CarrierMessagingServiceWrapper#filterSms}.
         * @param result a bitmask integer to indicate how the incoming text SMS should be handled
         *               by the platform. Bits set can be
         *               {@link CarrierMessagingService#RECEIVE_OPTIONS_DROP} and
         *               {@link CarrierMessagingService#
         *               RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE}.
         *               {@see CarrierMessagingService#onReceiveTextSms}.
         * @hide
         */
        @SystemApi
        public void onFilterComplete(int result) {

        }

        /**
         * Response callback for {@link CarrierMessagingServiceWrapper#sendTextSms} and
         * {@link CarrierMessagingServiceWrapper#sendDataSms}.
         * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
         *               {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
         *               and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
         * @param messageRef message reference of the just-sent message. This field is applicable
         *                   only if result is {@link CarrierMessagingService#SEND_STATUS_OK}.
         * @hide
         */
        @SystemApi
        public void onSendSmsComplete(int result, int messageRef) {

        }

        /**
         * Response callback for {@link CarrierMessagingServiceWrapper#sendMultipartTextSms}.
         * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
         *               {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
         *               and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
         * @param messageRefs an array of message references, one for each part of the
         *                    multipart SMS. This field is applicable only if result is
         *                    {@link CarrierMessagingService#SEND_STATUS_OK}.
         * @hide
         */
        @SystemApi
        public void onSendMultipartSmsComplete(int result, @Nullable int[] messageRefs) {

        }

        /**
         * Response callback for {@link CarrierMessagingServiceWrapper#sendMms}.
         * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
         *               {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
         *               and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
         * @param sendConfPdu a possibly {code null} SendConf PDU, which confirms that the message
         *                    was sent. sendConfPdu is ignored if the {@code result} is not
         *                    {@link CarrierMessagingService#SEND_STATUS_OK}.
         * @hide
         */
        @SystemApi
        public void onSendMmsComplete(int result, @Nullable byte[] sendConfPdu) {

        }

        /**
         * Response callback for {@link CarrierMessagingServiceWrapper#downloadMms}.
         * @param result download status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
         *               {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
         *               and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
         * @hide
         */
        @SystemApi
        public void onDownloadMmsComplete(int result) {

        }
    }

    private final class CarrierMessagingCallbackWrapperInternal
            extends ICarrierMessagingCallback.Stub {
        CarrierMessagingCallbackWrapper mCarrierMessagingCallbackWrapper;

        CarrierMessagingCallbackWrapperInternal(CarrierMessagingCallbackWrapper callback) {
            mCarrierMessagingCallbackWrapper = callback;
        }

        @Override
        public void onFilterComplete(int result) throws RemoteException {
            mCarrierMessagingCallbackWrapper.onFilterComplete(result);
        }

        @Override
        public void onSendSmsComplete(int result, int messageRef) throws RemoteException {
            mCarrierMessagingCallbackWrapper.onSendSmsComplete(result, messageRef);
        }

        @Override
        public void onSendMultipartSmsComplete(int result, int[] messageRefs)
                throws RemoteException {
            mCarrierMessagingCallbackWrapper.onSendMultipartSmsComplete(result, messageRefs);
        }

        @Override
        public void onSendMmsComplete(int result, byte[] sendConfPdu) throws RemoteException {
            mCarrierMessagingCallbackWrapper.onSendMmsComplete(result, sendConfPdu);
        }

        @Override
        public void onDownloadMmsComplete(int result) throws RemoteException {
            mCarrierMessagingCallbackWrapper.onDownloadMmsComplete(result);
        }
    }
}