diff --git a/src/com/android/exchange/adapter/CalendarSyncAdapter.java b/src/com/android/exchange/adapter/CalendarSyncAdapter.java
index f5459b5..8b01f9c 100644
--- a/src/com/android/exchange/adapter/CalendarSyncAdapter.java
+++ b/src/com/android/exchange/adapter/CalendarSyncAdapter.java
@@ -23,6 +23,7 @@
 import com.android.exchange.utility.CalendarUtilities;
 import com.android.exchange.utility.Duration;
 
+import android.content.ContentProviderClient;
 import android.content.ContentProviderOperation;
 import android.content.ContentProviderResult;
 import android.content.ContentResolver;
@@ -37,12 +38,14 @@
 import android.os.RemoteException;
 import android.pim.DateException;
 import android.provider.Calendar;
+import android.provider.SyncStateContract;
 import android.provider.Calendar.Attendees;
 import android.provider.Calendar.Calendars;
 import android.provider.Calendar.Events;
 import android.provider.Calendar.EventsEntity;
 import android.provider.Calendar.ExtendedProperties;
 import android.provider.Calendar.Reminders;
+import android.provider.Calendar.SyncState;
 import android.provider.ContactsContract.RawContacts;
 import android.util.Log;
 
@@ -61,12 +64,19 @@
     private static final String TAG = "EasCalendarSyncAdapter";
     // Since exceptions will have the same _SYNC_ID as the original event we have to check that
     // there's no original event when finding an item by _SYNC_ID
-    private static final String SERVER_ID_SELECTION = Events._SYNC_ID + "=? AND " +
+    private static final String SERVER_ID = Events._SYNC_ID + "=? AND " +
         Events.ORIGINAL_EVENT + " ISNULL";
+    private static final String DIRTY_TOP_LEVEL =
+        Events._SYNC_DIRTY + "=1 AND " + Events.ORIGINAL_EVENT + " ISNULL";
+    private static final String DIRTY_EXCEPTION =
+        Events._SYNC_DIRTY + "=1 AND " + Events.ORIGINAL_EVENT + " NOTNULL";
+    private static final String DIRTY_IN_CALENDAR =
+        Events._SYNC_DIRTY + "=1 AND " + Events.CALENDAR_ID + "=?";
     private static final String CLIENT_ID_SELECTION = Events._SYNC_LOCAL_ID + "=?";
     private static final String ATTENDEES_EXCEPT_ORGANIZER = Attendees.EVENT_ID + "=? AND " +
         Attendees.ATTENDEE_RELATIONSHIP + "!=" + Attendees.RELATIONSHIP_ORGANIZER;
     private static final String[] ID_PROJECTION = new String[] {Events._ID};
+    private static final String[] ORIGINAL_EVENT_PROJECTION = new String[] {Events.ORIGINAL_EVENT};
 
     private static final String CALENDAR_SELECTION =
         Calendars._SYNC_ACCOUNT + "=? AND " + Calendars._SYNC_ACCOUNT_TYPE + "=?";
@@ -138,19 +148,47 @@
     }
 
     /**
-     * We will eventually get our SyncKey from CalendarProvider.
+     * We get our SyncKey from CalendarProvider.  If there's not one, we set it to "0" (the reset
+     * state) and save that away.
      */
     @Override
     public String getSyncKey() throws IOException {
-        return super.getSyncKey();
+        ContentProviderClient client =
+            mService.mContentResolver.acquireContentProviderClient(Calendar.CONTENT_URI);
+        try {
+            byte[] data = SyncStateContract.Helpers.get(client,
+                    asSyncAdapter(Calendar.SyncState.CONTENT_URI), getAccountManagerAccount());
+            if (data == null || data.length == 0) {
+                // Initialize the SyncKey
+                setSyncKey("0", false);
+                return "0";
+            } else {
+                return new String(data);
+            }
+        } catch (RemoteException e) {
+            throw new IOException("Can't get SyncKey from ContactsProvider");
+        }
     }
 
     /**
-     * We will eventually set our SyncKey in CalendarProvider
+     * We only need to set this when we're forced to make the SyncKey "0" (a reset).  In all other
+     * cases, the SyncKey is set within Calendar
      */
     @Override
     public void setSyncKey(String syncKey, boolean inCommands) throws IOException {
-        super.setSyncKey(syncKey, inCommands);
+        if ("0".equals(syncKey) || !inCommands) {
+            ContentProviderClient client =
+                mService.mContentResolver
+                    .acquireContentProviderClient(Calendar.CONTENT_URI);
+            try {
+                SyncStateContract.Helpers.set(client, asSyncAdapter(Calendar.SyncState.CONTENT_URI),
+                        getAccountManagerAccount(), syncKey.getBytes());
+                userLog("SyncKey set to ", syncKey, " in CalendarProvider");
+           } catch (RemoteException e) {
+                throw new IOException("Can't set SyncKey in CalendarProvider");
+            }
+        }
+        mMailbox.mSyncKey = syncKey;
     }
 
     public android.accounts.Account getAccountManagerAccount() {
@@ -171,7 +209,6 @@
         public EasCalendarSyncParser(InputStream in, CalendarSyncAdapter adapter)
                 throws IOException {
             super(in, adapter);
-            setDebug(true);
             setLoggingTag("CalendarParser");
             mAccountUri = Events.CONTENT_URI;
         }
@@ -393,7 +430,6 @@
             cv.put(Events.CALENDAR_ID, mCalendarId);
             cv.put(Events._SYNC_ACCOUNT, mAccount.mEmailAddress);
             cv.put(Events._SYNC_ACCOUNT_TYPE, Eas.ACCOUNT_MANAGER_TYPE);
-            cv.put(Events._SYNC_ID, parentCv.getAsString(Events._SYNC_ID));
 
             // It appears that these values have to be copied from the parent if they are to appear
             // Note that they can be overridden below
@@ -637,7 +673,7 @@
 
         private Cursor getServerIdCursor(String serverId) {
             mBindArgument[0] = serverId;
-            return mContentResolver.query(mAccountUri, ID_PROJECTION, SERVER_ID_SELECTION,
+            return mContentResolver.query(mAccountUri, ID_PROJECTION, SERVER_ID,
                     mBindArgument, null);
         }
 
@@ -669,16 +705,6 @@
             }
         }
 
-        class ServerChange {
-            long id;
-            boolean read;
-
-            ServerChange(long _id, boolean _read) {
-                id = _id;
-                read = _read;
-            }
-        }
-
         /**
          * A change is handled as a delete (including all exceptions) and an add
          * This isn't as efficient as attempting to traverse the original and all of its exceptions,
@@ -694,6 +720,7 @@
                         serverId = getValue();
                         break;
                     case Tags.SYNC_APPLICATION_DATA:
+                        userLog("Changing " + serverId);
                         addEvent(ops, serverId, true);
                         break;
                     default:
@@ -722,15 +749,19 @@
         @Override
         public void commit() throws IOException {
             userLog("Calendar SyncKey saved as: ", mMailbox.mSyncKey);
-            // Save the syncKey here, using the Helper provider by Contacts provider
-            //ops.add(SyncStateContract.Helpers.newSetOperation(SyncState.CONTENT_URI,
-            //        getAccountManagerAccount(), mMailbox.mSyncKey.getBytes()));
+            // Save the syncKey here, using the Helper provider by Calendar provider
+            mOps.add(SyncStateContract.Helpers.newSetOperation(SyncState.CONTENT_URI,
+                    getAccountManagerAccount(), mMailbox.mSyncKey.getBytes()));
 
             // Execute these all at once...
             mOps.execute();
 
             if (mOps.mResults != null) {
-                // Clear dirty flag if necessary...
+                // Clear dirty flags for Events sent to server
+                ContentValues cv = new ContentValues();
+                cv.put(Events._SYNC_DIRTY, 0);
+                mContentResolver.update(sEventsUri, cv, DIRTY_IN_CALENDAR,
+                        new String[] {Long.toString(mCalendarId)});
             }
         }
 
@@ -913,6 +944,194 @@
         return Integer.toString(easVisibility);
     }
 
+    private void sendEvent(Entity entity, String clientId, Serializer s)
+            throws IOException {
+        // Serialize for EAS here
+        // Set uid with the client id we created
+        // 1) Serialize the top-level event
+        // 2) Serialize attendees and reminders from subvalues
+        // 3) Look for exceptions and serialize with the top-level event
+        ContentValues entityValues = entity.getEntityValues();
+        boolean isException = (clientId == null);
+
+        if (entityValues.containsKey(Events.ALL_DAY)) {
+            s.data(Tags.CALENDAR_ALL_DAY_EVENT,
+                    entityValues.getAsInteger(Events.ALL_DAY).toString());
+        }
+
+        long startTime = entityValues.getAsLong(Events.DTSTART);
+        s.data(Tags.CALENDAR_START_TIME,
+                CalendarUtilities.millisToEasDateTime(startTime));
+
+        if (!entityValues.containsKey(Events.DURATION)) {
+            if (entityValues.containsKey(Events.DTEND)) {
+                s.data(Tags.CALENDAR_END_TIME, CalendarUtilities.millisToEasDateTime(
+                        entityValues.getAsLong(Events.DTEND)));
+            }
+        } else {
+            // Convert this into millis and add it to DTSTART for DTEND
+            // We'll use 1 hour as a default
+            long durationMillis = HOURS;
+            Duration duration = new Duration();
+            try {
+                duration.parse(entityValues.getAsString(Events.DURATION));
+            } catch (DateException e) {
+                // Can't do much about this; use the default (1 hour)
+            }
+            s.data(Tags.CALENDAR_END_TIME,
+                    CalendarUtilities.millisToEasDateTime(startTime + durationMillis));
+        }
+
+        s.data(Tags.CALENDAR_DTSTAMP,
+                CalendarUtilities.millisToEasDateTime(System.currentTimeMillis()));
+
+        if (entityValues.containsKey(Events.EVENT_LOCATION)) {
+            s.data(Tags.CALENDAR_LOCATION,
+                    entityValues.getAsString(Events.EVENT_LOCATION));
+        }
+        if (entityValues.containsKey(Events.TITLE)) {
+            s.data(Tags.CALENDAR_SUBJECT, entityValues.getAsString(Events.TITLE));
+        }
+
+        if (entityValues.containsKey(Events.VISIBILITY)) {
+            s.data(Tags.CALENDAR_SENSITIVITY,
+                    decodeVisibility(entityValues.getAsInteger(Events.VISIBILITY)));
+        } else {
+            // Private if not set
+            s.data(Tags.CALENDAR_SENSITIVITY, "1");
+        }
+
+        if (!isException) {
+            // A time zone is required in all EAS events; we'll use the default if none
+            // is set.
+            String timeZoneName;
+            if (entityValues.containsKey(Events.EVENT_TIMEZONE)) {
+                timeZoneName = entityValues.getAsString(Events.EVENT_TIMEZONE);
+            } else {
+                timeZoneName = TimeZone.getDefault().getID();
+            }
+            String x = CalendarUtilities.timeZoneToTZIString(timeZoneName);
+            s.data(Tags.CALENDAR_TIME_ZONE, x);
+
+            if (entityValues.containsKey(Events.DESCRIPTION)) {
+                String desc = entityValues.getAsString(Events.DESCRIPTION);
+                if (mService.mProtocolVersionDouble >= 12.0) {
+                    s.start(Tags.BASE_BODY);
+                    s.data(Tags.BASE_TYPE, "1");
+                    s.data(Tags.BASE_DATA, desc);
+                    s.end();
+                } else {
+                    s.data(Tags.CALENDAR_BODY, desc);
+                }
+            }
+
+            if (entityValues.containsKey(Events.ORGANIZER)) {
+                s.data(Tags.CALENDAR_ORGANIZER_EMAIL,
+                        entityValues.getAsString(Events.ORGANIZER));
+            }
+
+            if (entityValues.containsKey(Events.RRULE)) {
+                CalendarUtilities.recurrenceFromRrule(
+                        entityValues.getAsString(Events.RRULE), startTime, s);
+            }
+
+            // Handle associated data EXCEPT for attendees, which have to be grouped
+            ArrayList<NamedContentValues> subValues = entity.getSubValues();
+            for (NamedContentValues ncv: subValues) {
+                Uri ncvUri = ncv.uri;
+                ContentValues ncvValues = ncv.values;
+                if (ncvUri.equals(ExtendedProperties.CONTENT_URI)) {
+                    if (ncvValues.containsKey("uid")) {
+                        clientId = ncvValues.getAsString("uid");
+                        s.data(Tags.CALENDAR_UID, clientId);
+                    }
+                    if (ncvValues.containsKey("dtstamp")) {
+                        s.data(Tags.CALENDAR_DTSTAMP, ncvValues.getAsString("dtstamp"));
+                    }
+                    if (ncvValues.containsKey("categories")) {
+                        // Send all the categories back to the server
+                        // We've saved them as a String of delimited tokens
+                        String categories = ncvValues.getAsString("categories");
+                        StringTokenizer st =
+                            new StringTokenizer(categories, CATEGORY_TOKENIZER_DELIMITER);
+                        if (st.countTokens() > 0) {
+                            s.start(Tags.CALENDAR_CATEGORIES);
+                            while (st.hasMoreTokens()) {
+                                String category = st.nextToken();
+                                s.data(Tags.CALENDAR_CATEGORY, category);
+                            }
+                            s.end();
+                        }
+                    }
+                } else if (ncvUri.equals(Reminders.CONTENT_URI)) {
+                    if (ncvValues.containsKey(Reminders.MINUTES)) {
+                        s.data(Tags.CALENDAR_REMINDER_MINS_BEFORE,
+                                ncvValues.getAsString(Reminders.MINUTES));
+                    }
+                }
+            }
+
+            // We've got to send a UID.  If the event is new, we've generated one; if not,
+            // we should have gotten one from extended properties.
+            s.data(Tags.CALENDAR_UID, clientId);
+
+            // Handle attendee data here; keep track of organizer and stream it afterward
+            boolean hasAttendees = false;
+            String organizerName = null;
+            for (NamedContentValues ncv: subValues) {
+                Uri ncvUri = ncv.uri;
+                ContentValues ncvValues = ncv.values;
+                if (ncvUri.equals(Attendees.CONTENT_URI)) {
+                    if (ncvValues.containsKey(Attendees.ATTENDEE_RELATIONSHIP)) {
+                        int relationship =
+                            ncvValues.getAsInteger(Attendees.ATTENDEE_RELATIONSHIP);
+                        // Organizer isn't among attendees in EAS
+                        if (relationship == Attendees.RELATIONSHIP_ORGANIZER) {
+                            if (ncvValues.containsKey(Attendees.ATTENDEE_NAME)) {
+                                // Remember this; we can't insert it into the stream in
+                                // the middle of attendees
+                                organizerName =
+                                    ncvValues.getAsString(Attendees.ATTENDEE_NAME);
+                            }
+                            continue;
+                        }
+                        if (!hasAttendees) {
+                            s.start(Tags.CALENDAR_ATTENDEES);
+                            hasAttendees = true;
+                        }
+                        s.start(Tags.CALENDAR_ATTENDEE);
+                        if (ncvValues.containsKey(Attendees.ATTENDEE_NAME)) {
+                            s.data(Tags.CALENDAR_ATTENDEE_NAME,
+                                    ncvValues.getAsString(Attendees.ATTENDEE_NAME));
+                        }
+                        if (ncvValues.containsKey(Attendees.ATTENDEE_EMAIL)) {
+                            s.data(Tags.CALENDAR_ATTENDEE_EMAIL,
+                                    ncvValues.getAsString(Attendees.ATTENDEE_EMAIL));
+                        }
+                        s.data(Tags.CALENDAR_ATTENDEE_TYPE, "1"); // Required
+                        s.end(); // Attendee
+                    }
+                    // If there's no relationship, we can't create this for EAS
+                }
+            }
+            if (hasAttendees) {
+                s.end();  // Attendees
+            }
+            if (organizerName != null) {
+                s.data(Tags.CALENDAR_ORGANIZER_NAME, organizerName);
+            }
+        } else {
+            // TODO Add reminders to exceptions (allow them to be specified!)
+            if (entityValues.containsKey(Events.ORIGINAL_INSTANCE_TIME)) {
+                s.data(Tags.CALENDAR_EXCEPTION_START_TIME,
+                        CalendarUtilities.millisToEasDateTime(entityValues.getAsLong(
+                                Events.ORIGINAL_INSTANCE_TIME)));
+            } else {
+                // Illegal; what should we do?
+            }
+        }
+    }
+
     @Override
     public boolean sendLocalChanges(Serializer s) throws IOException {
         ContentResolver cr = mService.mContentResolver;
@@ -925,15 +1144,31 @@
         }
 
         try {
-            // TODO This just handles NEW events at the moment
-            // Cheap way to handle changes would be to delete/add
-            EntityIterator ei = EventsEntity.newEntityIterator(
-                    cr.query(uri, null, Events._SYNC_ID + " ISNULL", null, null), cr);
+            // We've got to handle exceptions as part of the parent when changes occur, so we need
+            // to find new/changed exceptions and mark the parent dirty
+            Cursor c = cr.query(Events.CONTENT_URI, ORIGINAL_EVENT_PROJECTION, DIRTY_EXCEPTION,
+                    null, null);
+            try {
+                ContentValues cv = new ContentValues();
+                cv.put(Events._SYNC_DIRTY, 1);
+                // Mark the parent dirty in this loop
+                while (c.moveToNext()) {
+                    String serverId = c.getString(0);
+                    cr.update(asSyncAdapter(Events.CONTENT_URI), cv, SERVER_ID,
+                             new String[] {serverId});
+                }
+            } finally {
+                c.close();
+            }
+
+            // Now we can go through dirty top-level events and send them back to the server
+            EntityIterator eventIterator = EventsEntity.newEntityIterator(
+                    cr.query(uri, null, DIRTY_TOP_LEVEL, null, null), cr);
             ContentValues cidValues = new ContentValues();
             try {
                 boolean first = true;
-                while (ei.hasNext()) {
-                    Entity entity = ei.next();
+                while (eventIterator.hasNext()) {
+                    Entity entity = eventIterator.next();
                     String clientId = "uid_" + mMailbox.mId + '_' + System.currentTimeMillis();
 
                     // For each of these entities, create the change commands
@@ -949,8 +1184,6 @@
                     // TODO Handle BusyStatus for EAS 2.5
                     // What should it be??
 
-                    // Ignore exceptions (will have Events.ORIGINAL_EVENT)
-
                     if (first) {
                         s.start(Tags.SYNC_COMMANDS);
                         userLog("Sending Calendar changes to the server");
@@ -962,7 +1195,6 @@
                         s.start(Tags.SYNC_ADD).data(Tags.SYNC_CLIENT_ID, clientId);
                         // And save it in the Event as the local id
                         cidValues.put(Events._SYNC_LOCAL_ID, clientId);
-                        // TODO sync adapter!
                         cr.update(ContentUris.
                                 withAppendedId(uri,
                                         entityValues.getAsLong(Events._ID)),
@@ -978,173 +1210,29 @@
                         s.start(Tags.SYNC_CHANGE).data(Tags.SYNC_SERVER_ID, serverId);
                     }
                     s.start(Tags.SYNC_APPLICATION_DATA);
+                    sendEvent(entity, clientId, s);
 
-                    // Serialize for EAS here
-                    // Set uid with the client id we created
-                    // 1) Serialize the top-level event
-                    // 2) Serialize attendees and reminders from subvalues
-                    // 3) Look for exceptions and serialize with the top-level event
-                    if (entityValues.containsKey(Events.ALL_DAY)) {
-                        s.data(Tags.CALENDAR_ALL_DAY_EVENT,
-                                entityValues.getAsInteger(Events.ALL_DAY).toString());
-                    }
-
-                    long startTime = entityValues.getAsLong(Events.DTSTART);
-                    s.data(Tags.CALENDAR_START_TIME,
-                            CalendarUtilities.millisToEasDateTime(startTime));
-                    // Convert this into millis and add it to DTSTART for DTEND
-                    // We'll use 1 hour as a default
-                    long durationMillis = HOURS;
-                    Duration duration = new Duration();
-                    try {
-                        duration.parse(entityValues.getAsString(Events.DURATION));
-                    } catch (DateException e) {
-                        // Can't do much about this; use the default (1 hour)
-                    }
-                    s.data(Tags.CALENDAR_END_TIME,
-                            CalendarUtilities.millisToEasDateTime(startTime + durationMillis));
-                    if (entityValues.containsKey(Events.DTEND)) {
-                        // TODO Use this to determine last date; it's NOT the same as EAS DTEND
-                        //long endTime = entityValues.getAsLong(Events.DTEND);
-                        //s.data(Tags.CALENDAR_END_TIME,
-                        //        CalendarUtilities.millisToEasDateTime(endTime));
-                    }
-                    s.data(Tags.CALENDAR_DTSTAMP,
-                            CalendarUtilities.millisToEasDateTime(System.currentTimeMillis()));
-
-                    // A time zone is required in all EAS events; we'll use the default if none
-                    // is set.
-                    String timeZoneName;
-                    if (entityValues.containsKey(Events.EVENT_TIMEZONE)) {
-                        timeZoneName = entityValues.getAsString(Events.EVENT_TIMEZONE);
-                    } else {
-                        timeZoneName = TimeZone.getDefault().getID();
-                    }
-                    String x = CalendarUtilities.timeZoneToTZIString(timeZoneName);
-                    s.data(Tags.CALENDAR_TIME_ZONE, x);
-
-                    if (entityValues.containsKey(Events.EVENT_LOCATION)) {
-                        s.data(Tags.CALENDAR_LOCATION,
-                                entityValues.getAsString(Events.EVENT_LOCATION));
-                    }
-                    if (entityValues.containsKey(Events.TITLE)) {
-                        s.data(Tags.CALENDAR_SUBJECT, entityValues.getAsString(Events.TITLE));
-                    }
-                    if (entityValues.containsKey(Events.DESCRIPTION)) {
-                        String desc = entityValues.getAsString(Events.DESCRIPTION);
-                        if (mService.mProtocolVersionDouble >= 12.0) {
-                            s.start(Tags.BASE_BODY);
-                            s.data(Tags.BASE_TYPE, "1");
-                            s.data(Tags.BASE_DATA, desc);
-                            s.end();
-                        } else {
-                            s.data(Tags.CALENDAR_BODY, desc);
+                    // Now, the hard part; find exceptions for this event
+                    if (serverId != null) {
+                        EntityIterator exceptionIterator = EventsEntity.newEntityIterator(
+                                cr.query(uri, null, Events.ORIGINAL_EVENT + "=?",
+                                        new String[] {serverId}, null), cr);
+                        boolean exFirst = true;
+                        while (exceptionIterator.hasNext()) {
+                            Entity exceptionEntity = exceptionIterator.next();
+                            if (exFirst) {
+                                s.start(Tags.CALENDAR_EXCEPTIONS);
+                                exFirst = false;
+                            }
+                            s.start(Tags.CALENDAR_EXCEPTION);
+                            sendEvent(exceptionEntity, null, s);
+                            s.end(); // EXCEPTION
                         }
-                    }
-                    if (entityValues.containsKey(Events.ORGANIZER)) {
-                        s.data(Tags.CALENDAR_ORGANIZER_EMAIL,
-                                entityValues.getAsString(Events.ORGANIZER));
-                    }
-                    if (entityValues.containsKey(Events.VISIBILITY)) {
-                        s.data(Tags.CALENDAR_SENSITIVITY,
-                                decodeVisibility(entityValues.getAsInteger(Events.VISIBILITY)));
-                    } else {
-                        // Private if not set
-                        s.data(Tags.CALENDAR_SENSITIVITY, "1");
-                    }
-                    if (entityValues.containsKey(Events.RRULE)) {
-                        CalendarUtilities.recurrenceFromRrule(
-                                entityValues.getAsString(Events.RRULE), startTime, s);
-                    }
-
-                    // Handle associated data EXCEPT for attendees, which have to be grouped
-                    ArrayList<NamedContentValues> subValues = entity.getSubValues();
-                    for (NamedContentValues ncv: subValues) {
-                        Uri ncvUri = ncv.uri;
-                        ContentValues ncvValues = ncv.values;
-                        if (ncvUri.equals(ExtendedProperties.CONTENT_URI)) {
-                            if (ncvValues.containsKey("uid")) {
-                                clientId = ncvValues.getAsString("uid");
-                                s.data(Tags.CALENDAR_UID, clientId);
-                            }
-                            if (ncvValues.containsKey("dtstamp")) {
-                                s.data(Tags.CALENDAR_DTSTAMP, ncvValues.getAsString("dtstamp"));
-                            }
-                            if (ncvValues.containsKey("categories")) {
-                                // Send all the categories back to the server
-                                // We've saved them as a String of delimited tokens
-                                String categories = ncvValues.getAsString("categories");
-                                StringTokenizer st =
-                                    new StringTokenizer(categories, CATEGORY_TOKENIZER_DELIMITER);
-                                if (st.countTokens() > 0) {
-                                    s.start(Tags.CALENDAR_CATEGORIES);
-                                    while (st.hasMoreTokens()) {
-                                        String category = st.nextToken();
-                                        s.data(Tags.CALENDAR_CATEGORY, category);
-                                    }
-                                    s.end();
-                                }
-                            }
-                        } else if (ncvUri.equals(Reminders.CONTENT_URI)) {
-                            if (ncvValues.containsKey(Reminders.MINUTES)) {
-                                s.data(Tags.CALENDAR_REMINDER_MINS_BEFORE,
-                                        ncvValues.getAsString(Reminders.MINUTES));
-                            }
+                        if (!exFirst) {
+                            s.end(); // EXCEPTIONS
                         }
                     }
 
-                    // We've got to send a UID.  If the event is new, we've generated one; if not,
-                    // we should have gotten one from extended properties.
-                    s.data(Tags.CALENDAR_UID, clientId);
-
-                    // Handle attendee data here; keep track of organizer and stream it afterward
-                    boolean hasAttendees = false;
-                    String organizerName = null;
-                    for (NamedContentValues ncv: subValues) {
-                        Uri ncvUri = ncv.uri;
-                        ContentValues ncvValues = ncv.values;
-                        if (ncvUri.equals(Attendees.CONTENT_URI)) {
-                            if (ncvValues.containsKey(Attendees.ATTENDEE_RELATIONSHIP)) {
-                                int relationship =
-                                    ncvValues.getAsInteger(Attendees.ATTENDEE_RELATIONSHIP);
-                                // Organizer isn't among attendees in EAS
-                                if (relationship == Attendees.RELATIONSHIP_ORGANIZER) {
-                                    if (ncvValues.containsKey(Attendees.ATTENDEE_NAME)) {
-                                        // Remember this; we can't insert it into the stream in
-                                        // the middle of attendees
-                                        organizerName =
-                                            ncvValues.getAsString(Attendees.ATTENDEE_NAME);
-                                    }
-                                    continue;
-                                }
-                                if (!hasAttendees) {
-                                    s.start(Tags.CALENDAR_ATTENDEES);
-                                    hasAttendees = true;
-                                }
-                                s.start(Tags.CALENDAR_ATTENDEE);
-                                if (ncvValues.containsKey(Attendees.ATTENDEE_NAME)) {
-                                    s.data(Tags.CALENDAR_ATTENDEE_NAME,
-                                            ncvValues.getAsString(Attendees.ATTENDEE_NAME));
-                                }
-                                if (ncvValues.containsKey(Attendees.ATTENDEE_EMAIL)) {
-                                    s.data(Tags.CALENDAR_ATTENDEE_EMAIL,
-                                            ncvValues.getAsString(Attendees.ATTENDEE_EMAIL));
-                                }
-                                s.data(Tags.CALENDAR_ATTENDEE_TYPE, "1"); // Required
-                                s.end(); // Attendee
-                            }
-                            // If there's no relationship, we can't create this for EAS
-                        }
-                    }
-                    if (hasAttendees) {
-                        s.end();  // Attendees
-                    }
-                    if (organizerName != null) {
-                        s.data(Tags.CALENDAR_ORGANIZER_NAME, organizerName);
-                    }
-//                    case Tags.CALENDAR_EXCEPTIONS:
-//                        exceptionsParser(ops, cv);
-//                        break;
                     s.end().end(); // ApplicationData & Change
                     mUpdatedIdList.add(entityValues.getAsLong(Events._ID));
                 }
@@ -1152,7 +1240,7 @@
                     s.end(); // Commands
                 }
             } finally {
-                ei.close();
+                eventIterator.close();
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Could not read dirty events.");
