Loading core/java/android/app/ApplicationPackageManager.java +8 −3 Original line number Diff line number Diff line Loading @@ -621,10 +621,15 @@ final class ApplicationPackageManager extends PackageManager { } @Override public ProviderInfo resolveContentProvider(String name, int flags) { public ProviderInfo resolveContentProvider(String name, int flags) { return resolveContentProviderAsUser(name, flags, mContext.getUserId()); } /** @hide **/ @Override public ProviderInfo resolveContentProviderAsUser(String name, int flags, int userId) { try { return mPM.resolveContentProvider(name, flags, mContext.getUserId()); return mPM.resolveContentProvider(name, flags, userId); } catch (RemoteException e) { throw new RuntimeException("Package manager has died", e); } Loading core/java/android/content/ContentResolver.java +99 −1 Original line number Diff line number Diff line Loading @@ -1751,6 +1751,15 @@ public abstract class ContentResolver { * @param extras any extras to pass to the SyncAdapter. */ public static void requestSync(Account account, String authority, Bundle extras) { requestSyncAsUser(account, authority, UserHandle.getCallingUserId(), extras); } /** * @see #requestSync(Account, String, Bundle) * @hide */ public static void requestSyncAsUser(Account account, String authority, int userId, Bundle extras) { if (extras == null) { throw new IllegalArgumentException("Must specify extras."); } Loading @@ -1760,7 +1769,11 @@ public abstract class ContentResolver { .setExtras(extras) .syncOnce() // Immediate sync. .build(); requestSync(request); try { getContentService().syncAsUser(request, userId); } catch(RemoteException e) { // Shouldn't happen. } } /** Loading Loading @@ -1838,6 +1851,17 @@ public abstract class ContentResolver { } } /** * @see #cancelSync(Account, String) * @hide */ public static void cancelSyncAsUser(Account account, String authority, int userId) { try { getContentService().cancelSyncAsUser(account, authority, null, userId); } catch (RemoteException e) { } } /** * Get information about the SyncAdapters that are known to the system. * @return an array of SyncAdapters that have registered with the system Loading @@ -1850,6 +1874,18 @@ public abstract class ContentResolver { } } /** * @see #getSyncAdapterTypes() * @hide */ public static SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) { try { return getContentService().getSyncAdapterTypesAsUser(userId); } catch (RemoteException e) { throw new RuntimeException("the ContentService should always be reachable", e); } } /** * Check if the provider should be synced when a network tickle is received * <p>This method requires the caller to hold the permission Loading @@ -1867,6 +1903,19 @@ public abstract class ContentResolver { } } /** * @see #getSyncAutomatically(Account, String) * @hide */ public static boolean getSyncAutomaticallyAsUser(Account account, String authority, int userId) { try { return getContentService().getSyncAutomaticallyAsUser(account, authority, userId); } catch (RemoteException e) { throw new RuntimeException("the ContentService should always be reachable", e); } } /** * Set whether or not the provider is synced when it receives a network tickle. * <p>This method requires the caller to hold the permission Loading Loading @@ -2031,6 +2080,18 @@ public abstract class ContentResolver { } } /** * @see #getIsSyncable(Account, String) * @hide */ public static int getIsSyncableAsUser(Account account, String authority, int userId) { try { return getContentService().getIsSyncableAsUser(account, authority, userId); } catch (RemoteException e) { throw new RuntimeException("the ContentService should always be reachable", e); } } /** * Set whether this account/provider is syncable. * <p>This method requires the caller to hold the permission Loading Loading @@ -2062,6 +2123,18 @@ public abstract class ContentResolver { } } /** * @see #getMasterSyncAutomatically() * @hide */ public static boolean getMasterSyncAutomaticallyAsUser(int userId) { try { return getContentService().getMasterSyncAutomaticallyAsUser(userId); } catch (RemoteException e) { throw new RuntimeException("the ContentService should always be reachable", e); } } /** * Sets the master auto-sync setting that applies to all the providers and accounts. * If this is false then the per-provider auto-sync setting is ignored. Loading Loading @@ -2146,6 +2219,18 @@ public abstract class ContentResolver { } } /** * @see #getCurrentSyncs() * @hide */ public static List<SyncInfo> getCurrentSyncsAsUser(int userId) { try { return getContentService().getCurrentSyncsAsUser(userId); } catch (RemoteException e) { throw new RuntimeException("the ContentService should always be reachable", e); } } /** * Returns the status that matches the authority. * @param account the account whose setting we are querying Loading @@ -2161,6 +2246,19 @@ public abstract class ContentResolver { } } /** * @see #getSyncStatus(Account, String) * @hide */ public static SyncStatusInfo getSyncStatusAsUser(Account account, String authority, int userId) { try { return getContentService().getSyncStatusAsUser(account, authority, null, userId); } catch (RemoteException e) { throw new RuntimeException("the ContentService should always be reachable", e); } } /** * Return true if the pending status is true of any matching authorities. * <p>This method requires the caller to hold the permission Loading core/java/android/content/IContentService.aidl +9 −0 Original line number Diff line number Diff line Loading @@ -60,7 +60,9 @@ interface IContentService { * Start a sync given a request. */ void sync(in SyncRequest request); void syncAsUser(in SyncRequest request, int userId); void cancelSync(in Account account, String authority, in ComponentName cname); void cancelSyncAsUser(in Account account, String authority, in ComponentName cname, int userId); /** Cancel a sync, providing information about the sync to be cancelled. */ void cancelRequest(in SyncRequest request); Loading @@ -71,6 +73,7 @@ interface IContentService { * @return true if the provider should be synced when a network tickle is received */ boolean getSyncAutomatically(in Account account, String providerName); boolean getSyncAutomaticallyAsUser(in Account account, String providerName, int userId); /** * Set whether or not the provider is synced when it receives a network tickle. Loading Loading @@ -114,6 +117,7 @@ interface IContentService { * @return >0 if it is syncable, 0 if not, and <0 if the state isn't known yet. */ int getIsSyncable(in Account account, String providerName); int getIsSyncableAsUser(in Account account, String providerName, int userId); /** * Set whether this account/provider is syncable. Loading @@ -124,14 +128,17 @@ interface IContentService { void setMasterSyncAutomatically(boolean flag); boolean getMasterSyncAutomatically(); boolean getMasterSyncAutomaticallyAsUser(int userId); List<SyncInfo> getCurrentSyncs(); List<SyncInfo> getCurrentSyncsAsUser(int userId); /** * Returns the types of the SyncAdapters that are registered with the system. * @return Returns the types of the SyncAdapters that are registered with the system. */ SyncAdapterType[] getSyncAdapterTypes(); SyncAdapterType[] getSyncAdapterTypesAsUser(int userId); /** * Returns true if there is currently a operation for the given account/authority or service Loading @@ -152,6 +159,8 @@ interface IContentService { * non-null. */ SyncStatusInfo getSyncStatus(in Account account, String authority, in ComponentName cname); SyncStatusInfo getSyncStatusAsUser(in Account account, String authority, in ComponentName cname, int userId); /** * Return true if the pending status is true of any matching authorities. Loading core/java/android/content/pm/PackageManager.java +13 −0 Original line number Diff line number Diff line Loading @@ -2477,6 +2477,19 @@ public abstract class PackageManager { public abstract ProviderInfo resolveContentProvider(String name, int flags); /** * Find a single content provider by its base path name. * * @param name The name of the provider to find. * @param flags Additional option flags. Currently should always be 0. * @param userId The user id. * * @return ContentProviderInfo Information about the provider, if found, * else null. * @hide */ public abstract ProviderInfo resolveContentProviderAsUser(String name, int flags, int userId); /** * Retrieve content provider information. * Loading services/core/java/com/android/server/content/ContentService.java +116 −14 Original line number Diff line number Diff line Loading @@ -172,11 +172,8 @@ public final class ContentService extends IContentService.Stub { throw new IllegalArgumentException("You must pass a valid uri and observer"); } final int callingUser = UserHandle.getCallingUserId(); if (callingUser != userHandle) { mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, enforceCrossUserPermission(userHandle, "no permission to observe other users' provider view"); } if (userHandle < 0) { if (userHandle == UserHandle.USER_CURRENT) { Loading Loading @@ -346,7 +343,15 @@ public final class ContentService extends IContentService.Stub { * @param request The request object. Validation of this object is done by its builder. */ public void sync(SyncRequest request) { int userId = UserHandle.getCallingUserId(); syncAsUser(request, UserHandle.getCallingUserId()); } /** * If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. */ public void syncAsUser(SyncRequest request, int userId) { enforceCrossUserPermission(userId, "no permission to request sync as user: " + userId); int callerUid = Binder.getCallingUid(); // This makes it so that future permission checks will be in the context of this // process rather than the caller's process. We will restore this before returning. Loading Loading @@ -399,11 +404,30 @@ public final class ContentService extends IContentService.Stub { */ @Override public void cancelSync(Account account, String authority, ComponentName cname) { cancelSyncAsUser(account, authority, cname, UserHandle.getCallingUserId()); } /** * Clear all scheduled sync operations that match the uri and cancel the active sync * if they match the authority and account, if they are present. * * <p> If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. * * @param account filter the pending and active syncs to cancel using this account, or null. * @param authority filter the pending and active syncs to cancel using this authority, or * null. * @param userId the user id for which to cancel sync operations. * @param cname cancel syncs running on this service, or null for provider/account. */ @Override public void cancelSyncAsUser(Account account, String authority, ComponentName cname, int userId) { if (authority != null && authority.length() == 0) { throw new IllegalArgumentException("Authority must be non-empty"); } int userId = UserHandle.getCallingUserId(); enforceCrossUserPermission(userId, "no permission to modify the sync settings for user " + userId); // This makes it so that future permission checks will be in the context of this // process rather than the caller's process. We will restore this before returning. long identityToken = clearCallingIdentity(); Loading Loading @@ -456,9 +480,23 @@ public final class ContentService extends IContentService.Stub { */ @Override public SyncAdapterType[] getSyncAdapterTypes() { return getSyncAdapterTypesAsUser(UserHandle.getCallingUserId()); } /** * Get information about the SyncAdapters that are known to the system for a particular user. * * <p> If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. * * @return an array of SyncAdapters that have registered with the system */ @Override public SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) { enforceCrossUserPermission(userId, "no permission to read sync settings for user " + userId); // This makes it so that future permission checks will be in the context of this // process rather than the caller's process. We will restore this before returning. final int userId = UserHandle.getCallingUserId(); final long identityToken = clearCallingIdentity(); try { SyncManager syncManager = getSyncManager(); Loading @@ -470,10 +508,20 @@ public final class ContentService extends IContentService.Stub { @Override public boolean getSyncAutomatically(Account account, String providerName) { return getSyncAutomaticallyAsUser(account, providerName, UserHandle.getCallingUserId()); } /** * If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. */ @Override public boolean getSyncAutomaticallyAsUser(Account account, String providerName, int userId) { enforceCrossUserPermission(userId, "no permission to read the sync settings for user " + userId); mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, "no permission to read the sync settings"); int userId = UserHandle.getCallingUserId(); long identityToken = clearCallingIdentity(); try { SyncManager syncManager = getSyncManager(); Loading Loading @@ -588,9 +636,18 @@ public final class ContentService extends IContentService.Stub { } public int getIsSyncable(Account account, String providerName) { return getIsSyncableAsUser(account, providerName, UserHandle.getCallingUserId()); } /** * If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. */ public int getIsSyncableAsUser(Account account, String providerName, int userId) { enforceCrossUserPermission(userId, "no permission to read the sync settings for user " + userId); mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, "no permission to read the sync settings"); int userId = UserHandle.getCallingUserId(); long identityToken = clearCallingIdentity(); try { Loading Loading @@ -627,10 +684,20 @@ public final class ContentService extends IContentService.Stub { @Override public boolean getMasterSyncAutomatically() { return getMasterSyncAutomaticallyAsUser(UserHandle.getCallingUserId()); } /** * If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. */ @Override public boolean getMasterSyncAutomaticallyAsUser(int userId) { enforceCrossUserPermission(userId, "no permission to read the sync settings for user " + userId); mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, "no permission to read the sync settings"); int userId = UserHandle.getCallingUserId(); long identityToken = clearCallingIdentity(); try { SyncManager syncManager = getSyncManager(); Loading Loading @@ -679,10 +746,19 @@ public final class ContentService extends IContentService.Stub { } public List<SyncInfo> getCurrentSyncs() { return getCurrentSyncsAsUser(UserHandle.getCallingUserId()); } /** * If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. */ public List<SyncInfo> getCurrentSyncsAsUser(int userId) { enforceCrossUserPermission(userId, "no permission to read the sync settings for user " + userId); mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, "no permission to read the sync stats"); int userId = UserHandle.getCallingUserId(); long identityToken = clearCallingIdentity(); try { return getSyncManager().getSyncStorageEngine().getCurrentSyncsCopy(userId); Loading @@ -692,13 +768,24 @@ public final class ContentService extends IContentService.Stub { } public SyncStatusInfo getSyncStatus(Account account, String authority, ComponentName cname) { return getSyncStatusAsUser(account, authority, cname, UserHandle.getCallingUserId()); } /** * If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. */ public SyncStatusInfo getSyncStatusAsUser(Account account, String authority, ComponentName cname, int userId) { if (TextUtils.isEmpty(authority)) { throw new IllegalArgumentException("Authority must not be empty"); } enforceCrossUserPermission(userId, "no permission to read the sync stats for user " + userId); mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, "no permission to read the sync stats"); int userId = UserHandle.getCallingUserId(); int callerUid = Binder.getCallingUid(); long identityToken = clearCallingIdentity(); try { Loading Loading @@ -771,6 +858,21 @@ public final class ContentService extends IContentService.Stub { return service; } /** * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS_FULL * permission, if the userHandle is not for the caller. * * @param userHandle the user handle of the user we want to act on behalf of. * @param message the message to log on security exception. */ private void enforceCrossUserPermission(int userHandle, String message) { final int callingUser = UserHandle.getCallingUserId(); if (callingUser != userHandle) { mContext.enforceCallingOrSelfPermission( Manifest.permission.INTERACT_ACROSS_USERS_FULL, message); } } /** * Hide this class since it is not part of api, * but current unittest framework requires it to be public Loading Loading
core/java/android/app/ApplicationPackageManager.java +8 −3 Original line number Diff line number Diff line Loading @@ -621,10 +621,15 @@ final class ApplicationPackageManager extends PackageManager { } @Override public ProviderInfo resolveContentProvider(String name, int flags) { public ProviderInfo resolveContentProvider(String name, int flags) { return resolveContentProviderAsUser(name, flags, mContext.getUserId()); } /** @hide **/ @Override public ProviderInfo resolveContentProviderAsUser(String name, int flags, int userId) { try { return mPM.resolveContentProvider(name, flags, mContext.getUserId()); return mPM.resolveContentProvider(name, flags, userId); } catch (RemoteException e) { throw new RuntimeException("Package manager has died", e); } Loading
core/java/android/content/ContentResolver.java +99 −1 Original line number Diff line number Diff line Loading @@ -1751,6 +1751,15 @@ public abstract class ContentResolver { * @param extras any extras to pass to the SyncAdapter. */ public static void requestSync(Account account, String authority, Bundle extras) { requestSyncAsUser(account, authority, UserHandle.getCallingUserId(), extras); } /** * @see #requestSync(Account, String, Bundle) * @hide */ public static void requestSyncAsUser(Account account, String authority, int userId, Bundle extras) { if (extras == null) { throw new IllegalArgumentException("Must specify extras."); } Loading @@ -1760,7 +1769,11 @@ public abstract class ContentResolver { .setExtras(extras) .syncOnce() // Immediate sync. .build(); requestSync(request); try { getContentService().syncAsUser(request, userId); } catch(RemoteException e) { // Shouldn't happen. } } /** Loading Loading @@ -1838,6 +1851,17 @@ public abstract class ContentResolver { } } /** * @see #cancelSync(Account, String) * @hide */ public static void cancelSyncAsUser(Account account, String authority, int userId) { try { getContentService().cancelSyncAsUser(account, authority, null, userId); } catch (RemoteException e) { } } /** * Get information about the SyncAdapters that are known to the system. * @return an array of SyncAdapters that have registered with the system Loading @@ -1850,6 +1874,18 @@ public abstract class ContentResolver { } } /** * @see #getSyncAdapterTypes() * @hide */ public static SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) { try { return getContentService().getSyncAdapterTypesAsUser(userId); } catch (RemoteException e) { throw new RuntimeException("the ContentService should always be reachable", e); } } /** * Check if the provider should be synced when a network tickle is received * <p>This method requires the caller to hold the permission Loading @@ -1867,6 +1903,19 @@ public abstract class ContentResolver { } } /** * @see #getSyncAutomatically(Account, String) * @hide */ public static boolean getSyncAutomaticallyAsUser(Account account, String authority, int userId) { try { return getContentService().getSyncAutomaticallyAsUser(account, authority, userId); } catch (RemoteException e) { throw new RuntimeException("the ContentService should always be reachable", e); } } /** * Set whether or not the provider is synced when it receives a network tickle. * <p>This method requires the caller to hold the permission Loading Loading @@ -2031,6 +2080,18 @@ public abstract class ContentResolver { } } /** * @see #getIsSyncable(Account, String) * @hide */ public static int getIsSyncableAsUser(Account account, String authority, int userId) { try { return getContentService().getIsSyncableAsUser(account, authority, userId); } catch (RemoteException e) { throw new RuntimeException("the ContentService should always be reachable", e); } } /** * Set whether this account/provider is syncable. * <p>This method requires the caller to hold the permission Loading Loading @@ -2062,6 +2123,18 @@ public abstract class ContentResolver { } } /** * @see #getMasterSyncAutomatically() * @hide */ public static boolean getMasterSyncAutomaticallyAsUser(int userId) { try { return getContentService().getMasterSyncAutomaticallyAsUser(userId); } catch (RemoteException e) { throw new RuntimeException("the ContentService should always be reachable", e); } } /** * Sets the master auto-sync setting that applies to all the providers and accounts. * If this is false then the per-provider auto-sync setting is ignored. Loading Loading @@ -2146,6 +2219,18 @@ public abstract class ContentResolver { } } /** * @see #getCurrentSyncs() * @hide */ public static List<SyncInfo> getCurrentSyncsAsUser(int userId) { try { return getContentService().getCurrentSyncsAsUser(userId); } catch (RemoteException e) { throw new RuntimeException("the ContentService should always be reachable", e); } } /** * Returns the status that matches the authority. * @param account the account whose setting we are querying Loading @@ -2161,6 +2246,19 @@ public abstract class ContentResolver { } } /** * @see #getSyncStatus(Account, String) * @hide */ public static SyncStatusInfo getSyncStatusAsUser(Account account, String authority, int userId) { try { return getContentService().getSyncStatusAsUser(account, authority, null, userId); } catch (RemoteException e) { throw new RuntimeException("the ContentService should always be reachable", e); } } /** * Return true if the pending status is true of any matching authorities. * <p>This method requires the caller to hold the permission Loading
core/java/android/content/IContentService.aidl +9 −0 Original line number Diff line number Diff line Loading @@ -60,7 +60,9 @@ interface IContentService { * Start a sync given a request. */ void sync(in SyncRequest request); void syncAsUser(in SyncRequest request, int userId); void cancelSync(in Account account, String authority, in ComponentName cname); void cancelSyncAsUser(in Account account, String authority, in ComponentName cname, int userId); /** Cancel a sync, providing information about the sync to be cancelled. */ void cancelRequest(in SyncRequest request); Loading @@ -71,6 +73,7 @@ interface IContentService { * @return true if the provider should be synced when a network tickle is received */ boolean getSyncAutomatically(in Account account, String providerName); boolean getSyncAutomaticallyAsUser(in Account account, String providerName, int userId); /** * Set whether or not the provider is synced when it receives a network tickle. Loading Loading @@ -114,6 +117,7 @@ interface IContentService { * @return >0 if it is syncable, 0 if not, and <0 if the state isn't known yet. */ int getIsSyncable(in Account account, String providerName); int getIsSyncableAsUser(in Account account, String providerName, int userId); /** * Set whether this account/provider is syncable. Loading @@ -124,14 +128,17 @@ interface IContentService { void setMasterSyncAutomatically(boolean flag); boolean getMasterSyncAutomatically(); boolean getMasterSyncAutomaticallyAsUser(int userId); List<SyncInfo> getCurrentSyncs(); List<SyncInfo> getCurrentSyncsAsUser(int userId); /** * Returns the types of the SyncAdapters that are registered with the system. * @return Returns the types of the SyncAdapters that are registered with the system. */ SyncAdapterType[] getSyncAdapterTypes(); SyncAdapterType[] getSyncAdapterTypesAsUser(int userId); /** * Returns true if there is currently a operation for the given account/authority or service Loading @@ -152,6 +159,8 @@ interface IContentService { * non-null. */ SyncStatusInfo getSyncStatus(in Account account, String authority, in ComponentName cname); SyncStatusInfo getSyncStatusAsUser(in Account account, String authority, in ComponentName cname, int userId); /** * Return true if the pending status is true of any matching authorities. Loading
core/java/android/content/pm/PackageManager.java +13 −0 Original line number Diff line number Diff line Loading @@ -2477,6 +2477,19 @@ public abstract class PackageManager { public abstract ProviderInfo resolveContentProvider(String name, int flags); /** * Find a single content provider by its base path name. * * @param name The name of the provider to find. * @param flags Additional option flags. Currently should always be 0. * @param userId The user id. * * @return ContentProviderInfo Information about the provider, if found, * else null. * @hide */ public abstract ProviderInfo resolveContentProviderAsUser(String name, int flags, int userId); /** * Retrieve content provider information. * Loading
services/core/java/com/android/server/content/ContentService.java +116 −14 Original line number Diff line number Diff line Loading @@ -172,11 +172,8 @@ public final class ContentService extends IContentService.Stub { throw new IllegalArgumentException("You must pass a valid uri and observer"); } final int callingUser = UserHandle.getCallingUserId(); if (callingUser != userHandle) { mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, enforceCrossUserPermission(userHandle, "no permission to observe other users' provider view"); } if (userHandle < 0) { if (userHandle == UserHandle.USER_CURRENT) { Loading Loading @@ -346,7 +343,15 @@ public final class ContentService extends IContentService.Stub { * @param request The request object. Validation of this object is done by its builder. */ public void sync(SyncRequest request) { int userId = UserHandle.getCallingUserId(); syncAsUser(request, UserHandle.getCallingUserId()); } /** * If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. */ public void syncAsUser(SyncRequest request, int userId) { enforceCrossUserPermission(userId, "no permission to request sync as user: " + userId); int callerUid = Binder.getCallingUid(); // This makes it so that future permission checks will be in the context of this // process rather than the caller's process. We will restore this before returning. Loading Loading @@ -399,11 +404,30 @@ public final class ContentService extends IContentService.Stub { */ @Override public void cancelSync(Account account, String authority, ComponentName cname) { cancelSyncAsUser(account, authority, cname, UserHandle.getCallingUserId()); } /** * Clear all scheduled sync operations that match the uri and cancel the active sync * if they match the authority and account, if they are present. * * <p> If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. * * @param account filter the pending and active syncs to cancel using this account, or null. * @param authority filter the pending and active syncs to cancel using this authority, or * null. * @param userId the user id for which to cancel sync operations. * @param cname cancel syncs running on this service, or null for provider/account. */ @Override public void cancelSyncAsUser(Account account, String authority, ComponentName cname, int userId) { if (authority != null && authority.length() == 0) { throw new IllegalArgumentException("Authority must be non-empty"); } int userId = UserHandle.getCallingUserId(); enforceCrossUserPermission(userId, "no permission to modify the sync settings for user " + userId); // This makes it so that future permission checks will be in the context of this // process rather than the caller's process. We will restore this before returning. long identityToken = clearCallingIdentity(); Loading Loading @@ -456,9 +480,23 @@ public final class ContentService extends IContentService.Stub { */ @Override public SyncAdapterType[] getSyncAdapterTypes() { return getSyncAdapterTypesAsUser(UserHandle.getCallingUserId()); } /** * Get information about the SyncAdapters that are known to the system for a particular user. * * <p> If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. * * @return an array of SyncAdapters that have registered with the system */ @Override public SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) { enforceCrossUserPermission(userId, "no permission to read sync settings for user " + userId); // This makes it so that future permission checks will be in the context of this // process rather than the caller's process. We will restore this before returning. final int userId = UserHandle.getCallingUserId(); final long identityToken = clearCallingIdentity(); try { SyncManager syncManager = getSyncManager(); Loading @@ -470,10 +508,20 @@ public final class ContentService extends IContentService.Stub { @Override public boolean getSyncAutomatically(Account account, String providerName) { return getSyncAutomaticallyAsUser(account, providerName, UserHandle.getCallingUserId()); } /** * If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. */ @Override public boolean getSyncAutomaticallyAsUser(Account account, String providerName, int userId) { enforceCrossUserPermission(userId, "no permission to read the sync settings for user " + userId); mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, "no permission to read the sync settings"); int userId = UserHandle.getCallingUserId(); long identityToken = clearCallingIdentity(); try { SyncManager syncManager = getSyncManager(); Loading Loading @@ -588,9 +636,18 @@ public final class ContentService extends IContentService.Stub { } public int getIsSyncable(Account account, String providerName) { return getIsSyncableAsUser(account, providerName, UserHandle.getCallingUserId()); } /** * If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. */ public int getIsSyncableAsUser(Account account, String providerName, int userId) { enforceCrossUserPermission(userId, "no permission to read the sync settings for user " + userId); mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, "no permission to read the sync settings"); int userId = UserHandle.getCallingUserId(); long identityToken = clearCallingIdentity(); try { Loading Loading @@ -627,10 +684,20 @@ public final class ContentService extends IContentService.Stub { @Override public boolean getMasterSyncAutomatically() { return getMasterSyncAutomaticallyAsUser(UserHandle.getCallingUserId()); } /** * If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. */ @Override public boolean getMasterSyncAutomaticallyAsUser(int userId) { enforceCrossUserPermission(userId, "no permission to read the sync settings for user " + userId); mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, "no permission to read the sync settings"); int userId = UserHandle.getCallingUserId(); long identityToken = clearCallingIdentity(); try { SyncManager syncManager = getSyncManager(); Loading Loading @@ -679,10 +746,19 @@ public final class ContentService extends IContentService.Stub { } public List<SyncInfo> getCurrentSyncs() { return getCurrentSyncsAsUser(UserHandle.getCallingUserId()); } /** * If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. */ public List<SyncInfo> getCurrentSyncsAsUser(int userId) { enforceCrossUserPermission(userId, "no permission to read the sync settings for user " + userId); mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, "no permission to read the sync stats"); int userId = UserHandle.getCallingUserId(); long identityToken = clearCallingIdentity(); try { return getSyncManager().getSyncStorageEngine().getCurrentSyncsCopy(userId); Loading @@ -692,13 +768,24 @@ public final class ContentService extends IContentService.Stub { } public SyncStatusInfo getSyncStatus(Account account, String authority, ComponentName cname) { return getSyncStatusAsUser(account, authority, cname, UserHandle.getCallingUserId()); } /** * If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. */ public SyncStatusInfo getSyncStatusAsUser(Account account, String authority, ComponentName cname, int userId) { if (TextUtils.isEmpty(authority)) { throw new IllegalArgumentException("Authority must not be empty"); } enforceCrossUserPermission(userId, "no permission to read the sync stats for user " + userId); mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, "no permission to read the sync stats"); int userId = UserHandle.getCallingUserId(); int callerUid = Binder.getCallingUid(); long identityToken = clearCallingIdentity(); try { Loading Loading @@ -771,6 +858,21 @@ public final class ContentService extends IContentService.Stub { return service; } /** * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS_FULL * permission, if the userHandle is not for the caller. * * @param userHandle the user handle of the user we want to act on behalf of. * @param message the message to log on security exception. */ private void enforceCrossUserPermission(int userHandle, String message) { final int callingUser = UserHandle.getCallingUserId(); if (callingUser != userHandle) { mContext.enforceCallingOrSelfPermission( Manifest.permission.INTERACT_ACROSS_USERS_FULL, message); } } /** * Hide this class since it is not part of api, * but current unittest framework requires it to be public Loading