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