Automated import from //branches/master/...@141380,141380
diff --git a/core/java/android/content/AbstractTableMerger.java b/core/java/android/content/AbstractTableMerger.java
index 700f1d8..5588513 100644
--- a/core/java/android/content/AbstractTableMerger.java
+++ b/core/java/android/content/AbstractTableMerger.java
@@ -164,304 +164,301 @@
             mDb.update(mDeletedTable, mSyncMarkValues, null, null);
         }
 
-        // load the local database entries, so we can merge them with the server
-        final String[] accountSelectionArgs = new String[]{account};
-        Cursor localCursor = mDb.query(mTable, syncDirtyProjection,
-                SELECT_MARKED, accountSelectionArgs, null, null,
-                mTable + "." + _SYNC_ID);
-        Cursor deletedCursor;
-        if (mDeletedTable != null) {
-            deletedCursor = mDb.query(mDeletedTable, syncIdAndVersionProjection,
+        Cursor localCursor = null;
+        Cursor deletedCursor = null;
+        Cursor diffsCursor = null;
+        try {
+            // load the local database entries, so we can merge them with the server
+            final String[] accountSelectionArgs = new String[]{account};
+            localCursor = mDb.query(mTable, syncDirtyProjection,
                     SELECT_MARKED, accountSelectionArgs, null, null,
-                    mDeletedTable + "." + _SYNC_ID);
-        } else {
-            deletedCursor =
-                    mDb.rawQuery("select 'a' as _sync_id, 'b' as _sync_version limit 0", null);
-        }
-
-        // Apply updates and insertions from the server
-        Cursor diffsCursor = serverDiffs.query(mTableURL,
-                null, null, null, mTable + "." + _SYNC_ID);
-        int deletedSyncIDColumn = deletedCursor.getColumnIndexOrThrow(_SYNC_ID);
-        int deletedSyncVersionColumn = deletedCursor.getColumnIndexOrThrow(_SYNC_VERSION);
-        int serverSyncIDColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_ID);
-        int serverSyncVersionColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_VERSION);
-        int serverSyncLocalIdColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_LOCAL_ID);
-
-        String lastSyncId = null;
-        int diffsCount = 0;
-        int localCount = 0;
-        localCursor.moveToFirst();
-        deletedCursor.moveToFirst();
-        while (diffsCursor.moveToNext()) {
-            if (mIsMergeCancelled) {
-                localCursor.close();
-                deletedCursor.close();
-                diffsCursor.close();
-                return;
-            }
-            mDb.yieldIfContended();
-            String serverSyncId = diffsCursor.getString(serverSyncIDColumn);
-            String serverSyncVersion = diffsCursor.getString(serverSyncVersionColumn);
-            long localRowId = 0;
-            String localSyncVersion = null;
-
-            diffsCount++;
-            context.setStatusText("Processing " + diffsCount + "/"
-                    + diffsCursor.getCount());
-            if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "processing server entry " +
-                    diffsCount + ", " + serverSyncId);
-
-            if (TRACE) {
-                if (diffsCount == 10) {
-                    Debug.startMethodTracing("atmtrace");
-                }
-                if (diffsCount == 20) {
-                    Debug.stopMethodTracing();
-                }
+                    mTable + "." + _SYNC_ID);
+            if (mDeletedTable != null) {
+                deletedCursor = mDb.query(mDeletedTable, syncIdAndVersionProjection,
+                        SELECT_MARKED, accountSelectionArgs, null, null,
+                        mDeletedTable + "." + _SYNC_ID);
+            } else {
+                deletedCursor =
+                        mDb.rawQuery("select 'a' as _sync_id, 'b' as _sync_version limit 0", null);
             }
 
-            boolean conflict = false;
-            boolean update = false;
-            boolean insert = false;
+            // Apply updates and insertions from the server
+            diffsCursor = serverDiffs.query(mTableURL,
+                    null, null, null, mTable + "." + _SYNC_ID);
+            int deletedSyncIDColumn = deletedCursor.getColumnIndexOrThrow(_SYNC_ID);
+            int deletedSyncVersionColumn = deletedCursor.getColumnIndexOrThrow(_SYNC_VERSION);
+            int serverSyncIDColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_ID);
+            int serverSyncVersionColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_VERSION);
+            int serverSyncLocalIdColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_LOCAL_ID);
+
+            String lastSyncId = null;
+            int diffsCount = 0;
+            int localCount = 0;
+            localCursor.moveToFirst();
+            deletedCursor.moveToFirst();
+            while (diffsCursor.moveToNext()) {
+                if (mIsMergeCancelled) {
+                    return;
+                }
+                mDb.yieldIfContended();
+                String serverSyncId = diffsCursor.getString(serverSyncIDColumn);
+                String serverSyncVersion = diffsCursor.getString(serverSyncVersionColumn);
+                long localRowId = 0;
+                String localSyncVersion = null;
+
+                diffsCount++;
+                context.setStatusText("Processing " + diffsCount + "/"
+                        + diffsCursor.getCount());
+                if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "processing server entry " +
+                        diffsCount + ", " + serverSyncId);
+
+                if (TRACE) {
+                    if (diffsCount == 10) {
+                        Debug.startMethodTracing("atmtrace");
+                    }
+                    if (diffsCount == 20) {
+                        Debug.stopMethodTracing();
+                    }
+                }
+
+                boolean conflict = false;
+                boolean update = false;
+                boolean insert = false;
+
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Log.v(TAG, "found event with serverSyncID " + serverSyncId);
+                }
+                if (TextUtils.isEmpty(serverSyncId)) {
+                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                        Log.e(TAG, "server entry doesn't have a serverSyncID");
+                    }
+                    continue;
+                }
+
+                // It is possible that the sync adapter wrote the same record multiple times,
+                // e.g. if the same record came via multiple feeds. If this happens just ignore
+                // the duplicate records.
+                if (serverSyncId.equals(lastSyncId)) {
+                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                        Log.v(TAG, "skipping record with duplicate remote server id " + lastSyncId);
+                    }
+                    continue;
+                }
+                lastSyncId = serverSyncId;
+
+                String localSyncID = null;
+                boolean localSyncDirty = false;
+
+                while (!localCursor.isAfterLast()) {
+                    if (mIsMergeCancelled) {
+                        return;
+                    }
+                    localCount++;
+                    localSyncID = localCursor.getString(2);
+
+                    // If the local record doesn't have a _sync_id then
+                    // it is new. Ignore it for now, we will send an insert
+                    // the the server later.
+                    if (TextUtils.isEmpty(localSyncID)) {
+                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                            Log.v(TAG, "local record " +
+                                    localCursor.getLong(1) +
+                                    " has no _sync_id, ignoring");
+                        }
+                        localCursor.moveToNext();
+                        localSyncID = null;
+                        continue;
+                    }
+
+                    int comp = serverSyncId.compareTo(localSyncID);
+
+                    // the local DB has a record that the server doesn't have
+                    if (comp > 0) {
+                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                            Log.v(TAG, "local record " +
+                                    localCursor.getLong(1) +
+                                    " has _sync_id " + localSyncID +
+                                    " that is < server _sync_id " + serverSyncId);
+                        }
+                        if (diffsArePartial) {
+                            localCursor.moveToNext();
+                        } else {
+                            deleteRow(localCursor);
+                            if (mDeletedTable != null) {
+                                mDb.delete(mDeletedTable, _SYNC_ID +"=?", new String[] {localSyncID});
+                            }
+                            syncResult.stats.numDeletes++;
+                            mDb.yieldIfContended();
+                        }
+                        localSyncID = null;
+                        continue;
+                    }
+
+                    // the server has a record that the local DB doesn't have
+                    if (comp < 0) {
+                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                            Log.v(TAG, "local record " +
+                                    localCursor.getLong(1) +
+                                    " has _sync_id " + localSyncID +
+                                    " that is > server _sync_id " + serverSyncId);
+                        }
+                        localSyncID = null;
+                    }
+
+                    // the server and the local DB both have this record
+                    if (comp == 0) {
+                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                            Log.v(TAG, "local record " +
+                                    localCursor.getLong(1) +
+                                    " has _sync_id " + localSyncID +
+                                    " that matches the server _sync_id");
+                        }
+                        localSyncDirty = localCursor.getInt(0) != 0;
+                        localRowId = localCursor.getLong(1);
+                        localSyncVersion = localCursor.getString(3);
+                        localCursor.moveToNext();
+                    }
+
+                    break;
+                }
+
+                // If this record is in the deleted table then update the server version
+                // in the deleted table, if necessary, and then ignore it here.
+                // We will send a deletion indication to the server down a
+                // little further.
+                if (findInCursor(deletedCursor, deletedSyncIDColumn, serverSyncId)) {
+                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                        Log.v(TAG, "remote record " + serverSyncId + " is in the deleted table");
+                    }
+                    final String deletedSyncVersion = deletedCursor.getString(deletedSyncVersionColumn);
+                    if (!TextUtils.equals(deletedSyncVersion, serverSyncVersion)) {
+                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                            Log.v(TAG, "setting version of deleted record " + serverSyncId + " to "
+                                    + serverSyncVersion);
+                        }
+                        ContentValues values = new ContentValues();
+                        values.put(_SYNC_VERSION, serverSyncVersion);
+                        mDb.update(mDeletedTable, values, "_sync_id=?", new String[]{serverSyncId});
+                    }
+                    continue;
+                }
+
+                // If the _sync_local_id is present in the diffsCursor
+                // then this record corresponds to a local record that was just
+                // inserted into the server and the _sync_local_id is the row id
+                // of the local record. Set these fields so that the next check
+                // treats this record as an update, which will allow the
+                // merger to update the record with the server's sync id
+                if (!diffsCursor.isNull(serverSyncLocalIdColumn)) {
+                    localRowId = diffsCursor.getLong(serverSyncLocalIdColumn);
+                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                        Log.v(TAG, "the remote record with sync id " + serverSyncId
+                                + " has a local sync id, " + localRowId);
+                    }
+                    localSyncID = serverSyncId;
+                    localSyncDirty = false;
+                    localSyncVersion = null;
+                }
+
+                if (!TextUtils.isEmpty(localSyncID)) {
+                    // An existing server item has changed
+                    boolean recordChanged = (localSyncVersion == null) ||
+                            !serverSyncVersion.equals(localSyncVersion);
+                    if (recordChanged) {
+                        if (localSyncDirty) {
+                            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                                Log.v(TAG, "remote record " + serverSyncId
+                                        + " conflicts with local _sync_id " + localSyncID
+                                        + ", local _id " + localRowId);
+                            }
+                            conflict = true;
+                        } else {
+                            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                                 Log.v(TAG,
+                                         "remote record " +
+                                                 serverSyncId +
+                                         " updates local _sync_id " +
+                                         localSyncID + ", local _id " +
+                                         localRowId);
+                             }
+                             update = true;
+                        }
+                    }
+                } else {
+                    // the local db doesn't know about this record so add it
+                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                        Log.v(TAG, "remote record " + serverSyncId + " is new, inserting");
+                    }
+                    insert = true;
+                }
+
+                if (update) {
+                    updateRow(localRowId, serverDiffs, diffsCursor);
+                    syncResult.stats.numUpdates++;
+                } else if (conflict) {
+                    resolveRow(localRowId, serverSyncId, serverDiffs, diffsCursor);
+                    syncResult.stats.numUpdates++;
+                } else if (insert) {
+                    insertRow(serverDiffs, diffsCursor);
+                    syncResult.stats.numInserts++;
+                }
+            }
 
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "found event with serverSyncID " + serverSyncId);
-            }
-            if (TextUtils.isEmpty(serverSyncId)) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.e(TAG, "server entry doesn't have a serverSyncID");
-                }
-                continue;
+                Log.v(TAG, "processed " + diffsCount + " server entries");
             }
 
-            // It is possible that the sync adapter wrote the same record multiple times,
-            // e.g. if the same record came via multiple feeds. If this happens just ignore
-            // the duplicate records.
-            if (serverSyncId.equals(lastSyncId)) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "skipping record with duplicate remote server id " + lastSyncId);
-                }
-                continue;
-            }
-            lastSyncId = serverSyncId;
-
-            String localSyncID = null;
-            boolean localSyncDirty = false;
-
-            while (!localCursor.isAfterLast()) {
-                if (mIsMergeCancelled) {
-                    localCursor.deactivate();
-                    deletedCursor.deactivate();
-                    diffsCursor.deactivate();
-                    return;
-                }
-                localCount++;
-                localSyncID = localCursor.getString(2);
-
-                // If the local record doesn't have a _sync_id then
-                // it is new. Ignore it for now, we will send an insert
-                // the the server later.
-                if (TextUtils.isEmpty(localSyncID)) {
+            // If tombstones aren't in use delete any remaining local rows that
+            // don't have corresponding server rows. Keep the rows that don't
+            // have a sync id since those were created locally and haven't been
+            // synced to the server yet.
+            if (!diffsArePartial) {
+                while (!localCursor.isAfterLast() && !TextUtils.isEmpty(localCursor.getString(2))) {
+                    if (mIsMergeCancelled) {
+                        return;
+                    }
+                    localCount++;
+                    final String localSyncId = localCursor.getString(2);
                     if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "local record " +
-                                localCursor.getLong(1) +
-                                " has no _sync_id, ignoring");
+                        Log.v(TAG,
+                                "deleting local record " +
+                                        localCursor.getLong(1) +
+                                        " _sync_id " + localSyncId);
                     }
-                    localCursor.moveToNext();
-                    localSyncID = null;
-                    continue;
+                    deleteRow(localCursor);
+                    if (mDeletedTable != null) {
+                        mDb.delete(mDeletedTable, _SYNC_ID + "=?", new String[] {localSyncId});
+                    }
+                    syncResult.stats.numDeletes++;
+                    mDb.yieldIfContended();
                 }
-
-                int comp = serverSyncId.compareTo(localSyncID);
-
-                // the local DB has a record that the server doesn't have
-                if (comp > 0) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "local record " +
-                                localCursor.getLong(1) +
-                                " has _sync_id " + localSyncID +
-                                " that is < server _sync_id " + serverSyncId);
-                    }
-                    if (diffsArePartial) {
-                        localCursor.moveToNext();
-                    } else {
-                        deleteRow(localCursor);
-                        if (mDeletedTable != null) {
-                            mDb.delete(mDeletedTable, _SYNC_ID +"=?", new String[] {localSyncID});
-                        }
-                        syncResult.stats.numDeletes++;
-                        mDb.yieldIfContended();
-                    }
-                    localSyncID = null;
-                    continue;
-                }
-
-                // the server has a record that the local DB doesn't have
-                if (comp < 0) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "local record " +
-                                localCursor.getLong(1) +
-                                " has _sync_id " + localSyncID +
-                                " that is > server _sync_id " + serverSyncId);
-                    }
-                    localSyncID = null;
-                }
-
-                // the server and the local DB both have this record
-                if (comp == 0) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "local record " +
-                                localCursor.getLong(1) +
-                                " has _sync_id " + localSyncID +
-                                " that matches the server _sync_id");
-                    }
-                    localSyncDirty = localCursor.getInt(0) != 0;
-                    localRowId = localCursor.getLong(1);
-                    localSyncVersion = localCursor.getString(3);
-                    localCursor.moveToNext();
-                }
-
-                break;
             }
-
-            // If this record is in the deleted table then update the server version
-            // in the deleted table, if necessary, and then ignore it here.
-            // We will send a deletion indication to the server down a
-            // little further.
-            if (findInCursor(deletedCursor, deletedSyncIDColumn, serverSyncId)) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "remote record " + serverSyncId + " is in the deleted table");
-                }
-                final String deletedSyncVersion = deletedCursor.getString(deletedSyncVersionColumn);
-                if (!TextUtils.equals(deletedSyncVersion, serverSyncVersion)) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "setting version of deleted record " + serverSyncId + " to "
-                                + serverSyncVersion);
-                    }
-                    ContentValues values = new ContentValues();
-                    values.put(_SYNC_VERSION, serverSyncVersion);
-                    mDb.update(mDeletedTable, values, "_sync_id=?", new String[]{serverSyncId});
-                }
-                continue;
-            }
-
-            // If the _sync_local_id is present in the diffsCursor
-            // then this record corresponds to a local record that was just
-            // inserted into the server and the _sync_local_id is the row id
-            // of the local record. Set these fields so that the next check
-            // treats this record as an update, which will allow the
-            // merger to update the record with the server's sync id
-            if (!diffsCursor.isNull(serverSyncLocalIdColumn)) {
-                localRowId = diffsCursor.getLong(serverSyncLocalIdColumn);
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "the remote record with sync id " + serverSyncId
-                            + " has a local sync id, " + localRowId);
-                }
-                localSyncID = serverSyncId;
-                localSyncDirty = false;
-                localSyncVersion = null;
-            }
-
-            if (!TextUtils.isEmpty(localSyncID)) {
-                // An existing server item has changed
-                boolean recordChanged = (localSyncVersion == null) ||
-                        !serverSyncVersion.equals(localSyncVersion);
-                if (recordChanged) {
-                    if (localSyncDirty) {
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                            Log.v(TAG, "remote record " + serverSyncId
-                                    + " conflicts with local _sync_id " + localSyncID
-                                    + ", local _id " + localRowId);
-                        }
-                        conflict = true;
-                    } else {
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                             Log.v(TAG,
-                                     "remote record " +
-                                             serverSyncId +
-                                     " updates local _sync_id " +
-                                     localSyncID + ", local _id " +
-                                     localRowId);
-                         }
-                         update = true;
-                    }
-                }
-            } else {
-                // the local db doesn't know about this record so add it
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "remote record " + serverSyncId + " is new, inserting");
-                }
-                insert = true;
-            }
-
-            if (update) {
-                updateRow(localRowId, serverDiffs, diffsCursor);
-                syncResult.stats.numUpdates++;
-            } else if (conflict) {
-                resolveRow(localRowId, serverSyncId, serverDiffs, diffsCursor);
-                syncResult.stats.numUpdates++;
-            } else if (insert) {
-                insertRow(serverDiffs, diffsCursor);
-                syncResult.stats.numInserts++;
-            }
+            if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "checked " + localCount +
+                    " local entries");
+        } finally {
+            if (diffsCursor != null) diffsCursor.close();
+            if (localCursor != null) localCursor.close();
+            if (deletedCursor != null) deletedCursor.close();
         }
 
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "processed " + diffsCount + " server entries");
-        }
-
-        // If tombstones aren't in use delete any remaining local rows that
-        // don't have corresponding server rows. Keep the rows that don't
-        // have a sync id since those were created locally and haven't been
-        // synced to the server yet.
-        if (!diffsArePartial) {
-            while (!localCursor.isAfterLast() && !TextUtils.isEmpty(localCursor.getString(2))) {
-                if (mIsMergeCancelled) {
-                    localCursor.deactivate();
-                    deletedCursor.deactivate();
-                    diffsCursor.deactivate();
-                    return;
-                }
-                localCount++;
-                final String localSyncId = localCursor.getString(2);
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG,
-                            "deleting local record " +
-                                    localCursor.getLong(1) +
-                                    " _sync_id " + localSyncId);
-                }
-                deleteRow(localCursor);
-                if (mDeletedTable != null) {
-                    mDb.delete(mDeletedTable, _SYNC_ID + "=?", new String[] {localSyncId});
-                }
-                syncResult.stats.numDeletes++;
-                mDb.yieldIfContended();
-            }
-        }
-
-        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "checked " + localCount +
-                " local entries");
-        diffsCursor.deactivate();
-        localCursor.deactivate();
-        deletedCursor.deactivate();
 
         if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "applying deletions from the server");
 
         // Apply deletions from the server
         if (mDeletedTableURL != null) {
             diffsCursor = serverDiffs.query(mDeletedTableURL, null, null, null, null);
-
-            while (diffsCursor.moveToNext()) {
-                if (mIsMergeCancelled) {
-                    diffsCursor.deactivate();
-                    return;
+            try {
+                while (diffsCursor.moveToNext()) {
+                    if (mIsMergeCancelled) {
+                        return;
+                    }
+                    // delete all rows that match each element in the diffsCursor
+                    fullyDeleteMatchingRows(diffsCursor, account, syncResult);
+                    mDb.yieldIfContended();
                 }
-                // delete all rows that match each element in the diffsCursor
-                fullyDeleteMatchingRows(diffsCursor, account, syncResult);
-                mDb.yieldIfContended();
+            } finally {
+                diffsCursor.close();
             }
-            diffsCursor.deactivate();
         }
     }
 
@@ -471,26 +468,26 @@
         final boolean deleteBySyncId = !diffsCursor.isNull(serverSyncIdColumn);
 
         // delete the rows explicitly so that the delete operation can be overridden
-        final Cursor c;
         final String[] selectionArgs;
-        if (deleteBySyncId) {
-            selectionArgs = new String[]{diffsCursor.getString(serverSyncIdColumn), account};
-            c = mDb.query(mTable, new String[]{BaseColumns._ID}, SELECT_BY_SYNC_ID_AND_ACCOUNT,
-                    selectionArgs, null, null, null);
-        } else {
-            int serverSyncLocalIdColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_LOCAL_ID);
-            selectionArgs = new String[]{diffsCursor.getString(serverSyncLocalIdColumn)};
-            c = mDb.query(mTable, new String[]{BaseColumns._ID}, SELECT_BY_ID, selectionArgs,
-                    null, null, null);
-        }
+        Cursor c = null;
         try {
+            if (deleteBySyncId) {
+                selectionArgs = new String[]{diffsCursor.getString(serverSyncIdColumn), account};
+                c = mDb.query(mTable, new String[]{BaseColumns._ID}, SELECT_BY_SYNC_ID_AND_ACCOUNT,
+                        selectionArgs, null, null, null);
+            } else {
+                int serverSyncLocalIdColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_LOCAL_ID);
+                selectionArgs = new String[]{diffsCursor.getString(serverSyncLocalIdColumn)};
+                c = mDb.query(mTable, new String[]{BaseColumns._ID}, SELECT_BY_ID, selectionArgs,
+                        null, null, null);
+            }
             c.moveToFirst();
             while (!c.isAfterLast()) {
                 deleteRow(c); // advances the cursor
                 syncResult.stats.numDeletes++;
             }
         } finally {
-            c.deactivate();
+          if (c != null) c.close();
         }
         if (deleteBySyncId && mDeletedTable != null) {
             mDb.delete(mDeletedTable, SELECT_BY_SYNC_ID_AND_ACCOUNT, selectionArgs);
@@ -526,25 +523,28 @@
 
         // Generate the client updates and insertions
         // Create a cursor for dirty records
+        long numInsertsOrUpdates = 0;
         Cursor localChangesCursor = mDb.query(mTable, null, SELECT_UNSYNCED, accountSelectionArgs,
                 null, null, null);
-        long numInsertsOrUpdates = localChangesCursor.getCount();
-        while (localChangesCursor.moveToNext()) {
-            if (mIsMergeCancelled) {
-                localChangesCursor.close();
-                return;
+        try {
+            numInsertsOrUpdates = localChangesCursor.getCount();
+            while (localChangesCursor.moveToNext()) {
+                if (mIsMergeCancelled) {
+                    return;
+                }
+                if (clientDiffs == null) {
+                    clientDiffs = temporaryInstanceFactory.getTemporaryInstance();
+                }
+                mValues.clear();
+                cursorRowToContentValues(localChangesCursor, mValues);
+                mValues.remove("_id");
+                DatabaseUtils.cursorLongToContentValues(localChangesCursor, "_id", mValues,
+                        _SYNC_LOCAL_ID);
+                clientDiffs.insert(mTableURL, mValues);
             }
-            if (clientDiffs == null) {
-                clientDiffs = temporaryInstanceFactory.getTemporaryInstance();
-            }
-            mValues.clear();
-            cursorRowToContentValues(localChangesCursor, mValues);
-            mValues.remove("_id");
-            DatabaseUtils.cursorLongToContentValues(localChangesCursor, "_id", mValues,
-                    _SYNC_LOCAL_ID);
-            clientDiffs.insert(mTableURL, mValues);
+        } finally {
+          localChangesCursor.close();
         }
-        localChangesCursor.close();
 
         // Generate the client deletions
         if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "generating client deletions");
@@ -555,21 +555,22 @@
                     syncIdAndVersionProjection,
                     _SYNC_ACCOUNT + "=? AND " + _SYNC_ID + " IS NOT NULL", accountSelectionArgs,
                     null, null, mDeletedTable + "." + _SYNC_ID);
-
-            numDeletedEntries = deletedCursor.getCount();
-            while (deletedCursor.moveToNext()) {
-                if (mIsMergeCancelled) {
-                    deletedCursor.close();
-                    return;
+            try {
+                numDeletedEntries = deletedCursor.getCount();
+                while (deletedCursor.moveToNext()) {
+                    if (mIsMergeCancelled) {
+                        return;
+                    }
+                    if (clientDiffs == null) {
+                        clientDiffs = temporaryInstanceFactory.getTemporaryInstance();
+                    }
+                    mValues.clear();
+                    DatabaseUtils.cursorRowToContentValues(deletedCursor, mValues);
+                    clientDiffs.insert(mDeletedTableURL, mValues);
                 }
-                if (clientDiffs == null) {
-                    clientDiffs = temporaryInstanceFactory.getTemporaryInstance();
-                }
-                mValues.clear();
-                DatabaseUtils.cursorRowToContentValues(deletedCursor, mValues);
-                clientDiffs.insert(mDeletedTableURL, mValues);
+            } finally {
+                deletedCursor.close();
             }
-            deletedCursor.close();
         }
 
         if (clientDiffs != null) {
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 10f3806..78ef374 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -211,7 +211,7 @@
             sb.append(sqlString);
         sb.append('\'');
     }
-    
+
     /**
      * SQL-escape a string.
      */
@@ -240,7 +240,7 @@
             appendEscapedSQLString(sql, value.toString());
         }
     }
-    
+
     /**
      * Concatenates two SQL WHERE clauses, handling empty or null values.
      * @hide
@@ -252,12 +252,12 @@
         if (TextUtils.isEmpty(b)) {
             return a;
         }
-            
+
         return "(" + a + ") AND (" + b + ")";
     }
-    
+
     /**
-     * return the collation key 
+     * return the collation key
      * @param name
      * @return the collation key
      */
@@ -269,7 +269,7 @@
             return "";
         }
     }
-    
+
     /**
      * return the collation key in hex format
      * @param name
@@ -280,7 +280,7 @@
         char[] keys = Hex.encodeHex(arr);
         return new String(keys, 0, getKeyLen(arr) * 2);
     }
-    
+
     private static int getKeyLen(byte[] arr) {
         if (arr[arr.length - 1] != 0) {
             return arr.length;
@@ -289,16 +289,16 @@
             return arr.length-1;
         }
     }
-    
+
     private static byte[] getCollationKeyInBytes(String name) {
         if (mColl == null) {
             mColl = Collator.getInstance();
             mColl.setStrength(Collator.PRIMARY);
         }
-        return mColl.getCollationKey(name).toByteArray();        
+        return mColl.getCollationKey(name).toByteArray();
     }
-    
-    private static Collator mColl = null;    
+
+    private static Collator mColl = null;
     /**
      * Prints the contents of a Cursor to System.out. The position is restored
      * after printing.
@@ -591,10 +591,12 @@
     public static long queryNumEntries(SQLiteDatabase db, String table) {
         Cursor cursor = db.query(table, countProjection,
                 null, null, null, null, null);
-        cursor.moveToFirst();
-        long count = cursor.getLong(0);
-        cursor.deactivate();
-        return count;
+        try {
+            cursor.moveToFirst();
+            return cursor.getLong(0);
+        } finally {
+            cursor.close();
+        }
     }
 
     /**
diff --git a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java
index df599c7..8268fee 100644
--- a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java
+++ b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java
@@ -155,14 +155,17 @@
         ContentResolver contentResolver = context.getContentResolver();
         Cursor c = contentResolver.query(SubscribedFeeds.Accounts.CONTENT_URI,
                 sAccountProjection, null, null, null);
-        while (c.moveToNext()) {
-            String account = c.getString(0);
-            if (TextUtils.isEmpty(account)) {
-                continue;
+        try {
+            while (c.moveToNext()) {
+                String account = c.getString(0);
+                if (TextUtils.isEmpty(account)) {
+                    continue;
+                }
+                accounts.add(account);
             }
-            accounts.add(account);
+        } finally {
+            c.close();
         }
-        c.deactivate();
 
         // Clear the auth tokens for all these accounts so that we are sure
         // they will still be valid until the next time we refresh them.