summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
authorFred Quintana <fredq@google.com>2009-06-16 10:24:58 -0700
committerFred Quintana <fredq@google.com>2009-06-16 15:25:24 -0700
commit21bb0deb36af32339521038cdbd827f74468df4a (patch)
treee8f8d47fd40cda7233e2a3fd7efe355613030500 /core/java/android
parentd638d8d6305bf5861736045e0215099d2fb693f1 (diff)
downloadframeworks_base-21bb0deb36af32339521038cdbd827f74468df4a.zip
frameworks_base-21bb0deb36af32339521038cdbd827f74468df4a.tar.gz
frameworks_base-21bb0deb36af32339521038cdbd827f74468df4a.tar.bz2
beef up the syncadapter API
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/content/AbstractThreadedSyncAdapter.java176
-rw-r--r--core/java/android/content/ISyncAdapter.aidl7
-rw-r--r--core/java/android/content/SyncAdapter.java4
-rw-r--r--core/java/android/content/SyncAdapterNew.java135
-rw-r--r--core/java/android/content/SyncManager.java15
5 files changed, 187 insertions, 150 deletions
diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java
new file mode 100644
index 0000000..f15a902
--- /dev/null
+++ b/core/java/android/content/AbstractThreadedSyncAdapter.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+import android.accounts.Account;
+import android.os.Bundle;
+import android.os.Process;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * An abstract implementation of a SyncAdapter that spawns a thread to invoke a sync operation.
+ * If a sync operation is already in progress when a startSync() request is received then an error
+ * will be returned to the new request and the existing request will be allowed to continue.
+ * When a startSync() is received and there is no sync operation in progress then a thread
+ * will be started to run the operation and {@link #performSync} will be invoked on that thread.
+ * If a cancelSync() is received that matches an existing sync operation then the thread
+ * that is running that sync operation will be interrupted, which will indicate to the thread
+ * that the sync has been canceled.
+ *
+ * @hide
+ */
+public abstract class AbstractThreadedSyncAdapter {
+ private final Context mContext;
+ private final AtomicInteger mNumSyncStarts;
+ private final ISyncAdapterImpl mISyncAdapterImpl;
+
+ // all accesses to this member variable must be synchronized on "this"
+ private SyncThread mSyncThread;
+
+ /** Kernel event log tag. Also listed in data/etc/event-log-tags. */
+ public static final int LOG_SYNC_DETAILS = 2743;
+
+ /**
+ * Creates an {@link AbstractThreadedSyncAdapter}.
+ * @param context the {@link Context} that this is running within.
+ */
+ public AbstractThreadedSyncAdapter(Context context) {
+ mContext = context;
+ mISyncAdapterImpl = new ISyncAdapterImpl();
+ mNumSyncStarts = new AtomicInteger(0);
+ mSyncThread = null;
+ }
+
+ class ISyncAdapterImpl extends ISyncAdapter.Stub {
+ public void startSync(ISyncContext syncContext, String authority, Account account,
+ Bundle extras) {
+ final SyncContext syncContextClient = new SyncContext(syncContext);
+
+ boolean alreadyInProgress;
+ // synchronize to make sure that mSyncThread doesn't change between when we
+ // check it and when we use it
+ synchronized (this) {
+ if (mSyncThread == null) {
+ mSyncThread = new SyncThread(
+ "SyncAdapterThread-" + mNumSyncStarts.incrementAndGet(),
+ syncContextClient, authority, account, extras);
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ mSyncThread.start();
+ alreadyInProgress = false;
+ } else {
+ alreadyInProgress = true;
+ }
+ }
+
+ // do this outside since we don't want to call back into the syncContext while
+ // holding the synchronization lock
+ if (alreadyInProgress) {
+ syncContextClient.onFinished(SyncResult.ALREADY_IN_PROGRESS);
+ }
+ }
+
+ public void cancelSync(ISyncContext syncContext) {
+ // synchronize to make sure that mSyncThread doesn't change between when we
+ // check it and when we use it
+ synchronized (this) {
+ if (mSyncThread != null
+ && mSyncThread.mSyncContext.getISyncContext() == syncContext) {
+ mSyncThread.interrupt();
+ }
+ }
+ }
+ }
+
+ /**
+ * The thread that invokes performSync(). It also acquires the provider for this sync
+ * before calling performSync and releases it afterwards. Cancel this thread in order to
+ * cancel the sync.
+ */
+ private class SyncThread extends Thread {
+ private final SyncContext mSyncContext;
+ private final String mAuthority;
+ private final Account mAccount;
+ private final Bundle mExtras;
+
+ private SyncThread(String name, SyncContext syncContext, String authority,
+ Account account, Bundle extras) {
+ super(name);
+ mSyncContext = syncContext;
+ mAuthority = authority;
+ mAccount = account;
+ mExtras = extras;
+ }
+
+ public void run() {
+ if (isCanceled()) {
+ return;
+ }
+
+ SyncResult syncResult = new SyncResult();
+ ContentProviderClient provider = null;
+ try {
+ provider = mContext.getContentResolver().acquireContentProviderClient(mAuthority);
+ if (provider != null) {
+ AbstractThreadedSyncAdapter.this.performSync(mAccount, mExtras,
+ mAuthority, provider, syncResult);
+ } else {
+ // TODO(fredq) update the syncResults to indicate that we were unable to
+ // find the provider. maybe with a ProviderError?
+ }
+ } finally {
+ if (provider != null) {
+ provider.release();
+ }
+ if (!isCanceled()) {
+ mSyncContext.onFinished(syncResult);
+ }
+ // synchronize so that the assignment will be seen by other threads
+ // that also synchronize accesses to mSyncThread
+ synchronized (this) {
+ mSyncThread = null;
+ }
+ }
+ }
+
+ private boolean isCanceled() {
+ return Thread.currentThread().isInterrupted();
+ }
+ }
+
+ /**
+ * @return a reference to the ISyncAdapter interface into this SyncAdapter implementation.
+ */
+ public final ISyncAdapter getISyncAdapter() {
+ return mISyncAdapterImpl;
+ }
+
+ /**
+ * Perform a sync for this account. SyncAdapter-specific parameters may
+ * be specified in extras, which is guaranteed to not be null. Invocations
+ * of this method are guaranteed to be serialized.
+ *
+ * @param account the account that should be synced
+ * @param extras SyncAdapter-specific parameters
+ * @param authority the authority of this sync request
+ * @param provider a ContentProviderClient that points to the ContentProvider for this
+ * authority
+ * @param syncResult SyncAdapter-specific parameters
+ */
+ public abstract void performSync(Account account, Bundle extras,
+ String authority, ContentProviderClient provider, SyncResult syncResult);
+} \ No newline at end of file
diff --git a/core/java/android/content/ISyncAdapter.aidl b/core/java/android/content/ISyncAdapter.aidl
index d228605..4660527 100644
--- a/core/java/android/content/ISyncAdapter.aidl
+++ b/core/java/android/content/ISyncAdapter.aidl
@@ -31,14 +31,17 @@ oneway interface ISyncAdapter {
*
* @param syncContext the ISyncContext used to indicate the progress of the sync. When
* the sync is finished (successfully or not) ISyncContext.onFinished() must be called.
+ * @param authority the authority that should be synced
* @param account the account that should be synced
* @param extras SyncAdapter-specific parameters
*/
- void startSync(ISyncContext syncContext, in Account account, in Bundle extras);
+ void startSync(ISyncContext syncContext, String authority,
+ in Account account, in Bundle extras);
/**
* Cancel the most recently initiated sync. Due to race conditions, this may arrive
* after the ISyncContext.onFinished() for that sync was called.
+ * @param syncContext the ISyncContext that was passed to {@link #startSync}
*/
- void cancelSync();
+ void cancelSync(ISyncContext syncContext);
}
diff --git a/core/java/android/content/SyncAdapter.java b/core/java/android/content/SyncAdapter.java
index c658fb7..1d5ade1 100644
--- a/core/java/android/content/SyncAdapter.java
+++ b/core/java/android/content/SyncAdapter.java
@@ -30,12 +30,12 @@ public abstract class SyncAdapter {
public static final int LOG_SYNC_DETAILS = 2743;
class Transport extends ISyncAdapter.Stub {
- public void startSync(ISyncContext syncContext, Account account,
+ public void startSync(ISyncContext syncContext, String authority, Account account,
Bundle extras) throws RemoteException {
SyncAdapter.this.startSync(new SyncContext(syncContext), account, extras);
}
- public void cancelSync() throws RemoteException {
+ public void cancelSync(ISyncContext syncContext) throws RemoteException {
SyncAdapter.this.cancelSync();
}
}
diff --git a/core/java/android/content/SyncAdapterNew.java b/core/java/android/content/SyncAdapterNew.java
deleted file mode 100644
index 5b23395..0000000
--- a/core/java/android/content/SyncAdapterNew.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.os.*;
-import android.os.Process;
-import android.accounts.Account;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * @hide
- */
-public abstract class SyncAdapterNew {
- private static final String TAG = "SyncAdapter";
- private final Context mContext;
- private final String mAuthority;
-
- /** Kernel event log tag. Also listed in data/etc/event-log-tags. */
- public static final int LOG_SYNC_DETAILS = 2743;
-
- public SyncAdapterNew(Context context, String authority) {
- mContext = context;
- mAuthority = authority;
- }
-
- class Transport extends ISyncAdapter.Stub {
- private final AtomicInteger mNumSyncStarts = new AtomicInteger(0);
- private volatile Thread mSyncThread;
-
- public void startSync(ISyncContext syncContext, Account account, Bundle extras) {
- boolean alreadyInProgress;
- synchronized (this) {
- if (mSyncThread == null) {
- mSyncThread = new Thread(
- new SyncRunnable(new SyncContext(syncContext), account, extras),
- "SyncAdapterThread-" + mNumSyncStarts.incrementAndGet());
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- mSyncThread.start();
- alreadyInProgress = false;
- } else {
- alreadyInProgress = true;
- }
- }
-
- if (alreadyInProgress) {
- try {
- syncContext.onFinished(SyncResult.ALREADY_IN_PROGRESS);
- } catch (RemoteException e) {
- // don't care if the caller is no longer around
- }
- }
- }
-
- public void cancelSync() {
- synchronized (this) {
- if (mSyncThread != null) {
- mSyncThread.interrupt();
- }
- }
- }
-
- private class SyncRunnable implements Runnable {
- private final SyncContext mSyncContext;
- private final Account mAccount;
- private final Bundle mExtras;
-
- private SyncRunnable(SyncContext syncContext, Account account, Bundle extras) {
- mSyncContext = syncContext;
- mAccount = account;
- mExtras = extras;
- }
-
- public void run() {
- if (isCanceled()) {
- return;
- }
-
- SyncResult syncResult = new SyncResult();
- ContentProviderClient provider = mAuthority != null
- ? mContext.getContentResolver().acquireContentProviderClient(mAuthority)
- : null;
- try {
- SyncAdapterNew.this.performSync(mAccount, mExtras, provider, syncResult);
- } finally {
- if (provider != null) {
- provider.release();
- }
- if (!isCanceled()) {
- mSyncContext.onFinished(syncResult);
- }
- mSyncThread = null;
- }
- }
-
- private boolean isCanceled() {
- return Thread.currentThread().isInterrupted();
- }
- }
- }
-
- Transport mTransport = new Transport();
-
- /**
- * Get the Transport object.
- */
- public final ISyncAdapter getISyncAdapter() {
- return mTransport;
- }
-
- /**
- * Perform a sync for this account. SyncAdapter-specific parameters may
- * be specified in extras, which is guaranteed to not be null. Invocations
- * of this method are guaranteed to be serialized.
- *
- * @param account the account that should be synced
- * @param extras SyncAdapter-specific parameters
- */
- public abstract void performSync(Account account, Bundle extras,
- ContentProviderClient provider, SyncResult syncResult);
-} \ No newline at end of file
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index cba02aa..c7954a5 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -33,8 +33,6 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.RegisteredServicesCache;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
@@ -50,10 +48,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.provider.Sync;
import android.provider.Settings;
-import android.provider.Sync.History;
-import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Config;
@@ -77,8 +72,6 @@ import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Random;
-import java.util.Observer;
-import java.util.Observable;
import java.util.Set;
/**
@@ -1435,7 +1428,7 @@ class SyncManager implements OnAccountsUpdatedListener {
// outstanding
if (mActiveSyncContext.mSyncAdapter != null) {
try {
- mActiveSyncContext.mSyncAdapter.cancelSync();
+ mActiveSyncContext.mSyncAdapter.cancelSync(mActiveSyncContext);
} catch (RemoteException e) {
// we don't need to retry this in this case
}
@@ -1678,8 +1671,8 @@ class SyncManager implements OnAccountsUpdatedListener {
mActiveSyncContext.mSyncAdapter = syncAdapter;
final SyncOperation syncOperation = mActiveSyncContext.mSyncOperation;
try {
- syncAdapter.startSync(mActiveSyncContext, syncOperation.account,
- syncOperation.extras);
+ syncAdapter.startSync(mActiveSyncContext, syncOperation.authority,
+ syncOperation.account, syncOperation.extras);
} catch (RemoteException remoteExc) {
if (Config.LOGD) {
Log.d(TAG, "runStateIdle: caught a RemoteException, rescheduling", remoteExc);
@@ -1742,7 +1735,7 @@ class SyncManager implements OnAccountsUpdatedListener {
}
if (activeSyncContext.mSyncAdapter != null) {
try {
- activeSyncContext.mSyncAdapter.cancelSync();
+ activeSyncContext.mSyncAdapter.cancelSync(activeSyncContext);
} catch (RemoteException e) {
// we don't need to retry this in this case
}