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