Loading core/java/android/content/SyncInfo.java +18 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,13 @@ import android.os.Parcelable.Creator; * Information about the sync operation that is currently underway. */ public class SyncInfo implements Parcelable { /** * Used when the caller receiving this object doesn't have permission to access the accounts * on device. * @See Manifest.permission.GET_ACCOUNTS */ private static final Account REDACTED_ACCOUNT = new Account("*****", "*****"); /** @hide */ public final int authorityId; Loading @@ -45,6 +52,17 @@ public class SyncInfo implements Parcelable { */ public final long startTime; /** * Creates a SyncInfo object with an unusable Account. Used when the caller receiving this * object doesn't have access to the accounts on the device. * @See Manifest.permission.GET_ACCOUNTS * @hide */ public static SyncInfo createAccountRedacted( int authorityId, String authority, long startTime) { return new SyncInfo(authorityId, REDACTED_ACCOUNT, authority, startTime); } /** @hide */ public SyncInfo(int authorityId, Account account, String authority, long startTime) { Loading services/java/com/android/server/content/ContentService.java +31 −2 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.content.SyncAdapterType; import android.content.SyncInfo; import android.content.SyncRequest; import android.content.SyncStatusInfo; import android.content.pm.PackageManager; import android.database.IContentObserver; import android.database.sqlite.SQLiteException; import android.net.Uri; Loading Loading @@ -654,13 +655,26 @@ 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(); final boolean canAccessAccounts = mContext.checkCallingOrSelfPermission(Manifest.permission.GET_ACCOUNTS) == PackageManager.PERMISSION_GRANTED; long identityToken = clearCallingIdentity(); try { return getSyncManager().getSyncStorageEngine().getCurrentSyncsCopy(userId); return getSyncManager().getSyncStorageEngine() .getCurrentSyncsCopy(userId, canAccessAccounts); } finally { restoreCallingIdentity(identityToken); } Loading Loading @@ -734,6 +748,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 services/java/com/android/server/content/SyncStorageEngine.java +12 −4 Original line number Diff line number Diff line Loading @@ -1306,15 +1306,23 @@ public class SyncStorageEngine extends Handler { } /** * @return a copy of the current syncs data structure. Will not return * null. * @param userId Id of user to return current sync info. * @param canAccessAccounts Determines whether to redact Account information from the result. * @return a copy of the current syncs data structure. Will not return null. */ public List<SyncInfo> getCurrentSyncsCopy(int userId) { public List<SyncInfo> getCurrentSyncsCopy(int userId, boolean canAccessAccounts) { synchronized (mAuthorities) { final List<SyncInfo> syncs = getCurrentSyncsLocked(userId); final List<SyncInfo> syncsCopy = new ArrayList<SyncInfo>(); for (SyncInfo sync : syncs) { syncsCopy.add(new SyncInfo(sync)); SyncInfo copy; if (!canAccessAccounts) { copy = SyncInfo.createAccountRedacted( sync.authorityId, sync.authority, sync.startTime); } else { copy = new SyncInfo(sync); } syncsCopy.add(copy); } return syncsCopy; } Loading Loading
core/java/android/content/SyncInfo.java +18 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,13 @@ import android.os.Parcelable.Creator; * Information about the sync operation that is currently underway. */ public class SyncInfo implements Parcelable { /** * Used when the caller receiving this object doesn't have permission to access the accounts * on device. * @See Manifest.permission.GET_ACCOUNTS */ private static final Account REDACTED_ACCOUNT = new Account("*****", "*****"); /** @hide */ public final int authorityId; Loading @@ -45,6 +52,17 @@ public class SyncInfo implements Parcelable { */ public final long startTime; /** * Creates a SyncInfo object with an unusable Account. Used when the caller receiving this * object doesn't have access to the accounts on the device. * @See Manifest.permission.GET_ACCOUNTS * @hide */ public static SyncInfo createAccountRedacted( int authorityId, String authority, long startTime) { return new SyncInfo(authorityId, REDACTED_ACCOUNT, authority, startTime); } /** @hide */ public SyncInfo(int authorityId, Account account, String authority, long startTime) { Loading
services/java/com/android/server/content/ContentService.java +31 −2 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.content.SyncAdapterType; import android.content.SyncInfo; import android.content.SyncRequest; import android.content.SyncStatusInfo; import android.content.pm.PackageManager; import android.database.IContentObserver; import android.database.sqlite.SQLiteException; import android.net.Uri; Loading Loading @@ -654,13 +655,26 @@ 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(); final boolean canAccessAccounts = mContext.checkCallingOrSelfPermission(Manifest.permission.GET_ACCOUNTS) == PackageManager.PERMISSION_GRANTED; long identityToken = clearCallingIdentity(); try { return getSyncManager().getSyncStorageEngine().getCurrentSyncsCopy(userId); return getSyncManager().getSyncStorageEngine() .getCurrentSyncsCopy(userId, canAccessAccounts); } finally { restoreCallingIdentity(identityToken); } Loading Loading @@ -734,6 +748,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
services/java/com/android/server/content/SyncStorageEngine.java +12 −4 Original line number Diff line number Diff line Loading @@ -1306,15 +1306,23 @@ public class SyncStorageEngine extends Handler { } /** * @return a copy of the current syncs data structure. Will not return * null. * @param userId Id of user to return current sync info. * @param canAccessAccounts Determines whether to redact Account information from the result. * @return a copy of the current syncs data structure. Will not return null. */ public List<SyncInfo> getCurrentSyncsCopy(int userId) { public List<SyncInfo> getCurrentSyncsCopy(int userId, boolean canAccessAccounts) { synchronized (mAuthorities) { final List<SyncInfo> syncs = getCurrentSyncsLocked(userId); final List<SyncInfo> syncsCopy = new ArrayList<SyncInfo>(); for (SyncInfo sync : syncs) { syncsCopy.add(new SyncInfo(sync)); SyncInfo copy; if (!canAccessAccounts) { copy = SyncInfo.createAccountRedacted( sync.authorityId, sync.authority, sync.startTime); } else { copy = new SyncInfo(sync); } syncsCopy.add(copy); } return syncsCopy; } Loading