diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 13b922cd890cc..cb48e5885207f 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -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); } diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 392bfbc0b942a..be70411e56ef2 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -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."); } @@ -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. + } } /** @@ -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 @@ -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 *
This method requires the caller to hold the permission @@ -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. *
This method requires the caller to hold the permission @@ -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. *
This method requires the caller to hold the permission
@@ -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.
@@ -2146,6 +2219,18 @@ public abstract class ContentResolver {
}
}
+ /**
+ * @see #getCurrentSyncs()
+ * @hide
+ */
+ public static List This method requires the caller to hold the permission
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 373f2fb624947..1e967134f42a0 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -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);
@@ -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.
@@ -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.
@@ -124,14 +128,17 @@ interface IContentService {
void setMasterSyncAutomatically(boolean flag);
boolean getMasterSyncAutomatically();
+ boolean getMasterSyncAutomaticallyAsUser(int userId);
List 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();
@@ -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.
+ *
+ * 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();
@@ -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();
@@ -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 {
@@ -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();
@@ -679,10 +746,19 @@ public final class ContentService extends IContentService.Stub {
}
public List