1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.content; 18 19 import static android.provider.DocumentsContract.EXTRA_ORIENTATION; 20 21 import android.accounts.Account; 22 import android.annotation.IntDef; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.RequiresPermission; 26 import android.annotation.SuppressLint; 27 import android.annotation.SystemApi; 28 import android.annotation.TestApi; 29 import android.annotation.UserIdInt; 30 import android.app.ActivityManager; 31 import android.app.ActivityThread; 32 import android.app.AppGlobals; 33 import android.app.UriGrantsManager; 34 import android.compat.annotation.UnsupportedAppUsage; 35 import android.content.pm.PackageManager; 36 import android.content.pm.PackageManager.NameNotFoundException; 37 import android.content.res.AssetFileDescriptor; 38 import android.content.res.Resources; 39 import android.database.ContentObserver; 40 import android.database.CrossProcessCursorWrapper; 41 import android.database.Cursor; 42 import android.database.IContentObserver; 43 import android.graphics.Bitmap; 44 import android.graphics.ImageDecoder; 45 import android.graphics.ImageDecoder.ImageInfo; 46 import android.graphics.ImageDecoder.Source; 47 import android.graphics.Matrix; 48 import android.graphics.Point; 49 import android.graphics.drawable.Drawable; 50 import android.graphics.drawable.Icon; 51 import android.net.Uri; 52 import android.os.Bundle; 53 import android.os.CancellationSignal; 54 import android.os.DeadObjectException; 55 import android.os.IBinder; 56 import android.os.ICancellationSignal; 57 import android.os.OperationCanceledException; 58 import android.os.ParcelFileDescriptor; 59 import android.os.ParcelableException; 60 import android.os.RemoteCallback; 61 import android.os.RemoteException; 62 import android.os.ServiceManager; 63 import android.os.SystemClock; 64 import android.os.UserHandle; 65 import android.os.storage.StorageManager; 66 import android.system.Int32Ref; 67 import android.text.TextUtils; 68 import android.util.EventLog; 69 import android.util.Log; 70 import android.util.Size; 71 import android.util.SparseArray; 72 73 import com.android.internal.annotations.GuardedBy; 74 import com.android.internal.util.MimeIconUtils; 75 76 import dalvik.system.CloseGuard; 77 78 import java.io.File; 79 import java.io.FileInputStream; 80 import java.io.FileNotFoundException; 81 import java.io.IOException; 82 import java.io.InputStream; 83 import java.io.OutputStream; 84 import java.lang.annotation.Retention; 85 import java.lang.annotation.RetentionPolicy; 86 import java.util.ArrayList; 87 import java.util.Collection; 88 import java.util.List; 89 import java.util.Objects; 90 import java.util.Random; 91 import java.util.concurrent.atomic.AtomicBoolean; 92 93 /** 94 * This class provides applications access to the content model. 95 * 96 * <div class="special reference"> 97 * <h3>Developer Guides</h3> 98 * <p>For more information about using a ContentResolver with content providers, read the 99 * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> 100 * developer guide.</p> 101 * </div> 102 */ 103 public abstract class ContentResolver implements ContentInterface { 104 /** 105 * Enables logic that supports deprecation of {@code _data} columns, 106 * typically by replacing values with fake paths that the OS then offers to 107 * redirect to {@link #openFileDescriptor(Uri, String)}, which developers 108 * should be using directly. 109 * 110 * @hide 111 */ 112 public static final boolean DEPRECATE_DATA_COLUMNS = StorageManager.hasIsolatedStorage(); 113 114 /** 115 * Special filesystem path prefix which indicates that a path should be 116 * treated as a {@code content://} {@link Uri} when 117 * {@link #DEPRECATE_DATA_COLUMNS} is enabled. 118 * <p> 119 * The remainder of the path after this prefix is a 120 * {@link Uri#getSchemeSpecificPart()} value, which includes authority, path 121 * segments, and query parameters. 122 * 123 * @hide 124 */ 125 public static final String DEPRECATE_DATA_PREFIX = "/mnt/content/"; 126 127 /** 128 * @deprecated instead use 129 * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)} 130 */ 131 @Deprecated 132 public static final String SYNC_EXTRAS_ACCOUNT = "account"; 133 134 /** 135 * If this extra is set to true, the sync request will be scheduled 136 * at the front of the sync request queue and without any delay 137 */ 138 public static final String SYNC_EXTRAS_EXPEDITED = "expedited"; 139 140 /** 141 * If this extra is set to true, the sync request will be scheduled 142 * only when the device is plugged in. This is equivalent to calling 143 * setRequiresCharging(true) on {@link SyncRequest}. 144 */ 145 public static final String SYNC_EXTRAS_REQUIRE_CHARGING = "require_charging"; 146 147 /** 148 * @deprecated instead use 149 * {@link #SYNC_EXTRAS_MANUAL} 150 */ 151 @Deprecated 152 public static final String SYNC_EXTRAS_FORCE = "force"; 153 154 /** 155 * If this extra is set to true then the sync settings (like getSyncAutomatically()) 156 * are ignored by the sync scheduler. 157 */ 158 public static final String SYNC_EXTRAS_IGNORE_SETTINGS = "ignore_settings"; 159 160 /** 161 * If this extra is set to true then any backoffs for the initial attempt (e.g. due to retries) 162 * are ignored by the sync scheduler. If this request fails and gets rescheduled then the 163 * retries will still honor the backoff. 164 */ 165 public static final String SYNC_EXTRAS_IGNORE_BACKOFF = "ignore_backoff"; 166 167 /** 168 * If this extra is set to true then the request will not be retried if it fails. 169 */ 170 public static final String SYNC_EXTRAS_DO_NOT_RETRY = "do_not_retry"; 171 172 /** 173 * Setting this extra is the equivalent of setting both {@link #SYNC_EXTRAS_IGNORE_SETTINGS} 174 * and {@link #SYNC_EXTRAS_IGNORE_BACKOFF} 175 */ 176 public static final String SYNC_EXTRAS_MANUAL = "force"; 177 178 /** 179 * Indicates that this sync is intended to only upload local changes to the server. 180 * For example, this will be set to true if the sync is initiated by a call to 181 * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)} 182 */ 183 public static final String SYNC_EXTRAS_UPLOAD = "upload"; 184 185 /** 186 * Indicates that the sync adapter should proceed with the delete operations, 187 * even if it determines that there are too many. 188 * See {@link SyncResult#tooManyDeletions} 189 */ 190 public static final String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override"; 191 192 /** 193 * Indicates that the sync adapter should not proceed with the delete operations, 194 * if it determines that there are too many. 195 * See {@link SyncResult#tooManyDeletions} 196 */ 197 public static final String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS = "discard_deletions"; 198 199 /* Extensions to API. TODO: Not clear if we will keep these as public flags. */ 200 /** {@hide} User-specified flag for expected upload size. */ 201 public static final String SYNC_EXTRAS_EXPECTED_UPLOAD = "expected_upload"; 202 203 /** {@hide} User-specified flag for expected download size. */ 204 public static final String SYNC_EXTRAS_EXPECTED_DOWNLOAD = "expected_download"; 205 206 /** {@hide} Priority of this sync with respect to other syncs scheduled for this application. */ 207 public static final String SYNC_EXTRAS_PRIORITY = "sync_priority"; 208 209 /** {@hide} Flag to allow sync to occur on metered network. */ 210 public static final String SYNC_EXTRAS_DISALLOW_METERED = "allow_metered"; 211 212 /** 213 * {@hide} Integer extra containing a SyncExemption flag. 214 * 215 * Only the system and the shell user can set it. 216 * 217 * This extra is "virtual". Once passed to the system server, it'll be removed from the bundle. 218 */ 219 public static final String SYNC_VIRTUAL_EXTRAS_EXEMPTION_FLAG = "v_exemption"; 220 221 /** 222 * Set by the SyncManager to request that the SyncAdapter initialize itself for 223 * the given account/authority pair. One required initialization step is to 224 * ensure that {@link #setIsSyncable(android.accounts.Account, String, int)} has been 225 * called with a >= 0 value. When this flag is set the SyncAdapter does not need to 226 * do a full sync, though it is allowed to do so. 227 */ 228 public static final String SYNC_EXTRAS_INITIALIZE = "initialize"; 229 230 /** @hide */ 231 public static final Intent ACTION_SYNC_CONN_STATUS_CHANGED = 232 new Intent("com.android.sync.SYNC_CONN_STATUS_CHANGED"); 233 234 public static final String SCHEME_CONTENT = "content"; 235 public static final String SCHEME_ANDROID_RESOURCE = "android.resource"; 236 public static final String SCHEME_FILE = "file"; 237 238 /** 239 * An extra {@link Point} describing the optimal size for a requested image 240 * resource, in pixels. If a provider has multiple sizes of the image, it 241 * should return the image closest to this size. 242 * 243 * @see #openTypedAssetFileDescriptor(Uri, String, Bundle) 244 * @see #openTypedAssetFileDescriptor(Uri, String, Bundle, 245 * CancellationSignal) 246 */ 247 public static final String EXTRA_SIZE = "android.content.extra.SIZE"; 248 249 /** 250 * An extra boolean describing whether a particular provider supports refresh 251 * or not. If a provider supports refresh, it should include this key in its 252 * returned Cursor as part of its query call. 253 * 254 */ 255 public static final String EXTRA_REFRESH_SUPPORTED = "android.content.extra.REFRESH_SUPPORTED"; 256 257 /** 258 * Key for an SQL style selection string that may be present in the query Bundle argument 259 * passed to {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)} 260 * when called by a legacy client. 261 * 262 * <p>Clients should never include user supplied values directly in the selection string, 263 * as this presents an avenue for SQL injection attacks. In lieu of this, a client 264 * should use standard placeholder notation to represent values in a selection string, 265 * then supply a corresponding value in {@value #QUERY_ARG_SQL_SELECTION_ARGS}. 266 * 267 * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly 268 * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b> 269 * 270 * @see #QUERY_ARG_SORT_COLUMNS 271 * @see #QUERY_ARG_SORT_DIRECTION 272 * @see #QUERY_ARG_SORT_COLLATION 273 * @see #QUERY_ARG_SORT_LOCALE 274 */ 275 public static final String QUERY_ARG_SQL_SELECTION = "android:query-arg-sql-selection"; 276 277 /** 278 * Key for SQL selection string arguments list. 279 * 280 * <p>Clients should never include user supplied values directly in the selection string, 281 * as this presents an avenue for SQL injection attacks. In lieu of this, a client 282 * should use standard placeholder notation to represent values in a selection string, 283 * then supply a corresponding value in {@value #QUERY_ARG_SQL_SELECTION_ARGS}. 284 * 285 * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly 286 * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b> 287 * 288 * @see #QUERY_ARG_SORT_COLUMNS 289 * @see #QUERY_ARG_SORT_DIRECTION 290 * @see #QUERY_ARG_SORT_COLLATION 291 * @see #QUERY_ARG_SORT_LOCALE 292 */ 293 public static final String QUERY_ARG_SQL_SELECTION_ARGS = 294 "android:query-arg-sql-selection-args"; 295 296 /** 297 * Key for an SQL style sort string that may be present in the query Bundle argument 298 * passed to {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)} 299 * when called by a legacy client. 300 * 301 * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly 302 * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b> 303 * 304 * @see #QUERY_ARG_SORT_COLUMNS 305 * @see #QUERY_ARG_SORT_DIRECTION 306 * @see #QUERY_ARG_SORT_COLLATION 307 * @see #QUERY_ARG_SORT_LOCALE 308 */ 309 public static final String QUERY_ARG_SQL_SORT_ORDER = "android:query-arg-sql-sort-order"; 310 311 /** 312 * Key for an SQL style {@code GROUP BY} string that may be present in the 313 * query Bundle argument passed to 314 * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}. 315 * 316 * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly 317 * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b> 318 * 319 * @see #QUERY_ARG_GROUP_COLUMNS 320 */ 321 public static final String QUERY_ARG_SQL_GROUP_BY = "android:query-arg-sql-group-by"; 322 323 /** 324 * Key for an SQL style {@code HAVING} string that may be present in the 325 * query Bundle argument passed to 326 * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}. 327 * 328 * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly 329 * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b> 330 */ 331 public static final String QUERY_ARG_SQL_HAVING = "android:query-arg-sql-having"; 332 333 /** 334 * Key for an SQL style {@code LIMIT} string that may be present in the 335 * query Bundle argument passed to 336 * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}. 337 * 338 * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly 339 * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b> 340 * 341 * @see #QUERY_ARG_LIMIT 342 * @see #QUERY_ARG_OFFSET 343 */ 344 public static final String QUERY_ARG_SQL_LIMIT = "android:query-arg-sql-limit"; 345 346 /** 347 * Specifies the list of columns (stored as a {@code String[]}) against 348 * which to sort results. When first column values are identical, records 349 * are then sorted based on second column values, and so on. 350 * <p> 351 * Columns present in this list must also be included in the projection 352 * supplied to 353 * {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}. 354 * <p> 355 * Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher: 356 * <li>{@link ContentProvider} implementations: When preparing data in 357 * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}, 358 * if sort columns is reflected in the returned Cursor, it is strongly 359 * recommended that {@link #QUERY_ARG_SORT_COLUMNS} then be included in the 360 * array of honored arguments reflected in {@link Cursor} extras 361 * {@link Bundle} under {@link #EXTRA_HONORED_ARGS}. 362 * <li>When querying a provider, where no QUERY_ARG_SQL* otherwise exists in 363 * the arguments {@link Bundle}, the Content framework will attempt to 364 * synthesize an QUERY_ARG_SQL* argument using the corresponding 365 * QUERY_ARG_SORT* values. 366 */ 367 public static final String QUERY_ARG_SORT_COLUMNS = "android:query-arg-sort-columns"; 368 369 /** 370 * Specifies desired sort order. When unspecified a provider may provide a default 371 * sort direction, or choose to return unsorted results. 372 * 373 * <p>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher: 374 * 375 * <li>{@link ContentProvider} implementations: When preparing data in 376 * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}, if sort direction 377 * is reflected in the returned Cursor, it is strongly recommended that 378 * {@link #QUERY_ARG_SORT_DIRECTION} then be included in the array of honored arguments 379 * reflected in {@link Cursor} extras {@link Bundle} under {@link #EXTRA_HONORED_ARGS}. 380 * 381 * <li>When querying a provider, where no QUERY_ARG_SQL* otherwise exists in the 382 * arguments {@link Bundle}, the Content framework will attempt to synthesize 383 * a QUERY_ARG_SQL* argument using the corresponding QUERY_ARG_SORT* values. 384 * 385 * @see #QUERY_SORT_DIRECTION_ASCENDING 386 * @see #QUERY_SORT_DIRECTION_DESCENDING 387 */ 388 public static final String QUERY_ARG_SORT_DIRECTION = "android:query-arg-sort-direction"; 389 390 /** 391 * Allows client to specify a hint to the provider declaring which collation 392 * to use when sorting values. 393 * <p> 394 * Providers may support custom collators. When specifying a custom collator 395 * the value is determined by the Provider. 396 * <p> 397 * {@link ContentProvider} implementations: When preparing data in 398 * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}, 399 * if sort collation is reflected in the returned Cursor, it is strongly 400 * recommended that {@link #QUERY_ARG_SORT_COLLATION} then be included in 401 * the array of honored arguments reflected in {@link Cursor} extras 402 * {@link Bundle} under {@link #EXTRA_HONORED_ARGS}. 403 * <p> 404 * When querying a provider, where no QUERY_ARG_SQL* otherwise exists in the 405 * arguments {@link Bundle}, the Content framework will attempt to 406 * synthesize a QUERY_ARG_SQL* argument using the corresponding 407 * QUERY_ARG_SORT* values. 408 * 409 * @see java.text.Collator#PRIMARY 410 * @see java.text.Collator#SECONDARY 411 * @see java.text.Collator#TERTIARY 412 * @see java.text.Collator#IDENTICAL 413 */ 414 public static final String QUERY_ARG_SORT_COLLATION = "android:query-arg-sort-collation"; 415 416 /** 417 * Allows client to specify a hint to the provider declaring which locale to 418 * use when sorting values. 419 * <p> 420 * The value is defined as a RFC 3066 locale ID followed by an optional 421 * keyword list, which is the locale format used to configure ICU through 422 * classes like {@link android.icu.util.ULocale}. This supports requesting 423 * advanced sorting options, such as {@code de@collation=phonebook}, 424 * {@code zh@collation=pinyin}, etc. 425 * <p> 426 * {@link ContentProvider} implementations: When preparing data in 427 * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}, 428 * if sort locale is reflected in the returned Cursor, it is strongly 429 * recommended that {@link #QUERY_ARG_SORT_LOCALE} then be included in the 430 * array of honored arguments reflected in {@link Cursor} extras 431 * {@link Bundle} under {@link #EXTRA_HONORED_ARGS}. 432 * 433 * @see java.util.Locale#Locale(String) 434 * @see android.icu.util.ULocale#ULocale(String) 435 */ 436 public static final String QUERY_ARG_SORT_LOCALE = "android:query-arg-sort-locale"; 437 438 /** 439 * Specifies the list of columns (stored as a {@code String[]}) against 440 * which to group results. When column values are identical, multiple 441 * records are collapsed together into a single record. 442 * <p> 443 * Columns present in this list must also be included in the projection 444 * supplied to 445 * {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}. 446 * <p> 447 * Apps targeting {@link android.os.Build.VERSION_CODES#R} or higher: 448 * <li>{@link ContentProvider} implementations: When preparing data in 449 * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}, 450 * if group columns is reflected in the returned Cursor, it is strongly 451 * recommended that {@link #QUERY_ARG_SORT_COLUMNS} then be included in the 452 * array of honored arguments reflected in {@link Cursor} extras 453 * {@link Bundle} under {@link #EXTRA_HONORED_ARGS}. 454 * <li>When querying a provider, where no QUERY_ARG_SQL* otherwise exists in 455 * the arguments {@link Bundle}, the Content framework will attempt to 456 * synthesize an QUERY_ARG_SQL* argument using the corresponding 457 * QUERY_ARG_SORT* values. 458 */ 459 public static final String QUERY_ARG_GROUP_COLUMNS = "android:query-arg-group-columns"; 460 461 /** 462 * Allows provider to report back to client which query keys are honored in a Cursor. 463 * 464 * <p>Key identifying a {@code String[]} containing all QUERY_ARG_SORT* arguments 465 * honored by the provider. Include this in {@link Cursor} extras {@link Bundle} 466 * when any QUERY_ARG_SORT* value was honored during the preparation of the 467 * results {@link Cursor}. 468 * 469 * <p>If present, ALL honored arguments are enumerated in this extra’s payload. 470 * 471 * @see #QUERY_ARG_SORT_COLUMNS 472 * @see #QUERY_ARG_SORT_DIRECTION 473 * @see #QUERY_ARG_SORT_COLLATION 474 * @see #QUERY_ARG_SORT_LOCALE 475 * @see #QUERY_ARG_GROUP_COLUMNS 476 */ 477 public static final String EXTRA_HONORED_ARGS = "android.content.extra.HONORED_ARGS"; 478 479 /** @hide */ 480 @IntDef(flag = false, prefix = { "QUERY_SORT_DIRECTION_" }, value = { 481 QUERY_SORT_DIRECTION_ASCENDING, 482 QUERY_SORT_DIRECTION_DESCENDING 483 }) 484 @Retention(RetentionPolicy.SOURCE) 485 public @interface SortDirection {} 486 public static final int QUERY_SORT_DIRECTION_ASCENDING = 0; 487 public static final int QUERY_SORT_DIRECTION_DESCENDING = 1; 488 489 /** 490 * @see {@link java.text.Collector} for details on respective collation strength. 491 * @hide 492 */ 493 @IntDef(flag = false, value = { 494 java.text.Collator.PRIMARY, 495 java.text.Collator.SECONDARY, 496 java.text.Collator.TERTIARY, 497 java.text.Collator.IDENTICAL 498 }) 499 @Retention(RetentionPolicy.SOURCE) 500 public @interface QueryCollator {} 501 502 /** 503 * Specifies the offset row index within a Cursor. 504 */ 505 public static final String QUERY_ARG_OFFSET = "android:query-arg-offset"; 506 507 /** 508 * Specifies the max number of rows to include in a Cursor. 509 */ 510 public static final String QUERY_ARG_LIMIT = "android:query-arg-limit"; 511 512 /** 513 * Added to {@link Cursor} extras {@link Bundle} to indicate total row count of 514 * recordset when paging is supported. Providers must include this when 515 * implementing paging support. 516 * 517 * <p>A provider may return -1 that row count of the recordset is unknown. 518 * 519 * <p>Providers having returned -1 in a previous query are recommended to 520 * send content change notification once (if) full recordset size becomes 521 * known. 522 */ 523 public static final String EXTRA_TOTAL_COUNT = "android.content.extra.TOTAL_COUNT"; 524 525 /** 526 * This is the Android platform's base MIME type for a content: URI 527 * containing a Cursor of a single item. Applications should use this 528 * as the base type along with their own sub-type of their content: URIs 529 * that represent a particular item. For example, hypothetical IMAP email 530 * client may have a URI 531 * <code>content://com.company.provider.imap/inbox/1</code> for a particular 532 * message in the inbox, whose MIME type would be reported as 533 * <code>CURSOR_ITEM_BASE_TYPE + "/vnd.company.imap-msg"</code> 534 * 535 * <p>Compare with {@link #CURSOR_DIR_BASE_TYPE}. 536 */ 537 public static final String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item"; 538 539 /** 540 * This is the Android platform's base MIME type for a content: URI 541 * containing a Cursor of zero or more items. Applications should use this 542 * as the base type along with their own sub-type of their content: URIs 543 * that represent a directory of items. For example, hypothetical IMAP email 544 * client may have a URI 545 * <code>content://com.company.provider.imap/inbox</code> for all of the 546 * messages in its inbox, whose MIME type would be reported as 547 * <code>CURSOR_DIR_BASE_TYPE + "/vnd.company.imap-msg"</code> 548 * 549 * <p>Note how the base MIME type varies between this and 550 * {@link #CURSOR_ITEM_BASE_TYPE} depending on whether there is 551 * one single item or multiple items in the data set, while the sub-type 552 * remains the same because in either case the data structure contained 553 * in the cursor is the same. 554 */ 555 public static final String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir"; 556 557 /** 558 * This is the Android platform's generic MIME type to match any MIME 559 * type of the form "{@link #CURSOR_ITEM_BASE_TYPE}/{@code SUB_TYPE}". 560 * {@code SUB_TYPE} is the sub-type of the application-dependent 561 * content, e.g., "audio", "video", "playlist". 562 */ 563 public static final String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*"; 564 565 /** {@hide} */ 566 @Deprecated 567 public static final String MIME_TYPE_DEFAULT = ClipDescription.MIMETYPE_UNKNOWN; 568 569 /** @hide */ 570 @UnsupportedAppUsage 571 public static final int SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS = 1; 572 /** @hide */ 573 public static final int SYNC_ERROR_AUTHENTICATION = 2; 574 /** @hide */ 575 public static final int SYNC_ERROR_IO = 3; 576 /** @hide */ 577 public static final int SYNC_ERROR_PARSE = 4; 578 /** @hide */ 579 public static final int SYNC_ERROR_CONFLICT = 5; 580 /** @hide */ 581 public static final int SYNC_ERROR_TOO_MANY_DELETIONS = 6; 582 /** @hide */ 583 public static final int SYNC_ERROR_TOO_MANY_RETRIES = 7; 584 /** @hide */ 585 public static final int SYNC_ERROR_INTERNAL = 8; 586 587 private static final String[] SYNC_ERROR_NAMES = new String[] { 588 "already-in-progress", 589 "authentication-error", 590 "io-error", 591 "parse-error", 592 "conflict", 593 "too-many-deletions", 594 "too-many-retries", 595 "internal-error", 596 }; 597 598 /** @hide */ syncErrorToString(int error)599 public static String syncErrorToString(int error) { 600 if (error < 1 || error > SYNC_ERROR_NAMES.length) { 601 return String.valueOf(error); 602 } 603 return SYNC_ERROR_NAMES[error - 1]; 604 } 605 606 /** @hide */ syncErrorStringToInt(String error)607 public static int syncErrorStringToInt(String error) { 608 for (int i = 0, n = SYNC_ERROR_NAMES.length; i < n; i++) { 609 if (SYNC_ERROR_NAMES[i].equals(error)) { 610 return i + 1; 611 } 612 } 613 if (error != null) { 614 try { 615 return Integer.parseInt(error); 616 } catch (NumberFormatException e) { 617 Log.d(TAG, "error parsing sync error: " + error); 618 } 619 } 620 return 0; 621 } 622 623 public static final int SYNC_OBSERVER_TYPE_SETTINGS = 1<<0; 624 public static final int SYNC_OBSERVER_TYPE_PENDING = 1<<1; 625 public static final int SYNC_OBSERVER_TYPE_ACTIVE = 1<<2; 626 /** @hide */ 627 @UnsupportedAppUsage 628 public static final int SYNC_OBSERVER_TYPE_STATUS = 1<<3; 629 /** @hide */ 630 public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff; 631 632 /** @hide */ 633 @IntDef(flag = true, prefix = { "NOTIFY_" }, value = { 634 NOTIFY_SYNC_TO_NETWORK, 635 NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS, 636 NOTIFY_INSERT, 637 NOTIFY_UPDATE, 638 NOTIFY_DELETE 639 }) 640 @Retention(RetentionPolicy.SOURCE) 641 public @interface NotifyFlags {} 642 643 /** 644 * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: attempt to sync the change 645 * to the network. 646 */ 647 public static final int NOTIFY_SYNC_TO_NETWORK = 1<<0; 648 649 /** 650 * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: if set, this notification 651 * will be skipped if it is being delivered to the root URI of a ContentObserver that is 652 * using "notify for descendants." The purpose of this is to allow the provide to send 653 * a general notification of "something under X" changed that observers of that specific 654 * URI can receive, while also sending a specific URI under X. It would use this flag 655 * when sending the former, so that observers of "X and descendants" only see the latter. 656 */ 657 public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 1<<1; 658 659 /** 660 * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: typically set 661 * by a {@link ContentProvider} to indicate that this notification is the 662 * result of an {@link ContentProvider#insert} call. 663 * <p> 664 * Sending these detailed flags are optional, but providers are strongly 665 * recommended to send them. 666 */ 667 public static final int NOTIFY_INSERT = 1 << 2; 668 669 /** 670 * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: typically set 671 * by a {@link ContentProvider} to indicate that this notification is the 672 * result of an {@link ContentProvider#update} call. 673 * <p> 674 * Sending these detailed flags are optional, but providers are strongly 675 * recommended to send them. 676 */ 677 public static final int NOTIFY_UPDATE = 1 << 3; 678 679 /** 680 * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: typically set 681 * by a {@link ContentProvider} to indicate that this notification is the 682 * result of a {@link ContentProvider#delete} call. 683 * <p> 684 * Sending these detailed flags are optional, but providers are strongly 685 * recommended to send them. 686 */ 687 public static final int NOTIFY_DELETE = 1 << 4; 688 689 /** 690 * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: typically set 691 * by a {@link ContentProvider} to indicate that this notification should 692 * not be subject to any delays when dispatching to apps running in the 693 * background. 694 * <p> 695 * Using this flag may negatively impact system health and performance, and 696 * should be used sparingly. 697 * 698 * @hide 699 */ 700 public static final int NOTIFY_NO_DELAY = 1 << 15; 701 702 /** 703 * No exception, throttled by app standby normally. 704 * @hide 705 */ 706 public static final int SYNC_EXEMPTION_NONE = 0; 707 708 /** 709 * Exemption given to a sync request made by a foreground app (including 710 * PROCESS_STATE_IMPORTANT_FOREGROUND). 711 * 712 * At the schedule time, we promote the sync adapter app for a higher bucket: 713 * - If the device is not dozing (so the sync will start right away) 714 * promote to ACTIVE for 1 hour. 715 * - If the device is dozing (so the sync *won't* start right away), 716 * promote to WORKING_SET for 4 hours, so it'll get a higher chance to be started once the 717 * device comes out of doze. 718 * - When the sync actually starts, we promote the sync adapter app to ACTIVE for 10 minutes, 719 * so it can schedule and start more syncs without getting throttled, even when the first 720 * operation was canceled and now we're retrying. 721 * 722 * 723 * @hide 724 */ 725 public static final int SYNC_EXEMPTION_PROMOTE_BUCKET = 1; 726 727 /** 728 * In addition to {@link #SYNC_EXEMPTION_PROMOTE_BUCKET}, we put the sync adapter app in the 729 * temp whitelist for 10 minutes, so that even RARE apps can run syncs right away. 730 * @hide 731 */ 732 public static final int SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP = 2; 733 734 /** @hide */ 735 @IntDef(flag = false, prefix = { "SYNC_EXEMPTION_" }, value = { 736 SYNC_EXEMPTION_NONE, 737 SYNC_EXEMPTION_PROMOTE_BUCKET, 738 SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP, 739 }) 740 @Retention(RetentionPolicy.SOURCE) 741 public @interface SyncExemption {} 742 743 // Always log queries which take 500ms+; shorter queries are 744 // sampled accordingly. 745 private static final boolean ENABLE_CONTENT_SAMPLE = false; 746 private static final int SLOW_THRESHOLD_MILLIS = 500; 747 private final Random mRandom = new Random(); // guarded by itself 748 749 /** @hide */ 750 public static final String REMOTE_CALLBACK_RESULT = "result"; 751 752 /** @hide */ 753 public static final String REMOTE_CALLBACK_ERROR = "error"; 754 755 /** 756 * How long we wait for an attached process to publish its content providers 757 * before we decide it must be hung. 758 * @hide 759 */ 760 public static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS = 10 * 1000; 761 762 /** 763 * How long we wait for an provider to be published. Should be longer than 764 * {@link #CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS}. 765 * @hide 766 */ 767 public static final int CONTENT_PROVIDER_READY_TIMEOUT_MILLIS = 768 CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS + 10 * 1000; 769 770 // Timeout given a ContentProvider that has already been started and connected to. 771 private static final int CONTENT_PROVIDER_TIMEOUT_MILLIS = 3 * 1000; 772 773 // Should be >= {@link #CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS}, because that's how 774 // long ActivityManagerService is giving a content provider to get published if a new process 775 // needs to be started for that. 776 private static final int REMOTE_CONTENT_PROVIDER_TIMEOUT_MILLIS = 777 CONTENT_PROVIDER_READY_TIMEOUT_MILLIS + CONTENT_PROVIDER_TIMEOUT_MILLIS; 778 ContentResolver(@ullable Context context)779 public ContentResolver(@Nullable Context context) { 780 this(context, null); 781 } 782 783 /** {@hide} */ ContentResolver(@ullable Context context, @Nullable ContentInterface wrapped)784 public ContentResolver(@Nullable Context context, @Nullable ContentInterface wrapped) { 785 mContext = context != null ? context : ActivityThread.currentApplication(); 786 mPackageName = mContext.getOpPackageName(); 787 mAttributionTag = mContext.getAttributionTag(); 788 mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion; 789 mWrapped = wrapped; 790 } 791 792 /** {@hide} */ wrap(@onNull ContentInterface wrapped)793 public static @NonNull ContentResolver wrap(@NonNull ContentInterface wrapped) { 794 Objects.requireNonNull(wrapped); 795 796 return new ContentResolver(null, wrapped) { 797 @Override 798 public void unstableProviderDied(IContentProvider icp) { 799 throw new UnsupportedOperationException(); 800 } 801 @Override 802 public boolean releaseUnstableProvider(IContentProvider icp) { 803 throw new UnsupportedOperationException(); 804 } 805 @Override 806 public boolean releaseProvider(IContentProvider icp) { 807 throw new UnsupportedOperationException(); 808 } 809 @Override 810 protected IContentProvider acquireUnstableProvider(Context c, String name) { 811 throw new UnsupportedOperationException(); 812 } 813 @Override 814 protected IContentProvider acquireProvider(Context c, String name) { 815 throw new UnsupportedOperationException(); 816 } 817 }; 818 } 819 820 /** 821 * Create a {@link ContentResolver} instance that redirects all its methods 822 * to the given {@link ContentProvider}. 823 */ 824 public static @NonNull ContentResolver wrap(@NonNull ContentProvider wrapped) { 825 return wrap((ContentInterface) wrapped); 826 } 827 828 /** 829 * Create a {@link ContentResolver} instance that redirects all its methods 830 * to the given {@link ContentProviderClient}. 831 */ 832 public static @NonNull ContentResolver wrap(@NonNull ContentProviderClient wrapped) { 833 return wrap((ContentInterface) wrapped); 834 } 835 836 /** @hide */ 837 @UnsupportedAppUsage 838 protected abstract IContentProvider acquireProvider(Context c, String name); 839 840 /** 841 * Providing a default implementation of this, to avoid having to change a 842 * lot of other things, but implementations of ContentResolver should 843 * implement it. 844 * 845 * @hide 846 */ 847 @UnsupportedAppUsage 848 protected IContentProvider acquireExistingProvider(Context c, String name) { 849 return acquireProvider(c, name); 850 } 851 852 /** @hide */ 853 @UnsupportedAppUsage 854 public abstract boolean releaseProvider(IContentProvider icp); 855 /** @hide */ 856 @UnsupportedAppUsage 857 protected abstract IContentProvider acquireUnstableProvider(Context c, String name); 858 /** @hide */ 859 @UnsupportedAppUsage 860 public abstract boolean releaseUnstableProvider(IContentProvider icp); 861 /** @hide */ 862 @UnsupportedAppUsage 863 public abstract void unstableProviderDied(IContentProvider icp); 864 865 /** @hide */ 866 public void appNotRespondingViaProvider(IContentProvider icp) { 867 throw new UnsupportedOperationException("appNotRespondingViaProvider"); 868 } 869 870 /** 871 * Return the MIME type of the given content URL. 872 * 873 * @param url A Uri identifying content (either a list or specific type), 874 * using the content:// scheme. 875 * @return A MIME type for the content, or null if the URL is invalid or the type is unknown 876 */ 877 @Override 878 public final @Nullable String getType(@NonNull Uri url) { 879 Objects.requireNonNull(url, "url"); 880 881 try { 882 if (mWrapped != null) return mWrapped.getType(url); 883 } catch (RemoteException e) { 884 return null; 885 } 886 887 // XXX would like to have an acquireExistingUnstableProvider for this. 888 IContentProvider provider = acquireExistingProvider(url); 889 if (provider != null) { 890 try { 891 final StringResultListener resultListener = new StringResultListener(); 892 provider.getTypeAsync(url, new RemoteCallback(resultListener)); 893 resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS); 894 if (resultListener.exception != null) { 895 throw resultListener.exception; 896 } 897 return resultListener.result; 898 } catch (RemoteException e) { 899 // Arbitrary and not worth documenting, as Activity 900 // Manager will kill this process shortly anyway. 901 return null; 902 } catch (java.lang.Exception e) { 903 Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")"); 904 return null; 905 } finally { 906 releaseProvider(provider); 907 } 908 } 909 910 if (!SCHEME_CONTENT.equals(url.getScheme())) { 911 return null; 912 } 913 914 try { 915 final StringResultListener resultListener = new StringResultListener(); 916 ActivityManager.getService().getProviderMimeTypeAsync( 917 ContentProvider.getUriWithoutUserId(url), 918 resolveUserId(url), 919 new RemoteCallback(resultListener)); 920 resultListener.waitForResult(REMOTE_CONTENT_PROVIDER_TIMEOUT_MILLIS); 921 if (resultListener.exception != null) { 922 throw resultListener.exception; 923 } 924 return resultListener.result; 925 } catch (RemoteException e) { 926 // We just failed to send a oneway request to the System Server. Nothing to do. 927 return null; 928 } catch (java.lang.Exception e) { 929 Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")"); 930 return null; 931 } 932 } 933 934 private abstract static class ResultListener<T> implements RemoteCallback.OnResultListener { 935 @GuardedBy("this") 936 public boolean done; 937 938 @GuardedBy("this") 939 public T result; 940 941 @GuardedBy("this") 942 public RuntimeException exception; 943 944 @Override 945 public void onResult(Bundle result) { 946 synchronized (this) { 947 ParcelableException e = result.getParcelable(REMOTE_CALLBACK_ERROR); 948 if (e != null) { 949 Throwable t = e.getCause(); 950 if (t instanceof RuntimeException) { 951 this.exception = (RuntimeException) t; 952 } else { 953 this.exception = new RuntimeException(t); 954 } 955 } else { 956 this.result = getResultFromBundle(result); 957 } 958 done = true; 959 notifyAll(); 960 } 961 } 962 963 protected abstract T getResultFromBundle(Bundle result); 964 965 public void waitForResult(long timeout) { 966 synchronized (this) { 967 if (!done) { 968 try { 969 wait(timeout); 970 } catch (InterruptedException e) { 971 // Ignore 972 } 973 } 974 } 975 } 976 } 977 978 private static class StringResultListener extends ResultListener<String> { 979 @Override 980 protected String getResultFromBundle(Bundle result) { 981 return result.getString(REMOTE_CALLBACK_RESULT); 982 } 983 } 984 985 private static class UriResultListener extends ResultListener<Uri> { 986 @Override 987 protected Uri getResultFromBundle(Bundle result) { 988 return result.getParcelable(REMOTE_CALLBACK_RESULT); 989 } 990 } 991 992 /** 993 * Query for the possible MIME types for the representations the given 994 * content URL can be returned when opened as as stream with 995 * {@link #openTypedAssetFileDescriptor}. Note that the types here are 996 * not necessarily a superset of the type returned by {@link #getType} -- 997 * many content providers cannot return a raw stream for the structured 998 * data that they contain. 999 * 1000 * @param url A Uri identifying content (either a list or specific type), 1001 * using the content:// scheme. 1002 * @param mimeTypeFilter The desired MIME type. This may be a pattern, 1003 * such as */*, to query for all available MIME types that match the 1004 * pattern. 1005 * @return Returns an array of MIME type strings for all available 1006 * data streams that match the given mimeTypeFilter. If there are none, 1007 * null is returned. 1008 */ 1009 @Override 1010 public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter) { 1011 Objects.requireNonNull(url, "url"); 1012 Objects.requireNonNull(mimeTypeFilter, "mimeTypeFilter"); 1013 1014 try { 1015 if (mWrapped != null) return mWrapped.getStreamTypes(url, mimeTypeFilter); 1016 } catch (RemoteException e) { 1017 return null; 1018 } 1019 1020 IContentProvider provider = acquireProvider(url); 1021 if (provider == null) { 1022 return null; 1023 } 1024 1025 try { 1026 return provider.getStreamTypes(url, mimeTypeFilter); 1027 } catch (RemoteException e) { 1028 // Arbitrary and not worth documenting, as Activity 1029 // Manager will kill this process shortly anyway. 1030 return null; 1031 } finally { 1032 releaseProvider(provider); 1033 } 1034 } 1035 1036 /** 1037 * Query the given URI, returning a {@link Cursor} over the result set. 1038 * <p> 1039 * For best performance, the caller should follow these guidelines: 1040 * <ul> 1041 * <li>Provide an explicit projection, to prevent 1042 * reading data from storage that aren't going to be used.</li> 1043 * <li>Use question mark parameter markers such as 'phone=?' instead of 1044 * explicit values in the {@code selection} parameter, so that queries 1045 * that differ only by those values will be recognized as the same 1046 * for caching purposes.</li> 1047 * </ul> 1048 * </p> 1049 * 1050 * @param uri The URI, using the content:// scheme, for the content to 1051 * retrieve. 1052 * @param projection A list of which columns to return. Passing null will 1053 * return all columns, which is inefficient. 1054 * @param selection A filter declaring which rows to return, formatted as an 1055 * SQL WHERE clause (excluding the WHERE itself). Passing null will 1056 * return all rows for the given URI. 1057 * @param selectionArgs You may include ?s in selection, which will be 1058 * replaced by the values from selectionArgs, in the order that they 1059 * appear in the selection. The values will be bound as Strings. 1060 * @param sortOrder How to order the rows, formatted as an SQL ORDER BY 1061 * clause (excluding the ORDER BY itself). Passing null will use the 1062 * default sort order, which may be unordered. 1063 * @return A Cursor object, which is positioned before the first entry. May return 1064 * <code>null</code> if the underlying content provider returns <code>null</code>, 1065 * or if it crashes. 1066 * @see Cursor 1067 */ 1068 public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri, 1069 @Nullable String[] projection, @Nullable String selection, 1070 @Nullable String[] selectionArgs, @Nullable String sortOrder) { 1071 return query(uri, projection, selection, selectionArgs, sortOrder, null); 1072 } 1073 1074 /** 1075 * Query the given URI, returning a {@link Cursor} over the result set 1076 * with optional support for cancellation. 1077 * <p> 1078 * For best performance, the caller should follow these guidelines: 1079 * <ul> 1080 * <li>Provide an explicit projection, to prevent 1081 * reading data from storage that aren't going to be used.</li> 1082 * <li>Use question mark parameter markers such as 'phone=?' instead of 1083 * explicit values in the {@code selection} parameter, so that queries 1084 * that differ only by those values will be recognized as the same 1085 * for caching purposes.</li> 1086 * </ul> 1087 * </p> 1088 * 1089 * @param uri The URI, using the content:// scheme, for the content to 1090 * retrieve. 1091 * @param projection A list of which columns to return. Passing null will 1092 * return all columns, which is inefficient. 1093 * @param selection A filter declaring which rows to return, formatted as an 1094 * SQL WHERE clause (excluding the WHERE itself). Passing null will 1095 * return all rows for the given URI. 1096 * @param selectionArgs You may include ?s in selection, which will be 1097 * replaced by the values from selectionArgs, in the order that they 1098 * appear in the selection. The values will be bound as Strings. 1099 * @param sortOrder How to order the rows, formatted as an SQL ORDER BY 1100 * clause (excluding the ORDER BY itself). Passing null will use the 1101 * default sort order, which may be unordered. 1102 * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 1103 * If the operation is canceled, then {@link OperationCanceledException} will be thrown 1104 * when the query is executed. 1105 * @return A Cursor object, which is positioned before the first entry. May return 1106 * <code>null</code> if the underlying content provider returns <code>null</code>, 1107 * or if it crashes. 1108 * @see Cursor 1109 */ 1110 public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri, 1111 @Nullable String[] projection, @Nullable String selection, 1112 @Nullable String[] selectionArgs, @Nullable String sortOrder, 1113 @Nullable CancellationSignal cancellationSignal) { 1114 Bundle queryArgs = createSqlQueryBundle(selection, selectionArgs, sortOrder); 1115 return query(uri, projection, queryArgs, cancellationSignal); 1116 } 1117 1118 /** 1119 * Query the given URI, returning a {@link Cursor} over the result set 1120 * with support for cancellation. 1121 * 1122 * <p>For best performance, the caller should follow these guidelines: 1123 * 1124 * <li>Provide an explicit projection, to prevent reading data from storage 1125 * that aren't going to be used. 1126 * 1127 * Provider must identify which QUERY_ARG_SORT* arguments were honored during 1128 * the preparation of the result set by including the respective argument keys 1129 * in the {@link Cursor} extras {@link Bundle}. See {@link #EXTRA_HONORED_ARGS} 1130 * for details. 1131 * 1132 * @see #QUERY_ARG_SORT_COLUMNS 1133 * @see #QUERY_ARG_SORT_DIRECTION 1134 * @see #QUERY_ARG_SORT_COLLATION 1135 * 1136 * @param uri The URI, using the content:// scheme, for the content to 1137 * retrieve. 1138 * @param projection A list of which columns to return. Passing null will 1139 * return all columns, which is inefficient. 1140 * @param queryArgs A Bundle containing additional information necessary for 1141 * the operation. Arguments may include SQL style arguments, such 1142 * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that 1143 * the documentation for each individual provider will indicate 1144 * which arguments they support. 1145 * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 1146 * If the operation is canceled, then {@link OperationCanceledException} will be thrown 1147 * when the query is executed. 1148 * @return A Cursor object, which is positioned before the first entry. May return 1149 * <code>null</code> if the underlying content provider returns <code>null</code>, 1150 * or if it crashes. 1151 * @see Cursor 1152 */ 1153 @Override 1154 public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri, 1155 @Nullable String[] projection, @Nullable Bundle queryArgs, 1156 @Nullable CancellationSignal cancellationSignal) { 1157 Objects.requireNonNull(uri, "uri"); 1158 1159 try { 1160 if (mWrapped != null) { 1161 return mWrapped.query(uri, projection, queryArgs, cancellationSignal); 1162 } 1163 } catch (RemoteException e) { 1164 return null; 1165 } 1166 1167 IContentProvider unstableProvider = acquireUnstableProvider(uri); 1168 if (unstableProvider == null) { 1169 return null; 1170 } 1171 IContentProvider stableProvider = null; 1172 Cursor qCursor = null; 1173 try { 1174 long startTime = SystemClock.uptimeMillis(); 1175 1176 ICancellationSignal remoteCancellationSignal = null; 1177 if (cancellationSignal != null) { 1178 cancellationSignal.throwIfCanceled(); 1179 remoteCancellationSignal = unstableProvider.createCancellationSignal(); 1180 cancellationSignal.setRemote(remoteCancellationSignal); 1181 } 1182 try { 1183 qCursor = unstableProvider.query(mPackageName, mAttributionTag, uri, projection, 1184 queryArgs, remoteCancellationSignal); 1185 } catch (DeadObjectException e) { 1186 // The remote process has died... but we only hold an unstable 1187 // reference though, so we might recover!!! Let's try!!!! 1188 // This is exciting!!1!!1!!!!1 1189 unstableProviderDied(unstableProvider); 1190 stableProvider = acquireProvider(uri); 1191 if (stableProvider == null) { 1192 return null; 1193 } 1194 qCursor = stableProvider.query(mPackageName, mAttributionTag, uri, projection, 1195 queryArgs, remoteCancellationSignal); 1196 } 1197 if (qCursor == null) { 1198 return null; 1199 } 1200 1201 // Force query execution. Might fail and throw a runtime exception here. 1202 qCursor.getCount(); 1203 long durationMillis = SystemClock.uptimeMillis() - startTime; 1204 maybeLogQueryToEventLog(durationMillis, uri, projection, queryArgs); 1205 1206 // Wrap the cursor object into CursorWrapperInner object. 1207 final IContentProvider provider = (stableProvider != null) ? stableProvider 1208 : acquireProvider(uri); 1209 final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider); 1210 stableProvider = null; 1211 qCursor = null; 1212 return wrapper; 1213 } catch (RemoteException e) { 1214 // Arbitrary and not worth documenting, as Activity 1215 // Manager will kill this process shortly anyway. 1216 return null; 1217 } finally { 1218 if (qCursor != null) { 1219 qCursor.close(); 1220 } 1221 if (cancellationSignal != null) { 1222 cancellationSignal.setRemote(null); 1223 } 1224 if (unstableProvider != null) { 1225 releaseUnstableProvider(unstableProvider); 1226 } 1227 if (stableProvider != null) { 1228 releaseProvider(stableProvider); 1229 } 1230 } 1231 } 1232 1233 /** {@hide} */ 1234 public final @NonNull Uri canonicalizeOrElse(@NonNull Uri uri) { 1235 final Uri res = canonicalize(uri); 1236 return (res != null) ? res : uri; 1237 } 1238 1239 /** 1240 * Transform the given <var>url</var> to a canonical representation of 1241 * its referenced resource, which can be used across devices, persisted, 1242 * backed up and restored, etc. The returned Uri is still a fully capable 1243 * Uri for use with its content provider, allowing you to do all of the 1244 * same content provider operations as with the original Uri -- 1245 * {@link #query}, {@link #openInputStream(android.net.Uri)}, etc. The 1246 * only difference in behavior between the original and new Uris is that 1247 * the content provider may need to do some additional work at each call 1248 * using it to resolve it to the correct resource, especially if the 1249 * canonical Uri has been moved to a different environment. 1250 * 1251 * <p>If you are moving a canonical Uri between environments, you should 1252 * perform another call to {@link #canonicalize} with that original Uri to 1253 * re-canonicalize it for the current environment. Alternatively, you may 1254 * want to use {@link #uncanonicalize} to transform it to a non-canonical 1255 * Uri that works only in the current environment but potentially more 1256 * efficiently than the canonical representation.</p> 1257 * 1258 * @param url The {@link Uri} that is to be transformed to a canonical 1259 * representation. Like all resolver calls, the input can be either 1260 * a non-canonical or canonical Uri. 1261 * 1262 * @return Returns the official canonical representation of <var>url</var>, 1263 * or null if the content provider does not support a canonical representation 1264 * of the given Uri. Many providers may not support canonicalization of some 1265 * or all of their Uris. 1266 * 1267 * @see #uncanonicalize 1268 */ 1269 @Override 1270 public final @Nullable Uri canonicalize(@NonNull Uri url) { 1271 Objects.requireNonNull(url, "url"); 1272 1273 try { 1274 if (mWrapped != null) return mWrapped.canonicalize(url); 1275 } catch (RemoteException e) { 1276 return null; 1277 } 1278 1279 IContentProvider provider = acquireProvider(url); 1280 if (provider == null) { 1281 return null; 1282 } 1283 1284 try { 1285 final UriResultListener resultListener = new UriResultListener(); 1286 provider.canonicalizeAsync(mPackageName, mAttributionTag, url, 1287 new RemoteCallback(resultListener)); 1288 resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS); 1289 if (resultListener.exception != null) { 1290 throw resultListener.exception; 1291 } 1292 return resultListener.result; 1293 } catch (RemoteException e) { 1294 // Arbitrary and not worth documenting, as Activity 1295 // Manager will kill this process shortly anyway. 1296 return null; 1297 } finally { 1298 releaseProvider(provider); 1299 } 1300 } 1301 1302 /** 1303 * Given a canonical Uri previously generated by {@link #canonicalize}, convert 1304 * it to its local non-canonical form. This can be useful in some cases where 1305 * you know that you will only be using the Uri in the current environment and 1306 * want to avoid any possible overhead when using it with the content 1307 * provider or want to verify that the referenced data exists at all in the 1308 * new environment. 1309 * 1310 * @param url The canonical {@link Uri} that is to be convered back to its 1311 * non-canonical form. 1312 * 1313 * @return Returns the non-canonical representation of <var>url</var>. This will 1314 * return null if data identified by the canonical Uri can not be found in 1315 * the current environment; callers must always check for null and deal with 1316 * that by appropriately falling back to an alternative. 1317 * 1318 * @see #canonicalize 1319 */ 1320 @Override 1321 public final @Nullable Uri uncanonicalize(@NonNull Uri url) { 1322 Objects.requireNonNull(url, "url"); 1323 1324 try { 1325 if (mWrapped != null) return mWrapped.uncanonicalize(url); 1326 } catch (RemoteException e) { 1327 return null; 1328 } 1329 1330 IContentProvider provider = acquireProvider(url); 1331 if (provider == null) { 1332 return null; 1333 } 1334 1335 try { 1336 return provider.uncanonicalize(mPackageName, mAttributionTag, url); 1337 } catch (RemoteException e) { 1338 // Arbitrary and not worth documenting, as Activity 1339 // Manager will kill this process shortly anyway. 1340 return null; 1341 } finally { 1342 releaseProvider(provider); 1343 } 1344 } 1345 1346 /** 1347 * This allows clients to request an explicit refresh of content identified 1348 * by {@code uri}. 1349 * <p> 1350 * Client code should only invoke this method when there is a strong 1351 * indication (such as a user initiated pull to refresh gesture) that the 1352 * content is stale. 1353 * <p> 1354 * 1355 * @param url The Uri identifying the data to refresh. 1356 * @param extras Additional options from the client. The definitions of 1357 * these are specific to the content provider being called. 1358 * @param cancellationSignal A signal to cancel the operation in progress, 1359 * or {@code null} if none. For example, if you called refresh on 1360 * a particular uri, you should call 1361 * {@link CancellationSignal#throwIfCanceled()} to check whether 1362 * the client has canceled the refresh request. 1363 * @return true if the provider actually tried refreshing. 1364 */ 1365 @Override 1366 public final boolean refresh(@NonNull Uri url, @Nullable Bundle extras, 1367 @Nullable CancellationSignal cancellationSignal) { 1368 Objects.requireNonNull(url, "url"); 1369 1370 try { 1371 if (mWrapped != null) return mWrapped.refresh(url, extras, cancellationSignal); 1372 } catch (RemoteException e) { 1373 return false; 1374 } 1375 1376 IContentProvider provider = acquireProvider(url); 1377 if (provider == null) { 1378 return false; 1379 } 1380 1381 try { 1382 ICancellationSignal remoteCancellationSignal = null; 1383 if (cancellationSignal != null) { 1384 cancellationSignal.throwIfCanceled(); 1385 remoteCancellationSignal = provider.createCancellationSignal(); 1386 cancellationSignal.setRemote(remoteCancellationSignal); 1387 } 1388 return provider.refresh(mPackageName, mAttributionTag, url, extras, 1389 remoteCancellationSignal); 1390 } catch (RemoteException e) { 1391 // Arbitrary and not worth documenting, as Activity 1392 // Manager will kill this process shortly anyway. 1393 return false; 1394 } finally { 1395 releaseProvider(provider); 1396 } 1397 } 1398 1399 /** 1400 * Perform a detailed internal check on a {@link Uri} to determine if a UID 1401 * is able to access it with specific mode flags. 1402 * <p> 1403 * This method is typically used when the provider implements more dynamic 1404 * access controls that cannot be expressed with {@code <path-permission>} 1405 * style static rules. 1406 * <p> 1407 * Because validation of these dynamic access controls has significant 1408 * system health impact, this feature is only available to providers that 1409 * are built into the system. 1410 * 1411 * @param uri the {@link Uri} to perform an access check on. 1412 * @param uid the UID to check the permission for. 1413 * @param modeFlags the access flags to use for the access check, such as 1414 * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}. 1415 * @return {@link PackageManager#PERMISSION_GRANTED} if access is allowed, 1416 * otherwise {@link PackageManager#PERMISSION_DENIED}. 1417 * @hide 1418 */ 1419 @Override 1420 @SystemApi 1421 public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) { 1422 Objects.requireNonNull(uri, "uri"); 1423 1424 try { 1425 if (mWrapped != null) return mWrapped.checkUriPermission(uri, uid, modeFlags); 1426 } catch (RemoteException e) { 1427 return PackageManager.PERMISSION_DENIED; 1428 } 1429 1430 try (ContentProviderClient client = acquireUnstableContentProviderClient(uri)) { 1431 return client.checkUriPermission(uri, uid, modeFlags); 1432 } catch (RemoteException e) { 1433 return PackageManager.PERMISSION_DENIED; 1434 } 1435 } 1436 1437 /** 1438 * Open a stream on to the content associated with a content URI. If there 1439 * is no data associated with the URI, FileNotFoundException is thrown. 1440 * 1441 * <h5>Accepts the following URI schemes:</h5> 1442 * <ul> 1443 * <li>content ({@link #SCHEME_CONTENT})</li> 1444 * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li> 1445 * <li>file ({@link #SCHEME_FILE})</li> 1446 * </ul> 1447 * 1448 * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information 1449 * on these schemes. 1450 * 1451 * @param uri The desired URI. 1452 * @return InputStream or {@code null} if the provider recently crashed. 1453 * @throws FileNotFoundException if the provided URI could not be opened. 1454 * @see #openAssetFileDescriptor(Uri, String) 1455 */ 1456 public final @Nullable InputStream openInputStream(@NonNull Uri uri) 1457 throws FileNotFoundException { 1458 Objects.requireNonNull(uri, "uri"); 1459 String scheme = uri.getScheme(); 1460 if (SCHEME_ANDROID_RESOURCE.equals(scheme)) { 1461 // Note: left here to avoid breaking compatibility. May be removed 1462 // with sufficient testing. 1463 OpenResourceIdResult r = getResourceId(uri); 1464 try { 1465 InputStream stream = r.r.openRawResource(r.id); 1466 return stream; 1467 } catch (Resources.NotFoundException ex) { 1468 throw new FileNotFoundException("Resource does not exist: " + uri); 1469 } 1470 } else if (SCHEME_FILE.equals(scheme)) { 1471 // Note: left here to avoid breaking compatibility. May be removed 1472 // with sufficient testing. 1473 return new FileInputStream(uri.getPath()); 1474 } else { 1475 AssetFileDescriptor fd = openAssetFileDescriptor(uri, "r", null); 1476 try { 1477 return fd != null ? fd.createInputStream() : null; 1478 } catch (IOException e) { 1479 throw new FileNotFoundException("Unable to create stream"); 1480 } 1481 } 1482 } 1483 1484 /** 1485 * Synonym for {@link #openOutputStream(Uri, String) 1486 * openOutputStream(uri, "w")}. 1487 * 1488 * @param uri The desired URI. 1489 * @return an OutputStream or {@code null} if the provider recently crashed. 1490 * @throws FileNotFoundException if the provided URI could not be opened. 1491 */ 1492 public final @Nullable OutputStream openOutputStream(@NonNull Uri uri) 1493 throws FileNotFoundException { 1494 return openOutputStream(uri, "w"); 1495 } 1496 1497 /** 1498 * Open a stream on to the content associated with a content URI. If there 1499 * is no data associated with the URI, FileNotFoundException is thrown. 1500 * 1501 * <h5>Accepts the following URI schemes:</h5> 1502 * <ul> 1503 * <li>content ({@link #SCHEME_CONTENT})</li> 1504 * <li>file ({@link #SCHEME_FILE})</li> 1505 * </ul> 1506 * 1507 * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information 1508 * on these schemes. 1509 * 1510 * @param uri The desired URI. 1511 * @param mode May be "w", "wa", "rw", or "rwt". 1512 * @return an OutputStream or {@code null} if the provider recently crashed. 1513 * @throws FileNotFoundException if the provided URI could not be opened. 1514 * @see #openAssetFileDescriptor(Uri, String) 1515 */ 1516 public final @Nullable OutputStream openOutputStream(@NonNull Uri uri, @NonNull String mode) 1517 throws FileNotFoundException { 1518 AssetFileDescriptor fd = openAssetFileDescriptor(uri, mode, null); 1519 try { 1520 return fd != null ? fd.createOutputStream() : null; 1521 } catch (IOException e) { 1522 throw new FileNotFoundException("Unable to create stream"); 1523 } 1524 } 1525 1526 @Override 1527 public final @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode, 1528 @Nullable CancellationSignal signal) throws FileNotFoundException { 1529 try { 1530 if (mWrapped != null) return mWrapped.openFile(uri, mode, signal); 1531 } catch (RemoteException e) { 1532 return null; 1533 } 1534 1535 return openFileDescriptor(uri, mode, signal); 1536 } 1537 1538 /** 1539 * Open a raw file descriptor to access data under a URI. This 1540 * is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the 1541 * underlying {@link ContentProvider#openFile} 1542 * ContentProvider.openFile()} method, so will <em>not</em> work with 1543 * providers that return sub-sections of files. If at all possible, 1544 * you should use {@link #openAssetFileDescriptor(Uri, String)}. You 1545 * will receive a FileNotFoundException exception if the provider returns a 1546 * sub-section of a file. 1547 * 1548 * <h5>Accepts the following URI schemes:</h5> 1549 * <ul> 1550 * <li>content ({@link #SCHEME_CONTENT})</li> 1551 * <li>file ({@link #SCHEME_FILE})</li> 1552 * </ul> 1553 * 1554 * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information 1555 * on these schemes. 1556 * <p> 1557 * If opening with the exclusive "r" or "w" modes, the returned 1558 * ParcelFileDescriptor could be a pipe or socket pair to enable streaming 1559 * of data. Opening with the "rw" mode implies a file on disk that supports 1560 * seeking. If possible, always use an exclusive mode to give the underlying 1561 * {@link ContentProvider} the most flexibility. 1562 * <p> 1563 * If you are writing a file, and need to communicate an error to the 1564 * provider, use {@link ParcelFileDescriptor#closeWithError(String)}. 1565 * 1566 * @param uri The desired URI to open. 1567 * @param mode The file mode to use, as per {@link ContentProvider#openFile 1568 * ContentProvider.openFile}. 1569 * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the 1570 * provider recently crashed. You own this descriptor and are responsible for closing it 1571 * when done. 1572 * @throws FileNotFoundException Throws FileNotFoundException if no 1573 * file exists under the URI or the mode is invalid. 1574 * @see #openAssetFileDescriptor(Uri, String) 1575 */ 1576 public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri, 1577 @NonNull String mode) throws FileNotFoundException { 1578 return openFileDescriptor(uri, mode, null); 1579 } 1580 1581 /** 1582 * Open a raw file descriptor to access data under a URI. This 1583 * is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the 1584 * underlying {@link ContentProvider#openFile} 1585 * ContentProvider.openFile()} method, so will <em>not</em> work with 1586 * providers that return sub-sections of files. If at all possible, 1587 * you should use {@link #openAssetFileDescriptor(Uri, String)}. You 1588 * will receive a FileNotFoundException exception if the provider returns a 1589 * sub-section of a file. 1590 * 1591 * <h5>Accepts the following URI schemes:</h5> 1592 * <ul> 1593 * <li>content ({@link #SCHEME_CONTENT})</li> 1594 * <li>file ({@link #SCHEME_FILE})</li> 1595 * </ul> 1596 * 1597 * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information 1598 * on these schemes. 1599 * <p> 1600 * If opening with the exclusive "r" or "w" modes, the returned 1601 * ParcelFileDescriptor could be a pipe or socket pair to enable streaming 1602 * of data. Opening with the "rw" mode implies a file on disk that supports 1603 * seeking. If possible, always use an exclusive mode to give the underlying 1604 * {@link ContentProvider} the most flexibility. 1605 * <p> 1606 * If you are writing a file, and need to communicate an error to the 1607 * provider, use {@link ParcelFileDescriptor#closeWithError(String)}. 1608 * 1609 * @param uri The desired URI to open. 1610 * @param mode The file mode to use, as per {@link ContentProvider#openFile 1611 * ContentProvider.openFile}. 1612 * @param cancellationSignal A signal to cancel the operation in progress, 1613 * or null if none. If the operation is canceled, then 1614 * {@link OperationCanceledException} will be thrown. 1615 * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the 1616 * provider recently crashed. You own this descriptor and are responsible for closing it 1617 * when done. 1618 * @throws FileNotFoundException Throws FileNotFoundException if no 1619 * file exists under the URI or the mode is invalid. 1620 * @see #openAssetFileDescriptor(Uri, String) 1621 */ 1622 public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri, 1623 @NonNull String mode, @Nullable CancellationSignal cancellationSignal) 1624 throws FileNotFoundException { 1625 try { 1626 if (mWrapped != null) return mWrapped.openFile(uri, mode, cancellationSignal); 1627 } catch (RemoteException e) { 1628 return null; 1629 } 1630 1631 AssetFileDescriptor afd = openAssetFileDescriptor(uri, mode, cancellationSignal); 1632 if (afd == null) { 1633 return null; 1634 } 1635 1636 if (afd.getDeclaredLength() < 0) { 1637 // This is a full file! 1638 return afd.getParcelFileDescriptor(); 1639 } 1640 1641 // Client can't handle a sub-section of a file, so close what 1642 // we got and bail with an exception. 1643 try { 1644 afd.close(); 1645 } catch (IOException e) { 1646 } 1647 1648 throw new FileNotFoundException("Not a whole file"); 1649 } 1650 1651 @Override 1652 public final @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode, 1653 @Nullable CancellationSignal signal) throws FileNotFoundException { 1654 try { 1655 if (mWrapped != null) return mWrapped.openAssetFile(uri, mode, signal); 1656 } catch (RemoteException e) { 1657 return null; 1658 } 1659 1660 return openAssetFileDescriptor(uri, mode, signal); 1661 } 1662 1663 /** 1664 * Open a raw file descriptor to access data under a URI. This 1665 * interacts with the underlying {@link ContentProvider#openAssetFile} 1666 * method of the provider associated with the given URI, to retrieve any file stored there. 1667 * 1668 * <h5>Accepts the following URI schemes:</h5> 1669 * <ul> 1670 * <li>content ({@link #SCHEME_CONTENT})</li> 1671 * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li> 1672 * <li>file ({@link #SCHEME_FILE})</li> 1673 * </ul> 1674 * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5> 1675 * <p> 1676 * A Uri object can be used to reference a resource in an APK file. The 1677 * Uri should be one of the following formats: 1678 * <ul> 1679 * <li><code>android.resource://package_name/id_number</code><br/> 1680 * <code>package_name</code> is your package name as listed in your AndroidManifest.xml. 1681 * For example <code>com.example.myapp</code><br/> 1682 * <code>id_number</code> is the int form of the ID.<br/> 1683 * The easiest way to construct this form is 1684 * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre> 1685 * </li> 1686 * <li><code>android.resource://package_name/type/name</code><br/> 1687 * <code>package_name</code> is your package name as listed in your AndroidManifest.xml. 1688 * For example <code>com.example.myapp</code><br/> 1689 * <code>type</code> is the string form of the resource type. For example, <code>raw</code> 1690 * or <code>drawable</code>. 1691 * <code>name</code> is the string form of the resource name. That is, whatever the file 1692 * name was in your res directory, without the type extension. 1693 * The easiest way to construct this form is 1694 * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre> 1695 * </li> 1696 * </ul> 1697 * 1698 * <p>Note that if this function is called for read-only input (mode is "r") 1699 * on a content: URI, it will instead call {@link #openTypedAssetFileDescriptor} 1700 * for you with a MIME type of "*/*". This allows such callers to benefit 1701 * from any built-in data conversion that a provider implements. 1702 * 1703 * @param uri The desired URI to open. 1704 * @param mode The file mode to use, as per {@link ContentProvider#openAssetFile 1705 * ContentProvider.openAssetFile}. 1706 * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the 1707 * provider recently crashed. You own this descriptor and are responsible for closing it 1708 * when done. 1709 * @throws FileNotFoundException Throws FileNotFoundException of no 1710 * file exists under the URI or the mode is invalid. 1711 */ 1712 public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri, 1713 @NonNull String mode) throws FileNotFoundException { 1714 return openAssetFileDescriptor(uri, mode, null); 1715 } 1716 1717 /** 1718 * Open a raw file descriptor to access data under a URI. This 1719 * interacts with the underlying {@link ContentProvider#openAssetFile} 1720 * method of the provider associated with the given URI, to retrieve any file stored there. 1721 * 1722 * <h5>Accepts the following URI schemes:</h5> 1723 * <ul> 1724 * <li>content ({@link #SCHEME_CONTENT})</li> 1725 * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li> 1726 * <li>file ({@link #SCHEME_FILE})</li> 1727 * </ul> 1728 * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5> 1729 * <p> 1730 * A Uri object can be used to reference a resource in an APK file. The 1731 * Uri should be one of the following formats: 1732 * <ul> 1733 * <li><code>android.resource://package_name/id_number</code><br/> 1734 * <code>package_name</code> is your package name as listed in your AndroidManifest.xml. 1735 * For example <code>com.example.myapp</code><br/> 1736 * <code>id_number</code> is the int form of the ID.<br/> 1737 * The easiest way to construct this form is 1738 * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre> 1739 * </li> 1740 * <li><code>android.resource://package_name/type/name</code><br/> 1741 * <code>package_name</code> is your package name as listed in your AndroidManifest.xml. 1742 * For example <code>com.example.myapp</code><br/> 1743 * <code>type</code> is the string form of the resource type. For example, <code>raw</code> 1744 * or <code>drawable</code>. 1745 * <code>name</code> is the string form of the resource name. That is, whatever the file 1746 * name was in your res directory, without the type extension. 1747 * The easiest way to construct this form is 1748 * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre> 1749 * </li> 1750 * </ul> 1751 * 1752 * <p>Note that if this function is called for read-only input (mode is "r") 1753 * on a content: URI, it will instead call {@link #openTypedAssetFileDescriptor} 1754 * for you with a MIME type of "*/*". This allows such callers to benefit 1755 * from any built-in data conversion that a provider implements. 1756 * 1757 * @param uri The desired URI to open. 1758 * @param mode The file mode to use, as per {@link ContentProvider#openAssetFile 1759 * ContentProvider.openAssetFile}. 1760 * @param cancellationSignal A signal to cancel the operation in progress, or null if 1761 * none. If the operation is canceled, then 1762 * {@link OperationCanceledException} will be thrown. 1763 * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the 1764 * provider recently crashed. You own this descriptor and are responsible for closing it 1765 * when done. 1766 * @throws FileNotFoundException Throws FileNotFoundException of no 1767 * file exists under the URI or the mode is invalid. 1768 */ 1769 public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri, 1770 @NonNull String mode, @Nullable CancellationSignal cancellationSignal) 1771 throws FileNotFoundException { 1772 Objects.requireNonNull(uri, "uri"); 1773 Objects.requireNonNull(mode, "mode"); 1774 1775 try { 1776 if (mWrapped != null) return mWrapped.openAssetFile(uri, mode, cancellationSignal); 1777 } catch (RemoteException e) { 1778 return null; 1779 } 1780 1781 String scheme = uri.getScheme(); 1782 if (SCHEME_ANDROID_RESOURCE.equals(scheme)) { 1783 if (!"r".equals(mode)) { 1784 throw new FileNotFoundException("Can't write resources: " + uri); 1785 } 1786 OpenResourceIdResult r = getResourceId(uri); 1787 try { 1788 return r.r.openRawResourceFd(r.id); 1789 } catch (Resources.NotFoundException ex) { 1790 throw new FileNotFoundException("Resource does not exist: " + uri); 1791 } 1792 } else if (SCHEME_FILE.equals(scheme)) { 1793 ParcelFileDescriptor pfd = ParcelFileDescriptor.open( 1794 new File(uri.getPath()), ParcelFileDescriptor.parseMode(mode)); 1795 return new AssetFileDescriptor(pfd, 0, -1); 1796 } else { 1797 if ("r".equals(mode)) { 1798 return openTypedAssetFileDescriptor(uri, "*/*", null, cancellationSignal); 1799 } else { 1800 IContentProvider unstableProvider = acquireUnstableProvider(uri); 1801 if (unstableProvider == null) { 1802 throw new FileNotFoundException("No content provider: " + uri); 1803 } 1804 IContentProvider stableProvider = null; 1805 AssetFileDescriptor fd = null; 1806 1807 try { 1808 ICancellationSignal remoteCancellationSignal = null; 1809 if (cancellationSignal != null) { 1810 cancellationSignal.throwIfCanceled(); 1811 remoteCancellationSignal = unstableProvider.createCancellationSignal(); 1812 cancellationSignal.setRemote(remoteCancellationSignal); 1813 } 1814 1815 try { 1816 fd = unstableProvider.openAssetFile( 1817 mPackageName, mAttributionTag, uri, mode, 1818 remoteCancellationSignal); 1819 if (fd == null) { 1820 // The provider will be released by the finally{} clause 1821 return null; 1822 } 1823 } catch (DeadObjectException e) { 1824 // The remote process has died... but we only hold an unstable 1825 // reference though, so we might recover!!! Let's try!!!! 1826 // This is exciting!!1!!1!!!!1 1827 unstableProviderDied(unstableProvider); 1828 stableProvider = acquireProvider(uri); 1829 if (stableProvider == null) { 1830 throw new FileNotFoundException("No content provider: " + uri); 1831 } 1832 fd = stableProvider.openAssetFile( 1833 mPackageName, mAttributionTag, uri, mode, remoteCancellationSignal); 1834 if (fd == null) { 1835 // The provider will be released by the finally{} clause 1836 return null; 1837 } 1838 } 1839 1840 if (stableProvider == null) { 1841 stableProvider = acquireProvider(uri); 1842 } 1843 releaseUnstableProvider(unstableProvider); 1844 unstableProvider = null; 1845 ParcelFileDescriptor pfd = new ParcelFileDescriptorInner( 1846 fd.getParcelFileDescriptor(), stableProvider); 1847 1848 // Success! Don't release the provider when exiting, let 1849 // ParcelFileDescriptorInner do that when it is closed. 1850 stableProvider = null; 1851 1852 return new AssetFileDescriptor(pfd, fd.getStartOffset(), 1853 fd.getDeclaredLength()); 1854 1855 } catch (RemoteException e) { 1856 // Whatever, whatever, we'll go away. 1857 throw new FileNotFoundException( 1858 "Failed opening content provider: " + uri); 1859 } catch (FileNotFoundException e) { 1860 throw e; 1861 } finally { 1862 if (cancellationSignal != null) { 1863 cancellationSignal.setRemote(null); 1864 } 1865 if (stableProvider != null) { 1866 releaseProvider(stableProvider); 1867 } 1868 if (unstableProvider != null) { 1869 releaseUnstableProvider(unstableProvider); 1870 } 1871 } 1872 } 1873 } 1874 } 1875 1876 @Override 1877 public final @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri, 1878 @NonNull String mimeTypeFilter, @Nullable Bundle opts, 1879 @Nullable CancellationSignal signal) throws FileNotFoundException { 1880 try { 1881 if (mWrapped != null) { 1882 return mWrapped.openTypedAssetFile(uri, mimeTypeFilter, opts, signal); 1883 } 1884 } catch (RemoteException e) { 1885 return null; 1886 } 1887 1888 return openTypedAssetFileDescriptor(uri, mimeTypeFilter, opts, signal); 1889 } 1890 1891 /** 1892 * Open a raw file descriptor to access (potentially type transformed) 1893 * data from a "content:" URI. This interacts with the underlying 1894 * {@link ContentProvider#openTypedAssetFile} method of the provider 1895 * associated with the given URI, to retrieve retrieve any appropriate 1896 * data stream for the data stored there. 1897 * 1898 * <p>Unlike {@link #openAssetFileDescriptor}, this function only works 1899 * with "content:" URIs, because content providers are the only facility 1900 * with an associated MIME type to ensure that the returned data stream 1901 * is of the desired type. 1902 * 1903 * <p>All text/* streams are encoded in UTF-8. 1904 * 1905 * @param uri The desired URI to open. 1906 * @param mimeType The desired MIME type of the returned data. This can 1907 * be a pattern such as */*, which will allow the content provider to 1908 * select a type, though there is no way for you to determine what type 1909 * it is returning. 1910 * @param opts Additional provider-dependent options. 1911 * @return Returns a new ParcelFileDescriptor from which you can read the 1912 * data stream from the provider or {@code null} if the provider recently crashed. 1913 * Note that this may be a pipe, meaning you can't seek in it. The only seek you 1914 * should do is if the AssetFileDescriptor contains an offset, to move to that offset before 1915 * reading. You own this descriptor and are responsible for closing it when done. 1916 * @throws FileNotFoundException Throws FileNotFoundException of no 1917 * data of the desired type exists under the URI. 1918 */ 1919 public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri, 1920 @NonNull String mimeType, @Nullable Bundle opts) throws FileNotFoundException { 1921 return openTypedAssetFileDescriptor(uri, mimeType, opts, null); 1922 } 1923 1924 /** 1925 * Open a raw file descriptor to access (potentially type transformed) 1926 * data from a "content:" URI. This interacts with the underlying 1927 * {@link ContentProvider#openTypedAssetFile} method of the provider 1928 * associated with the given URI, to retrieve retrieve any appropriate 1929 * data stream for the data stored there. 1930 * 1931 * <p>Unlike {@link #openAssetFileDescriptor}, this function only works 1932 * with "content:" URIs, because content providers are the only facility 1933 * with an associated MIME type to ensure that the returned data stream 1934 * is of the desired type. 1935 * 1936 * <p>All text/* streams are encoded in UTF-8. 1937 * 1938 * @param uri The desired URI to open. 1939 * @param mimeType The desired MIME type of the returned data. This can 1940 * be a pattern such as */*, which will allow the content provider to 1941 * select a type, though there is no way for you to determine what type 1942 * it is returning. 1943 * @param opts Additional provider-dependent options. 1944 * @param cancellationSignal A signal to cancel the operation in progress, 1945 * or null if none. If the operation is canceled, then 1946 * {@link OperationCanceledException} will be thrown. 1947 * @return Returns a new ParcelFileDescriptor from which you can read the 1948 * data stream from the provider or {@code null} if the provider recently crashed. 1949 * Note that this may be a pipe, meaning you can't seek in it. The only seek you 1950 * should do is if the AssetFileDescriptor contains an offset, to move to that offset before 1951 * reading. You own this descriptor and are responsible for closing it when done. 1952 * @throws FileNotFoundException Throws FileNotFoundException of no 1953 * data of the desired type exists under the URI. 1954 */ 1955 public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri, 1956 @NonNull String mimeType, @Nullable Bundle opts, 1957 @Nullable CancellationSignal cancellationSignal) throws FileNotFoundException { 1958 Objects.requireNonNull(uri, "uri"); 1959 Objects.requireNonNull(mimeType, "mimeType"); 1960 1961 try { 1962 if (mWrapped != null) return mWrapped.openTypedAssetFile(uri, mimeType, opts, cancellationSignal); 1963 } catch (RemoteException e) { 1964 return null; 1965 } 1966 1967 IContentProvider unstableProvider = acquireUnstableProvider(uri); 1968 if (unstableProvider == null) { 1969 throw new FileNotFoundException("No content provider: " + uri); 1970 } 1971 IContentProvider stableProvider = null; 1972 AssetFileDescriptor fd = null; 1973 1974 try { 1975 ICancellationSignal remoteCancellationSignal = null; 1976 if (cancellationSignal != null) { 1977 cancellationSignal.throwIfCanceled(); 1978 remoteCancellationSignal = unstableProvider.createCancellationSignal(); 1979 cancellationSignal.setRemote(remoteCancellationSignal); 1980 } 1981 1982 try { 1983 fd = unstableProvider.openTypedAssetFile( 1984 mPackageName, mAttributionTag, uri, mimeType, opts, 1985 remoteCancellationSignal); 1986 if (fd == null) { 1987 // The provider will be released by the finally{} clause 1988 return null; 1989 } 1990 } catch (DeadObjectException e) { 1991 // The remote process has died... but we only hold an unstable 1992 // reference though, so we might recover!!! Let's try!!!! 1993 // This is exciting!!1!!1!!!!1 1994 unstableProviderDied(unstableProvider); 1995 stableProvider = acquireProvider(uri); 1996 if (stableProvider == null) { 1997 throw new FileNotFoundException("No content provider: " + uri); 1998 } 1999 fd = stableProvider.openTypedAssetFile( 2000 mPackageName, mAttributionTag, uri, mimeType, opts, 2001 remoteCancellationSignal); 2002 if (fd == null) { 2003 // The provider will be released by the finally{} clause 2004 return null; 2005 } 2006 } 2007 2008 if (stableProvider == null) { 2009 stableProvider = acquireProvider(uri); 2010 } 2011 releaseUnstableProvider(unstableProvider); 2012 unstableProvider = null; 2013 ParcelFileDescriptor pfd = new ParcelFileDescriptorInner( 2014 fd.getParcelFileDescriptor(), stableProvider); 2015 2016 // Success! Don't release the provider when exiting, let 2017 // ParcelFileDescriptorInner do that when it is closed. 2018 stableProvider = null; 2019 2020 return new AssetFileDescriptor(pfd, fd.getStartOffset(), 2021 fd.getDeclaredLength(), fd.getExtras()); 2022 2023 } catch (RemoteException e) { 2024 // Whatever, whatever, we'll go away. 2025 throw new FileNotFoundException( 2026 "Failed opening content provider: " + uri); 2027 } catch (FileNotFoundException e) { 2028 throw e; 2029 } finally { 2030 if (cancellationSignal != null) { 2031 cancellationSignal.setRemote(null); 2032 } 2033 if (stableProvider != null) { 2034 releaseProvider(stableProvider); 2035 } 2036 if (unstableProvider != null) { 2037 releaseUnstableProvider(unstableProvider); 2038 } 2039 } 2040 } 2041 2042 /** 2043 * A resource identified by the {@link Resources} that contains it, and a resource id. 2044 * 2045 * @hide 2046 */ 2047 public class OpenResourceIdResult { 2048 @UnsupportedAppUsage 2049 public Resources r; 2050 @UnsupportedAppUsage 2051 public int id; 2052 } 2053 2054 /** 2055 * Resolves an android.resource URI to a {@link Resources} and a resource id. 2056 * 2057 * @hide 2058 */ 2059 @UnsupportedAppUsage 2060 public OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException { 2061 String authority = uri.getAuthority(); 2062 Resources r; 2063 if (TextUtils.isEmpty(authority)) { 2064 throw new FileNotFoundException("No authority: " + uri); 2065 } else { 2066 try { 2067 r = mContext.getPackageManager().getResourcesForApplication(authority); 2068 } catch (NameNotFoundException ex) { 2069 throw new FileNotFoundException("No package found for authority: " + uri); 2070 } 2071 } 2072 List<String> path = uri.getPathSegments(); 2073 if (path == null) { 2074 throw new FileNotFoundException("No path: " + uri); 2075 } 2076 int len = path.size(); 2077 int id; 2078 if (len == 1) { 2079 try { 2080 id = Integer.parseInt(path.get(0)); 2081 } catch (NumberFormatException e) { 2082 throw new FileNotFoundException("Single path segment is not a resource ID: " + uri); 2083 } 2084 } else if (len == 2) { 2085 id = r.getIdentifier(path.get(1), path.get(0), authority); 2086 } else { 2087 throw new FileNotFoundException("More than two path segments: " + uri); 2088 } 2089 if (id == 0) { 2090 throw new FileNotFoundException("No resource found for: " + uri); 2091 } 2092 OpenResourceIdResult res = new OpenResourceIdResult(); 2093 res.r = r; 2094 res.id = id; 2095 return res; 2096 } 2097 2098 /** 2099 * Inserts a row into a table at the given URL. 2100 * 2101 * If the content provider supports transactions the insertion will be atomic. 2102 * 2103 * @param url The URL of the table to insert into. 2104 * @param values The initial values for the newly inserted row. The key is the column name for 2105 * the field. Passing an empty ContentValues will create an empty row. 2106 * @return the URL of the newly created row. May return <code>null</code> if the underlying 2107 * content provider returns <code>null</code>, or if it crashes. 2108 */ 2109 public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url, 2110 @Nullable ContentValues values) { 2111 return insert(url, values, null); 2112 } 2113 2114 /** 2115 * Inserts a row into a table at the given URL. 2116 * 2117 * If the content provider supports transactions the insertion will be atomic. 2118 * 2119 * @param url The URL of the table to insert into. 2120 * @param values The initial values for the newly inserted row. The key is the column name for 2121 * the field. Passing an empty ContentValues will create an empty row. 2122 * @param extras A Bundle containing additional information necessary for 2123 * the operation. Arguments may include SQL style arguments, such 2124 * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that 2125 * the documentation for each individual provider will indicate 2126 * which arguments they support. 2127 * @return the URL of the newly created row. May return <code>null</code> if the underlying 2128 * content provider returns <code>null</code>, or if it crashes. 2129 * @throws IllegalArgumentException if the provider doesn't support one of 2130 * the requested Bundle arguments. 2131 */ 2132 @Override 2133 public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url, 2134 @Nullable ContentValues values, @Nullable Bundle extras) { 2135 Objects.requireNonNull(url, "url"); 2136 2137 try { 2138 if (mWrapped != null) return mWrapped.insert(url, values, extras); 2139 } catch (RemoteException e) { 2140 return null; 2141 } 2142 2143 IContentProvider provider = acquireProvider(url); 2144 if (provider == null) { 2145 throw new IllegalArgumentException("Unknown URL " + url); 2146 } 2147 try { 2148 long startTime = SystemClock.uptimeMillis(); 2149 Uri createdRow = provider.insert(mPackageName, mAttributionTag, url, values, extras); 2150 long durationMillis = SystemClock.uptimeMillis() - startTime; 2151 maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */); 2152 return createdRow; 2153 } catch (RemoteException e) { 2154 // Arbitrary and not worth documenting, as Activity 2155 // Manager will kill this process shortly anyway. 2156 return null; 2157 } finally { 2158 releaseProvider(provider); 2159 } 2160 } 2161 2162 /** 2163 * Applies each of the {@link ContentProviderOperation} objects and returns an array 2164 * of their results. Passes through OperationApplicationException, which may be thrown 2165 * by the call to {@link ContentProviderOperation#apply}. 2166 * If all the applications succeed then a {@link ContentProviderResult} array with the 2167 * same number of elements as the operations will be returned. It is implementation-specific 2168 * how many, if any, operations will have been successfully applied if a call to 2169 * apply results in a {@link OperationApplicationException}. 2170 * @param authority the authority of the ContentProvider to which this batch should be applied 2171 * @param operations the operations to apply 2172 * @return the results of the applications 2173 * @throws OperationApplicationException thrown if an application fails. 2174 * See {@link ContentProviderOperation#apply} for more information. 2175 * @throws RemoteException thrown if a RemoteException is encountered while attempting 2176 * to communicate with a remote provider. 2177 */ 2178 @Override 2179 public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority, 2180 @NonNull ArrayList<ContentProviderOperation> operations) 2181 throws RemoteException, OperationApplicationException { 2182 Objects.requireNonNull(authority, "authority"); 2183 Objects.requireNonNull(operations, "operations"); 2184 2185 try { 2186 if (mWrapped != null) return mWrapped.applyBatch(authority, operations); 2187 } catch (RemoteException e) { 2188 return null; 2189 } 2190 2191 ContentProviderClient provider = acquireContentProviderClient(authority); 2192 if (provider == null) { 2193 throw new IllegalArgumentException("Unknown authority " + authority); 2194 } 2195 try { 2196 return provider.applyBatch(operations); 2197 } finally { 2198 provider.release(); 2199 } 2200 } 2201 2202 /** 2203 * Inserts multiple rows into a table at the given URL. 2204 * 2205 * This function make no guarantees about the atomicity of the insertions. 2206 * 2207 * @param url The URL of the table to insert into. 2208 * @param values The initial values for the newly inserted rows. The key is the column name for 2209 * the field. Passing null will create an empty row. 2210 * @return the number of newly created rows. 2211 */ 2212 @Override 2213 public final int bulkInsert(@RequiresPermission.Write @NonNull Uri url, 2214 @NonNull ContentValues[] values) { 2215 Objects.requireNonNull(url, "url"); 2216 Objects.requireNonNull(values, "values"); 2217 2218 try { 2219 if (mWrapped != null) return mWrapped.bulkInsert(url, values); 2220 } catch (RemoteException e) { 2221 return 0; 2222 } 2223 2224 IContentProvider provider = acquireProvider(url); 2225 if (provider == null) { 2226 throw new IllegalArgumentException("Unknown URL " + url); 2227 } 2228 try { 2229 long startTime = SystemClock.uptimeMillis(); 2230 int rowsCreated = provider.bulkInsert(mPackageName, mAttributionTag, url, values); 2231 long durationMillis = SystemClock.uptimeMillis() - startTime; 2232 maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */); 2233 return rowsCreated; 2234 } catch (RemoteException e) { 2235 // Arbitrary and not worth documenting, as Activity 2236 // Manager will kill this process shortly anyway. 2237 return 0; 2238 } finally { 2239 releaseProvider(provider); 2240 } 2241 } 2242 2243 /** 2244 * Deletes row(s) specified by a content URI. 2245 * 2246 * If the content provider supports transactions, the deletion will be atomic. 2247 * 2248 * @param url The URL of the row to delete. 2249 * @param where A filter to apply to rows before deleting, formatted as an SQL WHERE clause 2250 (excluding the WHERE itself). 2251 * @return The number of rows deleted. 2252 */ 2253 public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable String where, 2254 @Nullable String[] selectionArgs) { 2255 return delete(url, createSqlQueryBundle(where, selectionArgs)); 2256 } 2257 2258 /** 2259 * Deletes row(s) specified by a content URI. 2260 * 2261 * If the content provider supports transactions, the deletion will be atomic. 2262 * 2263 * @param url The URL of the row to delete. 2264 * @param extras A Bundle containing additional information necessary for 2265 * the operation. Arguments may include SQL style arguments, such 2266 * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that 2267 * the documentation for each individual provider will indicate 2268 * which arguments they support. 2269 * @return The number of rows deleted. 2270 * @throws IllegalArgumentException if the provider doesn't support one of 2271 * the requested Bundle arguments. 2272 */ 2273 @Override 2274 public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable Bundle extras) { 2275 Objects.requireNonNull(url, "url"); 2276 2277 try { 2278 if (mWrapped != null) return mWrapped.delete(url, extras); 2279 } catch (RemoteException e) { 2280 return 0; 2281 } 2282 2283 IContentProvider provider = acquireProvider(url); 2284 if (provider == null) { 2285 throw new IllegalArgumentException("Unknown URL " + url); 2286 } 2287 try { 2288 long startTime = SystemClock.uptimeMillis(); 2289 int rowsDeleted = provider.delete(mPackageName, mAttributionTag, url, extras); 2290 long durationMillis = SystemClock.uptimeMillis() - startTime; 2291 maybeLogUpdateToEventLog(durationMillis, url, "delete", null); 2292 return rowsDeleted; 2293 } catch (RemoteException e) { 2294 // Arbitrary and not worth documenting, as Activity 2295 // Manager will kill this process shortly anyway. 2296 return -1; 2297 } finally { 2298 releaseProvider(provider); 2299 } 2300 } 2301 2302 /** 2303 * Update row(s) in a content URI. 2304 * 2305 * If the content provider supports transactions the update will be atomic. 2306 * 2307 * @param uri The URI to modify. 2308 * @param values The new field values. The key is the column name for the field. 2309 A null value will remove an existing field value. 2310 * @param where A filter to apply to rows before updating, formatted as an SQL WHERE clause 2311 (excluding the WHERE itself). 2312 * @return the number of rows updated. 2313 * @throws NullPointerException if uri or values are null 2314 */ 2315 public final int update(@RequiresPermission.Write @NonNull Uri uri, 2316 @Nullable ContentValues values, @Nullable String where, 2317 @Nullable String[] selectionArgs) { 2318 return update(uri, values, createSqlQueryBundle(where, selectionArgs)); 2319 } 2320 2321 /** 2322 * Update row(s) in a content URI. 2323 * 2324 * If the content provider supports transactions the update will be atomic. 2325 * 2326 * @param uri The URI to modify. 2327 * @param values The new field values. The key is the column name for the field. 2328 A null value will remove an existing field value. 2329 * @param extras A Bundle containing additional information necessary for 2330 * the operation. Arguments may include SQL style arguments, such 2331 * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that 2332 * the documentation for each individual provider will indicate 2333 * which arguments they support. 2334 * @return the number of rows updated. 2335 * @throws NullPointerException if uri or values are null 2336 * @throws IllegalArgumentException if the provider doesn't support one of 2337 * the requested Bundle arguments. 2338 */ 2339 @Override 2340 public final int update(@RequiresPermission.Write @NonNull Uri uri, 2341 @Nullable ContentValues values, @Nullable Bundle extras) { 2342 Objects.requireNonNull(uri, "uri"); 2343 2344 try { 2345 if (mWrapped != null) return mWrapped.update(uri, values, extras); 2346 } catch (RemoteException e) { 2347 return 0; 2348 } 2349 2350 IContentProvider provider = acquireProvider(uri); 2351 if (provider == null) { 2352 throw new IllegalArgumentException("Unknown URI " + uri); 2353 } 2354 try { 2355 long startTime = SystemClock.uptimeMillis(); 2356 int rowsUpdated = provider.update(mPackageName, mAttributionTag, uri, values, extras); 2357 long durationMillis = SystemClock.uptimeMillis() - startTime; 2358 maybeLogUpdateToEventLog(durationMillis, uri, "update", null); 2359 return rowsUpdated; 2360 } catch (RemoteException e) { 2361 // Arbitrary and not worth documenting, as Activity 2362 // Manager will kill this process shortly anyway. 2363 return -1; 2364 } finally { 2365 releaseProvider(provider); 2366 } 2367 } 2368 2369 /** 2370 * Call a provider-defined method. This can be used to implement 2371 * read or write interfaces which are cheaper than using a Cursor and/or 2372 * do not fit into the traditional table model. 2373 * 2374 * @param method provider-defined method name to call. Opaque to 2375 * framework, but must be non-null. 2376 * @param arg provider-defined String argument. May be null. 2377 * @param extras provider-defined Bundle argument. May be null. 2378 * @return a result Bundle, possibly null. Will be null if the ContentProvider 2379 * does not implement call. 2380 * @throws NullPointerException if uri or method is null 2381 * @throws IllegalArgumentException if uri is not known 2382 */ 2383 public final @Nullable Bundle call(@NonNull Uri uri, @NonNull String method, 2384 @Nullable String arg, @Nullable Bundle extras) { 2385 return call(uri.getAuthority(), method, arg, extras); 2386 } 2387 2388 @Override 2389 public final @Nullable Bundle call(@NonNull String authority, @NonNull String method, 2390 @Nullable String arg, @Nullable Bundle extras) { 2391 Objects.requireNonNull(authority, "authority"); 2392 Objects.requireNonNull(method, "method"); 2393 2394 try { 2395 if (mWrapped != null) return mWrapped.call(authority, method, arg, extras); 2396 } catch (RemoteException e) { 2397 return null; 2398 } 2399 2400 IContentProvider provider = acquireProvider(authority); 2401 if (provider == null) { 2402 throw new IllegalArgumentException("Unknown authority " + authority); 2403 } 2404 try { 2405 final Bundle res = provider.call(mPackageName, mAttributionTag, authority, method, arg, 2406 extras); 2407 Bundle.setDefusable(res, true); 2408 return res; 2409 } catch (RemoteException e) { 2410 // Arbitrary and not worth documenting, as Activity 2411 // Manager will kill this process shortly anyway. 2412 return null; 2413 } finally { 2414 releaseProvider(provider); 2415 } 2416 } 2417 2418 /** 2419 * Returns the content provider for the given content URI. 2420 * 2421 * @param uri The URI to a content provider 2422 * @return The ContentProvider for the given URI, or null if no content provider is found. 2423 * @hide 2424 */ 2425 @UnsupportedAppUsage 2426 public final IContentProvider acquireProvider(Uri uri) { 2427 if (!SCHEME_CONTENT.equals(uri.getScheme())) { 2428 return null; 2429 } 2430 final String auth = uri.getAuthority(); 2431 if (auth != null) { 2432 return acquireProvider(mContext, auth); 2433 } 2434 return null; 2435 } 2436 2437 /** 2438 * Returns the content provider for the given content URI if the process 2439 * already has a reference on it. 2440 * 2441 * @param uri The URI to a content provider 2442 * @return The ContentProvider for the given URI, or null if no content provider is found. 2443 * @hide 2444 */ 2445 @UnsupportedAppUsage 2446 public final IContentProvider acquireExistingProvider(Uri uri) { 2447 if (!SCHEME_CONTENT.equals(uri.getScheme())) { 2448 return null; 2449 } 2450 final String auth = uri.getAuthority(); 2451 if (auth != null) { 2452 return acquireExistingProvider(mContext, auth); 2453 } 2454 return null; 2455 } 2456 2457 /** 2458 * @hide 2459 */ 2460 @UnsupportedAppUsage 2461 public final IContentProvider acquireProvider(String name) { 2462 if (name == null) { 2463 return null; 2464 } 2465 return acquireProvider(mContext, name); 2466 } 2467 2468 /** 2469 * Returns the content provider for the given content URI. 2470 * 2471 * @param uri The URI to a content provider 2472 * @return The ContentProvider for the given URI, or null if no content provider is found. 2473 * @hide 2474 */ 2475 public final IContentProvider acquireUnstableProvider(Uri uri) { 2476 if (!SCHEME_CONTENT.equals(uri.getScheme())) { 2477 return null; 2478 } 2479 String auth = uri.getAuthority(); 2480 if (auth != null) { 2481 return acquireUnstableProvider(mContext, uri.getAuthority()); 2482 } 2483 return null; 2484 } 2485 2486 /** 2487 * @hide 2488 */ 2489 @UnsupportedAppUsage 2490 public final IContentProvider acquireUnstableProvider(String name) { 2491 if (name == null) { 2492 return null; 2493 } 2494 return acquireUnstableProvider(mContext, name); 2495 } 2496 2497 /** 2498 * Returns a {@link ContentProviderClient} that is associated with the {@link ContentProvider} 2499 * that services the content at uri, starting the provider if necessary. Returns 2500 * null if there is no provider associated wih the uri. The caller must indicate that they are 2501 * done with the provider by calling {@link ContentProviderClient#release} which will allow 2502 * the system to release the provider if it determines that there is no other reason for 2503 * keeping it active. 2504 * @param uri specifies which provider should be acquired 2505 * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider} 2506 * that services the content at uri or null if there isn't one. 2507 */ 2508 public final @Nullable ContentProviderClient acquireContentProviderClient(@NonNull Uri uri) { 2509 Objects.requireNonNull(uri, "uri"); 2510 IContentProvider provider = acquireProvider(uri); 2511 if (provider != null) { 2512 return new ContentProviderClient(this, provider, uri.getAuthority(), true); 2513 } 2514 return null; 2515 } 2516 2517 /** 2518 * Returns a {@link ContentProviderClient} that is associated with the {@link ContentProvider} 2519 * with the authority of name, starting the provider if necessary. Returns 2520 * null if there is no provider associated wih the uri. The caller must indicate that they are 2521 * done with the provider by calling {@link ContentProviderClient#release} which will allow 2522 * the system to release the provider if it determines that there is no other reason for 2523 * keeping it active. 2524 * @param name specifies which provider should be acquired 2525 * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider} 2526 * with the authority of name or null if there isn't one. 2527 */ 2528 public final @Nullable ContentProviderClient acquireContentProviderClient( 2529 @NonNull String name) { 2530 Objects.requireNonNull(name, "name"); 2531 IContentProvider provider = acquireProvider(name); 2532 if (provider != null) { 2533 return new ContentProviderClient(this, provider, name, true); 2534 } 2535 2536 return null; 2537 } 2538 2539 /** 2540 * Like {@link #acquireContentProviderClient(Uri)}, but for use when you do 2541 * not trust the stability of the target content provider. This turns off 2542 * the mechanism in the platform clean up processes that are dependent on 2543 * a content provider if that content provider's process goes away. Normally 2544 * you can safely assume that once you have acquired a provider, you can freely 2545 * use it as needed and it won't disappear, even if your process is in the 2546 * background. If using this method, you need to take care to deal with any 2547 * failures when communicating with the provider, and be sure to close it 2548 * so that it can be re-opened later. In particular, catching a 2549 * {@link android.os.DeadObjectException} from the calls there will let you 2550 * know that the content provider has gone away; at that point the current 2551 * ContentProviderClient object is invalid, and you should release it. You 2552 * can acquire a new one if you would like to try to restart the provider 2553 * and perform new operations on it. 2554 */ 2555 public final @Nullable ContentProviderClient acquireUnstableContentProviderClient( 2556 @NonNull Uri uri) { 2557 Objects.requireNonNull(uri, "uri"); 2558 IContentProvider provider = acquireUnstableProvider(uri); 2559 if (provider != null) { 2560 return new ContentProviderClient(this, provider, uri.getAuthority(), false); 2561 } 2562 2563 return null; 2564 } 2565 2566 /** 2567 * Like {@link #acquireContentProviderClient(String)}, but for use when you do 2568 * not trust the stability of the target content provider. This turns off 2569 * the mechanism in the platform clean up processes that are dependent on 2570 * a content provider if that content provider's process goes away. Normally 2571 * you can safely assume that once you have acquired a provider, you can freely 2572 * use it as needed and it won't disappear, even if your process is in the 2573 * background. If using this method, you need to take care to deal with any 2574 * failures when communicating with the provider, and be sure to close it 2575 * so that it can be re-opened later. In particular, catching a 2576 * {@link android.os.DeadObjectException} from the calls there will let you 2577 * know that the content provider has gone away; at that point the current 2578 * ContentProviderClient object is invalid, and you should release it. You 2579 * can acquire a new one if you would like to try to restart the provider 2580 * and perform new operations on it. 2581 */ 2582 public final @Nullable ContentProviderClient acquireUnstableContentProviderClient( 2583 @NonNull String name) { 2584 Objects.requireNonNull(name, "name"); 2585 IContentProvider provider = acquireUnstableProvider(name); 2586 if (provider != null) { 2587 return new ContentProviderClient(this, provider, name, false); 2588 } 2589 2590 return null; 2591 } 2592 2593 /** 2594 * Register an observer class that gets callbacks when data identified by a 2595 * given content URI changes. 2596 * <p> 2597 * Starting in {@link android.os.Build.VERSION_CODES#O}, all content 2598 * notifications must be backed by a valid {@link ContentProvider}. 2599 * 2600 * @param uri The URI to watch for changes. This can be a specific row URI, 2601 * or a base URI for a whole class of content. 2602 * @param notifyForDescendants When false, the observer will be notified 2603 * whenever a change occurs to the exact URI specified by 2604 * <code>uri</code> or to one of the URI's ancestors in the path 2605 * hierarchy. When true, the observer will also be notified 2606 * whenever a change occurs to the URI's descendants in the path 2607 * hierarchy. 2608 * @param observer The object that receives callbacks when changes occur. 2609 * @see #unregisterContentObserver 2610 */ 2611 public final void registerContentObserver(@NonNull Uri uri, boolean notifyForDescendants, 2612 @NonNull ContentObserver observer) { 2613 Objects.requireNonNull(uri, "uri"); 2614 Objects.requireNonNull(observer, "observer"); 2615 registerContentObserver( 2616 ContentProvider.getUriWithoutUserId(uri), 2617 notifyForDescendants, 2618 observer, 2619 ContentProvider.getUserIdFromUri(uri, mContext.getUserId())); 2620 } 2621 2622 /** @hide - designated user version */ 2623 @UnsupportedAppUsage 2624 public final void registerContentObserver(Uri uri, boolean notifyForDescendents, 2625 ContentObserver observer, @UserIdInt int userHandle) { 2626 try { 2627 getContentService().registerContentObserver(uri, notifyForDescendents, 2628 observer.getContentObserver(), userHandle, mTargetSdkVersion); 2629 } catch (RemoteException e) { 2630 throw e.rethrowFromSystemServer(); 2631 } 2632 } 2633 2634 /** 2635 * Unregisters a change observer. 2636 * 2637 * @param observer The previously registered observer that is no longer needed. 2638 * @see #registerContentObserver 2639 */ 2640 public final void unregisterContentObserver(@NonNull ContentObserver observer) { 2641 Objects.requireNonNull(observer, "observer"); 2642 try { 2643 IContentObserver contentObserver = observer.releaseContentObserver(); 2644 if (contentObserver != null) { 2645 getContentService().unregisterContentObserver( 2646 contentObserver); 2647 } 2648 } catch (RemoteException e) { 2649 throw e.rethrowFromSystemServer(); 2650 } 2651 } 2652 2653 /** 2654 * Notify registered observers that a row was updated and attempt to sync 2655 * changes to the network. 2656 * <p> 2657 * To observe events sent through this call, use 2658 * {@link #registerContentObserver(Uri, boolean, ContentObserver)}. 2659 * <p> 2660 * Starting in {@link android.os.Build.VERSION_CODES#O}, all content 2661 * notifications must be backed by a valid {@link ContentProvider}. 2662 * 2663 * @param uri The uri of the content that was changed. 2664 * @param observer The observer that originated the change, may be 2665 * <code>null</null>. The observer that originated the change 2666 * will only receive the notification if it has requested to 2667 * receive self-change notifications by implementing 2668 * {@link ContentObserver#deliverSelfNotifications()} to return 2669 * true. 2670 */ 2671 public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) { 2672 notifyChange(uri, observer, true /* sync to network */); 2673 } 2674 2675 /** 2676 * Notify registered observers that a row was updated. 2677 * <p> 2678 * To observe events sent through this call, use 2679 * {@link #registerContentObserver(Uri, boolean, ContentObserver)}. 2680 * <p> 2681 * If syncToNetwork is true, this will attempt to schedule a local sync 2682 * using the sync adapter that's registered for the authority of the 2683 * provided uri. No account will be passed to the sync adapter, so all 2684 * matching accounts will be synchronized. 2685 * <p> 2686 * Starting in {@link android.os.Build.VERSION_CODES#O}, all content 2687 * notifications must be backed by a valid {@link ContentProvider}. 2688 * 2689 * @param uri The uri of the content that was changed. 2690 * @param observer The observer that originated the change, may be 2691 * <code>null</null>. The observer that originated the change 2692 * will only receive the notification if it has requested to 2693 * receive self-change notifications by implementing 2694 * {@link ContentObserver#deliverSelfNotifications()} to return 2695 * true. 2696 * @param syncToNetwork If true, same as {@link #NOTIFY_SYNC_TO_NETWORK}. 2697 * @see #requestSync(android.accounts.Account, String, android.os.Bundle) 2698 * @deprecated callers should consider migrating to 2699 * {@link #notifyChange(Uri, ContentObserver, int)}, as it 2700 * offers support for many more options than just 2701 * {@link #NOTIFY_SYNC_TO_NETWORK}. 2702 */ 2703 @Deprecated 2704 public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer, 2705 boolean syncToNetwork) { 2706 notifyChange(uri, observer, syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0); 2707 } 2708 2709 /** 2710 * Notify registered observers that a row was updated. 2711 * <p> 2712 * To observe events sent through this call, use 2713 * {@link #registerContentObserver(Uri, boolean, ContentObserver)}. 2714 * <p> 2715 * If {@link #NOTIFY_SYNC_TO_NETWORK} is set, this will attempt to schedule 2716 * a local sync using the sync adapter that's registered for the authority 2717 * of the provided uri. No account will be passed to the sync adapter, so 2718 * all matching accounts will be synchronized. 2719 * <p> 2720 * Starting in {@link android.os.Build.VERSION_CODES#O}, all content 2721 * notifications must be backed by a valid {@link ContentProvider}. 2722 * 2723 * @param uri The uri of the content that was changed. 2724 * @param observer The observer that originated the change, may be 2725 * <code>null</null>. The observer that originated the change 2726 * will only receive the notification if it has requested to 2727 * receive self-change notifications by implementing 2728 * {@link ContentObserver#deliverSelfNotifications()} to return 2729 * true. 2730 * @param flags Additional flags: {@link #NOTIFY_SYNC_TO_NETWORK}. 2731 * @see #requestSync(android.accounts.Account, String, android.os.Bundle) 2732 */ 2733 public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer, 2734 @NotifyFlags int flags) { 2735 Objects.requireNonNull(uri, "uri"); 2736 notifyChange( 2737 ContentProvider.getUriWithoutUserId(uri), 2738 observer, 2739 flags, 2740 ContentProvider.getUserIdFromUri(uri, mContext.getUserId())); 2741 } 2742 2743 /** @removed */ 2744 @Deprecated 2745 public void notifyChange(@NonNull Iterable<Uri> uris, @Nullable ContentObserver observer, 2746 @NotifyFlags int flags) { 2747 final Collection<Uri> asCollection = new ArrayList<>(); 2748 uris.forEach(asCollection::add); 2749 notifyChange(asCollection, observer, flags); 2750 } 2751 2752 /** 2753 * Notify registered observers that several rows have been updated. 2754 * <p> 2755 * To observe events sent through this call, use 2756 * {@link #registerContentObserver(Uri, boolean, ContentObserver)}. 2757 * <p> 2758 * If {@link #NOTIFY_SYNC_TO_NETWORK} is set, this will attempt to schedule 2759 * a local sync using the sync adapter that's registered for the authority 2760 * of the provided uri. No account will be passed to the sync adapter, so 2761 * all matching accounts will be synchronized. 2762 * <p> 2763 * Starting in {@link android.os.Build.VERSION_CODES#O}, all content 2764 * notifications must be backed by a valid {@link ContentProvider}. 2765 * 2766 * @param uris The uris of the content that was changed. 2767 * @param observer The observer that originated the change, may be 2768 * <code>null</null>. The observer that originated the change 2769 * will only receive the notification if it has requested to 2770 * receive self-change notifications by implementing 2771 * {@link ContentObserver#deliverSelfNotifications()} to return 2772 * true. 2773 * @param flags Flags such as {@link #NOTIFY_SYNC_TO_NETWORK} or 2774 * {@link #NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS}. 2775 */ 2776 public void notifyChange(@NonNull Collection<Uri> uris, @Nullable ContentObserver observer, 2777 @NotifyFlags int flags) { 2778 Objects.requireNonNull(uris, "uris"); 2779 2780 // Cluster based on user ID 2781 final SparseArray<ArrayList<Uri>> clusteredByUser = new SparseArray<>(); 2782 for (Uri uri : uris) { 2783 final int userId = ContentProvider.getUserIdFromUri(uri, mContext.getUserId()); 2784 ArrayList<Uri> list = clusteredByUser.get(userId); 2785 if (list == null) { 2786 list = new ArrayList<>(); 2787 clusteredByUser.put(userId, list); 2788 } 2789 list.add(ContentProvider.getUriWithoutUserId(uri)); 2790 } 2791 2792 for (int i = 0; i < clusteredByUser.size(); i++) { 2793 final int userId = clusteredByUser.keyAt(i); 2794 final ArrayList<Uri> list = clusteredByUser.valueAt(i); 2795 notifyChange(list.toArray(new Uri[list.size()]), observer, flags, userId); 2796 } 2797 } 2798 2799 /** 2800 * Notify registered observers within the designated user(s) that a row was updated. 2801 * 2802 * @deprecated callers should consider migrating to 2803 * {@link #notifyChange(Uri, ContentObserver, int)}, as it 2804 * offers support for many more options than just 2805 * {@link #NOTIFY_SYNC_TO_NETWORK}. 2806 * @hide 2807 */ 2808 @Deprecated 2809 public void notifyChange(@NonNull Uri uri, ContentObserver observer, boolean syncToNetwork, 2810 @UserIdInt int userHandle) { 2811 notifyChange(uri, observer, syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0, userHandle); 2812 } 2813 2814 /** {@hide} */ 2815 public void notifyChange(@NonNull Uri uri, ContentObserver observer, @NotifyFlags int flags, 2816 @UserIdInt int userHandle) { 2817 notifyChange(new Uri[] { uri }, observer, flags, userHandle); 2818 } 2819 2820 /** 2821 * Notify registered observers within the designated user(s) that a row was updated. 2822 * 2823 * @hide 2824 */ 2825 public void notifyChange(@NonNull Uri[] uris, ContentObserver observer, @NotifyFlags int flags, 2826 @UserIdInt int userHandle) { 2827 try { 2828 getContentService().notifyChange( 2829 uris, observer == null ? null : observer.getContentObserver(), 2830 observer != null && observer.deliverSelfNotifications(), flags, 2831 userHandle, mTargetSdkVersion, mContext.getPackageName()); 2832 } catch (RemoteException e) { 2833 throw e.rethrowFromSystemServer(); 2834 } 2835 } 2836 2837 /** 2838 * Take a persistable URI permission grant that has been offered. Once 2839 * taken, the permission grant will be remembered across device reboots. 2840 * Only URI permissions granted with 2841 * {@link Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION} can be persisted. If 2842 * the grant has already been persisted, taking it again will touch 2843 * {@link UriPermission#getPersistedTime()}. 2844 * 2845 * @see #getPersistedUriPermissions() 2846 */ 2847 public void takePersistableUriPermission(@NonNull Uri uri, 2848 @Intent.AccessUriMode int modeFlags) { 2849 Objects.requireNonNull(uri, "uri"); 2850 try { 2851 UriGrantsManager.getService().takePersistableUriPermission( 2852 ContentProvider.getUriWithoutUserId(uri), modeFlags, /* toPackage= */ null, 2853 resolveUserId(uri)); 2854 } catch (RemoteException e) { 2855 throw e.rethrowFromSystemServer(); 2856 } 2857 } 2858 2859 /** 2860 * @hide 2861 */ 2862 @UnsupportedAppUsage 2863 public void takePersistableUriPermission(@NonNull String toPackage, @NonNull Uri uri, 2864 @Intent.AccessUriMode int modeFlags) { 2865 Objects.requireNonNull(toPackage, "toPackage"); 2866 Objects.requireNonNull(uri, "uri"); 2867 try { 2868 UriGrantsManager.getService().takePersistableUriPermission( 2869 ContentProvider.getUriWithoutUserId(uri), modeFlags, toPackage, 2870 resolveUserId(uri)); 2871 } catch (RemoteException e) { 2872 throw e.rethrowFromSystemServer(); 2873 } 2874 } 2875 2876 /** 2877 * Relinquish a persisted URI permission grant. The URI must have been 2878 * previously made persistent with 2879 * {@link #takePersistableUriPermission(Uri, int)}. Any non-persistent 2880 * grants to the calling package will remain intact. 2881 * 2882 * @see #getPersistedUriPermissions() 2883 */ 2884 public void releasePersistableUriPermission(@NonNull Uri uri, 2885 @Intent.AccessUriMode int modeFlags) { 2886 Objects.requireNonNull(uri, "uri"); 2887 try { 2888 UriGrantsManager.getService().releasePersistableUriPermission( 2889 ContentProvider.getUriWithoutUserId(uri), modeFlags, /* toPackage= */ null, 2890 resolveUserId(uri)); 2891 } catch (RemoteException e) { 2892 throw e.rethrowFromSystemServer(); 2893 } 2894 } 2895 2896 /** 2897 * Return list of all URI permission grants that have been persisted by the 2898 * calling app. That is, the returned permissions have been granted 2899 * <em>to</em> the calling app. Only persistable grants taken with 2900 * {@link #takePersistableUriPermission(Uri, int)} are returned. 2901 * <p>Note: Some of the returned URIs may not be usable until after the user is unlocked. 2902 * 2903 * @see #takePersistableUriPermission(Uri, int) 2904 * @see #releasePersistableUriPermission(Uri, int) 2905 */ 2906 public @NonNull List<UriPermission> getPersistedUriPermissions() { 2907 try { 2908 return UriGrantsManager.getService().getUriPermissions( 2909 mPackageName, true /* incoming */, true /* persistedOnly */).getList(); 2910 } catch (RemoteException e) { 2911 throw e.rethrowFromSystemServer(); 2912 } 2913 } 2914 2915 /** 2916 * Return list of all persisted URI permission grants that are hosted by the 2917 * calling app. That is, the returned permissions have been granted 2918 * <em>from</em> the calling app. Only grants taken with 2919 * {@link #takePersistableUriPermission(Uri, int)} are returned. 2920 * <p>Note: Some of the returned URIs may not be usable until after the user is unlocked. 2921 */ 2922 public @NonNull List<UriPermission> getOutgoingPersistedUriPermissions() { 2923 try { 2924 return UriGrantsManager.getService().getUriPermissions( 2925 mPackageName, false /* incoming */, true /* persistedOnly */).getList(); 2926 } catch (RemoteException e) { 2927 throw e.rethrowFromSystemServer(); 2928 } 2929 } 2930 2931 /** @hide */ 2932 public @NonNull List<UriPermission> getOutgoingUriPermissions() { 2933 try { 2934 return UriGrantsManager.getService().getUriPermissions( 2935 mPackageName, false /* incoming */, false /* persistedOnly */).getList(); 2936 } catch (RemoteException e) { 2937 throw e.rethrowFromSystemServer(); 2938 } 2939 } 2940 2941 /** 2942 * Start an asynchronous sync operation. If you want to monitor the progress 2943 * of the sync you may register a SyncObserver. Only values of the following 2944 * types may be used in the extras bundle: 2945 * <ul> 2946 * <li>Integer</li> 2947 * <li>Long</li> 2948 * <li>Boolean</li> 2949 * <li>Float</li> 2950 * <li>Double</li> 2951 * <li>String</li> 2952 * <li>Account</li> 2953 * <li>null</li> 2954 * </ul> 2955 * 2956 * @param uri the uri of the provider to sync or null to sync all providers. 2957 * @param extras any extras to pass to the SyncAdapter. 2958 * @deprecated instead use 2959 * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)} 2960 */ 2961 @Deprecated 2962 public void startSync(Uri uri, Bundle extras) { 2963 Account account = null; 2964 if (extras != null) { 2965 String accountName = extras.getString(SYNC_EXTRAS_ACCOUNT); 2966 if (!TextUtils.isEmpty(accountName)) { 2967 // TODO: No references to Google in AOSP 2968 account = new Account(accountName, "com.google"); 2969 } 2970 extras.remove(SYNC_EXTRAS_ACCOUNT); 2971 } 2972 requestSync(account, uri != null ? uri.getAuthority() : null, extras); 2973 } 2974 2975 /** 2976 * Start an asynchronous sync operation. If you want to monitor the progress 2977 * of the sync you may register a SyncObserver. Only values of the following 2978 * types may be used in the extras bundle: 2979 * <ul> 2980 * <li>Integer</li> 2981 * <li>Long</li> 2982 * <li>Boolean</li> 2983 * <li>Float</li> 2984 * <li>Double</li> 2985 * <li>String</li> 2986 * <li>Account</li> 2987 * <li>null</li> 2988 * </ul> 2989 * 2990 * @param account which account should be synced 2991 * @param authority which authority should be synced 2992 * @param extras any extras to pass to the SyncAdapter. 2993 */ 2994 public static void requestSync(Account account, String authority, Bundle extras) { 2995 requestSyncAsUser(account, authority, UserHandle.myUserId(), extras); 2996 } 2997 2998 /** 2999 * @see #requestSync(Account, String, Bundle) 3000 * @hide 3001 */ 3002 public static void requestSyncAsUser(Account account, String authority, @UserIdInt int userId, 3003 Bundle extras) { 3004 if (extras == null) { 3005 throw new IllegalArgumentException("Must specify extras."); 3006 } 3007 SyncRequest request = 3008 new SyncRequest.Builder() 3009 .setSyncAdapter(account, authority) 3010 .setExtras(extras) 3011 .syncOnce() // Immediate sync. 3012 .build(); 3013 try { 3014 // Note ActivityThread.currentPackageName() may not be accurate in a shared process 3015 // case, but it's only for debugging. 3016 getContentService().syncAsUser(request, userId, ActivityThread.currentPackageName()); 3017 } catch(RemoteException e) { 3018 throw e.rethrowFromSystemServer(); 3019 } 3020 } 3021 3022 /** 3023 * Register a sync with the SyncManager. These requests are built using the 3024 * {@link SyncRequest.Builder}. 3025 */ 3026 public static void requestSync(SyncRequest request) { 3027 try { 3028 // Note ActivityThread.currentPackageName() may not be accurate in a shared process 3029 // case, but it's only for debugging. 3030 getContentService().sync(request, ActivityThread.currentPackageName()); 3031 } catch(RemoteException e) { 3032 throw e.rethrowFromSystemServer(); 3033 } 3034 } 3035 3036 /** 3037 * Check that only values of the following types are in the Bundle: 3038 * <ul> 3039 * <li>Integer</li> 3040 * <li>Long</li> 3041 * <li>Boolean</li> 3042 * <li>Float</li> 3043 * <li>Double</li> 3044 * <li>String</li> 3045 * <li>Account</li> 3046 * <li>null</li> 3047 * </ul> 3048 * @param extras the Bundle to check 3049 */ 3050 public static void validateSyncExtrasBundle(Bundle extras) { 3051 try { 3052 for (String key : extras.keySet()) { 3053 Object value = extras.get(key); 3054 if (value == null) continue; 3055 if (value instanceof Long) continue; 3056 if (value instanceof Integer) continue; 3057 if (value instanceof Boolean) continue; 3058 if (value instanceof Float) continue; 3059 if (value instanceof Double) continue; 3060 if (value instanceof String) continue; 3061 if (value instanceof Account) continue; 3062 throw new IllegalArgumentException("unexpected value type: " 3063 + value.getClass().getName()); 3064 } 3065 } catch (IllegalArgumentException e) { 3066 throw e; 3067 } catch (RuntimeException exc) { 3068 throw new IllegalArgumentException("error unparceling Bundle", exc); 3069 } 3070 } 3071 3072 /** 3073 * Cancel any active or pending syncs that match the Uri. If the uri is null then 3074 * all syncs will be canceled. 3075 * 3076 * @param uri the uri of the provider to sync or null to sync all providers. 3077 * @deprecated instead use {@link #cancelSync(android.accounts.Account, String)} 3078 */ 3079 @Deprecated 3080 public void cancelSync(Uri uri) { 3081 cancelSync(null /* all accounts */, uri != null ? uri.getAuthority() : null); 3082 } 3083 3084 /** 3085 * Cancel any active or pending syncs that match account and authority. The account and 3086 * authority can each independently be set to null, which means that syncs with any account 3087 * or authority, respectively, will match. 3088 * 3089 * @param account filters the syncs that match by this account 3090 * @param authority filters the syncs that match by this authority 3091 */ 3092 public static void cancelSync(Account account, String authority) { 3093 try { 3094 getContentService().cancelSync(account, authority, null); 3095 } catch (RemoteException e) { 3096 throw e.rethrowFromSystemServer(); 3097 } 3098 } 3099 3100 /** 3101 * @see #cancelSync(Account, String) 3102 * @hide 3103 */ 3104 public static void cancelSyncAsUser(Account account, String authority, @UserIdInt int userId) { 3105 try { 3106 getContentService().cancelSyncAsUser(account, authority, null, userId); 3107 } catch (RemoteException e) { 3108 throw e.rethrowFromSystemServer(); 3109 } 3110 } 3111 3112 /** 3113 * Get information about the SyncAdapters that are known to the system. 3114 * @return an array of SyncAdapters that have registered with the system 3115 */ 3116 public static SyncAdapterType[] getSyncAdapterTypes() { 3117 try { 3118 return getContentService().getSyncAdapterTypes(); 3119 } catch (RemoteException e) { 3120 throw e.rethrowFromSystemServer(); 3121 } 3122 } 3123 3124 /** 3125 * @see #getSyncAdapterTypes() 3126 * @hide 3127 */ 3128 public static SyncAdapterType[] getSyncAdapterTypesAsUser(@UserIdInt int userId) { 3129 try { 3130 return getContentService().getSyncAdapterTypesAsUser(userId); 3131 } catch (RemoteException e) { 3132 throw e.rethrowFromSystemServer(); 3133 } 3134 } 3135 3136 /** 3137 * @hide 3138 * Returns the package names of syncadapters that match a given user and authority. 3139 */ 3140 @TestApi 3141 public static String[] getSyncAdapterPackagesForAuthorityAsUser(String authority, 3142 @UserIdInt int userId) { 3143 try { 3144 return getContentService().getSyncAdapterPackagesForAuthorityAsUser(authority, userId); 3145 } catch (RemoteException e) { 3146 throw e.rethrowFromSystemServer(); 3147 } 3148 } 3149 3150 /** 3151 * Check if the provider should be synced when a network tickle is received 3152 * <p>This method requires the caller to hold the permission 3153 * {@link android.Manifest.permission#READ_SYNC_SETTINGS}. 3154 * 3155 * @param account the account whose setting we are querying 3156 * @param authority the provider whose setting we are querying 3157 * @return true if the provider should be synced when a network tickle is received 3158 */ 3159 public static boolean getSyncAutomatically(Account account, String authority) { 3160 try { 3161 return getContentService().getSyncAutomatically(account, authority); 3162 } catch (RemoteException e) { 3163 throw e.rethrowFromSystemServer(); 3164 } 3165 } 3166 3167 /** 3168 * @see #getSyncAutomatically(Account, String) 3169 * @hide 3170 */ 3171 public static boolean getSyncAutomaticallyAsUser(Account account, String authority, 3172 @UserIdInt int userId) { 3173 try { 3174 return getContentService().getSyncAutomaticallyAsUser(account, authority, userId); 3175 } catch (RemoteException e) { 3176 throw e.rethrowFromSystemServer(); 3177 } 3178 } 3179 3180 /** 3181 * Set whether or not the provider is synced when it receives a network tickle. 3182 * <p>This method requires the caller to hold the permission 3183 * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}. 3184 * 3185 * @param account the account whose setting we are querying 3186 * @param authority the provider whose behavior is being controlled 3187 * @param sync true if the provider should be synced when tickles are received for it 3188 */ 3189 public static void setSyncAutomatically(Account account, String authority, boolean sync) { 3190 setSyncAutomaticallyAsUser(account, authority, sync, UserHandle.myUserId()); 3191 } 3192 3193 /** 3194 * @see #setSyncAutomatically(Account, String, boolean) 3195 * @hide 3196 */ 3197 public static void setSyncAutomaticallyAsUser(Account account, String authority, boolean sync, 3198 @UserIdInt int userId) { 3199 try { 3200 getContentService().setSyncAutomaticallyAsUser(account, authority, sync, userId); 3201 } catch (RemoteException e) { 3202 throw e.rethrowFromSystemServer(); 3203 } 3204 } 3205 3206 /** 3207 * Specifies that a sync should be requested with the specified the account, authority, 3208 * and extras at the given frequency. If there is already another periodic sync scheduled 3209 * with the account, authority and extras then a new periodic sync won't be added, instead 3210 * the frequency of the previous one will be updated. 3211 * <p> 3212 * These periodic syncs honor the "syncAutomatically" and "masterSyncAutomatically" settings. 3213 * Although these sync are scheduled at the specified frequency, it may take longer for it to 3214 * actually be started if other syncs are ahead of it in the sync operation queue. This means 3215 * that the actual start time may drift. 3216 * <p> 3217 * Periodic syncs are not allowed to have any of {@link #SYNC_EXTRAS_DO_NOT_RETRY}, 3218 * {@link #SYNC_EXTRAS_IGNORE_BACKOFF}, {@link #SYNC_EXTRAS_IGNORE_SETTINGS}, 3219 * {@link #SYNC_EXTRAS_INITIALIZE}, {@link #SYNC_EXTRAS_FORCE}, 3220 * {@link #SYNC_EXTRAS_EXPEDITED}, {@link #SYNC_EXTRAS_MANUAL} set to true. 3221 * If any are supplied then an {@link IllegalArgumentException} will be thrown. 3222 * 3223 * <p>This method requires the caller to hold the permission 3224 * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}. 3225 * <p>The bundle for a periodic sync can be queried by applications with the correct 3226 * permissions using 3227 * {@link ContentResolver#getPeriodicSyncs(Account account, String provider)}, so no 3228 * sensitive data should be transferred here. 3229 * 3230 * @param account the account to specify in the sync 3231 * @param authority the provider to specify in the sync request 3232 * @param extras extra parameters to go along with the sync request 3233 * @param pollFrequency how frequently the sync should be performed, in seconds. 3234 * On Android API level 24 and above, a minmam interval of 15 minutes is enforced. 3235 * On previous versions, the minimum interval is 1 hour. 3236 * @throws IllegalArgumentException if an illegal extra was set or if any of the parameters 3237 * are null. 3238 */ 3239 public static void addPeriodicSync(Account account, String authority, Bundle extras, 3240 long pollFrequency) { 3241 validateSyncExtrasBundle(extras); 3242 if (invalidPeriodicExtras(extras)) { 3243 throw new IllegalArgumentException("illegal extras were set"); 3244 } 3245 try { 3246 getContentService().addPeriodicSync(account, authority, extras, pollFrequency); 3247 } catch (RemoteException e) { 3248 throw e.rethrowFromSystemServer(); 3249 } 3250 } 3251 3252 /** 3253 * {@hide} 3254 * Helper function to throw an <code>IllegalArgumentException</code> if any illegal 3255 * extras were set for a periodic sync. 3256 * 3257 * @param extras bundle to validate. 3258 */ 3259 public static boolean invalidPeriodicExtras(Bundle extras) { 3260 if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false) 3261 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false) 3262 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false) 3263 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false) 3264 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false) 3265 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false) 3266 || extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) { 3267 return true; 3268 } 3269 return false; 3270 } 3271 3272 /** 3273 * Remove a periodic sync. Has no affect if account, authority and extras don't match 3274 * an existing periodic sync. 3275 * <p>This method requires the caller to hold the permission 3276 * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}. 3277 * 3278 * @param account the account of the periodic sync to remove 3279 * @param authority the provider of the periodic sync to remove 3280 * @param extras the extras of the periodic sync to remove 3281 */ 3282 public static void removePeriodicSync(Account account, String authority, Bundle extras) { 3283 validateSyncExtrasBundle(extras); 3284 try { 3285 getContentService().removePeriodicSync(account, authority, extras); 3286 } catch (RemoteException e) { 3287 throw e.rethrowFromSystemServer(); 3288 } 3289 } 3290 3291 /** 3292 * Remove the specified sync. This will cancel any pending or active syncs. If the request is 3293 * for a periodic sync, this call will remove any future occurrences. 3294 * <p> 3295 * If a periodic sync is specified, the caller must hold the permission 3296 * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}. 3297 *</p> 3298 * It is possible to cancel a sync using a SyncRequest object that is not the same object 3299 * with which you requested the sync. Do so by building a SyncRequest with the same 3300 * adapter, frequency, <b>and</b> extras bundle. 3301 * 3302 * @param request SyncRequest object containing information about sync to cancel. 3303 */ 3304 public static void cancelSync(SyncRequest request) { 3305 if (request == null) { 3306 throw new IllegalArgumentException("request cannot be null"); 3307 } 3308 try { 3309 getContentService().cancelRequest(request); 3310 } catch (RemoteException e) { 3311 throw e.rethrowFromSystemServer(); 3312 } 3313 } 3314 3315 /** 3316 * Get the list of information about the periodic syncs for the given account and authority. 3317 * <p>This method requires the caller to hold the permission 3318 * {@link android.Manifest.permission#READ_SYNC_SETTINGS}. 3319 * 3320 * @param account the account whose periodic syncs we are querying 3321 * @param authority the provider whose periodic syncs we are querying 3322 * @return a list of PeriodicSync objects. This list may be empty but will never be null. 3323 */ 3324 public static List<PeriodicSync> getPeriodicSyncs(Account account, String authority) { 3325 try { 3326 return getContentService().getPeriodicSyncs(account, authority, null); 3327 } catch (RemoteException e) { 3328 throw e.rethrowFromSystemServer(); 3329 } 3330 } 3331 3332 /** 3333 * Check if this account/provider is syncable. 3334 * <p>This method requires the caller to hold the permission 3335 * {@link android.Manifest.permission#READ_SYNC_SETTINGS}. 3336 * @return >0 if it is syncable, 0 if not, and <0 if the state isn't known yet. 3337 */ 3338 public static int getIsSyncable(Account account, String authority) { 3339 try { 3340 return getContentService().getIsSyncable(account, authority); 3341 } catch (RemoteException e) { 3342 throw e.rethrowFromSystemServer(); 3343 } 3344 } 3345 3346 /** 3347 * @see #getIsSyncable(Account, String) 3348 * @hide 3349 */ 3350 public static int getIsSyncableAsUser(Account account, String authority, 3351 @UserIdInt int userId) { 3352 try { 3353 return getContentService().getIsSyncableAsUser(account, authority, userId); 3354 } catch (RemoteException e) { 3355 throw e.rethrowFromSystemServer(); 3356 } 3357 } 3358 3359 /** 3360 * Set whether this account/provider is syncable. 3361 * <p>This method requires the caller to hold the permission 3362 * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}. 3363 * @param syncable >0 denotes syncable, 0 means not syncable, <0 means unknown 3364 */ 3365 public static void setIsSyncable(Account account, String authority, int syncable) { 3366 try { 3367 getContentService().setIsSyncable(account, authority, syncable); 3368 } catch (RemoteException e) { 3369 throw e.rethrowFromSystemServer(); 3370 } 3371 } 3372 3373 /** 3374 * @see #setIsSyncable(Account, String, int) 3375 * @hide 3376 */ 3377 public static void setIsSyncableAsUser(Account account, String authority, int syncable, 3378 int userId) { 3379 try { 3380 getContentService().setIsSyncableAsUser(account, authority, syncable, userId); 3381 } catch (RemoteException e) { 3382 throw e.rethrowFromSystemServer(); 3383 } 3384 } 3385 3386 /** 3387 * Gets the master auto-sync setting that applies to all the providers and accounts. 3388 * If this is false then the per-provider auto-sync setting is ignored. 3389 * <p>This method requires the caller to hold the permission 3390 * {@link android.Manifest.permission#READ_SYNC_SETTINGS}. 3391 * 3392 * @return the master auto-sync setting that applies to all the providers and accounts 3393 */ 3394 public static boolean getMasterSyncAutomatically() { 3395 try { 3396 return getContentService().getMasterSyncAutomatically(); 3397 } catch (RemoteException e) { 3398 throw e.rethrowFromSystemServer(); 3399 } 3400 } 3401 3402 /** 3403 * @see #getMasterSyncAutomatically() 3404 * @hide 3405 */ 3406 public static boolean getMasterSyncAutomaticallyAsUser(@UserIdInt int userId) { 3407 try { 3408 return getContentService().getMasterSyncAutomaticallyAsUser(userId); 3409 } catch (RemoteException e) { 3410 throw e.rethrowFromSystemServer(); 3411 } 3412 } 3413 3414 /** 3415 * Sets the master auto-sync setting that applies to all the providers and accounts. 3416 * If this is false then the per-provider auto-sync setting is ignored. 3417 * <p>This method requires the caller to hold the permission 3418 * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}. 3419 * 3420 * @param sync the master auto-sync setting that applies to all the providers and accounts 3421 */ 3422 public static void setMasterSyncAutomatically(boolean sync) { 3423 setMasterSyncAutomaticallyAsUser(sync, UserHandle.myUserId()); 3424 } 3425 3426 /** 3427 * @see #setMasterSyncAutomatically(boolean) 3428 * @hide 3429 */ 3430 public static void setMasterSyncAutomaticallyAsUser(boolean sync, @UserIdInt int userId) { 3431 try { 3432 getContentService().setMasterSyncAutomaticallyAsUser(sync, userId); 3433 } catch (RemoteException e) { 3434 throw e.rethrowFromSystemServer(); 3435 } 3436 } 3437 3438 /** 3439 * Returns true if there is currently a sync operation for the given account or authority 3440 * actively being processed. 3441 * <p>This method requires the caller to hold the permission 3442 * {@link android.Manifest.permission#READ_SYNC_STATS}. 3443 * @param account the account whose setting we are querying 3444 * @param authority the provider whose behavior is being queried 3445 * @return true if a sync is active for the given account or authority. 3446 */ 3447 public static boolean isSyncActive(Account account, String authority) { 3448 if (account == null) { 3449 throw new IllegalArgumentException("account must not be null"); 3450 } 3451 if (authority == null) { 3452 throw new IllegalArgumentException("authority must not be null"); 3453 } 3454 3455 try { 3456 return getContentService().isSyncActive(account, authority, null); 3457 } catch (RemoteException e) { 3458 throw e.rethrowFromSystemServer(); 3459 } 3460 } 3461 3462 /** 3463 * If a sync is active returns the information about it, otherwise returns null. 3464 * <p> 3465 * This method requires the caller to hold the permission 3466 * {@link android.Manifest.permission#READ_SYNC_STATS}. 3467 * <p> 3468 * @return the SyncInfo for the currently active sync or null if one is not active. 3469 * @deprecated 3470 * Since multiple concurrent syncs are now supported you should use 3471 * {@link #getCurrentSyncs()} to get the accurate list of current syncs. 3472 * This method returns the first item from the list of current syncs 3473 * or null if there are none. 3474 */ 3475 @Deprecated 3476 public static SyncInfo getCurrentSync() { 3477 try { 3478 final List<SyncInfo> syncs = getContentService().getCurrentSyncs(); 3479 if (syncs.isEmpty()) { 3480 return null; 3481 } 3482 return syncs.get(0); 3483 } catch (RemoteException e) { 3484 throw e.rethrowFromSystemServer(); 3485 } 3486 } 3487 3488 /** 3489 * Returns a list with information about all the active syncs. This list will be empty 3490 * if there are no active syncs. 3491 * <p> 3492 * This method requires the caller to hold the permission 3493 * {@link android.Manifest.permission#READ_SYNC_STATS}. 3494 * <p> 3495 * @return a List of SyncInfo objects for the currently active syncs. 3496 */ 3497 public static List<SyncInfo> getCurrentSyncs() { 3498 try { 3499 return getContentService().getCurrentSyncs(); 3500 } catch (RemoteException e) { 3501 throw e.rethrowFromSystemServer(); 3502 } 3503 } 3504 3505 /** 3506 * @see #getCurrentSyncs() 3507 * @hide 3508 */ 3509 public static List<SyncInfo> getCurrentSyncsAsUser(@UserIdInt int userId) { 3510 try { 3511 return getContentService().getCurrentSyncsAsUser(userId); 3512 } catch (RemoteException e) { 3513 throw e.rethrowFromSystemServer(); 3514 } 3515 } 3516 3517 /** 3518 * Returns the status that matches the authority. 3519 * @param account the account whose setting we are querying 3520 * @param authority the provider whose behavior is being queried 3521 * @return the SyncStatusInfo for the authority, or null if none exists 3522 * @hide 3523 */ 3524 @UnsupportedAppUsage 3525 public static SyncStatusInfo getSyncStatus(Account account, String authority) { 3526 try { 3527 return getContentService().getSyncStatus(account, authority, null); 3528 } catch (RemoteException e) { 3529 throw e.rethrowFromSystemServer(); 3530 } 3531 } 3532 3533 /** 3534 * @see #getSyncStatus(Account, String) 3535 * @hide 3536 */ 3537 @UnsupportedAppUsage 3538 public static SyncStatusInfo getSyncStatusAsUser(Account account, String authority, 3539 @UserIdInt int userId) { 3540 try { 3541 return getContentService().getSyncStatusAsUser(account, authority, null, userId); 3542 } catch (RemoteException e) { 3543 throw e.rethrowFromSystemServer(); 3544 } 3545 } 3546 3547 /** 3548 * Return true if the pending status is true of any matching authorities. 3549 * <p>This method requires the caller to hold the permission 3550 * {@link android.Manifest.permission#READ_SYNC_STATS}. 3551 * @param account the account whose setting we are querying 3552 * @param authority the provider whose behavior is being queried 3553 * @return true if there is a pending sync with the matching account and authority 3554 */ 3555 public static boolean isSyncPending(Account account, String authority) { 3556 return isSyncPendingAsUser(account, authority, UserHandle.myUserId()); 3557 } 3558 3559 /** 3560 * @see #requestSync(Account, String, Bundle) 3561 * @hide 3562 */ 3563 public static boolean isSyncPendingAsUser(Account account, String authority, 3564 @UserIdInt int userId) { 3565 try { 3566 return getContentService().isSyncPendingAsUser(account, authority, null, userId); 3567 } catch (RemoteException e) { 3568 throw e.rethrowFromSystemServer(); 3569 } 3570 } 3571 3572 /** 3573 * Request notifications when the different aspects of the SyncManager change. The 3574 * different items that can be requested are: 3575 * <ul> 3576 * <li> {@link #SYNC_OBSERVER_TYPE_PENDING} 3577 * <li> {@link #SYNC_OBSERVER_TYPE_ACTIVE} 3578 * <li> {@link #SYNC_OBSERVER_TYPE_SETTINGS} 3579 * </ul> 3580 * The caller can set one or more of the status types in the mask for any 3581 * given listener registration. 3582 * @param mask the status change types that will cause the callback to be invoked 3583 * @param callback observer to be invoked when the status changes 3584 * @return a handle that can be used to remove the listener at a later time 3585 */ 3586 public static Object addStatusChangeListener(int mask, final SyncStatusObserver callback) { 3587 if (callback == null) { 3588 throw new IllegalArgumentException("you passed in a null callback"); 3589 } 3590 try { 3591 ISyncStatusObserver.Stub observer = new ISyncStatusObserver.Stub() { 3592 @Override 3593 public void onStatusChanged(int which) throws RemoteException { 3594 callback.onStatusChanged(which); 3595 } 3596 }; 3597 getContentService().addStatusChangeListener(mask, observer); 3598 return observer; 3599 } catch (RemoteException e) { 3600 throw e.rethrowFromSystemServer(); 3601 } 3602 } 3603 3604 /** 3605 * Remove a previously registered status change listener. 3606 * @param handle the handle that was returned by {@link #addStatusChangeListener} 3607 */ 3608 public static void removeStatusChangeListener(Object handle) { 3609 if (handle == null) { 3610 throw new IllegalArgumentException("you passed in a null handle"); 3611 } 3612 try { 3613 getContentService().removeStatusChangeListener((ISyncStatusObserver.Stub) handle); 3614 } catch (RemoteException e) { 3615 throw e.rethrowFromSystemServer(); 3616 } 3617 } 3618 3619 /** 3620 * Store the given {@link Bundle} as a long-lived cached object within the 3621 * system. This can be useful to avoid expensive re-parsing when apps are 3622 * restarted multiple times on low-RAM devices. 3623 * <p> 3624 * The {@link Bundle} is automatically invalidated when a 3625 * {@link #notifyChange(Uri, ContentObserver)} event applies to the key. 3626 * 3627 * @hide 3628 */ 3629 @SystemApi 3630 @RequiresPermission(android.Manifest.permission.CACHE_CONTENT) 3631 public void putCache(@NonNull Uri key, @Nullable Bundle value) { 3632 try { 3633 getContentService().putCache(mContext.getPackageName(), key, value, 3634 mContext.getUserId()); 3635 } catch (RemoteException e) { 3636 throw e.rethrowFromSystemServer(); 3637 } 3638 } 3639 3640 /** 3641 * Retrieve the last {@link Bundle} stored as a long-lived cached object 3642 * within the system. 3643 * 3644 * @return {@code null} if no cached object has been stored, or if the 3645 * stored object has been invalidated due to a 3646 * {@link #notifyChange(Uri, ContentObserver)} event. 3647 * @hide 3648 */ 3649 @SystemApi 3650 @RequiresPermission(android.Manifest.permission.CACHE_CONTENT) 3651 public @Nullable Bundle getCache(@NonNull Uri key) { 3652 try { 3653 final Bundle bundle = getContentService().getCache(mContext.getPackageName(), key, 3654 mContext.getUserId()); 3655 if (bundle != null) bundle.setClassLoader(mContext.getClassLoader()); 3656 return bundle; 3657 } catch (RemoteException e) { 3658 throw e.rethrowFromSystemServer(); 3659 } 3660 } 3661 3662 /** {@hide} */ 3663 public int getTargetSdkVersion() { 3664 return mTargetSdkVersion; 3665 } 3666 3667 /** 3668 * Returns sampling percentage for a given duration. 3669 * 3670 * Always returns at least 1%. 3671 */ 3672 private int samplePercentForDuration(long durationMillis) { 3673 if (durationMillis >= SLOW_THRESHOLD_MILLIS) { 3674 return 100; 3675 } 3676 return (int) (100 * durationMillis / SLOW_THRESHOLD_MILLIS) + 1; 3677 } 3678 3679 private void maybeLogQueryToEventLog( 3680 long durationMillis, Uri uri, String[] projection, @Nullable Bundle queryArgs) { 3681 if (!ENABLE_CONTENT_SAMPLE) return; 3682 int samplePercent = samplePercentForDuration(durationMillis); 3683 if (samplePercent < 100) { 3684 synchronized (mRandom) { 3685 if (mRandom.nextInt(100) >= samplePercent) { 3686 return; 3687 } 3688 } 3689 } 3690 3691 // Ensure a non-null bundle. 3692 queryArgs = (queryArgs != null) ? queryArgs : Bundle.EMPTY; 3693 3694 StringBuilder projectionBuffer = new StringBuilder(100); 3695 if (projection != null) { 3696 for (int i = 0; i < projection.length; ++i) { 3697 // Note: not using a comma delimiter here, as the 3698 // multiple arguments to EventLog.writeEvent later 3699 // stringify with a comma delimiter, which would make 3700 // parsing uglier later. 3701 if (i != 0) projectionBuffer.append('/'); 3702 projectionBuffer.append(projection[i]); 3703 } 3704 } 3705 3706 // ActivityThread.currentPackageName() only returns non-null if the 3707 // current thread is an application main thread. This parameter tells 3708 // us whether an event loop is blocked, and if so, which app it is. 3709 String blockingPackage = AppGlobals.getInitialPackage(); 3710 3711 EventLog.writeEvent( 3712 EventLogTags.CONTENT_QUERY_SAMPLE, 3713 uri.toString(), 3714 projectionBuffer.toString(), 3715 queryArgs.getString(QUERY_ARG_SQL_SELECTION, ""), 3716 queryArgs.getString(QUERY_ARG_SQL_SORT_ORDER, ""), 3717 durationMillis, 3718 blockingPackage != null ? blockingPackage : "", 3719 samplePercent); 3720 } 3721 3722 private void maybeLogUpdateToEventLog( 3723 long durationMillis, Uri uri, String operation, String selection) { 3724 if (!ENABLE_CONTENT_SAMPLE) return; 3725 int samplePercent = samplePercentForDuration(durationMillis); 3726 if (samplePercent < 100) { 3727 synchronized (mRandom) { 3728 if (mRandom.nextInt(100) >= samplePercent) { 3729 return; 3730 } 3731 } 3732 } 3733 String blockingPackage = AppGlobals.getInitialPackage(); 3734 EventLog.writeEvent( 3735 EventLogTags.CONTENT_UPDATE_SAMPLE, 3736 uri.toString(), 3737 operation, 3738 selection != null ? selection : "", 3739 durationMillis, 3740 blockingPackage != null ? blockingPackage : "", 3741 samplePercent); 3742 } 3743 3744 private final class CursorWrapperInner extends CrossProcessCursorWrapper { 3745 private final IContentProvider mContentProvider; 3746 private final AtomicBoolean mProviderReleased = new AtomicBoolean(); 3747 3748 private final CloseGuard mCloseGuard = CloseGuard.get(); 3749 3750 CursorWrapperInner(Cursor cursor, IContentProvider contentProvider) { 3751 super(cursor); 3752 mContentProvider = contentProvider; 3753 mCloseGuard.open("close"); 3754 } 3755 3756 @Override 3757 public void close() { 3758 mCloseGuard.close(); 3759 super.close(); 3760 3761 if (mProviderReleased.compareAndSet(false, true)) { 3762 ContentResolver.this.releaseProvider(mContentProvider); 3763 } 3764 } 3765 3766 @Override 3767 protected void finalize() throws Throwable { 3768 try { 3769 if (mCloseGuard != null) { 3770 mCloseGuard.warnIfOpen(); 3771 } 3772 3773 close(); 3774 } finally { 3775 super.finalize(); 3776 } 3777 } 3778 } 3779 3780 private final class ParcelFileDescriptorInner extends ParcelFileDescriptor { 3781 private final IContentProvider mContentProvider; 3782 private final AtomicBoolean mProviderReleased = new AtomicBoolean(); 3783 3784 ParcelFileDescriptorInner(ParcelFileDescriptor pfd, IContentProvider icp) { 3785 super(pfd); 3786 mContentProvider = icp; 3787 } 3788 3789 @Override 3790 public void releaseResources() { 3791 if (mProviderReleased.compareAndSet(false, true)) { 3792 ContentResolver.this.releaseProvider(mContentProvider); 3793 } 3794 } 3795 } 3796 3797 /** @hide */ 3798 public static final String CONTENT_SERVICE_NAME = "content"; 3799 3800 /** @hide */ 3801 @UnsupportedAppUsage 3802 public static IContentService getContentService() { 3803 if (sContentService != null) { 3804 return sContentService; 3805 } 3806 IBinder b = ServiceManager.getService(CONTENT_SERVICE_NAME); 3807 sContentService = IContentService.Stub.asInterface(b); 3808 return sContentService; 3809 } 3810 3811 /** @hide */ 3812 @UnsupportedAppUsage 3813 public String getPackageName() { 3814 return mPackageName; 3815 } 3816 3817 /** @hide */ 3818 public @Nullable String getAttributionTag() { 3819 return mAttributionTag; 3820 } 3821 3822 @UnsupportedAppUsage 3823 private static volatile IContentService sContentService; 3824 @UnsupportedAppUsage 3825 private final Context mContext; 3826 3827 @UnsupportedAppUsage 3828 final String mPackageName; 3829 final @Nullable String mAttributionTag; 3830 final int mTargetSdkVersion; 3831 final ContentInterface mWrapped; 3832 3833 private static final String TAG = "ContentResolver"; 3834 3835 /** @hide */ 3836 public int resolveUserId(Uri uri) { 3837 return ContentProvider.getUserIdFromUri(uri, mContext.getUserId()); 3838 } 3839 3840 /** @hide */ 3841 public int getUserId() { 3842 return mContext.getUserId(); 3843 } 3844 3845 /** {@hide} */ 3846 @Deprecated 3847 public Drawable getTypeDrawable(String mimeType) { 3848 return getTypeInfo(mimeType).getIcon().loadDrawable(mContext); 3849 } 3850 3851 /** 3852 * Return a detailed description of the given MIME type, including an icon 3853 * and label that describe the type. 3854 * 3855 * @param mimeType Valid, concrete MIME type. 3856 */ 3857 public final @NonNull MimeTypeInfo getTypeInfo(@NonNull String mimeType) { 3858 Objects.requireNonNull(mimeType); 3859 return MimeIconUtils.getTypeInfo(mimeType); 3860 } 3861 3862 /** 3863 * Detailed description of a specific MIME type, including an icon and label 3864 * that describe the type. 3865 */ 3866 public static final class MimeTypeInfo { 3867 private final Icon mIcon; 3868 private final CharSequence mLabel; 3869 private final CharSequence mContentDescription; 3870 3871 /** {@hide} */ 3872 public MimeTypeInfo(@NonNull Icon icon, @NonNull CharSequence label, 3873 @NonNull CharSequence contentDescription) { 3874 mIcon = Objects.requireNonNull(icon); 3875 mLabel = Objects.requireNonNull(label); 3876 mContentDescription = Objects.requireNonNull(contentDescription); 3877 } 3878 3879 /** 3880 * Return a visual representation of this MIME type. This can be styled 3881 * using {@link Icon#setTint(int)} to match surrounding UI. 3882 * 3883 * @see Icon#loadDrawable(Context) 3884 * @see android.widget.ImageView#setImageDrawable(Drawable) 3885 */ 3886 public @NonNull Icon getIcon() { 3887 return mIcon; 3888 } 3889 3890 /** 3891 * Return a textual representation of this MIME type. 3892 * 3893 * @see android.widget.TextView#setText(CharSequence) 3894 */ 3895 public @NonNull CharSequence getLabel() { 3896 return mLabel; 3897 } 3898 3899 /** 3900 * Return a content description for this MIME type. 3901 * 3902 * @see android.view.View#setContentDescription(CharSequence) 3903 */ 3904 public @NonNull CharSequence getContentDescription() { 3905 return mContentDescription; 3906 } 3907 } 3908 3909 /** 3910 * @hide 3911 */ 3912 public static @Nullable Bundle createSqlQueryBundle( 3913 @Nullable String selection, 3914 @Nullable String[] selectionArgs) { 3915 return createSqlQueryBundle(selection, selectionArgs, null); 3916 } 3917 3918 /** 3919 * @hide 3920 */ 3921 public static @Nullable Bundle createSqlQueryBundle( 3922 @Nullable String selection, 3923 @Nullable String[] selectionArgs, 3924 @Nullable String sortOrder) { 3925 3926 if (selection == null && selectionArgs == null && sortOrder == null) { 3927 return null; 3928 } 3929 3930 Bundle queryArgs = new Bundle(); 3931 if (selection != null) { 3932 queryArgs.putString(QUERY_ARG_SQL_SELECTION, selection); 3933 } 3934 if (selectionArgs != null) { 3935 queryArgs.putStringArray(QUERY_ARG_SQL_SELECTION_ARGS, selectionArgs); 3936 } 3937 if (sortOrder != null) { 3938 queryArgs.putString(QUERY_ARG_SQL_SORT_ORDER, sortOrder); 3939 } 3940 return queryArgs; 3941 } 3942 3943 /** @hide */ 3944 public static @NonNull Bundle includeSqlSelectionArgs(@NonNull Bundle queryArgs, 3945 @Nullable String selection, @Nullable String[] selectionArgs) { 3946 if (selection != null) { 3947 queryArgs.putString(QUERY_ARG_SQL_SELECTION, selection); 3948 } 3949 if (selectionArgs != null) { 3950 queryArgs.putStringArray(QUERY_ARG_SQL_SELECTION_ARGS, selectionArgs); 3951 } 3952 return queryArgs; 3953 } 3954 3955 /** 3956 * Returns structured sort args formatted as an SQL sort clause. 3957 * 3958 * NOTE: Collator clauses are suitable for use with non text fields. We might 3959 * choose to omit any collation clause since we don't know the underlying 3960 * type of data to be collated. Imperical testing shows that sqlite3 doesn't 3961 * appear to care much about the presence of collate clauses in queries 3962 * when ordering by numeric fields. For this reason we include collate 3963 * clause unilaterally when {@link #QUERY_ARG_SORT_COLLATION} is present 3964 * in query args bundle. 3965 * 3966 * TODO: Would be nice to explicitly validate that colums referenced in 3967 * {@link #QUERY_ARG_SORT_COLUMNS} are present in the associated projection. 3968 * 3969 * @hide 3970 */ 3971 public static String createSqlSortClause(Bundle queryArgs) { 3972 String[] columns = queryArgs.getStringArray(QUERY_ARG_SORT_COLUMNS); 3973 if (columns == null || columns.length == 0) { 3974 throw new IllegalArgumentException("Can't create sort clause without columns."); 3975 } 3976 3977 String query = TextUtils.join(", ", columns); 3978 3979 // Interpret PRIMARY and SECONDARY collation strength as no-case collation based 3980 // on their javadoc descriptions. 3981 int collation = queryArgs.getInt( 3982 ContentResolver.QUERY_ARG_SORT_COLLATION, java.text.Collator.IDENTICAL); 3983 if (collation == java.text.Collator.PRIMARY || collation == java.text.Collator.SECONDARY) { 3984 query += " COLLATE NOCASE"; 3985 } 3986 3987 int sortDir = queryArgs.getInt(QUERY_ARG_SORT_DIRECTION, Integer.MIN_VALUE); 3988 if (sortDir != Integer.MIN_VALUE) { 3989 switch (sortDir) { 3990 case QUERY_SORT_DIRECTION_ASCENDING: 3991 query += " ASC"; 3992 break; 3993 case QUERY_SORT_DIRECTION_DESCENDING: 3994 query += " DESC"; 3995 break; 3996 default: 3997 throw new IllegalArgumentException("Unsupported sort direction value." 3998 + " See ContentResolver documentation for details."); 3999 } 4000 } 4001 return query; 4002 } 4003 4004 /** 4005 * Convenience method that efficiently loads a visual thumbnail for the 4006 * given {@link Uri}. Internally calls 4007 * {@link ContentProvider#openTypedAssetFile} on the remote provider, but 4008 * also defensively resizes any returned content to match the requested 4009 * target size. 4010 * 4011 * @param uri The item that should be visualized as a thumbnail. 4012 * @param size The target area on the screen where this thumbnail will be 4013 * shown. This is passed to the provider as {@link #EXTRA_SIZE} 4014 * to help it avoid downloading or generating heavy resources. 4015 * @param signal A signal to cancel the operation in progress. 4016 * @return Valid {@link Bitmap} which is a visual thumbnail. 4017 * @throws IOException If any trouble was encountered while generating or 4018 * loading the thumbnail, or if 4019 * {@link CancellationSignal#cancel()} was invoked. 4020 */ 4021 public @NonNull Bitmap loadThumbnail(@NonNull Uri uri, @NonNull Size size, 4022 @Nullable CancellationSignal signal) throws IOException { 4023 return loadThumbnail(this, uri, size, signal, ImageDecoder.ALLOCATOR_SOFTWARE); 4024 } 4025 4026 /** {@hide} */ 4027 public static Bitmap loadThumbnail(@NonNull ContentInterface content, @NonNull Uri uri, 4028 @NonNull Size size, @Nullable CancellationSignal signal, int allocator) 4029 throws IOException { 4030 Objects.requireNonNull(content); 4031 Objects.requireNonNull(uri); 4032 Objects.requireNonNull(size); 4033 4034 // Convert to Point, since that's what the API is defined as 4035 final Bundle opts = new Bundle(); 4036 opts.putParcelable(EXTRA_SIZE, Point.convert(size)); 4037 final Int32Ref orientation = new Int32Ref(0); 4038 4039 Bitmap bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(() -> { 4040 final AssetFileDescriptor afd = content.openTypedAssetFile(uri, "image/*", opts, 4041 signal); 4042 final Bundle extras = afd.getExtras(); 4043 orientation.value = (extras != null) ? extras.getInt(EXTRA_ORIENTATION, 0) : 0; 4044 return afd; 4045 }), (ImageDecoder decoder, ImageInfo info, Source source) -> { 4046 decoder.setAllocator(allocator); 4047 4048 // One last-ditch check to see if we've been canceled. 4049 if (signal != null) signal.throwIfCanceled(); 4050 4051 // We requested a rough thumbnail size, but the remote size may have 4052 // returned something giant, so defensively scale down as needed. 4053 final int widthSample = info.getSize().getWidth() / size.getWidth(); 4054 final int heightSample = info.getSize().getHeight() / size.getHeight(); 4055 final int sample = Math.max(widthSample, heightSample); 4056 if (sample > 1) { 4057 decoder.setTargetSampleSize(sample); 4058 } 4059 }); 4060 4061 // Transform the bitmap if requested. We use a side-channel to 4062 // communicate the orientation, since EXIF thumbnails don't contain 4063 // the rotation flags of the original image. 4064 if (orientation.value != 0) { 4065 final int width = bitmap.getWidth(); 4066 final int height = bitmap.getHeight(); 4067 4068 final Matrix m = new Matrix(); 4069 m.setRotate(orientation.value, width / 2, height / 2); 4070 bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, m, false); 4071 } 4072 4073 return bitmap; 4074 } 4075 4076 /** {@hide} */ 4077 public static void onDbCorruption(String tag, String message, Throwable stacktrace) { 4078 try { 4079 getContentService().onDbCorruption(tag, message, Log.getStackTraceString(stacktrace)); 4080 } catch (RemoteException e) { 4081 e.rethrowFromSystemServer(); 4082 } 4083 } 4084 4085 /** 4086 * Decode a path generated by {@link #encodeToFile(Uri)} back into 4087 * the original {@link Uri}. 4088 * <p> 4089 * This is used to offer a way to intercept filesystem calls in 4090 * {@link ContentProvider} unaware code and redirect them to a 4091 * {@link ContentProvider} when they attempt to use {@code _DATA} columns 4092 * that are otherwise deprecated. 4093 * 4094 * @hide 4095 */ 4096 @SystemApi 4097 @TestApi 4098 // We can't accept an already-opened FD here, since these methods are 4099 // rewriting actual filesystem paths 4100 @SuppressLint("StreamFiles") 4101 public static @NonNull Uri decodeFromFile(@NonNull File file) { 4102 return translateDeprecatedDataPath(file.getAbsolutePath()); 4103 } 4104 4105 /** 4106 * Encode a {@link Uri} into an opaque filesystem path which can then be 4107 * resurrected by {@link #decodeFromFile(File)}. 4108 * <p> 4109 * This is used to offer a way to intercept filesystem calls in 4110 * {@link ContentProvider} unaware code and redirect them to a 4111 * {@link ContentProvider} when they attempt to use {@code _DATA} columns 4112 * that are otherwise deprecated. 4113 * 4114 * @hide 4115 */ 4116 @SystemApi 4117 @TestApi 4118 // We can't accept an already-opened FD here, since these methods are 4119 // rewriting actual filesystem paths 4120 @SuppressLint("StreamFiles") 4121 public static @NonNull File encodeToFile(@NonNull Uri uri) { 4122 return new File(translateDeprecatedDataPath(uri)); 4123 } 4124 4125 /** {@hide} */ 4126 public static @NonNull Uri translateDeprecatedDataPath(@NonNull String path) { 4127 final String ssp = "//" + path.substring(DEPRECATE_DATA_PREFIX.length()); 4128 return Uri.parse(new Uri.Builder().scheme(SCHEME_CONTENT) 4129 .encodedOpaquePart(ssp).build().toString()); 4130 } 4131 4132 /** {@hide} */ 4133 public static @NonNull String translateDeprecatedDataPath(@NonNull Uri uri) { 4134 return DEPRECATE_DATA_PREFIX + uri.getEncodedSchemeSpecificPart().substring(2); 4135 } 4136 } 4137