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