CarrierMessagingService.java revision 08c7116ab9cd04ad6dd3c04aa1017237e7f409ac
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_MESSAGING_SERVICE} 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_MESSAGING_SERVICE"> 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 * Indicates that an SMS or MMS message was successfully sent. 55 */ 56 public static final int SEND_STATUS_OK = 0; 57 58 /** 59 * SMS/MMS sending failed. We should retry via the carrier network. 60 */ 61 public static final int SEND_STATUS_RETRY_ON_CARRIER_NETWORK = 1; 62 63 /** 64 * SMS/MMS sending failed. We should not retry via the carrier network. 65 */ 66 public static final int SEND_STATUS_ERROR = 2; 67 68 /** 69 * Successfully downloaded an MMS message. 70 */ 71 public static final int DOWNLOAD_STATUS_OK = 0; 72 73 /** 74 * MMS downloading failed. We should retry via the carrier network. 75 */ 76 public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; 77 78 /** 79 * MMS downloading failed. We should not retry via the carrier network. 80 */ 81 public static final int DOWNLOAD_STATUS_ERROR = 2; 82 83 private final ICarrierMessagingWrapper mWrapper = new ICarrierMessagingWrapper(); 84 85 /** 86 * Override this method to filter inbound SMS messages. 87 * 88 * @param pdu the PDUs of the message 89 * @param format the format of the PDUs, typically "3gpp" or "3gpp2" 90 * @param destPort the destination port of a binary SMS, this will be -1 for text SMS 91 * @param subId SMS subscription ID of the SIM 92 * @param callback result callback. Call with {@code true} to keep an inbound SMS message and 93 * deliver to SMS apps, and {@code false} to drop the message. 94 */ 95 public void onFilterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort, 96 int subId, @NonNull ResultCallback<Boolean> callback) { 97 // optional 98 try { 99 callback.onReceiveResult(true); 100 } catch (RemoteException ex) { 101 } 102 } 103 104 /** 105 * Override this method to intercept text SMSs sent from the device. 106 * 107 * @param text the text to send 108 * @param subId SMS subscription ID of the SIM 109 * @param destAddress phone number of the recipient of the message 110 * @param callback result callback. Call with a {@link SendSmsResult}. 111 */ 112 public void onSendTextSms( 113 @NonNull String text, int subId, @NonNull String destAddress, 114 @NonNull ResultCallback<SendSmsResult> callback) { 115 // optional 116 try { 117 callback.onReceiveResult(new SendSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0)); 118 } catch (RemoteException ex) { 119 } 120 } 121 122 /** 123 * Override this method to intercept binary SMSs sent from the device. 124 * 125 * @param data the binary content 126 * @param subId SMS subscription ID of the SIM 127 * @param destAddress phone number of the recipient of the message 128 * @param destPort the destination port 129 * @param callback result callback. Call with a {@link SendSmsResult}. 130 */ 131 public void onSendDataSms(@NonNull byte[] data, int subId, 132 @NonNull String destAddress, int destPort, 133 @NonNull ResultCallback<SendSmsResult> callback) { 134 // optional 135 try { 136 callback.onReceiveResult(new SendSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0)); 137 } catch (RemoteException ex) { 138 } 139 } 140 141 /** 142 * Override this method to intercept long SMSs sent from the device. 143 * 144 * @param parts a {@link List} of the message parts 145 * @param subId SMS subscription ID of the SIM 146 * @param destAddress phone number of the recipient of the message 147 * @param callback result callback. Call with a {@link SendMultipartSmsResult}. 148 */ 149 public void onSendMultipartTextSms(@NonNull List<String> parts, 150 int subId, @NonNull String destAddress, 151 @NonNull ResultCallback<SendMultipartSmsResult> callback) { 152 // optional 153 try { 154 callback.onReceiveResult( 155 new SendMultipartSmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, null)); 156 } catch (RemoteException ex) { 157 } 158 } 159 160 /** 161 * Override this method to intercept MMSs sent from the device. 162 * 163 * @param pduUri the content provider URI of the PDU to send 164 * @param subId SMS subscription ID of the SIM 165 * @param location the optional URI to send this MMS PDU. If this is {code null}, 166 * the PDU should be sent to the default MMSC URL. 167 * @param callback result callback. Call with a {@link SendMmsResult}. 168 */ 169 public void onSendMms(@NonNull Uri pduUri, int subId, 170 @Nullable Uri location, @NonNull ResultCallback<SendMmsResult> callback) { 171 // optional 172 try { 173 callback.onReceiveResult(new SendMmsResult(SEND_STATUS_RETRY_ON_CARRIER_NETWORK, null)); 174 } catch (RemoteException ex) { 175 } 176 } 177 178 /** 179 * Override this method to download MMSs received. 180 * 181 * @param contentUri the content provider URI of the PDU to be downloaded. 182 * @param subId SMS subscription ID of the SIM 183 * @param location the URI of the message to be downloaded. 184 * @param callback result callback. Call with a status code which is one of 185 * {@link #DOWNLOAD_STATUS_OK}, 186 * {@link #DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK}, or {@link #DOWNLOAD_STATUS_ERROR}. 187 */ 188 public void onDownloadMms(@NonNull Uri contentUri, int subId, @NonNull Uri location, 189 @NonNull ResultCallback<Integer> callback) { 190 // optional 191 try { 192 callback.onReceiveResult(DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK); 193 } catch (RemoteException ex) { 194 } 195 } 196 197 @Override 198 public @Nullable IBinder onBind(@NonNull Intent intent) { 199 if (!SERVICE_INTERFACE.equals(intent.getAction())) { 200 return null; 201 } 202 return mWrapper; 203 } 204 205 /** 206 * The result of sending an MMS. 207 */ 208 public static final class SendMmsResult { 209 private int mSendStatus; 210 private byte[] mSendConfPdu; 211 212 /** 213 * Constructs a SendMmsResult with the MMS send result, and the SendConf PDU. 214 * 215 * @param sendStatus send status, one of {@link #SEND_STATUS_OK}, 216 * {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and 217 * {@link #SEND_STATUS_ERROR} 218 * @param sendConfPdu a possibly {code null} SendConf PDU, which confirms that the message 219 * was sent. sendConfPdu is ignored if the {@code result} is not 220 * {@link #SEND_STATUS_OK}. 221 */ 222 public SendMmsResult(int sendStatus, @Nullable byte[] sendConfPdu) { 223 mSendStatus = sendStatus; 224 mSendConfPdu = sendConfPdu; 225 } 226 227 /** 228 * Returns the send status of the just-sent MMS. 229 * 230 * @return the send status which is one of {@link #SEND_STATUS_OK}, 231 * {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR} 232 */ 233 public int getSendStatus() { 234 return mSendStatus; 235 } 236 237 /** 238 * Returns the SendConf PDU, which confirms that the message was sent. 239 * 240 * @return the SendConf PDU 241 */ 242 public @Nullable byte[] getSendConfPdu() { 243 return mSendConfPdu; 244 } 245 } 246 247 /** 248 * The result of sending an SMS. 249 */ 250 public static final class SendSmsResult { 251 private final int mSendStatus; 252 private final int mMessageRef; 253 254 /** 255 * Constructs a SendSmsResult with the send status and message reference for the 256 * just-sent SMS. 257 * 258 * @param sendStatus send status, one of {@link #SEND_STATUS_OK}, 259 * {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR}. 260 * @param messageRef message reference of the just-sent SMS. This field is applicable only 261 * if send status is {@link #SEND_STATUS_OK}. 262 */ 263 public SendSmsResult(int sendStatus, int messageRef) { 264 mSendStatus = sendStatus; 265 mMessageRef = messageRef; 266 } 267 268 /** 269 * Returns the message reference of the just-sent SMS. 270 * 271 * @return the message reference 272 */ 273 public int getMessageRef() { 274 return mMessageRef; 275 } 276 277 /** 278 * Returns the send status of the just-sent SMS. 279 * 280 * @return the send status 281 */ 282 public int getSendStatus() { 283 return mSendStatus; 284 } 285 } 286 287 /** 288 * The result of sending a multipart SMS. 289 */ 290 public static final class SendMultipartSmsResult { 291 private final int mSendStatus; 292 private final int[] mMessageRefs; 293 294 /** 295 * Constructs a SendMultipartSmsResult with the send status and message references for the 296 * just-sent multipart SMS. 297 * 298 * @param sendStatus send status, one of {@link #SEND_STATUS_OK}, 299 * {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR}. 300 * @param messageRefs an array of message references, one for each part of the 301 * multipart SMS. This field is applicable only if send status is 302 * {@link #SEND_STATUS_OK}. 303 */ 304 public SendMultipartSmsResult(int sendStatus, @Nullable int[] messageRefs) { 305 mSendStatus = sendStatus; 306 mMessageRefs = messageRefs; 307 } 308 309 /** 310 * Returns the message references of the just-sent multipart SMS. 311 * 312 * @return the message references, one for each part of the multipart SMS 313 */ 314 public @Nullable int[] getMessageRefs() { 315 return mMessageRefs; 316 } 317 318 /** 319 * Returns the send status of the just-sent SMS. 320 * 321 * @return the send status 322 */ 323 public int getSendStatus() { 324 return mSendStatus; 325 } 326 } 327 328 /** 329 * A callback interface used to provide results asynchronously. 330 */ 331 public interface ResultCallback<T> { 332 /** 333 * Invoked when the result is available. 334 * 335 * @param result the result 336 */ 337 public void onReceiveResult(@NonNull T result) throws RemoteException; 338 }; 339 340 /** 341 * A wrapper around ICarrierMessagingService to enable the carrier messaging app to implement 342 * methods it cares about in the {@link ICarrierMessagingService} interface. 343 */ 344 private class ICarrierMessagingWrapper extends ICarrierMessagingService.Stub { 345 @Override 346 public void filterSms(MessagePdu pdu, String format, int destPort, 347 int subId, final ICarrierMessagingCallback callback) { 348 onFilterSms(pdu, format, destPort, subId, new ResultCallback<Boolean>() { 349 @Override 350 public void onReceiveResult(final Boolean result) throws RemoteException { 351 callback.onFilterComplete(result); 352 } 353 }); 354 } 355 356 @Override 357 public void sendTextSms(String text, int subId, String destAddress, 358 final ICarrierMessagingCallback callback) { 359 onSendTextSms(text, subId, destAddress, new ResultCallback<SendSmsResult>() { 360 @Override 361 public void onReceiveResult(final SendSmsResult result) throws RemoteException { 362 callback.onSendSmsComplete(result.getSendStatus(), result.getMessageRef()); 363 } 364 }); 365 } 366 367 @Override 368 public void sendDataSms(byte[] data, int subId, String destAddress, int destPort, 369 final ICarrierMessagingCallback callback) { 370 onSendDataSms(data, subId, destAddress, destPort, new ResultCallback<SendSmsResult>() { 371 @Override 372 public void onReceiveResult(final SendSmsResult result) throws RemoteException { 373 callback.onSendSmsComplete(result.getSendStatus(), result.getMessageRef()); 374 } 375 }); 376 } 377 378 @Override 379 public void sendMultipartTextSms(List<String> parts, int subId, String destAddress, 380 final ICarrierMessagingCallback callback) { 381 onSendMultipartTextSms(parts, subId, destAddress, 382 new ResultCallback<SendMultipartSmsResult>() { 383 @Override 384 public void onReceiveResult(final SendMultipartSmsResult result) 385 throws RemoteException { 386 callback.onSendMultipartSmsComplete( 387 result.getSendStatus(), result.getMessageRefs()); 388 } 389 }); 390 } 391 392 @Override 393 public void sendMms(Uri pduUri, int subId, Uri location, 394 final ICarrierMessagingCallback callback) { 395 onSendMms(pduUri, subId, location, new ResultCallback<SendMmsResult>() { 396 @Override 397 public void onReceiveResult(final SendMmsResult result) throws RemoteException { 398 callback.onSendMmsComplete(result.getSendStatus(), result.getSendConfPdu()); 399 } 400 }); 401 } 402 403 @Override 404 public void downloadMms(Uri pduUri, int subId, Uri location, 405 final ICarrierMessagingCallback callback) { 406 onDownloadMms(pduUri, subId, location, new ResultCallback<Integer>() { 407 @Override 408 public void onReceiveResult(Integer result) throws RemoteException { 409 callback.onDownloadMmsComplete(result); 410 } 411 }); 412 } 413 } 414} 415