Refactor common sync adapter code.

Change-Id: I548d4657f31b04f4f944c5e54207523aeeeafe09
diff --git a/src/com/android/exchange/service/AbstractSyncAdapterService.java b/src/com/android/exchange/service/AbstractSyncAdapterService.java
index 330a093..eb56083 100644
--- a/src/com/android/exchange/service/AbstractSyncAdapterService.java
+++ b/src/com/android/exchange/service/AbstractSyncAdapterService.java
@@ -17,18 +17,40 @@
 package com.android.exchange.service;
 
 import android.app.Service;
+import android.content.AbstractThreadedSyncAdapter;
+import android.content.Intent;
+import android.os.IBinder;
 
 import com.android.emailcommon.provider.EmailContent;
 
+/**
+ * Base class for services that handle sync requests from the system SyncManager.
+ * This class covers the boilerplate for using an {@link AbstractThreadedSyncAdapter}. Subclasses
+ * should just implement their sync adapter, and override {@link #newSyncAdapter}.
+ */
 public abstract class AbstractSyncAdapterService extends Service {
+    private AbstractThreadedSyncAdapter mSyncAdapter = null;
 
     public AbstractSyncAdapterService() {
         super();
     }
 
+    @Override
     public void onCreate() {
         super.onCreate();
         // Make sure EmailContent is initialized in Exchange app
         EmailContent.init(this);
+        mSyncAdapter = newSyncAdapter();
     }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mSyncAdapter.getSyncAdapterBinder();
+    }
+
+    /**
+     * Subclasses should override this to supply a new instance of its sync adapter.
+     * @return A new instance of the sync adapter.
+     */
+    protected abstract AbstractThreadedSyncAdapter newSyncAdapter();
 }
diff --git a/src/com/android/exchange/service/CalendarSyncAdapterService.java b/src/com/android/exchange/service/CalendarSyncAdapterService.java
index bf672cf..99cf669 100644
--- a/src/com/android/exchange/service/CalendarSyncAdapterService.java
+++ b/src/com/android/exchange/service/CalendarSyncAdapterService.java
@@ -21,11 +21,9 @@
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.Intent;
 import android.content.SyncResult;
 import android.database.Cursor;
 import android.os.Bundle;
-import android.os.IBinder;
 import android.provider.CalendarContract.Events;
 import android.util.Log;
 
@@ -47,12 +45,15 @@
     private static final int ID_SYNC_KEY_MAILBOX_ID = 0;
     private static final int ID_SYNC_KEY_SYNC_KEY = 1;
 
-    private SyncAdapterImpl mSyncAdapter = null;
-
     public CalendarSyncAdapterService() {
         super();
     }
 
+    @Override
+    protected AbstractThreadedSyncAdapter newSyncAdapter() {
+        return new SyncAdapterImpl(this);
+    }
+
     private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
         public SyncAdapterImpl(Context context) {
             super(context, true /* autoInitialize */);
@@ -66,17 +67,6 @@
         }
     }
 
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        mSyncAdapter = new SyncAdapterImpl(this);
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return mSyncAdapter.getSyncAdapterBinder();
-    }
-
     /**
      * Partial integration with system SyncManager; we tell our EAS ExchangeService to start a
      * calendar sync when we get the signal from SyncManager.
diff --git a/src/com/android/exchange/service/ContactsSyncAdapterService.java b/src/com/android/exchange/service/ContactsSyncAdapterService.java
index c3b4e76..3db292c 100644
--- a/src/com/android/exchange/service/ContactsSyncAdapterService.java
+++ b/src/com/android/exchange/service/ContactsSyncAdapterService.java
@@ -27,12 +27,10 @@
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.Intent;
 import android.content.SyncResult;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.IBinder;
 import android.provider.ContactsContract.Groups;
 import android.provider.ContactsContract.RawContacts;
 import android.util.Log;
@@ -43,12 +41,15 @@
     private static final String ACCOUNT_AND_TYPE_CONTACTS =
         MailboxColumns.ACCOUNT_KEY + "=? AND " + MailboxColumns.TYPE + '=' + Mailbox.TYPE_CONTACTS;
 
-    private SyncAdapterImpl mSyncAdapter = null;
-
     public ContactsSyncAdapterService() {
         super();
     }
 
+    @Override
+    protected AbstractThreadedSyncAdapter newSyncAdapter() {
+        return new SyncAdapterImpl(this);
+    }
+
     private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
         public SyncAdapterImpl(Context context) {
             super(context, true /* autoInitialize */);
@@ -62,17 +63,6 @@
         }
     }
 
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        mSyncAdapter = new SyncAdapterImpl(this);
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return mSyncAdapter.getSyncAdapterBinder();
-    }
-
     private static boolean hasDirtyRows(ContentResolver resolver, Uri uri, String dirtyColumn) {
         Cursor c = resolver.query(uri, ID_PROJECTION, dirtyColumn + "=1", null, null);
         try {
diff --git a/src/com/android/exchange/service/EmailSyncAdapterService.java b/src/com/android/exchange/service/EmailSyncAdapterService.java
index 676bc76..f5444fc 100644
--- a/src/com/android/exchange/service/EmailSyncAdapterService.java
+++ b/src/com/android/exchange/service/EmailSyncAdapterService.java
@@ -29,11 +29,9 @@
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.Intent;
 import android.content.SyncResult;
 import android.database.Cursor;
 import android.os.Bundle;
-import android.os.IBinder;
 import android.util.Log;
 
 public class EmailSyncAdapterService extends AbstractSyncAdapterService {
@@ -42,12 +40,15 @@
     private static final String ACCOUNT_AND_TYPE_INBOX =
         MailboxColumns.ACCOUNT_KEY + "=? AND " + MailboxColumns.TYPE + '=' + Mailbox.TYPE_INBOX;
 
-    private SyncAdapterImpl mSyncAdapter = null;
-
     public EmailSyncAdapterService() {
         super();
     }
 
+    @Override
+    protected AbstractThreadedSyncAdapter newSyncAdapter() {
+        return new SyncAdapterImpl(this);
+    }
+
     private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
         public SyncAdapterImpl(Context context) {
             super(context, true /* autoInitialize */);
@@ -61,17 +62,6 @@
         }
     }
 
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        mSyncAdapter = new SyncAdapterImpl(getApplicationContext());
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return mSyncAdapter.getSyncAdapterBinder();
-    }
-
     /**
      * Partial integration with system SyncManager; we tell our EAS ExchangeService to start an
      * inbox sync when we get the signal from the system SyncManager.