* commit 'e0a2bdaf61a7a72e92d614f81f86e7fd441b38e4': Fix infinite boot-loop bug in SM.
This commit is contained in:
@@ -1914,12 +1914,6 @@ public abstract class ContentResolver {
|
||||
public static void addPeriodicSync(Account account, String authority, Bundle extras,
|
||||
long pollFrequency) {
|
||||
validateSyncExtrasBundle(extras);
|
||||
if (account == null) {
|
||||
throw new IllegalArgumentException("account must not be null");
|
||||
}
|
||||
if (authority == null) {
|
||||
throw new IllegalArgumentException("authority must not be null");
|
||||
}
|
||||
if (extras.getBoolean(SYNC_EXTRAS_MANUAL, false)
|
||||
|| extras.getBoolean(SYNC_EXTRAS_DO_NOT_RETRY, false)
|
||||
|| extras.getBoolean(SYNC_EXTRAS_IGNORE_BACKOFF, false)
|
||||
@@ -1949,12 +1943,6 @@ public abstract class ContentResolver {
|
||||
*/
|
||||
public static void removePeriodicSync(Account account, String authority, Bundle extras) {
|
||||
validateSyncExtrasBundle(extras);
|
||||
if (account == null) {
|
||||
throw new IllegalArgumentException("account must not be null");
|
||||
}
|
||||
if (authority == null) {
|
||||
throw new IllegalArgumentException("authority must not be null");
|
||||
}
|
||||
try {
|
||||
getContentService().removePeriodicSync(account, authority, extras);
|
||||
} catch (RemoteException e) {
|
||||
@@ -1972,12 +1960,6 @@ public abstract class ContentResolver {
|
||||
* @return a list of PeriodicSync objects. This list may be empty but will never be null.
|
||||
*/
|
||||
public static List<PeriodicSync> getPeriodicSyncs(Account account, String authority) {
|
||||
if (account == null) {
|
||||
throw new IllegalArgumentException("account must not be null");
|
||||
}
|
||||
if (authority == null) {
|
||||
throw new IllegalArgumentException("authority must not be null");
|
||||
}
|
||||
try {
|
||||
return getContentService().getPeriodicSyncs(account, authority);
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -408,6 +408,9 @@ public class SyncRequest implements Parcelable {
|
||||
if (mSyncTarget != SYNC_TARGET_UNKNOWN) {
|
||||
throw new IllegalArgumentException("Sync target has already been defined.");
|
||||
}
|
||||
if (authority != null && authority.length() == 0) {
|
||||
throw new IllegalArgumentException("Authority must be non-empty");
|
||||
}
|
||||
mSyncTarget = SYNC_TARGET_ADAPTER;
|
||||
mAccount = account;
|
||||
mAuthority = authority;
|
||||
|
||||
@@ -39,6 +39,7 @@ import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
@@ -342,13 +343,11 @@ public final class ContentService extends IContentService.Stub {
|
||||
* and
|
||||
* anonymous OR provider sync.
|
||||
* Depending on the request, we enqueue to suit in the SyncManager.
|
||||
* @param request
|
||||
* @param request The request object. Validation of this object is done by its builder.
|
||||
*/
|
||||
@Override
|
||||
public void sync(SyncRequest request) {
|
||||
Bundle extras = request.getBundle();
|
||||
ContentResolver.validateSyncExtrasBundle(extras);
|
||||
|
||||
long flextime = request.getSyncFlexTime();
|
||||
long runAtTime = request.getSyncRunTime();
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
@@ -401,8 +400,11 @@ public final class ContentService extends IContentService.Stub {
|
||||
*/
|
||||
@Override
|
||||
public void cancelSync(Account account, String authority) {
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
if (authority != null && authority.length() == 0) {
|
||||
throw new IllegalArgumentException("Authority must be non-empty");
|
||||
}
|
||||
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
// 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();
|
||||
@@ -439,8 +441,8 @@ public final class ContentService extends IContentService.Stub {
|
||||
public boolean getSyncAutomatically(Account account, String providerName) {
|
||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
|
||||
"no permission to read the sync settings");
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
long identityToken = clearCallingIdentity();
|
||||
try {
|
||||
SyncManager syncManager = getSyncManager();
|
||||
@@ -456,10 +458,13 @@ public final class ContentService extends IContentService.Stub {
|
||||
|
||||
@Override
|
||||
public void setSyncAutomatically(Account account, String providerName, boolean sync) {
|
||||
if (TextUtils.isEmpty(providerName)) {
|
||||
throw new IllegalArgumentException("Authority must be non-empty");
|
||||
}
|
||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
|
||||
"no permission to write the sync settings");
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
long identityToken = clearCallingIdentity();
|
||||
try {
|
||||
SyncManager syncManager = getSyncManager();
|
||||
@@ -472,16 +477,20 @@ public final class ContentService extends IContentService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Old API. Schedule periodic sync with default flex time.
|
||||
*/
|
||||
/** Old API. Schedule periodic sync with default flex time. */
|
||||
@Override
|
||||
public void addPeriodicSync(Account account, String authority, Bundle extras,
|
||||
long pollFrequency) {
|
||||
if (account == null) {
|
||||
throw new IllegalArgumentException("Account must not be null");
|
||||
}
|
||||
if (TextUtils.isEmpty(authority)) {
|
||||
throw new IllegalArgumentException("Authority must not be empty.");
|
||||
}
|
||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
|
||||
"no permission to write the sync settings");
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
if (pollFrequency < 60) {
|
||||
Slog.w(TAG, "Requested poll frequency of " + pollFrequency
|
||||
+ " seconds being rounded up to 60 seconds.");
|
||||
@@ -503,10 +512,16 @@ public final class ContentService extends IContentService.Stub {
|
||||
|
||||
@Override
|
||||
public void removePeriodicSync(Account account, String authority, Bundle extras) {
|
||||
if (account == null) {
|
||||
throw new IllegalArgumentException("Account must not be null");
|
||||
}
|
||||
if (TextUtils.isEmpty(authority)) {
|
||||
throw new IllegalArgumentException("Authority must not be empty");
|
||||
}
|
||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
|
||||
"no permission to write the sync settings");
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
long identityToken = clearCallingIdentity();
|
||||
try {
|
||||
PeriodicSync syncToRemove = new PeriodicSync(account, authority, extras,
|
||||
@@ -527,10 +542,16 @@ public final class ContentService extends IContentService.Stub {
|
||||
|
||||
@Override
|
||||
public List<PeriodicSync> getPeriodicSyncs(Account account, String providerName) {
|
||||
if (account == null) {
|
||||
throw new IllegalArgumentException("Account must not be null");
|
||||
}
|
||||
if (TextUtils.isEmpty(providerName)) {
|
||||
throw new IllegalArgumentException("Authority must not be empty");
|
||||
}
|
||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
|
||||
"no permission to read the sync settings");
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
long identityToken = clearCallingIdentity();
|
||||
try {
|
||||
return getSyncManager().getSyncStorageEngine().getPeriodicSyncs(
|
||||
@@ -560,10 +581,13 @@ public final class ContentService extends IContentService.Stub {
|
||||
|
||||
@Override
|
||||
public void setIsSyncable(Account account, String providerName, int syncable) {
|
||||
if (TextUtils.isEmpty(providerName)) {
|
||||
throw new IllegalArgumentException("Authority must not be empty");
|
||||
}
|
||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
|
||||
"no permission to write the sync settings");
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
long identityToken = clearCallingIdentity();
|
||||
try {
|
||||
SyncManager syncManager = getSyncManager();
|
||||
@@ -580,8 +604,8 @@ public final class ContentService extends IContentService.Stub {
|
||||
public boolean getMasterSyncAutomatically() {
|
||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
|
||||
"no permission to read the sync settings");
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
long identityToken = clearCallingIdentity();
|
||||
try {
|
||||
SyncManager syncManager = getSyncManager();
|
||||
@@ -598,8 +622,8 @@ public final class ContentService extends IContentService.Stub {
|
||||
public void setMasterSyncAutomatically(boolean flag) {
|
||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
|
||||
"no permission to write the sync settings");
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
long identityToken = clearCallingIdentity();
|
||||
try {
|
||||
SyncManager syncManager = getSyncManager();
|
||||
@@ -632,8 +656,8 @@ public final class ContentService extends IContentService.Stub {
|
||||
public List<SyncInfo> getCurrentSyncs() {
|
||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
|
||||
"no permission to read the sync stats");
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
long identityToken = clearCallingIdentity();
|
||||
try {
|
||||
return getSyncManager().getSyncStorageEngine().getCurrentSyncs(userId);
|
||||
@@ -643,10 +667,13 @@ public final class ContentService extends IContentService.Stub {
|
||||
}
|
||||
|
||||
public SyncStatusInfo getSyncStatus(Account account, String authority) {
|
||||
if (TextUtils.isEmpty(authority)) {
|
||||
throw new IllegalArgumentException("Authority must not be empty");
|
||||
}
|
||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
|
||||
"no permission to read the sync stats");
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
long identityToken = clearCallingIdentity();
|
||||
try {
|
||||
SyncManager syncManager = getSyncManager();
|
||||
@@ -663,8 +690,8 @@ public final class ContentService extends IContentService.Stub {
|
||||
public boolean isSyncPending(Account account, String authority) {
|
||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
|
||||
"no permission to read the sync stats");
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
long identityToken = clearCallingIdentity();
|
||||
try {
|
||||
SyncManager syncManager = getSyncManager();
|
||||
|
||||
@@ -67,6 +67,7 @@ import android.os.WorkSource;
|
||||
import android.provider.Settings;
|
||||
import android.text.format.DateUtils;
|
||||
import android.text.format.Time;
|
||||
import android.text.TextUtils;
|
||||
import android.util.EventLog;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
@@ -2009,8 +2010,11 @@ public class SyncManager {
|
||||
for (Pair<AuthorityInfo, SyncStatusInfo> info : infos) {
|
||||
final AuthorityInfo authorityInfo = info.first;
|
||||
final SyncStatusInfo status = info.second;
|
||||
// skip the sync if the account of this operation no longer
|
||||
// exists
|
||||
if (TextUtils.isEmpty(authorityInfo.authority)) {
|
||||
Log.e(TAG, "Got an empty provider string. Skipping: " + authorityInfo);
|
||||
continue;
|
||||
}
|
||||
// skip the sync if the account of this operation no longer exists
|
||||
if (!containsAccountAndUser(
|
||||
accounts, authorityInfo.account, authorityInfo.userId)) {
|
||||
continue;
|
||||
|
||||
@@ -1357,12 +1357,12 @@ public class SyncStorageEngine extends Handler {
|
||||
*
|
||||
* @param account the account we want to check
|
||||
* @param authority the authority whose row should be selected
|
||||
* @return the SyncStatusInfo for the authority
|
||||
* @return the SyncStatusInfo for the authority or null if none found.
|
||||
*/
|
||||
public SyncStatusInfo getStatusByAccountAndAuthority(Account account, int userId,
|
||||
String authority) {
|
||||
if (account == null || authority == null) {
|
||||
throw new IllegalArgumentException();
|
||||
return null;
|
||||
}
|
||||
synchronized (mAuthorities) {
|
||||
final int N = mSyncStatus.size();
|
||||
|
||||
@@ -670,6 +670,61 @@ public class SyncStorageEngineTest extends AndroidTestCase {
|
||||
assertEquals(0, engine.getIsSyncable(account, 0, "other3"));
|
||||
assertEquals(1, engine.getIsSyncable(account, 0, "other4"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the API cannot cause a run-time reboot by passing in the empty string as an
|
||||
* authority. The problem here is that
|
||||
* {@link SyncStorageEngine#getOrCreateAuthorityLocked(account, provider)} would register
|
||||
* an empty authority which causes a RTE in {@link SyncManager#scheduleReadyPeriodicSyncs()}.
|
||||
* This is not strictly a SSE test, but it does depend on the SSE data structures.
|
||||
*/
|
||||
@SmallTest
|
||||
public void testExpectedIllegalArguments() throws Exception {
|
||||
try {
|
||||
ContentResolver.setSyncAutomatically(account1, "", true);
|
||||
fail("empty provider string should throw IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {}
|
||||
|
||||
try {
|
||||
ContentResolver.addPeriodicSync(account1, "", Bundle.EMPTY, 84000L);
|
||||
fail("empty provider string should throw IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {}
|
||||
|
||||
try {
|
||||
ContentResolver.removePeriodicSync(account1, "", Bundle.EMPTY);
|
||||
fail("empty provider string should throw IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {}
|
||||
|
||||
try {
|
||||
ContentResolver.cancelSync(account1, "");
|
||||
fail("empty provider string should throw IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {}
|
||||
|
||||
try {
|
||||
ContentResolver.setIsSyncable(account1, "", 0);
|
||||
fail("empty provider string should throw IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {}
|
||||
|
||||
try {
|
||||
ContentResolver.cancelSync(account1, "");
|
||||
fail("empty provider string should throw IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {}
|
||||
|
||||
try {
|
||||
ContentResolver.requestSync(account1, "", Bundle.EMPTY);
|
||||
fail("empty provider string should throw IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {}
|
||||
|
||||
try {
|
||||
ContentResolver.getSyncStatus(account1, "");
|
||||
fail("empty provider string should throw IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {}
|
||||
|
||||
// Make sure we aren't blocking null account/provider for those functions that use it
|
||||
// to specify ALL accounts/providers.
|
||||
ContentResolver.requestSync(null, null, Bundle.EMPTY);
|
||||
ContentResolver.cancelSync(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
class TestContext extends ContextWrapper {
|
||||
|
||||
Reference in New Issue
Block a user