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.Manifest; 21 import android.annotation.CallbackExecutor; 22 import android.annotation.FlaggedApi; 23 import android.annotation.IntDef; 24 import android.annotation.LongDef; 25 import android.annotation.NonNull; 26 import android.annotation.RequiresPermission; 27 import android.annotation.SuppressLint; 28 import android.annotation.SystemApi; 29 import android.annotation.UserHandleAware; 30 import android.compat.annotation.UnsupportedAppUsage; 31 import android.content.ComponentName; 32 import android.content.ContentProvider; 33 import android.content.ContentResolver; 34 import android.content.ContentValues; 35 import android.content.Context; 36 import android.content.Intent; 37 import android.content.pm.UserInfo; 38 import android.database.Cursor; 39 import android.location.Country; 40 import android.location.CountryDetector; 41 import android.net.Uri; 42 import android.os.Build; 43 import android.os.OutcomeReceiver; 44 import android.os.ParcelFileDescriptor; 45 import android.os.ParcelableException; 46 import android.os.UserHandle; 47 import android.os.UserManager; 48 import android.provider.ContactsContract.CommonDataKinds.Callable; 49 import android.provider.ContactsContract.CommonDataKinds.Phone; 50 import android.provider.ContactsContract.Data; 51 import android.provider.ContactsContract.DataUsageFeedback; 52 import android.telecom.CallerInfo; 53 import android.telecom.PhoneAccount; 54 import android.telecom.PhoneAccountHandle; 55 import android.telecom.TelecomManager; 56 import android.telephony.PhoneNumberUtils; 57 import android.text.TextUtils; 58 import android.util.Log; 59 60 import com.android.server.telecom.flags.Flags; 61 62 import java.io.ByteArrayOutputStream; 63 import java.io.FileNotFoundException; 64 import java.io.FileOutputStream; 65 import java.io.IOException; 66 import java.io.InputStream; 67 import java.lang.annotation.Retention; 68 import java.lang.annotation.RetentionPolicy; 69 import java.util.List; 70 import java.util.Locale; 71 import java.util.Objects; 72 import java.util.concurrent.Executor; 73 74 /** 75 * The CallLog provider contains information about placed and received calls. 76 */ 77 public class CallLog { 78 private static final String LOG_TAG = "CallLog"; 79 private static final boolean VERBOSE_LOG = false; // DON'T SUBMIT WITH TRUE. 80 81 public static final String AUTHORITY = "call_log"; 82 83 /** 84 * The content:// style URL for this provider 85 */ 86 public static final Uri CONTENT_URI = 87 Uri.parse("content://" + AUTHORITY); 88 89 /** @hide */ 90 public static final String CALL_COMPOSER_SEGMENT = "call_composer"; 91 92 /** @hide */ 93 public static final Uri CALL_COMPOSER_PICTURE_URI = 94 CONTENT_URI.buildUpon().appendPath(CALL_COMPOSER_SEGMENT).build(); 95 96 /** 97 * The "shadow" provider stores calllog when the real calllog provider is encrypted. The 98 * real provider will alter copy from it when it starts, and remove the entries in the shadow. 99 * 100 * <p>See the comment in {@link Calls#addCall} for the details. 101 * 102 * @hide 103 */ 104 public static final String SHADOW_AUTHORITY = "call_log_shadow"; 105 106 /** @hide */ 107 public static final Uri SHADOW_CALL_COMPOSER_PICTURE_URI = CALL_COMPOSER_PICTURE_URI.buildUpon() 108 .authority(SHADOW_AUTHORITY).build(); 109 110 /** 111 * Describes an error encountered while storing a call composer picture in the call log. 112 * @hide 113 */ 114 @SystemApi 115 public static class CallComposerLoggingException extends Throwable { 116 /** 117 * Indicates an unknown error. 118 */ 119 public static final int ERROR_UNKNOWN = 0; 120 121 /** 122 * Indicates that the process hosting the call log died or otherwise encountered an 123 * unrecoverable error while storing the picture. 124 * 125 * The caller should retry if this error is encountered. 126 */ 127 public static final int ERROR_REMOTE_END_CLOSED = 1; 128 129 /** 130 * Indicates that the device has insufficient space to store this picture. 131 * 132 * The caller should not retry if this error is encountered. 133 */ 134 public static final int ERROR_STORAGE_FULL = 2; 135 136 /** 137 * Indicates that the {@link InputStream} passed to {@link #storeCallComposerPicture} 138 * was closed. 139 * 140 * The caller should retry if this error is encountered, and be sure to not close the stream 141 * before the callback is called this time. 142 */ 143 public static final int ERROR_INPUT_CLOSED = 3; 144 145 /** @hide */ 146 @IntDef(prefix = {"ERROR_"}, value = { 147 ERROR_UNKNOWN, 148 ERROR_REMOTE_END_CLOSED, 149 ERROR_STORAGE_FULL, 150 ERROR_INPUT_CLOSED, 151 }) 152 @Retention(RetentionPolicy.SOURCE) 153 public @interface CallComposerLoggingError { } 154 155 private final int mErrorCode; 156 CallComposerLoggingException(@allComposerLoggingError int errorCode)157 public CallComposerLoggingException(@CallComposerLoggingError int errorCode) { 158 mErrorCode = errorCode; 159 } 160 161 /** 162 * @return The error code for this exception. 163 */ getErrorCode()164 public @CallComposerLoggingError int getErrorCode() { 165 return mErrorCode; 166 } 167 168 @Override toString()169 public String toString() { 170 String errorString; 171 switch (mErrorCode) { 172 case ERROR_UNKNOWN: 173 errorString = "UNKNOWN"; 174 break; 175 case ERROR_REMOTE_END_CLOSED: 176 errorString = "REMOTE_END_CLOSED"; 177 break; 178 case ERROR_STORAGE_FULL: 179 errorString = "STORAGE_FULL"; 180 break; 181 case ERROR_INPUT_CLOSED: 182 errorString = "INPUT_CLOSED"; 183 break; 184 default: 185 errorString = "[[" + mErrorCode + "]]"; 186 break; 187 } 188 return "CallComposerLoggingException: " + errorString; 189 } 190 } 191 192 /** 193 * Supplies a call composer picture to the call log for persistent storage. 194 * 195 * This method is used by Telephony to store pictures selected by the user or sent from the 196 * remote party as part of a voice call with call composer. The {@link Uri} supplied in the 197 * callback can be used to retrieve the image via {@link ContentResolver#openFile} or stored in 198 * the {@link Calls} table in the {@link Calls#COMPOSER_PHOTO_URI} column. 199 * 200 * The caller is responsible for closing the {@link InputStream} after the callback indicating 201 * success or failure. 202 * 203 * @param context An instance of {@link Context}. The picture will be stored to the user 204 * corresponding to {@link Context#getUser()}. 205 * @param input An input stream from which the picture to store should be read. The input data 206 * must be decodeable as either a JPEG, PNG, or GIF image. 207 * @param executor The {@link Executor} on which to perform the file transfer operation and 208 * call the supplied callback. 209 * @param callback Callback that's called after the picture is successfully stored or when an 210 * error occurs. 211 * @hide 212 */ 213 @SystemApi 214 @UserHandleAware 215 @RequiresPermission(allOf = { 216 Manifest.permission.WRITE_CALL_LOG, 217 Manifest.permission.INTERACT_ACROSS_USERS 218 }) storeCallComposerPicture(@onNull Context context, @NonNull InputStream input, @CallbackExecutor @NonNull Executor executor, @NonNull OutcomeReceiver<Uri, CallComposerLoggingException> callback)219 public static void storeCallComposerPicture(@NonNull Context context, 220 @NonNull InputStream input, 221 @CallbackExecutor @NonNull Executor executor, 222 @NonNull OutcomeReceiver<Uri, CallComposerLoggingException> callback) { 223 Objects.requireNonNull(context); 224 Objects.requireNonNull(input); 225 Objects.requireNonNull(executor); 226 Objects.requireNonNull(callback); 227 228 executor.execute(() -> { 229 ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(); 230 231 // Read the entire input into memory first in case we have to write multiple times and 232 // the input isn't resettable. 233 byte[] buffer = new byte[1024]; 234 int bytesRead; 235 while (true) { 236 try { 237 bytesRead = input.read(buffer); 238 } catch (IOException e) { 239 Log.e(LOG_TAG, "IOException while reading call composer pic from input: " 240 + e); 241 callback.onError(new CallComposerLoggingException( 242 CallComposerLoggingException.ERROR_INPUT_CLOSED)); 243 return; 244 } 245 if (bytesRead < 0) { 246 break; 247 } 248 tmpOut.write(buffer, 0, bytesRead); 249 } 250 byte[] picData = tmpOut.toByteArray(); 251 252 UserManager userManager = context.getSystemService(UserManager.class); 253 UserHandle user = context.getUser(); 254 // Nasty casework for the shadow calllog begins... 255 // First see if we're just inserting for one user. If so, insert into the shadow 256 // based on whether that user is unlocked. 257 UserHandle realUser = UserHandle.CURRENT.equals(user) 258 ? android.os.Process.myUserHandle() : user; 259 if (realUser != UserHandle.ALL) { 260 Uri baseUri = userManager.isUserUnlocked(realUser) ? CALL_COMPOSER_PICTURE_URI 261 : SHADOW_CALL_COMPOSER_PICTURE_URI; 262 Uri pictureInsertionUri = ContentProvider.maybeAddUserId(baseUri, 263 realUser.getIdentifier()); 264 Log.i(LOG_TAG, "Inserting call composer for single user at " 265 + pictureInsertionUri); 266 267 try { 268 Uri result = storeCallComposerPictureAtUri( 269 context, pictureInsertionUri, false, picData); 270 callback.onResult(result); 271 } catch (CallComposerLoggingException e) { 272 callback.onError(e); 273 } 274 return; 275 } 276 277 // Next, see if the system user is locked. If so, only insert to the system shadow 278 if (!userManager.isUserUnlocked(UserHandle.SYSTEM)) { 279 Uri pictureInsertionUri = ContentProvider.maybeAddUserId( 280 SHADOW_CALL_COMPOSER_PICTURE_URI, 281 UserHandle.SYSTEM.getIdentifier()); 282 Log.i(LOG_TAG, "Inserting call composer for all users, but system locked at " 283 + pictureInsertionUri); 284 try { 285 Uri result = 286 storeCallComposerPictureAtUri(context, pictureInsertionUri, 287 true, picData); 288 callback.onResult(result); 289 } catch (CallComposerLoggingException e) { 290 callback.onError(e); 291 } 292 return; 293 } 294 295 // If we're inserting to all users and the system user is unlocked, then insert to all 296 // running users. Non running/still locked users will copy from the system when they 297 // start. 298 // First, insert to the system calllog to get the basename to use for the rest of the 299 // users. 300 Uri systemPictureInsertionUri = ContentProvider.maybeAddUserId( 301 CALL_COMPOSER_PICTURE_URI, 302 UserHandle.SYSTEM.getIdentifier()); 303 Uri systemInsertedPicture; 304 try { 305 systemInsertedPicture = 306 storeCallComposerPictureAtUri(context, systemPictureInsertionUri, 307 true, picData); 308 Log.i(LOG_TAG, "Inserting call composer for all users, succeeded with system," 309 + " result is " + systemInsertedPicture); 310 } catch (CallComposerLoggingException e) { 311 callback.onError(e); 312 return; 313 } 314 315 // Next, insert into all users that have call log access AND are running AND are 316 // decrypted. 317 Uri strippedInsertionUri = ContentProvider.getUriWithoutUserId(systemInsertedPicture); 318 for (UserInfo u : userManager.getAliveUsers()) { 319 UserHandle userHandle = u.getUserHandle(); 320 if (userHandle.isSystem()) { 321 // Already written. 322 continue; 323 } 324 325 if (!Calls.shouldHaveSharedCallLogEntries( 326 context, userManager, userHandle.getIdentifier())) { 327 // Shouldn't have calllog entries. 328 continue; 329 } 330 331 if (userManager.isUserRunning(userHandle) 332 && userManager.isUserUnlocked(userHandle)) { 333 Uri insertionUri = ContentProvider.maybeAddUserId(strippedInsertionUri, 334 userHandle.getIdentifier()); 335 Log.i(LOG_TAG, "Inserting call composer for all users, now on user " 336 + userHandle + " inserting at " + insertionUri); 337 try { 338 storeCallComposerPictureAtUri(context, insertionUri, false, picData); 339 } catch (CallComposerLoggingException e) { 340 Log.e(LOG_TAG, "Error writing for user " + userHandle.getIdentifier() 341 + ": " + e); 342 // If one or more users failed but the system user succeeded, don't return 343 // an error -- the image is still around somewhere, and we'll be able to 344 // find it in the system user's call log if needed. 345 } 346 } 347 } 348 callback.onResult(strippedInsertionUri); 349 }); 350 } 351 storeCallComposerPictureAtUri( Context context, Uri insertionUri, boolean forAllUsers, byte[] picData)352 private static Uri storeCallComposerPictureAtUri( 353 Context context, Uri insertionUri, 354 boolean forAllUsers, byte[] picData) throws CallComposerLoggingException { 355 Uri pictureFileUri; 356 try { 357 ContentValues cv = new ContentValues(); 358 cv.put(Calls.ADD_FOR_ALL_USERS, forAllUsers ? 1 : 0); 359 pictureFileUri = context.getContentResolver().insert(insertionUri, cv); 360 } catch (ParcelableException e) { 361 // Most likely an IOException. We don't have a good way of distinguishing them so 362 // just return an unknown error. 363 throw new CallComposerLoggingException(CallComposerLoggingException.ERROR_UNKNOWN); 364 } 365 if (pictureFileUri == null) { 366 // If the call log provider returns null, it means that there's not enough space 367 // left to store the maximum-sized call composer image. 368 throw new CallComposerLoggingException(CallComposerLoggingException.ERROR_STORAGE_FULL); 369 } 370 371 try (ParcelFileDescriptor pfd = 372 context.getContentResolver().openFileDescriptor(pictureFileUri, "w")) { 373 FileOutputStream output = new FileOutputStream(pfd.getFileDescriptor()); 374 try { 375 output.write(picData); 376 } catch (IOException e) { 377 Log.e(LOG_TAG, "Got IOException writing to remote end: " + e); 378 // Clean up our mess if we didn't successfully write the file. 379 context.getContentResolver().delete(pictureFileUri, null); 380 throw new CallComposerLoggingException( 381 CallComposerLoggingException.ERROR_REMOTE_END_CLOSED); 382 } 383 } catch (FileNotFoundException e) { 384 throw new CallComposerLoggingException(CallComposerLoggingException.ERROR_UNKNOWN); 385 } catch (IOException e) { 386 // Ignore, this is only thrown upon closing. 387 Log.e(LOG_TAG, "Got IOException closing remote descriptor: " + e); 388 } 389 return pictureFileUri; 390 } 391 392 // Only call on the correct executor. sendCallComposerError(OutcomeReceiver<?, CallComposerLoggingException> cb, int error)393 private static void sendCallComposerError(OutcomeReceiver<?, CallComposerLoggingException> cb, 394 int error) { 395 cb.onError(new CallComposerLoggingException(error)); 396 } 397 398 /** 399 * Used as an argument to {@link Calls#addCall(Context, AddCallParams)}. 400 * 401 * Contains details to log about a call. 402 * @hide 403 */ 404 public static class AddCallParams { 405 406 /** 407 * Builder for the add-call parameters. 408 */ 409 public static final class AddCallParametersBuilder { 410 public static final int MAX_NUMBER_OF_CHARACTERS = 256; 411 private CallerInfo mCallerInfo; 412 private String mNumber; 413 private String mPostDialDigits; 414 private String mViaNumber; 415 private int mPresentation = TelecomManager.PRESENTATION_UNKNOWN; 416 private int mCallType = Calls.INCOMING_TYPE; 417 private int mFeatures; 418 private PhoneAccountHandle mAccountHandle; 419 private long mStart; 420 private int mDuration; 421 private Long mDataUsage = Long.MIN_VALUE; 422 private boolean mAddForAllUsers; 423 private UserHandle mUserToBeInsertedTo; 424 private boolean mIsRead; 425 private int mCallBlockReason = Calls.BLOCK_REASON_NOT_BLOCKED; 426 private CharSequence mCallScreeningAppName; 427 private String mCallScreeningComponentName; 428 private long mMissedReason = Calls.MISSED_REASON_NOT_MISSED; 429 private int mPriority = Calls.PRIORITY_NORMAL; 430 private String mSubject; 431 private double mLatitude = Double.NaN; 432 private double mLongitude = Double.NaN; 433 private Uri mPictureUri; 434 private int mIsPhoneAccountMigrationPending; 435 private boolean mIsBusinessCall; 436 private String mAssertedDisplayName; 437 438 /** 439 * @param callerInfo the CallerInfo object to get the target contact from. 440 */ setCallerInfo( @onNull CallerInfo callerInfo)441 public @NonNull AddCallParametersBuilder setCallerInfo( 442 @NonNull CallerInfo callerInfo) { 443 mCallerInfo = callerInfo; 444 return this; 445 } 446 447 /** 448 * @param number the phone number to be added to the calls db 449 */ setNumber(@onNull String number)450 public @NonNull AddCallParametersBuilder setNumber(@NonNull String number) { 451 mNumber = number; 452 return this; 453 } 454 455 /** 456 * @param postDialDigits the post-dial digits that were dialed after the number, 457 * if it was outgoing. Otherwise it is ''. 458 */ setPostDialDigits( @onNull String postDialDigits)459 public @NonNull AddCallParametersBuilder setPostDialDigits( 460 @NonNull String postDialDigits) { 461 mPostDialDigits = postDialDigits; 462 return this; 463 } 464 465 /** 466 * @param viaNumber the secondary number that the incoming call received with. If the 467 * call was received with the SIM assigned number, then this field must be ''. 468 */ setViaNumber(@onNull String viaNumber)469 public @NonNull AddCallParametersBuilder setViaNumber(@NonNull String viaNumber) { 470 mViaNumber = viaNumber; 471 return this; 472 } 473 474 /** 475 * @param presentation enum value from TelecomManager.PRESENTATION_xxx, which 476 * is set by the network and denotes the number presenting rules for 477 * "allowed", "payphone", "restricted" or "unknown" 478 */ setPresentation(int presentation)479 public @NonNull AddCallParametersBuilder setPresentation(int presentation) { 480 mPresentation = presentation; 481 return this; 482 } 483 484 /** 485 * @param callType enumerated values for "incoming", "outgoing", or "missed" 486 */ setCallType(int callType)487 public @NonNull AddCallParametersBuilder setCallType(int callType) { 488 mCallType = callType; 489 return this; 490 } 491 492 /** 493 * @param features features of the call (e.g. Video). 494 */ setFeatures(int features)495 public @NonNull AddCallParametersBuilder setFeatures(int features) { 496 mFeatures = features; 497 return this; 498 } 499 500 /** 501 * @param accountHandle The accountHandle object identifying the provider of the call 502 */ setAccountHandle( @onNull PhoneAccountHandle accountHandle)503 public @NonNull AddCallParametersBuilder setAccountHandle( 504 @NonNull PhoneAccountHandle accountHandle) { 505 mAccountHandle = accountHandle; 506 return this; 507 } 508 509 /** 510 * @param start time stamp for the call in milliseconds 511 */ setStart(long start)512 public @NonNull AddCallParametersBuilder setStart(long start) { 513 mStart = start; 514 return this; 515 } 516 517 /** 518 * @param duration call duration in seconds 519 */ setDuration(int duration)520 public @NonNull AddCallParametersBuilder setDuration(int duration) { 521 mDuration = duration; 522 return this; 523 } 524 525 /** 526 * @param dataUsage data usage for the call in bytes or 527 * {@link Long#MIN_VALUE} if data usage was not tracked 528 * for the call. 529 */ setDataUsage(long dataUsage)530 public @NonNull AddCallParametersBuilder setDataUsage(long dataUsage) { 531 mDataUsage = dataUsage; 532 return this; 533 } 534 535 /** 536 * @param addForAllUsers If true, the call is added to the call log of all currently 537 * running users. The caller must have the MANAGE_USERS permission if this is 538 * true. 539 */ setAddForAllUsers( boolean addForAllUsers)540 public @NonNull AddCallParametersBuilder setAddForAllUsers( 541 boolean addForAllUsers) { 542 mAddForAllUsers = addForAllUsers; 543 return this; 544 } 545 546 /** 547 * @param userToBeInsertedTo {@link UserHandle} of user that the call is going to be 548 * inserted to. null if it is inserted to the current user. 549 * The value is ignored if {@link #setAddForAllUsers} is 550 * called with {@code true}. 551 */ 552 @SuppressLint("UserHandleName") setUserToBeInsertedTo( @onNull UserHandle userToBeInsertedTo)553 public @NonNull AddCallParametersBuilder setUserToBeInsertedTo( 554 @NonNull UserHandle userToBeInsertedTo) { 555 mUserToBeInsertedTo = userToBeInsertedTo; 556 return this; 557 } 558 559 /** 560 * @param isRead Flag to show if the missed call log has been read by the user or not. 561 * Used for call log restore of missed calls. 562 */ setIsRead(boolean isRead)563 public @NonNull AddCallParametersBuilder setIsRead(boolean isRead) { 564 mIsRead = isRead; 565 return this; 566 } 567 568 /** 569 * @param callBlockReason The reason why the call is blocked. 570 */ setCallBlockReason(int callBlockReason)571 public @NonNull AddCallParametersBuilder setCallBlockReason(int callBlockReason) { 572 mCallBlockReason = callBlockReason; 573 return this; 574 } 575 576 /** 577 * @param callScreeningAppName The call screening application name which block the call. 578 */ setCallScreeningAppName( @onNull CharSequence callScreeningAppName)579 public @NonNull AddCallParametersBuilder setCallScreeningAppName( 580 @NonNull CharSequence callScreeningAppName) { 581 mCallScreeningAppName = callScreeningAppName; 582 return this; 583 } 584 585 /** 586 * @param callScreeningComponentName The call screening component name which blocked 587 * the call. 588 */ setCallScreeningComponentName( @onNull String callScreeningComponentName)589 public @NonNull AddCallParametersBuilder setCallScreeningComponentName( 590 @NonNull String callScreeningComponentName) { 591 mCallScreeningComponentName = callScreeningComponentName; 592 return this; 593 } 594 595 /** 596 * @param missedReason The encoded missed information of the call. 597 */ setMissedReason(long missedReason)598 public @NonNull AddCallParametersBuilder setMissedReason(long missedReason) { 599 mMissedReason = missedReason; 600 return this; 601 } 602 603 /** 604 * @param priority The priority of the call, either {@link Calls#PRIORITY_NORMAL} 605 * or {@link Calls#PRIORITY_URGENT} as sent via call composer 606 */ setPriority(int priority)607 public @NonNull AddCallParametersBuilder setPriority(int priority) { 608 mPriority = priority; 609 return this; 610 } 611 612 /** 613 * @param subject The subject as sent via call composer. 614 */ setSubject(@onNull String subject)615 public @NonNull AddCallParametersBuilder setSubject(@NonNull String subject) { 616 mSubject = subject; 617 return this; 618 } 619 620 /** 621 * @param latitude Latitude of the location sent via call composer. 622 */ setLatitude(double latitude)623 public @NonNull AddCallParametersBuilder setLatitude(double latitude) { 624 mLatitude = latitude; 625 return this; 626 } 627 628 /** 629 * @param longitude Longitude of the location sent via call composer. 630 */ setLongitude(double longitude)631 public @NonNull AddCallParametersBuilder setLongitude(double longitude) { 632 mLongitude = longitude; 633 return this; 634 } 635 636 /** 637 * @param pictureUri {@link Uri} returned from {@link #storeCallComposerPicture}. 638 * Associates that stored picture with this call in the log. 639 */ setPictureUri(@onNull Uri pictureUri)640 public @NonNull AddCallParametersBuilder setPictureUri(@NonNull Uri pictureUri) { 641 mPictureUri = pictureUri; 642 return this; 643 } 644 645 /** 646 * @param isPhoneAccountMigrationPending whether the phone account migration is pending 647 */ setIsPhoneAccountMigrationPending( int isPhoneAccountMigrationPending)648 public @NonNull AddCallParametersBuilder setIsPhoneAccountMigrationPending( 649 int isPhoneAccountMigrationPending) { 650 mIsPhoneAccountMigrationPending = isPhoneAccountMigrationPending; 651 return this; 652 } 653 654 /** 655 * @param isBusinessCall should be set if the caller is a business call 656 */ 657 @FlaggedApi(Flags.FLAG_BUSINESS_CALL_COMPOSER) setIsBusinessCall(boolean isBusinessCall)658 public @NonNull AddCallParametersBuilder setIsBusinessCall(boolean isBusinessCall) { 659 mIsBusinessCall = isBusinessCall; 660 return this; 661 } 662 663 /** 664 * @param assertedDisplayName the asserted display name associated with the business 665 * call 666 * @throws IllegalArgumentException if the assertedDisplayName is over 256 characters 667 */ 668 @FlaggedApi(Flags.FLAG_BUSINESS_CALL_COMPOSER) setAssertedDisplayName( String assertedDisplayName)669 public @NonNull AddCallParametersBuilder setAssertedDisplayName( 670 String assertedDisplayName) { 671 if (assertedDisplayName != null 672 && assertedDisplayName.length() > MAX_NUMBER_OF_CHARACTERS) { 673 throw new IllegalArgumentException("assertedDisplayName exceeds the character" 674 + " limit of " + MAX_NUMBER_OF_CHARACTERS + "."); 675 } 676 mAssertedDisplayName = assertedDisplayName; 677 return this; 678 } 679 680 /** 681 * Builds the object 682 */ build()683 public @NonNull AddCallParams build() { 684 if (Flags.businessCallComposer()) { 685 return new AddCallParams(mCallerInfo, mNumber, mPostDialDigits, mViaNumber, 686 mPresentation, mCallType, mFeatures, mAccountHandle, mStart, mDuration, 687 mDataUsage, mAddForAllUsers, mUserToBeInsertedTo, mIsRead, 688 mCallBlockReason, 689 mCallScreeningAppName, mCallScreeningComponentName, mMissedReason, 690 mPriority, mSubject, mLatitude, mLongitude, mPictureUri, 691 mIsPhoneAccountMigrationPending, mIsBusinessCall, mAssertedDisplayName); 692 } else { 693 return new AddCallParams(mCallerInfo, mNumber, mPostDialDigits, mViaNumber, 694 mPresentation, mCallType, mFeatures, mAccountHandle, mStart, mDuration, 695 mDataUsage, mAddForAllUsers, mUserToBeInsertedTo, mIsRead, 696 mCallBlockReason, 697 mCallScreeningAppName, mCallScreeningComponentName, mMissedReason, 698 mPriority, mSubject, mLatitude, mLongitude, mPictureUri, 699 mIsPhoneAccountMigrationPending); 700 } 701 } 702 } 703 704 private CallerInfo mCallerInfo; 705 private String mNumber; 706 private String mPostDialDigits; 707 private String mViaNumber; 708 private int mPresentation; 709 private int mCallType; 710 private int mFeatures; 711 private PhoneAccountHandle mAccountHandle; 712 private long mStart; 713 private int mDuration; 714 private long mDataUsage; 715 private boolean mAddForAllUsers; 716 private UserHandle mUserToBeInsertedTo; 717 private boolean mIsRead; 718 private int mCallBlockReason; 719 private CharSequence mCallScreeningAppName; 720 private String mCallScreeningComponentName; 721 private long mMissedReason; 722 private int mPriority; 723 private String mSubject; 724 private double mLatitude = Double.NaN; 725 private double mLongitude = Double.NaN; 726 private Uri mPictureUri; 727 private int mIsPhoneAccountMigrationPending; 728 private boolean mIsBusinessCall; 729 private String mAssertedDisplayName; 730 AddCallParams(CallerInfo callerInfo, 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, long missedReason, int priority, String subject, double latitude, double longitude, Uri pictureUri, int isPhoneAccountMigrationPending)731 private AddCallParams(CallerInfo callerInfo, String number, String postDialDigits, 732 String viaNumber, int presentation, int callType, int features, 733 PhoneAccountHandle accountHandle, long start, int duration, long dataUsage, 734 boolean addForAllUsers, UserHandle userToBeInsertedTo, boolean isRead, 735 int callBlockReason, 736 CharSequence callScreeningAppName, String callScreeningComponentName, 737 long missedReason, 738 int priority, String subject, double latitude, double longitude, Uri pictureUri, 739 int isPhoneAccountMigrationPending) { 740 mCallerInfo = callerInfo; 741 mNumber = number; 742 mPostDialDigits = postDialDigits; 743 mViaNumber = viaNumber; 744 mPresentation = presentation; 745 mCallType = callType; 746 mFeatures = features; 747 mAccountHandle = accountHandle; 748 mStart = start; 749 mDuration = duration; 750 mDataUsage = dataUsage; 751 mAddForAllUsers = addForAllUsers; 752 mUserToBeInsertedTo = userToBeInsertedTo; 753 mIsRead = isRead; 754 mCallBlockReason = callBlockReason; 755 mCallScreeningAppName = callScreeningAppName; 756 mCallScreeningComponentName = callScreeningComponentName; 757 mMissedReason = missedReason; 758 mPriority = priority; 759 mSubject = subject; 760 mLatitude = latitude; 761 mLongitude = longitude; 762 mPictureUri = pictureUri; 763 mIsPhoneAccountMigrationPending = isPhoneAccountMigrationPending; 764 } 765 AddCallParams(CallerInfo callerInfo, 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, long missedReason, int priority, String subject, double latitude, double longitude, Uri pictureUri, int isPhoneAccountMigrationPending, boolean isBusinessCall, String assertedDisplayName)766 private AddCallParams(CallerInfo callerInfo, String number, String postDialDigits, 767 String viaNumber, int presentation, int callType, int features, 768 PhoneAccountHandle accountHandle, long start, int duration, long dataUsage, 769 boolean addForAllUsers, UserHandle userToBeInsertedTo, boolean isRead, 770 int callBlockReason, 771 CharSequence callScreeningAppName, String callScreeningComponentName, 772 long missedReason, 773 int priority, String subject, double latitude, double longitude, Uri pictureUri, 774 int isPhoneAccountMigrationPending, boolean isBusinessCall, 775 String assertedDisplayName) { 776 mCallerInfo = callerInfo; 777 mNumber = number; 778 mPostDialDigits = postDialDigits; 779 mViaNumber = viaNumber; 780 mPresentation = presentation; 781 mCallType = callType; 782 mFeatures = features; 783 mAccountHandle = accountHandle; 784 mStart = start; 785 mDuration = duration; 786 mDataUsage = dataUsage; 787 mAddForAllUsers = addForAllUsers; 788 mUserToBeInsertedTo = userToBeInsertedTo; 789 mIsRead = isRead; 790 mCallBlockReason = callBlockReason; 791 mCallScreeningAppName = callScreeningAppName; 792 mCallScreeningComponentName = callScreeningComponentName; 793 mMissedReason = missedReason; 794 mPriority = priority; 795 mSubject = subject; 796 mLatitude = latitude; 797 mLongitude = longitude; 798 mPictureUri = pictureUri; 799 mIsPhoneAccountMigrationPending = isPhoneAccountMigrationPending; 800 mIsBusinessCall = isBusinessCall; 801 mAssertedDisplayName = assertedDisplayName; 802 } 803 804 } 805 806 /** 807 * Contains the recent calls. 808 * <p> 809 * Note: If you want to query the call log and limit the results to a single value, you should 810 * append the {@link #LIMIT_PARAM_KEY} parameter to the content URI. For example: 811 * <pre> 812 * {@code 813 * getContentResolver().query( 814 * Calls.CONTENT_URI.buildUpon().appendQueryParameter(LIMIT_PARAM_KEY, "1") 815 * .build(), 816 * null, null, null, null); 817 * } 818 * </pre> 819 * <p> 820 * The call log provider enforces strict SQL grammar, so you CANNOT append "LIMIT" to the SQL 821 * query as below: 822 * <pre> 823 * {@code 824 * getContentResolver().query(Calls.CONTENT_URI, null, "LIMIT 1", null, null); 825 * } 826 * </pre> 827 */ 828 public static class Calls implements BaseColumns { 829 /** 830 * The content:// style URL for this table 831 */ 832 public static final Uri CONTENT_URI = 833 Uri.parse("content://call_log/calls"); 834 835 /** @hide */ 836 public static final Uri SHADOW_CONTENT_URI = 837 Uri.parse("content://call_log_shadow/calls"); 838 839 /** 840 * The content:// style URL for filtering this table on phone numbers 841 */ 842 public static final Uri CONTENT_FILTER_URI = 843 Uri.parse("content://call_log/calls/filter"); 844 845 /** 846 * Query parameter used to limit the number of call logs returned. 847 * <p> 848 * TYPE: integer 849 */ 850 public static final String LIMIT_PARAM_KEY = "limit"; 851 852 /** 853 * Form of {@link #CONTENT_URI} which limits the query results to a single result. 854 */ 855 private static final Uri CONTENT_URI_LIMIT_1 = CONTENT_URI.buildUpon() 856 .appendQueryParameter(LIMIT_PARAM_KEY, "1") 857 .build(); 858 859 /** 860 * Query parameter used to specify the starting record to return. 861 * <p> 862 * TYPE: integer 863 */ 864 public static final String OFFSET_PARAM_KEY = "offset"; 865 866 /** 867 * An optional URI parameter which instructs the provider to allow the operation to be 868 * applied to voicemail records as well. 869 * <p> 870 * TYPE: Boolean 871 * <p> 872 * Using this parameter with a value of {@code true} will result in a security error if the 873 * calling package does not have appropriate permissions to access voicemails. 874 * 875 * @hide 876 */ 877 public static final String ALLOW_VOICEMAILS_PARAM_KEY = "allow_voicemails"; 878 879 /** 880 * An optional extra used with {@link #CONTENT_TYPE Calls.CONTENT_TYPE} and 881 * {@link Intent#ACTION_VIEW} to specify that the presented list of calls should be 882 * filtered for a particular call type. 883 * 884 * Applications implementing a call log UI should check for this extra, and display a 885 * filtered list of calls based on the specified call type. If not applicable within the 886 * application's UI, it should be silently ignored. 887 * 888 * <p> 889 * The following example brings up the call log, showing only missed calls. 890 * <pre> 891 * Intent intent = new Intent(Intent.ACTION_VIEW); 892 * intent.setType(CallLog.Calls.CONTENT_TYPE); 893 * intent.putExtra(CallLog.Calls.EXTRA_CALL_TYPE_FILTER, CallLog.Calls.MISSED_TYPE); 894 * startActivity(intent); 895 * </pre> 896 * </p> 897 */ 898 public static final String EXTRA_CALL_TYPE_FILTER = 899 "android.provider.extra.CALL_TYPE_FILTER"; 900 901 /** 902 * Content uri used to access call log entries, including voicemail records. You must have 903 * the READ_CALL_LOG and WRITE_CALL_LOG permissions to read and write to the call log, as 904 * well as READ_VOICEMAIL and WRITE_VOICEMAIL permissions to read and write voicemails. 905 */ 906 public static final Uri CONTENT_URI_WITH_VOICEMAIL = CONTENT_URI.buildUpon() 907 .appendQueryParameter(ALLOW_VOICEMAILS_PARAM_KEY, "true") 908 .build(); 909 910 /** 911 * The default sort order for this table 912 */ 913 public static final String DEFAULT_SORT_ORDER = "date DESC"; 914 915 /** 916 * The MIME type of {@link #CONTENT_URI} and {@link #CONTENT_FILTER_URI} 917 * providing a directory of calls. 918 */ 919 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/calls"; 920 921 /** 922 * The MIME type of a {@link #CONTENT_URI} sub-directory of a single 923 * call. 924 */ 925 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/calls"; 926 927 /** 928 * The type of the call (incoming, outgoing or missed). 929 * <P>Type: INTEGER (int)</P> 930 * 931 * <p> 932 * Allowed values: 933 * <ul> 934 * <li>{@link #INCOMING_TYPE}</li> 935 * <li>{@link #OUTGOING_TYPE}</li> 936 * <li>{@link #MISSED_TYPE}</li> 937 * <li>{@link #VOICEMAIL_TYPE}</li> 938 * <li>{@link #REJECTED_TYPE}</li> 939 * <li>{@link #BLOCKED_TYPE}</li> 940 * <li>{@link #ANSWERED_EXTERNALLY_TYPE}</li> 941 * </ul> 942 * </p> 943 */ 944 public static final String TYPE = "type"; 945 946 /** Call log type for incoming calls. */ 947 public static final int INCOMING_TYPE = 1; 948 /** Call log type for outgoing calls. */ 949 public static final int OUTGOING_TYPE = 2; 950 /** Call log type for missed calls. */ 951 public static final int MISSED_TYPE = 3; 952 /** Call log type for voicemails. */ 953 public static final int VOICEMAIL_TYPE = 4; 954 /** Call log type for calls rejected by direct user action. */ 955 public static final int REJECTED_TYPE = 5; 956 /** Call log type for calls blocked automatically. */ 957 public static final int BLOCKED_TYPE = 6; 958 /** 959 * Call log type for a call which was answered on another device. Used in situations where 960 * a call rings on multiple devices simultaneously and it ended up being answered on a 961 * device other than the current one. 962 */ 963 public static final int ANSWERED_EXTERNALLY_TYPE = 7; 964 965 /** 966 * Bit-mask describing features of the call (e.g. video). 967 * 968 * <P>Type: INTEGER (int)</P> 969 */ 970 public static final String FEATURES = "features"; 971 972 /** Call had video. */ 973 public static final int FEATURES_VIDEO = 1 << 0; 974 975 /** Call was pulled externally. */ 976 public static final int FEATURES_PULLED_EXTERNALLY = 1 << 1; 977 978 /** Call was HD. */ 979 public static final int FEATURES_HD_CALL = 1 << 2; 980 981 /** Call was WIFI call. */ 982 public static final int FEATURES_WIFI = 1 << 3; 983 984 /** 985 * Indicates the call underwent Assisted Dialing. 986 * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING 987 */ 988 public static final int FEATURES_ASSISTED_DIALING_USED = 1 << 4; 989 990 /** Call was on RTT at some point */ 991 public static final int FEATURES_RTT = 1 << 5; 992 993 /** Call was VoLTE */ 994 public static final int FEATURES_VOLTE = 1 << 6; 995 996 /** 997 * The phone number as the user entered it. 998 * <P>Type: TEXT</P> 999 */ 1000 public static final String NUMBER = "number"; 1001 1002 1003 /** 1004 * Boolean indicating whether the call is a business call. 1005 */ 1006 @FlaggedApi(Flags.FLAG_BUSINESS_CALL_COMPOSER) 1007 public static final String IS_BUSINESS_CALL = "is_business_call"; 1008 1009 /** 1010 * String that stores the asserted display name associated with business call. 1011 */ 1012 @FlaggedApi(Flags.FLAG_BUSINESS_CALL_COMPOSER) 1013 public static final String ASSERTED_DISPLAY_NAME = "asserted_display_name"; 1014 1015 /** 1016 * The number presenting rules set by the network. 1017 * 1018 * <p> 1019 * Allowed values: 1020 * <ul> 1021 * <li>{@link #PRESENTATION_ALLOWED}</li> 1022 * <li>{@link #PRESENTATION_RESTRICTED}</li> 1023 * <li>{@link #PRESENTATION_UNKNOWN}</li> 1024 * <li>{@link #PRESENTATION_PAYPHONE}</li> 1025 * <li>{@link #PRESENTATION_UNAVAILABLE}</li> 1026 * </ul> 1027 * </p> 1028 * 1029 * <P>Type: INTEGER</P> 1030 */ 1031 public static final String NUMBER_PRESENTATION = "presentation"; 1032 1033 /** Number is allowed to display for caller id. */ 1034 public static final int PRESENTATION_ALLOWED = 1; 1035 /** Number is blocked by user. */ 1036 public static final int PRESENTATION_RESTRICTED = 2; 1037 /** Number is not specified or unknown by network. */ 1038 public static final int PRESENTATION_UNKNOWN = 3; 1039 /** Number is a pay phone. */ 1040 public static final int PRESENTATION_PAYPHONE = 4; 1041 /** Number is unavailable. */ 1042 public static final int PRESENTATION_UNAVAILABLE = 5; 1043 1044 /** 1045 * The ISO 3166-1 two letters country code of the country where the 1046 * user received or made the call. 1047 * <P> 1048 * Type: TEXT 1049 * </P> 1050 */ 1051 public static final String COUNTRY_ISO = "countryiso"; 1052 1053 /** 1054 * The date the call occured, in milliseconds since the epoch 1055 * <P>Type: INTEGER (long)</P> 1056 */ 1057 public static final String DATE = "date"; 1058 1059 /** 1060 * The duration of the call in seconds 1061 * <P>Type: INTEGER (long)</P> 1062 */ 1063 public static final String DURATION = "duration"; 1064 1065 /** 1066 * The data usage of the call in bytes. 1067 * <P>Type: INTEGER (long)</P> 1068 */ 1069 public static final String DATA_USAGE = "data_usage"; 1070 1071 /** 1072 * Whether or not the call has been acknowledged 1073 * <P>Type: INTEGER (boolean)</P> 1074 */ 1075 public static final String NEW = "new"; 1076 1077 /** 1078 * The cached name associated with the phone number, if it exists. 1079 * 1080 * <p>This value is typically filled in by the dialer app for the caching purpose, 1081 * so it's not guaranteed to be present, and may not be current if the contact 1082 * information associated with this number has changed. 1083 * <P>Type: TEXT</P> 1084 */ 1085 public static final String CACHED_NAME = "name"; 1086 1087 /** 1088 * The cached number type (Home, Work, etc) associated with the 1089 * phone number, if it exists. 1090 * 1091 * <p>This value is typically filled in by the dialer app for the caching purpose, 1092 * so it's not guaranteed to be present, and may not be current if the contact 1093 * information associated with this number has changed. 1094 * <P>Type: INTEGER</P> 1095 */ 1096 public static final String CACHED_NUMBER_TYPE = "numbertype"; 1097 1098 /** 1099 * The cached number label, for a custom number type, associated with the 1100 * phone number, if it exists. 1101 * 1102 * <p>This value is typically filled in by the dialer app for the caching purpose, 1103 * so it's not guaranteed to be present, and may not be current if the contact 1104 * information associated with this number has changed. 1105 * <P>Type: TEXT</P> 1106 */ 1107 public static final String CACHED_NUMBER_LABEL = "numberlabel"; 1108 1109 /** 1110 * URI of the voicemail entry. Populated only for {@link #VOICEMAIL_TYPE}. 1111 * <P>Type: TEXT</P> 1112 */ 1113 public static final String VOICEMAIL_URI = "voicemail_uri"; 1114 1115 /** 1116 * Transcription of the call or voicemail entry. This will only be populated for call log 1117 * entries of type {@link #VOICEMAIL_TYPE} that have valid transcriptions. 1118 */ 1119 public static final String TRANSCRIPTION = "transcription"; 1120 1121 /** 1122 * State of voicemail transcription entry. This will only be populated for call log 1123 * entries of type {@link #VOICEMAIL_TYPE}. 1124 * @hide 1125 */ 1126 public static final String TRANSCRIPTION_STATE = "transcription_state"; 1127 1128 /** 1129 * Whether this item has been read or otherwise consumed by the user. 1130 * <p> 1131 * Unlike the {@link #NEW} field, which requires the user to have acknowledged the 1132 * existence of the entry, this implies the user has interacted with the entry. 1133 * <P>Type: INTEGER (boolean)</P> 1134 */ 1135 public static final String IS_READ = "is_read"; 1136 1137 /** 1138 * A geocoded location for the number associated with this call. 1139 * <p> 1140 * The string represents a city, state, or country associated with the number. 1141 * <P>Type: TEXT</P> 1142 */ 1143 public static final String GEOCODED_LOCATION = "geocoded_location"; 1144 1145 /** 1146 * The cached URI to look up the contact associated with the phone number, if it exists. 1147 * 1148 * <p>This value is typically filled in by the dialer app for the caching purpose, 1149 * so it's not guaranteed to be present, and may not be current if the contact 1150 * information associated with this number has changed. 1151 * <P>Type: TEXT</P> 1152 */ 1153 public static final String CACHED_LOOKUP_URI = "lookup_uri"; 1154 1155 /** 1156 * The cached phone number of the contact which matches this entry, if it exists. 1157 * 1158 * <p>This value is typically filled in by the dialer app for the caching purpose, 1159 * so it's not guaranteed to be present, and may not be current if the contact 1160 * information associated with this number has changed. 1161 * <P>Type: TEXT</P> 1162 */ 1163 public static final String CACHED_MATCHED_NUMBER = "matched_number"; 1164 1165 /** 1166 * The cached normalized(E164) version of the phone number, if it exists. 1167 * 1168 * <p>This value is typically filled in by the dialer app for the caching purpose, 1169 * so it's not guaranteed to be present, and may not be current if the contact 1170 * information associated with this number has changed. 1171 * <P>Type: TEXT</P> 1172 */ 1173 public static final String CACHED_NORMALIZED_NUMBER = "normalized_number"; 1174 1175 /** 1176 * The cached photo id of the picture associated with the phone number, if it exists. 1177 * 1178 * <p>This value is typically filled in by the dialer app for the caching purpose, 1179 * so it's not guaranteed to be present, and may not be current if the contact 1180 * information associated with this number has changed. 1181 * <P>Type: INTEGER (long)</P> 1182 */ 1183 public static final String CACHED_PHOTO_ID = "photo_id"; 1184 1185 /** 1186 * The cached photo URI of the picture associated with the phone number, if it exists. 1187 * 1188 * <p>This value is typically filled in by the dialer app for the caching purpose, 1189 * so it's not guaranteed to be present, and may not be current if the contact 1190 * information associated with this number has changed. 1191 * <P>Type: TEXT (URI)</P> 1192 */ 1193 public static final String CACHED_PHOTO_URI = "photo_uri"; 1194 1195 /** 1196 * The cached phone number, formatted with formatting rules based on the country the 1197 * user was in when the call was made or received. 1198 * 1199 * <p>This value is typically filled in by the dialer app for the caching purpose, 1200 * so it's not guaranteed to be present, and may not be current if the contact 1201 * information associated with this number has changed. 1202 * <P>Type: TEXT</P> 1203 */ 1204 public static final String CACHED_FORMATTED_NUMBER = "formatted_number"; 1205 1206 // Note: PHONE_ACCOUNT_* constant values are "subscription_*" due to a historic naming 1207 // that was encoded into call log databases. 1208 1209 /** 1210 * The component name of the account used to place or receive the call; in string form. 1211 * <P>Type: TEXT</P> 1212 */ 1213 public static final String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name"; 1214 1215 /** 1216 * The identifier for the account used to place or receive the call. 1217 * <P>Type: TEXT</P> 1218 */ 1219 public static final String PHONE_ACCOUNT_ID = "subscription_id"; 1220 1221 /** 1222 * The address associated with the account used to place or receive the call; in string 1223 * form. For SIM-based calls, this is the user's own phone number. 1224 * <P>Type: TEXT</P> 1225 * 1226 * @hide 1227 */ 1228 public static final String PHONE_ACCOUNT_ADDRESS = "phone_account_address"; 1229 1230 /** 1231 * Indicates that the entry will be hidden from all queries until the associated 1232 * {@link android.telecom.PhoneAccount} is registered with the system. 1233 * <P>Type: INTEGER</P> 1234 * 1235 * @hide 1236 */ 1237 public static final String PHONE_ACCOUNT_HIDDEN = "phone_account_hidden"; 1238 1239 /** 1240 * The subscription ID used to place this call. This is no longer used and has been 1241 * replaced with PHONE_ACCOUNT_COMPONENT_NAME/PHONE_ACCOUNT_ID. 1242 * For ContactsProvider internal use only. 1243 * <P>Type: INTEGER</P> 1244 * 1245 * @Deprecated 1246 * @hide 1247 */ 1248 public static final String SUB_ID = "sub_id"; 1249 1250 /** 1251 * The post-dial portion of a dialed number, including any digits dialed after a 1252 * {@link TelecomManager#DTMF_CHARACTER_PAUSE} or a {@link 1253 * TelecomManager#DTMF_CHARACTER_WAIT} and these characters themselves. 1254 * <P>Type: TEXT</P> 1255 */ 1256 public static final String POST_DIAL_DIGITS = "post_dial_digits"; 1257 1258 /** 1259 * For an incoming call, the secondary line number the call was received via. 1260 * When a SIM card has multiple phone numbers associated with it, the via number indicates 1261 * which of the numbers associated with the SIM was called. 1262 */ 1263 public static final String VIA_NUMBER = "via_number"; 1264 1265 /** 1266 * Indicates that the entry will be copied from primary user to other users. 1267 * <P>Type: INTEGER</P> 1268 * 1269 * @hide 1270 */ 1271 public static final String ADD_FOR_ALL_USERS = "add_for_all_users"; 1272 1273 /** 1274 * The date the row is last inserted, updated, or marked as deleted, in milliseconds 1275 * since the epoch. Read only. 1276 * <P>Type: INTEGER (long)</P> 1277 */ 1278 public static final String LAST_MODIFIED = "last_modified"; 1279 1280 /** 1281 * If a successful call is made that is longer than this duration, update the phone number 1282 * in the ContactsProvider with the normalized version of the number, based on the user's 1283 * current country code. 1284 */ 1285 private static final int MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS = 1000 * 10; 1286 1287 /** 1288 * Value for {@link CallLog.Calls#BLOCK_REASON}, set as the default value when a call was 1289 * not blocked by a CallScreeningService or any other system call blocking method. 1290 */ 1291 public static final int BLOCK_REASON_NOT_BLOCKED = 0; 1292 1293 /** 1294 * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is 1295 * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked by a 1296 * CallScreeningService. The {@link CallLog.Calls#CALL_SCREENING_COMPONENT_NAME} and 1297 * {@link CallLog.Calls#CALL_SCREENING_APP_NAME} columns will indicate which call screening 1298 * service was responsible for blocking the call. 1299 */ 1300 public static final int BLOCK_REASON_CALL_SCREENING_SERVICE = 1; 1301 1302 /** 1303 * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is 1304 * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user 1305 * configured a contact to be sent directly to voicemail. 1306 */ 1307 public static final int BLOCK_REASON_DIRECT_TO_VOICEMAIL = 2; 1308 1309 /** 1310 * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is 1311 * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because it is 1312 * in the BlockedNumbers provider. 1313 */ 1314 public static final int BLOCK_REASON_BLOCKED_NUMBER = 3; 1315 1316 /** 1317 * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is 1318 * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user 1319 * has chosen to block all calls from unknown numbers. 1320 */ 1321 public static final int BLOCK_REASON_UNKNOWN_NUMBER = 4; 1322 1323 /** 1324 * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is 1325 * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user 1326 * has chosen to block all calls from restricted numbers. 1327 */ 1328 public static final int BLOCK_REASON_RESTRICTED_NUMBER = 5; 1329 1330 /** 1331 * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is 1332 * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user 1333 * has chosen to block all calls from pay phones. 1334 */ 1335 public static final int BLOCK_REASON_PAY_PHONE = 6; 1336 1337 /** 1338 * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is 1339 * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user 1340 * has chosen to block all calls from numbers not in their contacts. 1341 */ 1342 public static final int BLOCK_REASON_NOT_IN_CONTACTS = 7; 1343 1344 /** 1345 * The ComponentName of the CallScreeningService which blocked this call. Will be 1346 * populated when the {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE}. 1347 * <P>Type: TEXT</P> 1348 */ 1349 public static final String CALL_SCREENING_COMPONENT_NAME = "call_screening_component_name"; 1350 1351 /** 1352 * The name of the app which blocked a call. Will be populated when the 1353 * {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE}. Provided as a 1354 * convenience so that the call log can still indicate which app blocked a call, even if 1355 * that app is no longer installed. 1356 * <P>Type: TEXT</P> 1357 */ 1358 public static final String CALL_SCREENING_APP_NAME = "call_screening_app_name"; 1359 1360 /** 1361 * Where the {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE}, 1362 * indicates the reason why a call is blocked. 1363 * <P>Type: INTEGER</P> 1364 * 1365 * <p> 1366 * Allowed values: 1367 * <ul> 1368 * <li>{@link CallLog.Calls#BLOCK_REASON_NOT_BLOCKED}</li> 1369 * <li>{@link CallLog.Calls#BLOCK_REASON_CALL_SCREENING_SERVICE}</li> 1370 * <li>{@link CallLog.Calls#BLOCK_REASON_DIRECT_TO_VOICEMAIL}</li> 1371 * <li>{@link CallLog.Calls#BLOCK_REASON_BLOCKED_NUMBER}</li> 1372 * <li>{@link CallLog.Calls#BLOCK_REASON_UNKNOWN_NUMBER}</li> 1373 * <li>{@link CallLog.Calls#BLOCK_REASON_RESTRICTED_NUMBER}</li> 1374 * <li>{@link CallLog.Calls#BLOCK_REASON_PAY_PHONE}</li> 1375 * <li>{@link CallLog.Calls#BLOCK_REASON_NOT_IN_CONTACTS}</li> 1376 * </ul> 1377 * </p> 1378 */ 1379 public static final String BLOCK_REASON = "block_reason"; 1380 1381 /** @hide */ 1382 @LongDef(flag = true, value = { 1383 MISSED_REASON_NOT_MISSED, 1384 AUTO_MISSED_EMERGENCY_CALL, 1385 AUTO_MISSED_MAXIMUM_RINGING, 1386 AUTO_MISSED_MAXIMUM_DIALING, 1387 USER_MISSED_NO_ANSWER, 1388 USER_MISSED_SHORT_RING, 1389 USER_MISSED_DND_MODE, 1390 USER_MISSED_LOW_RING_VOLUME, 1391 USER_MISSED_NO_VIBRATE, 1392 USER_MISSED_CALL_SCREENING_SERVICE_SILENCED, 1393 USER_MISSED_CALL_FILTERS_TIMEOUT, 1394 USER_MISSED_NEVER_RANG, 1395 USER_MISSED_NOT_RUNNING 1396 }) 1397 @Retention(RetentionPolicy.SOURCE) 1398 public @interface MissedReason {} 1399 1400 /** 1401 * Value for {@link CallLog.Calls#MISSED_REASON}, set as the default value when a call was 1402 * not missed. 1403 */ 1404 public static final long MISSED_REASON_NOT_MISSED = 0; 1405 1406 /** 1407 * Value for {@link CallLog.Calls#MISSED_REASON}, set when {@link CallLog.Calls#TYPE} is 1408 * {@link CallLog.Calls#MISSED_TYPE} to indicate that a call was automatically rejected by 1409 * system because an ongoing emergency call. 1410 */ 1411 public static final long AUTO_MISSED_EMERGENCY_CALL = 1 << 0; 1412 1413 /** 1414 * Value for {@link CallLog.Calls#MISSED_REASON}, set when {@link CallLog.Calls#TYPE} is 1415 * {@link CallLog.Calls#MISSED_TYPE} to indicate that a call was automatically rejected by 1416 * system because the system cannot support any more ringing calls. 1417 */ 1418 public static final long AUTO_MISSED_MAXIMUM_RINGING = 1 << 1; 1419 1420 /** 1421 * Value for {@link CallLog.Calls#MISSED_REASON}, set when {@link CallLog.Calls#TYPE} is 1422 * {@link CallLog.Calls#MISSED_TYPE} to indicate that a call was automatically rejected by 1423 * system because the system cannot support any more dialing calls. 1424 */ 1425 public static final long AUTO_MISSED_MAXIMUM_DIALING = 1 << 2; 1426 1427 /** 1428 * When {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#MISSED_TYPE}, set this bit when 1429 * the call was missed just because user didn't answer it. 1430 */ 1431 public static final long USER_MISSED_NO_ANSWER = 1 << 16; 1432 1433 /** 1434 * When {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#MISSED_TYPE}, set this bit when 1435 * this call rang for a short period of time. 1436 */ 1437 public static final long USER_MISSED_SHORT_RING = 1 << 17; 1438 1439 /** 1440 * When {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#MISSED_TYPE}, when this call 1441 * rings less than this defined time in millisecond, set 1442 * {@link CallLog.Calls#USER_MISSED_SHORT_RING} bit. 1443 * @hide 1444 */ 1445 public static final long SHORT_RING_THRESHOLD = 5000L; 1446 1447 /** 1448 * When {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#MISSED_TYPE}, set this bit when 1449 * this call is silenced because the phone is in 'do not disturb mode'. 1450 */ 1451 public static final long USER_MISSED_DND_MODE = 1 << 18; 1452 1453 /** 1454 * When {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#MISSED_TYPE}, set this bit when 1455 * this call rings with a low ring volume. 1456 */ 1457 public static final long USER_MISSED_LOW_RING_VOLUME = 1 << 19; 1458 1459 /** 1460 * When {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#MISSED_TYPE}, when this call 1461 * rings in volume less than this defined volume threshold, set 1462 * {@link CallLog.Calls#USER_MISSED_LOW_RING_VOLUME} bit. 1463 * @hide 1464 */ 1465 public static final int LOW_RING_VOLUME = 0; 1466 1467 /** 1468 * When {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#MISSED_TYPE} set this bit when 1469 * this call rings without vibration. 1470 */ 1471 public static final long USER_MISSED_NO_VIBRATE = 1 << 20; 1472 1473 /** 1474 * When {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#MISSED_TYPE}, set this bit when 1475 * this call is silenced by the call screening service. 1476 */ 1477 public static final long USER_MISSED_CALL_SCREENING_SERVICE_SILENCED = 1 << 21; 1478 1479 /** 1480 * When {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#MISSED_TYPE}, set this bit when 1481 * the call filters timed out. 1482 */ 1483 public static final long USER_MISSED_CALL_FILTERS_TIMEOUT = 1 << 22; 1484 1485 /** 1486 * When {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#MISSED_TYPE}, set this bit when 1487 * the call ended before ringing. 1488 * @hide 1489 */ 1490 public static final long USER_MISSED_NEVER_RANG = 1 << 23; 1491 1492 /** 1493 * When {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#MISSED_TYPE}, set this bit when 1494 * the user receiving the call is not running (i.e. work profile paused). 1495 * @hide 1496 */ 1497 public static final long USER_MISSED_NOT_RUNNING = 1 << 24; 1498 1499 /** 1500 * Where the {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#MISSED_TYPE}, 1501 * indicates factors which may have lead the user to miss the call. 1502 * <P>Type: INTEGER</P> 1503 * 1504 * <p> 1505 * There are two main cases. Auto missed cases and user missed cases. Default value is: 1506 * <ul> 1507 * <li>{@link CallLog.Calls#MISSED_REASON_NOT_MISSED}</li> 1508 * </ul> 1509 * </p> 1510 * <P> 1511 * Auto missed cases are those where a call was missed because it was not possible for the 1512 * incoming call to be presented to the user at all. Possible values are: 1513 * <ul> 1514 * <li>{@link CallLog.Calls#AUTO_MISSED_EMERGENCY_CALL}</li> 1515 * <li>{@link CallLog.Calls#AUTO_MISSED_MAXIMUM_RINGING}</li> 1516 * <li>{@link CallLog.Calls#AUTO_MISSED_MAXIMUM_DIALING}</li> 1517 * </ul> 1518 * </P> 1519 * <P> 1520 * User missed cases are those where the incoming call was presented to the user, but 1521 * factors such as a low ringing volume may have contributed to the call being missed. 1522 * Following bits can be set to indicate possible reasons for this: 1523 * <ul> 1524 * <li>{@link CallLog.Calls#USER_MISSED_SHORT_RING}</li> 1525 * <li>{@link CallLog.Calls#USER_MISSED_DND_MODE}</li> 1526 * <li>{@link CallLog.Calls#USER_MISSED_LOW_RING_VOLUME}</li> 1527 * <li>{@link CallLog.Calls#USER_MISSED_NO_VIBRATE}</li> 1528 * <li>{@link CallLog.Calls#USER_MISSED_CALL_SCREENING_SERVICE_SILENCED}</li> 1529 * <li>{@link CallLog.Calls#USER_MISSED_CALL_FILTERS_TIMEOUT}</li> 1530 * </ul> 1531 * </P> 1532 */ 1533 public static final String MISSED_REASON = "missed_reason"; 1534 1535 /** 1536 * The subject of the call, as delivered via call composer. 1537 * 1538 * For outgoing calls, contains the subject set by the local user. For incoming calls, 1539 * contains the subject set by the remote caller. May be null if no subject was set. 1540 * <p>Type: TEXT</p> 1541 */ 1542 public static final String SUBJECT = "subject"; 1543 1544 /** 1545 * Used as a value in the {@link #PRIORITY} column. 1546 * 1547 * Indicates that the call is of normal priority. This is also the default value for calls 1548 * that did not include call composer elements. 1549 */ 1550 public static final int PRIORITY_NORMAL = 0; 1551 1552 /** 1553 * Used as a value in the {@link #PRIORITY} column. 1554 * 1555 * Indicates that the call is of urgent priority. 1556 */ 1557 public static final int PRIORITY_URGENT = 1; 1558 1559 /** 1560 * The priority of the call, as delivered via call composer. 1561 * 1562 * For outgoing calls, contains the priority set by the local user. For incoming calls, 1563 * contains the priority set by the remote caller. If no priority was set or the call 1564 * did not include call composer elements, defaults to {@link #PRIORITY_NORMAL}. 1565 * Valid values are {@link #PRIORITY_NORMAL} and {@link #PRIORITY_URGENT}. 1566 * <p>Type: INTEGER</p> 1567 */ 1568 public static final String PRIORITY = "priority"; 1569 1570 /** 1571 * A reference to the picture that was sent via call composer. 1572 * 1573 * The string contained in this field should be converted to an {@link Uri} via 1574 * {@link Uri#parse(String)}, then passed to {@link ContentResolver#openFileDescriptor} 1575 * in order to obtain a file descriptor to access the picture data. 1576 * 1577 * The user may choose to delete the picture associated with a call independently of the 1578 * call log entry, in which case {@link ContentResolver#openFileDescriptor} may throw a 1579 * {@link FileNotFoundException}. 1580 * 1581 * Note that pictures sent or received via call composer will not be included in any 1582 * backups of the call log. 1583 * 1584 * <p>Type: TEXT</p> 1585 */ 1586 public static final String COMPOSER_PHOTO_URI = "composer_photo_uri"; 1587 1588 /** 1589 * A reference to the location that was sent via call composer. 1590 * 1591 * This column contains the content URI of the corresponding entry in {@link Locations} 1592 * table, which contains the actual location data. The 1593 * {@link Manifest.permission#ACCESS_FINE_LOCATION} permission is required to access that 1594 * table. 1595 * 1596 * If your app has the appropriate permissions, the location data may be obtained by 1597 * converting the value of this column to an {@link Uri} via {@link Uri#parse}, then passing 1598 * the result to {@link ContentResolver#query}. 1599 * 1600 * The user may choose to delete the location associated with a call independently of the 1601 * call log entry, in which case the {@link Cursor} returned from 1602 * {@link ContentResolver#query} will either be {@code null} or empty, with 1603 * {@link Cursor#getCount()} returning {@code 0}. 1604 * 1605 * This column will not be populated when a call is received while the device is locked, and 1606 * it will not be part of any backups. 1607 * 1608 * <p>Type: TEXT</p> 1609 */ 1610 public static final String LOCATION = "location"; 1611 1612 /** 1613 * A reference to indicate whether phone account migration process is pending. 1614 * 1615 * Before Android 13, {@link PhoneAccountHandle#getId()} returns the ICCID for Telephony 1616 * PhoneAccountHandle. Starting from Android 13, {@link PhoneAccountHandle#getId()} returns 1617 * the Subscription ID for Telephony PhoneAccountHandle. A phone account migration process 1618 * is to ensure this PhoneAccountHandle migration process cross the Android versions in 1619 * the CallLog database. 1620 * 1621 * <p>Type: INTEGER</p> 1622 * @hide 1623 */ 1624 public static final String IS_PHONE_ACCOUNT_MIGRATION_PENDING = 1625 "is_call_log_phone_account_migration_pending"; 1626 1627 /** 1628 * The default maximum number of call log entries stored in the call log provider for each 1629 * {@link PhoneAccountHandle}. 1630 */ 1631 private static final int DEFAULT_MAX_CALL_LOG_SIZE = 500; 1632 1633 /** 1634 * Expected component name of Telephony phone accounts. 1635 */ 1636 private static final ComponentName TELEPHONY_COMPONENT_NAME = 1637 new ComponentName("com.android.phone", 1638 "com.android.services.telephony.TelephonyConnectionService"); 1639 1640 /** 1641 * Adds a call to the call log. 1642 * 1643 * @param ci the CallerInfo object to get the target contact from. Can be null 1644 * if the contact is unknown. 1645 * @param context the context used to get the ContentResolver 1646 * @param number the phone number to be added to the calls db 1647 * @param presentation enum value from TelecomManager.PRESENTATION_xxx, which 1648 * is set by the network and denotes the number presenting rules for 1649 * "allowed", "payphone", "restricted" or "unknown" 1650 * @param callType enumerated values for "incoming", "outgoing", or "missed" 1651 * @param features features of the call (e.g. Video). 1652 * @param accountHandle The accountHandle object identifying the provider of the call 1653 * @param start time stamp for the call in milliseconds 1654 * @param duration call duration in seconds 1655 * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for 1656 * the call. 1657 * @param isPhoneAccountMigrationPending whether the PhoneAccountHandle ID need to migrate 1658 * @result The URI of the call log entry belonging to the user that made or received this 1659 * call. 1660 * {@hide} 1661 */ addCall(CallerInfo ci, Context context, String number, int presentation, int callType, int features, PhoneAccountHandle accountHandle, long start, int duration, Long dataUsage, long missedReason, int isPhoneAccountMigrationPending)1662 public static Uri addCall(CallerInfo ci, Context context, String number, 1663 int presentation, int callType, int features, 1664 PhoneAccountHandle accountHandle, 1665 long start, int duration, Long dataUsage, long missedReason, 1666 int isPhoneAccountMigrationPending) { 1667 return addCall(ci, context, number, "" /* postDialDigits */, "" /* viaNumber */, 1668 presentation, callType, features, accountHandle, start, duration, 1669 dataUsage, false /* addForAllUsers */, null /* userToBeInsertedTo */, 1670 false /* isRead */, Calls.BLOCK_REASON_NOT_BLOCKED /* callBlockReason */, 1671 null /* callScreeningAppName */, null /* callScreeningComponentName */, 1672 missedReason, isPhoneAccountMigrationPending); 1673 } 1674 1675 1676 /** 1677 * Adds a call to the call log. 1678 * 1679 * @param ci the CallerInfo object to get the target contact from. Can be null 1680 * if the contact is unknown. 1681 * @param context the context used to get the ContentResolver 1682 * @param number the phone number to be added to the calls db 1683 * @param viaNumber the secondary number that the incoming call received with. If the 1684 * call was received with the SIM assigned number, then this field must be ''. 1685 * @param presentation enum value from TelecomManager.PRESENTATION_xxx, which 1686 * is set by the network and denotes the number presenting rules for 1687 * "allowed", "payphone", "restricted" or "unknown" 1688 * @param callType enumerated values for "incoming", "outgoing", or "missed" 1689 * @param features features of the call (e.g. Video). 1690 * @param accountHandle The accountHandle object identifying the provider of the call 1691 * @param start time stamp for the call in milliseconds 1692 * @param duration call duration in seconds 1693 * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for 1694 * the call. 1695 * @param addForAllUsers If true, the call is added to the call log of all currently 1696 * running users. The caller must have the MANAGE_USERS permission if this is true. 1697 * @param userToBeInsertedTo {@link UserHandle} of user that the call is going to be 1698 * inserted to. null if it is inserted to the current user. The 1699 * value is ignored if @{link addForAllUsers} is true. 1700 * @param isPhoneAccountMigrationPending whether the PhoneAccountHandle ID need to migrate 1701 * @result The URI of the call log entry belonging to the user that made or received this 1702 * call. 1703 * {@hide} 1704 */ 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, long missedReason, int isPhoneAccountMigrationPending)1705 public static Uri addCall(CallerInfo ci, Context context, String number, 1706 String postDialDigits, String viaNumber, int presentation, int callType, 1707 int features, PhoneAccountHandle accountHandle, long start, int duration, 1708 Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo, 1709 long missedReason, int isPhoneAccountMigrationPending) { 1710 return addCall(ci, context, number, postDialDigits, viaNumber, presentation, callType, 1711 features, accountHandle, start, duration, dataUsage, addForAllUsers, 1712 userToBeInsertedTo, false /* isRead */ , Calls.BLOCK_REASON_NOT_BLOCKED 1713 /* callBlockReason */, null /* callScreeningAppName */, 1714 null /* callScreeningComponentName */, missedReason, 1715 isPhoneAccountMigrationPending); 1716 } 1717 1718 1719 /** 1720 * Adds a call to the call log. 1721 * 1722 * @param ci the CallerInfo object to get the target contact from. Can be null 1723 * if the contact is unknown. 1724 * @param context the context used to get the ContentResolver 1725 * @param number the phone number to be added to the calls db 1726 * @param postDialDigits the post-dial digits that were dialed after the number, 1727 * if it was outgoing. Otherwise it is ''. 1728 * @param viaNumber the secondary number that the incoming call received with. If the 1729 * call was received with the SIM assigned number, then this field must be ''. 1730 * @param presentation enum value from TelecomManager.PRESENTATION_xxx, which 1731 * is set by the network and denotes the number presenting rules for 1732 * "allowed", "payphone", "restricted" or "unknown" 1733 * @param callType enumerated values for "incoming", "outgoing", or "missed" 1734 * @param features features of the call (e.g. Video). 1735 * @param accountHandle The accountHandle object identifying the provider of the call 1736 * @param start time stamp for the call in milliseconds 1737 * @param duration call duration in seconds 1738 * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for 1739 * the call. 1740 * @param addForAllUsers If true, the call is added to the call log of all currently 1741 * running users. The caller must have the MANAGE_USERS permission if this is true. 1742 * @param userToBeInsertedTo {@link UserHandle} of user that the call is going to be 1743 * inserted to. null if it is inserted to the current user. The 1744 * value is ignored if @{link addForAllUsers} is true. 1745 * @param isRead Flag to show if the missed call log has been read by the user or not. 1746 * Used for call log restore of missed calls. 1747 * @param callBlockReason The reason why the call is blocked. 1748 * @param callScreeningAppName The call screening application name which block the call. 1749 * @param callScreeningComponentName The call screening component name which block the call. 1750 * @param missedReason The encoded missed information of the call. 1751 * @param isPhoneAccountMigrationPending whether the PhoneAccountHandle ID need to migrate 1752 * 1753 * @result The URI of the call log entry belonging to the user that made or received this 1754 * call. This could be of the shadow provider. Do not return it to non-system apps, 1755 * as they don't have permissions. 1756 * {@hide} 1757 */ 1758 @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, long missedReason, int isPhoneAccountMigrationPending)1759 public static Uri addCall(CallerInfo ci, Context context, String number, 1760 String postDialDigits, String viaNumber, int presentation, int callType, 1761 int features, PhoneAccountHandle accountHandle, long start, int duration, 1762 Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo, 1763 boolean isRead, int callBlockReason, CharSequence callScreeningAppName, 1764 String callScreeningComponentName, long missedReason, 1765 int isPhoneAccountMigrationPending) { 1766 AddCallParams.AddCallParametersBuilder builder = 1767 new AddCallParams.AddCallParametersBuilder(); 1768 builder.setCallerInfo(ci); 1769 builder.setNumber(number); 1770 builder.setPostDialDigits(postDialDigits); 1771 builder.setViaNumber(viaNumber); 1772 builder.setPresentation(presentation); 1773 builder.setCallType(callType); 1774 builder.setFeatures(features); 1775 builder.setAccountHandle(accountHandle); 1776 builder.setStart(start); 1777 builder.setDuration(duration); 1778 builder.setDataUsage(dataUsage == null ? Long.MIN_VALUE : dataUsage); 1779 builder.setAddForAllUsers(addForAllUsers); 1780 builder.setUserToBeInsertedTo(userToBeInsertedTo); 1781 builder.setIsRead(isRead); 1782 builder.setCallBlockReason(callBlockReason); 1783 builder.setCallScreeningAppName(callScreeningAppName); 1784 builder.setCallScreeningComponentName(callScreeningComponentName); 1785 builder.setMissedReason(missedReason); 1786 builder.setIsPhoneAccountMigrationPending(isPhoneAccountMigrationPending); 1787 1788 return addCall(context, builder.build()); 1789 } 1790 1791 /** 1792 * Adds a call to the call log, using the provided parameters 1793 * @result The URI of the call log entry belonging to the user that made or received this 1794 * call. This could be of the shadow provider. Do not return it to non-system apps, 1795 * as they don't have permissions. 1796 * @hide 1797 */ addCall( @onNull Context context, @NonNull AddCallParams params)1798 public static @NonNull Uri addCall( 1799 @NonNull Context context, @NonNull AddCallParams params) { 1800 if (VERBOSE_LOG) { 1801 Log.v(LOG_TAG, String.format("Add call: number=%s, user=%s, for all=%s", 1802 params.mNumber, params.mUserToBeInsertedTo, params.mAddForAllUsers)); 1803 } 1804 final ContentResolver resolver = context.getContentResolver(); 1805 1806 String accountAddress = getLogAccountAddress(context, params.mAccountHandle); 1807 1808 int numberPresentation = getLogNumberPresentation(params.mNumber, params.mPresentation); 1809 String name = (params.mCallerInfo != null) ? params.mCallerInfo.getName() : ""; 1810 if (numberPresentation != PRESENTATION_ALLOWED) { 1811 params.mNumber = ""; 1812 if (params.mCallerInfo != null) { 1813 name = ""; 1814 } 1815 } 1816 1817 // accountHandle information 1818 String accountComponentString = null; 1819 String accountId = null; 1820 if (params.mAccountHandle != null) { 1821 accountComponentString = params.mAccountHandle.getComponentName().flattenToString(); 1822 accountId = params.mAccountHandle.getId(); 1823 } 1824 1825 ContentValues values = new ContentValues(14); 1826 values.put(NUMBER, params.mNumber); 1827 values.put(POST_DIAL_DIGITS, params.mPostDialDigits); 1828 values.put(VIA_NUMBER, params.mViaNumber); 1829 values.put(NUMBER_PRESENTATION, Integer.valueOf(numberPresentation)); 1830 values.put(TYPE, Integer.valueOf(params.mCallType)); 1831 values.put(FEATURES, params.mFeatures); 1832 values.put(DATE, Long.valueOf(params.mStart)); 1833 values.put(DURATION, Long.valueOf(params.mDuration)); 1834 if (params.mDataUsage != Long.MIN_VALUE) { 1835 values.put(DATA_USAGE, params.mDataUsage); 1836 } 1837 values.put(PHONE_ACCOUNT_COMPONENT_NAME, accountComponentString); 1838 values.put(PHONE_ACCOUNT_ID, accountId); 1839 values.put(PHONE_ACCOUNT_ADDRESS, accountAddress); 1840 values.put(NEW, Integer.valueOf(1)); 1841 values.put(CACHED_NAME, name); 1842 values.put(ADD_FOR_ALL_USERS, params.mAddForAllUsers ? 1 : 0); 1843 1844 if (params.mCallType == MISSED_TYPE) { 1845 values.put(IS_READ, Integer.valueOf(params.mIsRead ? 1 : 0)); 1846 } 1847 1848 values.put(BLOCK_REASON, params.mCallBlockReason); 1849 values.put(CALL_SCREENING_APP_NAME, charSequenceToString(params.mCallScreeningAppName)); 1850 values.put(CALL_SCREENING_COMPONENT_NAME, params.mCallScreeningComponentName); 1851 values.put(MISSED_REASON, Long.valueOf(params.mMissedReason)); 1852 values.put(PRIORITY, params.mPriority); 1853 values.put(SUBJECT, params.mSubject); 1854 if (params.mPictureUri != null) { 1855 values.put(COMPOSER_PHOTO_URI, params.mPictureUri.toString()); 1856 } 1857 values.put(IS_PHONE_ACCOUNT_MIGRATION_PENDING, params.mIsPhoneAccountMigrationPending); 1858 if (Flags.businessCallComposer()) { 1859 values.put(IS_BUSINESS_CALL, Integer.valueOf(params.mIsBusinessCall ? 1 : 0)); 1860 values.put(ASSERTED_DISPLAY_NAME, params.mAssertedDisplayName); 1861 } 1862 if ((params.mCallerInfo != null) && (params.mCallerInfo.getContactId() > 0)) { 1863 // Update usage information for the number associated with the contact ID. 1864 // We need to use both the number and the ID for obtaining a data ID since other 1865 // contacts may have the same number. 1866 1867 final Cursor cursor; 1868 1869 // We should prefer normalized one (probably coming from 1870 // Phone.NORMALIZED_NUMBER column) first. If it isn't available try others. 1871 if (params.mCallerInfo.normalizedNumber != null) { 1872 final String normalizedPhoneNumber = params.mCallerInfo.normalizedNumber; 1873 cursor = resolver.query(Phone.CONTENT_URI, 1874 new String[] { Phone._ID }, 1875 Phone.CONTACT_ID + " =? AND " + Phone.NORMALIZED_NUMBER + " =?", 1876 new String[] { String.valueOf(params.mCallerInfo.getContactId()), 1877 normalizedPhoneNumber}, 1878 null); 1879 } else { 1880 final String phoneNumber = params.mCallerInfo.getPhoneNumber() != null 1881 ? params.mCallerInfo.getPhoneNumber() : params.mNumber; 1882 cursor = resolver.query( 1883 Uri.withAppendedPath(Callable.CONTENT_FILTER_URI, 1884 Uri.encode(phoneNumber)), 1885 new String[] { Phone._ID }, 1886 Phone.CONTACT_ID + " =?", 1887 new String[] { String.valueOf(params.mCallerInfo.getContactId()) }, 1888 null); 1889 } 1890 1891 if (cursor != null) { 1892 try { 1893 if (cursor.getCount() > 0 && cursor.moveToFirst()) { 1894 final String dataId = cursor.getString(0); 1895 updateDataUsageStatForData(resolver, dataId); 1896 if (params.mDuration >= MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS 1897 && params.mCallType == Calls.OUTGOING_TYPE 1898 && TextUtils.isEmpty(params.mCallerInfo.normalizedNumber)) { 1899 updateNormalizedNumber(context, resolver, dataId, params.mNumber); 1900 } 1901 } 1902 } finally { 1903 cursor.close(); 1904 } 1905 } 1906 } 1907 1908 /* 1909 Writing the calllog works in the following way: 1910 - All user entries 1911 - if user-0 is encrypted, insert to user-0's shadow only. 1912 (other users should also be encrypted, so nothing to do for other users.) 1913 - if user-0 is decrypted, insert to user-0's real provider, as well as 1914 all other users that are running and decrypted and should have calllog. 1915 1916 - Single user entry. 1917 - If the target user is encryted, insert to its shadow. 1918 - Otherwise insert to its real provider. 1919 1920 When the (real) calllog provider starts, it copies entries that it missed from 1921 elsewhere. 1922 - When user-0's (real) provider starts, it copies from user-0's shadow, and clears 1923 the shadow. 1924 1925 - When other users (real) providers start, unless it shouldn't have calllog entries, 1926 - Copy from the user's shadow, and clears the shadow. 1927 - Copy from user-0's entries that are FOR_ALL_USERS = 1. (and don't clear it.) 1928 */ 1929 1930 Uri result = null; 1931 1932 final UserManager userManager = context.getSystemService(UserManager.class); 1933 final int currentUserId = userManager.getProcessUserId(); 1934 1935 if (params.mAddForAllUsers) { 1936 if (userManager.isUserUnlocked(UserHandle.SYSTEM)) { 1937 // If the user is unlocked, insert to the location provider if a location is 1938 // provided. Do not store location if the device is still locked -- this 1939 // puts it into device-encrypted storage instead of credential-encrypted 1940 // storage. 1941 Uri locationUri = maybeInsertLocation(params, resolver, UserHandle.SYSTEM); 1942 if (locationUri != null) { 1943 values.put(Calls.LOCATION, locationUri.toString()); 1944 } 1945 } 1946 1947 // First, insert to the system user. 1948 final Uri uriForSystem = addEntryAndRemoveExpiredEntries( 1949 context, userManager, UserHandle.SYSTEM, values); 1950 if (uriForSystem == null 1951 || SHADOW_AUTHORITY.equals(uriForSystem.getAuthority())) { 1952 // This means the system user is still encrypted and the entry has inserted 1953 // into the shadow. This means other users are still all encrypted. 1954 // Nothing further to do; just return null. 1955 return null; 1956 } 1957 if (UserHandle.USER_SYSTEM == currentUserId) { 1958 result = uriForSystem; 1959 } 1960 1961 // Otherwise, insert to all other users that are running and unlocked. 1962 1963 final List<UserInfo> users = userManager.getAliveUsers(); 1964 1965 final int count = users.size(); 1966 for (int i = 0; i < count; i++) { 1967 final UserInfo userInfo = users.get(i); 1968 final UserHandle userHandle = userInfo.getUserHandle(); 1969 final int userId = userHandle.getIdentifier(); 1970 1971 if (userHandle.isSystem()) { 1972 // Already written. 1973 continue; 1974 } 1975 1976 if (!shouldHaveSharedCallLogEntries(context, userManager, userId)) { 1977 // Shouldn't have calllog entries. 1978 continue; 1979 } 1980 1981 // For other users, we write only when they're running *and* decrypted. 1982 // Other providers will copy from the system user's real provider, when they 1983 // start. 1984 if (userManager.isUserRunning(userHandle) 1985 && userManager.isUserUnlocked(userHandle)) { 1986 Uri locationUri = maybeInsertLocation(params, resolver, userHandle); 1987 if (locationUri != null) { 1988 values.put(Calls.LOCATION, locationUri.toString()); 1989 } else { 1990 values.put(Calls.LOCATION, (String) null); 1991 } 1992 final Uri uri = addEntryAndRemoveExpiredEntries(context, userManager, 1993 userHandle, values); 1994 if (userId == currentUserId) { 1995 result = uri; 1996 } 1997 } 1998 } 1999 } else { 2000 // Single-user entry. Just write to that user, assuming it's running. If the 2001 // user is encrypted, we write to the shadow calllog. 2002 final UserHandle targetUserHandle = params.mUserToBeInsertedTo != null 2003 ? params.mUserToBeInsertedTo 2004 : UserHandle.of(currentUserId); 2005 2006 if (userManager.isUserRunning(targetUserHandle) 2007 && userManager.isUserUnlocked(targetUserHandle)) { 2008 Uri locationUri = maybeInsertLocation(params, resolver, targetUserHandle); 2009 if (locationUri != null) { 2010 values.put(Calls.LOCATION, locationUri.toString()); 2011 } else { 2012 values.put(Calls.LOCATION, (String) null); 2013 } 2014 } 2015 2016 result = addEntryAndRemoveExpiredEntries(context, userManager, targetUserHandle, 2017 values); 2018 } 2019 return result; 2020 } 2021 charSequenceToString(CharSequence sequence)2022 private static String charSequenceToString(CharSequence sequence) { 2023 return sequence == null ? null : sequence.toString(); 2024 } 2025 2026 /** @hide */ shouldHaveSharedCallLogEntries(Context context, UserManager userManager, int userId)2027 public static boolean shouldHaveSharedCallLogEntries(Context context, 2028 UserManager userManager, int userId) { 2029 if (userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, 2030 UserHandle.of(userId))) { 2031 return false; 2032 } 2033 final UserInfo userInfo = userManager.getUserInfo(userId); 2034 return userInfo != null && !userInfo.isProfile(); 2035 } 2036 2037 /** 2038 * Query the call log database for the last dialed number. 2039 * @param context Used to get the content resolver. 2040 * @return The last phone number dialed (outgoing) or an empty 2041 * string if none exist yet. 2042 */ getLastOutgoingCall(Context context)2043 public static String getLastOutgoingCall(Context context) { 2044 final ContentResolver resolver = context.getContentResolver(); 2045 Cursor c = null; 2046 try { 2047 c = resolver.query( 2048 CONTENT_URI_LIMIT_1, 2049 new String[] {NUMBER}, 2050 TYPE + " = " + OUTGOING_TYPE, 2051 null, 2052 DEFAULT_SORT_ORDER); 2053 if (c == null || !c.moveToFirst()) { 2054 return ""; 2055 } 2056 return c.getString(0); 2057 } finally { 2058 if (c != null) c.close(); 2059 } 2060 } 2061 addEntryAndRemoveExpiredEntries(Context context, UserManager userManager, UserHandle user, ContentValues values)2062 private static Uri addEntryAndRemoveExpiredEntries(Context context, UserManager userManager, 2063 UserHandle user, ContentValues values) { 2064 final ContentResolver resolver = context.getContentResolver(); 2065 2066 // Since we're doing this operation on behalf of an app, we only 2067 // want to use the actual "unlocked" state. 2068 final Uri uri = ContentProvider.maybeAddUserId( 2069 userManager.isUserUnlocked(user) ? CONTENT_URI : SHADOW_CONTENT_URI, 2070 user.getIdentifier()); 2071 2072 Log.i(LOG_TAG, String.format(Locale.getDefault(), 2073 "addEntryAndRemoveExpiredEntries: provider uri=%s", uri)); 2074 2075 try { 2076 // When cleaning up the call log, try to delete older call long entries on a per 2077 // PhoneAccount basis first. There can be multiple ConnectionServices causing 2078 // the addition of entries in the call log. With the introduction of Self-Managed 2079 // ConnectionServices, we want to ensure that a misbehaving self-managed CS cannot 2080 // spam the call log with its own entries, causing entries from Telephony to be 2081 // removed. 2082 final Uri result = resolver.insert(uri, values); 2083 if (result != null) { 2084 String lastPathSegment = result.getLastPathSegment(); 2085 // When inserting into the call log, if ContentProvider#insert detect an appops 2086 // denial a non-null "silent rejection" URI is returned which ends in 0. 2087 // Example: content://call_log/calls/0 2088 // The 0 in the last part of the path indicates a fake call id of 0. 2089 // A denial when logging calls from the platform is bad; there is no other 2090 // logging to indicate that this has happened so we will check for that scenario 2091 // here and log a warning so we have a hint as to what is going on. 2092 if (lastPathSegment != null && lastPathSegment.equals("0")) { 2093 Log.w(LOG_TAG, "Failed to insert into call log due to appops denial;" 2094 + " resultUri=" + result); 2095 } 2096 } else { 2097 Log.w(LOG_TAG, "Failed to insert into call log; null result uri."); 2098 } 2099 2100 int numDeleted; 2101 final String phoneAccountId = 2102 values.containsKey(PHONE_ACCOUNT_ID) 2103 ? values.getAsString(PHONE_ACCOUNT_ID) : null; 2104 final String phoneAccountComponentName = 2105 values.containsKey(PHONE_ACCOUNT_COMPONENT_NAME) 2106 ? values.getAsString(PHONE_ACCOUNT_COMPONENT_NAME) : null; 2107 int maxCallLogSize = DEFAULT_MAX_CALL_LOG_SIZE; 2108 if (!TextUtils.isEmpty(phoneAccountId) 2109 && !TextUtils.isEmpty(phoneAccountComponentName)) { 2110 if (android.provider.Flags.allowConfigMaximumCallLogEntriesPerSim() 2111 && TELEPHONY_COMPONENT_NAME 2112 .flattenToString().equals(phoneAccountComponentName)) { 2113 maxCallLogSize = context.getResources().getInteger( 2114 com.android.internal.R.integer.config_maximumCallLogEntriesPerSim); 2115 } 2116 // Only purge entries for the same phone account. 2117 numDeleted = resolver.delete(uri, "_id IN " 2118 + "(SELECT _id FROM calls" 2119 + " WHERE " + PHONE_ACCOUNT_COMPONENT_NAME + " = ?" 2120 + " AND " + PHONE_ACCOUNT_ID + " = ?" 2121 + " ORDER BY " + DEFAULT_SORT_ORDER 2122 + " LIMIT -1 OFFSET " + maxCallLogSize + ")", 2123 new String[] { phoneAccountComponentName, phoneAccountId } 2124 ); 2125 } else { 2126 // No valid phone account specified, so default to the old behavior. 2127 numDeleted = resolver.delete(uri, "_id IN " 2128 + "(SELECT _id FROM calls ORDER BY " + DEFAULT_SORT_ORDER 2129 + " LIMIT -1 OFFSET " + maxCallLogSize + ")", null); 2130 } 2131 Log.i(LOG_TAG, "addEntry: cleaned up " + numDeleted + " old entries"); 2132 2133 return result; 2134 } catch (IllegalArgumentException e) { 2135 Log.e(LOG_TAG, "Failed to insert calllog", e); 2136 // Even though we make sure the target user is running and decrypted before calling 2137 // this method, there's a chance that the user just got shut down, in which case 2138 // we'll still get "IllegalArgumentException: Unknown URL content://call_log/calls". 2139 return null; 2140 } 2141 } 2142 maybeInsertLocation(AddCallParams params, ContentResolver resolver, UserHandle user)2143 private static Uri maybeInsertLocation(AddCallParams params, ContentResolver resolver, 2144 UserHandle user) { 2145 if (Double.isNaN(params.mLatitude) || Double.isNaN(params.mLongitude)) { 2146 return null; 2147 } 2148 ContentValues locationValues = new ContentValues(); 2149 locationValues.put(Locations.LATITUDE, params.mLatitude); 2150 locationValues.put(Locations.LONGITUDE, params.mLongitude); 2151 Uri locationUri = ContentProvider.maybeAddUserId(Locations.CONTENT_URI, 2152 user.getIdentifier()); 2153 try { 2154 return resolver.insert(locationUri, locationValues); 2155 } catch (SecurityException e) { 2156 // This can happen if the caller doesn't have location permissions. If that's the 2157 // case just skip the insertion. 2158 Log.w(LOG_TAG, "Skipping inserting location because caller lacks" 2159 + " ACCESS_FINE_LOCATION."); 2160 return null; 2161 } 2162 } 2163 updateDataUsageStatForData(ContentResolver resolver, String dataId)2164 private static void updateDataUsageStatForData(ContentResolver resolver, String dataId) { 2165 final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() 2166 .appendPath(dataId) 2167 .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, 2168 DataUsageFeedback.USAGE_TYPE_CALL) 2169 .build(); 2170 resolver.update(feedbackUri, new ContentValues(), null, null); 2171 } 2172 2173 /* 2174 * Update the normalized phone number for the given dataId in the ContactsProvider, based 2175 * on the user's current country. 2176 */ updateNormalizedNumber(Context context, ContentResolver resolver, String dataId, String number)2177 private static void updateNormalizedNumber(Context context, ContentResolver resolver, 2178 String dataId, String number) { 2179 if (TextUtils.isEmpty(number) || TextUtils.isEmpty(dataId)) { 2180 return; 2181 } 2182 final String countryIso = getCurrentCountryIso(context); 2183 if (TextUtils.isEmpty(countryIso)) { 2184 return; 2185 } 2186 final String normalizedNumber = PhoneNumberUtils.formatNumberToE164(number, countryIso); 2187 if (TextUtils.isEmpty(normalizedNumber)) { 2188 return; 2189 } 2190 final ContentValues values = new ContentValues(); 2191 values.put(Phone.NORMALIZED_NUMBER, normalizedNumber); 2192 resolver.update(Data.CONTENT_URI, values, Data._ID + "=?", new String[] {dataId}); 2193 } 2194 2195 /** 2196 * Remap network specified number presentation types 2197 * TelecomManager.PRESENTATION_xxx to calllog number presentation types 2198 * Calls.PRESENTATION_xxx, in order to insulate the persistent calllog 2199 * from any future radio changes. 2200 * If the number field is empty set the presentation type to Unknown. 2201 */ getLogNumberPresentation(String number, int presentation)2202 private static int getLogNumberPresentation(String number, int presentation) { 2203 if (presentation == TelecomManager.PRESENTATION_RESTRICTED) { 2204 return presentation; 2205 } 2206 2207 if (presentation == TelecomManager.PRESENTATION_PAYPHONE) { 2208 return presentation; 2209 } 2210 2211 if (presentation == TelecomManager.PRESENTATION_UNAVAILABLE) { 2212 return PRESENTATION_UNAVAILABLE; 2213 } 2214 2215 if (TextUtils.isEmpty(number) 2216 || presentation == TelecomManager.PRESENTATION_UNKNOWN) { 2217 return PRESENTATION_UNKNOWN; 2218 } 2219 2220 return PRESENTATION_ALLOWED; 2221 } 2222 getLogAccountAddress(Context context, PhoneAccountHandle accountHandle)2223 private static String getLogAccountAddress(Context context, 2224 PhoneAccountHandle accountHandle) { 2225 TelecomManager tm = null; 2226 try { 2227 tm = context.getSystemService(TelecomManager.class); 2228 } catch (UnsupportedOperationException e) { 2229 if (VERBOSE_LOG) { 2230 Log.v(LOG_TAG, "No TelecomManager found to get account address."); 2231 } 2232 } 2233 2234 String accountAddress = null; 2235 if (tm != null && accountHandle != null) { 2236 PhoneAccount account = tm.getPhoneAccount(accountHandle); 2237 if (account != null) { 2238 Uri address = account.getSubscriptionAddress(); 2239 if (address != null) { 2240 accountAddress = address.getSchemeSpecificPart(); 2241 } 2242 } 2243 } 2244 return accountAddress; 2245 } 2246 getCurrentCountryIso(Context context)2247 private static String getCurrentCountryIso(Context context) { 2248 String countryIso = null; 2249 final CountryDetector detector = (CountryDetector) context.getSystemService( 2250 Context.COUNTRY_DETECTOR); 2251 if (detector != null) { 2252 final Country country = detector.detectCountry(); 2253 if (country != null) { 2254 countryIso = country.getCountryIso(); 2255 } 2256 } 2257 return countryIso; 2258 } 2259 2260 /** 2261 * Check if the missedReason code indicate that the call was user missed or automatically 2262 * rejected by system. 2263 * 2264 * @param missedReason 2265 * The result is true if the call was user missed, false if the call was automatically 2266 * rejected by system. 2267 * 2268 * @hide 2269 */ isUserMissed(long missedReason)2270 public static boolean isUserMissed(long missedReason) { 2271 return missedReason >= (USER_MISSED_NO_ANSWER); 2272 } 2273 } 2274 2275 /** 2276 * Table that contains information on location data sent via call composer. 2277 * 2278 * All fields in this table require the {@link Manifest.permission#ACCESS_FINE_LOCATION} 2279 * permission for access. 2280 */ 2281 public static class Locations implements BaseColumns { Locations()2282 private Locations() {} 2283 /** 2284 * Authority for the locations content provider. 2285 */ 2286 public static final String AUTHORITY = "call_composer_locations"; 2287 2288 /** 2289 * Content type for the location table. 2290 */ 2291 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_composer_location"; 2292 2293 /** 2294 * Content type for the location entries. 2295 */ 2296 public static final String CONTENT_ITEM_TYPE = 2297 "vnd.android.cursor.item/call_composer_location"; 2298 2299 /** 2300 * The content URI for this table 2301 */ 2302 @NonNull 2303 public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); 2304 2305 /** 2306 * Latitude in degrees. See {@link android.location.Location#setLatitude(double)}. 2307 * <p>Type: REAL</p> 2308 */ 2309 public static final String LATITUDE = "latitude"; 2310 2311 /** 2312 * Longitude in degrees. See {@link android.location.Location#setLongitude(double)}. 2313 * <p>Type: REAL</p> 2314 */ 2315 public static final String LONGITUDE = "longitude"; 2316 } 2317 } 2318