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.NonNull;
20 import android.annotation.Nullable;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.ServiceConnection;
25 import android.net.Uri;
26 import android.os.IBinder;
27 import android.os.RemoteException;
28 
29 import com.android.internal.util.Preconditions;
30 
31 import java.util.List;
32 
33 /**
34  * Provides basic structure for platform to connect to the carrier messaging service.
35  * <p>
36  * <code>
37  * CarrierMessagingServiceWrapper carrierMessagingServiceWrapper =
38  *     new CarrierMessagingServiceWrapperImpl();
39  * if (carrierMessagingServiceWrapper.bindToCarrierMessagingService(context, carrierPackageName)) {
40  *   // wait for onServiceReady callback
41  * } else {
42  *   // Unable to bind: handle error.
43  * }
44  * </code>
45  * <p> Upon completion {@link #disposeConnection} should be called to unbind the
46  * CarrierMessagingService.
47  * @hide
48  */
49 public abstract class CarrierMessagingServiceWrapper {
50     // Populated by bindToCarrierMessagingService. bindToCarrierMessagingService must complete
51     // prior to calling disposeConnection so that mCarrierMessagingServiceConnection is initialized.
52     private volatile CarrierMessagingServiceConnection mCarrierMessagingServiceConnection;
53 
54     private volatile ICarrierMessagingService mICarrierMessagingService;
55 
56     /**
57      * Binds to the carrier messaging service under package {@code carrierPackageName}. This method
58      * should be called exactly once.
59      *
60      * @param context the context
61      * @param carrierPackageName the carrier package name
62      * @return true upon successfully binding to a carrier messaging service, false otherwise
63      * @hide
64      */
bindToCarrierMessagingService(@onNull Context context, @NonNull String carrierPackageName)65     public boolean bindToCarrierMessagingService(@NonNull Context context,
66             @NonNull String carrierPackageName) {
67         Preconditions.checkState(mCarrierMessagingServiceConnection == null);
68 
69         Intent intent = new Intent(CarrierMessagingService.SERVICE_INTERFACE);
70         intent.setPackage(carrierPackageName);
71         mCarrierMessagingServiceConnection = new CarrierMessagingServiceConnection();
72         return context.bindService(intent, mCarrierMessagingServiceConnection,
73                 Context.BIND_AUTO_CREATE);
74     }
75 
76     /**
77      * Unbinds the carrier messaging service. This method should be called exactly once.
78      *
79      * @param context the context
80      * @hide
81      */
disposeConnection(@onNull Context context)82     public void disposeConnection(@NonNull Context context) {
83         Preconditions.checkNotNull(mCarrierMessagingServiceConnection);
84         context.unbindService(mCarrierMessagingServiceConnection);
85         mCarrierMessagingServiceConnection = null;
86     }
87 
88     /**
89      * Implemented by subclasses to use the carrier messaging service once it is ready.
90      * @hide
91      */
onServiceReady()92     public abstract void onServiceReady();
93 
94     /**
95      * Called when connection with service is established.
96      *
97      * @param carrierMessagingService the carrier messaing service interface
98      */
onServiceReady(ICarrierMessagingService carrierMessagingService)99     private void onServiceReady(ICarrierMessagingService carrierMessagingService) {
100         mICarrierMessagingService = carrierMessagingService;
101         onServiceReady();
102     }
103 
104     /**
105      * Request filtering an incoming SMS message.
106      * The service will call callback.onFilterComplete with the filtering result.
107      *
108      * @param pdu the PDUs of the message
109      * @param format the format of the PDUs, typically "3gpp" or "3gpp2"
110      * @param destPort the destination port of a data SMS. It will be -1 for text SMS
111      * @param subId SMS subscription ID of the SIM
112      * @param callback the callback to notify upon completion
113      * @hide
114      */
filterSms(@onNull MessagePdu pdu, @NonNull String format, int destPort, int subId, @NonNull final CarrierMessagingCallbackWrapper callback)115     public void filterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort,
116             int subId, @NonNull final CarrierMessagingCallbackWrapper callback) {
117         if (mICarrierMessagingService != null) {
118             try {
119                 mICarrierMessagingService.filterSms(pdu, format, destPort, subId,
120                         new CarrierMessagingCallbackWrapperInternal(callback));
121             } catch (RemoteException e) {
122                 throw new RuntimeException(e);
123             }
124         }
125     }
126 
127     /**
128      * Request sending a new text SMS from the device.
129      * The service will call {@link ICarrierMessagingCallback#onSendSmsComplete} with the send
130      * status.
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
136      * @param callback the callback to notify upon completion
137      * @hide
138      */
sendTextSms(@onNull String text, int subId, @NonNull String destAddress, int sendSmsFlag, @NonNull final CarrierMessagingCallbackWrapper callback)139     public void sendTextSms(@NonNull String text, int subId, @NonNull String destAddress,
140             int sendSmsFlag, @NonNull final CarrierMessagingCallbackWrapper callback) {
141         if (mICarrierMessagingService != null) {
142             try {
143                 mICarrierMessagingService.sendTextSms(text, subId, destAddress, sendSmsFlag,
144                         new CarrierMessagingCallbackWrapperInternal(callback));
145             } catch (RemoteException e) {
146                 throw new RuntimeException(e);
147             }
148         }
149     }
150 
151     /**
152      * Request sending a new data SMS from the device.
153      * The service will call {@link ICarrierMessagingCallback#onSendSmsComplete} with the send
154      * status.
155      *
156      * @param data the data to send
157      * @param subId SMS subscription ID of the SIM
158      * @param destAddress phone number of the recipient of the message
159      * @param destPort port number of the recipient of the message
160      * @param sendSmsFlag flag for sending SMS
161      * @param callback the callback to notify upon completion
162      * @hide
163      */
sendDataSms(@onNull byte[] data, int subId, @NonNull String destAddress, int destPort, int sendSmsFlag, @NonNull final CarrierMessagingCallbackWrapper callback)164     public void sendDataSms(@NonNull byte[] data, int subId, @NonNull String destAddress,
165             int destPort, int sendSmsFlag,
166             @NonNull final CarrierMessagingCallbackWrapper callback) {
167         if (mICarrierMessagingService != null) {
168             try {
169                 mICarrierMessagingService.sendDataSms(data, subId, destAddress, destPort,
170                         sendSmsFlag, new CarrierMessagingCallbackWrapperInternal(callback));
171             } catch (RemoteException e) {
172                 throw new RuntimeException(e);
173             }
174         }
175     }
176 
177     /**
178      * Request sending a new multi-part text SMS from the device.
179      * The service will call {@link ICarrierMessagingCallback#onSendMultipartSmsComplete}
180      * with the send status.
181      *
182      * @param parts the parts of the multi-part text SMS to send
183      * @param subId SMS subscription ID of the SIM
184      * @param destAddress phone number of the recipient of the message
185      * @param sendSmsFlag flag for sending SMS
186      * @param callback the callback to notify upon completion
187      * @hide
188      */
sendMultipartTextSms(@onNull List<String> parts, int subId, @NonNull String destAddress, int sendSmsFlag, @NonNull final CarrierMessagingCallbackWrapper callback)189     public void sendMultipartTextSms(@NonNull List<String> parts, int subId,
190             @NonNull String destAddress, int sendSmsFlag,
191             @NonNull final CarrierMessagingCallbackWrapper callback) {
192         if (mICarrierMessagingService != null) {
193             try {
194                 mICarrierMessagingService.sendMultipartTextSms(parts, subId, destAddress,
195                         sendSmsFlag, new CarrierMessagingCallbackWrapperInternal(callback));
196             } catch (RemoteException e) {
197                 throw new RuntimeException(e);
198             }
199         }
200     }
201 
202     /**
203      * Request sending a new MMS PDU from the device.
204      * The service will call {@link ICarrierMessagingCallback#onSendMmsComplete} with the send
205      * status.
206      *
207      * @param pduUri the content provider URI of the PDU to send
208      * @param subId SMS subscription ID of the SIM
209      * @param location the optional URI to send this MMS PDU. If this is {code null},
210      *        the PDU should be sent to the default MMSC URL.
211      * @param callback the callback to notify upon completion
212      * @hide
213      */
sendMms(@onNull Uri pduUri, int subId, @NonNull Uri location, @NonNull final CarrierMessagingCallbackWrapper callback)214     public void sendMms(@NonNull Uri pduUri, int subId, @NonNull Uri location,
215             @NonNull final CarrierMessagingCallbackWrapper callback) {
216         if (mICarrierMessagingService != null) {
217             try {
218                 mICarrierMessagingService.sendMms(pduUri, subId, location,
219                         new CarrierMessagingCallbackWrapperInternal(callback));
220             } catch (RemoteException e) {
221                 throw new RuntimeException(e);
222             }
223         }
224     }
225 
226     /**
227      * Request downloading a new MMS.
228      * The service will call {@link ICarrierMessagingCallback#onDownloadMmsComplete} with the
229      * download status.
230      *
231      * @param pduUri the content provider URI of the PDU to be downloaded.
232      * @param subId SMS subscription ID of the SIM
233      * @param location the URI of the message to be downloaded.
234      * @param callback the callback to notify upon completion
235      * @hide
236      */
downloadMms(@onNull Uri pduUri, int subId, @NonNull Uri location, @NonNull final CarrierMessagingCallbackWrapper callback)237     public void downloadMms(@NonNull Uri pduUri, int subId, @NonNull Uri location,
238             @NonNull final CarrierMessagingCallbackWrapper callback) {
239         if (mICarrierMessagingService != null) {
240             try {
241                 mICarrierMessagingService.downloadMms(pduUri, subId, location,
242                         new CarrierMessagingCallbackWrapperInternal(callback));
243             } catch (RemoteException e) {
244                 throw new RuntimeException(e);
245             }
246         }
247     }
248 
249     /**
250      * A basic {@link ServiceConnection}.
251      */
252     private final class CarrierMessagingServiceConnection implements ServiceConnection {
253         @Override
onServiceConnected(ComponentName name, IBinder service)254         public void onServiceConnected(ComponentName name, IBinder service) {
255             onServiceReady(ICarrierMessagingService.Stub.asInterface(service));
256         }
257 
258         @Override
onServiceDisconnected(ComponentName name)259         public void onServiceDisconnected(ComponentName name) {
260         }
261     }
262 
263     /**
264      * Callback wrapper used for response to requests exposed by
265      * {@link CarrierMessagingServiceWrapper}.
266      * @hide
267      */
268     public abstract static class CarrierMessagingCallbackWrapper {
269 
270         /**
271          * Response callback for {@link CarrierMessagingServiceWrapper#filterSms}.
272          * @param result a bitmask integer to indicate how the incoming text SMS should be handled
273          *               by the platform. Bits set can be
274          *               {@link CarrierMessagingService#RECEIVE_OPTIONS_DROP} and
275          *               {@link CarrierMessagingService#
276          *               RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE}.
277          *               {@see CarrierMessagingService#onReceiveTextSms}.
278          * @hide
279          */
onFilterComplete(int result)280         public void onFilterComplete(int result) {
281 
282         }
283 
284         /**
285          * Response callback for {@link CarrierMessagingServiceWrapper#sendTextSms} and
286          * {@link CarrierMessagingServiceWrapper#sendDataSms}.
287          * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
288          *               {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
289          *               and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
290          * @param messageRef message reference of the just-sent message. This field is applicable
291          *                   only if result is {@link CarrierMessagingService#SEND_STATUS_OK}.
292          * @hide
293          */
onSendSmsComplete(int result, int messageRef)294         public void onSendSmsComplete(int result, int messageRef) {
295 
296         }
297 
298         /**
299          * Response callback for {@link CarrierMessagingServiceWrapper#sendMultipartTextSms}.
300          * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
301          *               {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
302          *               and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
303          * @param messageRefs an array of message references, one for each part of the
304          *                    multipart SMS. This field is applicable only if result is
305          *                    {@link CarrierMessagingService#SEND_STATUS_OK}.
306          * @hide
307          */
onSendMultipartSmsComplete(int result, @Nullable int[] messageRefs)308         public void onSendMultipartSmsComplete(int result, @Nullable int[] messageRefs) {
309 
310         }
311 
312         /**
313          * Response callback for {@link CarrierMessagingServiceWrapper#sendMms}.
314          * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
315          *               {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
316          *               and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
317          * @param sendConfPdu a possibly {code null} SendConf PDU, which confirms that the message
318          *                    was sent. sendConfPdu is ignored if the {@code result} is not
319          *                    {@link CarrierMessagingService#SEND_STATUS_OK}.
320          * @hide
321          */
onSendMmsComplete(int result, @Nullable byte[] sendConfPdu)322         public void onSendMmsComplete(int result, @Nullable byte[] sendConfPdu) {
323 
324         }
325 
326         /**
327          * Response callback for {@link CarrierMessagingServiceWrapper#downloadMms}.
328          * @param result download status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
329          *               {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
330          *               and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
331          * @hide
332          */
onDownloadMmsComplete(int result)333         public void onDownloadMmsComplete(int result) {
334 
335         }
336     }
337 
338     private final class CarrierMessagingCallbackWrapperInternal
339             extends ICarrierMessagingCallback.Stub {
340         CarrierMessagingCallbackWrapper mCarrierMessagingCallbackWrapper;
341 
CarrierMessagingCallbackWrapperInternal(CarrierMessagingCallbackWrapper callback)342         CarrierMessagingCallbackWrapperInternal(CarrierMessagingCallbackWrapper callback) {
343             mCarrierMessagingCallbackWrapper = callback;
344         }
345 
346         @Override
onFilterComplete(int result)347         public void onFilterComplete(int result) throws RemoteException {
348             mCarrierMessagingCallbackWrapper.onFilterComplete(result);
349         }
350 
351         @Override
onSendSmsComplete(int result, int messageRef)352         public void onSendSmsComplete(int result, int messageRef) throws RemoteException {
353             mCarrierMessagingCallbackWrapper.onSendSmsComplete(result, messageRef);
354         }
355 
356         @Override
onSendMultipartSmsComplete(int result, int[] messageRefs)357         public void onSendMultipartSmsComplete(int result, int[] messageRefs)
358                 throws RemoteException {
359             mCarrierMessagingCallbackWrapper.onSendMultipartSmsComplete(result, messageRefs);
360         }
361 
362         @Override
onSendMmsComplete(int result, byte[] sendConfPdu)363         public void onSendMmsComplete(int result, byte[] sendConfPdu) throws RemoteException {
364             mCarrierMessagingCallbackWrapper.onSendMmsComplete(result, sendConfPdu);
365         }
366 
367         @Override
onDownloadMmsComplete(int result)368         public void onDownloadMmsComplete(int result) throws RemoteException {
369             mCarrierMessagingCallbackWrapper.onDownloadMmsComplete(result);
370         }
371     }
372 }
373