ContentServicepublic final class ContentService extends IContentService.Stub
Fields Summary |
---|
private static final String | TAG | private android.content.Context | mContext | private boolean | mFactoryTest | private final ObserverNode | mRootNode | private SyncManager | mSyncManager | private final Object | mSyncManagerLock |
Methods Summary |
---|
public void | addPeriodicSync(android.accounts.Account account, java.lang.String authority, android.os.Bundle extras, long pollFrequency)Old API. Schedule periodic sync with default flex time.
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();
if (pollFrequency < 60) {
Slog.w(TAG, "Requested poll frequency of " + pollFrequency
+ " seconds being rounded up to 60 seconds.");
pollFrequency = 60;
}
long defaultFlex = SyncStorageEngine.calculateDefaultFlexTime(pollFrequency);
long identityToken = clearCallingIdentity();
try {
SyncStorageEngine.EndPoint info =
new SyncStorageEngine.EndPoint(account, authority, userId);
getSyncManager().getSyncStorageEngine()
.updateOrAddPeriodicSync(info,
pollFrequency,
defaultFlex,
extras);
} finally {
restoreCallingIdentity(identityToken);
}
| public void | addStatusChangeListener(int mask, android.content.ISyncStatusObserver callback)
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null && callback != null) {
syncManager.getSyncStorageEngine().addStatusChangeListener(mask, callback);
}
} finally {
restoreCallingIdentity(identityToken);
}
| public void | cancelRequest(android.content.SyncRequest request)
SyncManager syncManager = getSyncManager();
if (syncManager == null) return;
int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
SyncStorageEngine.EndPoint info;
Bundle extras = new Bundle(request.getBundle());
Account account = request.getAccount();
String provider = request.getProvider();
info = new SyncStorageEngine.EndPoint(account, provider, userId);
if (request.isPeriodic()) {
// Remove periodic sync.
mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
"no permission to write the sync settings");
getSyncManager().getSyncStorageEngine().removePeriodicSync(info, extras);
}
// Cancel active syncs and clear pending syncs from the queue.
syncManager.cancelScheduledSyncOperation(info, extras);
syncManager.cancelActiveSync(info, extras);
} finally {
restoreCallingIdentity(identityToken);
}
| public void | cancelSync(android.accounts.Account account, java.lang.String authority, android.content.ComponentName cname)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.
cancelSyncAsUser(account, authority, cname, UserHandle.getCallingUserId());
| public void | cancelSyncAsUser(android.accounts.Account account, java.lang.String authority, android.content.ComponentName cname, int userId)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.
If the user id supplied is different to the calling user, the caller must hold the
INTERACT_ACROSS_USERS_FULL permission.
if (authority != null && authority.length() == 0) {
throw new IllegalArgumentException("Authority must be non-empty");
}
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();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
SyncStorageEngine.EndPoint info;
if (cname == null) {
info = new SyncStorageEngine.EndPoint(account, authority, userId);
} else {
info = new SyncStorageEngine.EndPoint(cname, userId);
}
syncManager.clearScheduledSyncOperations(info);
syncManager.cancelActiveSync(info, null /* all syncs for this adapter */);
}
} finally {
restoreCallingIdentity(identityToken);
}
| protected synchronized void | dump(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.lang.String[] args)
mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP,
"caller doesn't have the DUMP permission");
// 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();
try {
if (mSyncManager == null) {
pw.println("No SyncManager created! (Disk full?)");
} else {
mSyncManager.dump(fd, pw);
}
pw.println();
pw.println("Observer tree:");
synchronized (mRootNode) {
int[] counts = new int[2];
final SparseIntArray pidCounts = new SparseIntArray();
mRootNode.dumpLocked(fd, pw, args, "", " ", counts, pidCounts);
pw.println();
ArrayList<Integer> sorted = new ArrayList<Integer>();
for (int i=0; i<pidCounts.size(); i++) {
sorted.add(pidCounts.keyAt(i));
}
Collections.sort(sorted, new Comparator<Integer>() {
@Override
public int compare(Integer lhs, Integer rhs) {
int lc = pidCounts.get(lhs);
int rc = pidCounts.get(rhs);
if (lc < rc) {
return 1;
} else if (lc > rc) {
return -1;
}
return 0;
}
});
for (int i=0; i<sorted.size(); i++) {
int pid = sorted.get(i);
pw.print(" pid "); pw.print(pid); pw.print(": ");
pw.print(pidCounts.get(pid)); pw.println(" observers");
}
pw.println();
pw.print(" Total number of nodes: "); pw.println(counts[0]);
pw.print(" Total number of observers: "); pw.println(counts[1]);
}
} finally {
restoreCallingIdentity(identityToken);
}
| private void | enforceCrossUserPermission(int userHandle, java.lang.String message)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.
final int callingUser = UserHandle.getCallingUserId();
if (callingUser != userHandle) {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
}
| public java.util.List | getCurrentSyncs()
return getCurrentSyncsAsUser(UserHandle.getCallingUserId());
| public java.util.List | getCurrentSyncsAsUser(int userId)If the user id supplied is different to the calling user, the caller must hold the
INTERACT_ACROSS_USERS_FULL permission.
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");
long identityToken = clearCallingIdentity();
try {
return getSyncManager().getSyncStorageEngine().getCurrentSyncsCopy(userId);
} finally {
restoreCallingIdentity(identityToken);
}
| public int | getIsSyncable(android.accounts.Account account, java.lang.String providerName)
return getIsSyncableAsUser(account, providerName, UserHandle.getCallingUserId());
| public int | getIsSyncableAsUser(android.accounts.Account account, java.lang.String providerName, int userId)If the user id supplied is different to the calling user, the caller must hold the
INTERACT_ACROSS_USERS_FULL permission.
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");
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
return syncManager.getIsSyncable(
account, userId, providerName);
}
} finally {
restoreCallingIdentity(identityToken);
}
return -1;
| public boolean | getMasterSyncAutomatically()
return getMasterSyncAutomaticallyAsUser(UserHandle.getCallingUserId());
| public boolean | getMasterSyncAutomaticallyAsUser(int userId)If the user id supplied is different to the calling user, the caller must hold the
INTERACT_ACROSS_USERS_FULL permission.
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");
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
return syncManager.getSyncStorageEngine().getMasterSyncAutomatically(userId);
}
} finally {
restoreCallingIdentity(identityToken);
}
return false;
| public java.util.List | getPeriodicSyncs(android.accounts.Account account, java.lang.String providerName, android.content.ComponentName cname)
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();
long identityToken = clearCallingIdentity();
try {
return getSyncManager().getSyncStorageEngine().getPeriodicSyncs(
new SyncStorageEngine.EndPoint(account, providerName, userId));
} finally {
restoreCallingIdentity(identityToken);
}
| public android.content.SyncAdapterType[] | getSyncAdapterTypes()Get information about the SyncAdapters that are known to the system.
return getSyncAdapterTypesAsUser(UserHandle.getCallingUserId());
| public android.content.SyncAdapterType[] | getSyncAdapterTypesAsUser(int userId)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.
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 long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
return syncManager.getSyncAdapterTypes(userId);
} finally {
restoreCallingIdentity(identityToken);
}
| public boolean | getSyncAutomatically(android.accounts.Account account, java.lang.String providerName)
return getSyncAutomaticallyAsUser(account, providerName, UserHandle.getCallingUserId());
| public boolean | getSyncAutomaticallyAsUser(android.accounts.Account account, java.lang.String providerName, int userId)If the user id supplied is different to the calling user, the caller must hold the
INTERACT_ACROSS_USERS_FULL permission.
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");
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
return syncManager.getSyncStorageEngine()
.getSyncAutomatically(account, userId, providerName);
}
} finally {
restoreCallingIdentity(identityToken);
}
return false;
| private SyncManager | getSyncManager()
if (SystemProperties.getBoolean("config.disable_network", false)) {
return null;
}
synchronized(mSyncManagerLock) {
try {
// Try to create the SyncManager, return null if it fails (e.g. the disk is full).
if (mSyncManager == null) mSyncManager = new SyncManager(mContext, mFactoryTest);
} catch (SQLiteException e) {
Log.e(TAG, "Can't create SyncManager", e);
}
return mSyncManager;
}
| public android.content.SyncStatusInfo | getSyncStatus(android.accounts.Account account, java.lang.String authority, android.content.ComponentName cname)
return getSyncStatusAsUser(account, authority, cname, UserHandle.getCallingUserId());
| public android.content.SyncStatusInfo | getSyncStatusAsUser(android.accounts.Account account, java.lang.String authority, android.content.ComponentName cname, int userId)If the user id supplied is different to the calling user, the caller must hold the
INTERACT_ACROSS_USERS_FULL permission.
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 callerUid = Binder.getCallingUid();
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager == null) {
return null;
}
SyncStorageEngine.EndPoint info;
if (!(account == null || authority == null)) {
info = new SyncStorageEngine.EndPoint(account, authority, userId);
} else {
throw new IllegalArgumentException("Must call sync status with valid authority");
}
return syncManager.getSyncStorageEngine().getStatusByAuthority(info);
} finally {
restoreCallingIdentity(identityToken);
}
| public boolean | isSyncActive(android.accounts.Account account, java.lang.String authority, android.content.ComponentName cname)
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
"no permission to read the sync stats");
int userId = UserHandle.getCallingUserId();
int callingUid = Binder.getCallingUid();
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager == null) {
return false;
}
return syncManager.getSyncStorageEngine().isSyncActive(
new SyncStorageEngine.EndPoint(account, authority, userId));
} finally {
restoreCallingIdentity(identityToken);
}
| public boolean | isSyncPending(android.accounts.Account account, java.lang.String authority, android.content.ComponentName cname)
return isSyncPendingAsUser(account, authority, cname, UserHandle.getCallingUserId());
| public boolean | isSyncPendingAsUser(android.accounts.Account account, java.lang.String authority, android.content.ComponentName cname, int userId)
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
"no permission to read the sync stats");
enforceCrossUserPermission(userId,
"no permission to retrieve the sync settings for user " + userId);
int callerUid = Binder.getCallingUid();
long identityToken = clearCallingIdentity();
SyncManager syncManager = getSyncManager();
if (syncManager == null) return false;
try {
SyncStorageEngine.EndPoint info;
if (!(account == null || authority == null)) {
info = new SyncStorageEngine.EndPoint(account, authority, userId);
} else {
throw new IllegalArgumentException("Invalid authority specified");
}
return syncManager.getSyncStorageEngine().isSyncPending(info);
} finally {
restoreCallingIdentity(identityToken);
}
| public static com.android.server.content.ContentService | main(android.content.Context context, boolean factoryTest)
ContentService service = new ContentService(context, factoryTest);
ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service);
return service;
| public void | notifyChange(android.net.Uri uri, android.database.IContentObserver observer, boolean observerWantsSelfNotifications, boolean syncToNetwork)
notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork,
UserHandle.getCallingUserId());
| public void | notifyChange(android.net.Uri uri, android.database.IContentObserver observer, boolean observerWantsSelfNotifications, boolean syncToNetwork, int userHandle)Notify observers of a particular user's view of the provider.
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Notifying update of " + uri + " for user " + userHandle
+ " from observer " + observer + ", syncToNetwork " + syncToNetwork);
}
// Notify for any user other than the caller's own requires permission.
final int callingUserHandle = UserHandle.getCallingUserId();
if (userHandle != callingUserHandle) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS,
"no permission to notify other users");
}
// We passed the permission check; resolve pseudouser targets as appropriate
if (userHandle < 0) {
if (userHandle == UserHandle.USER_CURRENT) {
userHandle = ActivityManager.getCurrentUser();
} else if (userHandle != UserHandle.USER_ALL) {
throw new InvalidParameterException("Bad user handle for notifyChange: "
+ userHandle);
}
}
final int uid = 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.
long identityToken = clearCallingIdentity();
try {
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
synchronized (mRootNode) {
mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
userHandle, calls);
}
final int numCalls = calls.size();
for (int i=0; i<numCalls; i++) {
ObserverCall oc = calls.get(i);
try {
oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri);
}
} catch (RemoteException ex) {
synchronized (mRootNode) {
Log.w(TAG, "Found dead observer, removing");
IBinder binder = oc.mObserver.asBinder();
final ArrayList<ObserverNode.ObserverEntry> list
= oc.mNode.mObservers;
int numList = list.size();
for (int j=0; j<numList; j++) {
ObserverNode.ObserverEntry oe = list.get(j);
if (oe.observer.asBinder() == binder) {
list.remove(j);
j--;
numList--;
}
}
}
}
}
if (syncToNetwork) {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle, uid,
uri.getAuthority());
}
}
} finally {
restoreCallingIdentity(identityToken);
}
| public boolean | onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
try {
return super.onTransact(code, data, reply, flags);
} catch (RuntimeException e) {
// The content service only throws security exceptions, so let's
// log all others.
if (!(e instanceof SecurityException)) {
Slog.wtf(TAG, "Content Service Crash", e);
}
throw e;
}
| public void | registerContentObserver(android.net.Uri uri, boolean notifyForDescendants, android.database.IContentObserver observer, int userHandle)Register a content observer tied to a specific user's view of the provider.
if (observer == null || uri == null) {
throw new IllegalArgumentException("You must pass a valid uri and observer");
}
enforceCrossUserPermission(userHandle,
"no permission to observe other users' provider view");
if (userHandle < 0) {
if (userHandle == UserHandle.USER_CURRENT) {
userHandle = ActivityManager.getCurrentUser();
} else if (userHandle != UserHandle.USER_ALL) {
throw new InvalidParameterException("Bad user handle for registerContentObserver: "
+ userHandle);
}
}
synchronized (mRootNode) {
mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,
Binder.getCallingUid(), Binder.getCallingPid(), userHandle);
if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
" with notifyForDescendants " + notifyForDescendants);
}
| public void | registerContentObserver(android.net.Uri uri, boolean notifyForDescendants, android.database.IContentObserver observer)
registerContentObserver(uri, notifyForDescendants, observer,
UserHandle.getCallingUserId());
| public void | removePeriodicSync(android.accounts.Account account, java.lang.String authority, android.os.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();
long identityToken = clearCallingIdentity();
try {
getSyncManager().getSyncStorageEngine()
.removePeriodicSync(
new SyncStorageEngine.EndPoint(account, authority, userId),
extras);
} finally {
restoreCallingIdentity(identityToken);
}
| public void | removeStatusChangeListener(android.content.ISyncStatusObserver callback)
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null && callback != null) {
syncManager.getSyncStorageEngine().removeStatusChangeListener(callback);
}
} finally {
restoreCallingIdentity(identityToken);
}
| public void | requestSync(android.accounts.Account account, java.lang.String authority, android.os.Bundle extras)
ContentResolver.validateSyncExtrasBundle(extras);
int userId = UserHandle.getCallingUserId();
int uId = 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.
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
syncManager.scheduleSync(account, userId, uId, authority, extras,
0 /* no delay */, 0 /* no delay */,
false /* onlyThoseWithUnkownSyncableState */);
}
} finally {
restoreCallingIdentity(identityToken);
}
| public void | setIsSyncable(android.accounts.Account account, java.lang.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();
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
syncManager.getSyncStorageEngine().setIsSyncable(
account, userId, providerName, syncable);
}
} finally {
restoreCallingIdentity(identityToken);
}
| public void | setMasterSyncAutomatically(boolean flag)
setMasterSyncAutomaticallyAsUser(flag, UserHandle.getCallingUserId());
| public void | setMasterSyncAutomaticallyAsUser(boolean flag, int userId)
enforceCrossUserPermission(userId,
"no permission to set the sync status for user " + userId);
mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
"no permission to write the sync settings");
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
syncManager.getSyncStorageEngine().setMasterSyncAutomatically(flag, userId);
}
} finally {
restoreCallingIdentity(identityToken);
}
| public void | setSyncAutomatically(android.accounts.Account account, java.lang.String providerName, boolean sync)
setSyncAutomaticallyAsUser(account, providerName, sync, UserHandle.getCallingUserId());
| public void | setSyncAutomaticallyAsUser(android.accounts.Account account, java.lang.String providerName, boolean sync, int userId)
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");
enforceCrossUserPermission(userId,
"no permission to modify the sync settings for user " + userId);
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
syncManager.getSyncStorageEngine().setSyncAutomatically(account, userId,
providerName, sync);
}
} finally {
restoreCallingIdentity(identityToken);
}
| public void | sync(android.content.SyncRequest request)Request a sync with a generic {@link android.content.SyncRequest} object. This will be
either:
periodic OR one-off sync.
and
anonymous OR provider sync.
Depending on the request, we enqueue to suit in the SyncManager.
syncAsUser(request, UserHandle.getCallingUserId());
| public void | syncAsUser(android.content.SyncRequest request, int userId)If the user id supplied is different to the calling user, the caller must hold the
INTERACT_ACROSS_USERS_FULL permission.
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.
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager == null) {
return;
}
Bundle extras = request.getBundle();
long flextime = request.getSyncFlexTime();
long runAtTime = request.getSyncRunTime();
if (request.isPeriodic()) {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.WRITE_SYNC_SETTINGS,
"no permission to write the sync settings");
SyncStorageEngine.EndPoint info;
info = new SyncStorageEngine.EndPoint(
request.getAccount(), request.getProvider(), userId);
if (runAtTime < 60) {
Slog.w(TAG, "Requested poll frequency of " + runAtTime
+ " seconds being rounded up to 60 seconds.");
runAtTime = 60;
}
// Schedule periodic sync.
getSyncManager().getSyncStorageEngine()
.updateOrAddPeriodicSync(info, runAtTime, flextime, extras);
} else {
long beforeRuntimeMillis = (flextime) * 1000;
long runtimeMillis = runAtTime * 1000;
syncManager.scheduleSync(
request.getAccount(), userId, callerUid, request.getProvider(), extras,
beforeRuntimeMillis, runtimeMillis,
false /* onlyThoseWithUnknownSyncableState */);
}
} finally {
restoreCallingIdentity(identityToken);
}
| public void | systemReady()
getSyncManager();
| public void | unregisterContentObserver(android.database.IContentObserver observer)
if (observer == null) {
throw new IllegalArgumentException("You must pass a valid observer");
}
synchronized (mRootNode) {
mRootNode.removeObserverLocked(observer);
if (false) Log.v(TAG, "Unregistered observer " + observer);
}
|
|