1bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan/* 2bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * Copyright (C) 2010 The Android Open Source Project 3bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 4bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * Licensed under the Apache License, Version 2.0 (the "License"); 5bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * you may not use this file except in compliance with the License. 6bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * You may obtain a copy of the License at 7bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 8bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * http://www.apache.org/licenses/LICENSE-2.0 9bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 10bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * Unless required by applicable law or agreed to in writing, software 11bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * distributed under the License is distributed on an "AS IS" BASIS, 12bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * See the License for the specific language governing permissions and 14bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * limitations under the License. 15bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 16bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 17bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanpackage com.android.calendar; 18bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 19bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport com.android.calendar.AsyncQueryServiceHelper.OperationInfo; 20bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 21bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.content.ContentProviderOperation; 22bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.content.ContentProviderResult; 23bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.content.ContentResolver; 24bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.content.ContentValues; 25bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.content.Context; 26bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.database.Cursor; 27bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.net.Uri; 28bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.os.Handler; 29bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.os.Message; 30bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.util.Log; 31bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 32bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport java.util.ArrayList; 3337960c091b5912dd45beb561a85a9064ea42e616Erikimport java.util.concurrent.atomic.AtomicInteger; 34bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 35bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan/** 36bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * A helper class that executes {@link ContentResolver} calls in a background 37bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link android.app.Service}. This minimizes the chance of the call getting 38bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * lost because the caller ({@link android.app.Activity}) is killed. It is 39bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * designed for easy migration from {@link android.content.AsyncQueryHandler} 40bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * which calls the {@link ContentResolver} in a background thread. This supports 41bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * query/insert/update/delete and also batch mode i.e. 42bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link ContentProviderOperation}. It also supports delay execution and cancel 43bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * which allows for time-limited undo. Note that there's one queue per 44bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * application which serializes all the calls. 45bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 46bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanpublic class AsyncQueryService extends Handler { 47bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan private static final String TAG = "AsyncQuery"; 480847dbf80788392f1e6e2a25f6f0a91e1f9cda04Michael Chan static final boolean localLOGV = false; 49bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 5037960c091b5912dd45beb561a85a9064ea42e616Erik // Used for generating unique tokens for calls to this service 5137960c091b5912dd45beb561a85a9064ea42e616Erik private static AtomicInteger mUniqueToken = new AtomicInteger(0); 5237960c091b5912dd45beb561a85a9064ea42e616Erik 53bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan private Context mContext; 54bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan private Handler mHandler = this; // can be overridden for testing 55bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 56bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 57bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * Data class which holds into info of the queued operation 58bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 59bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan public static class Operation { 60bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan static final int EVENT_ARG_QUERY = 1; 61bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan static final int EVENT_ARG_INSERT = 2; 62bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan static final int EVENT_ARG_UPDATE = 3; 63bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan static final int EVENT_ARG_DELETE = 4; 64bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan static final int EVENT_ARG_BATCH = 5; 65bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 66bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 67bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * unique identify for cancellation purpose 68bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 69bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan public int token; 70bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 71bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 72bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * One of the EVENT_ARG_ constants in the class describing the operation 73bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 74bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan public int op; 75bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 76bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 77bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link SystemClock.elapsedRealtime()} based 78bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 79bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan public long scheduledExecutionTime; 80bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 81bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan protected static char opToChar(int op) { 82bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan switch (op) { 83bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan case Operation.EVENT_ARG_QUERY: 84bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan return 'Q'; 85bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan case Operation.EVENT_ARG_INSERT: 86bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan return 'I'; 87bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan case Operation.EVENT_ARG_UPDATE: 88bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan return 'U'; 89bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan case Operation.EVENT_ARG_DELETE: 90bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan return 'D'; 91bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan case Operation.EVENT_ARG_BATCH: 92bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan return 'B'; 93bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan default: 94bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan return '?'; 95bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 96bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 97bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 98bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan @Override 99bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan public String toString() { 100bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan StringBuilder builder = new StringBuilder(); 101bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan builder.append("Operation [op="); 102bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan builder.append(op); 103bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan builder.append(", token="); 104bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan builder.append(token); 105bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan builder.append(", scheduledExecutionTime="); 106bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan builder.append(scheduledExecutionTime); 107bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan builder.append("]"); 108bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan return builder.toString(); 109bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 110bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 111bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 112bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan public AsyncQueryService(Context context) { 113bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan mContext = context; 114bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 115bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 116bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 11737960c091b5912dd45beb561a85a9064ea42e616Erik * returns a practically unique token for db operations 11837960c091b5912dd45beb561a85a9064ea42e616Erik */ 11937960c091b5912dd45beb561a85a9064ea42e616Erik public final int getNextToken() { 12037960c091b5912dd45beb561a85a9064ea42e616Erik return mUniqueToken.getAndIncrement(); 12137960c091b5912dd45beb561a85a9064ea42e616Erik } 12237960c091b5912dd45beb561a85a9064ea42e616Erik 12337960c091b5912dd45beb561a85a9064ea42e616Erik /** 124bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * Gets the last delayed operation. It is typically used for canceling. 125bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 126bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @return Operation object which contains of the last cancelable operation 127bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 128bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan public final Operation getLastCancelableOperation() { 129bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan return AsyncQueryServiceHelper.getLastCancelableOperation(); 130bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 131bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 132bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 133bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * Attempts to cancel operation that has not already started. Note that 134bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * there is no guarantee that the operation will be canceled. They still may 135bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * result in a call to on[Query/Insert/Update/Delete/Batch]Complete after 136bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * this call has completed. 137bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 138bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param token The token representing the operation to be canceled. If 139bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * multiple operations have the same token they will all be 140bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * canceled. 141bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 142bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan public final int cancelOperation(int token) { 143bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan return AsyncQueryServiceHelper.cancelOperation(token); 144bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 145bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 146bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 147bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * This method begins an asynchronous query. When the query is done 148bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link #onQueryComplete} is called. 149bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 150bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param token A token passed into {@link #onQueryComplete} to identify the 151bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * query. 152bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param cookie An object that gets passed into {@link #onQueryComplete} 153bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param uri The URI, using the content:// scheme, for the content to 154bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * retrieve. 155bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param projection A list of which columns to return. Passing null will 156bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * return all columns, which is discouraged to prevent reading 157bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * data from storage that isn't going to be used. 158bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param selection A filter declaring which rows to return, formatted as an 159bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * SQL WHERE clause (excluding the WHERE itself). Passing null 160bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * will return all rows for the given URI. 161bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param selectionArgs You may include ?s in selection, which will be 162bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * replaced by the values from selectionArgs, in the order that 163bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * they appear in the selection. The values will be bound as 164bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * Strings. 165bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 166bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * (excluding the ORDER BY itself). Passing null will use the 167bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * default sort order, which may be unordered. 168bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 169bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan public void startQuery(int token, Object cookie, Uri uri, String[] projection, 170bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan String selection, String[] selectionArgs, String orderBy) { 171bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan OperationInfo info = new OperationInfo(); 172bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.op = Operation.EVENT_ARG_QUERY; 173bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.resolver = mContext.getContentResolver(); 174bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 175bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.handler = mHandler; 176bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.token = token; 177bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.cookie = cookie; 178bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.uri = uri; 179bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.projection = projection; 180bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.selection = selection; 181bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.selectionArgs = selectionArgs; 182bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.orderBy = orderBy; 183bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 184bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan AsyncQueryServiceHelper.queueOperation(mContext, info); 185bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 186bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 187bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 188bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * This method begins an asynchronous insert. When the insert operation is 189bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * done {@link #onInsertComplete} is called. 190bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 191bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param token A token passed into {@link #onInsertComplete} to identify 192bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * the insert operation. 193bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param cookie An object that gets passed into {@link #onInsertComplete} 194bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param uri the Uri passed to the insert operation. 195bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param initialValues the ContentValues parameter passed to the insert 196bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * operation. 197bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param delayMillis delay in executing the operation. This operation will 198bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * execute before the delayed time when another operation is 199bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * added. Useful for implementing single level undo. 200bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 20137960c091b5912dd45beb561a85a9064ea42e616Erik public void startInsert(int token, Object cookie, Uri uri, ContentValues initialValues, 202bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan long delayMillis) { 203bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan OperationInfo info = new OperationInfo(); 204bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.op = Operation.EVENT_ARG_INSERT; 205bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.resolver = mContext.getContentResolver(); 206bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.handler = mHandler; 207bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 208bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.token = token; 209bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.cookie = cookie; 210bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.uri = uri; 211bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.values = initialValues; 212bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.delayMillis = delayMillis; 213bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 214bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan AsyncQueryServiceHelper.queueOperation(mContext, info); 215bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 216bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 217bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 218bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * This method begins an asynchronous update. When the update operation is 219bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * done {@link #onUpdateComplete} is called. 220bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 221bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param token A token passed into {@link #onUpdateComplete} to identify 222bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * the update operation. 223bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param cookie An object that gets passed into {@link #onUpdateComplete} 224bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param uri the Uri passed to the update operation. 225bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param values the ContentValues parameter passed to the update operation. 226bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param selection A filter declaring which rows to update, formatted as an 227bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * SQL WHERE clause (excluding the WHERE itself). Passing null 228bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * will update all rows for the given URI. 229bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param selectionArgs You may include ?s in selection, which will be 230bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * replaced by the values from selectionArgs, in the order that 231bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * they appear in the selection. The values will be bound as 232bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * Strings. 233bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param delayMillis delay in executing the operation. This operation will 234bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * execute before the delayed time when another operation is 235bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * added. Useful for implementing single level undo. 236bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 23737960c091b5912dd45beb561a85a9064ea42e616Erik public void startUpdate(int token, Object cookie, Uri uri, ContentValues values, 238bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan String selection, String[] selectionArgs, long delayMillis) { 239bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan OperationInfo info = new OperationInfo(); 240bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.op = Operation.EVENT_ARG_UPDATE; 241bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.resolver = mContext.getContentResolver(); 242bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.handler = mHandler; 243bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 244bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.token = token; 245bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.cookie = cookie; 246bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.uri = uri; 247bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.values = values; 248bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.selection = selection; 249bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.selectionArgs = selectionArgs; 250bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.delayMillis = delayMillis; 251bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 252bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan AsyncQueryServiceHelper.queueOperation(mContext, info); 253bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 254bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 255bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 256bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * This method begins an asynchronous delete. When the delete operation is 257bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * done {@link #onDeleteComplete} is called. 258bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 259bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param token A token passed into {@link #onDeleteComplete} to identify 260bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * the delete operation. 261bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param cookie An object that gets passed into {@link #onDeleteComplete} 262bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param uri the Uri passed to the delete operation. 263bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param selection A filter declaring which rows to delete, formatted as an 264bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * SQL WHERE clause (excluding the WHERE itself). Passing null 265bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * will delete all rows for the given URI. 266bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param selectionArgs You may include ?s in selection, which will be 267bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * replaced by the values from selectionArgs, in the order that 268bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * they appear in the selection. The values will be bound as 269bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * Strings. 270bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param delayMillis delay in executing the operation. This operation will 271bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * execute before the delayed time when another operation is 272bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * added. Useful for implementing single level undo. 273bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 27437960c091b5912dd45beb561a85a9064ea42e616Erik public void startDelete(int token, Object cookie, Uri uri, String selection, 275bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan String[] selectionArgs, long delayMillis) { 276bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan OperationInfo info = new OperationInfo(); 277bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.op = Operation.EVENT_ARG_DELETE; 278bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.resolver = mContext.getContentResolver(); 279bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.handler = mHandler; 280bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 281bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.token = token; 282bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.cookie = cookie; 283bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.uri = uri; 284bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.selection = selection; 285bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.selectionArgs = selectionArgs; 286bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.delayMillis = delayMillis; 287bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 288bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan AsyncQueryServiceHelper.queueOperation(mContext, info); 289bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 290bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 291bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 292bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * This method begins an asynchronous {@link ContentProviderOperation}. When 293bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * the operation is done {@link #onBatchComplete} is called. 294bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 295bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param token A token passed into {@link #onDeleteComplete} to identify 296bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * the delete operation. 297bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param cookie An object that gets passed into {@link #onDeleteComplete} 298bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param authority the authority used for the 299bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link ContentProviderOperation}. 300bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param cpo the {@link ContentProviderOperation} to be executed. 301bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param delayMillis delay in executing the operation. This operation will 302bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * execute before the delayed time when another operation is 303bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * added. Useful for implementing single level undo. 304bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 30537960c091b5912dd45beb561a85a9064ea42e616Erik public void startBatch(int token, Object cookie, String authority, 306bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan ArrayList<ContentProviderOperation> cpo, long delayMillis) { 307bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan OperationInfo info = new OperationInfo(); 308bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.op = Operation.EVENT_ARG_BATCH; 309bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.resolver = mContext.getContentResolver(); 310bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.handler = mHandler; 311bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 312bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.token = token; 313bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.cookie = cookie; 314bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.authority = authority; 315bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.cpo = cpo; 316bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan info.delayMillis = delayMillis; 317bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 318bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan AsyncQueryServiceHelper.queueOperation(mContext, info); 319bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 320bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 321bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 322bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * Called when an asynchronous query is completed. 323bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 324bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param token the token to identify the query, passed in from 325bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link #startQuery}. 326bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param cookie the cookie object passed in from {@link #startQuery}. 327bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param cursor The cursor holding the results from the query. 328bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 329bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 330bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan if (localLOGV) { 331bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan Log.d(TAG, "########## default onQueryComplete"); 332bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 333bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 334bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 335bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 336bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * Called when an asynchronous insert is completed. 337bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 338bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param token the token to identify the query, passed in from 339bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link #startInsert}. 340bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param cookie the cookie object that's passed in from 341bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link #startInsert}. 342bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param uri the uri returned from the insert operation. 343bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 344bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan protected void onInsertComplete(int token, Object cookie, Uri uri) { 345bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan if (localLOGV) { 346bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan Log.d(TAG, "########## default onInsertComplete"); 347bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 348bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 349bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 350bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 351bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * Called when an asynchronous update is completed. 352bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 353bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param token the token to identify the query, passed in from 354bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link #startUpdate}. 355bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param cookie the cookie object that's passed in from 356bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link #startUpdate}. 357bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param result the result returned from the update operation 358bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 359bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan protected void onUpdateComplete(int token, Object cookie, int result) { 360bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan if (localLOGV) { 361bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan Log.d(TAG, "########## default onUpdateComplete"); 362bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 363bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 364bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 365bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 366bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * Called when an asynchronous delete is completed. 367bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 368bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param token the token to identify the query, passed in from 369bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link #startDelete}. 370bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param cookie the cookie object that's passed in from 371bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link #startDelete}. 372bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param result the result returned from the delete operation 373bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 374bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan protected void onDeleteComplete(int token, Object cookie, int result) { 375bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan if (localLOGV) { 376bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan Log.d(TAG, "########## default onDeleteComplete"); 377bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 378bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 379bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 380bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan /** 381bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * Called when an asynchronous {@link ContentProviderOperation} is 382bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * completed. 383bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * 384bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param token the token to identify the query, passed in from 385bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link #startDelete}. 386bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param cookie the cookie object that's passed in from 387bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link #startDelete}. 388bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * @param results the result returned from executing the 389bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan * {@link ContentProviderOperation} 390bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan */ 391bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan protected void onBatchComplete(int token, Object cookie, ContentProviderResult[] results) { 392bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan if (localLOGV) { 393bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan Log.d(TAG, "########## default onBatchComplete"); 394bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 395bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 396bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 397bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan @Override 398bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan public void handleMessage(Message msg) { 399bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan OperationInfo info = (OperationInfo) msg.obj; 400bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 401bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan int token = msg.what; 402bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan int op = msg.arg1; 403bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 404bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan if (localLOGV) { 405bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan Log.d(TAG, "AsyncQueryService.handleMessage: token=" + token + ", op=" + op 406bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan + ", result=" + info.result); 407bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 408bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 409bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan // pass token back to caller on each callback. 410bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan switch (op) { 411bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan case Operation.EVENT_ARG_QUERY: 412bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan onQueryComplete(token, info.cookie, (Cursor) info.result); 413bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan break; 414bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 415bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan case Operation.EVENT_ARG_INSERT: 416bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan onInsertComplete(token, info.cookie, (Uri) info.result); 417bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan break; 418bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 419bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan case Operation.EVENT_ARG_UPDATE: 420bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan onUpdateComplete(token, info.cookie, (Integer) info.result); 421bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan break; 422bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 423bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan case Operation.EVENT_ARG_DELETE: 424bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan onDeleteComplete(token, info.cookie, (Integer) info.result); 425bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan break; 426bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 427bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan case Operation.EVENT_ARG_BATCH: 428bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan onBatchComplete(token, info.cookie, (ContentProviderResult[]) info.result); 429bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan break; 430bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 431bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 432bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan 433bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan// @VisibleForTesting 434bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan protected void setTestHandler(Handler handler) { 435bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan mHandler = handler; 436bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan } 437bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan} 438