1 /* 2 * Copyright (C) 2008 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.telephony; 18 19 import android.app.ActivityThread; 20 import android.app.PendingIntent; 21 import android.content.ActivityNotFoundException; 22 import android.content.ContentValues; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.net.Uri; 26 import android.os.Bundle; 27 import android.os.RemoteException; 28 import android.os.ServiceManager; 29 import android.text.TextUtils; 30 import android.util.ArrayMap; 31 import android.util.Log; 32 33 import com.android.internal.telephony.ISms; 34 import com.android.internal.telephony.SmsRawData; 35 import com.android.internal.telephony.IMms; 36 import com.android.internal.telephony.uicc.IccConstants; 37 38 import java.util.ArrayList; 39 import java.util.Arrays; 40 import java.util.List; 41 import java.util.Map; 42 43 /* 44 * TODO(code review): Curious question... Why are a lot of these 45 * methods not declared as static, since they do not seem to require 46 * any local object state? Presumably this cannot be changed without 47 * interfering with the API... 48 */ 49 50 /** 51 * Manages SMS operations such as sending data, text, and pdu SMS messages. 52 * Get this object by calling the static method {@link #getDefault()}. 53 * 54 * <p>For information about how to behave as the default SMS app on Android 4.4 (API level 19) 55 * and higher, see {@link android.provider.Telephony}. 56 */ 57 public final class SmsManager { 58 private static final String TAG = "SmsManager"; 59 /** 60 * A psuedo-subId that represents the default subId at any given time. The actual subId it 61 * represents changes as the default subId is changed. 62 */ 63 private static final int DEFAULT_SUBSCRIPTION_ID = -1002; 64 65 /** Singleton object constructed during class initialization. */ 66 private static final SmsManager sInstance = new SmsManager(DEFAULT_SUBSCRIPTION_ID); 67 private static final Object sLockObject = new Object(); 68 69 /** @hide */ 70 public static final int CELL_BROADCAST_RAN_TYPE_GSM = 0; 71 /** @hide */ 72 public static final int CELL_BROADCAST_RAN_TYPE_CDMA = 1; 73 74 private static final Map<Integer, SmsManager> sSubInstances = 75 new ArrayMap<Integer, SmsManager>(); 76 77 /** A concrete subscription id, or the pseudo DEFAULT_SUBSCRIPTION_ID */ 78 private int mSubId; 79 80 /* 81 * Key for the various carrier-dependent configuration values. 82 * Some of the values are used by the system in processing SMS or MMS messages. Others 83 * are provided for the convenience of SMS applications. 84 */ 85 86 /** 87 * Whether to append transaction id to MMS WAP Push M-Notification.ind's content location URI 88 * when constructing the download URL of a new MMS (boolean type) 89 */ 90 public static final String MMS_CONFIG_APPEND_TRANSACTION_ID = "enabledTransID"; 91 /** 92 * Whether MMS is enabled for the current carrier (boolean type) 93 */ 94 public static final String MMS_CONFIG_MMS_ENABLED = "enabledMMS"; 95 /** 96 * Whether group MMS is enabled for the current carrier (boolean type) 97 */ 98 public static final String MMS_CONFIG_GROUP_MMS_ENABLED = "enableGroupMms"; 99 /** 100 * If this is enabled, M-NotifyResp.ind should be sent to the WAP Push content location 101 * instead of the default MMSC (boolean type) 102 */ 103 public static final String MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED = "enabledNotifyWapMMSC"; 104 /** 105 * Whether alias is enabled (boolean type) 106 */ 107 public static final String MMS_CONFIG_ALIAS_ENABLED = "aliasEnabled"; 108 /** 109 * Whether audio is allowed to be attached for MMS messages (boolean type) 110 */ 111 public static final String MMS_CONFIG_ALLOW_ATTACH_AUDIO = "allowAttachAudio"; 112 /** 113 * Whether multipart SMS is enabled (boolean type) 114 */ 115 public static final String MMS_CONFIG_MULTIPART_SMS_ENABLED = "enableMultipartSMS"; 116 /** 117 * Whether SMS delivery report is enabled (boolean type) 118 */ 119 public static final String MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED = "enableSMSDeliveryReports"; 120 /** 121 * Whether content-disposition field should be expected in an MMS PDU (boolean type) 122 */ 123 public static final String MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION = 124 "supportMmsContentDisposition"; 125 /** 126 * Whether multipart SMS should be sent as separate messages 127 */ 128 public static final String MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES = 129 "sendMultipartSmsAsSeparateMessages"; 130 /** 131 * Whether MMS read report is enabled (boolean type) 132 */ 133 public static final String MMS_CONFIG_MMS_READ_REPORT_ENABLED = "enableMMSReadReports"; 134 /** 135 * Whether MMS delivery report is enabled (boolean type) 136 */ 137 public static final String MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED = "enableMMSDeliveryReports"; 138 /** 139 * Max MMS message size in bytes (int type) 140 */ 141 public static final String MMS_CONFIG_MAX_MESSAGE_SIZE = "maxMessageSize"; 142 /** 143 * Max MMS image width (int type) 144 */ 145 public static final String MMS_CONFIG_MAX_IMAGE_WIDTH = "maxImageWidth"; 146 /** 147 * Max MMS image height (int type) 148 */ 149 public static final String MMS_CONFIG_MAX_IMAGE_HEIGHT = "maxImageHeight"; 150 /** 151 * Limit of recipients of MMS messages (int type) 152 */ 153 public static final String MMS_CONFIG_RECIPIENT_LIMIT = "recipientLimit"; 154 /** 155 * Min alias character count (int type) 156 */ 157 public static final String MMS_CONFIG_ALIAS_MIN_CHARS = "aliasMinChars"; 158 /** 159 * Max alias character count (int type) 160 */ 161 public static final String MMS_CONFIG_ALIAS_MAX_CHARS = "aliasMaxChars"; 162 /** 163 * When the number of parts of a multipart SMS reaches this threshold, it should be 164 * converted into an MMS (int type) 165 */ 166 public static final String MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD = "smsToMmsTextThreshold"; 167 /** 168 * Some carriers require SMS to be converted into MMS when text length reaches this threshold 169 * (int type) 170 */ 171 public static final String MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD = 172 "smsToMmsTextLengthThreshold"; 173 /** 174 * Max message text size (int type) 175 */ 176 public static final String MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE = "maxMessageTextSize"; 177 /** 178 * Max message subject length (int type) 179 */ 180 public static final String MMS_CONFIG_SUBJECT_MAX_LENGTH = "maxSubjectLength"; 181 /** 182 * MMS HTTP socket timeout in milliseconds (int type) 183 */ 184 public static final String MMS_CONFIG_HTTP_SOCKET_TIMEOUT = "httpSocketTimeout"; 185 /** 186 * The name of the UA Prof URL HTTP header for MMS HTTP request (String type) 187 */ 188 public static final String MMS_CONFIG_UA_PROF_TAG_NAME = "uaProfTagName"; 189 /** 190 * The User-Agent header value for MMS HTTP request (String type) 191 */ 192 public static final String MMS_CONFIG_USER_AGENT = "userAgent"; 193 /** 194 * The UA Profile URL header value for MMS HTTP request (String type) 195 */ 196 public static final String MMS_CONFIG_UA_PROF_URL = "uaProfUrl"; 197 /** 198 * A list of HTTP headers to add to MMS HTTP request, separated by "|" (String type) 199 */ 200 public static final String MMS_CONFIG_HTTP_PARAMS = "httpParams"; 201 /** 202 * Email gateway number (String type) 203 */ 204 public static final String MMS_CONFIG_EMAIL_GATEWAY_NUMBER = "emailGatewayNumber"; 205 /** 206 * The suffix to append to the NAI header value for MMS HTTP request (String type) 207 */ 208 public static final String MMS_CONFIG_NAI_SUFFIX = "naiSuffix"; 209 /** 210 * If true, show the cell broadcast (amber alert) in the SMS settings. Some carriers 211 * don't want this shown. (Boolean type) 212 */ 213 public static final String MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS = 214 "config_cellBroadcastAppLinks"; 215 /* 216 * Forwarded constants from SimDialogActivity. 217 */ 218 private static String DIALOG_TYPE_KEY = "dialog_type"; 219 private static final int SMS_PICK = 2; 220 221 /** 222 * Send a text based SMS. 223 * 224 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 225 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 226 * 227 * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if 228 * <em>and only if</em> an app is not selected as the default SMS app, the system automatically 229 * writes messages sent using this method to the SMS Provider (the default SMS app is always 230 * responsible for writing its sent messages to the SMS Provider). For information about 231 * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p> 232 * 233 * 234 * @param destinationAddress the address to send the message to 235 * @param scAddress is the service center address or null to use 236 * the current default SMSC 237 * @param text the body of the message to send 238 * @param sentIntent if not NULL this <code>PendingIntent</code> is 239 * broadcast when the message is successfully sent, or failed. 240 * The result code will be <code>Activity.RESULT_OK</code> for success, 241 * or one of these errors:<br> 242 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 243 * <code>RESULT_ERROR_RADIO_OFF</code><br> 244 * <code>RESULT_ERROR_NULL_PDU</code><br> 245 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 246 * the extra "errorCode" containing a radio technology specific value, 247 * generally only useful for troubleshooting.<br> 248 * The per-application based SMS control checks sentIntent. If sentIntent 249 * is NULL the caller will be checked against all unknown applications, 250 * which cause smaller number of SMS to be sent in checking period. 251 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 252 * broadcast when the message is delivered to the recipient. The 253 * raw pdu of the status report is in the extended data ("pdu"). 254 * 255 * @throws IllegalArgumentException if destinationAddress or text are empty 256 */ sendTextMessage( String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)257 public void sendTextMessage( 258 String destinationAddress, String scAddress, String text, 259 PendingIntent sentIntent, PendingIntent deliveryIntent) { 260 if (TextUtils.isEmpty(destinationAddress)) { 261 throw new IllegalArgumentException("Invalid destinationAddress"); 262 } 263 264 if (TextUtils.isEmpty(text)) { 265 throw new IllegalArgumentException("Invalid message body"); 266 } 267 268 try { 269 ISms iccISms = getISmsServiceOrThrow(); 270 iccISms.sendTextForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), 271 destinationAddress, 272 scAddress, text, sentIntent, deliveryIntent); 273 } catch (RemoteException ex) { 274 // ignore it 275 } 276 } 277 278 /** 279 * Inject an SMS PDU into the android application framework. 280 * 281 * The caller should have carrier privileges. 282 * @see android.telephony.TelephonyManager.hasCarrierPrivileges 283 * 284 * @param pdu is the byte array of pdu to be injected into android application framework 285 * @param format is the format of SMS pdu (3gpp or 3gpp2) 286 * @param receivedIntent if not NULL this <code>PendingIntent</code> is 287 * broadcast when the message is successfully received by the 288 * android application framework, or failed. This intent is broadcasted at 289 * the same time an SMS received from radio is acknowledged back. 290 * The result code will be <code>RESULT_SMS_HANDLED</code> for success, or 291 * <code>RESULT_SMS_GENERIC_ERROR</code> for error. 292 * 293 * @throws IllegalArgumentException if format is not one of 3gpp and 3gpp2. 294 */ injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent)295 public void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) { 296 if (!format.equals(SmsMessage.FORMAT_3GPP) && !format.equals(SmsMessage.FORMAT_3GPP2)) { 297 // Format must be either 3gpp or 3gpp2. 298 throw new IllegalArgumentException( 299 "Invalid pdu format. format must be either 3gpp or 3gpp2"); 300 } 301 try { 302 ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 303 if (iccISms != null) { 304 iccISms.injectSmsPdu(pdu, format, receivedIntent); 305 } 306 } catch (RemoteException ex) { 307 // ignore it 308 } 309 } 310 311 /** 312 * Divide a message text into several fragments, none bigger than 313 * the maximum SMS message size. 314 * 315 * @param text the original message. Must not be null. 316 * @return an <code>ArrayList</code> of strings that, in order, 317 * comprise the original message 318 * 319 * @throws IllegalArgumentException if text is null 320 */ divideMessage(String text)321 public ArrayList<String> divideMessage(String text) { 322 if (null == text) { 323 throw new IllegalArgumentException("text is null"); 324 } 325 return SmsMessage.fragmentText(text); 326 } 327 328 /** 329 * Send a multi-part text based SMS. The callee should have already 330 * divided the message into correctly sized parts by calling 331 * <code>divideMessage</code>. 332 * 333 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 334 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 335 * 336 * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if 337 * <em>and only if</em> an app is not selected as the default SMS app, the system automatically 338 * writes messages sent using this method to the SMS Provider (the default SMS app is always 339 * responsible for writing its sent messages to the SMS Provider). For information about 340 * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p> 341 * 342 * @param destinationAddress the address to send the message to 343 * @param scAddress is the service center address or null to use 344 * the current default SMSC 345 * @param parts an <code>ArrayList</code> of strings that, in order, 346 * comprise the original message 347 * @param sentIntents if not null, an <code>ArrayList</code> of 348 * <code>PendingIntent</code>s (one for each message part) that is 349 * broadcast when the corresponding message part has been sent. 350 * The result code will be <code>Activity.RESULT_OK</code> for success, 351 * or one of these errors:<br> 352 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 353 * <code>RESULT_ERROR_RADIO_OFF</code><br> 354 * <code>RESULT_ERROR_NULL_PDU</code><br> 355 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include 356 * the extra "errorCode" containing a radio technology specific value, 357 * generally only useful for troubleshooting.<br> 358 * The per-application based SMS control checks sentIntent. If sentIntent 359 * is NULL the caller will be checked against all unknown applications, 360 * which cause smaller number of SMS to be sent in checking period. 361 * @param deliveryIntents if not null, an <code>ArrayList</code> of 362 * <code>PendingIntent</code>s (one for each message part) that is 363 * broadcast when the corresponding message part has been delivered 364 * to the recipient. The raw pdu of the status report is in the 365 * extended data ("pdu"). 366 * 367 * @throws IllegalArgumentException if destinationAddress or data are empty 368 */ sendMultipartTextMessage( String destinationAddress, String scAddress, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents)369 public void sendMultipartTextMessage( 370 String destinationAddress, String scAddress, ArrayList<String> parts, 371 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { 372 if (TextUtils.isEmpty(destinationAddress)) { 373 throw new IllegalArgumentException("Invalid destinationAddress"); 374 } 375 if (parts == null || parts.size() < 1) { 376 throw new IllegalArgumentException("Invalid message body"); 377 } 378 379 if (parts.size() > 1) { 380 try { 381 ISms iccISms = getISmsServiceOrThrow(); 382 iccISms.sendMultipartTextForSubscriber(getSubscriptionId(), 383 ActivityThread.currentPackageName(), 384 destinationAddress, scAddress, parts, 385 sentIntents, deliveryIntents); 386 } catch (RemoteException ex) { 387 // ignore it 388 } 389 } else { 390 PendingIntent sentIntent = null; 391 PendingIntent deliveryIntent = null; 392 if (sentIntents != null && sentIntents.size() > 0) { 393 sentIntent = sentIntents.get(0); 394 } 395 if (deliveryIntents != null && deliveryIntents.size() > 0) { 396 deliveryIntent = deliveryIntents.get(0); 397 } 398 sendTextMessage(destinationAddress, scAddress, parts.get(0), 399 sentIntent, deliveryIntent); 400 } 401 } 402 403 /** 404 * Send a data based SMS to a specific application port. 405 * 406 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 407 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 408 * 409 * @param destinationAddress the address to send the message to 410 * @param scAddress is the service center address or null to use 411 * the current default SMSC 412 * @param destinationPort the port to deliver the message to 413 * @param data the body of the message to send 414 * @param sentIntent if not NULL this <code>PendingIntent</code> is 415 * broadcast when the message is successfully sent, or failed. 416 * The result code will be <code>Activity.RESULT_OK</code> for success, 417 * or one of these errors:<br> 418 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 419 * <code>RESULT_ERROR_RADIO_OFF</code><br> 420 * <code>RESULT_ERROR_NULL_PDU</code><br> 421 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 422 * the extra "errorCode" containing a radio technology specific value, 423 * generally only useful for troubleshooting.<br> 424 * The per-application based SMS control checks sentIntent. If sentIntent 425 * is NULL the caller will be checked against all unknown applications, 426 * which cause smaller number of SMS to be sent in checking period. 427 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 428 * broadcast when the message is delivered to the recipient. The 429 * raw pdu of the status report is in the extended data ("pdu"). 430 * 431 * @throws IllegalArgumentException if destinationAddress or data are empty 432 */ sendDataMessage( String destinationAddress, String scAddress, short destinationPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)433 public void sendDataMessage( 434 String destinationAddress, String scAddress, short destinationPort, 435 byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { 436 if (TextUtils.isEmpty(destinationAddress)) { 437 throw new IllegalArgumentException("Invalid destinationAddress"); 438 } 439 440 if (data == null || data.length == 0) { 441 throw new IllegalArgumentException("Invalid message data"); 442 } 443 444 try { 445 ISms iccISms = getISmsServiceOrThrow(); 446 iccISms.sendDataForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), 447 destinationAddress, scAddress, destinationPort & 0xFFFF, 448 data, sentIntent, deliveryIntent); 449 } catch (RemoteException ex) { 450 // ignore it 451 } 452 } 453 454 /** 455 * Get the SmsManager associated with the default subscription id. The instance will always be 456 * associated with the default subscription id, even if the default subscription id is changed. 457 * 458 * @return the SmsManager associated with the default subscription id 459 */ getDefault()460 public static SmsManager getDefault() { 461 return sInstance; 462 } 463 464 /** 465 * Get the the instance of the SmsManager associated with a particular subscription id 466 * 467 * @param subId an SMS subscription id, typically accessed using 468 * {@link android.telephony.SubscriptionManager} 469 * @return the instance of the SmsManager associated with subId 470 */ getSmsManagerForSubscriptionId(int subId)471 public static SmsManager getSmsManagerForSubscriptionId(int subId) { 472 // TODO(shri): Add javadoc link once SubscriptionManager is made public api 473 synchronized(sLockObject) { 474 SmsManager smsManager = sSubInstances.get(subId); 475 if (smsManager == null) { 476 smsManager = new SmsManager(subId); 477 sSubInstances.put(subId, smsManager); 478 } 479 return smsManager; 480 } 481 } 482 SmsManager(int subId)483 private SmsManager(int subId) { 484 mSubId = subId; 485 } 486 487 /** 488 * Get the associated subscription id. If the instance was returned by {@link #getDefault()}, 489 * then this method may return different values at different points in time (if the user 490 * changes the default subscription id). It will return < 0 if the default subscription id 491 * cannot be determined. 492 * 493 * Additionally, to support legacy applications that are not multi-SIM aware, 494 * if the following are true: 495 * - We are using a multi-SIM device 496 * - A default SMS SIM has not been selected 497 * - At least one SIM subscription is available 498 * then ask the user to set the default SMS SIM. 499 * 500 * @return associated subscription id 501 */ getSubscriptionId()502 public int getSubscriptionId() { 503 final int subId = (mSubId == DEFAULT_SUBSCRIPTION_ID) 504 ? getDefaultSmsSubscriptionId() : mSubId; 505 boolean isSmsSimPickActivityNeeded = false; 506 final Context context = ActivityThread.currentApplication().getApplicationContext(); 507 try { 508 ISms iccISms = getISmsService(); 509 if (iccISms != null) { 510 isSmsSimPickActivityNeeded = iccISms.isSmsSimPickActivityNeeded(subId); 511 } 512 } catch (RemoteException ex) { 513 Log.e(TAG, "Exception in getSubscriptionId"); 514 } 515 516 if (isSmsSimPickActivityNeeded) { 517 Log.d(TAG, "getSubscriptionId isSmsSimPickActivityNeeded is true"); 518 // ask the user for a default SMS SIM. 519 Intent intent = new Intent(); 520 intent.setClassName("com.android.settings", 521 "com.android.settings.sim.SimDialogActivity"); 522 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 523 intent.putExtra(DIALOG_TYPE_KEY, SMS_PICK); 524 try { 525 context.startActivity(intent); 526 } catch (ActivityNotFoundException anfe) { 527 // If Settings is not installed, only log the error as we do not want to break 528 // legacy applications. 529 Log.e(TAG, "Unable to launch Settings application."); 530 } 531 } 532 533 return subId; 534 } 535 536 /** 537 * Returns the ISms service, or throws an UnsupportedOperationException if 538 * the service does not exist. 539 */ getISmsServiceOrThrow()540 private static ISms getISmsServiceOrThrow() { 541 ISms iccISms = getISmsService(); 542 if (iccISms == null) { 543 throw new UnsupportedOperationException("Sms is not supported"); 544 } 545 return iccISms; 546 } 547 getISmsService()548 private static ISms getISmsService() { 549 return ISms.Stub.asInterface(ServiceManager.getService("isms")); 550 } 551 552 /** 553 * Copy a raw SMS PDU to the ICC. 554 * ICC (Integrated Circuit Card) is the card of the device. 555 * For example, this can be the SIM or USIM for GSM. 556 * 557 * @param smsc the SMSC for this message, or NULL for the default SMSC 558 * @param pdu the raw PDU to store 559 * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD, 560 * STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT) 561 * @return true for success 562 * 563 * @throws IllegalArgumentException if pdu is NULL 564 * {@hide} 565 */ copyMessageToIcc(byte[] smsc, byte[] pdu,int status)566 public boolean copyMessageToIcc(byte[] smsc, byte[] pdu,int status) { 567 boolean success = false; 568 569 if (null == pdu) { 570 throw new IllegalArgumentException("pdu is NULL"); 571 } 572 try { 573 ISms iccISms = getISmsService(); 574 if (iccISms != null) { 575 success = iccISms.copyMessageToIccEfForSubscriber(getSubscriptionId(), 576 ActivityThread.currentPackageName(), 577 status, pdu, smsc); 578 } 579 } catch (RemoteException ex) { 580 // ignore it 581 } 582 583 return success; 584 } 585 586 /** 587 * Delete the specified message from the ICC. 588 * ICC (Integrated Circuit Card) is the card of the device. 589 * For example, this can be the SIM or USIM for GSM. 590 * 591 * @param messageIndex is the record index of the message on ICC 592 * @return true for success 593 * 594 * {@hide} 595 */ 596 public boolean deleteMessageFromIcc(int messageIndex)597 deleteMessageFromIcc(int messageIndex) { 598 boolean success = false; 599 byte[] pdu = new byte[IccConstants.SMS_RECORD_LENGTH-1]; 600 Arrays.fill(pdu, (byte)0xff); 601 602 try { 603 ISms iccISms = getISmsService(); 604 if (iccISms != null) { 605 success = iccISms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), 606 ActivityThread.currentPackageName(), 607 messageIndex, STATUS_ON_ICC_FREE, pdu); 608 } 609 } catch (RemoteException ex) { 610 // ignore it 611 } 612 613 return success; 614 } 615 616 /** 617 * Update the specified message on the ICC. 618 * ICC (Integrated Circuit Card) is the card of the device. 619 * For example, this can be the SIM or USIM for GSM. 620 * 621 * @param messageIndex record index of message to update 622 * @param newStatus new message status (STATUS_ON_ICC_READ, 623 * STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT, 624 * STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE) 625 * @param pdu the raw PDU to store 626 * @return true for success 627 * 628 * {@hide} 629 */ updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu)630 public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) { 631 boolean success = false; 632 633 try { 634 ISms iccISms = getISmsService(); 635 if (iccISms != null) { 636 success = iccISms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), 637 ActivityThread.currentPackageName(), 638 messageIndex, newStatus, pdu); 639 } 640 } catch (RemoteException ex) { 641 // ignore it 642 } 643 644 return success; 645 } 646 647 /** 648 * Retrieves all messages currently stored on ICC. 649 * ICC (Integrated Circuit Card) is the card of the device. 650 * For example, this can be the SIM or USIM for GSM. 651 * 652 * @return <code>ArrayList</code> of <code>SmsMessage</code> objects 653 * 654 * {@hide} 655 */ getAllMessagesFromIcc()656 public ArrayList<SmsMessage> getAllMessagesFromIcc() { 657 List<SmsRawData> records = null; 658 659 try { 660 ISms iccISms = getISmsService(); 661 if (iccISms != null) { 662 records = iccISms.getAllMessagesFromIccEfForSubscriber( 663 getSubscriptionId(), 664 ActivityThread.currentPackageName()); 665 } 666 } catch (RemoteException ex) { 667 // ignore it 668 } 669 670 return createMessageListFromRawRecords(records); 671 } 672 673 /** 674 * Enable reception of cell broadcast (SMS-CB) messages with the given 675 * message identifier and RAN type. The RAN type specify this message ID 676 * belong to 3GPP (GSM) or 3GPP2(CDMA).Note that if two different clients 677 * enable the same message identifier, they must both disable it for the device to stop 678 * receiving those messages. All received messages will be broadcast in an 679 * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED". 680 * Note: This call is blocking, callers may want to avoid calling it from 681 * the main thread of an application. 682 * 683 * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) 684 * or C.R1001-G (3GPP2) 685 * @param ranType as defined in class SmsManager, the value can be one of these: 686 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM 687 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA 688 * @return true if successful, false otherwise 689 * @see #disableCellBroadcast(int, int) 690 * 691 * {@hide} 692 */ enableCellBroadcast(int messageIdentifier, int ranType)693 public boolean enableCellBroadcast(int messageIdentifier, int ranType) { 694 boolean success = false; 695 696 try { 697 ISms iccISms = getISmsService(); 698 if (iccISms != null) { 699 success = iccISms.enableCellBroadcastForSubscriber( 700 getSubscriptionId(), messageIdentifier, ranType); 701 } 702 } catch (RemoteException ex) { 703 // ignore it 704 } 705 706 return success; 707 } 708 709 /** 710 * Disable reception of cell broadcast (SMS-CB) messages with the given 711 * message identifier and RAN type. The RAN type specify this message ID 712 * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients 713 * enable the same message identifier, they must both disable it for the 714 * device to stop receiving those messages. 715 * Note: This call is blocking, callers may want to avoid calling it from 716 * the main thread of an application. 717 * 718 * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) 719 * or C.R1001-G (3GPP2) 720 * @param ranType as defined in class SmsManager, the value can be one of these: 721 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM 722 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA 723 * @return true if successful, false otherwise 724 * 725 * @see #enableCellBroadcast(int, int) 726 * 727 * {@hide} 728 */ disableCellBroadcast(int messageIdentifier, int ranType)729 public boolean disableCellBroadcast(int messageIdentifier, int ranType) { 730 boolean success = false; 731 732 try { 733 ISms iccISms = getISmsService(); 734 if (iccISms != null) { 735 success = iccISms.disableCellBroadcastForSubscriber( 736 getSubscriptionId(), messageIdentifier, ranType); 737 } 738 } catch (RemoteException ex) { 739 // ignore it 740 } 741 742 return success; 743 } 744 745 /** 746 * Enable reception of cell broadcast (SMS-CB) messages with the given 747 * message identifier range and RAN type. The RAN type specify this message ID 748 * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients enable 749 * the same message identifier, they must both disable it for the device to stop 750 * receiving those messages. All received messages will be broadcast in an 751 * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED". 752 * Note: This call is blocking, callers may want to avoid calling it from 753 * the main thread of an application. 754 * 755 * @param startMessageId first message identifier as specified in TS 23.041 (3GPP) 756 * or C.R1001-G (3GPP2) 757 * @param endMessageId last message identifier as specified in TS 23.041 (3GPP) 758 * or C.R1001-G (3GPP2) 759 * @param ranType as defined in class SmsManager, the value can be one of these: 760 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM 761 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA 762 * @return true if successful, false otherwise 763 * @see #disableCellBroadcastRange(int, int, int) 764 * 765 * @throws IllegalArgumentException if endMessageId < startMessageId 766 * {@hide} 767 */ enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType)768 public boolean enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) { 769 boolean success = false; 770 771 if (endMessageId < startMessageId) { 772 throw new IllegalArgumentException("endMessageId < startMessageId"); 773 } 774 try { 775 ISms iccISms = getISmsService(); 776 if (iccISms != null) { 777 success = iccISms.enableCellBroadcastRangeForSubscriber(getSubscriptionId(), 778 startMessageId, endMessageId, ranType); 779 } 780 } catch (RemoteException ex) { 781 // ignore it 782 } 783 784 return success; 785 } 786 787 /** 788 * Disable reception of cell broadcast (SMS-CB) messages with the given 789 * message identifier range and RAN type. The RAN type specify this message 790 * ID range belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different 791 * clients enable the same message identifier, they must both disable it for 792 * the device to stop receiving those messages. 793 * Note: This call is blocking, callers may want to avoid calling it from 794 * the main thread of an application. 795 * 796 * @param startMessageId first message identifier as specified in TS 23.041 (3GPP) 797 * or C.R1001-G (3GPP2) 798 * @param endMessageId last message identifier as specified in TS 23.041 (3GPP) 799 * or C.R1001-G (3GPP2) 800 * @param ranType as defined in class SmsManager, the value can be one of these: 801 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM 802 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA 803 * @return true if successful, false otherwise 804 * 805 * @see #enableCellBroadcastRange(int, int, int) 806 * 807 * @throws IllegalArgumentException if endMessageId < startMessageId 808 * {@hide} 809 */ disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType)810 public boolean disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) { 811 boolean success = false; 812 813 if (endMessageId < startMessageId) { 814 throw new IllegalArgumentException("endMessageId < startMessageId"); 815 } 816 try { 817 ISms iccISms = getISmsService(); 818 if (iccISms != null) { 819 success = iccISms.disableCellBroadcastRangeForSubscriber(getSubscriptionId(), 820 startMessageId, endMessageId, ranType); 821 } 822 } catch (RemoteException ex) { 823 // ignore it 824 } 825 826 return success; 827 } 828 829 /** 830 * Create a list of <code>SmsMessage</code>s from a list of RawSmsData 831 * records returned by <code>getAllMessagesFromIcc()</code> 832 * 833 * @param records SMS EF records, returned by 834 * <code>getAllMessagesFromIcc</code> 835 * @return <code>ArrayList</code> of <code>SmsMessage</code> objects. 836 */ createMessageListFromRawRecords(List<SmsRawData> records)837 private static ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) { 838 ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>(); 839 if (records != null) { 840 int count = records.size(); 841 for (int i = 0; i < count; i++) { 842 SmsRawData data = records.get(i); 843 // List contains all records, including "free" records (null) 844 if (data != null) { 845 SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes()); 846 if (sms != null) { 847 messages.add(sms); 848 } 849 } 850 } 851 } 852 return messages; 853 } 854 855 /** 856 * SMS over IMS is supported if IMS is registered and SMS is supported 857 * on IMS. 858 * 859 * @return true if SMS over IMS is supported, false otherwise 860 * 861 * @see #getImsSmsFormat() 862 * 863 * @hide 864 */ isImsSmsSupported()865 public boolean isImsSmsSupported() { 866 boolean boSupported = false; 867 try { 868 ISms iccISms = getISmsService(); 869 if (iccISms != null) { 870 boSupported = iccISms.isImsSmsSupportedForSubscriber(getSubscriptionId()); 871 } 872 } catch (RemoteException ex) { 873 // ignore it 874 } 875 return boSupported; 876 } 877 878 /** 879 * Gets SMS format supported on IMS. SMS over IMS format is 880 * either 3GPP or 3GPP2. 881 * 882 * @return SmsMessage.FORMAT_3GPP, 883 * SmsMessage.FORMAT_3GPP2 884 * or SmsMessage.FORMAT_UNKNOWN 885 * 886 * @see #isImsSmsSupported() 887 * 888 * @hide 889 */ getImsSmsFormat()890 public String getImsSmsFormat() { 891 String format = com.android.internal.telephony.SmsConstants.FORMAT_UNKNOWN; 892 try { 893 ISms iccISms = getISmsService(); 894 if (iccISms != null) { 895 format = iccISms.getImsSmsFormatForSubscriber(getSubscriptionId()); 896 } 897 } catch (RemoteException ex) { 898 // ignore it 899 } 900 return format; 901 } 902 903 /** 904 * Get default sms subscription id 905 * 906 * @return the default SMS subscription id 907 */ getDefaultSmsSubscriptionId()908 public static int getDefaultSmsSubscriptionId() { 909 ISms iccISms = null; 910 try { 911 iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 912 return iccISms.getPreferredSmsSubscription(); 913 } catch (RemoteException ex) { 914 return -1; 915 } catch (NullPointerException ex) { 916 return -1; 917 } 918 } 919 920 /** 921 * Get SMS prompt property, enabled or not 922 * 923 * @return true if enabled, false otherwise 924 * @hide 925 */ isSMSPromptEnabled()926 public boolean isSMSPromptEnabled() { 927 ISms iccISms = null; 928 try { 929 iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 930 return iccISms.isSMSPromptEnabled(); 931 } catch (RemoteException ex) { 932 return false; 933 } catch (NullPointerException ex) { 934 return false; 935 } 936 } 937 938 // see SmsMessage.getStatusOnIcc 939 940 /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 941 static public final int STATUS_ON_ICC_FREE = 0; 942 943 /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 944 static public final int STATUS_ON_ICC_READ = 1; 945 946 /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 947 static public final int STATUS_ON_ICC_UNREAD = 3; 948 949 /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 950 static public final int STATUS_ON_ICC_SENT = 5; 951 952 /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 953 static public final int STATUS_ON_ICC_UNSENT = 7; 954 955 // SMS send failure result codes 956 957 /** Generic failure cause */ 958 static public final int RESULT_ERROR_GENERIC_FAILURE = 1; 959 /** Failed because radio was explicitly turned off */ 960 static public final int RESULT_ERROR_RADIO_OFF = 2; 961 /** Failed because no pdu provided */ 962 static public final int RESULT_ERROR_NULL_PDU = 3; 963 /** Failed because service is currently unavailable */ 964 static public final int RESULT_ERROR_NO_SERVICE = 4; 965 /** Failed because we reached the sending queue limit. {@hide} */ 966 static public final int RESULT_ERROR_LIMIT_EXCEEDED = 5; 967 /** Failed because FDN is enabled. {@hide} */ 968 static public final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; 969 970 static private final String PHONE_PACKAGE_NAME = "com.android.phone"; 971 972 /** 973 * Send an MMS message 974 * 975 * @param context application context 976 * @param contentUri the content Uri from which the message pdu will be read 977 * @param locationUrl the optional location url where message should be sent to 978 * @param configOverrides the carrier-specific messaging configuration values to override for 979 * sending the message. 980 * @param sentIntent if not NULL this <code>PendingIntent</code> is 981 * broadcast when the message is successfully sent, or failed 982 * @throws IllegalArgumentException if contentUri is empty 983 */ sendMultimediaMessage(Context context, Uri contentUri, String locationUrl, Bundle configOverrides, PendingIntent sentIntent)984 public void sendMultimediaMessage(Context context, Uri contentUri, String locationUrl, 985 Bundle configOverrides, PendingIntent sentIntent) { 986 if (contentUri == null) { 987 throw new IllegalArgumentException("Uri contentUri null"); 988 } 989 try { 990 final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 991 if (iMms == null) { 992 return; 993 } 994 995 iMms.sendMessage(getSubscriptionId(), ActivityThread.currentPackageName(), contentUri, 996 locationUrl, configOverrides, sentIntent); 997 } catch (RemoteException e) { 998 // Ignore it 999 } 1000 } 1001 1002 /** 1003 * Download an MMS message from carrier by a given location URL 1004 * 1005 * @param context application context 1006 * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained 1007 * from the MMS WAP push notification 1008 * @param contentUri the content uri to which the downloaded pdu will be written 1009 * @param configOverrides the carrier-specific messaging configuration values to override for 1010 * downloading the message. 1011 * @param downloadedIntent if not NULL this <code>PendingIntent</code> is 1012 * broadcast when the message is downloaded, or the download is failed 1013 * @throws IllegalArgumentException if locationUrl or contentUri is empty 1014 */ downloadMultimediaMessage(Context context, String locationUrl, Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent)1015 public void downloadMultimediaMessage(Context context, String locationUrl, Uri contentUri, 1016 Bundle configOverrides, PendingIntent downloadedIntent) { 1017 if (TextUtils.isEmpty(locationUrl)) { 1018 throw new IllegalArgumentException("Empty MMS location URL"); 1019 } 1020 if (contentUri == null) { 1021 throw new IllegalArgumentException("Uri contentUri null"); 1022 } 1023 try { 1024 final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1025 if (iMms == null) { 1026 return; 1027 } 1028 iMms.downloadMessage( 1029 getSubscriptionId(), ActivityThread.currentPackageName(), locationUrl, 1030 contentUri, configOverrides, downloadedIntent); 1031 } catch (RemoteException e) { 1032 // Ignore it 1033 } 1034 } 1035 1036 // MMS send/download failure result codes 1037 public static final int MMS_ERROR_UNSPECIFIED = 1; 1038 public static final int MMS_ERROR_INVALID_APN = 2; 1039 public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; 1040 public static final int MMS_ERROR_HTTP_FAILURE = 4; 1041 public static final int MMS_ERROR_IO_ERROR = 5; 1042 public static final int MMS_ERROR_RETRY = 6; 1043 public static final int MMS_ERROR_CONFIGURATION_ERROR = 7; 1044 public static final int MMS_ERROR_NO_DATA_NETWORK = 8; 1045 1046 /** Intent extra name for MMS sending result data in byte array type */ 1047 public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA"; 1048 /** Intent extra name for HTTP status code for MMS HTTP failure in integer type */ 1049 public static final String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS"; 1050 1051 /** 1052 * Import a text message into system's SMS store 1053 * 1054 * Only default SMS apps can import SMS 1055 * 1056 * @param address the destination(source) address of the sent(received) message 1057 * @param type the type of the message 1058 * @param text the message text 1059 * @param timestampMillis the message timestamp in milliseconds 1060 * @param seen if the message is seen 1061 * @param read if the message is read 1062 * @return the message URI, null if failed 1063 * @hide 1064 */ importTextMessage(String address, int type, String text, long timestampMillis, boolean seen, boolean read)1065 public Uri importTextMessage(String address, int type, String text, long timestampMillis, 1066 boolean seen, boolean read) { 1067 try { 1068 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1069 if (iMms != null) { 1070 return iMms.importTextMessage(ActivityThread.currentPackageName(), 1071 address, type, text, timestampMillis, seen, read); 1072 } 1073 } catch (RemoteException ex) { 1074 // ignore it 1075 } 1076 return null; 1077 } 1078 1079 /** Represents the received SMS message for importing {@hide} */ 1080 public static final int SMS_TYPE_INCOMING = 0; 1081 /** Represents the sent SMS message for importing {@hide} */ 1082 public static final int SMS_TYPE_OUTGOING = 1; 1083 1084 /** 1085 * Import a multimedia message into system's MMS store. Only the following PDU type is 1086 * supported: Retrieve.conf, Send.req, Notification.ind, Delivery.ind, Read-Orig.ind 1087 * 1088 * Only default SMS apps can import MMS 1089 * 1090 * @param contentUri the content uri from which to read the PDU of the message to import 1091 * @param messageId the optional message id. Use null if not specifying 1092 * @param timestampSecs the optional message timestamp. Use -1 if not specifying 1093 * @param seen if the message is seen 1094 * @param read if the message is read 1095 * @return the message URI, null if failed 1096 * @throws IllegalArgumentException if pdu is empty 1097 * {@hide} 1098 */ importMultimediaMessage(Uri contentUri, String messageId, long timestampSecs, boolean seen, boolean read)1099 public Uri importMultimediaMessage(Uri contentUri, String messageId, long timestampSecs, 1100 boolean seen, boolean read) { 1101 if (contentUri == null) { 1102 throw new IllegalArgumentException("Uri contentUri null"); 1103 } 1104 try { 1105 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1106 if (iMms != null) { 1107 return iMms.importMultimediaMessage(ActivityThread.currentPackageName(), 1108 contentUri, messageId, timestampSecs, seen, read); 1109 } 1110 } catch (RemoteException ex) { 1111 // ignore it 1112 } 1113 return null; 1114 } 1115 1116 /** 1117 * Delete a system stored SMS or MMS message 1118 * 1119 * Only default SMS apps can delete system stored SMS and MMS messages 1120 * 1121 * @param messageUri the URI of the stored message 1122 * @return true if deletion is successful, false otherwise 1123 * @throws IllegalArgumentException if messageUri is empty 1124 * {@hide} 1125 */ deleteStoredMessage(Uri messageUri)1126 public boolean deleteStoredMessage(Uri messageUri) { 1127 if (messageUri == null) { 1128 throw new IllegalArgumentException("Empty message URI"); 1129 } 1130 try { 1131 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1132 if (iMms != null) { 1133 return iMms.deleteStoredMessage(ActivityThread.currentPackageName(), messageUri); 1134 } 1135 } catch (RemoteException ex) { 1136 // ignore it 1137 } 1138 return false; 1139 } 1140 1141 /** 1142 * Delete a system stored SMS or MMS thread 1143 * 1144 * Only default SMS apps can delete system stored SMS and MMS conversations 1145 * 1146 * @param conversationId the ID of the message conversation 1147 * @return true if deletion is successful, false otherwise 1148 * {@hide} 1149 */ deleteStoredConversation(long conversationId)1150 public boolean deleteStoredConversation(long conversationId) { 1151 try { 1152 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1153 if (iMms != null) { 1154 return iMms.deleteStoredConversation( 1155 ActivityThread.currentPackageName(), conversationId); 1156 } 1157 } catch (RemoteException ex) { 1158 // ignore it 1159 } 1160 return false; 1161 } 1162 1163 /** 1164 * Update the status properties of a system stored SMS or MMS message, e.g. 1165 * the read status of a message, etc. 1166 * 1167 * @param messageUri the URI of the stored message 1168 * @param statusValues a list of status properties in key-value pairs to update 1169 * @return true if update is successful, false otherwise 1170 * @throws IllegalArgumentException if messageUri is empty 1171 * {@hide} 1172 */ updateStoredMessageStatus(Uri messageUri, ContentValues statusValues)1173 public boolean updateStoredMessageStatus(Uri messageUri, ContentValues statusValues) { 1174 if (messageUri == null) { 1175 throw new IllegalArgumentException("Empty message URI"); 1176 } 1177 try { 1178 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1179 if (iMms != null) { 1180 return iMms.updateStoredMessageStatus(ActivityThread.currentPackageName(), 1181 messageUri, statusValues); 1182 } 1183 } catch (RemoteException ex) { 1184 // ignore it 1185 } 1186 return false; 1187 } 1188 1189 /** Message status property: whether the message has been seen. 1 means seen, 0 not {@hide} */ 1190 public static final String MESSAGE_STATUS_SEEN = "seen"; 1191 /** Message status property: whether the message has been read. 1 means read, 0 not {@hide} */ 1192 public static final String MESSAGE_STATUS_READ = "read"; 1193 1194 /** 1195 * Archive or unarchive a stored conversation 1196 * 1197 * @param conversationId the ID of the message conversation 1198 * @param archived true to archive the conversation, false to unarchive 1199 * @return true if update is successful, false otherwise 1200 * {@hide} 1201 */ archiveStoredConversation(long conversationId, boolean archived)1202 public boolean archiveStoredConversation(long conversationId, boolean archived) { 1203 try { 1204 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1205 if (iMms != null) { 1206 return iMms.archiveStoredConversation(ActivityThread.currentPackageName(), 1207 conversationId, archived); 1208 } 1209 } catch (RemoteException ex) { 1210 // ignore it 1211 } 1212 return false; 1213 } 1214 1215 /** 1216 * Add a text message draft to system SMS store 1217 * 1218 * Only default SMS apps can add SMS draft 1219 * 1220 * @param address the destination address of message 1221 * @param text the body of the message to send 1222 * @return the URI of the stored draft message 1223 * {@hide} 1224 */ addTextMessageDraft(String address, String text)1225 public Uri addTextMessageDraft(String address, String text) { 1226 try { 1227 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1228 if (iMms != null) { 1229 return iMms.addTextMessageDraft(ActivityThread.currentPackageName(), address, text); 1230 } 1231 } catch (RemoteException ex) { 1232 // ignore it 1233 } 1234 return null; 1235 } 1236 1237 /** 1238 * Add a multimedia message draft to system MMS store 1239 * 1240 * Only default SMS apps can add MMS draft 1241 * 1242 * @param contentUri the content uri from which to read the PDU data of the draft MMS 1243 * @return the URI of the stored draft message 1244 * @throws IllegalArgumentException if pdu is empty 1245 * {@hide} 1246 */ addMultimediaMessageDraft(Uri contentUri)1247 public Uri addMultimediaMessageDraft(Uri contentUri) { 1248 if (contentUri == null) { 1249 throw new IllegalArgumentException("Uri contentUri null"); 1250 } 1251 try { 1252 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1253 if (iMms != null) { 1254 return iMms.addMultimediaMessageDraft(ActivityThread.currentPackageName(), 1255 contentUri); 1256 } 1257 } catch (RemoteException ex) { 1258 // ignore it 1259 } 1260 return null; 1261 } 1262 1263 /** 1264 * Send a system stored text message. 1265 * 1266 * You can only send a failed text message or a draft text message. 1267 * 1268 * @param messageUri the URI of the stored message 1269 * @param scAddress is the service center address or null to use the current default SMSC 1270 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1271 * broadcast when the message is successfully sent, or failed. 1272 * The result code will be <code>Activity.RESULT_OK</code> for success, 1273 * or one of these errors:<br> 1274 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1275 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1276 * <code>RESULT_ERROR_NULL_PDU</code><br> 1277 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 1278 * the extra "errorCode" containing a radio technology specific value, 1279 * generally only useful for troubleshooting.<br> 1280 * The per-application based SMS control checks sentIntent. If sentIntent 1281 * is NULL the caller will be checked against all unknown applications, 1282 * which cause smaller number of SMS to be sent in checking period. 1283 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 1284 * broadcast when the message is delivered to the recipient. The 1285 * raw pdu of the status report is in the extended data ("pdu"). 1286 * 1287 * @throws IllegalArgumentException if messageUri is empty 1288 * {@hide} 1289 */ sendStoredTextMessage(Uri messageUri, String scAddress, PendingIntent sentIntent, PendingIntent deliveryIntent)1290 public void sendStoredTextMessage(Uri messageUri, String scAddress, PendingIntent sentIntent, 1291 PendingIntent deliveryIntent) { 1292 if (messageUri == null) { 1293 throw new IllegalArgumentException("Empty message URI"); 1294 } 1295 try { 1296 ISms iccISms = getISmsServiceOrThrow(); 1297 iccISms.sendStoredText( 1298 getSubscriptionId(), ActivityThread.currentPackageName(), messageUri, 1299 scAddress, sentIntent, deliveryIntent); 1300 } catch (RemoteException ex) { 1301 // ignore it 1302 } 1303 } 1304 1305 /** 1306 * Send a system stored multi-part text message. 1307 * 1308 * You can only send a failed text message or a draft text message. 1309 * The provided <code>PendingIntent</code> lists should match the part number of the 1310 * divided text of the stored message by using <code>divideMessage</code> 1311 * 1312 * @param messageUri the URI of the stored message 1313 * @param scAddress is the service center address or null to use 1314 * the current default SMSC 1315 * @param sentIntents if not null, an <code>ArrayList</code> of 1316 * <code>PendingIntent</code>s (one for each message part) that is 1317 * broadcast when the corresponding message part has been sent. 1318 * The result code will be <code>Activity.RESULT_OK</code> for success, 1319 * or one of these errors:<br> 1320 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1321 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1322 * <code>RESULT_ERROR_NULL_PDU</code><br> 1323 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include 1324 * the extra "errorCode" containing a radio technology specific value, 1325 * generally only useful for troubleshooting.<br> 1326 * The per-application based SMS control checks sentIntent. If sentIntent 1327 * is NULL the caller will be checked against all unknown applications, 1328 * which cause smaller number of SMS to be sent in checking period. 1329 * @param deliveryIntents if not null, an <code>ArrayList</code> of 1330 * <code>PendingIntent</code>s (one for each message part) that is 1331 * broadcast when the corresponding message part has been delivered 1332 * to the recipient. The raw pdu of the status report is in the 1333 * extended data ("pdu"). 1334 * 1335 * @throws IllegalArgumentException if messageUri is empty 1336 * {@hide} 1337 */ sendStoredMultipartTextMessage(Uri messageUri, String scAddress, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents)1338 public void sendStoredMultipartTextMessage(Uri messageUri, String scAddress, 1339 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { 1340 if (messageUri == null) { 1341 throw new IllegalArgumentException("Empty message URI"); 1342 } 1343 try { 1344 ISms iccISms = getISmsServiceOrThrow(); 1345 iccISms.sendStoredMultipartText( 1346 getSubscriptionId(), ActivityThread.currentPackageName(), messageUri, 1347 scAddress, sentIntents, deliveryIntents); 1348 } catch (RemoteException ex) { 1349 // ignore it 1350 } 1351 } 1352 1353 /** 1354 * Send a system stored MMS message 1355 * 1356 * This is used for sending a previously sent, but failed-to-send, message or 1357 * for sending a text message that has been stored as a draft. 1358 * 1359 * @param messageUri the URI of the stored message 1360 * @param configOverrides the carrier-specific messaging configuration values to override for 1361 * sending the message. 1362 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1363 * broadcast when the message is successfully sent, or failed 1364 * @throws IllegalArgumentException if messageUri is empty 1365 * {@hide} 1366 */ sendStoredMultimediaMessage(Uri messageUri, Bundle configOverrides, PendingIntent sentIntent)1367 public void sendStoredMultimediaMessage(Uri messageUri, Bundle configOverrides, 1368 PendingIntent sentIntent) { 1369 if (messageUri == null) { 1370 throw new IllegalArgumentException("Empty message URI"); 1371 } 1372 try { 1373 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1374 if (iMms != null) { 1375 iMms.sendStoredMessage( 1376 getSubscriptionId(), ActivityThread.currentPackageName(), messageUri, 1377 configOverrides, sentIntent); 1378 } 1379 } catch (RemoteException ex) { 1380 // ignore it 1381 } 1382 } 1383 1384 /** 1385 * Turns on/off the flag to automatically write sent/received SMS/MMS messages into system 1386 * 1387 * When this flag is on, all SMS/MMS sent/received are stored by system automatically 1388 * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system 1389 * automatically 1390 * 1391 * This flag can only be changed by default SMS apps 1392 * 1393 * @param enabled Whether to enable message auto persisting 1394 * {@hide} 1395 */ setAutoPersisting(boolean enabled)1396 public void setAutoPersisting(boolean enabled) { 1397 try { 1398 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1399 if (iMms != null) { 1400 iMms.setAutoPersisting(ActivityThread.currentPackageName(), enabled); 1401 } 1402 } catch (RemoteException ex) { 1403 // ignore it 1404 } 1405 } 1406 1407 /** 1408 * Get the value of the flag to automatically write sent/received SMS/MMS messages into system 1409 * 1410 * When this flag is on, all SMS/MMS sent/received are stored by system automatically 1411 * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system 1412 * automatically 1413 * 1414 * @return the current value of the auto persist flag 1415 * {@hide} 1416 */ getAutoPersisting()1417 public boolean getAutoPersisting() { 1418 try { 1419 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1420 if (iMms != null) { 1421 return iMms.getAutoPersisting(); 1422 } 1423 } catch (RemoteException ex) { 1424 // ignore it 1425 } 1426 return false; 1427 } 1428 1429 /** 1430 * Get carrier-dependent configuration values. 1431 * 1432 * @return bundle key/values pairs of configuration values 1433 */ getCarrierConfigValues()1434 public Bundle getCarrierConfigValues() { 1435 try { 1436 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1437 if (iMms != null) { 1438 return iMms.getCarrierConfigValues(getSubscriptionId()); 1439 } 1440 } catch (RemoteException ex) { 1441 // ignore it 1442 } 1443 return null; 1444 } 1445 1446 } 1447