diff options
Diffstat (limited to 'core/java/android/content/ContentResolver.java')
| -rw-r--r-- | core/java/android/content/ContentResolver.java | 184 |
1 files changed, 125 insertions, 59 deletions
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 9ccc552f77f5..32a674363535 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -51,7 +51,6 @@ import android.text.TextUtils; import android.util.EventLog; import android.util.Log; -import com.android.internal.util.ArrayUtils; import com.android.internal.util.MimeIconUtils; import com.android.internal.util.Preconditions; @@ -166,6 +165,15 @@ public abstract class ContentResolver { public static final String SYNC_EXTRAS_DISALLOW_METERED = "allow_metered"; /** + * {@hide} Integer extra containing a SyncExemption flag. + * + * Only the system and the shell user can set it. + * + * This extra is "virtual". Once passed to the system server, it'll be removed from the bundle. + */ + public static final String SYNC_VIRTUAL_EXTRAS_EXEMPTION_FLAG = "v_exemption"; + + /** * Set by the SyncManager to request that the SyncAdapter initialize itself for * the given account/authority pair. One required initialization step is to * ensure that {@link #setIsSyncable(android.accounts.Account, String, int)} has been @@ -335,7 +343,7 @@ public abstract class ContentResolver { public static final String EXTRA_HONORED_ARGS = "android.content.extra.HONORED_ARGS"; /** @hide */ - @IntDef(flag = false, value = { + @IntDef(flag = false, prefix = { "QUERY_SORT_DIRECTION_" }, value = { QUERY_SORT_DIRECTION_ASCENDING, QUERY_SORT_DIRECTION_DESCENDING }) @@ -482,11 +490,10 @@ public abstract class ContentResolver { public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff; /** @hide */ - @IntDef(flag = true, - value = { - NOTIFY_SYNC_TO_NETWORK, - NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS - }) + @IntDef(flag = true, prefix = { "NOTIFY_" }, value = { + NOTIFY_SYNC_TO_NETWORK, + NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS + }) @Retention(RetentionPolicy.SOURCE) public @interface NotifyFlags {} @@ -506,6 +513,47 @@ public abstract class ContentResolver { */ public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 1<<1; + /** + * No exception, throttled by app standby normally. + * @hide + */ + public static final int SYNC_EXEMPTION_NONE = 0; + + /** + * Exemption given to a sync request made by a foreground app (including + * PROCESS_STATE_IMPORTANT_FOREGROUND). + * + * At the schedule time, we promote the sync adapter app for a higher bucket: + * - If the device is not dozing (so the sync will start right away) + * promote to ACTIVE for 1 hour. + * - If the device is dozing (so the sync *won't* start right away), + * promote to WORKING_SET for 4 hours, so it'll get a higher chance to be started once the + * device comes out of doze. + * - When the sync actually starts, we promote the sync adapter app to ACTIVE for 10 minutes, + * so it can schedule and start more syncs without getting throttled, even when the first + * operation was canceled and now we're retrying. + * + * + * @hide + */ + public static final int SYNC_EXEMPTION_PROMOTE_BUCKET = 1; + + /** + * In addition to {@link #SYNC_EXEMPTION_PROMOTE_BUCKET}, we put the sync adapter app in the + * temp whitelist for 10 minutes, so that even RARE apps can run syncs right away. + * @hide + */ + public static final int SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP = 2; + + /** @hide */ + @IntDef(flag = false, prefix = { "SYNC_EXEMPTION_" }, value = { + SYNC_EXEMPTION_NONE, + SYNC_EXEMPTION_PROMOTE_BUCKET, + SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SyncExemption {} + // Always log queries which take 500ms+; shorter queries are // sampled accordingly. private static final boolean ENABLE_CONTENT_SAMPLE = false; @@ -562,6 +610,8 @@ public abstract class ContentResolver { try { return provider.getType(url); } catch (RemoteException e) { + // Arbitrary and not worth documenting, as Activity + // Manager will kill this process shortly anyway. return null; } catch (java.lang.Exception e) { Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")"); @@ -580,9 +630,7 @@ public abstract class ContentResolver { ContentProvider.getUriWithoutUserId(url), resolveUserId(url)); return type; } catch (RemoteException e) { - // Arbitrary and not worth documenting, as Activity - // Manager will kill this process shortly anyway. - return null; + throw e.rethrowFromSystemServer(); } catch (java.lang.Exception e) { Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")"); return null; @@ -1924,6 +1972,7 @@ public abstract class ContentResolver { getContentService().registerContentObserver(uri, notifyForDescendents, observer.getContentObserver(), userHandle, mTargetSdkVersion); } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } @@ -1942,6 +1991,7 @@ public abstract class ContentResolver { contentObserver); } } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } @@ -2049,6 +2099,7 @@ public abstract class ContentResolver { syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0, userHandle, mTargetSdkVersion); } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } @@ -2065,6 +2116,7 @@ public abstract class ContentResolver { observer != null && observer.deliverSelfNotifications(), flags, userHandle, mTargetSdkVersion); } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } @@ -2083,8 +2135,26 @@ public abstract class ContentResolver { Preconditions.checkNotNull(uri, "uri"); try { ActivityManager.getService().takePersistableUriPermission( - ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri)); + ContentProvider.getUriWithoutUserId(uri), modeFlags, /* toPackage= */ null, + resolveUserId(uri)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * @hide + */ + public void takePersistableUriPermission(@NonNull String toPackage, @NonNull Uri uri, + @Intent.AccessUriMode int modeFlags) { + Preconditions.checkNotNull(toPackage, "toPackage"); + Preconditions.checkNotNull(uri, "uri"); + try { + ActivityManager.getService().takePersistableUriPermission( + ContentProvider.getUriWithoutUserId(uri), modeFlags, toPackage, + resolveUserId(uri)); } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } @@ -2101,8 +2171,10 @@ public abstract class ContentResolver { Preconditions.checkNotNull(uri, "uri"); try { ActivityManager.getService().releasePersistableUriPermission( - ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri)); + ContentProvider.getUriWithoutUserId(uri), modeFlags, /* toPackage= */ null, + resolveUserId(uri)); } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } @@ -2121,7 +2193,7 @@ public abstract class ContentResolver { return ActivityManager.getService() .getPersistedUriPermissions(mPackageName, true).getList(); } catch (RemoteException e) { - throw new RuntimeException("Activity manager has died", e); + throw e.rethrowFromSystemServer(); } } @@ -2137,7 +2209,7 @@ public abstract class ContentResolver { return ActivityManager.getService() .getPersistedUriPermissions(mPackageName, false).getList(); } catch (RemoteException e) { - throw new RuntimeException("Activity manager has died", e); + throw e.rethrowFromSystemServer(); } } @@ -2216,7 +2288,7 @@ public abstract class ContentResolver { try { getContentService().syncAsUser(request, userId); } catch(RemoteException e) { - // Shouldn't happen. + throw e.rethrowFromSystemServer(); } } @@ -2228,7 +2300,7 @@ public abstract class ContentResolver { try { getContentService().sync(request); } catch(RemoteException e) { - // Shouldn't happen. + throw e.rethrowFromSystemServer(); } } @@ -2292,6 +2364,7 @@ public abstract class ContentResolver { try { getContentService().cancelSync(account, authority, null); } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } @@ -2303,6 +2376,7 @@ public abstract class ContentResolver { try { getContentService().cancelSyncAsUser(account, authority, null, userId); } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } @@ -2314,7 +2388,7 @@ public abstract class ContentResolver { try { return getContentService().getSyncAdapterTypes(); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2326,7 +2400,7 @@ public abstract class ContentResolver { try { return getContentService().getSyncAdapterTypesAsUser(userId); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2340,8 +2414,8 @@ public abstract class ContentResolver { try { return getContentService().getSyncAdapterPackagesForAuthorityAsUser(authority, userId); } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } - return ArrayUtils.emptyArray(String.class); } /** @@ -2357,7 +2431,7 @@ public abstract class ContentResolver { try { return getContentService().getSyncAutomatically(account, authority); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2370,7 +2444,7 @@ public abstract class ContentResolver { try { return getContentService().getSyncAutomaticallyAsUser(account, authority, userId); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2396,8 +2470,7 @@ public abstract class ContentResolver { try { getContentService().setSyncAutomaticallyAsUser(account, authority, sync, userId); } catch (RemoteException e) { - // exception ignored; if this is thrown then it means the runtime is in the midst of - // being restarted + throw e.rethrowFromSystemServer(); } } @@ -2428,28 +2501,22 @@ public abstract class ContentResolver { * @param account the account to specify in the sync * @param authority the provider to specify in the sync request * @param extras extra parameters to go along with the sync request - * @param pollFrequency how frequently the sync should be performed, in seconds. A minimum value - * of 1 hour is enforced. + * @param pollFrequency how frequently the sync should be performed, in seconds. + * On Android API level 24 and above, a minmam interval of 15 minutes is enforced. + * On previous versions, the minimum interval is 1 hour. * @throws IllegalArgumentException if an illegal extra was set or if any of the parameters * are null. */ public static void addPeriodicSync(Account account, String authority, Bundle extras, long pollFrequency) { validateSyncExtrasBundle(extras); - if (extras.getBoolean(SYNC_EXTRAS_MANUAL, false) - || extras.getBoolean(SYNC_EXTRAS_DO_NOT_RETRY, false) - || extras.getBoolean(SYNC_EXTRAS_IGNORE_BACKOFF, false) - || extras.getBoolean(SYNC_EXTRAS_IGNORE_SETTINGS, false) - || extras.getBoolean(SYNC_EXTRAS_INITIALIZE, false) - || extras.getBoolean(SYNC_EXTRAS_FORCE, false) - || extras.getBoolean(SYNC_EXTRAS_EXPEDITED, false)) { + if (invalidPeriodicExtras(extras)) { throw new IllegalArgumentException("illegal extras were set"); } try { getContentService().addPeriodicSync(account, authority, extras, pollFrequency); } catch (RemoteException e) { - // exception ignored; if this is thrown then it means the runtime is in the midst of - // being restarted + throw e.rethrowFromSystemServer(); } } @@ -2488,7 +2555,7 @@ public abstract class ContentResolver { try { getContentService().removePeriodicSync(account, authority, extras); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2512,8 +2579,7 @@ public abstract class ContentResolver { try { getContentService().cancelRequest(request); } catch (RemoteException e) { - // exception ignored; if this is thrown then it means the runtime is in the midst of - // being restarted + throw e.rethrowFromSystemServer(); } } @@ -2530,7 +2596,7 @@ public abstract class ContentResolver { try { return getContentService().getPeriodicSyncs(account, authority, null); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2544,7 +2610,7 @@ public abstract class ContentResolver { try { return getContentService().getIsSyncable(account, authority); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2557,7 +2623,7 @@ public abstract class ContentResolver { try { return getContentService().getIsSyncableAsUser(account, authority, userId); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2571,8 +2637,7 @@ public abstract class ContentResolver { try { getContentService().setIsSyncable(account, authority, syncable); } catch (RemoteException e) { - // exception ignored; if this is thrown then it means the runtime is in the midst of - // being restarted + throw e.rethrowFromSystemServer(); } } @@ -2588,7 +2653,7 @@ public abstract class ContentResolver { try { return getContentService().getMasterSyncAutomatically(); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2600,7 +2665,7 @@ public abstract class ContentResolver { try { return getContentService().getMasterSyncAutomaticallyAsUser(userId); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2624,8 +2689,7 @@ public abstract class ContentResolver { try { getContentService().setMasterSyncAutomaticallyAsUser(sync, userId); } catch (RemoteException e) { - // exception ignored; if this is thrown then it means the runtime is in the midst of - // being restarted + throw e.rethrowFromSystemServer(); } } @@ -2649,7 +2713,7 @@ public abstract class ContentResolver { try { return getContentService().isSyncActive(account, authority, null); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2675,7 +2739,7 @@ public abstract class ContentResolver { } return syncs.get(0); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2692,7 +2756,7 @@ public abstract class ContentResolver { try { return getContentService().getCurrentSyncs(); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2704,7 +2768,7 @@ public abstract class ContentResolver { try { return getContentService().getCurrentSyncsAsUser(userId); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2719,7 +2783,7 @@ public abstract class ContentResolver { try { return getContentService().getSyncStatus(account, authority, null); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2732,7 +2796,7 @@ public abstract class ContentResolver { try { return getContentService().getSyncStatusAsUser(account, authority, null, userId); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2757,7 +2821,7 @@ public abstract class ContentResolver { try { return getContentService().isSyncPendingAsUser(account, authority, null, userId); } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2789,7 +2853,7 @@ public abstract class ContentResolver { getContentService().addStatusChangeListener(mask, observer); return observer; } catch (RemoteException e) { - throw new RuntimeException("the ContentService should always be reachable", e); + throw e.rethrowFromSystemServer(); } } @@ -2804,8 +2868,7 @@ public abstract class ContentResolver { try { getContentService().removeStatusChangeListener((ISyncStatusObserver.Stub) handle); } catch (RemoteException e) { - // exception ignored; if this is thrown then it means the runtime is in the midst of - // being restarted + throw e.rethrowFromSystemServer(); } } @@ -2975,9 +3038,7 @@ public abstract class ContentResolver { return sContentService; } IBinder b = ServiceManager.getService(CONTENT_SERVICE_NAME); - if (false) Log.v("ContentService", "default service binder = " + b); sContentService = IContentService.Stub.asInterface(b); - if (false) Log.v("ContentService", "default service = " + sContentService); return sContentService; } @@ -2986,7 +3047,7 @@ public abstract class ContentResolver { return mPackageName; } - private static IContentService sContentService; + private static volatile IContentService sContentService; private final Context mContext; final String mPackageName; @@ -3000,6 +3061,11 @@ public abstract class ContentResolver { } /** @hide */ + public int getUserId() { + return mContext.getUserId(); + } + + /** @hide */ public Drawable getTypeDrawable(String mimeType) { return MimeIconUtils.loadMimeIcon(mContext, mimeType); } |
