18402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton/* 28402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * Copyright (C) 2009 The Android Open Source Project 38402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * 48402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * Licensed under the Apache License, Version 2.0 (the "License"); 58402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * you may not use this file except in compliance with the License. 68402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * You may obtain a copy of the License at 78402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * 88402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * http://www.apache.org/licenses/LICENSE-2.0 98402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * 108402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * Unless required by applicable law or agreed to in writing, software 118402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * distributed under the License is distributed on an "AS IS" BASIS, 128402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * See the License for the specific language governing permissions and 148402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * limitations under the License 158402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton */ 168402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 178402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamiltonpackage com.android.browser.provider; 188402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 198402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamiltonimport android.content.ContentProvider; 208402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamiltonimport android.content.ContentProviderOperation; 218402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamiltonimport android.content.ContentProviderResult; 22fca41d76f4839d6707aa9680d47a93646cd01df4John Reckimport android.content.ContentResolver; 238402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamiltonimport android.content.ContentValues; 248402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamiltonimport android.content.Context; 258402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamiltonimport android.content.OperationApplicationException; 268402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 278402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamiltonimport android.database.sqlite.SQLiteOpenHelper; 288402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamiltonimport android.net.Uri; 298402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 308402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamiltonimport java.util.ArrayList; 31fca41d76f4839d6707aa9680d47a93646cd01df4John Reckimport java.util.HashSet; 32fca41d76f4839d6707aa9680d47a93646cd01df4John Reckimport java.util.Set; 338402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 348402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton/** 358402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * General purpose {@link ContentProvider} base class that uses SQLiteDatabase for storage. 368402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton */ 37fca41d76f4839d6707aa9680d47a93646cd01df4John Reckpublic abstract class SQLiteContentProvider extends ContentProvider { 388402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 398402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton private static final String TAG = "SQLiteContentProvider"; 408402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 418402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton private SQLiteOpenHelper mOpenHelper; 42fca41d76f4839d6707aa9680d47a93646cd01df4John Reck private Set<Uri> mChangedUris; 438402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton protected SQLiteDatabase mDb; 448402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 458402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton private final ThreadLocal<Boolean> mApplyingBatch = new ThreadLocal<Boolean>(); 468402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton private static final int SLEEP_AFTER_YIELD_DELAY = 4000; 478402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 488402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton /** 498402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * Maximum number of operations allowed in a batch between yield points. 508402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton */ 518402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton private static final int MAX_OPERATIONS_PER_YIELD_POINT = 500; 528402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 538402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton @Override 548402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton public boolean onCreate() { 558402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton Context context = getContext(); 568402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mOpenHelper = getDatabaseHelper(context); 57fca41d76f4839d6707aa9680d47a93646cd01df4John Reck mChangedUris = new HashSet<Uri>(); 588402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton return true; 598402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 608402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 618402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton /** 628402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * Returns a {@link SQLiteOpenHelper} that can open the database. 638402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton */ 648402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton public abstract SQLiteOpenHelper getDatabaseHelper(Context context); 658402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 668402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton /** 678402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * The equivalent of the {@link #insert} method, but invoked within a transaction. 688402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton */ 698402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton public abstract Uri insertInTransaction(Uri uri, ContentValues values, 708402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton boolean callerIsSyncAdapter); 718402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 728402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton /** 738402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * The equivalent of the {@link #update} method, but invoked within a transaction. 748402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton */ 758402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton public abstract int updateInTransaction(Uri uri, ContentValues values, String selection, 768402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton String[] selectionArgs, boolean callerIsSyncAdapter); 778402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 788402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton /** 798402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton * The equivalent of the {@link #delete} method, but invoked within a transaction. 808402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton */ 818402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton public abstract int deleteInTransaction(Uri uri, String selection, String[] selectionArgs, 828402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton boolean callerIsSyncAdapter); 838402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 848402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton /** 85fca41d76f4839d6707aa9680d47a93646cd01df4John Reck * Call this to add a URI to the list of URIs to be notified when the transaction 86fca41d76f4839d6707aa9680d47a93646cd01df4John Reck * is committed. 878402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton */ 88fca41d76f4839d6707aa9680d47a93646cd01df4John Reck protected void postNotifyUri(Uri uri) { 89fca41d76f4839d6707aa9680d47a93646cd01df4John Reck synchronized (mChangedUris) { 90fca41d76f4839d6707aa9680d47a93646cd01df4John Reck mChangedUris.add(uri); 91fca41d76f4839d6707aa9680d47a93646cd01df4John Reck } 92fca41d76f4839d6707aa9680d47a93646cd01df4John Reck } 938402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 948402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton public boolean isCallerSyncAdapter(Uri uri) { 958402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton return false; 968402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 978402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 988402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton public SQLiteOpenHelper getDatabaseHelper() { 998402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton return mOpenHelper; 1008402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 1018402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 1028402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton private boolean applyingBatch() { 1038402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton return mApplyingBatch.get() != null && mApplyingBatch.get(); 1048402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 1058402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 1068402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton @Override 1078402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton public Uri insert(Uri uri, ContentValues values) { 1088402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton Uri result = null; 1098402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton boolean callerIsSyncAdapter = isCallerSyncAdapter(uri); 1108402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton boolean applyingBatch = applyingBatch(); 1118402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton if (!applyingBatch) { 1128402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb = mOpenHelper.getWritableDatabase(); 113fca41d76f4839d6707aa9680d47a93646cd01df4John Reck mDb.beginTransaction(); 1148402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton try { 1158402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton result = insertInTransaction(uri, values, callerIsSyncAdapter); 1168402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb.setTransactionSuccessful(); 1178402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } finally { 1188402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb.endTransaction(); 1198402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 1208402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 1218402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton onEndTransaction(callerIsSyncAdapter); 1228402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } else { 1238402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton result = insertInTransaction(uri, values, callerIsSyncAdapter); 1248402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 1258402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton return result; 1268402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 1278402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 1288402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton @Override 1298402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton public int bulkInsert(Uri uri, ContentValues[] values) { 1308402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton int numValues = values.length; 1318402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton boolean callerIsSyncAdapter = isCallerSyncAdapter(uri); 1328402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb = mOpenHelper.getWritableDatabase(); 133fca41d76f4839d6707aa9680d47a93646cd01df4John Reck mDb.beginTransaction(); 1348402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton try { 1358402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton for (int i = 0; i < numValues; i++) { 1368402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton Uri result = insertInTransaction(uri, values[i], callerIsSyncAdapter); 1378402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb.yieldIfContendedSafely(); 1388402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 1398402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb.setTransactionSuccessful(); 1408402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } finally { 1418402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb.endTransaction(); 1428402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 1438402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 1448402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton onEndTransaction(callerIsSyncAdapter); 1458402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton return numValues; 1468402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 1478402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 1488402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton @Override 1498402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1508402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton int count = 0; 1518402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton boolean callerIsSyncAdapter = isCallerSyncAdapter(uri); 1528402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton boolean applyingBatch = applyingBatch(); 1538402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton if (!applyingBatch) { 1548402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb = mOpenHelper.getWritableDatabase(); 155fca41d76f4839d6707aa9680d47a93646cd01df4John Reck mDb.beginTransaction(); 1568402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton try { 1578402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton count = updateInTransaction(uri, values, selection, selectionArgs, 1588402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton callerIsSyncAdapter); 1598402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb.setTransactionSuccessful(); 1608402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } finally { 1618402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb.endTransaction(); 1628402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 1638402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 1648402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton onEndTransaction(callerIsSyncAdapter); 1658402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } else { 1668402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton count = updateInTransaction(uri, values, selection, selectionArgs, callerIsSyncAdapter); 1678402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 1688402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 1698402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton return count; 1708402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 1718402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 1728402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton @Override 1738402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton public int delete(Uri uri, String selection, String[] selectionArgs) { 1748402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton int count = 0; 1758402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton boolean callerIsSyncAdapter = isCallerSyncAdapter(uri); 1768402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton boolean applyingBatch = applyingBatch(); 1778402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton if (!applyingBatch) { 1788402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb = mOpenHelper.getWritableDatabase(); 179fca41d76f4839d6707aa9680d47a93646cd01df4John Reck mDb.beginTransaction(); 1808402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton try { 1818402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton count = deleteInTransaction(uri, selection, selectionArgs, callerIsSyncAdapter); 1828402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb.setTransactionSuccessful(); 1838402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } finally { 1848402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb.endTransaction(); 1858402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 1868402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 1878402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton onEndTransaction(callerIsSyncAdapter); 1888402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } else { 1898402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton count = deleteInTransaction(uri, selection, selectionArgs, callerIsSyncAdapter); 1908402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 1918402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton return count; 1928402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 1938402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 1948402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton @Override 1958402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1968402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton throws OperationApplicationException { 1978402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton int ypCount = 0; 1988402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton int opCount = 0; 1998402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton boolean callerIsSyncAdapter = false; 2008402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb = mOpenHelper.getWritableDatabase(); 201fca41d76f4839d6707aa9680d47a93646cd01df4John Reck mDb.beginTransaction(); 2028402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton try { 2038402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mApplyingBatch.set(true); 2048402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton final int numOperations = operations.size(); 2058402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton final ContentProviderResult[] results = new ContentProviderResult[numOperations]; 2068402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton for (int i = 0; i < numOperations; i++) { 2078402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton if (++opCount >= MAX_OPERATIONS_PER_YIELD_POINT) { 2088402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton throw new OperationApplicationException( 2098402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton "Too many content provider operations between yield points. " 2108402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton + "The maximum number of operations per yield point is " 2118402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton + MAX_OPERATIONS_PER_YIELD_POINT, ypCount); 2128402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 2138402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton final ContentProviderOperation operation = operations.get(i); 2148402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton if (!callerIsSyncAdapter && isCallerSyncAdapter(operation.getUri())) { 2158402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton callerIsSyncAdapter = true; 2168402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 2178402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton if (i > 0 && operation.isYieldAllowed()) { 2188402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton opCount = 0; 2198402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton if (mDb.yieldIfContendedSafely(SLEEP_AFTER_YIELD_DELAY)) { 2208402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton ypCount++; 2218402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 2228402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 2238402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton results[i] = operation.apply(this, results, i); 2248402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 2258402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb.setTransactionSuccessful(); 2268402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton return results; 2278402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } finally { 2288402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mApplyingBatch.set(false); 2298402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton mDb.endTransaction(); 2308402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton onEndTransaction(callerIsSyncAdapter); 2318402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 2328402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 2338402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton 2348402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton protected void onEndTransaction(boolean callerIsSyncAdapter) { 235fca41d76f4839d6707aa9680d47a93646cd01df4John Reck Set<Uri> changed; 236fca41d76f4839d6707aa9680d47a93646cd01df4John Reck synchronized (mChangedUris) { 237fca41d76f4839d6707aa9680d47a93646cd01df4John Reck changed = new HashSet<Uri>(mChangedUris); 238fca41d76f4839d6707aa9680d47a93646cd01df4John Reck mChangedUris.clear(); 239fca41d76f4839d6707aa9680d47a93646cd01df4John Reck } 240fca41d76f4839d6707aa9680d47a93646cd01df4John Reck ContentResolver resolver = getContext().getContentResolver(); 241fca41d76f4839d6707aa9680d47a93646cd01df4John Reck for (Uri uri : changed) { 2423f3da5238625bd2d73fdce7667fd61fe0f2548c5John Reck boolean syncToNetwork = !callerIsSyncAdapter && syncToNetwork(uri); 2433f3da5238625bd2d73fdce7667fd61fe0f2548c5John Reck resolver.notifyChange(uri, null, syncToNetwork); 2448402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 2458402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton } 2463f3da5238625bd2d73fdce7667fd61fe0f2548c5John Reck 2473f3da5238625bd2d73fdce7667fd61fe0f2548c5John Reck protected boolean syncToNetwork(Uri uri) { 2483f3da5238625bd2d73fdce7667fd61fe0f2548c5John Reck return false; 2493f3da5238625bd2d73fdce7667fd61fe0f2548c5John Reck } 2508402962ef58546d3cfd48fbb211b5e36df0f118eJeff Hamilton} 251