• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 
17 package android.service.carrier;
18 
19 import android.annotation.CallbackExecutor;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.app.ActivityManager;
24 import android.content.ComponentName;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.ServiceConnection;
28 import android.net.Uri;
29 import android.os.Binder;
30 import android.os.IBinder;
31 import android.os.RemoteException;
32 import android.os.UserHandle;
33 import android.telephony.SmsMessage;
34 
35 import com.android.internal.telephony.flags.Flags;
36 import com.android.internal.util.Preconditions;
37 
38 import java.util.List;
39 import java.util.Objects;
40 import java.util.concurrent.Executor;
41 
42 /**
43  * Provides basic structure for platform to connect to the carrier messaging service.
44  * <p>
45  * <code>
46  * CarrierMessagingServiceWrapper carrierMessagingServiceWrapper =
47  *     new CarrierMessagingServiceWrapperImpl();
48  * if (carrierMessagingServiceWrapper.bindToCarrierMessagingService(context, carrierPackageName)) {
49  *   // wait for onServiceReady callback
50  * } else {
51  *   // Unable to bind: handle error.
52  * }
53  * </code>
54  * <p> Upon completion {@link #disconnect} should be called to unbind the
55  * CarrierMessagingService.
56  * @hide
57  */
58 @SystemApi
59 public final class CarrierMessagingServiceWrapper implements AutoCloseable {
60     // Populated by bindToCarrierMessagingService. bindToCarrierMessagingService must complete
61     // prior to calling disposeConnection so that mCarrierMessagingServiceConnection is initialized.
62     private volatile CarrierMessagingServiceConnection mCarrierMessagingServiceConnection;
63 
64     private volatile ICarrierMessagingService mICarrierMessagingService;
65     private Runnable mOnServiceReadyCallback;
66     private Executor mServiceReadyCallbackExecutor;
67     private Context mContext;
68 
69     /**
70      * Binds to the carrier messaging service under package {@code carrierPackageName}. This method
71      * should be called exactly once.
72      *
73      * @param context the context
74      * @param carrierPackageName the carrier package name
75      * @param executor the executor to run the callback.
76      * @param onServiceReadyCallback the callback when service becomes ready.
77      * @return true upon successfully binding to a carrier messaging service, false otherwise
78      * @hide
79      */
80     @SystemApi
bindToCarrierMessagingService(@onNull Context context, @NonNull String carrierPackageName, @NonNull @CallbackExecutor Executor executor, @NonNull Runnable onServiceReadyCallback)81     public boolean bindToCarrierMessagingService(@NonNull Context context,
82             @NonNull String carrierPackageName,
83             @NonNull @CallbackExecutor Executor executor,
84             @NonNull Runnable onServiceReadyCallback) {
85         Preconditions.checkState(mCarrierMessagingServiceConnection == null);
86         Objects.requireNonNull(context);
87         Objects.requireNonNull(carrierPackageName);
88         Objects.requireNonNull(executor);
89         Objects.requireNonNull(onServiceReadyCallback);
90 
91         Intent intent = new Intent(CarrierMessagingService.SERVICE_INTERFACE);
92         intent.setPackage(carrierPackageName);
93         mCarrierMessagingServiceConnection = new CarrierMessagingServiceConnection();
94         mOnServiceReadyCallback = onServiceReadyCallback;
95         mServiceReadyCallbackExecutor = executor;
96         mContext = context;
97         return Flags.supportCarrierServicesForHsum()
98                 ? context.bindServiceAsUser(intent, mCarrierMessagingServiceConnection,
99                 Context.BIND_AUTO_CREATE,
100                 UserHandle.of(ActivityManager.getCurrentUser()))
101                 : context.bindService(intent, mCarrierMessagingServiceConnection,
102                         Context.BIND_AUTO_CREATE);
103     }
104 
105     /**
106      * Unbinds the carrier messaging service. This method should be called exactly once.
107      *
108      * @hide
109      */
110     @SystemApi
disconnect()111     public void disconnect() {
112         Preconditions.checkNotNull(mCarrierMessagingServiceConnection);
113         mContext.unbindService(mCarrierMessagingServiceConnection);
114         mCarrierMessagingServiceConnection = null;
115         mOnServiceReadyCallback = null;
116         mServiceReadyCallbackExecutor = null;
117     }
118 
119     /**
120      * Called when connection with service is established.
121      *
122      * @param carrierMessagingService the carrier messaing service interface
123      */
onServiceReady(ICarrierMessagingService carrierMessagingService)124     private void onServiceReady(ICarrierMessagingService carrierMessagingService) {
125         mICarrierMessagingService = carrierMessagingService;
126         if (mOnServiceReadyCallback != null && mServiceReadyCallbackExecutor != null) {
127             final long identity = Binder.clearCallingIdentity();
128             try {
129                 mServiceReadyCallbackExecutor.execute(mOnServiceReadyCallback);
130             } finally {
131                 Binder.restoreCallingIdentity(identity);
132             }
133         }
134     }
135 
136     /**
137      * Request the CarrierMessagingService to process an incoming SMS text or data message.
138      * The service will call callback.onFilterComplete with the filtering result.
139      *
140      * @param pdu the PDUs of the message
141      * @param format the format of the PDUs, typically "3gpp" or "3gpp2".
142      *               See {@link SmsMessage#FORMAT_3GPP} and {@link SmsMessage#FORMAT_3GPP2} for
143      *               more details.
144      * @param destPort the destination port of a data SMS. It will be -1 for text SMS
145      * @param subId SMS subscription ID of the SIM
146      * @param executor the executor to run the callback.
147      * @param callback the callback to notify upon completion
148      * @hide
149      */
150     @SystemApi
receiveSms(@onNull MessagePdu pdu, @NonNull @SmsMessage.Format String format, int destPort, int subId, @NonNull @CallbackExecutor final Executor executor, @NonNull final CarrierMessagingCallback callback)151     public void receiveSms(@NonNull MessagePdu pdu, @NonNull @SmsMessage.Format String format,
152             int destPort, int subId, @NonNull @CallbackExecutor final Executor executor,
153             @NonNull final CarrierMessagingCallback callback) {
154         if (mICarrierMessagingService != null) {
155             try {
156                 mICarrierMessagingService.filterSms(pdu, format, destPort, subId,
157                         new CarrierMessagingCallbackInternal(callback, executor));
158             } catch (RemoteException e) {
159                 throw new RuntimeException(e);
160             }
161         }
162     }
163 
164     /**
165      * Request sending a new text SMS from the device.
166      * The service will call {@link ICarrierMessagingCallback#onSendSmsComplete} with the send
167      * status.
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 sendSmsFlag Flag for sending SMS. Acceptable values are 0 and
173      *        {@link CarrierMessagingService#SEND_FLAG_REQUEST_DELIVERY_STATUS}.
174      * @param executor the executor to run the callback.
175      * @param callback the callback to notify upon completion
176      * @hide
177      */
178     @SystemApi
sendTextSms(@onNull String text, int subId, @NonNull String destAddress, @CarrierMessagingService.SendRequest int sendSmsFlag, @NonNull @CallbackExecutor final Executor executor, @NonNull final CarrierMessagingCallback callback)179     public void sendTextSms(@NonNull String text, int subId, @NonNull String destAddress,
180             @CarrierMessagingService.SendRequest int sendSmsFlag,
181             @NonNull @CallbackExecutor final Executor executor,
182             @NonNull final CarrierMessagingCallback callback) {
183         Objects.requireNonNull(mICarrierMessagingService);
184         try {
185             mICarrierMessagingService.sendTextSms(text, subId, destAddress, sendSmsFlag,
186                     new CarrierMessagingCallbackInternal(callback, executor));
187         } catch (RemoteException e) {
188             throw new RuntimeException(e);
189         }
190     }
191 
192     /**
193      * Request sending a new data SMS from the device.
194      * The service will call {@link ICarrierMessagingCallback#onSendSmsComplete} with the send
195      * status.
196      *
197      * @param data the data to send
198      * @param subId SMS subscription ID of the SIM
199      * @param destAddress phone number of the recipient of the message
200      * @param destPort port number of the recipient of the message
201      * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and
202      *        {@link CarrierMessagingService#SEND_FLAG_REQUEST_DELIVERY_STATUS}.
203      * @param executor the executor to run the callback.
204      * @param callback the callback to notify upon completion
205      * @hide
206      */
207     @SystemApi
sendDataSms(@onNull byte[] data, int subId, @NonNull String destAddress, int destPort, @CarrierMessagingService.SendRequest int sendSmsFlag, @NonNull @CallbackExecutor final Executor executor, @NonNull final CarrierMessagingCallback callback)208     public void sendDataSms(@NonNull byte[] data, int subId, @NonNull String destAddress,
209             int destPort, @CarrierMessagingService.SendRequest int sendSmsFlag,
210             @NonNull @CallbackExecutor final Executor executor,
211             @NonNull final CarrierMessagingCallback callback) {
212         Objects.requireNonNull(mICarrierMessagingService);
213         try {
214             mICarrierMessagingService.sendDataSms(data, subId, destAddress, destPort,
215                     sendSmsFlag, new CarrierMessagingCallbackInternal(
216                             callback, executor));
217         } catch (RemoteException e) {
218             throw new RuntimeException(e);
219         }
220     }
221 
222     /**
223      * Request sending a new multi-part text SMS from the device.
224      * The service will call {@link ICarrierMessagingCallback#onSendMultipartSmsComplete}
225      * with the send status.
226      *
227      * @param parts the parts of the multi-part text SMS to send
228      * @param subId SMS subscription ID of the SIM
229      * @param destAddress phone number of the recipient of the message
230      * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and
231      *        {@link CarrierMessagingService#SEND_FLAG_REQUEST_DELIVERY_STATUS}.
232      * @param executor the executor to run the callback.
233      * @param callback the callback to notify upon completion
234      * @hide
235      */
236     @SystemApi
sendMultipartTextSms(@onNull List<String> parts, int subId, @NonNull String destAddress, @CarrierMessagingService.SendRequest int sendSmsFlag, @NonNull @CallbackExecutor final Executor executor, @NonNull final CarrierMessagingCallback callback)237     public void sendMultipartTextSms(@NonNull List<String> parts, int subId,
238             @NonNull String destAddress,
239             @CarrierMessagingService.SendRequest int sendSmsFlag,
240             @NonNull @CallbackExecutor final Executor executor,
241             @NonNull final CarrierMessagingCallback callback) {
242         Objects.requireNonNull(mICarrierMessagingService);
243         try {
244             mICarrierMessagingService.sendMultipartTextSms(parts, subId, destAddress,
245                     sendSmsFlag, new CarrierMessagingCallbackInternal(callback, executor));
246         } catch (RemoteException e) {
247             throw new RuntimeException(e);
248         }
249     }
250 
251     /**
252      * Request sending a new MMS PDU from the device.
253      * The service will call {@link ICarrierMessagingCallback#onSendMmsComplete} with the send
254      * status.
255      *
256      * @param pduUri the content provider URI of the PDU to send
257      * @param subId SMS subscription ID of the SIM
258      * @param location the optional URI to send this MMS PDU. If this is {code null},
259      *        the PDU should be sent to the default MMSC URL.
260      * @param executor the executor to run the callback.
261      * @param callback the callback to notify upon completion
262      * @hide
263      */
264     @SystemApi
sendMms(@onNull Uri pduUri, int subId, @NonNull Uri location, @NonNull @CallbackExecutor final Executor executor, @NonNull final CarrierMessagingCallback callback)265     public void sendMms(@NonNull Uri pduUri, int subId, @NonNull Uri location,
266             @NonNull @CallbackExecutor final Executor executor,
267             @NonNull final CarrierMessagingCallback callback) {
268         Objects.requireNonNull(mICarrierMessagingService);
269         try {
270             mICarrierMessagingService.sendMms(pduUri, subId, location,
271                     new CarrierMessagingCallbackInternal(callback, executor));
272         } catch (RemoteException e) {
273             throw new RuntimeException(e);
274         }
275     }
276 
277     /**
278      * Request downloading a new MMS.
279      * The service will call {@link ICarrierMessagingCallback#onDownloadMmsComplete} with the
280      * download status.
281      *
282      * @param pduUri the content provider URI of the PDU to be downloaded.
283      * @param subId SMS subscription ID of the SIM
284      * @param location the URI of the message to be downloaded.
285      * @param executor the executor to run the callback.
286      * @param callback the callback to notify upon completion
287      * @hide
288      */
289     @SystemApi
downloadMms(@onNull Uri pduUri, int subId, @NonNull Uri location, @NonNull @CallbackExecutor final Executor executor, @NonNull final CarrierMessagingCallback callback)290     public void downloadMms(@NonNull Uri pduUri, int subId, @NonNull Uri location,
291             @NonNull @CallbackExecutor final Executor executor,
292             @NonNull final CarrierMessagingCallback callback) {
293         Objects.requireNonNull(mICarrierMessagingService);
294         try {
295             mICarrierMessagingService.downloadMms(pduUri, subId, location,
296                     new CarrierMessagingCallbackInternal(callback, executor));
297         } catch (RemoteException e) {
298             throw new RuntimeException(e);
299         }
300     }
301 
302     /** @hide */
303     @Override
close()304     public void close() {
305         disconnect();
306     }
307 
308     /**
309      * A basic {@link ServiceConnection}.
310      */
311     private final class CarrierMessagingServiceConnection implements ServiceConnection {
312         @Override
onServiceConnected(ComponentName name, IBinder service)313         public void onServiceConnected(ComponentName name, IBinder service) {
314             onServiceReady(ICarrierMessagingService.Stub.asInterface(service));
315         }
316 
317         @Override
onServiceDisconnected(ComponentName name)318         public void onServiceDisconnected(ComponentName name) {
319         }
320     }
321 
322     /**
323      * Callback wrapper used for response to requests exposed by
324      * {@link CarrierMessagingServiceWrapper}.
325      * @hide
326      */
327     @SystemApi
328     public interface CarrierMessagingCallback {
329         /**
330          * Response callback for {@link CarrierMessagingServiceWrapper#receiveSms}.
331          * @param result a bitmask integer to indicate how the incoming text SMS should be handled
332          *               by the platform. Bits set can be
333          *               {@link CarrierMessagingService#RECEIVE_OPTIONS_DROP} and
334          *               {@link CarrierMessagingService#
335          *               RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE}.
336          *               {@link CarrierMessagingService#onReceiveTextSms}.
337          */
onReceiveSmsComplete( @arrierMessagingService.FilterCompleteResult int result)338         default void onReceiveSmsComplete(
339                 @CarrierMessagingService.FilterCompleteResult int result) {
340 
341         }
342 
343         /**
344          * Response callback for {@link CarrierMessagingServiceWrapper#sendTextSms} and
345          * {@link CarrierMessagingServiceWrapper#sendDataSms}.
346          * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
347          *               {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
348          *               and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
349          * @param messageRef message reference of the just-sent message. This field is applicable
350          *                   only if result is {@link CarrierMessagingService#SEND_STATUS_OK}.
351          */
onSendSmsComplete(@arrierMessagingService.SendResult int result, int messageRef)352         default void onSendSmsComplete(@CarrierMessagingService.SendResult
353                 int result, int messageRef) {
354         }
355 
356         /**
357          * Response callback for {@link CarrierMessagingServiceWrapper#sendMultipartTextSms}.
358          * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
359          *               {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
360          *               and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
361          * @param messageRefs an array of message references, one for each part of the
362          *                    multipart SMS. This field is applicable only if result is
363          *                    {@link CarrierMessagingService#SEND_STATUS_OK}.
364          */
onSendMultipartSmsComplete(@arrierMessagingService.SendResult int result, @Nullable int[] messageRefs)365         default void onSendMultipartSmsComplete(@CarrierMessagingService.SendResult
366                 int result, @Nullable int[] messageRefs) {
367 
368         }
369 
370         /**
371          * Response callback for {@link CarrierMessagingServiceWrapper#sendMms}.
372          * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
373          *               {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
374          *               and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
375          * @param sendConfPdu a possibly {code null} SendConf PDU, which confirms that the message
376          *                    was sent. sendConfPdu is ignored if the {@code result} is not
377          *                    {@link CarrierMessagingService#SEND_STATUS_OK}.
378          */
onSendMmsComplete(@arrierMessagingService.SendResult int result, @Nullable byte[] sendConfPdu)379         default void onSendMmsComplete(@CarrierMessagingService.SendResult
380                 int result, @Nullable byte[] sendConfPdu) {
381 
382         }
383 
384         /**
385          * Response callback for {@link CarrierMessagingServiceWrapper#downloadMms}.
386          * @param result download status, one of {@link CarrierMessagingService#DOWNLOAD_STATUS_OK},
387          *               {@link CarrierMessagingService#DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK},
388          *               and {@link CarrierMessagingService#DOWNLOAD_STATUS_ERROR}.
389          */
onDownloadMmsComplete(@arrierMessagingService.DownloadResult int result)390         default void onDownloadMmsComplete(@CarrierMessagingService.DownloadResult
391                 int result) {
392 
393         }
394     }
395 
396     private final class CarrierMessagingCallbackInternal
397             extends ICarrierMessagingCallback.Stub {
398         final CarrierMessagingCallback mCarrierMessagingCallback;
399         final Executor mExecutor;
400 
CarrierMessagingCallbackInternal(CarrierMessagingCallback callback, final Executor executor)401         CarrierMessagingCallbackInternal(CarrierMessagingCallback callback,
402                 final Executor executor) {
403             mCarrierMessagingCallback = callback;
404             mExecutor = executor;
405         }
406 
407         @Override
onFilterComplete(int result)408         public void onFilterComplete(int result) throws RemoteException {
409             mExecutor.execute(() -> mCarrierMessagingCallback.onReceiveSmsComplete(result));
410         }
411 
412         @Override
onSendSmsComplete(int result, int messageRef)413         public void onSendSmsComplete(int result, int messageRef) throws RemoteException {
414             mExecutor.execute(() -> mCarrierMessagingCallback.onSendSmsComplete(
415                     result, messageRef));
416         }
417 
418         @Override
onSendMultipartSmsComplete(int result, int[] messageRefs)419         public void onSendMultipartSmsComplete(int result, int[] messageRefs)
420                 throws RemoteException {
421             mExecutor.execute(() -> mCarrierMessagingCallback.onSendMultipartSmsComplete(
422                     result, messageRefs));
423         }
424 
425         @Override
onSendMmsComplete(int result, byte[] sendConfPdu)426         public void onSendMmsComplete(int result, byte[] sendConfPdu) throws RemoteException {
427             mExecutor.execute(() -> mCarrierMessagingCallback.onSendMmsComplete(
428                     result, sendConfPdu));
429         }
430 
431         @Override
onDownloadMmsComplete(int result)432         public void onDownloadMmsComplete(int result) throws RemoteException {
433             mExecutor.execute(() -> mCarrierMessagingCallback.onDownloadMmsComplete(result));
434         }
435     }
436 }
437