1 /* 2 * Copyright (C) 2006 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.provider; 18 19 import android.annotation.SdkConstant; 20 import android.annotation.SdkConstant.SdkConstantType; 21 import android.annotation.TestApi; 22 import android.app.job.JobService; 23 import android.content.ComponentName; 24 import android.content.ContentResolver; 25 import android.content.ContentValues; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.database.Cursor; 29 import android.database.ContentObserver; 30 import android.database.sqlite.SqliteWrapper; 31 import android.net.Uri; 32 import android.telephony.Rlog; 33 import android.telephony.ServiceState; 34 import android.telephony.SmsMessage; 35 import android.telephony.SubscriptionManager; 36 import android.telephony.TelephonyManager; 37 import android.text.TextUtils; 38 import android.util.Patterns; 39 40 import com.android.internal.telephony.PhoneConstants; 41 import com.android.internal.telephony.SmsApplication; 42 43 44 import java.util.HashSet; 45 import java.util.Set; 46 import java.util.regex.Matcher; 47 import java.util.regex.Pattern; 48 49 /** 50 * The Telephony provider contains data related to phone operation, specifically SMS and MMS 51 * messages, access to the APN list, including the MMSC to use, and the service state. 52 * 53 * <p class="note"><strong>Note:</strong> These APIs are not available on all Android-powered 54 * devices. If your app depends on telephony features such as for managing SMS messages, include 55 * a <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code <uses-feature>} 56 * </a> element in your manifest that declares the {@code "android.hardware.telephony"} hardware 57 * feature. Alternatively, you can check for telephony availability at runtime using either 58 * {@link android.content.pm.PackageManager#hasSystemFeature 59 * hasSystemFeature(PackageManager.FEATURE_TELEPHONY)} or {@link 60 * android.telephony.TelephonyManager#getPhoneType}.</p> 61 * 62 * <h3>Creating an SMS app</h3> 63 * 64 * <p>Only the default SMS app (selected by the user in system settings) is able to write to the 65 * SMS Provider (the tables defined within the {@code Telephony} class) and only the default SMS 66 * app receives the {@link android.provider.Telephony.Sms.Intents#SMS_DELIVER_ACTION} broadcast 67 * when the user receives an SMS or the {@link 68 * android.provider.Telephony.Sms.Intents#WAP_PUSH_DELIVER_ACTION} broadcast when the user 69 * receives an MMS.</p> 70 * 71 * <p>Any app that wants to behave as the user's default SMS app must handle the following intents: 72 * <ul> 73 * <li>In a broadcast receiver, include an intent filter for {@link Sms.Intents#SMS_DELIVER_ACTION} 74 * (<code>"android.provider.Telephony.SMS_DELIVER"</code>). The broadcast receiver must also 75 * require the {@link android.Manifest.permission#BROADCAST_SMS} permission. 76 * <p>This allows your app to directly receive incoming SMS messages.</p></li> 77 * <li>In a broadcast receiver, include an intent filter for {@link 78 * Sms.Intents#WAP_PUSH_DELIVER_ACTION}} ({@code "android.provider.Telephony.WAP_PUSH_DELIVER"}) 79 * with the MIME type <code>"application/vnd.wap.mms-message"</code>. 80 * The broadcast receiver must also require the {@link 81 * android.Manifest.permission#BROADCAST_WAP_PUSH} permission. 82 * <p>This allows your app to directly receive incoming MMS messages.</p></li> 83 * <li>In your activity that delivers new messages, include an intent filter for 84 * {@link android.content.Intent#ACTION_SENDTO} (<code>"android.intent.action.SENDTO" 85 * </code>) with schemas, <code>sms:</code>, <code>smsto:</code>, <code>mms:</code>, and 86 * <code>mmsto:</code>. 87 * <p>This allows your app to receive intents from other apps that want to deliver a 88 * message.</p></li> 89 * <li>In a service, include an intent filter for {@link 90 * android.telephony.TelephonyManager#ACTION_RESPOND_VIA_MESSAGE} 91 * (<code>"android.intent.action.RESPOND_VIA_MESSAGE"</code>) with schemas, 92 * <code>sms:</code>, <code>smsto:</code>, <code>mms:</code>, and <code>mmsto:</code>. 93 * This service must also require the {@link 94 * android.Manifest.permission#SEND_RESPOND_VIA_MESSAGE} permission. 95 * <p>This allows users to respond to incoming phone calls with an immediate text message 96 * using your app.</p></li> 97 * </ul> 98 * 99 * <p>Other apps that are not selected as the default SMS app can only <em>read</em> the SMS 100 * Provider, but may also be notified when a new SMS arrives by listening for the {@link 101 * Sms.Intents#SMS_RECEIVED_ACTION} 102 * broadcast, which is a non-abortable broadcast that may be delivered to multiple apps. This 103 * broadcast is intended for apps that—while not selected as the default SMS app—need to 104 * read special incoming messages such as to perform phone number verification.</p> 105 * 106 * <p>For more information about building SMS apps, read the blog post, <a 107 * href="http://android-developers.blogspot.com/2013/10/getting-your-sms-apps-ready-for-kitkat.html" 108 * >Getting Your SMS Apps Ready for KitKat</a>.</p> 109 * 110 */ 111 public final class Telephony { 112 private static final String TAG = "Telephony"; 113 114 /** 115 * Not instantiable. 116 * @hide 117 */ Telephony()118 private Telephony() { 119 } 120 121 /** 122 * Base columns for tables that contain text-based SMSs. 123 */ 124 public interface TextBasedSmsColumns { 125 126 /** Message type: all messages. */ 127 public static final int MESSAGE_TYPE_ALL = 0; 128 129 /** Message type: inbox. */ 130 public static final int MESSAGE_TYPE_INBOX = 1; 131 132 /** Message type: sent messages. */ 133 public static final int MESSAGE_TYPE_SENT = 2; 134 135 /** Message type: drafts. */ 136 public static final int MESSAGE_TYPE_DRAFT = 3; 137 138 /** Message type: outbox. */ 139 public static final int MESSAGE_TYPE_OUTBOX = 4; 140 141 /** Message type: failed outgoing message. */ 142 public static final int MESSAGE_TYPE_FAILED = 5; 143 144 /** Message type: queued to send later. */ 145 public static final int MESSAGE_TYPE_QUEUED = 6; 146 147 /** 148 * The type of message. 149 * <P>Type: INTEGER</P> 150 */ 151 public static final String TYPE = "type"; 152 153 /** 154 * The thread ID of the message. 155 * <P>Type: INTEGER</P> 156 */ 157 public static final String THREAD_ID = "thread_id"; 158 159 /** 160 * The address of the other party. 161 * <P>Type: TEXT</P> 162 */ 163 public static final String ADDRESS = "address"; 164 165 /** 166 * The date the message was received. 167 * <P>Type: INTEGER (long)</P> 168 */ 169 public static final String DATE = "date"; 170 171 /** 172 * The date the message was sent. 173 * <P>Type: INTEGER (long)</P> 174 */ 175 public static final String DATE_SENT = "date_sent"; 176 177 /** 178 * Has the message been read? 179 * <P>Type: INTEGER (boolean)</P> 180 */ 181 public static final String READ = "read"; 182 183 /** 184 * Has the message been seen by the user? The "seen" flag determines 185 * whether we need to show a notification. 186 * <P>Type: INTEGER (boolean)</P> 187 */ 188 public static final String SEEN = "seen"; 189 190 /** 191 * {@code TP-Status} value for the message, or -1 if no status has been received. 192 * <P>Type: INTEGER</P> 193 */ 194 public static final String STATUS = "status"; 195 196 /** TP-Status: no status received. */ 197 public static final int STATUS_NONE = -1; 198 /** TP-Status: complete. */ 199 public static final int STATUS_COMPLETE = 0; 200 /** TP-Status: pending. */ 201 public static final int STATUS_PENDING = 32; 202 /** TP-Status: failed. */ 203 public static final int STATUS_FAILED = 64; 204 205 /** 206 * The subject of the message, if present. 207 * <P>Type: TEXT</P> 208 */ 209 public static final String SUBJECT = "subject"; 210 211 /** 212 * The body of the message. 213 * <P>Type: TEXT</P> 214 */ 215 public static final String BODY = "body"; 216 217 /** 218 * The ID of the sender of the conversation, if present. 219 * <P>Type: INTEGER (reference to item in {@code content://contacts/people})</P> 220 */ 221 public static final String PERSON = "person"; 222 223 /** 224 * The protocol identifier code. 225 * <P>Type: INTEGER</P> 226 */ 227 public static final String PROTOCOL = "protocol"; 228 229 /** 230 * Is the {@code TP-Reply-Path} flag set? 231 * <P>Type: BOOLEAN</P> 232 */ 233 public static final String REPLY_PATH_PRESENT = "reply_path_present"; 234 235 /** 236 * The service center (SC) through which to send the message, if present. 237 * <P>Type: TEXT</P> 238 */ 239 public static final String SERVICE_CENTER = "service_center"; 240 241 /** 242 * Is the message locked? 243 * <P>Type: INTEGER (boolean)</P> 244 */ 245 public static final String LOCKED = "locked"; 246 247 /** 248 * The subscription to which the message belongs to. Its value will be 249 * < 0 if the sub id cannot be determined. 250 * <p>Type: INTEGER (long) </p> 251 */ 252 public static final String SUBSCRIPTION_ID = "sub_id"; 253 254 /** 255 * The MTU size of the mobile interface to which the APN connected 256 * @hide 257 */ 258 public static final String MTU = "mtu"; 259 260 /** 261 * Error code associated with sending or receiving this message 262 * <P>Type: INTEGER</P> 263 */ 264 public static final String ERROR_CODE = "error_code"; 265 266 /** 267 * The identity of the sender of a sent message. It is 268 * usually the package name of the app which sends the message. 269 * <p class="note"><strong>Note:</strong> 270 * This column is read-only. It is set by the provider and can not be changed by apps. 271 * <p>Type: TEXT</p> 272 */ 273 public static final String CREATOR = "creator"; 274 } 275 276 /** 277 * Contains all text-based SMS messages. 278 */ 279 public static final class Sms implements BaseColumns, TextBasedSmsColumns { 280 281 /** 282 * Not instantiable. 283 * @hide 284 */ Sms()285 private Sms() { 286 } 287 288 /** 289 * Used to determine the currently configured default SMS package. 290 * @param context context of the requesting application 291 * @return package name for the default SMS package or null 292 */ getDefaultSmsPackage(Context context)293 public static String getDefaultSmsPackage(Context context) { 294 ComponentName component = SmsApplication.getDefaultSmsApplication(context, false); 295 if (component != null) { 296 return component.getPackageName(); 297 } 298 return null; 299 } 300 301 /** 302 * Return cursor for table query. 303 * @hide 304 */ query(ContentResolver cr, String[] projection)305 public static Cursor query(ContentResolver cr, String[] projection) { 306 return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER); 307 } 308 309 /** 310 * Return cursor for table query. 311 * @hide 312 */ query(ContentResolver cr, String[] projection, String where, String orderBy)313 public static Cursor query(ContentResolver cr, String[] projection, 314 String where, String orderBy) { 315 return cr.query(CONTENT_URI, projection, where, 316 null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy); 317 } 318 319 /** 320 * The {@code content://} style URL for this table. 321 */ 322 public static final Uri CONTENT_URI = Uri.parse("content://sms"); 323 324 /** 325 * The default sort order for this table. 326 */ 327 public static final String DEFAULT_SORT_ORDER = "date DESC"; 328 329 /** 330 * Add an SMS to the given URI. 331 * 332 * @param resolver the content resolver to use 333 * @param uri the URI to add the message to 334 * @param address the address of the sender 335 * @param body the body of the message 336 * @param subject the pseudo-subject of the message 337 * @param date the timestamp for the message 338 * @param read true if the message has been read, false if not 339 * @param deliveryReport true if a delivery report was requested, false if not 340 * @return the URI for the new message 341 * @hide 342 */ addMessageToUri(ContentResolver resolver, Uri uri, String address, String body, String subject, Long date, boolean read, boolean deliveryReport)343 public static Uri addMessageToUri(ContentResolver resolver, 344 Uri uri, String address, String body, String subject, 345 Long date, boolean read, boolean deliveryReport) { 346 return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(), 347 resolver, uri, address, body, subject, date, read, deliveryReport, -1L); 348 } 349 350 /** 351 * Add an SMS to the given URI. 352 * 353 * @param resolver the content resolver to use 354 * @param uri the URI to add the message to 355 * @param address the address of the sender 356 * @param body the body of the message 357 * @param subject the psuedo-subject of the message 358 * @param date the timestamp for the message 359 * @param read true if the message has been read, false if not 360 * @param deliveryReport true if a delivery report was requested, false if not 361 * @param subId the subscription which the message belongs to 362 * @return the URI for the new message 363 * @hide 364 */ addMessageToUri(int subId, ContentResolver resolver, Uri uri, String address, String body, String subject, Long date, boolean read, boolean deliveryReport)365 public static Uri addMessageToUri(int subId, ContentResolver resolver, 366 Uri uri, String address, String body, String subject, 367 Long date, boolean read, boolean deliveryReport) { 368 return addMessageToUri(subId, resolver, uri, address, body, subject, 369 date, read, deliveryReport, -1L); 370 } 371 372 /** 373 * Add an SMS to the given URI with the specified thread ID. 374 * 375 * @param resolver the content resolver to use 376 * @param uri the URI to add the message to 377 * @param address the address of the sender 378 * @param body the body of the message 379 * @param subject the pseudo-subject of the message 380 * @param date the timestamp for the message 381 * @param read true if the message has been read, false if not 382 * @param deliveryReport true if a delivery report was requested, false if not 383 * @param threadId the thread_id of the message 384 * @return the URI for the new message 385 * @hide 386 */ addMessageToUri(ContentResolver resolver, Uri uri, String address, String body, String subject, Long date, boolean read, boolean deliveryReport, long threadId)387 public static Uri addMessageToUri(ContentResolver resolver, 388 Uri uri, String address, String body, String subject, 389 Long date, boolean read, boolean deliveryReport, long threadId) { 390 return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(), 391 resolver, uri, address, body, subject, 392 date, read, deliveryReport, threadId); 393 } 394 395 /** 396 * Add an SMS to the given URI with thread_id specified. 397 * 398 * @param resolver the content resolver to use 399 * @param uri the URI to add the message to 400 * @param address the address of the sender 401 * @param body the body of the message 402 * @param subject the psuedo-subject of the message 403 * @param date the timestamp for the message 404 * @param read true if the message has been read, false if not 405 * @param deliveryReport true if a delivery report was requested, false if not 406 * @param threadId the thread_id of the message 407 * @param subId the subscription which the message belongs to 408 * @return the URI for the new message 409 * @hide 410 */ addMessageToUri(int subId, ContentResolver resolver, Uri uri, String address, String body, String subject, Long date, boolean read, boolean deliveryReport, long threadId)411 public static Uri addMessageToUri(int subId, ContentResolver resolver, 412 Uri uri, String address, String body, String subject, 413 Long date, boolean read, boolean deliveryReport, long threadId) { 414 ContentValues values = new ContentValues(8); 415 Rlog.v(TAG,"Telephony addMessageToUri sub id: " + subId); 416 417 values.put(SUBSCRIPTION_ID, subId); 418 values.put(ADDRESS, address); 419 if (date != null) { 420 values.put(DATE, date); 421 } 422 values.put(READ, read ? Integer.valueOf(1) : Integer.valueOf(0)); 423 values.put(SUBJECT, subject); 424 values.put(BODY, body); 425 if (deliveryReport) { 426 values.put(STATUS, STATUS_PENDING); 427 } 428 if (threadId != -1L) { 429 values.put(THREAD_ID, threadId); 430 } 431 return resolver.insert(uri, values); 432 } 433 434 /** 435 * Move a message to the given folder. 436 * 437 * @param context the context to use 438 * @param uri the message to move 439 * @param folder the folder to move to 440 * @return true if the operation succeeded 441 * @hide 442 */ moveMessageToFolder(Context context, Uri uri, int folder, int error)443 public static boolean moveMessageToFolder(Context context, 444 Uri uri, int folder, int error) { 445 if (uri == null) { 446 return false; 447 } 448 449 boolean markAsUnread = false; 450 boolean markAsRead = false; 451 switch(folder) { 452 case MESSAGE_TYPE_INBOX: 453 case MESSAGE_TYPE_DRAFT: 454 break; 455 case MESSAGE_TYPE_OUTBOX: 456 case MESSAGE_TYPE_SENT: 457 markAsRead = true; 458 break; 459 case MESSAGE_TYPE_FAILED: 460 case MESSAGE_TYPE_QUEUED: 461 markAsUnread = true; 462 break; 463 default: 464 return false; 465 } 466 467 ContentValues values = new ContentValues(3); 468 469 values.put(TYPE, folder); 470 if (markAsUnread) { 471 values.put(READ, 0); 472 } else if (markAsRead) { 473 values.put(READ, 1); 474 } 475 values.put(ERROR_CODE, error); 476 477 return 1 == SqliteWrapper.update(context, context.getContentResolver(), 478 uri, values, null, null); 479 } 480 481 /** 482 * Returns true iff the folder (message type) identifies an 483 * outgoing message. 484 * @hide 485 */ isOutgoingFolder(int messageType)486 public static boolean isOutgoingFolder(int messageType) { 487 return (messageType == MESSAGE_TYPE_FAILED) 488 || (messageType == MESSAGE_TYPE_OUTBOX) 489 || (messageType == MESSAGE_TYPE_SENT) 490 || (messageType == MESSAGE_TYPE_QUEUED); 491 } 492 493 /** 494 * Contains all text-based SMS messages in the SMS app inbox. 495 */ 496 public static final class Inbox implements BaseColumns, TextBasedSmsColumns { 497 498 /** 499 * Not instantiable. 500 * @hide 501 */ Inbox()502 private Inbox() { 503 } 504 505 /** 506 * The {@code content://} style URL for this table. 507 */ 508 public static final Uri CONTENT_URI = Uri.parse("content://sms/inbox"); 509 510 /** 511 * The default sort order for this table. 512 */ 513 public static final String DEFAULT_SORT_ORDER = "date DESC"; 514 515 /** 516 * Add an SMS to the Draft box. 517 * 518 * @param resolver the content resolver to use 519 * @param address the address of the sender 520 * @param body the body of the message 521 * @param subject the pseudo-subject of the message 522 * @param date the timestamp for the message 523 * @param read true if the message has been read, false if not 524 * @return the URI for the new message 525 * @hide 526 */ addMessage(ContentResolver resolver, String address, String body, String subject, Long date, boolean read)527 public static Uri addMessage(ContentResolver resolver, 528 String address, String body, String subject, Long date, 529 boolean read) { 530 return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(), 531 resolver, CONTENT_URI, address, body, subject, date, read, false); 532 } 533 534 /** 535 * Add an SMS to the Draft box. 536 * 537 * @param resolver the content resolver to use 538 * @param address the address of the sender 539 * @param body the body of the message 540 * @param subject the psuedo-subject of the message 541 * @param date the timestamp for the message 542 * @param read true if the message has been read, false if not 543 * @param subId the subscription which the message belongs to 544 * @return the URI for the new message 545 * @hide 546 */ addMessage(int subId, ContentResolver resolver, String address, String body, String subject, Long date, boolean read)547 public static Uri addMessage(int subId, ContentResolver resolver, 548 String address, String body, String subject, Long date, boolean read) { 549 return addMessageToUri(subId, resolver, CONTENT_URI, address, body, 550 subject, date, read, false); 551 } 552 } 553 554 /** 555 * Contains all sent text-based SMS messages in the SMS app. 556 */ 557 public static final class Sent implements BaseColumns, TextBasedSmsColumns { 558 559 /** 560 * Not instantiable. 561 * @hide 562 */ Sent()563 private Sent() { 564 } 565 566 /** 567 * The {@code content://} style URL for this table. 568 */ 569 public static final Uri CONTENT_URI = Uri.parse("content://sms/sent"); 570 571 /** 572 * The default sort order for this table. 573 */ 574 public static final String DEFAULT_SORT_ORDER = "date DESC"; 575 576 /** 577 * Add an SMS to the Draft box. 578 * 579 * @param resolver the content resolver to use 580 * @param address the address of the sender 581 * @param body the body of the message 582 * @param subject the pseudo-subject of the message 583 * @param date the timestamp for the message 584 * @return the URI for the new message 585 * @hide 586 */ addMessage(ContentResolver resolver, String address, String body, String subject, Long date)587 public static Uri addMessage(ContentResolver resolver, 588 String address, String body, String subject, Long date) { 589 return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(), 590 resolver, CONTENT_URI, address, body, subject, date, true, false); 591 } 592 593 /** 594 * Add an SMS to the Draft box. 595 * 596 * @param resolver the content resolver to use 597 * @param address the address of the sender 598 * @param body the body of the message 599 * @param subject the psuedo-subject of the message 600 * @param date the timestamp for the message 601 * @param subId the subscription which the message belongs to 602 * @return the URI for the new message 603 * @hide 604 */ addMessage(int subId, ContentResolver resolver, String address, String body, String subject, Long date)605 public static Uri addMessage(int subId, ContentResolver resolver, 606 String address, String body, String subject, Long date) { 607 return addMessageToUri(subId, resolver, CONTENT_URI, address, body, 608 subject, date, true, false); 609 } 610 } 611 612 /** 613 * Contains all sent text-based SMS messages in the SMS app. 614 */ 615 public static final class Draft implements BaseColumns, TextBasedSmsColumns { 616 617 /** 618 * Not instantiable. 619 * @hide 620 */ Draft()621 private Draft() { 622 } 623 624 /** 625 * The {@code content://} style URL for this table. 626 */ 627 public static final Uri CONTENT_URI = Uri.parse("content://sms/draft"); 628 629 /** 630 * @hide 631 */ addMessage(ContentResolver resolver, String address, String body, String subject, Long date)632 public static Uri addMessage(ContentResolver resolver, 633 String address, String body, String subject, Long date) { 634 return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(), 635 resolver, CONTENT_URI, address, body, subject, date, true, false); 636 } 637 638 /** 639 * Add an SMS to the Draft box. 640 * 641 * @param resolver the content resolver to use 642 * @param address the address of the sender 643 * @param body the body of the message 644 * @param subject the psuedo-subject of the message 645 * @param date the timestamp for the message 646 * @param subId the subscription which the message belongs to 647 * @return the URI for the new message 648 * @hide 649 */ addMessage(int subId, ContentResolver resolver, String address, String body, String subject, Long date)650 public static Uri addMessage(int subId, ContentResolver resolver, 651 String address, String body, String subject, Long date) { 652 return addMessageToUri(subId, resolver, CONTENT_URI, address, body, 653 subject, date, true, false); 654 } 655 656 /** 657 * The default sort order for this table. 658 */ 659 public static final String DEFAULT_SORT_ORDER = "date DESC"; 660 } 661 662 /** 663 * Contains all pending outgoing text-based SMS messages. 664 */ 665 public static final class Outbox implements BaseColumns, TextBasedSmsColumns { 666 667 /** 668 * Not instantiable. 669 * @hide 670 */ Outbox()671 private Outbox() { 672 } 673 674 /** 675 * The {@code content://} style URL for this table. 676 */ 677 public static final Uri CONTENT_URI = Uri.parse("content://sms/outbox"); 678 679 /** 680 * The default sort order for this table. 681 */ 682 public static final String DEFAULT_SORT_ORDER = "date DESC"; 683 684 /** 685 * Add an SMS to the outbox. 686 * 687 * @param resolver the content resolver to use 688 * @param address the address of the sender 689 * @param body the body of the message 690 * @param subject the pseudo-subject of the message 691 * @param date the timestamp for the message 692 * @param deliveryReport whether a delivery report was requested for the message 693 * @return the URI for the new message 694 * @hide 695 */ addMessage(ContentResolver resolver, String address, String body, String subject, Long date, boolean deliveryReport, long threadId)696 public static Uri addMessage(ContentResolver resolver, 697 String address, String body, String subject, Long date, 698 boolean deliveryReport, long threadId) { 699 return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(), 700 resolver, CONTENT_URI, address, body, subject, date, 701 true, deliveryReport, threadId); 702 } 703 704 /** 705 * Add an SMS to the Out box. 706 * 707 * @param resolver the content resolver to use 708 * @param address the address of the sender 709 * @param body the body of the message 710 * @param subject the psuedo-subject of the message 711 * @param date the timestamp for the message 712 * @param deliveryReport whether a delivery report was requested for the message 713 * @param subId the subscription which the message belongs to 714 * @return the URI for the new message 715 * @hide 716 */ addMessage(int subId, ContentResolver resolver, String address, String body, String subject, Long date, boolean deliveryReport, long threadId)717 public static Uri addMessage(int subId, ContentResolver resolver, 718 String address, String body, String subject, Long date, 719 boolean deliveryReport, long threadId) { 720 return addMessageToUri(subId, resolver, CONTENT_URI, address, body, 721 subject, date, true, deliveryReport, threadId); 722 } 723 } 724 725 /** 726 * Contains all sent text-based SMS messages in the SMS app. 727 */ 728 public static final class Conversations 729 implements BaseColumns, TextBasedSmsColumns { 730 731 /** 732 * Not instantiable. 733 * @hide 734 */ Conversations()735 private Conversations() { 736 } 737 738 /** 739 * The {@code content://} style URL for this table. 740 */ 741 public static final Uri CONTENT_URI = Uri.parse("content://sms/conversations"); 742 743 /** 744 * The default sort order for this table. 745 */ 746 public static final String DEFAULT_SORT_ORDER = "date DESC"; 747 748 /** 749 * The first 45 characters of the body of the message. 750 * <P>Type: TEXT</P> 751 */ 752 public static final String SNIPPET = "snippet"; 753 754 /** 755 * The number of messages in the conversation. 756 * <P>Type: INTEGER</P> 757 */ 758 public static final String MESSAGE_COUNT = "msg_count"; 759 } 760 761 /** 762 * Contains constants for SMS related Intents that are broadcast. 763 */ 764 public static final class Intents { 765 766 /** 767 * Not instantiable. 768 * @hide 769 */ Intents()770 private Intents() { 771 } 772 773 /** 774 * Set by BroadcastReceiver to indicate that the message was handled 775 * successfully. 776 */ 777 public static final int RESULT_SMS_HANDLED = 1; 778 779 /** 780 * Set by BroadcastReceiver to indicate a generic error while 781 * processing the message. 782 */ 783 public static final int RESULT_SMS_GENERIC_ERROR = 2; 784 785 /** 786 * Set by BroadcastReceiver to indicate insufficient memory to store 787 * the message. 788 */ 789 public static final int RESULT_SMS_OUT_OF_MEMORY = 3; 790 791 /** 792 * Set by BroadcastReceiver to indicate that the message, while 793 * possibly valid, is of a format or encoding that is not 794 * supported. 795 */ 796 public static final int RESULT_SMS_UNSUPPORTED = 4; 797 798 /** 799 * Set by BroadcastReceiver to indicate a duplicate incoming message. 800 */ 801 public static final int RESULT_SMS_DUPLICATED = 5; 802 803 /** 804 * Activity action: Ask the user to change the default 805 * SMS application. This will show a dialog that asks the 806 * user whether they want to replace the current default 807 * SMS application with the one specified in 808 * {@link #EXTRA_PACKAGE_NAME}. 809 */ 810 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 811 public static final String ACTION_CHANGE_DEFAULT = 812 "android.provider.Telephony.ACTION_CHANGE_DEFAULT"; 813 814 /** 815 * The PackageName string passed in as an 816 * extra for {@link #ACTION_CHANGE_DEFAULT} 817 * 818 * @see #ACTION_CHANGE_DEFAULT 819 */ 820 public static final String EXTRA_PACKAGE_NAME = "package"; 821 822 /** 823 * Broadcast Action: A new text-based SMS message has been received 824 * by the device. This intent will only be delivered to the default 825 * sms app. That app is responsible for writing the message and notifying 826 * the user. The intent will have the following extra values:</p> 827 * 828 * <ul> 829 * <li><em>"pdus"</em> - An Object[] of byte[]s containing the PDUs 830 * that make up the message.</li> 831 * <li><em>"format"</em> - A String describing the format of the PDUs. It can 832 * be either "3gpp" or "3gpp2".</li> 833 * <li><em>"subscription"</em> - An optional long value of the subscription id which 834 * received the message.</li> 835 * <li><em>"slot"</em> - An optional int value of the SIM slot containing the 836 * subscription.</li> 837 * <li><em>"phone"</em> - An optional int value of the phone id associated with the 838 * subscription.</li> 839 * <li><em>"errorCode"</em> - An optional int error code associated with receiving 840 * the message.</li> 841 * </ul> 842 * 843 * <p>The extra values can be extracted using 844 * {@link #getMessagesFromIntent(Intent)}.</p> 845 * 846 * <p>If a BroadcastReceiver encounters an error while processing 847 * this intent it should set the result code appropriately.</p> 848 * 849 * <p class="note"><strong>Note:</strong> 850 * The broadcast receiver that filters for this intent must declare 851 * {@link android.Manifest.permission#BROADCAST_SMS} as a required permission in 852 * the <a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code 853 * <receiver>}</a> tag. 854 * 855 * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p> 856 */ 857 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 858 public static final String SMS_DELIVER_ACTION = 859 "android.provider.Telephony.SMS_DELIVER"; 860 861 /** 862 * Broadcast Action: A new text-based SMS message has been received 863 * by the device. This intent will be delivered to all registered 864 * receivers as a notification. These apps are not expected to write the 865 * message or notify the user. The intent will have the following extra 866 * values:</p> 867 * 868 * <ul> 869 * <li><em>"pdus"</em> - An Object[] of byte[]s containing the PDUs 870 * that make up the message.</li> 871 * </ul> 872 * 873 * <p>The extra values can be extracted using 874 * {@link #getMessagesFromIntent(Intent)}.</p> 875 * 876 * <p>If a BroadcastReceiver encounters an error while processing 877 * this intent it should set the result code appropriately.</p> 878 * 879 * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p> 880 */ 881 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 882 public static final String SMS_RECEIVED_ACTION = 883 "android.provider.Telephony.SMS_RECEIVED"; 884 885 /** 886 * Broadcast Action: A new data based SMS message has been received 887 * by the device. This intent will be delivered to all registered 888 * receivers as a notification. The intent will have the following extra 889 * values:</p> 890 * 891 * <ul> 892 * <li><em>"pdus"</em> - An Object[] of byte[]s containing the PDUs 893 * that make up the message.</li> 894 * </ul> 895 * 896 * <p>The extra values can be extracted using 897 * {@link #getMessagesFromIntent(Intent)}.</p> 898 * 899 * <p>If a BroadcastReceiver encounters an error while processing 900 * this intent it should set the result code appropriately.</p> 901 * 902 * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p> 903 */ 904 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 905 public static final String DATA_SMS_RECEIVED_ACTION = 906 "android.intent.action.DATA_SMS_RECEIVED"; 907 908 /** 909 * Broadcast Action: A new WAP PUSH message has been received by the 910 * device. This intent will only be delivered to the default 911 * sms app. That app is responsible for writing the message and notifying 912 * the user. The intent will have the following extra values:</p> 913 * 914 * <ul> 915 * <li><em>"transactionId"</em> - (Integer) The WAP transaction ID</li> 916 * <li><em>"pduType"</em> - (Integer) The WAP PDU type</li> 917 * <li><em>"header"</em> - (byte[]) The header of the message</li> 918 * <li><em>"data"</em> - (byte[]) The data payload of the message</li> 919 * <li><em>"contentTypeParameters" </em> 920 * -(HashMap<String,String>) Any parameters associated with the content type 921 * (decoded from the WSP Content-Type header)</li> 922 * <li><em>"subscription"</em> - An optional long value of the subscription id which 923 * received the message.</li> 924 * <li><em>"slot"</em> - An optional int value of the SIM slot containing the 925 * subscription.</li> 926 * <li><em>"phone"</em> - An optional int value of the phone id associated with the 927 * subscription.</li> 928 * </ul> 929 * 930 * <p>If a BroadcastReceiver encounters an error while processing 931 * this intent it should set the result code appropriately.</p> 932 * 933 * <p>The contentTypeParameters extra value is map of content parameters keyed by 934 * their names.</p> 935 * 936 * <p>If any unassigned well-known parameters are encountered, the key of the map will 937 * be 'unassigned/0x...', where '...' is the hex value of the unassigned parameter. If 938 * a parameter has No-Value the value in the map will be null.</p> 939 * 940 * <p>Requires {@link android.Manifest.permission#RECEIVE_MMS} or 941 * {@link android.Manifest.permission#RECEIVE_WAP_PUSH} (depending on WAP PUSH type) to 942 * receive.</p> 943 * 944 * <p class="note"><strong>Note:</strong> 945 * The broadcast receiver that filters for this intent must declare 946 * {@link android.Manifest.permission#BROADCAST_WAP_PUSH} as a required permission in 947 * the <a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code 948 * <receiver>}</a> tag. 949 */ 950 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 951 public static final String WAP_PUSH_DELIVER_ACTION = 952 "android.provider.Telephony.WAP_PUSH_DELIVER"; 953 954 /** 955 * Broadcast Action: A new WAP PUSH message has been received by the 956 * device. This intent will be delivered to all registered 957 * receivers as a notification. These apps are not expected to write the 958 * message or notify the user. The intent will have the following extra 959 * values:</p> 960 * 961 * <ul> 962 * <li><em>"transactionId"</em> - (Integer) The WAP transaction ID</li> 963 * <li><em>"pduType"</em> - (Integer) The WAP PDU type</li> 964 * <li><em>"header"</em> - (byte[]) The header of the message</li> 965 * <li><em>"data"</em> - (byte[]) The data payload of the message</li> 966 * <li><em>"contentTypeParameters"</em> 967 * - (HashMap<String,String>) Any parameters associated with the content type 968 * (decoded from the WSP Content-Type header)</li> 969 * </ul> 970 * 971 * <p>If a BroadcastReceiver encounters an error while processing 972 * this intent it should set the result code appropriately.</p> 973 * 974 * <p>The contentTypeParameters extra value is map of content parameters keyed by 975 * their names.</p> 976 * 977 * <p>If any unassigned well-known parameters are encountered, the key of the map will 978 * be 'unassigned/0x...', where '...' is the hex value of the unassigned parameter. If 979 * a parameter has No-Value the value in the map will be null.</p> 980 * 981 * <p>Requires {@link android.Manifest.permission#RECEIVE_MMS} or 982 * {@link android.Manifest.permission#RECEIVE_WAP_PUSH} (depending on WAP PUSH type) to 983 * receive.</p> 984 */ 985 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 986 public static final String WAP_PUSH_RECEIVED_ACTION = 987 "android.provider.Telephony.WAP_PUSH_RECEIVED"; 988 989 /** 990 * Broadcast Action: A new Cell Broadcast message has been received 991 * by the device. The intent will have the following extra 992 * values:</p> 993 * 994 * <ul> 995 * <li><em>"message"</em> - An SmsCbMessage object containing the broadcast message 996 * data. This is not an emergency alert, so ETWS and CMAS data will be null.</li> 997 * </ul> 998 * 999 * <p>The extra values can be extracted using 1000 * {@link #getMessagesFromIntent(Intent)}.</p> 1001 * 1002 * <p>If a BroadcastReceiver encounters an error while processing 1003 * this intent it should set the result code appropriately.</p> 1004 * 1005 * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p> 1006 */ 1007 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1008 public static final String SMS_CB_RECEIVED_ACTION = 1009 "android.provider.Telephony.SMS_CB_RECEIVED"; 1010 1011 /** 1012 * Action: A SMS based carrier provision intent. Used to identify default 1013 * carrier provisioning app on the device. 1014 * @hide 1015 */ 1016 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1017 @TestApi 1018 public static final String SMS_CARRIER_PROVISION_ACTION = 1019 "android.provider.Telephony.SMS_CARRIER_PROVISION"; 1020 1021 /** 1022 * Broadcast Action: A new Emergency Broadcast message has been received 1023 * by the device. The intent will have the following extra 1024 * values:</p> 1025 * 1026 * <ul> 1027 * <li><em>"message"</em> - An SmsCbMessage object containing the broadcast message 1028 * data, including ETWS or CMAS warning notification info if present.</li> 1029 * </ul> 1030 * 1031 * <p>The extra values can be extracted using 1032 * {@link #getMessagesFromIntent(Intent)}.</p> 1033 * 1034 * <p>If a BroadcastReceiver encounters an error while processing 1035 * this intent it should set the result code appropriately.</p> 1036 * 1037 * <p>Requires {@link android.Manifest.permission#RECEIVE_EMERGENCY_BROADCAST} to 1038 * receive.</p> 1039 * @removed 1040 */ 1041 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1042 public static final String SMS_EMERGENCY_CB_RECEIVED_ACTION = 1043 "android.provider.Telephony.SMS_EMERGENCY_CB_RECEIVED"; 1044 1045 /** 1046 * Broadcast Action: A new CDMA SMS has been received containing Service Category 1047 * Program Data (updates the list of enabled broadcast channels). The intent will 1048 * have the following extra values:</p> 1049 * 1050 * <ul> 1051 * <li><em>"operations"</em> - An array of CdmaSmsCbProgramData objects containing 1052 * the service category operations (add/delete/clear) to perform.</li> 1053 * </ul> 1054 * 1055 * <p>The extra values can be extracted using 1056 * {@link #getMessagesFromIntent(Intent)}.</p> 1057 * 1058 * <p>If a BroadcastReceiver encounters an error while processing 1059 * this intent it should set the result code appropriately.</p> 1060 * 1061 * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p> 1062 */ 1063 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1064 public static final String SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION = 1065 "android.provider.Telephony.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED"; 1066 1067 /** 1068 * Broadcast Action: The SIM storage for SMS messages is full. If 1069 * space is not freed, messages targeted for the SIM (class 2) may 1070 * not be saved. 1071 * 1072 * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p> 1073 */ 1074 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1075 public static final String SIM_FULL_ACTION = 1076 "android.provider.Telephony.SIM_FULL"; 1077 1078 /** 1079 * Broadcast Action: An incoming SMS has been rejected by the 1080 * telephony framework. This intent is sent in lieu of any 1081 * of the RECEIVED_ACTION intents. The intent will have the 1082 * following extra value:</p> 1083 * 1084 * <ul> 1085 * <li><em>"result"</em> - An int result code, e.g. {@link #RESULT_SMS_OUT_OF_MEMORY} 1086 * indicating the error returned to the network.</li> 1087 * </ul> 1088 * 1089 * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p> 1090 */ 1091 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1092 public static final String SMS_REJECTED_ACTION = 1093 "android.provider.Telephony.SMS_REJECTED"; 1094 1095 /** 1096 * Broadcast Action: An incoming MMS has been downloaded. The intent is sent to all 1097 * users, except for secondary users where SMS has been disabled and to managed 1098 * profiles. 1099 * @hide 1100 */ 1101 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1102 public static final String MMS_DOWNLOADED_ACTION = 1103 "android.provider.Telephony.MMS_DOWNLOADED"; 1104 1105 /** 1106 * Broadcast Action: A debug code has been entered in the dialer. This intent is 1107 * broadcast by the system and OEM telephony apps may need to receive these broadcasts. 1108 * These "secret codes" are used to activate developer menus by dialing certain codes. 1109 * And they are of the form {@code *#*#<code>#*#*}. The intent will have the data 1110 * URI: {@code android_secret_code://<code>}. It is possible that a manifest 1111 * receiver would be woken up even if it is not currently running. 1112 * 1113 * <p>Requires {@code android.Manifest.permission#CONTROL_INCALL_EXPERIENCE} to 1114 * send and receive.</p> 1115 */ 1116 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1117 public static final String SECRET_CODE_ACTION = 1118 "android.provider.Telephony.SECRET_CODE"; 1119 1120 /** 1121 * Broadcast action: When the default SMS package changes, 1122 * the previous default SMS package and the new default SMS 1123 * package are sent this broadcast to notify them of the change. 1124 * A boolean is specified in {@link #EXTRA_IS_DEFAULT_SMS_APP} to 1125 * indicate whether the package is the new default SMS package. 1126 */ 1127 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1128 public static final String ACTION_DEFAULT_SMS_PACKAGE_CHANGED = 1129 "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED"; 1130 1131 /** 1132 * The IsDefaultSmsApp boolean passed as an 1133 * extra for {@link #ACTION_DEFAULT_SMS_PACKAGE_CHANGED} to indicate whether the 1134 * SMS app is becoming the default SMS app or is no longer the default. 1135 * 1136 * @see #ACTION_DEFAULT_SMS_PACKAGE_CHANGED 1137 */ 1138 public static final String EXTRA_IS_DEFAULT_SMS_APP = 1139 "android.provider.extra.IS_DEFAULT_SMS_APP"; 1140 1141 /** 1142 * Broadcast action: When a change is made to the SmsProvider or 1143 * MmsProvider by a process other than the default SMS application, 1144 * this intent is broadcast to the default SMS application so it can 1145 * re-sync or update the change. The uri that was used to call the provider 1146 * can be retrieved from the intent with getData(). The actual affected uris 1147 * (which would depend on the selection specified) are not included. 1148 */ 1149 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1150 public static final String ACTION_EXTERNAL_PROVIDER_CHANGE = 1151 "android.provider.action.EXTERNAL_PROVIDER_CHANGE"; 1152 1153 /** 1154 * Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a 1155 * {@link #DATA_SMS_RECEIVED_ACTION} intent. 1156 * 1157 * @param intent the intent to read from 1158 * @return an array of SmsMessages for the PDUs 1159 */ getMessagesFromIntent(Intent intent)1160 public static SmsMessage[] getMessagesFromIntent(Intent intent) { 1161 Object[] messages; 1162 try { 1163 messages = (Object[]) intent.getSerializableExtra("pdus"); 1164 } 1165 catch (ClassCastException e) { 1166 Rlog.e(TAG, "getMessagesFromIntent: " + e); 1167 return null; 1168 } 1169 1170 if (messages == null) { 1171 Rlog.e(TAG, "pdus does not exist in the intent"); 1172 return null; 1173 } 1174 1175 String format = intent.getStringExtra("format"); 1176 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, 1177 SubscriptionManager.getDefaultSmsSubscriptionId()); 1178 1179 Rlog.v(TAG, " getMessagesFromIntent sub_id : " + subId); 1180 1181 int pduCount = messages.length; 1182 SmsMessage[] msgs = new SmsMessage[pduCount]; 1183 1184 for (int i = 0; i < pduCount; i++) { 1185 byte[] pdu = (byte[]) messages[i]; 1186 msgs[i] = SmsMessage.createFromPdu(pdu, format); 1187 if (msgs[i] != null) msgs[i].setSubId(subId); 1188 } 1189 return msgs; 1190 } 1191 } 1192 } 1193 1194 /** 1195 * Base column for the table that contain Carrier Public key. 1196 * @hide 1197 */ 1198 public interface CarrierColumns extends BaseColumns { 1199 1200 public static final String MCC = "mcc"; 1201 public static final String MNC = "mnc"; 1202 public static final String KEY_TYPE = "key_type"; 1203 public static final String MVNO_TYPE = "mvno_type"; 1204 public static final String MVNO_MATCH_DATA = "mvno_match_data"; 1205 public static final String PUBLIC_KEY = "public_key"; 1206 public static final String KEY_IDENTIFIER = "key_identifier"; 1207 public static final String EXPIRATION_TIME = "expiration_time"; 1208 public static final String LAST_MODIFIED = "last_modified"; 1209 1210 /** 1211 * The {@code content://} style URL for this table. 1212 * @hide 1213 */ 1214 public static final Uri CONTENT_URI = Uri.parse("content://carrier_information/carrier"); 1215 } 1216 1217 /** 1218 * Base columns for tables that contain MMSs. 1219 */ 1220 public interface BaseMmsColumns extends BaseColumns { 1221 1222 /** Message box: all messages. */ 1223 public static final int MESSAGE_BOX_ALL = 0; 1224 /** Message box: inbox. */ 1225 public static final int MESSAGE_BOX_INBOX = 1; 1226 /** Message box: sent messages. */ 1227 public static final int MESSAGE_BOX_SENT = 2; 1228 /** Message box: drafts. */ 1229 public static final int MESSAGE_BOX_DRAFTS = 3; 1230 /** Message box: outbox. */ 1231 public static final int MESSAGE_BOX_OUTBOX = 4; 1232 /** Message box: failed. */ 1233 public static final int MESSAGE_BOX_FAILED = 5; 1234 1235 /** 1236 * The thread ID of the message. 1237 * <P>Type: INTEGER (long)</P> 1238 */ 1239 public static final String THREAD_ID = "thread_id"; 1240 1241 /** 1242 * The date the message was received. 1243 * <P>Type: INTEGER (long)</P> 1244 */ 1245 public static final String DATE = "date"; 1246 1247 /** 1248 * The date the message was sent. 1249 * <P>Type: INTEGER (long)</P> 1250 */ 1251 public static final String DATE_SENT = "date_sent"; 1252 1253 /** 1254 * The box which the message belongs to, e.g. {@link #MESSAGE_BOX_INBOX}. 1255 * <P>Type: INTEGER</P> 1256 */ 1257 public static final String MESSAGE_BOX = "msg_box"; 1258 1259 /** 1260 * Has the message been read? 1261 * <P>Type: INTEGER (boolean)</P> 1262 */ 1263 public static final String READ = "read"; 1264 1265 /** 1266 * Has the message been seen by the user? The "seen" flag determines 1267 * whether we need to show a new message notification. 1268 * <P>Type: INTEGER (boolean)</P> 1269 */ 1270 public static final String SEEN = "seen"; 1271 1272 /** 1273 * Does the message have only a text part (can also have a subject) with 1274 * no picture, slideshow, sound, etc. parts? 1275 * <P>Type: INTEGER (boolean)</P> 1276 */ 1277 public static final String TEXT_ONLY = "text_only"; 1278 1279 /** 1280 * The {@code Message-ID} of the message. 1281 * <P>Type: TEXT</P> 1282 */ 1283 public static final String MESSAGE_ID = "m_id"; 1284 1285 /** 1286 * The subject of the message, if present. 1287 * <P>Type: TEXT</P> 1288 */ 1289 public static final String SUBJECT = "sub"; 1290 1291 /** 1292 * The character set of the subject, if present. 1293 * <P>Type: INTEGER</P> 1294 */ 1295 public static final String SUBJECT_CHARSET = "sub_cs"; 1296 1297 /** 1298 * The {@code Content-Type} of the message. 1299 * <P>Type: TEXT</P> 1300 */ 1301 public static final String CONTENT_TYPE = "ct_t"; 1302 1303 /** 1304 * The {@code Content-Location} of the message. 1305 * <P>Type: TEXT</P> 1306 */ 1307 public static final String CONTENT_LOCATION = "ct_l"; 1308 1309 /** 1310 * The expiry time of the message. 1311 * <P>Type: INTEGER (long)</P> 1312 */ 1313 public static final String EXPIRY = "exp"; 1314 1315 /** 1316 * The class of the message. 1317 * <P>Type: TEXT</P> 1318 */ 1319 public static final String MESSAGE_CLASS = "m_cls"; 1320 1321 /** 1322 * The type of the message defined by MMS spec. 1323 * <P>Type: INTEGER</P> 1324 */ 1325 public static final String MESSAGE_TYPE = "m_type"; 1326 1327 /** 1328 * The version of the specification that this message conforms to. 1329 * <P>Type: INTEGER</P> 1330 */ 1331 public static final String MMS_VERSION = "v"; 1332 1333 /** 1334 * The size of the message. 1335 * <P>Type: INTEGER</P> 1336 */ 1337 public static final String MESSAGE_SIZE = "m_size"; 1338 1339 /** 1340 * The priority of the message. 1341 * <P>Type: INTEGER</P> 1342 */ 1343 public static final String PRIORITY = "pri"; 1344 1345 /** 1346 * The {@code read-report} of the message. 1347 * <P>Type: INTEGER (boolean)</P> 1348 */ 1349 public static final String READ_REPORT = "rr"; 1350 1351 /** 1352 * Is read report allowed? 1353 * <P>Type: INTEGER (boolean)</P> 1354 */ 1355 public static final String REPORT_ALLOWED = "rpt_a"; 1356 1357 /** 1358 * The {@code response-status} of the message. 1359 * <P>Type: INTEGER</P> 1360 */ 1361 public static final String RESPONSE_STATUS = "resp_st"; 1362 1363 /** 1364 * The {@code status} of the message. 1365 * <P>Type: INTEGER</P> 1366 */ 1367 public static final String STATUS = "st"; 1368 1369 /** 1370 * The {@code transaction-id} of the message. 1371 * <P>Type: TEXT</P> 1372 */ 1373 public static final String TRANSACTION_ID = "tr_id"; 1374 1375 /** 1376 * The {@code retrieve-status} of the message. 1377 * <P>Type: INTEGER</P> 1378 */ 1379 public static final String RETRIEVE_STATUS = "retr_st"; 1380 1381 /** 1382 * The {@code retrieve-text} of the message. 1383 * <P>Type: TEXT</P> 1384 */ 1385 public static final String RETRIEVE_TEXT = "retr_txt"; 1386 1387 /** 1388 * The character set of the retrieve-text. 1389 * <P>Type: INTEGER</P> 1390 */ 1391 public static final String RETRIEVE_TEXT_CHARSET = "retr_txt_cs"; 1392 1393 /** 1394 * The {@code read-status} of the message. 1395 * <P>Type: INTEGER</P> 1396 */ 1397 public static final String READ_STATUS = "read_status"; 1398 1399 /** 1400 * The {@code content-class} of the message. 1401 * <P>Type: INTEGER</P> 1402 */ 1403 public static final String CONTENT_CLASS = "ct_cls"; 1404 1405 /** 1406 * The {@code delivery-report} of the message. 1407 * <P>Type: INTEGER</P> 1408 */ 1409 public static final String DELIVERY_REPORT = "d_rpt"; 1410 1411 /** 1412 * The {@code delivery-time-token} of the message. 1413 * <P>Type: INTEGER</P> 1414 * @deprecated this column is no longer supported. 1415 * @hide 1416 */ 1417 @Deprecated 1418 public static final String DELIVERY_TIME_TOKEN = "d_tm_tok"; 1419 1420 /** 1421 * The {@code delivery-time} of the message. 1422 * <P>Type: INTEGER</P> 1423 */ 1424 public static final String DELIVERY_TIME = "d_tm"; 1425 1426 /** 1427 * The {@code response-text} of the message. 1428 * <P>Type: TEXT</P> 1429 */ 1430 public static final String RESPONSE_TEXT = "resp_txt"; 1431 1432 /** 1433 * The {@code sender-visibility} of the message. 1434 * <P>Type: TEXT</P> 1435 * @deprecated this column is no longer supported. 1436 * @hide 1437 */ 1438 @Deprecated 1439 public static final String SENDER_VISIBILITY = "s_vis"; 1440 1441 /** 1442 * The {@code reply-charging} of the message. 1443 * <P>Type: INTEGER</P> 1444 * @deprecated this column is no longer supported. 1445 * @hide 1446 */ 1447 @Deprecated 1448 public static final String REPLY_CHARGING = "r_chg"; 1449 1450 /** 1451 * The {@code reply-charging-deadline-token} of the message. 1452 * <P>Type: INTEGER</P> 1453 * @deprecated this column is no longer supported. 1454 * @hide 1455 */ 1456 @Deprecated 1457 public static final String REPLY_CHARGING_DEADLINE_TOKEN = "r_chg_dl_tok"; 1458 1459 /** 1460 * The {@code reply-charging-deadline} of the message. 1461 * <P>Type: INTEGER</P> 1462 * @deprecated this column is no longer supported. 1463 * @hide 1464 */ 1465 @Deprecated 1466 public static final String REPLY_CHARGING_DEADLINE = "r_chg_dl"; 1467 1468 /** 1469 * The {@code reply-charging-id} of the message. 1470 * <P>Type: TEXT</P> 1471 * @deprecated this column is no longer supported. 1472 * @hide 1473 */ 1474 @Deprecated 1475 public static final String REPLY_CHARGING_ID = "r_chg_id"; 1476 1477 /** 1478 * The {@code reply-charging-size} of the message. 1479 * <P>Type: INTEGER</P> 1480 * @deprecated this column is no longer supported. 1481 * @hide 1482 */ 1483 @Deprecated 1484 public static final String REPLY_CHARGING_SIZE = "r_chg_sz"; 1485 1486 /** 1487 * The {@code previously-sent-by} of the message. 1488 * <P>Type: TEXT</P> 1489 * @deprecated this column is no longer supported. 1490 * @hide 1491 */ 1492 @Deprecated 1493 public static final String PREVIOUSLY_SENT_BY = "p_s_by"; 1494 1495 /** 1496 * The {@code previously-sent-date} of the message. 1497 * <P>Type: INTEGER</P> 1498 * @deprecated this column is no longer supported. 1499 * @hide 1500 */ 1501 @Deprecated 1502 public static final String PREVIOUSLY_SENT_DATE = "p_s_d"; 1503 1504 /** 1505 * The {@code store} of the message. 1506 * <P>Type: TEXT</P> 1507 * @deprecated this column is no longer supported. 1508 * @hide 1509 */ 1510 @Deprecated 1511 public static final String STORE = "store"; 1512 1513 /** 1514 * The {@code mm-state} of the message. 1515 * <P>Type: INTEGER</P> 1516 * @deprecated this column is no longer supported. 1517 * @hide 1518 */ 1519 @Deprecated 1520 public static final String MM_STATE = "mm_st"; 1521 1522 /** 1523 * The {@code mm-flags-token} of the message. 1524 * <P>Type: INTEGER</P> 1525 * @deprecated this column is no longer supported. 1526 * @hide 1527 */ 1528 @Deprecated 1529 public static final String MM_FLAGS_TOKEN = "mm_flg_tok"; 1530 1531 /** 1532 * The {@code mm-flags} of the message. 1533 * <P>Type: TEXT</P> 1534 * @deprecated this column is no longer supported. 1535 * @hide 1536 */ 1537 @Deprecated 1538 public static final String MM_FLAGS = "mm_flg"; 1539 1540 /** 1541 * The {@code store-status} of the message. 1542 * <P>Type: TEXT</P> 1543 * @deprecated this column is no longer supported. 1544 * @hide 1545 */ 1546 @Deprecated 1547 public static final String STORE_STATUS = "store_st"; 1548 1549 /** 1550 * The {@code store-status-text} of the message. 1551 * <P>Type: TEXT</P> 1552 * @deprecated this column is no longer supported. 1553 * @hide 1554 */ 1555 @Deprecated 1556 public static final String STORE_STATUS_TEXT = "store_st_txt"; 1557 1558 /** 1559 * The {@code stored} of the message. 1560 * <P>Type: TEXT</P> 1561 * @deprecated this column is no longer supported. 1562 * @hide 1563 */ 1564 @Deprecated 1565 public static final String STORED = "stored"; 1566 1567 /** 1568 * The {@code totals} of the message. 1569 * <P>Type: TEXT</P> 1570 * @deprecated this column is no longer supported. 1571 * @hide 1572 */ 1573 @Deprecated 1574 public static final String TOTALS = "totals"; 1575 1576 /** 1577 * The {@code mbox-totals} of the message. 1578 * <P>Type: TEXT</P> 1579 * @deprecated this column is no longer supported. 1580 * @hide 1581 */ 1582 @Deprecated 1583 public static final String MBOX_TOTALS = "mb_t"; 1584 1585 /** 1586 * The {@code mbox-totals-token} of the message. 1587 * <P>Type: INTEGER</P> 1588 * @deprecated this column is no longer supported. 1589 * @hide 1590 */ 1591 @Deprecated 1592 public static final String MBOX_TOTALS_TOKEN = "mb_t_tok"; 1593 1594 /** 1595 * The {@code quotas} of the message. 1596 * <P>Type: TEXT</P> 1597 * @deprecated this column is no longer supported. 1598 * @hide 1599 */ 1600 @Deprecated 1601 public static final String QUOTAS = "qt"; 1602 1603 /** 1604 * The {@code mbox-quotas} of the message. 1605 * <P>Type: TEXT</P> 1606 * @deprecated this column is no longer supported. 1607 * @hide 1608 */ 1609 @Deprecated 1610 public static final String MBOX_QUOTAS = "mb_qt"; 1611 1612 /** 1613 * The {@code mbox-quotas-token} of the message. 1614 * <P>Type: INTEGER</P> 1615 * @deprecated this column is no longer supported. 1616 * @hide 1617 */ 1618 @Deprecated 1619 public static final String MBOX_QUOTAS_TOKEN = "mb_qt_tok"; 1620 1621 /** 1622 * The {@code message-count} of the message. 1623 * <P>Type: INTEGER</P> 1624 * @deprecated this column is no longer supported. 1625 * @hide 1626 */ 1627 @Deprecated 1628 public static final String MESSAGE_COUNT = "m_cnt"; 1629 1630 /** 1631 * The {@code start} of the message. 1632 * <P>Type: INTEGER</P> 1633 * @deprecated this column is no longer supported. 1634 * @hide 1635 */ 1636 @Deprecated 1637 public static final String START = "start"; 1638 1639 /** 1640 * The {@code distribution-indicator} of the message. 1641 * <P>Type: TEXT</P> 1642 * @deprecated this column is no longer supported. 1643 * @hide 1644 */ 1645 @Deprecated 1646 public static final String DISTRIBUTION_INDICATOR = "d_ind"; 1647 1648 /** 1649 * The {@code element-descriptor} of the message. 1650 * <P>Type: TEXT</P> 1651 * @deprecated this column is no longer supported. 1652 * @hide 1653 */ 1654 @Deprecated 1655 public static final String ELEMENT_DESCRIPTOR = "e_des"; 1656 1657 /** 1658 * The {@code limit} of the message. 1659 * <P>Type: INTEGER</P> 1660 * @deprecated this column is no longer supported. 1661 * @hide 1662 */ 1663 @Deprecated 1664 public static final String LIMIT = "limit"; 1665 1666 /** 1667 * The {@code recommended-retrieval-mode} of the message. 1668 * <P>Type: INTEGER</P> 1669 * @deprecated this column is no longer supported. 1670 * @hide 1671 */ 1672 @Deprecated 1673 public static final String RECOMMENDED_RETRIEVAL_MODE = "r_r_mod"; 1674 1675 /** 1676 * The {@code recommended-retrieval-mode-text} of the message. 1677 * <P>Type: TEXT</P> 1678 * @deprecated this column is no longer supported. 1679 * @hide 1680 */ 1681 @Deprecated 1682 public static final String RECOMMENDED_RETRIEVAL_MODE_TEXT = "r_r_mod_txt"; 1683 1684 /** 1685 * The {@code status-text} of the message. 1686 * <P>Type: TEXT</P> 1687 * @deprecated this column is no longer supported. 1688 * @hide 1689 */ 1690 @Deprecated 1691 public static final String STATUS_TEXT = "st_txt"; 1692 1693 /** 1694 * The {@code applic-id} of the message. 1695 * <P>Type: TEXT</P> 1696 * @deprecated this column is no longer supported. 1697 * @hide 1698 */ 1699 @Deprecated 1700 public static final String APPLIC_ID = "apl_id"; 1701 1702 /** 1703 * The {@code reply-applic-id} of the message. 1704 * <P>Type: TEXT</P> 1705 * @deprecated this column is no longer supported. 1706 * @hide 1707 */ 1708 @Deprecated 1709 public static final String REPLY_APPLIC_ID = "r_apl_id"; 1710 1711 /** 1712 * The {@code aux-applic-id} of the message. 1713 * <P>Type: TEXT</P> 1714 * @deprecated this column is no longer supported. 1715 * @hide 1716 */ 1717 @Deprecated 1718 public static final String AUX_APPLIC_ID = "aux_apl_id"; 1719 1720 /** 1721 * The {@code drm-content} of the message. 1722 * <P>Type: TEXT</P> 1723 * @deprecated this column is no longer supported. 1724 * @hide 1725 */ 1726 @Deprecated 1727 public static final String DRM_CONTENT = "drm_c"; 1728 1729 /** 1730 * The {@code adaptation-allowed} of the message. 1731 * <P>Type: TEXT</P> 1732 * @deprecated this column is no longer supported. 1733 * @hide 1734 */ 1735 @Deprecated 1736 public static final String ADAPTATION_ALLOWED = "adp_a"; 1737 1738 /** 1739 * The {@code replace-id} of the message. 1740 * <P>Type: TEXT</P> 1741 * @deprecated this column is no longer supported. 1742 * @hide 1743 */ 1744 @Deprecated 1745 public static final String REPLACE_ID = "repl_id"; 1746 1747 /** 1748 * The {@code cancel-id} of the message. 1749 * <P>Type: TEXT</P> 1750 * @deprecated this column is no longer supported. 1751 * @hide 1752 */ 1753 @Deprecated 1754 public static final String CANCEL_ID = "cl_id"; 1755 1756 /** 1757 * The {@code cancel-status} of the message. 1758 * <P>Type: INTEGER</P> 1759 * @deprecated this column is no longer supported. 1760 * @hide 1761 */ 1762 @Deprecated 1763 public static final String CANCEL_STATUS = "cl_st"; 1764 1765 /** 1766 * Is the message locked? 1767 * <P>Type: INTEGER (boolean)</P> 1768 */ 1769 public static final String LOCKED = "locked"; 1770 1771 /** 1772 * The subscription to which the message belongs to. Its value will be 1773 * < 0 if the sub id cannot be determined. 1774 * <p>Type: INTEGER (long)</p> 1775 */ 1776 public static final String SUBSCRIPTION_ID = "sub_id"; 1777 1778 /** 1779 * The identity of the sender of a sent message. It is 1780 * usually the package name of the app which sends the message. 1781 * <p class="note"><strong>Note:</strong> 1782 * This column is read-only. It is set by the provider and can not be changed by apps. 1783 * <p>Type: TEXT</p> 1784 */ 1785 public static final String CREATOR = "creator"; 1786 } 1787 1788 /** 1789 * Columns for the "canonical_addresses" table used by MMS and SMS. 1790 */ 1791 public interface CanonicalAddressesColumns extends BaseColumns { 1792 /** 1793 * An address used in MMS or SMS. Email addresses are 1794 * converted to lower case and are compared by string 1795 * equality. Other addresses are compared using 1796 * PHONE_NUMBERS_EQUAL. 1797 * <P>Type: TEXT</P> 1798 */ 1799 public static final String ADDRESS = "address"; 1800 } 1801 1802 /** 1803 * Columns for the "threads" table used by MMS and SMS. 1804 */ 1805 public interface ThreadsColumns extends BaseColumns { 1806 1807 /** 1808 * The date at which the thread was created. 1809 * <P>Type: INTEGER (long)</P> 1810 */ 1811 public static final String DATE = "date"; 1812 1813 /** 1814 * A string encoding of the recipient IDs of the recipients of 1815 * the message, in numerical order and separated by spaces. 1816 * <P>Type: TEXT</P> 1817 */ 1818 public static final String RECIPIENT_IDS = "recipient_ids"; 1819 1820 /** 1821 * The message count of the thread. 1822 * <P>Type: INTEGER</P> 1823 */ 1824 public static final String MESSAGE_COUNT = "message_count"; 1825 1826 /** 1827 * Indicates whether all messages of the thread have been read. 1828 * <P>Type: INTEGER</P> 1829 */ 1830 public static final String READ = "read"; 1831 1832 /** 1833 * The snippet of the latest message in the thread. 1834 * <P>Type: TEXT</P> 1835 */ 1836 public static final String SNIPPET = "snippet"; 1837 1838 /** 1839 * The charset of the snippet. 1840 * <P>Type: INTEGER</P> 1841 */ 1842 public static final String SNIPPET_CHARSET = "snippet_cs"; 1843 1844 /** 1845 * Type of the thread, either {@link Threads#COMMON_THREAD} or 1846 * {@link Threads#BROADCAST_THREAD}. 1847 * <P>Type: INTEGER</P> 1848 */ 1849 public static final String TYPE = "type"; 1850 1851 /** 1852 * Indicates whether there is a transmission error in the thread. 1853 * <P>Type: INTEGER</P> 1854 */ 1855 public static final String ERROR = "error"; 1856 1857 /** 1858 * Indicates whether this thread contains any attachments. 1859 * <P>Type: INTEGER</P> 1860 */ 1861 public static final String HAS_ATTACHMENT = "has_attachment"; 1862 1863 /** 1864 * If the thread is archived 1865 * <P>Type: INTEGER (boolean)</P> 1866 */ 1867 public static final String ARCHIVED = "archived"; 1868 } 1869 1870 /** 1871 * Helper functions for the "threads" table used by MMS and SMS. 1872 */ 1873 public static final class Threads implements ThreadsColumns { 1874 1875 private static final String[] ID_PROJECTION = { BaseColumns._ID }; 1876 1877 /** 1878 * Private {@code content://} style URL for this table. Used by 1879 * {@link #getOrCreateThreadId(android.content.Context, java.util.Set)}. 1880 */ 1881 private static final Uri THREAD_ID_CONTENT_URI = Uri.parse( 1882 "content://mms-sms/threadID"); 1883 1884 /** 1885 * The {@code content://} style URL for this table, by conversation. 1886 */ 1887 public static final Uri CONTENT_URI = Uri.withAppendedPath( 1888 MmsSms.CONTENT_URI, "conversations"); 1889 1890 /** 1891 * The {@code content://} style URL for this table, for obsolete threads. 1892 */ 1893 public static final Uri OBSOLETE_THREADS_URI = Uri.withAppendedPath( 1894 CONTENT_URI, "obsolete"); 1895 1896 /** Thread type: common thread. */ 1897 public static final int COMMON_THREAD = 0; 1898 1899 /** Thread type: broadcast thread. */ 1900 public static final int BROADCAST_THREAD = 1; 1901 1902 /** 1903 * Not instantiable. 1904 * @hide 1905 */ Threads()1906 private Threads() { 1907 } 1908 1909 /** 1910 * This is a single-recipient version of {@code getOrCreateThreadId}. 1911 * It's convenient for use with SMS messages. 1912 * @param context the context object to use. 1913 * @param recipient the recipient to send to. 1914 */ getOrCreateThreadId(Context context, String recipient)1915 public static long getOrCreateThreadId(Context context, String recipient) { 1916 Set<String> recipients = new HashSet<String>(); 1917 1918 recipients.add(recipient); 1919 return getOrCreateThreadId(context, recipients); 1920 } 1921 1922 /** 1923 * Given the recipients list and subject of an unsaved message, 1924 * return its thread ID. If the message starts a new thread, 1925 * allocate a new thread ID. Otherwise, use the appropriate 1926 * existing thread ID. 1927 * 1928 * <p>Find the thread ID of the same set of recipients (in any order, 1929 * without any additions). If one is found, return it. Otherwise, 1930 * return a unique thread ID.</p> 1931 */ getOrCreateThreadId( Context context, Set<String> recipients)1932 public static long getOrCreateThreadId( 1933 Context context, Set<String> recipients) { 1934 Uri.Builder uriBuilder = THREAD_ID_CONTENT_URI.buildUpon(); 1935 1936 for (String recipient : recipients) { 1937 if (Mms.isEmailAddress(recipient)) { 1938 recipient = Mms.extractAddrSpec(recipient); 1939 } 1940 1941 uriBuilder.appendQueryParameter("recipient", recipient); 1942 } 1943 1944 Uri uri = uriBuilder.build(); 1945 //if (DEBUG) Rlog.v(TAG, "getOrCreateThreadId uri: " + uri); 1946 1947 Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(), 1948 uri, ID_PROJECTION, null, null, null); 1949 if (cursor != null) { 1950 try { 1951 if (cursor.moveToFirst()) { 1952 return cursor.getLong(0); 1953 } else { 1954 Rlog.e(TAG, "getOrCreateThreadId returned no rows!"); 1955 } 1956 } finally { 1957 cursor.close(); 1958 } 1959 } 1960 1961 Rlog.e(TAG, "getOrCreateThreadId failed with " + recipients.size() + " recipients"); 1962 throw new IllegalArgumentException("Unable to find or allocate a thread ID."); 1963 } 1964 } 1965 1966 /** 1967 * Contains all MMS messages. 1968 */ 1969 public static final class Mms implements BaseMmsColumns { 1970 1971 /** 1972 * Not instantiable. 1973 * @hide 1974 */ Mms()1975 private Mms() { 1976 } 1977 1978 /** 1979 * The {@code content://} URI for this table. 1980 */ 1981 public static final Uri CONTENT_URI = Uri.parse("content://mms"); 1982 1983 /** 1984 * Content URI for getting MMS report requests. 1985 */ 1986 public static final Uri REPORT_REQUEST_URI = Uri.withAppendedPath( 1987 CONTENT_URI, "report-request"); 1988 1989 /** 1990 * Content URI for getting MMS report status. 1991 */ 1992 public static final Uri REPORT_STATUS_URI = Uri.withAppendedPath( 1993 CONTENT_URI, "report-status"); 1994 1995 /** 1996 * The default sort order for this table. 1997 */ 1998 public static final String DEFAULT_SORT_ORDER = "date DESC"; 1999 2000 /** 2001 * Regex pattern for names and email addresses. 2002 * <ul> 2003 * <li><em>mailbox</em> = {@code name-addr}</li> 2004 * <li><em>name-addr</em> = {@code [display-name] angle-addr}</li> 2005 * <li><em>angle-addr</em> = {@code [CFWS] "<" addr-spec ">" [CFWS]}</li> 2006 * </ul> 2007 * @hide 2008 */ 2009 public static final Pattern NAME_ADDR_EMAIL_PATTERN = 2010 Pattern.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*"); 2011 2012 /** 2013 * Helper method to query this table. 2014 * @hide 2015 */ query( ContentResolver cr, String[] projection)2016 public static Cursor query( 2017 ContentResolver cr, String[] projection) { 2018 return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER); 2019 } 2020 2021 /** 2022 * Helper method to query this table. 2023 * @hide 2024 */ query( ContentResolver cr, String[] projection, String where, String orderBy)2025 public static Cursor query( 2026 ContentResolver cr, String[] projection, 2027 String where, String orderBy) { 2028 return cr.query(CONTENT_URI, projection, 2029 where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy); 2030 } 2031 2032 /** 2033 * Helper method to extract email address from address string. 2034 * @hide 2035 */ extractAddrSpec(String address)2036 public static String extractAddrSpec(String address) { 2037 Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(address); 2038 2039 if (match.matches()) { 2040 return match.group(2); 2041 } 2042 return address; 2043 } 2044 2045 /** 2046 * Is the specified address an email address? 2047 * 2048 * @param address the input address to test 2049 * @return true if address is an email address; false otherwise. 2050 * @hide 2051 */ isEmailAddress(String address)2052 public static boolean isEmailAddress(String address) { 2053 if (TextUtils.isEmpty(address)) { 2054 return false; 2055 } 2056 2057 String s = extractAddrSpec(address); 2058 Matcher match = Patterns.EMAIL_ADDRESS.matcher(s); 2059 return match.matches(); 2060 } 2061 2062 /** 2063 * Is the specified number a phone number? 2064 * 2065 * @param number the input number to test 2066 * @return true if number is a phone number; false otherwise. 2067 * @hide 2068 */ isPhoneNumber(String number)2069 public static boolean isPhoneNumber(String number) { 2070 if (TextUtils.isEmpty(number)) { 2071 return false; 2072 } 2073 2074 Matcher match = Patterns.PHONE.matcher(number); 2075 return match.matches(); 2076 } 2077 2078 /** 2079 * Contains all MMS messages in the MMS app inbox. 2080 */ 2081 public static final class Inbox implements BaseMmsColumns { 2082 2083 /** 2084 * Not instantiable. 2085 * @hide 2086 */ Inbox()2087 private Inbox() { 2088 } 2089 2090 /** 2091 * The {@code content://} style URL for this table. 2092 */ 2093 public static final Uri 2094 CONTENT_URI = Uri.parse("content://mms/inbox"); 2095 2096 /** 2097 * The default sort order for this table. 2098 */ 2099 public static final String DEFAULT_SORT_ORDER = "date DESC"; 2100 } 2101 2102 /** 2103 * Contains all MMS messages in the MMS app sent folder. 2104 */ 2105 public static final class Sent implements BaseMmsColumns { 2106 2107 /** 2108 * Not instantiable. 2109 * @hide 2110 */ Sent()2111 private Sent() { 2112 } 2113 2114 /** 2115 * The {@code content://} style URL for this table. 2116 */ 2117 public static final Uri 2118 CONTENT_URI = Uri.parse("content://mms/sent"); 2119 2120 /** 2121 * The default sort order for this table. 2122 */ 2123 public static final String DEFAULT_SORT_ORDER = "date DESC"; 2124 } 2125 2126 /** 2127 * Contains all MMS messages in the MMS app drafts folder. 2128 */ 2129 public static final class Draft implements BaseMmsColumns { 2130 2131 /** 2132 * Not instantiable. 2133 * @hide 2134 */ Draft()2135 private Draft() { 2136 } 2137 2138 /** 2139 * The {@code content://} style URL for this table. 2140 */ 2141 public static final Uri 2142 CONTENT_URI = Uri.parse("content://mms/drafts"); 2143 2144 /** 2145 * The default sort order for this table. 2146 */ 2147 public static final String DEFAULT_SORT_ORDER = "date DESC"; 2148 } 2149 2150 /** 2151 * Contains all MMS messages in the MMS app outbox. 2152 */ 2153 public static final class Outbox implements BaseMmsColumns { 2154 2155 /** 2156 * Not instantiable. 2157 * @hide 2158 */ Outbox()2159 private Outbox() { 2160 } 2161 2162 /** 2163 * The {@code content://} style URL for this table. 2164 */ 2165 public static final Uri 2166 CONTENT_URI = Uri.parse("content://mms/outbox"); 2167 2168 /** 2169 * The default sort order for this table. 2170 */ 2171 public static final String DEFAULT_SORT_ORDER = "date DESC"; 2172 } 2173 2174 /** 2175 * Contains address information for an MMS message. 2176 */ 2177 public static final class Addr implements BaseColumns { 2178 2179 /** 2180 * Not instantiable. 2181 * @hide 2182 */ Addr()2183 private Addr() { 2184 } 2185 2186 /** 2187 * The ID of MM which this address entry belongs to. 2188 * <P>Type: INTEGER (long)</P> 2189 */ 2190 public static final String MSG_ID = "msg_id"; 2191 2192 /** 2193 * The ID of contact entry in Phone Book. 2194 * <P>Type: INTEGER (long)</P> 2195 */ 2196 public static final String CONTACT_ID = "contact_id"; 2197 2198 /** 2199 * The address text. 2200 * <P>Type: TEXT</P> 2201 */ 2202 public static final String ADDRESS = "address"; 2203 2204 /** 2205 * Type of address: must be one of {@code PduHeaders.BCC}, 2206 * {@code PduHeaders.CC}, {@code PduHeaders.FROM}, {@code PduHeaders.TO}. 2207 * <P>Type: INTEGER</P> 2208 */ 2209 public static final String TYPE = "type"; 2210 2211 /** 2212 * Character set of this entry (MMS charset value). 2213 * <P>Type: INTEGER</P> 2214 */ 2215 public static final String CHARSET = "charset"; 2216 } 2217 2218 /** 2219 * Contains message parts. 2220 */ 2221 public static final class Part implements BaseColumns { 2222 2223 /** 2224 * Not instantiable. 2225 * @hide 2226 */ Part()2227 private Part() { 2228 } 2229 2230 /** 2231 * The identifier of the message which this part belongs to. 2232 * <P>Type: INTEGER</P> 2233 */ 2234 public static final String MSG_ID = "mid"; 2235 2236 /** 2237 * The order of the part. 2238 * <P>Type: INTEGER</P> 2239 */ 2240 public static final String SEQ = "seq"; 2241 2242 /** 2243 * The content type of the part. 2244 * <P>Type: TEXT</P> 2245 */ 2246 public static final String CONTENT_TYPE = "ct"; 2247 2248 /** 2249 * The name of the part. 2250 * <P>Type: TEXT</P> 2251 */ 2252 public static final String NAME = "name"; 2253 2254 /** 2255 * The charset of the part. 2256 * <P>Type: TEXT</P> 2257 */ 2258 public static final String CHARSET = "chset"; 2259 2260 /** 2261 * The file name of the part. 2262 * <P>Type: TEXT</P> 2263 */ 2264 public static final String FILENAME = "fn"; 2265 2266 /** 2267 * The content disposition of the part. 2268 * <P>Type: TEXT</P> 2269 */ 2270 public static final String CONTENT_DISPOSITION = "cd"; 2271 2272 /** 2273 * The content ID of the part. 2274 * <P>Type: INTEGER</P> 2275 */ 2276 public static final String CONTENT_ID = "cid"; 2277 2278 /** 2279 * The content location of the part. 2280 * <P>Type: INTEGER</P> 2281 */ 2282 public static final String CONTENT_LOCATION = "cl"; 2283 2284 /** 2285 * The start of content-type of the message. 2286 * <P>Type: INTEGER</P> 2287 */ 2288 public static final String CT_START = "ctt_s"; 2289 2290 /** 2291 * The type of content-type of the message. 2292 * <P>Type: TEXT</P> 2293 */ 2294 public static final String CT_TYPE = "ctt_t"; 2295 2296 /** 2297 * The location (on filesystem) of the binary data of the part. 2298 * <P>Type: INTEGER</P> 2299 */ 2300 public static final String _DATA = "_data"; 2301 2302 /** 2303 * The message text. 2304 * <P>Type: TEXT</P> 2305 */ 2306 public static final String TEXT = "text"; 2307 } 2308 2309 /** 2310 * Message send rate table. 2311 */ 2312 public static final class Rate { 2313 2314 /** 2315 * Not instantiable. 2316 * @hide 2317 */ Rate()2318 private Rate() { 2319 } 2320 2321 /** 2322 * The {@code content://} style URL for this table. 2323 */ 2324 public static final Uri CONTENT_URI = Uri.withAppendedPath( 2325 Mms.CONTENT_URI, "rate"); 2326 2327 /** 2328 * When a message was successfully sent. 2329 * <P>Type: INTEGER (long)</P> 2330 */ 2331 public static final String SENT_TIME = "sent_time"; 2332 } 2333 2334 /** 2335 * Intents class. 2336 */ 2337 public static final class Intents { 2338 2339 /** 2340 * Not instantiable. 2341 * @hide 2342 */ Intents()2343 private Intents() { 2344 } 2345 2346 /** 2347 * Indicates that the contents of specified URIs were changed. 2348 * The application which is showing or caching these contents 2349 * should be updated. 2350 */ 2351 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 2352 public static final String CONTENT_CHANGED_ACTION 2353 = "android.intent.action.CONTENT_CHANGED"; 2354 2355 /** 2356 * An extra field which stores the URI of deleted contents. 2357 */ 2358 public static final String DELETED_CONTENTS = "deleted_contents"; 2359 } 2360 } 2361 2362 /** 2363 * Contains all MMS and SMS messages. 2364 */ 2365 public static final class MmsSms implements BaseColumns { 2366 2367 /** 2368 * Not instantiable. 2369 * @hide 2370 */ MmsSms()2371 private MmsSms() { 2372 } 2373 2374 /** 2375 * The column to distinguish SMS and MMS messages in query results. 2376 */ 2377 public static final String TYPE_DISCRIMINATOR_COLUMN = 2378 "transport_type"; 2379 2380 /** 2381 * The {@code content://} style URL for this table. 2382 */ 2383 public static final Uri CONTENT_URI = Uri.parse("content://mms-sms/"); 2384 2385 /** 2386 * The {@code content://} style URL for this table, by conversation. 2387 */ 2388 public static final Uri CONTENT_CONVERSATIONS_URI = Uri.parse( 2389 "content://mms-sms/conversations"); 2390 2391 /** 2392 * The {@code content://} style URL for this table, by phone number. 2393 */ 2394 public static final Uri CONTENT_FILTER_BYPHONE_URI = Uri.parse( 2395 "content://mms-sms/messages/byphone"); 2396 2397 /** 2398 * The {@code content://} style URL for undelivered messages in this table. 2399 */ 2400 public static final Uri CONTENT_UNDELIVERED_URI = Uri.parse( 2401 "content://mms-sms/undelivered"); 2402 2403 /** 2404 * The {@code content://} style URL for draft messages in this table. 2405 */ 2406 public static final Uri CONTENT_DRAFT_URI = Uri.parse( 2407 "content://mms-sms/draft"); 2408 2409 /** 2410 * The {@code content://} style URL for locked messages in this table. 2411 */ 2412 public static final Uri CONTENT_LOCKED_URI = Uri.parse( 2413 "content://mms-sms/locked"); 2414 2415 /** 2416 * Pass in a query parameter called "pattern" which is the text to search for. 2417 * The sort order is fixed to be: {@code thread_id ASC, date DESC}. 2418 */ 2419 public static final Uri SEARCH_URI = Uri.parse( 2420 "content://mms-sms/search"); 2421 2422 // Constants for message protocol types. 2423 2424 /** SMS protocol type. */ 2425 public static final int SMS_PROTO = 0; 2426 2427 /** MMS protocol type. */ 2428 public static final int MMS_PROTO = 1; 2429 2430 // Constants for error types of pending messages. 2431 2432 /** Error type: no error. */ 2433 public static final int NO_ERROR = 0; 2434 2435 /** Error type: generic transient error. */ 2436 public static final int ERR_TYPE_GENERIC = 1; 2437 2438 /** Error type: SMS protocol transient error. */ 2439 public static final int ERR_TYPE_SMS_PROTO_TRANSIENT = 2; 2440 2441 /** Error type: MMS protocol transient error. */ 2442 public static final int ERR_TYPE_MMS_PROTO_TRANSIENT = 3; 2443 2444 /** Error type: transport failure. */ 2445 public static final int ERR_TYPE_TRANSPORT_FAILURE = 4; 2446 2447 /** Error type: permanent error (along with all higher error values). */ 2448 public static final int ERR_TYPE_GENERIC_PERMANENT = 10; 2449 2450 /** Error type: SMS protocol permanent error. */ 2451 public static final int ERR_TYPE_SMS_PROTO_PERMANENT = 11; 2452 2453 /** Error type: MMS protocol permanent error. */ 2454 public static final int ERR_TYPE_MMS_PROTO_PERMANENT = 12; 2455 2456 /** 2457 * Contains pending messages info. 2458 */ 2459 public static final class PendingMessages implements BaseColumns { 2460 2461 /** 2462 * Not instantiable. 2463 * @hide 2464 */ PendingMessages()2465 private PendingMessages() { 2466 } 2467 2468 public static final Uri CONTENT_URI = Uri.withAppendedPath( 2469 MmsSms.CONTENT_URI, "pending"); 2470 2471 /** 2472 * The type of transport protocol (MMS or SMS). 2473 * <P>Type: INTEGER</P> 2474 */ 2475 public static final String PROTO_TYPE = "proto_type"; 2476 2477 /** 2478 * The ID of the message to be sent or downloaded. 2479 * <P>Type: INTEGER (long)</P> 2480 */ 2481 public static final String MSG_ID = "msg_id"; 2482 2483 /** 2484 * The type of the message to be sent or downloaded. 2485 * This field is only valid for MM. For SM, its value is always set to 0. 2486 * <P>Type: INTEGER</P> 2487 */ 2488 public static final String MSG_TYPE = "msg_type"; 2489 2490 /** 2491 * The type of the error code. 2492 * <P>Type: INTEGER</P> 2493 */ 2494 public static final String ERROR_TYPE = "err_type"; 2495 2496 /** 2497 * The error code of sending/retrieving process. 2498 * <P>Type: INTEGER</P> 2499 */ 2500 public static final String ERROR_CODE = "err_code"; 2501 2502 /** 2503 * How many times we tried to send or download the message. 2504 * <P>Type: INTEGER</P> 2505 */ 2506 public static final String RETRY_INDEX = "retry_index"; 2507 2508 /** 2509 * The time to do next retry. 2510 * <P>Type: INTEGER (long)</P> 2511 */ 2512 public static final String DUE_TIME = "due_time"; 2513 2514 /** 2515 * The time we last tried to send or download the message. 2516 * <P>Type: INTEGER (long)</P> 2517 */ 2518 public static final String LAST_TRY = "last_try"; 2519 2520 /** 2521 * The subscription to which the message belongs to. Its value will be 2522 * < 0 if the sub id cannot be determined. 2523 * <p>Type: INTEGER (long) </p> 2524 */ 2525 public static final String SUBSCRIPTION_ID = "pending_sub_id"; 2526 } 2527 2528 /** 2529 * Words table used by provider for full-text searches. 2530 * @hide 2531 */ 2532 public static final class WordsTable { 2533 2534 /** 2535 * Not instantiable. 2536 * @hide 2537 */ WordsTable()2538 private WordsTable() {} 2539 2540 /** 2541 * Primary key. 2542 * <P>Type: INTEGER (long)</P> 2543 */ 2544 public static final String ID = "_id"; 2545 2546 /** 2547 * Source row ID. 2548 * <P>Type: INTEGER (long)</P> 2549 */ 2550 public static final String SOURCE_ROW_ID = "source_id"; 2551 2552 /** 2553 * Table ID (either 1 or 2). 2554 * <P>Type: INTEGER</P> 2555 */ 2556 public static final String TABLE_ID = "table_to_use"; 2557 2558 /** 2559 * The words to index. 2560 * <P>Type: TEXT</P> 2561 */ 2562 public static final String INDEXED_TEXT = "index_text"; 2563 } 2564 } 2565 2566 /** 2567 * Carriers class contains information about APNs, including MMSC information. 2568 */ 2569 public static final class Carriers implements BaseColumns { 2570 2571 /** 2572 * Not instantiable. 2573 * @hide 2574 */ Carriers()2575 private Carriers() {} 2576 2577 /** 2578 * The {@code content://} style URL for this table. 2579 */ 2580 public static final Uri CONTENT_URI = Uri.parse("content://telephony/carriers"); 2581 2582 /** 2583 * The {@code content://} style URL to be called from DevicePolicyManagerService, 2584 * can manage DPC-owned APNs. 2585 * @hide 2586 */ 2587 public static final Uri DPC_URI = Uri.parse("content://telephony/carriers/dpc"); 2588 2589 /** 2590 * The {@code content://} style URL to be called from Telephony to query APNs. 2591 * When DPC-owned APNs are enforced, only DPC-owned APNs are returned, otherwise only 2592 * non-DPC-owned APNs are returned. 2593 * @hide 2594 */ 2595 public static final Uri FILTERED_URI = Uri.parse("content://telephony/carriers/filtered"); 2596 2597 /** 2598 * The {@code content://} style URL to be called from DevicePolicyManagerService 2599 * or Telephony to manage whether DPC-owned APNs are enforced. 2600 * @hide 2601 */ 2602 public static final Uri ENFORCE_MANAGED_URI = Uri.parse( 2603 "content://telephony/carriers/enforce_managed"); 2604 2605 /** 2606 * The column name for ENFORCE_MANAGED_URI, indicates whether DPC-owned APNs are enforced. 2607 * @hide 2608 */ 2609 public static final String ENFORCE_KEY = "enforced"; 2610 2611 /** 2612 * The default sort order for this table. 2613 */ 2614 public static final String DEFAULT_SORT_ORDER = "name ASC"; 2615 2616 /** 2617 * Entry name. 2618 * <P>Type: TEXT</P> 2619 */ 2620 public static final String NAME = "name"; 2621 2622 /** 2623 * APN name. 2624 * <P>Type: TEXT</P> 2625 */ 2626 public static final String APN = "apn"; 2627 2628 /** 2629 * Proxy address. 2630 * <P>Type: TEXT</P> 2631 */ 2632 public static final String PROXY = "proxy"; 2633 2634 /** 2635 * Proxy port. 2636 * <P>Type: TEXT</P> 2637 */ 2638 public static final String PORT = "port"; 2639 2640 /** 2641 * MMS proxy address. 2642 * <P>Type: TEXT</P> 2643 */ 2644 public static final String MMSPROXY = "mmsproxy"; 2645 2646 /** 2647 * MMS proxy port. 2648 * <P>Type: TEXT</P> 2649 */ 2650 public static final String MMSPORT = "mmsport"; 2651 2652 /** 2653 * Server address. 2654 * <P>Type: TEXT</P> 2655 */ 2656 public static final String SERVER = "server"; 2657 2658 /** 2659 * APN username. 2660 * <P>Type: TEXT</P> 2661 */ 2662 public static final String USER = "user"; 2663 2664 /** 2665 * APN password. 2666 * <P>Type: TEXT</P> 2667 */ 2668 public static final String PASSWORD = "password"; 2669 2670 /** 2671 * MMSC URL. 2672 * <P>Type: TEXT</P> 2673 */ 2674 public static final String MMSC = "mmsc"; 2675 2676 /** 2677 * Mobile Country Code (MCC). 2678 * <P>Type: TEXT</P> 2679 */ 2680 public static final String MCC = "mcc"; 2681 2682 /** 2683 * Mobile Network Code (MNC). 2684 * <P>Type: TEXT</P> 2685 */ 2686 public static final String MNC = "mnc"; 2687 2688 /** 2689 * Numeric operator ID (as String). Usually {@code MCC + MNC}. 2690 * <P>Type: TEXT</P> 2691 */ 2692 public static final String NUMERIC = "numeric"; 2693 2694 /** 2695 * Authentication type. 2696 * <P>Type: INTEGER</P> 2697 */ 2698 public static final String AUTH_TYPE = "authtype"; 2699 2700 /** 2701 * Comma-delimited list of APN types. 2702 * <P>Type: TEXT</P> 2703 */ 2704 public static final String TYPE = "type"; 2705 2706 /** 2707 * The protocol to use to connect to this APN. 2708 * 2709 * One of the {@code PDP_type} values in TS 27.007 section 10.1.1. 2710 * For example: {@code IP}, {@code IPV6}, {@code IPV4V6}, or {@code PPP}. 2711 * <P>Type: TEXT</P> 2712 */ 2713 public static final String PROTOCOL = "protocol"; 2714 2715 /** 2716 * The protocol to use to connect to this APN when roaming. 2717 * The syntax is the same as protocol. 2718 * <P>Type: TEXT</P> 2719 */ 2720 public static final String ROAMING_PROTOCOL = "roaming_protocol"; 2721 2722 /** 2723 * Is this the current APN? 2724 * <P>Type: INTEGER (boolean)</P> 2725 */ 2726 public static final String CURRENT = "current"; 2727 2728 /** 2729 * Is this APN enabled? 2730 * <P>Type: INTEGER (boolean)</P> 2731 */ 2732 public static final String CARRIER_ENABLED = "carrier_enabled"; 2733 2734 /** 2735 * Radio Access Technology info. 2736 * To check what values are allowed, refer to {@link android.telephony.ServiceState}. 2737 * This should be spread to other technologies, 2738 * but is currently only used for LTE (14) and eHRPD (13). 2739 * <P>Type: INTEGER</P> 2740 * @deprecated this column is no longer supported, use {@link #NETWORK_TYPE_BITMASK} instead 2741 */ 2742 @Deprecated 2743 public static final String BEARER = "bearer"; 2744 2745 /** 2746 * Radio Access Technology bitmask. 2747 * To check what values can be contained, refer to {@link android.telephony.ServiceState}. 2748 * 0 indicates all techs otherwise first bit refers to RAT/bearer 1, second bit refers to 2749 * RAT/bearer 2 and so on. 2750 * Bitmask for a radio tech R is (1 << (R - 1)) 2751 * <P>Type: INTEGER</P> 2752 * @hide 2753 * @deprecated this column is no longer supported, use {@link #NETWORK_TYPE_BITMASK} instead 2754 */ 2755 @Deprecated 2756 public static final String BEARER_BITMASK = "bearer_bitmask"; 2757 2758 /** 2759 * Radio technology (network type) bitmask. 2760 * To check what values can be contained, refer to the NETWORK_TYPE_ constants in 2761 * {@link android.telephony.TelephonyManager}. 2762 * Bitmask for a radio tech R is (1 << (R - 1)) 2763 * <P>Type: INTEGER</P> 2764 */ 2765 public static final String NETWORK_TYPE_BITMASK = "network_type_bitmask"; 2766 2767 /** 2768 * MVNO type: 2769 * {@code SPN (Service Provider Name), IMSI, GID (Group Identifier Level 1)}. 2770 * <P>Type: TEXT</P> 2771 */ 2772 public static final String MVNO_TYPE = "mvno_type"; 2773 2774 /** 2775 * MVNO data. 2776 * Use the following examples. 2777 * <ul> 2778 * <li>SPN: A MOBILE, BEN NL, ...</li> 2779 * <li>IMSI: 302720x94, 2060188, ...</li> 2780 * <li>GID: 4E, 33, ...</li> 2781 * </ul> 2782 * <P>Type: TEXT</P> 2783 */ 2784 public static final String MVNO_MATCH_DATA = "mvno_match_data"; 2785 2786 /** 2787 * The subscription to which the APN belongs to 2788 * <p>Type: INTEGER (long) </p> 2789 */ 2790 public static final String SUBSCRIPTION_ID = "sub_id"; 2791 2792 /** 2793 * The profile_id to which the APN saved in modem 2794 * <p>Type: INTEGER</p> 2795 *@hide 2796 */ 2797 public static final String PROFILE_ID = "profile_id"; 2798 2799 /** 2800 * Is the apn setting to be set in modem 2801 * <P>Type: INTEGER (boolean)</P> 2802 *@hide 2803 */ 2804 public static final String MODEM_COGNITIVE = "modem_cognitive"; 2805 2806 /** 2807 * The max connections of this apn 2808 * <p>Type: INTEGER</p> 2809 *@hide 2810 */ 2811 public static final String MAX_CONNS = "max_conns"; 2812 2813 /** 2814 * The wait time for retry of the apn 2815 * <p>Type: INTEGER</p> 2816 *@hide 2817 */ 2818 public static final String WAIT_TIME = "wait_time"; 2819 2820 /** 2821 * The time to limit max connection for the apn 2822 * <p>Type: INTEGER</p> 2823 *@hide 2824 */ 2825 public static final String MAX_CONNS_TIME = "max_conns_time"; 2826 2827 /** 2828 * The MTU size of the mobile interface to which the APN connected 2829 * <p>Type: INTEGER </p> 2830 * @hide 2831 */ 2832 public static final String MTU = "mtu"; 2833 2834 /** 2835 * Is this APN added/edited/deleted by a user or carrier? 2836 * <p>Type: INTEGER </p> 2837 * @hide 2838 */ 2839 public static final String EDITED = "edited"; 2840 2841 /** 2842 * Is this APN visible to the user? 2843 * <p>Type: INTEGER (boolean) </p> 2844 * @hide 2845 */ 2846 public static final String USER_VISIBLE = "user_visible"; 2847 2848 /** 2849 * Is the user allowed to edit this APN? 2850 * <p>Type: INTEGER (boolean) </p> 2851 * @hide 2852 */ 2853 public static final String USER_EDITABLE = "user_editable"; 2854 2855 /** 2856 * Following are possible values for the EDITED field 2857 * @hide 2858 */ 2859 public static final int UNEDITED = 0; 2860 /** 2861 * @hide 2862 */ 2863 public static final int USER_EDITED = 1; 2864 /** 2865 * @hide 2866 */ 2867 public static final int USER_DELETED = 2; 2868 /** 2869 * DELETED_BUT_PRESENT is an intermediate value used to indicate that an entry deleted 2870 * by the user is still present in the new APN database and therefore must remain tagged 2871 * as user deleted rather than completely removed from the database 2872 * @hide 2873 */ 2874 public static final int USER_DELETED_BUT_PRESENT_IN_XML = 3; 2875 /** 2876 * @hide 2877 */ 2878 public static final int CARRIER_EDITED = 4; 2879 /** 2880 * CARRIER_DELETED values are currently not used as there is no usecase. If they are used, 2881 * delete() will have to change accordingly. Currently it is hardcoded to USER_DELETED. 2882 * @hide 2883 */ 2884 public static final int CARRIER_DELETED = 5; 2885 /** 2886 * @hide 2887 */ 2888 public static final int CARRIER_DELETED_BUT_PRESENT_IN_XML = 6; 2889 2890 /** 2891 * The owner of the APN. 2892 * <p>Type: INTEGER</p> 2893 * @hide 2894 */ 2895 public static final String OWNED_BY = "owned_by"; 2896 2897 /** 2898 * Possible value for the OWNED_BY field. 2899 * APN is owned by DPC. 2900 * @hide 2901 */ 2902 public static final int OWNED_BY_DPC = 0; 2903 2904 /** 2905 * Possible value for the OWNED_BY field. 2906 * APN is owned by other sources. 2907 * @hide 2908 */ 2909 public static final int OWNED_BY_OTHERS = 1; 2910 2911 /** 2912 * The APN set id. When the user manually selects an APN or the framework sets an APN as 2913 * preferred, all APNs with the same set id as the selected APN should be prioritized over 2914 * APNs in other sets. 2915 * @hide 2916 */ 2917 public static final String APN_SET_ID = "apn_set_id"; 2918 2919 /** 2920 * Possible value for the APN_SET_ID field. By default APNs will not belong to a set. If the 2921 * user manually selects an APN with no set set, there is no need to prioritize any specific 2922 * APN set ids. 2923 * @hide 2924 */ 2925 public static final int NO_SET_SET = 0; 2926 2927 } 2928 2929 /** 2930 * Contains received SMS cell broadcast messages. 2931 * @hide 2932 */ 2933 public static final class CellBroadcasts implements BaseColumns { 2934 2935 /** 2936 * Not instantiable. 2937 * @hide 2938 */ CellBroadcasts()2939 private CellBroadcasts() {} 2940 2941 /** 2942 * The {@code content://} URI for this table. 2943 */ 2944 public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts"); 2945 2946 /** 2947 * Message geographical scope. 2948 * <P>Type: INTEGER</P> 2949 */ 2950 public static final String GEOGRAPHICAL_SCOPE = "geo_scope"; 2951 2952 /** 2953 * Message serial number. 2954 * <P>Type: INTEGER</P> 2955 */ 2956 public static final String SERIAL_NUMBER = "serial_number"; 2957 2958 /** 2959 * PLMN of broadcast sender. {@code SERIAL_NUMBER + PLMN + LAC + CID} uniquely identifies 2960 * a broadcast for duplicate detection purposes. 2961 * <P>Type: TEXT</P> 2962 */ 2963 public static final String PLMN = "plmn"; 2964 2965 /** 2966 * Location Area (GSM) or Service Area (UMTS) of broadcast sender. Unused for CDMA. 2967 * Only included if Geographical Scope of message is not PLMN wide (01). 2968 * <P>Type: INTEGER</P> 2969 */ 2970 public static final String LAC = "lac"; 2971 2972 /** 2973 * Cell ID of message sender (GSM/UMTS). Unused for CDMA. Only included when the 2974 * Geographical Scope of message is cell wide (00 or 11). 2975 * <P>Type: INTEGER</P> 2976 */ 2977 public static final String CID = "cid"; 2978 2979 /** 2980 * Message code. <em>OBSOLETE: merged into SERIAL_NUMBER.</em> 2981 * <P>Type: INTEGER</P> 2982 */ 2983 public static final String V1_MESSAGE_CODE = "message_code"; 2984 2985 /** 2986 * Message identifier. <em>OBSOLETE: renamed to SERVICE_CATEGORY.</em> 2987 * <P>Type: INTEGER</P> 2988 */ 2989 public static final String V1_MESSAGE_IDENTIFIER = "message_id"; 2990 2991 /** 2992 * Service category (GSM/UMTS: message identifier; CDMA: service category). 2993 * <P>Type: INTEGER</P> 2994 */ 2995 public static final String SERVICE_CATEGORY = "service_category"; 2996 2997 /** 2998 * Message language code. 2999 * <P>Type: TEXT</P> 3000 */ 3001 public static final String LANGUAGE_CODE = "language"; 3002 3003 /** 3004 * Message body. 3005 * <P>Type: TEXT</P> 3006 */ 3007 public static final String MESSAGE_BODY = "body"; 3008 3009 /** 3010 * Message delivery time. 3011 * <P>Type: INTEGER (long)</P> 3012 */ 3013 public static final String DELIVERY_TIME = "date"; 3014 3015 /** 3016 * Has the message been viewed? 3017 * <P>Type: INTEGER (boolean)</P> 3018 */ 3019 public static final String MESSAGE_READ = "read"; 3020 3021 /** 3022 * Message format (3GPP or 3GPP2). 3023 * <P>Type: INTEGER</P> 3024 */ 3025 public static final String MESSAGE_FORMAT = "format"; 3026 3027 /** 3028 * Message priority (including emergency). 3029 * <P>Type: INTEGER</P> 3030 */ 3031 public static final String MESSAGE_PRIORITY = "priority"; 3032 3033 /** 3034 * ETWS warning type (ETWS alerts only). 3035 * <P>Type: INTEGER</P> 3036 */ 3037 public static final String ETWS_WARNING_TYPE = "etws_warning_type"; 3038 3039 /** 3040 * CMAS message class (CMAS alerts only). 3041 * <P>Type: INTEGER</P> 3042 */ 3043 public static final String CMAS_MESSAGE_CLASS = "cmas_message_class"; 3044 3045 /** 3046 * CMAS category (CMAS alerts only). 3047 * <P>Type: INTEGER</P> 3048 */ 3049 public static final String CMAS_CATEGORY = "cmas_category"; 3050 3051 /** 3052 * CMAS response type (CMAS alerts only). 3053 * <P>Type: INTEGER</P> 3054 */ 3055 public static final String CMAS_RESPONSE_TYPE = "cmas_response_type"; 3056 3057 /** 3058 * CMAS severity (CMAS alerts only). 3059 * <P>Type: INTEGER</P> 3060 */ 3061 public static final String CMAS_SEVERITY = "cmas_severity"; 3062 3063 /** 3064 * CMAS urgency (CMAS alerts only). 3065 * <P>Type: INTEGER</P> 3066 */ 3067 public static final String CMAS_URGENCY = "cmas_urgency"; 3068 3069 /** 3070 * CMAS certainty (CMAS alerts only). 3071 * <P>Type: INTEGER</P> 3072 */ 3073 public static final String CMAS_CERTAINTY = "cmas_certainty"; 3074 3075 /** The default sort order for this table. */ 3076 public static final String DEFAULT_SORT_ORDER = DELIVERY_TIME + " DESC"; 3077 3078 /** 3079 * Query columns for instantiating {@link android.telephony.CellBroadcastMessage} objects. 3080 */ 3081 public static final String[] QUERY_COLUMNS = { 3082 _ID, 3083 GEOGRAPHICAL_SCOPE, 3084 PLMN, 3085 LAC, 3086 CID, 3087 SERIAL_NUMBER, 3088 SERVICE_CATEGORY, 3089 LANGUAGE_CODE, 3090 MESSAGE_BODY, 3091 DELIVERY_TIME, 3092 MESSAGE_READ, 3093 MESSAGE_FORMAT, 3094 MESSAGE_PRIORITY, 3095 ETWS_WARNING_TYPE, 3096 CMAS_MESSAGE_CLASS, 3097 CMAS_CATEGORY, 3098 CMAS_RESPONSE_TYPE, 3099 CMAS_SEVERITY, 3100 CMAS_URGENCY, 3101 CMAS_CERTAINTY 3102 }; 3103 } 3104 3105 /** 3106 * Constants for interfacing with the ServiceStateProvider and the different fields of the 3107 * {@link ServiceState} class accessible through the provider. 3108 */ 3109 public static final class ServiceStateTable { 3110 3111 /** 3112 * Not instantiable. 3113 * @hide 3114 */ ServiceStateTable()3115 private ServiceStateTable() {} 3116 3117 /** 3118 * The authority string for the ServiceStateProvider 3119 */ 3120 public static final String AUTHORITY = "service-state"; 3121 3122 /** 3123 * The {@code content://} style URL for the ServiceStateProvider 3124 */ 3125 public static final Uri CONTENT_URI = Uri.parse("content://service-state/"); 3126 3127 /** 3128 * Generates a content {@link Uri} used to receive updates on a specific field in the 3129 * ServiceState provider. 3130 * <p> 3131 * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the 3132 * {@link ServiceState} while your app is running. You can also use a {@link JobService} to 3133 * ensure your app is notified of changes to the {@link Uri} even when it is not running. 3134 * Note, however, that using a {@link JobService} does not guarantee timely delivery of 3135 * updates to the {@link Uri}. 3136 * 3137 * @param subscriptionId the subscriptionId to receive updates on 3138 * @param field the ServiceState field to receive updates on 3139 * @return the Uri used to observe {@link ServiceState} changes 3140 */ getUriForSubscriptionIdAndField(int subscriptionId, String field)3141 public static Uri getUriForSubscriptionIdAndField(int subscriptionId, String field) { 3142 return CONTENT_URI.buildUpon().appendEncodedPath(String.valueOf(subscriptionId)) 3143 .appendEncodedPath(field).build(); 3144 } 3145 3146 /** 3147 * Generates a content {@link Uri} used to receive updates on every field in the 3148 * ServiceState provider. 3149 * <p> 3150 * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the 3151 * {@link ServiceState} while your app is running. You can also use a {@link JobService} to 3152 * ensure your app is notified of changes to the {@link Uri} even when it is not running. 3153 * Note, however, that using a {@link JobService} does not guarantee timely delivery of 3154 * updates to the {@link Uri}. 3155 * 3156 * @param subscriptionId the subscriptionId to receive updates on 3157 * @return the Uri used to observe {@link ServiceState} changes 3158 */ getUriForSubscriptionId(int subscriptionId)3159 public static Uri getUriForSubscriptionId(int subscriptionId) { 3160 return CONTENT_URI.buildUpon().appendEncodedPath(String.valueOf(subscriptionId)).build(); 3161 } 3162 3163 /** 3164 * Used to insert a ServiceState into the ServiceStateProvider as a ContentValues instance. 3165 * 3166 * @param state the ServiceState to convert into ContentValues 3167 * @return the convertedContentValues instance 3168 * @hide 3169 */ getContentValuesForServiceState(ServiceState state)3170 public static ContentValues getContentValuesForServiceState(ServiceState state) { 3171 ContentValues values = new ContentValues(); 3172 values.put(VOICE_REG_STATE, state.getVoiceRegState()); 3173 values.put(DATA_REG_STATE, state.getDataRegState()); 3174 values.put(VOICE_ROAMING_TYPE, state.getVoiceRoamingType()); 3175 values.put(DATA_ROAMING_TYPE, state.getDataRoamingType()); 3176 values.put(VOICE_OPERATOR_ALPHA_LONG, state.getVoiceOperatorAlphaLong()); 3177 values.put(VOICE_OPERATOR_ALPHA_SHORT, state.getVoiceOperatorAlphaShort()); 3178 values.put(VOICE_OPERATOR_NUMERIC, state.getVoiceOperatorNumeric()); 3179 values.put(DATA_OPERATOR_ALPHA_LONG, state.getDataOperatorAlphaLong()); 3180 values.put(DATA_OPERATOR_ALPHA_SHORT, state.getDataOperatorAlphaShort()); 3181 values.put(DATA_OPERATOR_NUMERIC, state.getDataOperatorNumeric()); 3182 values.put(IS_MANUAL_NETWORK_SELECTION, state.getIsManualSelection()); 3183 values.put(RIL_VOICE_RADIO_TECHNOLOGY, state.getRilVoiceRadioTechnology()); 3184 values.put(RIL_DATA_RADIO_TECHNOLOGY, state.getRilDataRadioTechnology()); 3185 values.put(CSS_INDICATOR, state.getCssIndicator()); 3186 values.put(NETWORK_ID, state.getCdmaNetworkId()); 3187 values.put(SYSTEM_ID, state.getCdmaSystemId()); 3188 values.put(CDMA_ROAMING_INDICATOR, state.getCdmaRoamingIndicator()); 3189 values.put(CDMA_DEFAULT_ROAMING_INDICATOR, state.getCdmaDefaultRoamingIndicator()); 3190 values.put(CDMA_ERI_ICON_INDEX, state.getCdmaEriIconIndex()); 3191 values.put(CDMA_ERI_ICON_MODE, state.getCdmaEriIconMode()); 3192 values.put(IS_EMERGENCY_ONLY, state.isEmergencyOnly()); 3193 values.put(IS_DATA_ROAMING_FROM_REGISTRATION, state.getDataRoamingFromRegistration()); 3194 values.put(IS_USING_CARRIER_AGGREGATION, state.isUsingCarrierAggregation()); 3195 return values; 3196 } 3197 3198 /** 3199 * An integer value indicating the current voice service state. 3200 * <p> 3201 * Valid values: {@link ServiceState#STATE_IN_SERVICE}, 3202 * {@link ServiceState#STATE_OUT_OF_SERVICE}, {@link ServiceState#STATE_EMERGENCY_ONLY}, 3203 * {@link ServiceState#STATE_POWER_OFF}. 3204 * <p> 3205 * This is the same as {@link ServiceState#getState()}. 3206 */ 3207 public static final String VOICE_REG_STATE = "voice_reg_state"; 3208 3209 /** 3210 * An integer value indicating the current data service state. 3211 * <p> 3212 * Valid values: {@link ServiceState#STATE_IN_SERVICE}, 3213 * {@link ServiceState#STATE_OUT_OF_SERVICE}, {@link ServiceState#STATE_EMERGENCY_ONLY}, 3214 * {@link ServiceState#STATE_POWER_OFF}. 3215 * <p> 3216 * This is the same as {@link ServiceState#getDataRegState()}. 3217 * @hide 3218 */ 3219 public static final String DATA_REG_STATE = "data_reg_state"; 3220 3221 /** 3222 * An integer value indicating the current voice roaming type. 3223 * <p> 3224 * This is the same as {@link ServiceState#getVoiceRoamingType()}. 3225 * @hide 3226 */ 3227 public static final String VOICE_ROAMING_TYPE = "voice_roaming_type"; 3228 3229 /** 3230 * An integer value indicating the current data roaming type. 3231 * <p> 3232 * This is the same as {@link ServiceState#getDataRoamingType()}. 3233 * @hide 3234 */ 3235 public static final String DATA_ROAMING_TYPE = "data_roaming_type"; 3236 3237 /** 3238 * The current registered voice network operator name in long alphanumeric format. 3239 * <p> 3240 * This is the same as {@link ServiceState#getVoiceOperatorAlphaLong()}. 3241 * @hide 3242 */ 3243 public static final String VOICE_OPERATOR_ALPHA_LONG = "voice_operator_alpha_long"; 3244 3245 /** 3246 * The current registered operator name in short alphanumeric format. 3247 * <p> 3248 * In GSM/UMTS, short format can be up to 8 characters long. The current registered voice 3249 * network operator name in long alphanumeric format. 3250 * <p> 3251 * This is the same as {@link ServiceState#getVoiceOperatorAlphaShort()}. 3252 * @hide 3253 */ 3254 public static final String VOICE_OPERATOR_ALPHA_SHORT = "voice_operator_alpha_short"; 3255 3256 3257 /** 3258 * The current registered operator numeric id. 3259 * <p> 3260 * In GSM/UMTS, numeric format is 3 digit country code plus 2 or 3 digit 3261 * network code. 3262 * <p> 3263 * This is the same as {@link ServiceState#getOperatorNumeric()}. 3264 */ 3265 public static final String VOICE_OPERATOR_NUMERIC = "voice_operator_numeric"; 3266 3267 /** 3268 * The current registered data network operator name in long alphanumeric format. 3269 * <p> 3270 * This is the same as {@link ServiceState#getDataOperatorAlphaLong()}. 3271 * @hide 3272 */ 3273 public static final String DATA_OPERATOR_ALPHA_LONG = "data_operator_alpha_long"; 3274 3275 /** 3276 * The current registered data network operator name in short alphanumeric format. 3277 * <p> 3278 * This is the same as {@link ServiceState#getDataOperatorAlphaShort()}. 3279 * @hide 3280 */ 3281 public static final String DATA_OPERATOR_ALPHA_SHORT = "data_operator_alpha_short"; 3282 3283 /** 3284 * The current registered data network operator numeric id. 3285 * <p> 3286 * This is the same as {@link ServiceState#getDataOperatorNumeric()}. 3287 * @hide 3288 */ 3289 public static final String DATA_OPERATOR_NUMERIC = "data_operator_numeric"; 3290 3291 /** 3292 * The current network selection mode. 3293 * <p> 3294 * This is the same as {@link ServiceState#getIsManualSelection()}. 3295 */ 3296 public static final String IS_MANUAL_NETWORK_SELECTION = "is_manual_network_selection"; 3297 3298 /** 3299 * This is the same as {@link ServiceState#getRilVoiceRadioTechnology()}. 3300 * @hide 3301 */ 3302 public static final String RIL_VOICE_RADIO_TECHNOLOGY = "ril_voice_radio_technology"; 3303 3304 /** 3305 * This is the same as {@link ServiceState#getRilDataRadioTechnology()}. 3306 * @hide 3307 */ 3308 public static final String RIL_DATA_RADIO_TECHNOLOGY = "ril_data_radio_technology"; 3309 3310 /** 3311 * This is the same as {@link ServiceState#getCssIndicator()}. 3312 * @hide 3313 */ 3314 public static final String CSS_INDICATOR = "css_indicator"; 3315 3316 /** 3317 * This is the same as {@link ServiceState#getCdmaNetworkId()}. 3318 * @hide 3319 */ 3320 public static final String NETWORK_ID = "network_id"; 3321 3322 /** 3323 * This is the same as {@link ServiceState#getCdmaSystemId()}. 3324 * @hide 3325 */ 3326 public static final String SYSTEM_ID = "system_id"; 3327 3328 /** 3329 * This is the same as {@link ServiceState#getCdmaRoamingIndicator()}. 3330 * @hide 3331 */ 3332 public static final String CDMA_ROAMING_INDICATOR = "cdma_roaming_indicator"; 3333 3334 /** 3335 * This is the same as {@link ServiceState#getCdmaDefaultRoamingIndicator()}. 3336 * @hide 3337 */ 3338 public static final String CDMA_DEFAULT_ROAMING_INDICATOR = 3339 "cdma_default_roaming_indicator"; 3340 3341 /** 3342 * This is the same as {@link ServiceState#getCdmaEriIconIndex()}. 3343 * @hide 3344 */ 3345 public static final String CDMA_ERI_ICON_INDEX = "cdma_eri_icon_index"; 3346 3347 /** 3348 * This is the same as {@link ServiceState#getCdmaEriIconMode()}. 3349 * @hide 3350 */ 3351 public static final String CDMA_ERI_ICON_MODE = "cdma_eri_icon_mode"; 3352 3353 /** 3354 * This is the same as {@link ServiceState#isEmergencyOnly()}. 3355 * @hide 3356 */ 3357 public static final String IS_EMERGENCY_ONLY = "is_emergency_only"; 3358 3359 /** 3360 * This is the same as {@link ServiceState#getDataRoamingFromRegistration()}. 3361 * @hide 3362 */ 3363 public static final String IS_DATA_ROAMING_FROM_REGISTRATION = 3364 "is_data_roaming_from_registration"; 3365 3366 /** 3367 * This is the same as {@link ServiceState#isUsingCarrierAggregation()}. 3368 * @hide 3369 */ 3370 public static final String IS_USING_CARRIER_AGGREGATION = "is_using_carrier_aggregation"; 3371 } 3372 3373 /** 3374 * Contains carrier identification information for the current subscriptions. 3375 * @see SubscriptionManager#getActiveSubscriptionIdList() 3376 */ 3377 public static final class CarrierId implements BaseColumns { 3378 /** 3379 * Not instantiable. 3380 * @hide 3381 */ CarrierId()3382 private CarrierId() {} 3383 3384 /** 3385 * The {@code content://} style URI for this provider. 3386 */ 3387 public static final Uri CONTENT_URI = Uri.parse("content://carrier_id"); 3388 3389 /** 3390 * The authority string for the CarrierId Provider 3391 * @hide 3392 */ 3393 public static final String AUTHORITY = "carrier_id"; 3394 3395 3396 /** 3397 * Generates a content {@link Uri} used to receive updates on carrier identity change 3398 * on the given subscriptionId 3399 * <p> 3400 * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the 3401 * carrier identity {@link TelephonyManager#getSimCarrierId()} 3402 * while your app is running. You can also use a {@link JobService} to ensure your app 3403 * is notified of changes to the {@link Uri} even when it is not running. 3404 * Note, however, that using a {@link JobService} does not guarantee timely delivery of 3405 * updates to the {@link Uri}. 3406 * 3407 * @param subscriptionId the subscriptionId to receive updates on 3408 * @return the Uri used to observe carrier identity changes 3409 */ getUriForSubscriptionId(int subscriptionId)3410 public static Uri getUriForSubscriptionId(int subscriptionId) { 3411 return CONTENT_URI.buildUpon().appendEncodedPath( 3412 String.valueOf(subscriptionId)).build(); 3413 } 3414 3415 /** 3416 * A user facing carrier name. 3417 * @see TelephonyManager#getSimCarrierIdName() 3418 * <P>Type: TEXT </P> 3419 */ 3420 public static final String CARRIER_NAME = "carrier_name"; 3421 3422 /** 3423 * A unique carrier id 3424 * @see TelephonyManager#getSimCarrierId() 3425 * <P>Type: INTEGER </P> 3426 */ 3427 public static final String CARRIER_ID = "carrier_id"; 3428 3429 /** 3430 * Contains mappings between matching rules with carrier id for all carriers. 3431 * @hide 3432 */ 3433 public static final class All implements BaseColumns { 3434 /** 3435 * Numeric operator ID (as String). {@code MCC + MNC} 3436 * <P>Type: TEXT </P> 3437 */ 3438 public static final String MCCMNC = "mccmnc"; 3439 3440 /** 3441 * Group id level 1 (as String). 3442 * <P>Type: TEXT </P> 3443 */ 3444 public static final String GID1 = "gid1"; 3445 3446 /** 3447 * Group id level 2 (as String). 3448 * <P>Type: TEXT </P> 3449 */ 3450 public static final String GID2 = "gid2"; 3451 3452 /** 3453 * Public Land Mobile Network name. 3454 * <P>Type: TEXT </P> 3455 */ 3456 public static final String PLMN = "plmn"; 3457 3458 /** 3459 * Prefix xpattern of IMSI (International Mobile Subscriber Identity). 3460 * <P>Type: TEXT </P> 3461 */ 3462 public static final String IMSI_PREFIX_XPATTERN = "imsi_prefix_xpattern"; 3463 3464 /** 3465 * Service Provider Name. 3466 * <P>Type: TEXT </P> 3467 */ 3468 public static final String SPN = "spn"; 3469 3470 /** 3471 * Prefer APN name. 3472 * <P>Type: TEXT </P> 3473 */ 3474 public static final String APN = "apn"; 3475 3476 /** 3477 * Prefix of Integrated Circuit Card Identifier. 3478 * <P>Type: TEXT </P> 3479 */ 3480 public static final String ICCID_PREFIX = "iccid_prefix"; 3481 3482 /** 3483 * The {@code content://} URI for this table. 3484 */ 3485 public static final Uri CONTENT_URI = Uri.parse("content://carrier_id/all"); 3486 } 3487 } 3488 } 3489