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 18 package android.provider; 19 20 import android.compat.annotation.UnsupportedAppUsage; 21 import android.content.ContentProvider; 22 import android.content.ContentResolver; 23 import android.content.ContentValues; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.pm.UserInfo; 27 import android.database.Cursor; 28 import android.location.Country; 29 import android.location.CountryDetector; 30 import android.net.Uri; 31 import android.os.Build; 32 import android.os.UserHandle; 33 import android.os.UserManager; 34 import android.provider.ContactsContract.CommonDataKinds.Callable; 35 import android.provider.ContactsContract.CommonDataKinds.Phone; 36 import android.provider.ContactsContract.Data; 37 import android.provider.ContactsContract.DataUsageFeedback; 38 import android.telecom.CallerInfo; 39 import android.telecom.PhoneAccount; 40 import android.telecom.PhoneAccountHandle; 41 import android.telecom.TelecomManager; 42 import android.telephony.PhoneNumberUtils; 43 import android.text.TextUtils; 44 import android.util.Log; 45 46 import java.util.List; 47 48 /** 49 * The CallLog provider contains information about placed and received calls. 50 */ 51 public class CallLog { 52 private static final String LOG_TAG = "CallLog"; 53 private static final boolean VERBOSE_LOG = false; // DON'T SUBMIT WITH TRUE. 54 55 public static final String AUTHORITY = "call_log"; 56 57 /** 58 * The content:// style URL for this provider 59 */ 60 public static final Uri CONTENT_URI = 61 Uri.parse("content://" + AUTHORITY); 62 63 64 /** 65 * The "shadow" provider stores calllog when the real calllog provider is encrypted. The 66 * real provider will alter copy from it when it starts, and remove the entries in the shadow. 67 * 68 * <p>See the comment in {@link Calls#addCall} for the details. 69 * 70 * @hide 71 */ 72 public static final String SHADOW_AUTHORITY = "call_log_shadow"; 73 74 /** 75 * Contains the recent calls. 76 */ 77 public static class Calls implements BaseColumns { 78 /** 79 * The content:// style URL for this table 80 */ 81 public static final Uri CONTENT_URI = 82 Uri.parse("content://call_log/calls"); 83 84 /** @hide */ 85 public static final Uri SHADOW_CONTENT_URI = 86 Uri.parse("content://call_log_shadow/calls"); 87 88 /** 89 * The content:// style URL for filtering this table on phone numbers 90 */ 91 public static final Uri CONTENT_FILTER_URI = 92 Uri.parse("content://call_log/calls/filter"); 93 94 /** 95 * Query parameter used to limit the number of call logs returned. 96 * <p> 97 * TYPE: integer 98 */ 99 public static final String LIMIT_PARAM_KEY = "limit"; 100 101 /** 102 * Query parameter used to specify the starting record to return. 103 * <p> 104 * TYPE: integer 105 */ 106 public static final String OFFSET_PARAM_KEY = "offset"; 107 108 /** 109 * An optional URI parameter which instructs the provider to allow the operation to be 110 * applied to voicemail records as well. 111 * <p> 112 * TYPE: Boolean 113 * <p> 114 * Using this parameter with a value of {@code true} will result in a security error if the 115 * calling package does not have appropriate permissions to access voicemails. 116 * 117 * @hide 118 */ 119 public static final String ALLOW_VOICEMAILS_PARAM_KEY = "allow_voicemails"; 120 121 /** 122 * An optional extra used with {@link #CONTENT_TYPE Calls.CONTENT_TYPE} and 123 * {@link Intent#ACTION_VIEW} to specify that the presented list of calls should be 124 * filtered for a particular call type. 125 * 126 * Applications implementing a call log UI should check for this extra, and display a 127 * filtered list of calls based on the specified call type. If not applicable within the 128 * application's UI, it should be silently ignored. 129 * 130 * <p> 131 * The following example brings up the call log, showing only missed calls. 132 * <pre> 133 * Intent intent = new Intent(Intent.ACTION_VIEW); 134 * intent.setType(CallLog.Calls.CONTENT_TYPE); 135 * intent.putExtra(CallLog.Calls.EXTRA_CALL_TYPE_FILTER, CallLog.Calls.MISSED_TYPE); 136 * startActivity(intent); 137 * </pre> 138 * </p> 139 */ 140 public static final String EXTRA_CALL_TYPE_FILTER = 141 "android.provider.extra.CALL_TYPE_FILTER"; 142 143 /** 144 * Content uri used to access call log entries, including voicemail records. You must have 145 * the READ_CALL_LOG and WRITE_CALL_LOG permissions to read and write to the call log, as 146 * well as READ_VOICEMAIL and WRITE_VOICEMAIL permissions to read and write voicemails. 147 */ 148 public static final Uri CONTENT_URI_WITH_VOICEMAIL = CONTENT_URI.buildUpon() 149 .appendQueryParameter(ALLOW_VOICEMAILS_PARAM_KEY, "true") 150 .build(); 151 152 /** 153 * The default sort order for this table 154 */ 155 public static final String DEFAULT_SORT_ORDER = "date DESC"; 156 157 /** 158 * The MIME type of {@link #CONTENT_URI} and {@link #CONTENT_FILTER_URI} 159 * providing a directory of calls. 160 */ 161 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/calls"; 162 163 /** 164 * The MIME type of a {@link #CONTENT_URI} sub-directory of a single 165 * call. 166 */ 167 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/calls"; 168 169 /** 170 * The type of the call (incoming, outgoing or missed). 171 * <P>Type: INTEGER (int)</P> 172 * 173 * <p> 174 * Allowed values: 175 * <ul> 176 * <li>{@link #INCOMING_TYPE}</li> 177 * <li>{@link #OUTGOING_TYPE}</li> 178 * <li>{@link #MISSED_TYPE}</li> 179 * <li>{@link #VOICEMAIL_TYPE}</li> 180 * <li>{@link #REJECTED_TYPE}</li> 181 * <li>{@link #BLOCKED_TYPE}</li> 182 * <li>{@link #ANSWERED_EXTERNALLY_TYPE}</li> 183 * </ul> 184 * </p> 185 */ 186 public static final String TYPE = "type"; 187 188 /** Call log type for incoming calls. */ 189 public static final int INCOMING_TYPE = 1; 190 /** Call log type for outgoing calls. */ 191 public static final int OUTGOING_TYPE = 2; 192 /** Call log type for missed calls. */ 193 public static final int MISSED_TYPE = 3; 194 /** Call log type for voicemails. */ 195 public static final int VOICEMAIL_TYPE = 4; 196 /** Call log type for calls rejected by direct user action. */ 197 public static final int REJECTED_TYPE = 5; 198 /** Call log type for calls blocked automatically. */ 199 public static final int BLOCKED_TYPE = 6; 200 /** 201 * Call log type for a call which was answered on another device. Used in situations where 202 * a call rings on multiple devices simultaneously and it ended up being answered on a 203 * device other than the current one. 204 */ 205 public static final int ANSWERED_EXTERNALLY_TYPE = 7; 206 207 /** 208 * Bit-mask describing features of the call (e.g. video). 209 * 210 * <P>Type: INTEGER (int)</P> 211 */ 212 public static final String FEATURES = "features"; 213 214 /** Call had video. */ 215 public static final int FEATURES_VIDEO = 1 << 0; 216 217 /** Call was pulled externally. */ 218 public static final int FEATURES_PULLED_EXTERNALLY = 1 << 1; 219 220 /** Call was HD. */ 221 public static final int FEATURES_HD_CALL = 1 << 2; 222 223 /** Call was WIFI call. */ 224 public static final int FEATURES_WIFI = 1 << 3; 225 226 /** 227 * Indicates the call underwent Assisted Dialing. 228 * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING 229 */ 230 public static final int FEATURES_ASSISTED_DIALING_USED = 1 << 4; 231 232 /** Call was on RTT at some point */ 233 public static final int FEATURES_RTT = 1 << 5; 234 235 /** Call was VoLTE */ 236 public static final int FEATURES_VOLTE = 1 << 6; 237 238 /** 239 * The phone number as the user entered it. 240 * <P>Type: TEXT</P> 241 */ 242 public static final String NUMBER = "number"; 243 244 /** 245 * The number presenting rules set by the network. 246 * 247 * <p> 248 * Allowed values: 249 * <ul> 250 * <li>{@link #PRESENTATION_ALLOWED}</li> 251 * <li>{@link #PRESENTATION_RESTRICTED}</li> 252 * <li>{@link #PRESENTATION_UNKNOWN}</li> 253 * <li>{@link #PRESENTATION_PAYPHONE}</li> 254 * </ul> 255 * </p> 256 * 257 * <P>Type: INTEGER</P> 258 */ 259 public static final String NUMBER_PRESENTATION = "presentation"; 260 261 /** Number is allowed to display for caller id. */ 262 public static final int PRESENTATION_ALLOWED = 1; 263 /** Number is blocked by user. */ 264 public static final int PRESENTATION_RESTRICTED = 2; 265 /** Number is not specified or unknown by network. */ 266 public static final int PRESENTATION_UNKNOWN = 3; 267 /** Number is a pay phone. */ 268 public static final int PRESENTATION_PAYPHONE = 4; 269 270 /** 271 * The ISO 3166-1 two letters country code of the country where the 272 * user received or made the call. 273 * <P> 274 * Type: TEXT 275 * </P> 276 */ 277 public static final String COUNTRY_ISO = "countryiso"; 278 279 /** 280 * The date the call occured, in milliseconds since the epoch 281 * <P>Type: INTEGER (long)</P> 282 */ 283 public static final String DATE = "date"; 284 285 /** 286 * The duration of the call in seconds 287 * <P>Type: INTEGER (long)</P> 288 */ 289 public static final String DURATION = "duration"; 290 291 /** 292 * The data usage of the call in bytes. 293 * <P>Type: INTEGER (long)</P> 294 */ 295 public static final String DATA_USAGE = "data_usage"; 296 297 /** 298 * Whether or not the call has been acknowledged 299 * <P>Type: INTEGER (boolean)</P> 300 */ 301 public static final String NEW = "new"; 302 303 /** 304 * The cached name associated with the phone number, if it exists. 305 * 306 * <p>This value is typically filled in by the dialer app for the caching purpose, 307 * so it's not guaranteed to be present, and may not be current if the contact 308 * information associated with this number has changed. 309 * <P>Type: TEXT</P> 310 */ 311 public static final String CACHED_NAME = "name"; 312 313 /** 314 * The cached number type (Home, Work, etc) associated with the 315 * phone number, if it exists. 316 * 317 * <p>This value is typically filled in by the dialer app for the caching purpose, 318 * so it's not guaranteed to be present, and may not be current if the contact 319 * information associated with this number has changed. 320 * <P>Type: INTEGER</P> 321 */ 322 public static final String CACHED_NUMBER_TYPE = "numbertype"; 323 324 /** 325 * The cached number label, for a custom number type, associated with the 326 * phone number, if it exists. 327 * 328 * <p>This value is typically filled in by the dialer app for the caching purpose, 329 * so it's not guaranteed to be present, and may not be current if the contact 330 * information associated with this number has changed. 331 * <P>Type: TEXT</P> 332 */ 333 public static final String CACHED_NUMBER_LABEL = "numberlabel"; 334 335 /** 336 * URI of the voicemail entry. Populated only for {@link #VOICEMAIL_TYPE}. 337 * <P>Type: TEXT</P> 338 */ 339 public static final String VOICEMAIL_URI = "voicemail_uri"; 340 341 /** 342 * Transcription of the call or voicemail entry. This will only be populated for call log 343 * entries of type {@link #VOICEMAIL_TYPE} that have valid transcriptions. 344 */ 345 public static final String TRANSCRIPTION = "transcription"; 346 347 /** 348 * State of voicemail transcription entry. This will only be populated for call log 349 * entries of type {@link #VOICEMAIL_TYPE}. 350 * @hide 351 */ 352 public static final String TRANSCRIPTION_STATE = "transcription_state"; 353 354 /** 355 * Whether this item has been read or otherwise consumed by the user. 356 * <p> 357 * Unlike the {@link #NEW} field, which requires the user to have acknowledged the 358 * existence of the entry, this implies the user has interacted with the entry. 359 * <P>Type: INTEGER (boolean)</P> 360 */ 361 public static final String IS_READ = "is_read"; 362 363 /** 364 * A geocoded location for the number associated with this call. 365 * <p> 366 * The string represents a city, state, or country associated with the number. 367 * <P>Type: TEXT</P> 368 */ 369 public static final String GEOCODED_LOCATION = "geocoded_location"; 370 371 /** 372 * The cached URI to look up the contact associated with the phone number, if it exists. 373 * 374 * <p>This value is typically filled in by the dialer app for the caching purpose, 375 * so it's not guaranteed to be present, and may not be current if the contact 376 * information associated with this number has changed. 377 * <P>Type: TEXT</P> 378 */ 379 public static final String CACHED_LOOKUP_URI = "lookup_uri"; 380 381 /** 382 * The cached phone number of the contact which matches this entry, if it exists. 383 * 384 * <p>This value is typically filled in by the dialer app for the caching purpose, 385 * so it's not guaranteed to be present, and may not be current if the contact 386 * information associated with this number has changed. 387 * <P>Type: TEXT</P> 388 */ 389 public static final String CACHED_MATCHED_NUMBER = "matched_number"; 390 391 /** 392 * The cached normalized(E164) version of the phone number, if it exists. 393 * 394 * <p>This value is typically filled in by the dialer app for the caching purpose, 395 * so it's not guaranteed to be present, and may not be current if the contact 396 * information associated with this number has changed. 397 * <P>Type: TEXT</P> 398 */ 399 public static final String CACHED_NORMALIZED_NUMBER = "normalized_number"; 400 401 /** 402 * The cached photo id of the picture associated with the phone number, if it exists. 403 * 404 * <p>This value is typically filled in by the dialer app for the caching purpose, 405 * so it's not guaranteed to be present, and may not be current if the contact 406 * information associated with this number has changed. 407 * <P>Type: INTEGER (long)</P> 408 */ 409 public static final String CACHED_PHOTO_ID = "photo_id"; 410 411 /** 412 * The cached photo URI of the picture associated with the phone number, if it exists. 413 * 414 * <p>This value is typically filled in by the dialer app for the caching purpose, 415 * so it's not guaranteed to be present, and may not be current if the contact 416 * information associated with this number has changed. 417 * <P>Type: TEXT (URI)</P> 418 */ 419 public static final String CACHED_PHOTO_URI = "photo_uri"; 420 421 /** 422 * The cached phone number, formatted with formatting rules based on the country the 423 * user was in when the call was made or received. 424 * 425 * <p>This value is typically filled in by the dialer app for the caching purpose, 426 * so it's not guaranteed to be present, and may not be current if the contact 427 * information associated with this number has changed. 428 * <P>Type: TEXT</P> 429 */ 430 public static final String CACHED_FORMATTED_NUMBER = "formatted_number"; 431 432 // Note: PHONE_ACCOUNT_* constant values are "subscription_*" due to a historic naming 433 // that was encoded into call log databases. 434 435 /** 436 * The component name of the account used to place or receive the call; in string form. 437 * <P>Type: TEXT</P> 438 */ 439 public static final String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name"; 440 441 /** 442 * The identifier for the account used to place or receive the call. 443 * <P>Type: TEXT</P> 444 */ 445 public static final String PHONE_ACCOUNT_ID = "subscription_id"; 446 447 /** 448 * The address associated with the account used to place or receive the call; in string 449 * form. For SIM-based calls, this is the user's own phone number. 450 * <P>Type: TEXT</P> 451 * 452 * @hide 453 */ 454 public static final String PHONE_ACCOUNT_ADDRESS = "phone_account_address"; 455 456 /** 457 * Indicates that the entry will be hidden from all queries until the associated 458 * {@link android.telecom.PhoneAccount} is registered with the system. 459 * <P>Type: INTEGER</P> 460 * 461 * @hide 462 */ 463 public static final String PHONE_ACCOUNT_HIDDEN = "phone_account_hidden"; 464 465 /** 466 * The subscription ID used to place this call. This is no longer used and has been 467 * replaced with PHONE_ACCOUNT_COMPONENT_NAME/PHONE_ACCOUNT_ID. 468 * For ContactsProvider internal use only. 469 * <P>Type: INTEGER</P> 470 * 471 * @Deprecated 472 * @hide 473 */ 474 public static final String SUB_ID = "sub_id"; 475 476 /** 477 * The post-dial portion of a dialed number, including any digits dialed after a 478 * {@link TelecomManager#DTMF_CHARACTER_PAUSE} or a {@link 479 * TelecomManager#DTMF_CHARACTER_WAIT} and these characters themselves. 480 * <P>Type: TEXT</P> 481 */ 482 public static final String POST_DIAL_DIGITS = "post_dial_digits"; 483 484 /** 485 * For an incoming call, the secondary line number the call was received via. 486 * When a SIM card has multiple phone numbers associated with it, the via number indicates 487 * which of the numbers associated with the SIM was called. 488 */ 489 public static final String VIA_NUMBER = "via_number"; 490 491 /** 492 * Indicates that the entry will be copied from primary user to other users. 493 * <P>Type: INTEGER</P> 494 * 495 * @hide 496 */ 497 public static final String ADD_FOR_ALL_USERS = "add_for_all_users"; 498 499 /** 500 * The date the row is last inserted, updated, or marked as deleted, in milliseconds 501 * since the epoch. Read only. 502 * <P>Type: INTEGER (long)</P> 503 */ 504 public static final String LAST_MODIFIED = "last_modified"; 505 506 /** 507 * If a successful call is made that is longer than this duration, update the phone number 508 * in the ContactsProvider with the normalized version of the number, based on the user's 509 * current country code. 510 */ 511 private static final int MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS = 1000 * 10; 512 513 /** 514 * Value for {@link CallLog.Calls#BLOCK_REASON}, set as the default value when a call was 515 * not blocked by a CallScreeningService or any other system call blocking method. 516 */ 517 public static final int BLOCK_REASON_NOT_BLOCKED = 0; 518 519 /** 520 * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is 521 * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked by a 522 * CallScreeningService. The {@link CallLog.Calls#CALL_SCREENING_COMPONENT_NAME} and 523 * {@link CallLog.Calls#CALL_SCREENING_APP_NAME} columns will indicate which call screening 524 * service was responsible for blocking the call. 525 */ 526 public static final int BLOCK_REASON_CALL_SCREENING_SERVICE = 1; 527 528 /** 529 * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is 530 * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user 531 * configured a contact to be sent directly to voicemail. 532 */ 533 public static final int BLOCK_REASON_DIRECT_TO_VOICEMAIL = 2; 534 535 /** 536 * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is 537 * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because it is 538 * in the BlockedNumbers provider. 539 */ 540 public static final int BLOCK_REASON_BLOCKED_NUMBER = 3; 541 542 /** 543 * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is 544 * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user 545 * has chosen to block all calls from unknown numbers. 546 */ 547 public static final int BLOCK_REASON_UNKNOWN_NUMBER = 4; 548 549 /** 550 * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is 551 * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user 552 * has chosen to block all calls from restricted numbers. 553 */ 554 public static final int BLOCK_REASON_RESTRICTED_NUMBER = 5; 555 556 /** 557 * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is 558 * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user 559 * has chosen to block all calls from pay phones. 560 */ 561 public static final int BLOCK_REASON_PAY_PHONE = 6; 562 563 /** 564 * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is 565 * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user 566 * has chosen to block all calls from numbers not in their contacts. 567 */ 568 public static final int BLOCK_REASON_NOT_IN_CONTACTS = 7; 569 570 /** 571 * The ComponentName of the CallScreeningService which blocked this call. Will be 572 * populated when the {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE}. 573 * <P>Type: TEXT</P> 574 */ 575 public static final String CALL_SCREENING_COMPONENT_NAME = "call_screening_component_name"; 576 577 /** 578 * The name of the app which blocked a call. Will be populated when the 579 * {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE}. Provided as a 580 * convenience so that the call log can still indicate which app blocked a call, even if 581 * that app is no longer installed. 582 * <P>Type: TEXT</P> 583 */ 584 public static final String CALL_SCREENING_APP_NAME = "call_screening_app_name"; 585 586 /** 587 * Where the {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE}, 588 * indicates the reason why a call is blocked. 589 * <P>Type: INTEGER</P> 590 * 591 * <p> 592 * Allowed values: 593 * <ul> 594 * <li>{@link CallLog.Calls#BLOCK_REASON_NOT_BLOCKED}</li> 595 * <li>{@link CallLog.Calls#BLOCK_REASON_CALL_SCREENING_SERVICE}</li> 596 * <li>{@link CallLog.Calls#BLOCK_REASON_DIRECT_TO_VOICEMAIL}</li> 597 * <li>{@link CallLog.Calls#BLOCK_REASON_BLOCKED_NUMBER}</li> 598 * <li>{@link CallLog.Calls#BLOCK_REASON_UNKNOWN_NUMBER}</li> 599 * <li>{@link CallLog.Calls#BLOCK_REASON_RESTRICTED_NUMBER}</li> 600 * <li>{@link CallLog.Calls#BLOCK_REASON_PAY_PHONE}</li> 601 * <li>{@link CallLog.Calls#BLOCK_REASON_NOT_IN_CONTACTS}</li> 602 * </ul> 603 * </p> 604 */ 605 public static final String BLOCK_REASON = "block_reason"; 606 607 /** 608 * Adds a call to the call log. 609 * 610 * @param ci the CallerInfo object to get the target contact from. Can be null 611 * if the contact is unknown. 612 * @param context the context used to get the ContentResolver 613 * @param number the phone number to be added to the calls db 614 * @param presentation enum value from TelecomManager.PRESENTATION_xxx, which 615 * is set by the network and denotes the number presenting rules for 616 * "allowed", "payphone", "restricted" or "unknown" 617 * @param callType enumerated values for "incoming", "outgoing", or "missed" 618 * @param features features of the call (e.g. Video). 619 * @param accountHandle The accountHandle object identifying the provider of the call 620 * @param start time stamp for the call in milliseconds 621 * @param duration call duration in seconds 622 * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for 623 * the call. 624 * @result The URI of the call log entry belonging to the user that made or received this 625 * call. 626 * {@hide} 627 */ addCall(CallerInfo ci, Context context, String number, int presentation, int callType, int features, PhoneAccountHandle accountHandle, long start, int duration, Long dataUsage)628 public static Uri addCall(CallerInfo ci, Context context, String number, 629 int presentation, int callType, int features, 630 PhoneAccountHandle accountHandle, 631 long start, int duration, Long dataUsage) { 632 return addCall(ci, context, number, "" /* postDialDigits */, "" /* viaNumber */, 633 presentation, callType, features, accountHandle, start, duration, 634 dataUsage, false /* addForAllUsers */, null /* userToBeInsertedTo */, 635 false /* isRead */, Calls.BLOCK_REASON_NOT_BLOCKED /* callBlockReason */, 636 null /* callScreeningAppName */, null /* callScreeningComponentName */); 637 } 638 639 640 /** 641 * Adds a call to the call log. 642 * 643 * @param ci the CallerInfo object to get the target contact from. Can be null 644 * if the contact is unknown. 645 * @param context the context used to get the ContentResolver 646 * @param number the phone number to be added to the calls db 647 * @param viaNumber the secondary number that the incoming call received with. If the 648 * call was received with the SIM assigned number, then this field must be ''. 649 * @param presentation enum value from TelecomManager.PRESENTATION_xxx, which 650 * is set by the network and denotes the number presenting rules for 651 * "allowed", "payphone", "restricted" or "unknown" 652 * @param callType enumerated values for "incoming", "outgoing", or "missed" 653 * @param features features of the call (e.g. Video). 654 * @param accountHandle The accountHandle object identifying the provider of the call 655 * @param start time stamp for the call in milliseconds 656 * @param duration call duration in seconds 657 * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for 658 * the call. 659 * @param addForAllUsers If true, the call is added to the call log of all currently 660 * running users. The caller must have the MANAGE_USERS permission if this is true. 661 * @param userToBeInsertedTo {@link UserHandle} of user that the call is going to be 662 * inserted to. null if it is inserted to the current user. The 663 * value is ignored if @{link addForAllUsers} is true. 664 * @result The URI of the call log entry belonging to the user that made or received this 665 * call. 666 * {@hide} 667 */ addCall(CallerInfo ci, Context context, String number, String postDialDigits, String viaNumber, int presentation, int callType, int features, PhoneAccountHandle accountHandle, long start, int duration, Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo)668 public static Uri addCall(CallerInfo ci, Context context, String number, 669 String postDialDigits, String viaNumber, int presentation, int callType, 670 int features, PhoneAccountHandle accountHandle, long start, int duration, 671 Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo) { 672 return addCall(ci, context, number, postDialDigits, viaNumber, presentation, callType, 673 features, accountHandle, start, duration, dataUsage, addForAllUsers, 674 userToBeInsertedTo, false /* isRead */ , Calls.BLOCK_REASON_NOT_BLOCKED 675 /* callBlockReason */, null /* callScreeningAppName */, 676 null /* callScreeningComponentName */); 677 } 678 679 /** 680 * Adds a call to the call log. 681 * 682 * @param ci the CallerInfo object to get the target contact from. Can be null 683 * if the contact is unknown. 684 * @param context the context used to get the ContentResolver 685 * @param number the phone number to be added to the calls db 686 * @param postDialDigits the post-dial digits that were dialed after the number, 687 * if it was outgoing. Otherwise it is ''. 688 * @param viaNumber the secondary number that the incoming call received with. If the 689 * call was received with the SIM assigned number, then this field must be ''. 690 * @param presentation enum value from TelecomManager.PRESENTATION_xxx, which 691 * is set by the network and denotes the number presenting rules for 692 * "allowed", "payphone", "restricted" or "unknown" 693 * @param callType enumerated values for "incoming", "outgoing", or "missed" 694 * @param features features of the call (e.g. Video). 695 * @param accountHandle The accountHandle object identifying the provider of the call 696 * @param start time stamp for the call in milliseconds 697 * @param duration call duration in seconds 698 * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for 699 * the call. 700 * @param addForAllUsers If true, the call is added to the call log of all currently 701 * running users. The caller must have the MANAGE_USERS permission if this is true. 702 * @param userToBeInsertedTo {@link UserHandle} of user that the call is going to be 703 * inserted to. null if it is inserted to the current user. The 704 * value is ignored if @{link addForAllUsers} is true. 705 * @param isRead Flag to show if the missed call log has been read by the user or not. 706 * Used for call log restore of missed calls. 707 * @param callBlockReason The reason why the call is blocked. 708 * @param callScreeningAppName The call screening application name which block the call. 709 * @param callScreeningComponentName The call screening component name which block the call. 710 * 711 * @result The URI of the call log entry belonging to the user that made or received this 712 * call. This could be of the shadow provider. Do not return it to non-system apps, 713 * as they don't have permissions. 714 * {@hide} 715 */ 716 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) addCall(CallerInfo ci, Context context, String number, String postDialDigits, String viaNumber, int presentation, int callType, int features, PhoneAccountHandle accountHandle, long start, int duration, Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo, boolean isRead, int callBlockReason, CharSequence callScreeningAppName, String callScreeningComponentName)717 public static Uri addCall(CallerInfo ci, Context context, String number, 718 String postDialDigits, String viaNumber, int presentation, int callType, 719 int features, PhoneAccountHandle accountHandle, long start, int duration, 720 Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo, 721 boolean isRead, int callBlockReason, CharSequence callScreeningAppName, 722 String callScreeningComponentName) { 723 if (VERBOSE_LOG) { 724 Log.v(LOG_TAG, String.format("Add call: number=%s, user=%s, for all=%s", 725 number, userToBeInsertedTo, addForAllUsers)); 726 } 727 final ContentResolver resolver = context.getContentResolver(); 728 729 String accountAddress = getLogAccountAddress(context, accountHandle); 730 731 int numberPresentation = getLogNumberPresentation(number, presentation); 732 String name = (ci != null) ? ci.getName() : ""; 733 if (numberPresentation != PRESENTATION_ALLOWED) { 734 number = ""; 735 if (ci != null) { 736 name = ""; 737 } 738 } 739 740 // accountHandle information 741 String accountComponentString = null; 742 String accountId = null; 743 if (accountHandle != null) { 744 accountComponentString = accountHandle.getComponentName().flattenToString(); 745 accountId = accountHandle.getId(); 746 } 747 748 ContentValues values = new ContentValues(6); 749 750 values.put(NUMBER, number); 751 values.put(POST_DIAL_DIGITS, postDialDigits); 752 values.put(VIA_NUMBER, viaNumber); 753 values.put(NUMBER_PRESENTATION, Integer.valueOf(numberPresentation)); 754 values.put(TYPE, Integer.valueOf(callType)); 755 values.put(FEATURES, features); 756 values.put(DATE, Long.valueOf(start)); 757 values.put(DURATION, Long.valueOf(duration)); 758 if (dataUsage != null) { 759 values.put(DATA_USAGE, dataUsage); 760 } 761 values.put(PHONE_ACCOUNT_COMPONENT_NAME, accountComponentString); 762 values.put(PHONE_ACCOUNT_ID, accountId); 763 values.put(PHONE_ACCOUNT_ADDRESS, accountAddress); 764 values.put(NEW, Integer.valueOf(1)); 765 values.put(CACHED_NAME, name); 766 values.put(ADD_FOR_ALL_USERS, addForAllUsers ? 1 : 0); 767 768 if (callType == MISSED_TYPE) { 769 values.put(IS_READ, Integer.valueOf(isRead ? 1 : 0)); 770 } 771 772 values.put(BLOCK_REASON, callBlockReason); 773 values.put(CALL_SCREENING_APP_NAME, charSequenceToString(callScreeningAppName)); 774 values.put(CALL_SCREENING_COMPONENT_NAME, callScreeningComponentName); 775 776 if ((ci != null) && (ci.getContactId() > 0)) { 777 // Update usage information for the number associated with the contact ID. 778 // We need to use both the number and the ID for obtaining a data ID since other 779 // contacts may have the same number. 780 781 final Cursor cursor; 782 783 // We should prefer normalized one (probably coming from 784 // Phone.NORMALIZED_NUMBER column) first. If it isn't available try others. 785 if (ci.normalizedNumber != null) { 786 final String normalizedPhoneNumber = ci.normalizedNumber; 787 cursor = resolver.query(Phone.CONTENT_URI, 788 new String[] { Phone._ID }, 789 Phone.CONTACT_ID + " =? AND " + Phone.NORMALIZED_NUMBER + " =?", 790 new String[] { String.valueOf(ci.getContactId()), 791 normalizedPhoneNumber}, 792 null); 793 } else { 794 final String phoneNumber = ci.getPhoneNumber() != null 795 ? ci.getPhoneNumber() : number; 796 cursor = resolver.query( 797 Uri.withAppendedPath(Callable.CONTENT_FILTER_URI, 798 Uri.encode(phoneNumber)), 799 new String[] { Phone._ID }, 800 Phone.CONTACT_ID + " =?", 801 new String[] { String.valueOf(ci.getContactId()) }, 802 null); 803 } 804 805 if (cursor != null) { 806 try { 807 if (cursor.getCount() > 0 && cursor.moveToFirst()) { 808 final String dataId = cursor.getString(0); 809 updateDataUsageStatForData(resolver, dataId); 810 if (duration >= MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS 811 && callType == Calls.OUTGOING_TYPE 812 && TextUtils.isEmpty(ci.normalizedNumber)) { 813 updateNormalizedNumber(context, resolver, dataId, number); 814 } 815 } 816 } finally { 817 cursor.close(); 818 } 819 } 820 } 821 822 /* 823 Writing the calllog works in the following way: 824 - All user entries 825 - if user-0 is encrypted, insert to user-0's shadow only. 826 (other users should also be encrypted, so nothing to do for other users.) 827 - if user-0 is decrypted, insert to user-0's real provider, as well as 828 all other users that are running and decrypted and should have calllog. 829 830 - Single user entry. 831 - If the target user is encryted, insert to its shadow. 832 - Otherwise insert to its real provider. 833 834 When the (real) calllog provider starts, it copies entries that it missed from 835 elsewhere. 836 - When user-0's (real) provider starts, it copies from user-0's shadow, and clears 837 the shadow. 838 839 - When other users (real) providers start, unless it shouldn't have calllog entries, 840 - Copy from the user's shadow, and clears the shadow. 841 - Copy from user-0's entries that are FOR_ALL_USERS = 1. (and don't clear it.) 842 */ 843 844 Uri result = null; 845 846 final UserManager userManager = context.getSystemService(UserManager.class); 847 final int currentUserId = userManager.getUserHandle(); 848 849 if (addForAllUsers) { 850 // First, insert to the system user. 851 final Uri uriForSystem = addEntryAndRemoveExpiredEntries( 852 context, userManager, UserHandle.SYSTEM, values); 853 if (uriForSystem == null 854 || SHADOW_AUTHORITY.equals(uriForSystem.getAuthority())) { 855 // This means the system user is still encrypted and the entry has inserted 856 // into the shadow. This means other users are still all encrypted. 857 // Nothing further to do; just return null. 858 return null; 859 } 860 if (UserHandle.USER_SYSTEM == currentUserId) { 861 result = uriForSystem; 862 } 863 864 // Otherwise, insert to all other users that are running and unlocked. 865 866 final List<UserInfo> users = userManager.getUsers(true); 867 868 final int count = users.size(); 869 for (int i = 0; i < count; i++) { 870 final UserInfo userInfo = users.get(i); 871 final UserHandle userHandle = userInfo.getUserHandle(); 872 final int userId = userHandle.getIdentifier(); 873 874 if (userHandle.isSystem()) { 875 // Already written. 876 continue; 877 } 878 879 if (!shouldHaveSharedCallLogEntries(context, userManager, userId)) { 880 // Shouldn't have calllog entries. 881 continue; 882 } 883 884 // For other users, we write only when they're running *and* decrypted. 885 // Other providers will copy from the system user's real provider, when they 886 // start. 887 if (userManager.isUserRunning(userHandle) 888 && userManager.isUserUnlocked(userHandle)) { 889 final Uri uri = addEntryAndRemoveExpiredEntries(context, userManager, 890 userHandle, values); 891 if (userId == currentUserId) { 892 result = uri; 893 } 894 } 895 } 896 } else { 897 // Single-user entry. Just write to that user, assuming it's running. If the 898 // user is encrypted, we write to the shadow calllog. 899 900 final UserHandle targetUserHandle = userToBeInsertedTo != null 901 ? userToBeInsertedTo 902 : UserHandle.of(currentUserId); 903 result = addEntryAndRemoveExpiredEntries(context, userManager, targetUserHandle, 904 values); 905 } 906 return result; 907 } 908 charSequenceToString(CharSequence sequence)909 private static String charSequenceToString(CharSequence sequence) { 910 return sequence == null ? null : sequence.toString(); 911 } 912 913 /** @hide */ shouldHaveSharedCallLogEntries(Context context, UserManager userManager, int userId)914 public static boolean shouldHaveSharedCallLogEntries(Context context, 915 UserManager userManager, int userId) { 916 if (userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, 917 UserHandle.of(userId))) { 918 return false; 919 } 920 final UserInfo userInfo = userManager.getUserInfo(userId); 921 return userInfo != null && !userInfo.isManagedProfile(); 922 } 923 924 /** 925 * Query the call log database for the last dialed number. 926 * @param context Used to get the content resolver. 927 * @return The last phone number dialed (outgoing) or an empty 928 * string if none exist yet. 929 */ getLastOutgoingCall(Context context)930 public static String getLastOutgoingCall(Context context) { 931 final ContentResolver resolver = context.getContentResolver(); 932 Cursor c = null; 933 try { 934 c = resolver.query( 935 CONTENT_URI, 936 new String[] {NUMBER}, 937 TYPE + " = " + OUTGOING_TYPE, 938 null, 939 DEFAULT_SORT_ORDER + " LIMIT 1"); 940 if (c == null || !c.moveToFirst()) { 941 return ""; 942 } 943 return c.getString(0); 944 } finally { 945 if (c != null) c.close(); 946 } 947 } 948 addEntryAndRemoveExpiredEntries(Context context, UserManager userManager, UserHandle user, ContentValues values)949 private static Uri addEntryAndRemoveExpiredEntries(Context context, UserManager userManager, 950 UserHandle user, ContentValues values) { 951 final ContentResolver resolver = context.getContentResolver(); 952 953 // Since we're doing this operation on behalf of an app, we only 954 // want to use the actual "unlocked" state. 955 final Uri uri = ContentProvider.maybeAddUserId( 956 userManager.isUserUnlocked(user) ? CONTENT_URI : SHADOW_CONTENT_URI, 957 user.getIdentifier()); 958 959 if (VERBOSE_LOG) { 960 Log.v(LOG_TAG, String.format("Inserting to %s", uri)); 961 } 962 963 try { 964 // When cleaning up the call log, try to delete older call long entries on a per 965 // PhoneAccount basis first. There can be multiple ConnectionServices causing 966 // the addition of entries in the call log. With the introduction of Self-Managed 967 // ConnectionServices, we want to ensure that a misbehaving self-managed CS cannot 968 // spam the call log with its own entries, causing entries from Telephony to be 969 // removed. 970 final Uri result = resolver.insert(uri, values); 971 if (result != null) { 972 String lastPathSegment = result.getLastPathSegment(); 973 // When inserting into the call log, if ContentProvider#insert detect an appops 974 // denial a non-null "silent rejection" URI is returned which ends in 0. 975 // Example: content://call_log/calls/0 976 // The 0 in the last part of the path indicates a fake call id of 0. 977 // A denial when logging calls from the platform is bad; there is no other 978 // logging to indicate that this has happened so we will check for that scenario 979 // here and log a warning so we have a hint as to what is going on. 980 if (lastPathSegment != null && lastPathSegment.equals("0")) { 981 Log.w(LOG_TAG, "Failed to insert into call log due to appops denial;" 982 + " resultUri=" + result); 983 } 984 } else { 985 Log.w(LOG_TAG, "Failed to insert into call log; null result uri."); 986 } 987 988 if (values.containsKey(PHONE_ACCOUNT_ID) 989 && !TextUtils.isEmpty(values.getAsString(PHONE_ACCOUNT_ID)) 990 && values.containsKey(PHONE_ACCOUNT_COMPONENT_NAME) 991 && !TextUtils.isEmpty(values.getAsString(PHONE_ACCOUNT_COMPONENT_NAME))) { 992 // Only purge entries for the same phone account. 993 resolver.delete(uri, "_id IN " + 994 "(SELECT _id FROM calls" 995 + " WHERE " + PHONE_ACCOUNT_COMPONENT_NAME + " = ?" 996 + " AND " + PHONE_ACCOUNT_ID + " = ?" 997 + " ORDER BY " + DEFAULT_SORT_ORDER 998 + " LIMIT -1 OFFSET 500)", new String[] { 999 values.getAsString(PHONE_ACCOUNT_COMPONENT_NAME), 1000 values.getAsString(PHONE_ACCOUNT_ID) 1001 }); 1002 } else { 1003 // No valid phone account specified, so default to the old behavior. 1004 resolver.delete(uri, "_id IN " + 1005 "(SELECT _id FROM calls ORDER BY " + DEFAULT_SORT_ORDER 1006 + " LIMIT -1 OFFSET 500)", null); 1007 } 1008 1009 return result; 1010 } catch (IllegalArgumentException e) { 1011 Log.w(LOG_TAG, "Failed to insert calllog", e); 1012 // Even though we make sure the target user is running and decrypted before calling 1013 // this method, there's a chance that the user just got shut down, in which case 1014 // we'll still get "IllegalArgumentException: Unknown URL content://call_log/calls". 1015 return null; 1016 } 1017 } 1018 updateDataUsageStatForData(ContentResolver resolver, String dataId)1019 private static void updateDataUsageStatForData(ContentResolver resolver, String dataId) { 1020 final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() 1021 .appendPath(dataId) 1022 .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, 1023 DataUsageFeedback.USAGE_TYPE_CALL) 1024 .build(); 1025 resolver.update(feedbackUri, new ContentValues(), null, null); 1026 } 1027 1028 /* 1029 * Update the normalized phone number for the given dataId in the ContactsProvider, based 1030 * on the user's current country. 1031 */ updateNormalizedNumber(Context context, ContentResolver resolver, String dataId, String number)1032 private static void updateNormalizedNumber(Context context, ContentResolver resolver, 1033 String dataId, String number) { 1034 if (TextUtils.isEmpty(number) || TextUtils.isEmpty(dataId)) { 1035 return; 1036 } 1037 final String countryIso = getCurrentCountryIso(context); 1038 if (TextUtils.isEmpty(countryIso)) { 1039 return; 1040 } 1041 final String normalizedNumber = PhoneNumberUtils.formatNumberToE164(number, countryIso); 1042 if (TextUtils.isEmpty(normalizedNumber)) { 1043 return; 1044 } 1045 final ContentValues values = new ContentValues(); 1046 values.put(Phone.NORMALIZED_NUMBER, normalizedNumber); 1047 resolver.update(Data.CONTENT_URI, values, Data._ID + "=?", new String[] {dataId}); 1048 } 1049 1050 /** 1051 * Remap network specified number presentation types 1052 * TelecomManager.PRESENTATION_xxx to calllog number presentation types 1053 * Calls.PRESENTATION_xxx, in order to insulate the persistent calllog 1054 * from any future radio changes. 1055 * If the number field is empty set the presentation type to Unknown. 1056 */ getLogNumberPresentation(String number, int presentation)1057 private static int getLogNumberPresentation(String number, int presentation) { 1058 if (presentation == TelecomManager.PRESENTATION_RESTRICTED) { 1059 return presentation; 1060 } 1061 1062 if (presentation == TelecomManager.PRESENTATION_PAYPHONE) { 1063 return presentation; 1064 } 1065 1066 if (TextUtils.isEmpty(number) 1067 || presentation == TelecomManager.PRESENTATION_UNKNOWN) { 1068 return PRESENTATION_UNKNOWN; 1069 } 1070 1071 return PRESENTATION_ALLOWED; 1072 } 1073 getLogAccountAddress(Context context, PhoneAccountHandle accountHandle)1074 private static String getLogAccountAddress(Context context, 1075 PhoneAccountHandle accountHandle) { 1076 TelecomManager tm = null; 1077 try { 1078 tm = TelecomManager.from(context); 1079 } catch (UnsupportedOperationException e) { 1080 if (VERBOSE_LOG) { 1081 Log.v(LOG_TAG, "No TelecomManager found to get account address."); 1082 } 1083 } 1084 1085 String accountAddress = null; 1086 if (tm != null && accountHandle != null) { 1087 PhoneAccount account = tm.getPhoneAccount(accountHandle); 1088 if (account != null) { 1089 Uri address = account.getSubscriptionAddress(); 1090 if (address != null) { 1091 accountAddress = address.getSchemeSpecificPart(); 1092 } 1093 } 1094 } 1095 return accountAddress; 1096 } 1097 getCurrentCountryIso(Context context)1098 private static String getCurrentCountryIso(Context context) { 1099 String countryIso = null; 1100 final CountryDetector detector = (CountryDetector) context.getSystemService( 1101 Context.COUNTRY_DETECTOR); 1102 if (detector != null) { 1103 final Country country = detector.detectCountry(); 1104 if (country != null) { 1105 countryIso = country.getCountryIso(); 1106 } 1107 } 1108 return countryIso; 1109 } 1110 } 1111 } 1112