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