1/* 2 * Copyright (C) 2014 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 17package android.service.carrier; 18 19import android.annotation.NonNull; 20import android.annotation.Nullable; 21import android.annotation.SdkConstant; 22import android.app.Service; 23import android.content.Intent; 24import android.net.Uri; 25import android.os.IBinder; 26import android.os.RemoteException; 27 28import java.util.List; 29 30/** 31 * A service that receives calls from the system when new SMS and MMS are 32 * sent or received. 33 * <p>To extend this class, you must declare the service in your manifest file with 34 * the {@link android.Manifest.permission#BIND_CARRIER_SERVICES} permission 35 * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p> 36 * <pre> 37 * <service android:name=".MyMessagingService" 38 * android:label="@string/service_name" 39 * android:permission="android.permission.BIND_CARRIER_SERVICES"> 40 * <intent-filter> 41 * <action android:name="android.service.carrier.CarrierMessagingService" /> 42 * </intent-filter> 43 * </service></pre> 44 */ 45public abstract class CarrierMessagingService extends Service { 46 /** 47 * The {@link android.content.Intent} that must be declared as handled by the service. 48 */ 49 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 50 public static final String SERVICE_INTERFACE 51 = "android.service.carrier.CarrierMessagingService"; 52 53 /** 54 * The default bitmask value passed to the callback of {@link #onReceiveTextSms} with all 55 * {@code RECEIVE_OPTIONS_x} flags cleared to indicate that the message should be kept and a 56 * new message notification should be shown. 57 * 58 * @see #RECEIVE_OPTIONS_DROP 59 * @see #RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE 60 */ 61 public static final int RECEIVE_OPTIONS_DEFAULT = 0; 62 63 /** 64 * Used to set the flag in the bitmask passed to the callback of {@link #onReceiveTextSms} to 65 * indicate that the inbound SMS should be dropped. 66 */ 67 public static final int RECEIVE_OPTIONS_DROP = 0x1; 68 69 /** 70 * Used to set the flag in the bitmask passed to the callback of {@link #onReceiveTextSms} to 71 * indicate that a new message notification should not be shown to the user when the 72 * credential-encrypted storage of the device is not available before the user unlocks the 73 * phone. It is only applicable to devices that support file-based encryption. 74 */ 75 public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE = 0x2; 76 77 /** 78 * Indicates that an SMS or MMS message was successfully sent. 79 */ 80 public static final int SEND_STATUS_OK = 0; 81 82 /** 83 * SMS/MMS sending failed. We should retry via the carrier network. 84 */ 85 public static final int SEND_STATUS_RETRY_ON_CARRIER_NETWORK = 1; 86 87 /** 88 * SMS/MMS sending failed. We should not retry via the carrier network. 89 */ 90 public static final int SEND_STATUS_ERROR = 2; 91 92 /** 93 * Successfully downloaded an MMS message. 94 */ 95 public static final int DOWNLOAD_STATUS_OK = 0; 96 97 /** 98 * MMS downloading failed. We should retry via the carrier network. 99 */ 100 public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; 101 102 /** 103 * MMS downloading failed. We should not retry via the carrier network. 104 */ 105 public static final int DOWNLOAD_STATUS_ERROR = 2; 106 107 /** 108 * Flag to request SMS delivery status report. 109 */ 110 public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; 111 112 private final ICarrierMessagingWrapper mWrapper = new ICarrierMessagingWrapper(); 113 114 /** 115 * Override this method to filter inbound SMS messages. 116 * 117 * @param pdu the PDUs of the message 118 * @param format the format of the PDUs, typically "3gpp" or "3gpp2" 119 * @param destPort the destination port of a binary SMS, this will be -1 for text SMS 120 * @param subId SMS subscription ID of the SIM 121 * @param callback result callback. Call with {@code true} to keep an inbound SMS message and 122 * deliver to SMS apps, and {@code false} to drop the message. 123 * @deprecated Use {@link #onReceiveTextSms} instead. 124 */ 125 @Deprecated 126 public void onFilterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort, 127 int subId, @NonNull ResultCallback<Boolean> callback) { 128 // optional 129 try { 130 callback.onReceiveResult(true); 131 } catch (RemoteException ex) { 132 } 133 } 134 135 /** 136 * Override this method to filter inbound SMS messages. 137 * 138 * <p>This method will be called once for every incoming text SMS. You can invoke the callback 139 * with a bitmask to tell the platform how to handle the SMS. For a SMS received on a 140 * file-based encryption capable device while the credential-encrypted storage is not available, 141 * this method will be called for the second time when the credential-encrypted storage becomes 142 * available after the user unlocks the phone, if the bit {@link #RECEIVE_OPTIONS_DROP} is not 143 * set when invoking the callback. 144 * 145 * @param pdu the PDUs of the message 146 * @param format the format of the PDUs, typically "3gpp" or "3gpp2" 147 * @param destPort the destination port of a binary SMS, this will be -1 for text SMS 148 * @param subId SMS subscription ID of the SIM 149 * @param callback result callback. Call with a bitmask integer to indicate how the incoming 150 * text SMS should be handled by the platform. Use {@link #RECEIVE_OPTIONS_DROP} and 151 * {@link #RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE} 152 * to set the flags in the bitmask. 153 */ 154 public void onReceiveTextSms(@NonNull MessagePdu pdu, @NonNull String format, 155 int destPort, int subId, @NonNull final ResultCallback<Integer> callback) { 156 onFilterSms(pdu, format, destPort, subId, new ResultCallback<Boolean>() { 157 @Override 158 public void onReceiveResult(Boolean result) throws RemoteException { 159 callback.onReceiveResult(result ? RECEIVE_OPTIONS_DEFAULT : RECEIVE_OPTIONS_DROP 160 | RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE); 161 } 162 }); 163 } 164 165 /** 166 * Override this method to intercept text SMSs sent from the device. 167 * @deprecated Override {@link #onSendTextSms} below instead. 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 callback result callback. Call with a {@link SendSmsResult}. 173 */ 174 @Deprecated 175 public void onSendTextSms( 176 @NonNull String text, int subId, @NonNull String destAddress, 177 @NonNull ResultCallback<SendSmsResult> callback) { 178 // optional 179 try { 180 callback.onReceiveResult(new SendSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0)); 181 } catch (RemoteException ex) { 182 } 183 } 184 185 /** 186 * Override this method to intercept text SMSs sent from the device. 187 * 188 * @param text the text to send 189 * @param subId SMS subscription ID of the SIM 190 * @param destAddress phone number of the recipient of the message 191 * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and 192 * {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}. 193 * @param callback result callback. Call with a {@link SendSmsResult}. 194 */ 195 public void onSendTextSms( 196 @NonNull String text, int subId, @NonNull String destAddress, 197 int sendSmsFlag, @NonNull ResultCallback<SendSmsResult> callback) { 198 // optional 199 onSendTextSms(text, subId, destAddress, callback); 200 } 201 202 /** 203 * Override this method to intercept binary SMSs sent from the device. 204 * @deprecated Override {@link #onSendDataSms} below instead. 205 * 206 * @param data the binary content 207 * @param subId SMS subscription ID of the SIM 208 * @param destAddress phone number of the recipient of the message 209 * @param destPort the destination port 210 * @param callback result callback. Call with a {@link SendSmsResult}. 211 */ 212 @Deprecated 213 public void onSendDataSms(@NonNull byte[] data, int subId, 214 @NonNull String destAddress, int destPort, 215 @NonNull ResultCallback<SendSmsResult> callback) { 216 // optional 217 try { 218 callback.onReceiveResult(new SendSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0)); 219 } catch (RemoteException ex) { 220 } 221 } 222 223 /** 224 * Override this method to intercept binary SMSs sent from the device. 225 * 226 * @param data the binary content 227 * @param subId SMS subscription ID of the SIM 228 * @param destAddress phone number of the recipient of the message 229 * @param destPort the destination port 230 * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and 231 * {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}. 232 * @param callback result callback. Call with a {@link SendSmsResult}. 233 */ 234 public void onSendDataSms(@NonNull byte[] data, int subId, 235 @NonNull String destAddress, int destPort, int sendSmsFlag, 236 @NonNull ResultCallback<SendSmsResult> callback) { 237 // optional 238 onSendDataSms(data, subId, destAddress, destPort, callback); 239 } 240 241 /** 242 * Override this method to intercept long SMSs sent from the device. 243 * @deprecated Override {@link #onSendMultipartTextSms} below instead. 244 * 245 * @param parts a {@link List} of the message parts 246 * @param subId SMS subscription ID of the SIM 247 * @param destAddress phone number of the recipient of the message 248 * @param callback result callback. Call with a {@link SendMultipartSmsResult}. 249 */ 250 @Deprecated 251 public void onSendMultipartTextSms(@NonNull List<String> parts, 252 int subId, @NonNull String destAddress, 253 @NonNull ResultCallback<SendMultipartSmsResult> callback) { 254 // optional 255 try { 256 callback.onReceiveResult( 257 new SendMultipartSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, null)); 258 } catch (RemoteException ex) { 259 } 260 } 261 262 /** 263 * Override this method to intercept long SMSs sent from the device. 264 * 265 * @param parts a {@link List} of the message parts 266 * @param subId SMS subscription ID of the SIM 267 * @param destAddress phone number of the recipient of the message 268 * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and 269 * {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}. 270 * @param callback result callback. Call with a {@link SendMultipartSmsResult}. 271 */ 272 public void onSendMultipartTextSms(@NonNull List<String> parts, 273 int subId, @NonNull String destAddress, int sendSmsFlag, 274 @NonNull ResultCallback<SendMultipartSmsResult> callback) { 275 // optional 276 onSendMultipartTextSms(parts, subId, destAddress, callback); 277 } 278 279 /** 280 * Override this method to intercept MMSs sent from the device. 281 * 282 * @param pduUri the content provider URI of the PDU to send 283 * @param subId SMS subscription ID of the SIM 284 * @param location the optional URI to send this MMS PDU. If this is {code null}, 285 * the PDU should be sent to the default MMSC URL. 286 * @param callback result callback. Call with a {@link SendMmsResult}. 287 */ 288 public void onSendMms(@NonNull Uri pduUri, int subId, 289 @Nullable Uri location, @NonNull ResultCallback<SendMmsResult> callback) { 290 // optional 291 try { 292 callback.onReceiveResult(new SendMmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, null)); 293 } catch (RemoteException ex) { 294 } 295 } 296 297 /** 298 * Override this method to download MMSs received. 299 * 300 * @param contentUri the content provider URI of the PDU to be downloaded. 301 * @param subId SMS subscription ID of the SIM 302 * @param location the URI of the message to be downloaded. 303 * @param callback result callback. Call with a status code which is one of 304 * {@link #DOWNLOAD_STATUS_OK}, 305 * {@link #DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK}, or {@link #DOWNLOAD_STATUS_ERROR}. 306 */ 307 public void onDownloadMms(@NonNull Uri contentUri, int subId, @NonNull Uri location, 308 @NonNull ResultCallback<Integer> callback) { 309 // optional 310 try { 311 callback.onReceiveResult(DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK); 312 } catch (RemoteException ex) { 313 } 314 } 315 316 @Override 317 public @Nullable IBinder onBind(@NonNull Intent intent) { 318 if (!SERVICE_INTERFACE.equals(intent.getAction())) { 319 return null; 320 } 321 return mWrapper; 322 } 323 324 /** 325 * The result of sending an MMS. 326 */ 327 public static final class SendMmsResult { 328 private int mSendStatus; 329 private byte[] mSendConfPdu; 330 331 /** 332 * Constructs a SendMmsResult with the MMS send result, and the SendConf PDU. 333 * 334 * @param sendStatus send status, one of {@link #SEND_STATUS_OK}, 335 * {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and 336 * {@link #SEND_STATUS_ERROR} 337 * @param sendConfPdu a possibly {code null} SendConf PDU, which confirms that the message 338 * was sent. sendConfPdu is ignored if the {@code result} is not 339 * {@link #SEND_STATUS_OK}. 340 */ 341 public SendMmsResult(int sendStatus, @Nullable byte[] sendConfPdu) { 342 mSendStatus = sendStatus; 343 mSendConfPdu = sendConfPdu; 344 } 345 346 /** 347 * Returns the send status of the just-sent MMS. 348 * 349 * @return the send status which is one of {@link #SEND_STATUS_OK}, 350 * {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR} 351 */ 352 public int getSendStatus() { 353 return mSendStatus; 354 } 355 356 /** 357 * Returns the SendConf PDU, which confirms that the message was sent. 358 * 359 * @return the SendConf PDU 360 */ 361 public @Nullable byte[] getSendConfPdu() { 362 return mSendConfPdu; 363 } 364 } 365 366 /** 367 * The result of sending an SMS. 368 */ 369 public static final class SendSmsResult { 370 private final int mSendStatus; 371 private final int mMessageRef; 372 373 /** 374 * Constructs a SendSmsResult with the send status and message reference for the 375 * just-sent SMS. 376 * 377 * @param sendStatus send status, one of {@link #SEND_STATUS_OK}, 378 * {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR}. 379 * @param messageRef message reference of the just-sent SMS. This field is applicable only 380 * if send status is {@link #SEND_STATUS_OK}. 381 */ 382 public SendSmsResult(int sendStatus, int messageRef) { 383 mSendStatus = sendStatus; 384 mMessageRef = messageRef; 385 } 386 387 /** 388 * Returns the message reference of the just-sent SMS. 389 * 390 * @return the message reference 391 */ 392 public int getMessageRef() { 393 return mMessageRef; 394 } 395 396 /** 397 * Returns the send status of the just-sent SMS. 398 * 399 * @return the send status 400 */ 401 public int getSendStatus() { 402 return mSendStatus; 403 } 404 } 405 406 /** 407 * The result of sending a multipart SMS. 408 */ 409 public static final class SendMultipartSmsResult { 410 private final int mSendStatus; 411 private final int[] mMessageRefs; 412 413 /** 414 * Constructs a SendMultipartSmsResult with the send status and message references for the 415 * just-sent multipart SMS. 416 * 417 * @param sendStatus send status, one of {@link #SEND_STATUS_OK}, 418 * {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR}. 419 * @param messageRefs an array of message references, one for each part of the 420 * multipart SMS. This field is applicable only if send status is 421 * {@link #SEND_STATUS_OK}. 422 */ 423 public SendMultipartSmsResult(int sendStatus, @Nullable int[] messageRefs) { 424 mSendStatus = sendStatus; 425 mMessageRefs = messageRefs; 426 } 427 428 /** 429 * Returns the message references of the just-sent multipart SMS. 430 * 431 * @return the message references, one for each part of the multipart SMS 432 */ 433 public @Nullable int[] getMessageRefs() { 434 return mMessageRefs; 435 } 436 437 /** 438 * Returns the send status of the just-sent SMS. 439 * 440 * @return the send status 441 */ 442 public int getSendStatus() { 443 return mSendStatus; 444 } 445 } 446 447 /** 448 * A callback interface used to provide results asynchronously. 449 */ 450 public interface ResultCallback<T> { 451 /** 452 * Invoked when the result is available. 453 * 454 * @param result the result 455 */ 456 public void onReceiveResult(@NonNull T result) throws RemoteException; 457 }; 458 459 /** 460 * A wrapper around ICarrierMessagingService to enable the carrier messaging app to implement 461 * methods it cares about in the {@link ICarrierMessagingService} interface. 462 */ 463 private class ICarrierMessagingWrapper extends ICarrierMessagingService.Stub { 464 @Override 465 public void filterSms(MessagePdu pdu, String format, int destPort, 466 int subId, final ICarrierMessagingCallback callback) { 467 onReceiveTextSms(pdu, format, destPort, subId, 468 new ResultCallback<Integer>() { 469 @Override 470 public void onReceiveResult(Integer options) throws RemoteException { 471 callback.onFilterComplete(options); 472 } 473 }); 474 } 475 476 @Override 477 public void sendTextSms(String text, int subId, String destAddress, 478 int sendSmsFlag, final ICarrierMessagingCallback callback) { 479 onSendTextSms(text, subId, destAddress, sendSmsFlag, 480 new ResultCallback<SendSmsResult>() { 481 @Override 482 public void onReceiveResult(final SendSmsResult result) throws RemoteException { 483 callback.onSendSmsComplete(result.getSendStatus(), result.getMessageRef()); 484 } 485 }); 486 } 487 488 @Override 489 public void sendDataSms(byte[] data, int subId, String destAddress, int destPort, 490 int sendSmsFlag, final ICarrierMessagingCallback callback) { 491 onSendDataSms(data, subId, destAddress, destPort, sendSmsFlag, 492 new ResultCallback<SendSmsResult>() { 493 @Override 494 public void onReceiveResult(final SendSmsResult result) throws RemoteException { 495 callback.onSendSmsComplete(result.getSendStatus(), result.getMessageRef()); 496 } 497 }); 498 } 499 500 @Override 501 public void sendMultipartTextSms(List<String> parts, int subId, String destAddress, 502 int sendSmsFlag, final ICarrierMessagingCallback callback) { 503 onSendMultipartTextSms(parts, subId, destAddress, sendSmsFlag, 504 new ResultCallback<SendMultipartSmsResult>() { 505 @Override 506 public void onReceiveResult(final SendMultipartSmsResult result) 507 throws RemoteException { 508 callback.onSendMultipartSmsComplete( 509 result.getSendStatus(), result.getMessageRefs()); 510 } 511 }); 512 } 513 514 @Override 515 public void sendMms(Uri pduUri, int subId, Uri location, 516 final ICarrierMessagingCallback callback) { 517 onSendMms(pduUri, subId, location, new ResultCallback<SendMmsResult>() { 518 @Override 519 public void onReceiveResult(final SendMmsResult result) throws RemoteException { 520 callback.onSendMmsComplete(result.getSendStatus(), result.getSendConfPdu()); 521 } 522 }); 523 } 524 525 @Override 526 public void downloadMms(Uri pduUri, int subId, Uri location, 527 final ICarrierMessagingCallback callback) { 528 onDownloadMms(pduUri, subId, location, new ResultCallback<Integer>() { 529 @Override 530 public void onReceiveResult(Integer result) throws RemoteException { 531 callback.onDownloadMmsComplete(result); 532 } 533 }); 534 } 535 } 536} 537