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.AsyncQueryService.Operation;
20bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
21bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.app.IntentService;
22bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.content.ContentProviderOperation;
23bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.content.ContentResolver;
24bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.content.ContentValues;
25bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.content.Context;
26bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.content.Intent;
27bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.content.OperationApplicationException;
28bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.database.Cursor;
29bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.net.Uri;
30bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.os.Handler;
31bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.os.Message;
32bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.os.RemoteException;
33bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.os.SystemClock;
34bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport android.util.Log;
35bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
36bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport java.util.ArrayList;
37bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport java.util.Arrays;
38bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport java.util.Iterator;
39bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport java.util.PriorityQueue;
40bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport java.util.concurrent.Delayed;
41bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanimport java.util.concurrent.TimeUnit;
42bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
43bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chanpublic class AsyncQueryServiceHelper extends IntentService {
44bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    private static final String TAG = "AsyncQuery";
45bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
46bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    private static final PriorityQueue<OperationInfo> sWorkQueue =
47bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        new PriorityQueue<OperationInfo>();
48bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
49bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    protected Class<AsyncQueryService> mService = AsyncQueryService.class;
50bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
51bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    protected static class OperationInfo implements Delayed{
52bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public int token; // Used for cancel
53bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public int op;
54bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public ContentResolver resolver;
55bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public Uri uri;
56bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public String authority;
57bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public Handler handler;
58bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public String[] projection;
59bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public String selection;
60bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public String[] selectionArgs;
61bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public String orderBy;
62bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public Object result;
63bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public Object cookie;
64bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public ContentValues values;
65bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public ArrayList<ContentProviderOperation> cpo;
66bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
67bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        /**
68bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan         * delayMillis is relative time e.g. 10,000 milliseconds
69bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan         */
70bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public long delayMillis;
71bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
72bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        /**
73bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan         * scheduleTimeMillis is the time scheduled for this to be processed.
74bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan         * e.g. SystemClock.elapsedRealtime() + 10,000 milliseconds Based on
75bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan         * {@link android.os.SystemClock#elapsedRealtime }
76bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan         */
77bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        private long mScheduledTimeMillis = 0;
78bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
79bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        // @VisibleForTesting
80bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        void calculateScheduledTime() {
81bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            mScheduledTimeMillis = SystemClock.elapsedRealtime() + delayMillis;
82bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
83bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
84bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        // @Override // Uncomment with Java6
85bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public long getDelay(TimeUnit unit) {
86bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            return unit.convert(mScheduledTimeMillis - SystemClock.elapsedRealtime(),
87bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    TimeUnit.MILLISECONDS);
88bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
89bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
90bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        // @Override // Uncomment with Java6
91bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public int compareTo(Delayed another) {
92bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            OperationInfo anotherArgs = (OperationInfo) another;
93bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            if (this.mScheduledTimeMillis == anotherArgs.mScheduledTimeMillis) {
94bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                return 0;
95bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            } else if (this.mScheduledTimeMillis < anotherArgs.mScheduledTimeMillis) {
96bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                return -1;
97bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            } else {
98bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                return 1;
99bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            }
100bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
101bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
102bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        @Override
103bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public String toString() {
104bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            StringBuilder builder = new StringBuilder();
105bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append("OperationInfo [\n\t token= ");
106bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(token);
107bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t op= ");
108bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(Operation.opToChar(op));
109bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t uri= ");
110bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(uri);
111bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t authority= ");
112bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(authority);
113bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t delayMillis= ");
114bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(delayMillis);
115bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t mScheduledTimeMillis= ");
116bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(mScheduledTimeMillis);
117bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t resolver= ");
118bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(resolver);
119bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t handler= ");
120bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(handler);
121bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t projection= ");
122bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(Arrays.toString(projection));
123bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t selection= ");
124bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(selection);
125bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t selectionArgs= ");
126bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(Arrays.toString(selectionArgs));
127bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t orderBy= ");
128bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(orderBy);
129bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t result= ");
130bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(result);
131bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t cookie= ");
132bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(cookie);
133bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t values= ");
134bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(values);
135bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(",\n\t cpo= ");
136bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append(cpo);
137bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            builder.append("\n]");
138bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            return builder.toString();
139bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
140bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
141bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        /**
142bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan         * Compares an user-visible operation to this private OperationInfo
143bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan         * object
144bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan         *
145bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan         * @param o operation to be compared
146bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan         * @return true if logically equivalent
147bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan         */
148bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public boolean equivalent(Operation o) {
149bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            return o.token == this.token && o.op == this.op;
150bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
151bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    }
152bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
153bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    /**
154bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     * Queues the operation for execution
155bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     *
156bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     * @param context
157bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     * @param args OperationInfo object describing the operation
158bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     */
159bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    static public void queueOperation(Context context, OperationInfo args) {
160bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        // Set the schedule time for execution based on the desired delay.
161bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        args.calculateScheduledTime();
162bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
163bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        synchronized (sWorkQueue) {
164bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            sWorkQueue.add(args);
165bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            sWorkQueue.notify();
166bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
167bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
168bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        context.startService(new Intent(context, AsyncQueryServiceHelper.class));
169bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    }
170bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
171bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    /**
172bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     * Gets the last delayed operation. It is typically used for canceling.
173bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     *
174bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     * @return Operation object which contains of the last cancelable operation
175bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     */
176bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    static public Operation getLastCancelableOperation() {
177bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        long lastScheduleTime = Long.MIN_VALUE;
178bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        Operation op = null;
179bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
180bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        synchronized (sWorkQueue) {
181bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            // Unknown order even for a PriorityQueue
182bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            Iterator<OperationInfo> it = sWorkQueue.iterator();
183bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            while (it.hasNext()) {
184bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                OperationInfo info = it.next();
185bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                if (info.delayMillis > 0 && lastScheduleTime < info.mScheduledTimeMillis) {
186bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    if (op == null) {
187bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        op = new Operation();
188bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    }
189bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
190bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    op.token = info.token;
191bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    op.op = info.op;
192bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    op.scheduledExecutionTime = info.mScheduledTimeMillis;
193bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
194bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    lastScheduleTime = info.mScheduledTimeMillis;
195bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                }
196bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            }
197bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
198bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
199bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        if (AsyncQueryService.localLOGV) {
200bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            Log.d(TAG, "getLastCancelableOperation -> Operation:" + Operation.opToChar(op.op)
201bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    + " token:" + op.token);
202bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
203bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        return op;
204bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    }
205bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
206bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    /**
207bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     * Attempts to cancel operation that has not already started. Note that
208bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     * there is no guarantee that the operation will be canceled. They still may
209bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     * result in a call to on[Query/Insert/Update/Delete/Batch]Complete after
210bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     * this call has completed.
211bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     *
212bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     * @param token The token representing the operation to be canceled. If
213bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     *            multiple operations have the same token they will all be
214bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     *            canceled.
215bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan     */
216bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    static public int cancelOperation(int token) {
217bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        int canceled = 0;
218bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        synchronized (sWorkQueue) {
219bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            Iterator<OperationInfo> it = sWorkQueue.iterator();
220bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            while (it.hasNext()) {
221bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                if (it.next().token == token) {
222bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    it.remove();
223bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    ++canceled;
224bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                }
225bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            }
226bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
227bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
228bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        if (AsyncQueryService.localLOGV) {
229bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            Log.d(TAG, "cancelOperation(" + token + ") -> " + canceled);
230bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
231bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        return canceled;
232bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    }
233bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
234bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    public AsyncQueryServiceHelper(String name) {
235bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        super(name);
236bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    }
237bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
238bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    public AsyncQueryServiceHelper() {
239bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        super("AsyncQueryServiceHelper");
240bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    }
241bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
242bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    @Override
243bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    protected void onHandleIntent(Intent intent) {
244bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        OperationInfo args;
245bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
246bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        if (AsyncQueryService.localLOGV) {
247bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            Log.d(TAG, "onHandleIntent: queue size=" + sWorkQueue.size());
248bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
249bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        synchronized (sWorkQueue) {
250bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            while (true) {
251bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                /*
252bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                 * This method can be called with no work because of
253bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                 * cancellations
254bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                 */
255bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                if (sWorkQueue.size() == 0) {
256bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    return;
257bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                } else if (sWorkQueue.size() == 1) {
258bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    OperationInfo first = sWorkQueue.peek();
259bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    long waitTime = first.mScheduledTimeMillis - SystemClock.elapsedRealtime();
260bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    if (waitTime > 0) {
261bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        try {
262bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                            sWorkQueue.wait(waitTime);
263bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        } catch (InterruptedException e) {
264bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        }
265bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    }
266bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                }
267bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
268bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                args = sWorkQueue.poll();
269bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                if (args != null) {
270bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    // Got work to do. Break out of waiting loop
271bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    break;
272bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                }
273bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            }
274bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
275bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
276bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        if (AsyncQueryService.localLOGV) {
277bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            Log.d(TAG, "onHandleIntent: " + args);
278bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
279bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
280bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        ContentResolver resolver = args.resolver;
281bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        if (resolver != null) {
282bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
283bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            switch (args.op) {
284bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                case Operation.EVENT_ARG_QUERY:
285bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    Cursor cursor;
286bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    try {
287bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        cursor = resolver.query(args.uri, args.projection, args.selection,
288bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                                args.selectionArgs, args.orderBy);
289bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        /*
290bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                         * Calling getCount() causes the cursor window to be
291bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                         * filled, which will make the first access on the main
292bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                         * thread a lot faster
293bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                         */
294bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        if (cursor != null) {
295bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                            cursor.getCount();
296bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        }
297bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    } catch (Exception e) {
298bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        Log.w(TAG, e.toString());
299bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        cursor = null;
300bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    }
301bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
302bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    args.result = cursor;
303bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    break;
304bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
305bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                case Operation.EVENT_ARG_INSERT:
306bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    args.result = resolver.insert(args.uri, args.values);
307bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    break;
308bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
309bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                case Operation.EVENT_ARG_UPDATE:
310bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    args.result = resolver.update(args.uri, args.values, args.selection,
311bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                            args.selectionArgs);
312bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    break;
313bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
314bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                case Operation.EVENT_ARG_DELETE:
315ae0a1002a66b13fcedffaa9561f3e9c92eb99f95Huaqiang Chen                    try {
316ae0a1002a66b13fcedffaa9561f3e9c92eb99f95Huaqiang Chen                        args.result = resolver.delete(args.uri, args.selection, args.selectionArgs);
317ae0a1002a66b13fcedffaa9561f3e9c92eb99f95Huaqiang Chen                    } catch (IllegalArgumentException e) {
318ae0a1002a66b13fcedffaa9561f3e9c92eb99f95Huaqiang Chen                        Log.w(TAG, "Delete failed.");
319ae0a1002a66b13fcedffaa9561f3e9c92eb99f95Huaqiang Chen                        Log.w(TAG, e.toString());
320ae0a1002a66b13fcedffaa9561f3e9c92eb99f95Huaqiang Chen                        args.result = 0;
321ae0a1002a66b13fcedffaa9561f3e9c92eb99f95Huaqiang Chen                    }
322ae0a1002a66b13fcedffaa9561f3e9c92eb99f95Huaqiang Chen
323bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    break;
324bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
325bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                case Operation.EVENT_ARG_BATCH:
326bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    try {
327bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        args.result = resolver.applyBatch(args.authority, args.cpo);
328bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    } catch (RemoteException e) {
329bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        Log.e(TAG, e.toString());
330bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        args.result = null;
331bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    } catch (OperationApplicationException e) {
332bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        Log.e(TAG, e.toString());
333bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        args.result = null;
334bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    }
335bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                    break;
336bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            }
337bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
338bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            /*
339bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan             * passing the original token value back to the caller on top of the
340bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan             * event values in arg1.
341bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan             */
342bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            Message reply = args.handler.obtainMessage(args.token);
343bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            reply.obj = args;
344bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            reply.arg1 = args.op;
345bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
346bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            if (AsyncQueryService.localLOGV) {
347bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                Log.d(TAG, "onHandleIntent: op=" + Operation.opToChar(args.op) + ", token="
348bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                        + reply.what);
349bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            }
350bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
351bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            reply.sendToTarget();
352bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
353bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    }
354bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
355bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    @Override
356bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    public void onStart(Intent intent, int startId) {
357bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        if (AsyncQueryService.localLOGV) {
358bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            Log.d(TAG, "onStart startId=" + startId);
359bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
360bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        super.onStart(intent, startId);
361bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    }
362bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
363bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    @Override
364bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    public void onCreate() {
365bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        if (AsyncQueryService.localLOGV) {
366bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            Log.d(TAG, "onCreate");
367bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
368bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        super.onCreate();
369bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    }
370bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
371bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    @Override
372bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    public void onDestroy() {
373bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        if (AsyncQueryService.localLOGV) {
374bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            Log.d(TAG, "onDestroy");
375bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        }
376bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        super.onDestroy();
377bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    }
378bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan}
379