19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.internal.telephony; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.AsyncQueryHandler; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.SQLException; 236a3d188f18b5ae278c802c8bbd1e0a44da555cdfBai Taoimport android.location.CountryDetector; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 28d34d30ac2e5d7fc0ee0592187492acd3d52a2545David Brownimport android.os.SystemProperties; 29158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brownimport android.provider.ContactsContract.CommonDataKinds.SipAddress; 30158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brownimport android.provider.ContactsContract.Data; 313c513ed95cee2e0bcd7208cb7e46307f09c907c9Dmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.telephony.PhoneNumberUtils; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 3794202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown * Helper class to make it easier to run asynchronous caller-id lookup queries. 3894202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown * @see CallerInfo 3994202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown * 4094202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown * {@hide} 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class CallerInfoAsyncQuery { 43431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato private static final boolean DBG = false; 44e22415817febc8d3229d1774f3b0dfda0fda8f46Nicolas Catania private static final String LOG_TAG = "CallerInfoAsyncQuery"; 452563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int EVENT_NEW_QUERY = 1; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int EVENT_ADD_LISTENER = 2; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int EVENT_END_OF_QUEUE = 3; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int EVENT_EMERGENCY_NUMBER = 4; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int EVENT_VOICEMAIL_NUMBER = 5; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private CallerInfoAsyncQueryHandler mHandler; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 542ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // If the CallerInfo query finds no contacts, should we use the 552ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // PhoneNumberOfflineGeocoder to look up a "geo description"? 562ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // (TODO: This could become a flag in config.xml if it ever needs to be 572ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // configured on a per-product basis.) 58cec25c4e8afdc56451f7405f8605c1d67433e2ffDavid Brown private static final boolean ENABLE_UNKNOWN_NUMBER_GEO_DESCRIPTION = true; 592ef46c65877a7188868cec440fbe93086e011f5bDavid Brown 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Interface for a CallerInfoAsyncQueryHandler result return. 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface OnQueryCompleteListener { 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 652563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville * Called when the query is complete. 662563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville */ 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onQueryComplete(int token, Object cookie, CallerInfo ci); 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 692563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 702563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Wrap the cookie from the WorkerArgs with additional information needed by our 732563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville * classes. 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final class CookieWrapper { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public OnQueryCompleteListener listener; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Object cookie; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int event; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String number; 802563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville } 812563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 822563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Simple exception used to communicate problems with the query pool. 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class QueryPoolException extends SQLException { 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public QueryPoolException(String error) { 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(error); 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 912563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Our own implementation of the AsyncQueryHandler. 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class CallerInfoAsyncQueryHandler extends AsyncQueryHandler { 962563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The information relevant to each CallerInfo query. Each query may have multiple 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * listeners, so each AsyncCursorInfo is associated with 2 or more CookieWrapper 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * objects in the queue (one with a new query event, and one with a end event, with 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 0 or more additional listeners in between). 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Context mQueryContext; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Uri mQueryUri; 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private CallerInfo mCallerInfo; 1062563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Our own query worker thread. 1092563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville * 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This thread handles the messages enqueued in the looper. The normal sequence 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of events is that a new query shows up in the looper queue, followed by 0 or 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * more add listener requests, and then an end request. Of course, these requests 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * can be interlaced with requests from other tokens, but is irrelevant to this 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * handler since the handler has no state. 1152563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville * 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note that we depend on the queue to keep things in order; in other words, the 1172563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville * looper queue must be FIFO with respect to input from the synchronous startQuery 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * calls and output to this handleMessage call. 1192563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville * 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This use of the queue is required because CallerInfo objects may be accessed 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * multiple times before the query is complete. All accesses (listeners) must be 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * queued up and informed in order when the query is complete. 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected class CallerInfoWorkerHandler extends WorkerHandler { 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CallerInfoWorkerHandler(Looper looper) { 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(looper); 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project WorkerArgs args = (WorkerArgs) msg.obj; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieWrapper cw = (CookieWrapper) args.cookie; 1332563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cw == null) { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Normally, this should never be the case for calls originating 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // from within this code. 1372563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville // However, if there is any code that this Handler calls (such as in 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // super.handleMessage) that DOES place unexpected messages on the 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // queue, then we need pass these messages on. 140431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato if (DBG) Log.d(LOG_TAG, "Unexpected command (CookieWrapper is null): " + msg.what + 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " ignored by CallerInfoWorkerHandler, passing onto parent."); 1422563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.handleMessage(msg); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1452563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 146431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato if (DBG) Log.d(LOG_TAG, "Processing event: " + cw.event + " token (arg1): " + msg.arg1 + 147a42880749b368e60caee77dd682d434e48ca96bdWink Saville " command: " + msg.what + " query URI: " + sanitizeUriToString(args.uri)); 1482563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (cw.event) { 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case EVENT_NEW_QUERY: 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //start the sql command. 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.handleMessage(msg); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // shortcuts to avoid query for recognized numbers. 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case EVENT_EMERGENCY_NUMBER: 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case EVENT_VOICEMAIL_NUMBER: 1582563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case EVENT_ADD_LISTENER: 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case EVENT_END_OF_QUEUE: 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // query was already completed, so just send the reply. 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // passing the original token value back to the caller 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // on top of the event values in arg1. 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Message reply = args.handler.obtainMessage(msg.what); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reply.obj = args; 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reply.arg1 = msg.arg1; 1672563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reply.sendToTarget(); 1692563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1762563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 1772563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Asynchronous query handler class for the contact / callerinfo object. 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private CallerInfoAsyncQueryHandler(Context context) { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context.getContentResolver()); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected Handler createHandler(Looper looper) { 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new CallerInfoWorkerHandler(looper); 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Overrides onQueryComplete from AsyncQueryHandler. 1922563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville * 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method takes into account the state of this class; we construct the CallerInfo 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * object only once for each set of listeners. When the query thread has done its work 1952563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville * and calls this method, we inform the remaining listeners in the queue, until we're 1962563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville * out of listeners. Once we get the message indicating that we should expect no new 1972563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville * listeners for this CallerInfo object, we release the AsyncCursorInfo back into the 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * pool. 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 202431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato if (DBG) Log.d(LOG_TAG, "##### onQueryComplete() ##### query complete for token: " + token); 2032563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //get the cookie and notify the listener. 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieWrapper cw = (CookieWrapper) cookie; 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cw == null) { 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Normally, this should never be the case for calls originating 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // from within this code. 2092563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville // However, if there is any code that calls this method, we should 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // check the parameters to make sure they're viable. 211431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato if (DBG) Log.d(LOG_TAG, "Cookie is null, ignoring onQueryComplete() request."); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2142563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cw.event == EVENT_END_OF_QUEUE) { 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project release(); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // check the token and if needed, create the callerinfo object. 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCallerInfo == null) { 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mQueryContext == null) || (mQueryUri == null)) { 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new QueryPoolException 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ("Bad context or query uri, or CallerInfoAsyncQuery already released."); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2262563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // adjust the callerInfo data as needed, and only if it was set from the 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // initial query request. 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Change the callerInfo number ONLY if it is an emergency number or the 2302563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville // voicemail number, and adjust other data (including photoResource) 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // accordingly. 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cw.event == EVENT_EMERGENCY_NUMBER) { 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Note we're setting the phone number here (refer to javadoc 2342563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville // comments at the top of CallerInfo class). 235e22415817febc8d3229d1774f3b0dfda0fda8f46Nicolas Catania mCallerInfo = new CallerInfo().markAsEmergency(mQueryContext); 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (cw.event == EVENT_VOICEMAIL_NUMBER) { 23760d45f0f0320801a16db2ad038453c098e98966cNicolas Catania mCallerInfo = new CallerInfo().markAsVoiceMail(); 2382563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville } else { 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCallerInfo = CallerInfo.getCallerInfo(mQueryContext, mQueryUri, cursor); 240431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato if (DBG) Log.d(LOG_TAG, "==> Got mCallerInfo: " + mCallerInfo); 241158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown 2426fe795ecd35c4d49822d349424fc71b660577dfcHung-ying Tyan CallerInfo newCallerInfo = CallerInfo.doSecondaryLookupIfNecessary( 2436fe795ecd35c4d49822d349424fc71b660577dfcHung-ying Tyan mQueryContext, cw.number, mCallerInfo); 2446fe795ecd35c4d49822d349424fc71b660577dfcHung-ying Tyan if (newCallerInfo != mCallerInfo) { 2456fe795ecd35c4d49822d349424fc71b660577dfcHung-ying Tyan mCallerInfo = newCallerInfo; 24623392a84bcb961d3fd50142ec40ce6ac6db89018Jeff Hamilton if (DBG) Log.d(LOG_TAG, "#####async contact look up with numeric username" 2476fe795ecd35c4d49822d349424fc71b660577dfcHung-ying Tyan + mCallerInfo); 2486fe795ecd35c4d49822d349424fc71b660577dfcHung-ying Tyan } 2496fe795ecd35c4d49822d349424fc71b660577dfcHung-ying Tyan 25094202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown // Final step: look up the geocoded description. 2512ef46c65877a7188868cec440fbe93086e011f5bDavid Brown if (ENABLE_UNKNOWN_NUMBER_GEO_DESCRIPTION) { 2522ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // Note we do this only if we *don't* have a valid name (i.e. if 2532ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // no contacts matched the phone number of the incoming call), 2542ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // since that's the only case where the incoming-call UI cares 2552ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // about this field. 2562ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // 2572ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // (TODO: But if we ever want the UI to show the geoDescription 2582ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // even when we *do* match a contact, we'll need to either call 2592ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // updateGeoDescription() unconditionally here, or possibly add a 2602ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // new parameter to CallerInfoAsyncQuery.startQuery() to force 2612ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // the geoDescription field to be populated.) 2622ef46c65877a7188868cec440fbe93086e011f5bDavid Brown 2632ef46c65877a7188868cec440fbe93086e011f5bDavid Brown if (TextUtils.isEmpty(mCallerInfo.name)) { 2642ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // Actually when no contacts match the incoming phone number, 2652ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // the CallerInfo object is totally blank here (i.e. no name 2662ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // *or* phoneNumber). So we need to pass in cw.number as 2672ef46c65877a7188868cec440fbe93086e011f5bDavid Brown // a fallback number. 2682ef46c65877a7188868cec440fbe93086e011f5bDavid Brown mCallerInfo.updateGeoDescription(mQueryContext, cw.number); 2692ef46c65877a7188868cec440fbe93086e011f5bDavid Brown } 27094202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown } 27194202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Use the number entered by the user for display. 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!TextUtils.isEmpty(cw.number)) { 2746a3d188f18b5ae278c802c8bbd1e0a44da555cdfBai Tao CountryDetector detector = (CountryDetector) mQueryContext.getSystemService( 2756a3d188f18b5ae278c802c8bbd1e0a44da555cdfBai Tao Context.COUNTRY_DETECTOR); 2766a3d188f18b5ae278c802c8bbd1e0a44da555cdfBai Tao mCallerInfo.phoneNumber = PhoneNumberUtils.formatNumber(cw.number, 27794202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown mCallerInfo.normalizedNumber, 2786a3d188f18b5ae278c802c8bbd1e0a44da555cdfBai Tao detector.detectCountry().getCountryIso()); 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2812563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 282431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato if (DBG) Log.d(LOG_TAG, "constructing CallerInfo object for token: " + token); 2832563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //notify that we can clean up the queue after this. 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieWrapper endMarker = new CookieWrapper(); 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project endMarker.event = EVENT_END_OF_QUEUE; 287158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown startQuery(token, endMarker, null, null, null, null, null); 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2892563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //notify the listener that the query is complete. 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cw.listener != null) { 292431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato if (DBG) Log.d(LOG_TAG, "notifying listener: " + cw.listener.getClass().toString() + 29360d45f0f0320801a16db2ad038453c098e98966cNicolas Catania " for token: " + token + mCallerInfo); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cw.listener.onQueryComplete(token, cw.cookie, mCallerInfo); 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2982563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Private constructor for factory methods. 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private CallerInfoAsyncQuery() { 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3052563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Factory method to start query with a Uri query spec 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3092563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville public static CallerInfoAsyncQuery startQuery(int token, Context context, Uri contactRef, 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OnQueryCompleteListener listener, Object cookie) { 3112563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CallerInfoAsyncQuery c = new CallerInfoAsyncQuery(); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.allocate(context, contactRef); 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 315431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato if (DBG) Log.d(LOG_TAG, "starting query for URI: " + contactRef + " handler: " + c.toString()); 3162563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //create cookieWrapper, start query 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieWrapper cw = new CookieWrapper(); 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cw.listener = listener; 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cw.cookie = cookie; 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cw.event = EVENT_NEW_QUERY; 3222563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 323158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown c.mHandler.startQuery(token, cw, contactRef, null, null, null, null); 3242563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return c; 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3272563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 329158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown * Factory method to start the query based on a number. 330158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown * 331158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown * Note: if the number contains an "@" character we treat it 332158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown * as a SIP address, and look it up directly in the Data table 333158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown * rather than using the PhoneLookup table. 334158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown * TODO: But eventually we should expose two separate methods, one for 335158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown * numbers and one for SIP addresses, and then have 336158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown * PhoneUtils.startGetCallerInfo() decide which one to call based on 337158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown * the phone type of the incoming connection. 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3392563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville public static CallerInfoAsyncQuery startQuery(int token, Context context, String number, 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OnQueryCompleteListener listener, Object cookie) { 341158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown if (DBG) { 342431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato Log.d(LOG_TAG, "##### CallerInfoAsyncQuery startQuery()... #####"); 343431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato Log.d(LOG_TAG, "- number: " + /*number*/ "xxxxxxx"); 344431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato Log.d(LOG_TAG, "- cookie: " + cookie); 345158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown } 346158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown 347158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // Construct the URI object and query params, and start the query. 348158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown 349158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown Uri contactRef; 350158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown String selection; 351158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown String[] selectionArgs; 352158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown 353158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown if (PhoneNumberUtils.isUriNumber(number)) { 354158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // "number" is really a SIP address. 355431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato if (DBG) Log.d(LOG_TAG, " - Treating number as a SIP address: " + /*number*/ "xxxxxxx"); 356158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown 357158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // We look up SIP addresses directly in the Data table: 358158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown contactRef = Data.CONTENT_URI; 359158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown 360158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // Note Data.DATA1 and SipAddress.SIP_ADDRESS are equivalent. 361158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // 362158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // Also note we use "upper(data1)" in the WHERE clause, and 363158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // uppercase the incoming SIP address, in order to do a 364158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // case-insensitive match. 365158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // 366158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // TODO: need to confirm that the use of upper() doesn't 367158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // prevent us from using the index! (Linear scan of the whole 368158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // contacts DB can be very slow.) 369158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // 370158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // TODO: May also need to normalize by adding "sip:" as a 371158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // prefix, if we start storing SIP addresses that way in the 372158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // database. 373158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown 374158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown selection = "upper(" + Data.DATA1 + ")=?" 375158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown + " AND " 376158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown + Data.MIMETYPE + "='" + SipAddress.CONTENT_ITEM_TYPE + "'"; 377158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown selectionArgs = new String[] { number.toUpperCase() }; 378158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown 379158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown } else { 380158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown // "number" is a regular phone number. Use the PhoneLookup table: 381158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown contactRef = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)); 382158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown selection = null; 383158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown selectionArgs = null; 384158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown } 385158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown 386158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown if (DBG) { 387431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato Log.d(LOG_TAG, "==> contactRef: " + sanitizeUriToString(contactRef)); 388431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato Log.d(LOG_TAG, "==> selection: " + selection); 389158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown if (selectionArgs != null) { 390158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown for (int i = 0; i < selectionArgs.length; i++) { 391431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato Log.d(LOG_TAG, "==> selectionArgs[" + i + "]: " + selectionArgs[i]); 392158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown } 393158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown } 394158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown } 3952563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CallerInfoAsyncQuery c = new CallerInfoAsyncQuery(); 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.allocate(context, contactRef); 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //create cookieWrapper, start query 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieWrapper cw = new CookieWrapper(); 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cw.listener = listener; 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cw.cookie = cookie; 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cw.number = number; 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4052563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville // check to see if these are recognized numbers, and use shortcuts if we can. 4066b7c3f8a1cd8b638defc28a3249746e99b8039aeShaopeng Jia if (PhoneNumberUtils.isLocalEmergencyNumber(number, context)) { 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cw.event = EVENT_EMERGENCY_NUMBER; 40860d45f0f0320801a16db2ad038453c098e98966cNicolas Catania } else if (PhoneNumberUtils.isVoiceMailNumber(number)) { 40960d45f0f0320801a16db2ad038453c098e98966cNicolas Catania cw.event = EVENT_VOICEMAIL_NUMBER; 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 41160d45f0f0320801a16db2ad038453c098e98966cNicolas Catania cw.event = EVENT_NEW_QUERY; 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 414158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown c.mHandler.startQuery(token, 415158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown cw, // cookie 416158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown contactRef, // uri 417158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown null, // projection 418158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown selection, // selection 419158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown selectionArgs, // selectionArgs 420158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown null); // orderBy 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return c; 422158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown } 4232563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Method to add listeners to a currently running query 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void addQueryListener(int token, OnQueryCompleteListener listener, Object cookie) { 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 429431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato if (DBG) Log.d(LOG_TAG, "adding listener to query: " + sanitizeUriToString(mHandler.mQueryUri) + 430a42880749b368e60caee77dd682d434e48ca96bdWink Saville " handler: " + mHandler.toString()); 4312563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //create cookieWrapper, add query request to end of queue. 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CookieWrapper cw = new CookieWrapper(); 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cw.listener = listener; 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cw.cookie = cookie; 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cw.event = EVENT_ADD_LISTENER; 4372563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 438158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown mHandler.startQuery(token, cw, null, null, null, null, null); 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Method to create a new CallerInfoAsyncQueryHandler object, ensuring correct 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * state of context and uri. 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 44594202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown private void allocate(Context context, Uri contactRef) { 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((context == null) || (contactRef == null)){ 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new QueryPoolException("Bad context or query uri."); 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler = new CallerInfoAsyncQueryHandler(context); 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.mQueryContext = context; 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.mQueryUri = contactRef; 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Releases the relevant data. 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 45794202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown private void release() { 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.mQueryContext = null; 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.mQueryUri = null; 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.mCallerInfo = null; 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler = null; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4632563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville 464a42880749b368e60caee77dd682d434e48ca96bdWink Saville private static String sanitizeUriToString(Uri uri) { 465a42880749b368e60caee77dd682d434e48ca96bdWink Saville if (uri != null) { 466a42880749b368e60caee77dd682d434e48ca96bdWink Saville String uriString = uri.toString(); 467a42880749b368e60caee77dd682d434e48ca96bdWink Saville int indexOfLastSlash = uriString.lastIndexOf('/'); 468a42880749b368e60caee77dd682d434e48ca96bdWink Saville if (indexOfLastSlash > 0) { 469a42880749b368e60caee77dd682d434e48ca96bdWink Saville return uriString.substring(0, indexOfLastSlash) + "/xxxxxxx"; 470a42880749b368e60caee77dd682d434e48ca96bdWink Saville } else { 471a42880749b368e60caee77dd682d434e48ca96bdWink Saville return uriString; 472a42880749b368e60caee77dd682d434e48ca96bdWink Saville } 473a42880749b368e60caee77dd682d434e48ca96bdWink Saville } else { 474a42880749b368e60caee77dd682d434e48ca96bdWink Saville return ""; 475a42880749b368e60caee77dd682d434e48ca96bdWink Saville } 476a42880749b368e60caee77dd682d434e48ca96bdWink Saville } 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 478