19f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff/* 29f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * Copyright (C) 2009 The Android Open Source Project 39f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * 49f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * Licensed under the Apache License, Version 2.0 (the "License"); 59f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * you may not use this file except in compliance with the License. 69f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * You may obtain a copy of the License at 79f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * 89f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * http://www.apache.org/licenses/LICENSE-2.0 99f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * 109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * Unless required by applicable law or agreed to in writing, software 119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * distributed under the License is distributed on an "AS IS" BASIS, 129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * See the License for the specific language governing permissions and 149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * limitations under the License 159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff */ 169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffpackage com.android.providers.calendar; 189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.content.ContentProvider; 209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.content.ContentProviderOperation; 219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.content.ContentProviderResult; 229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.content.ContentValues; 239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.content.Context; 249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.content.OperationApplicationException; 259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.database.sqlite.SQLiteDatabase; 269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.database.sqlite.SQLiteOpenHelper; 279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.database.sqlite.SQLiteTransactionListener; 289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.net.Uri; 298015a4086559d9d025473c2e773b2f64888c2942Alon Albertimport android.os.Binder; 30b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract; 319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport java.util.ArrayList; 339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff/** 359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * General purpose {@link ContentProvider} base class that uses SQLiteDatabase for storage. 369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff */ 379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffpublic abstract class SQLiteContentProvider extends ContentProvider 389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff implements SQLiteTransactionListener { 399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff private static final String TAG = "SQLiteContentProvider"; 419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff private SQLiteOpenHelper mOpenHelper; 439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff private volatile boolean mNotifyChange; 449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff protected SQLiteDatabase mDb; 459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff private final ThreadLocal<Boolean> mApplyingBatch = new ThreadLocal<Boolean>(); 479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff private static final int SLEEP_AFTER_YIELD_DELAY = 4000; 489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 49b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio private Boolean mIsCallerSyncAdapter; 50b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio 519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff @Override 529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff public boolean onCreate() { 539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff Context context = getContext(); 549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mOpenHelper = getDatabaseHelper(context); 559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff return true; 569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff protected abstract SQLiteOpenHelper getDatabaseHelper(Context context); 599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff /** 619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * The equivalent of the {@link #insert} method, but invoked within a transaction. 629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff */ 63b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio protected abstract Uri insertInTransaction(Uri uri, ContentValues values, 64b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio boolean callerIsSyncAdapter); 659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff /** 679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * The equivalent of the {@link #update} method, but invoked within a transaction. 689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff */ 699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff protected abstract int updateInTransaction(Uri uri, ContentValues values, String selection, 70b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio String[] selectionArgs, boolean callerIsSyncAdapter); 719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff /** 739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * The equivalent of the {@link #delete} method, but invoked within a transaction. 749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff */ 75b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio protected abstract int deleteInTransaction(Uri uri, String selection, String[] selectionArgs, 76b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio boolean callerIsSyncAdapter); 779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 78b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio protected abstract void notifyChange(boolean syncToNetwork); 799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff protected SQLiteOpenHelper getDatabaseHelper() { 819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff return mOpenHelper; 829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff private boolean applyingBatch() { 859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff return mApplyingBatch.get() != null && mApplyingBatch.get(); 869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff @Override 899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff public Uri insert(Uri uri, ContentValues values) { 909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff Uri result = null; 919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff boolean applyingBatch = applyingBatch(); 92b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio boolean isCallerSyncAdapter = getIsCallerSyncAdapter(uri); 939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff if (!applyingBatch) { 949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb = mOpenHelper.getWritableDatabase(); 959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.beginTransactionWithListener(this); 968015a4086559d9d025473c2e773b2f64888c2942Alon Albert final long identity = Binder.clearCallingIdentity(); 979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff try { 98b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio result = insertInTransaction(uri, values, isCallerSyncAdapter); 999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff if (result != null) { 1009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mNotifyChange = true; 1019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.setTransactionSuccessful(); 1039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } finally { 1048015a4086559d9d025473c2e773b2f64888c2942Alon Albert Binder.restoreCallingIdentity(identity); 1059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.endTransaction(); 1069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 108a55c3aaa2b13b5350918efda98906afb8b6206c1Alon Albert onEndTransaction(!isCallerSyncAdapter && shouldSyncFor(uri)); 1099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } else { 110b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio result = insertInTransaction(uri, values, isCallerSyncAdapter); 1119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff if (result != null) { 1129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mNotifyChange = true; 1139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff return result; 1169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 1189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff @Override 1199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff public int bulkInsert(Uri uri, ContentValues[] values) { 1209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff int numValues = values.length; 121b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio boolean isCallerSyncAdapter = getIsCallerSyncAdapter(uri); 1229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb = mOpenHelper.getWritableDatabase(); 1239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.beginTransactionWithListener(this); 1248015a4086559d9d025473c2e773b2f64888c2942Alon Albert final long identity = Binder.clearCallingIdentity(); 1259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff try { 1269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff for (int i = 0; i < numValues; i++) { 127b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio Uri result = insertInTransaction(uri, values[i], isCallerSyncAdapter); 1289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff if (result != null) { 1299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mNotifyChange = true; 1309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.yieldIfContendedSafely(); 1329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.setTransactionSuccessful(); 1349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } finally { 1358015a4086559d9d025473c2e773b2f64888c2942Alon Albert Binder.restoreCallingIdentity(identity); 1369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.endTransaction(); 1379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 139a55c3aaa2b13b5350918efda98906afb8b6206c1Alon Albert onEndTransaction(!isCallerSyncAdapter); 1409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff return numValues; 1419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 1439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff @Override 1449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff int count = 0; 1469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff boolean applyingBatch = applyingBatch(); 147b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio boolean isCallerSyncAdapter = getIsCallerSyncAdapter(uri); 1489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff if (!applyingBatch) { 1499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb = mOpenHelper.getWritableDatabase(); 1509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.beginTransactionWithListener(this); 1518015a4086559d9d025473c2e773b2f64888c2942Alon Albert final long identity = Binder.clearCallingIdentity(); 1529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff try { 153b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio count = updateInTransaction(uri, values, selection, selectionArgs, 154b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio isCallerSyncAdapter); 1559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff if (count > 0) { 1569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mNotifyChange = true; 1579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.setTransactionSuccessful(); 1599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } finally { 1608015a4086559d9d025473c2e773b2f64888c2942Alon Albert Binder.restoreCallingIdentity(identity); 1619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.endTransaction(); 1629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 164a55c3aaa2b13b5350918efda98906afb8b6206c1Alon Albert onEndTransaction(!isCallerSyncAdapter && shouldSyncFor(uri)); 1659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } else { 166b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio count = updateInTransaction(uri, values, selection, selectionArgs, 167b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio isCallerSyncAdapter); 1689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff if (count > 0) { 1699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mNotifyChange = true; 1709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 1739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff return count; 1749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 1769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff @Override 1779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff public int delete(Uri uri, String selection, String[] selectionArgs) { 1789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff int count = 0; 1799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff boolean applyingBatch = applyingBatch(); 180b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio boolean isCallerSyncAdapter = getIsCallerSyncAdapter(uri); 1819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff if (!applyingBatch) { 1829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb = mOpenHelper.getWritableDatabase(); 1839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.beginTransactionWithListener(this); 1848015a4086559d9d025473c2e773b2f64888c2942Alon Albert final long identity = Binder.clearCallingIdentity(); 1859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff try { 186b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio count = deleteInTransaction(uri, selection, selectionArgs, isCallerSyncAdapter); 1879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff if (count > 0) { 1889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mNotifyChange = true; 1899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.setTransactionSuccessful(); 1919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } finally { 1928015a4086559d9d025473c2e773b2f64888c2942Alon Albert Binder.restoreCallingIdentity(identity); 1939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.endTransaction(); 1949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 1959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 196a55c3aaa2b13b5350918efda98906afb8b6206c1Alon Albert onEndTransaction(!isCallerSyncAdapter && shouldSyncFor(uri)); 1979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } else { 198b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio count = deleteInTransaction(uri, selection, selectionArgs, isCallerSyncAdapter); 1999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff if (count > 0) { 2009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mNotifyChange = true; 2019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 2029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 2039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff return count; 2049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 2059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 2069ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert protected boolean getIsCallerSyncAdapter(Uri uri) { 207b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio boolean isCurrentSyncAdapter = QueryParameterUtils.readBooleanQueryParameter(uri, 208b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik CalendarContract.CALLER_IS_SYNCADAPTER, false); 209b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio if (mIsCallerSyncAdapter == null || mIsCallerSyncAdapter) { 210b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio mIsCallerSyncAdapter = isCurrentSyncAdapter; 211b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio } 212b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio return isCurrentSyncAdapter; 213b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio } 214b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio 2159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff @Override 2169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 2179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff throws OperationApplicationException { 21877f0cf2de36fd24541480638da22f477ec0af22fAlon Albert final int numOperations = operations.size(); 21977f0cf2de36fd24541480638da22f477ec0af22fAlon Albert if (numOperations == 0) { 22077f0cf2de36fd24541480638da22f477ec0af22fAlon Albert return new ContentProviderResult[0]; 22177f0cf2de36fd24541480638da22f477ec0af22fAlon Albert } 2229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb = mOpenHelper.getWritableDatabase(); 2239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.beginTransactionWithListener(this); 22477f0cf2de36fd24541480638da22f477ec0af22fAlon Albert final boolean isCallerSyncAdapter = getIsCallerSyncAdapter(operations.get(0).getUri()); 2258015a4086559d9d025473c2e773b2f64888c2942Alon Albert final long identity = Binder.clearCallingIdentity(); 2269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff try { 2279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mApplyingBatch.set(true); 2289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff final ContentProviderResult[] results = new ContentProviderResult[numOperations]; 2299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff for (int i = 0; i < numOperations; i++) { 2309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff final ContentProviderOperation operation = operations.get(i); 2319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff if (i > 0 && operation.isYieldAllowed()) { 2329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.yieldIfContendedSafely(SLEEP_AFTER_YIELD_DELAY); 2339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 2349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff results[i] = operation.apply(this, results, i); 2359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 2369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.setTransactionSuccessful(); 2379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff return results; 2389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } finally { 2399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mApplyingBatch.set(false); 2409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mDb.endTransaction(); 241a55c3aaa2b13b5350918efda98906afb8b6206c1Alon Albert onEndTransaction(!isCallerSyncAdapter); 2428015a4086559d9d025473c2e773b2f64888c2942Alon Albert Binder.restoreCallingIdentity(identity); 2439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 2449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 2459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 2469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff public void onBegin() { 247b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio mIsCallerSyncAdapter = null; 2489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff onBeginTransaction(); 2499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 2509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 2519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff public void onCommit() { 2529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff beforeTransactionCommit(); 2539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 2549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 2559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff public void onRollback() { 2569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff // not used 2579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 2589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 2599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff protected void onBeginTransaction() { 2609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 2619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 2629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff protected void beforeTransactionCommit() { 2639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 2649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff 265a55c3aaa2b13b5350918efda98906afb8b6206c1Alon Albert protected void onEndTransaction(boolean syncToNetwork) { 2669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff if (mNotifyChange) { 2679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff mNotifyChange = false; 268b7c010fdc02695b692cd74acf432e8ccb3bda70cFabrice Di Meglio // We sync to network if the caller was not the sync adapter 269a55c3aaa2b13b5350918efda98906afb8b6206c1Alon Albert notifyChange(syncToNetwork); 2709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 2719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff } 272a55c3aaa2b13b5350918efda98906afb8b6206c1Alon Albert 273a55c3aaa2b13b5350918efda98906afb8b6206c1Alon Albert /** 274a55c3aaa2b13b5350918efda98906afb8b6206c1Alon Albert * Some URI's are maintained locally so we should not request a sync for them 275a55c3aaa2b13b5350918efda98906afb8b6206c1Alon Albert */ 276a55c3aaa2b13b5350918efda98906afb8b6206c1Alon Albert protected abstract boolean shouldSyncFor(Uri uri); 2779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff} 278