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
195692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onukiimport android.app.ActivityManager;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.AsyncQueryHandler;
215692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onukiimport android.content.ContentResolver;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
235692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onukiimport android.content.pm.PackageManager.NameNotFoundException;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.SQLException;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
305692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onukiimport android.os.UserHandle;
315692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onukiimport android.os.UserManager;
323c513ed95cee2e0bcd7208cb7e46307f09c907c9Dmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.telephony.PhoneNumberUtils;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils;
35599a90c2a02645a5f2d189b9065b863397a4076eWink Savilleimport android.telephony.Rlog;
36fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Savilleimport android.telephony.SubscriptionManager;
375692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onukiimport android.util.Log;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
4094202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown * Helper class to make it easier to run asynchronous caller-id lookup queries.
4194202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown * @see CallerInfo
4294202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown *
4394202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown * {@hide}
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class CallerInfoAsyncQuery {
46431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato    private static final boolean DBG = false;
47e22415817febc8d3229d1774f3b0dfda0fda8f46Nicolas Catania    private static final String LOG_TAG = "CallerInfoAsyncQuery";
482563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EVENT_NEW_QUERY = 1;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EVENT_ADD_LISTENER = 2;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EVENT_END_OF_QUEUE = 3;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EVENT_EMERGENCY_NUMBER = 4;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EVENT_VOICEMAIL_NUMBER = 5;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private CallerInfoAsyncQueryHandler mHandler;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
572ef46c65877a7188868cec440fbe93086e011f5bDavid Brown    // If the CallerInfo query finds no contacts, should we use the
582ef46c65877a7188868cec440fbe93086e011f5bDavid Brown    // PhoneNumberOfflineGeocoder to look up a "geo description"?
592ef46c65877a7188868cec440fbe93086e011f5bDavid Brown    // (TODO: This could become a flag in config.xml if it ever needs to be
602ef46c65877a7188868cec440fbe93086e011f5bDavid Brown    // configured on a per-product basis.)
61cec25c4e8afdc56451f7405f8605c1d67433e2ffDavid Brown    private static final boolean ENABLE_UNKNOWN_NUMBER_GEO_DESCRIPTION = true;
622ef46c65877a7188868cec440fbe93086e011f5bDavid Brown
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Interface for a CallerInfoAsyncQueryHandler result return.
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnQueryCompleteListener {
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
682563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville         * Called when the query is complete.
692563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville         */
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onQueryComplete(int token, Object cookie, CallerInfo ci);
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
722563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
732563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Wrap the cookie from the WorkerArgs with additional information needed by our
762563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville     * classes.
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final class CookieWrapper {
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public OnQueryCompleteListener listener;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Object cookie;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int event;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String number;
83fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville
8463f03dd94c43c22f2c77306059b5748e5e1e0e3cWink Saville        public int subId;
852563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville    }
862563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
872563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Simple exception used to communicate problems with the query pool.
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static class QueryPoolException extends SQLException {
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public QueryPoolException(String error) {
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(error);
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
962563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
985692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki     * @return {@link ContentResolver} for the "current" user.
995692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki     */
1005692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki    static ContentResolver getCurrentProfileContentResolver(Context context) {
1015692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki
1025692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki        if (DBG) Rlog.d(LOG_TAG, "Trying to get current content resolver...");
1035692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki
1045692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki        final int currentUser = ActivityManager.getCurrentUser();
1055692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki        final int myUser = UserManager.get(context).getUserHandle();
1065692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki
1075692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki        if (DBG) Rlog.d(LOG_TAG, "myUser=" + myUser + "currentUser=" + currentUser);
1085692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki
1095692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki        if (myUser != currentUser) {
1105692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki            final Context otherContext;
1115692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki            try {
1125692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki                otherContext = context.createPackageContextAsUser(context.getPackageName(),
1135692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki                        /* flags =*/ 0, new UserHandle(currentUser));
1145692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki                return otherContext.getContentResolver();
1155692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki            } catch (NameNotFoundException e) {
1165692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki                Rlog.e(LOG_TAG, "Can't find self package", e);
1175692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki                // Fall back to the primary user.
1185692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki            }
1195692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki        }
1205692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki        return context.getContentResolver();
1215692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki    }
1225692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki
1235692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki    /**
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Our own implementation of the AsyncQueryHandler.
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class CallerInfoAsyncQueryHandler extends AsyncQueryHandler {
1272563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
1285692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki        /*
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * The information relevant to each CallerInfo query.  Each query may have multiple
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * listeners, so each AsyncCursorInfo is associated with 2 or more CookieWrapper
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * objects in the queue (one with a new query event, and one with a end event, with
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * 0 or more additional listeners in between).
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1345692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki
1355692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki        /**
1365692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki         * Context passed by the caller.
1375692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki         *
1385692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki         * NOTE: The actual context we use for query may *not* be this context; since we query
1395692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki         * against the "current" contacts provider.  In the constructor we pass the "current"
1405692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki         * context resolver (obtained via {@link #getCurrentProfileContentResolver) and pass it
1415692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki         * to the super class.
1425692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki         */
1435692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki        private Context mContext;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private Uri mQueryUri;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private CallerInfo mCallerInfo;
1462563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Our own query worker thread.
1492563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville         *
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This thread handles the messages enqueued in the looper.  The normal sequence
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * of events is that a new query shows up in the looper queue, followed by 0 or
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * more add listener requests, and then an end request.  Of course, these requests
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * can be interlaced with requests from other tokens, but is irrelevant to this
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * handler since the handler has no state.
1552563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville         *
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Note that we depend on the queue to keep things in order; in other words, the
1572563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville         * looper queue must be FIFO with respect to input from the synchronous startQuery
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * calls and output to this handleMessage call.
1592563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville         *
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This use of the queue is required because CallerInfo objects may be accessed
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * multiple times before the query is complete.  All accesses (listeners) must be
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * queued up and informed in order when the query is complete.
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected class CallerInfoWorkerHandler extends WorkerHandler {
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public CallerInfoWorkerHandler(Looper looper) {
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                super(looper);
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            @Override
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public void handleMessage(Message msg) {
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WorkerArgs args = (WorkerArgs) msg.obj;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                CookieWrapper cw = (CookieWrapper) args.cookie;
1732563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (cw == null) {
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Normally, this should never be the case for calls originating
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // from within this code.
1772563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville                    // However, if there is any code that this Handler calls (such as in
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // super.handleMessage) that DOES place unexpected messages on the
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // queue, then we need pass these messages on.
180599a90c2a02645a5f2d189b9065b863397a4076eWink Saville                    if (DBG) Rlog.d(LOG_TAG, "Unexpected command (CookieWrapper is null): " + msg.what +
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            " ignored by CallerInfoWorkerHandler, passing onto parent.");
1822563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    super.handleMessage(msg);
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
1852563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
186599a90c2a02645a5f2d189b9065b863397a4076eWink Saville                    if (DBG) Rlog.d(LOG_TAG, "Processing event: " + cw.event + " token (arg1): " + msg.arg1 +
187a42880749b368e60caee77dd682d434e48ca96bdWink Saville                        " command: " + msg.what + " query URI: " + sanitizeUriToString(args.uri));
1882563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    switch (cw.event) {
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case EVENT_NEW_QUERY:
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            //start the sql command.
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            super.handleMessage(msg);
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            break;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // shortcuts to avoid query for recognized numbers.
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case EVENT_EMERGENCY_NUMBER:
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case EVENT_VOICEMAIL_NUMBER:
1982563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case EVENT_ADD_LISTENER:
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        case EVENT_END_OF_QUEUE:
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // query was already completed, so just send the reply.
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // passing the original token value back to the caller
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // on top of the event values in arg1.
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            Message reply = args.handler.obtainMessage(msg.what);
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            reply.obj = args;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            reply.arg1 = msg.arg1;
2072563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            reply.sendToTarget();
2092563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            break;
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        default:
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2162563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
2172563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Asynchronous query handler class for the contact / callerinfo object.
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private CallerInfoAsyncQueryHandler(Context context) {
2225692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki            super(getCurrentProfileContentResolver(context));
2235692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki            mContext = context;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected Handler createHandler(Looper looper) {
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new CallerInfoWorkerHandler(looper);
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Overrides onQueryComplete from AsyncQueryHandler.
2332563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville         *
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This method takes into account the state of this class; we construct the CallerInfo
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * object only once for each set of listeners. When the query thread has done its work
2362563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville         * and calls this method, we inform the remaining listeners in the queue, until we're
2372563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville         * out of listeners.  Once we get the message indicating that we should expect no new
2382563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville         * listeners for this CallerInfo object, we release the AsyncCursorInfo back into the
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * pool.
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
243599a90c2a02645a5f2d189b9065b863397a4076eWink Saville            if (DBG) Rlog.d(LOG_TAG, "##### onQueryComplete() #####   query complete for token: " + token);
2442563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //get the cookie and notify the listener.
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            CookieWrapper cw = (CookieWrapper) cookie;
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cw == null) {
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Normally, this should never be the case for calls originating
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // from within this code.
2502563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville                // However, if there is any code that calls this method, we should
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // check the parameters to make sure they're viable.
252599a90c2a02645a5f2d189b9065b863397a4076eWink Saville                if (DBG) Rlog.d(LOG_TAG, "Cookie is null, ignoring onQueryComplete() request.");
253fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville                if (cursor != null) {
254fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville                    cursor.close();
255fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville                }
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2582563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cw.event == EVENT_END_OF_QUEUE) {
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                release();
261fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville                if (cursor != null) {
262fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville                    cursor.close();
263fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville                }
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // check the token and if needed, create the callerinfo object.
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCallerInfo == null) {
2695692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki                if ((mContext == null) || (mQueryUri == null)) {
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new QueryPoolException
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            ("Bad context or query uri, or CallerInfoAsyncQuery already released.");
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2732563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // adjust the callerInfo data as needed, and only if it was set from the
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // initial query request.
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Change the callerInfo number ONLY if it is an emergency number or the
2772563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville                // voicemail number, and adjust other data (including photoResource)
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // accordingly.
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (cw.event == EVENT_EMERGENCY_NUMBER) {
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Note we're setting the phone number here (refer to javadoc
2812563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville                    // comments at the top of CallerInfo class).
2825692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki                    mCallerInfo = new CallerInfo().markAsEmergency(mContext);
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (cw.event == EVENT_VOICEMAIL_NUMBER) {
284fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville                    mCallerInfo = new CallerInfo().markAsVoiceMail(cw.subId);
2852563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville                } else {
2865692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki                    mCallerInfo = CallerInfo.getCallerInfo(mContext, mQueryUri, cursor);
287599a90c2a02645a5f2d189b9065b863397a4076eWink Saville                    if (DBG) Rlog.d(LOG_TAG, "==> Got mCallerInfo: " + mCallerInfo);
288158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown
2896fe795ecd35c4d49822d349424fc71b660577dfcHung-ying Tyan                    CallerInfo newCallerInfo = CallerInfo.doSecondaryLookupIfNecessary(
2905692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki                            mContext, cw.number, mCallerInfo);
2916fe795ecd35c4d49822d349424fc71b660577dfcHung-ying Tyan                    if (newCallerInfo != mCallerInfo) {
2926fe795ecd35c4d49822d349424fc71b660577dfcHung-ying Tyan                        mCallerInfo = newCallerInfo;
293599a90c2a02645a5f2d189b9065b863397a4076eWink Saville                        if (DBG) Rlog.d(LOG_TAG, "#####async contact look up with numeric username"
2946fe795ecd35c4d49822d349424fc71b660577dfcHung-ying Tyan                                + mCallerInfo);
2956fe795ecd35c4d49822d349424fc71b660577dfcHung-ying Tyan                    }
2966fe795ecd35c4d49822d349424fc71b660577dfcHung-ying Tyan
29794202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown                    // Final step: look up the geocoded description.
2982ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                    if (ENABLE_UNKNOWN_NUMBER_GEO_DESCRIPTION) {
2992ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                        // Note we do this only if we *don't* have a valid name (i.e. if
3002ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                        // no contacts matched the phone number of the incoming call),
3012ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                        // since that's the only case where the incoming-call UI cares
3022ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                        // about this field.
3032ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                        //
3042ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                        // (TODO: But if we ever want the UI to show the geoDescription
3052ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                        // even when we *do* match a contact, we'll need to either call
3062ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                        // updateGeoDescription() unconditionally here, or possibly add a
3072ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                        // new parameter to CallerInfoAsyncQuery.startQuery() to force
3082ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                        // the geoDescription field to be populated.)
3092ef46c65877a7188868cec440fbe93086e011f5bDavid Brown
3102ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                        if (TextUtils.isEmpty(mCallerInfo.name)) {
3112ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                            // Actually when no contacts match the incoming phone number,
3122ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                            // the CallerInfo object is totally blank here (i.e. no name
3132ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                            // *or* phoneNumber).  So we need to pass in cw.number as
3142ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                            // a fallback number.
3155692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki                            mCallerInfo.updateGeoDescription(mContext, cw.number);
3162ef46c65877a7188868cec440fbe93086e011f5bDavid Brown                        }
31794202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown                    }
31894202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Use the number entered by the user for display.
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!TextUtils.isEmpty(cw.number)) {
3216a3d188f18b5ae278c802c8bbd1e0a44da555cdfBai Tao                        mCallerInfo.phoneNumber = PhoneNumberUtils.formatNumber(cw.number,
32294202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown                                mCallerInfo.normalizedNumber,
3235692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki                                CallerInfo.getCurrentCountryIso(mContext));
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3262563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
327599a90c2a02645a5f2d189b9065b863397a4076eWink Saville                if (DBG) Rlog.d(LOG_TAG, "constructing CallerInfo object for token: " + token);
3282563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //notify that we can clean up the queue after this.
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                CookieWrapper endMarker = new CookieWrapper();
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                endMarker.event = EVENT_END_OF_QUEUE;
332158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown                startQuery(token, endMarker, null, null, null, null, null);
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3342563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //notify the listener that the query is complete.
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cw.listener != null) {
337599a90c2a02645a5f2d189b9065b863397a4076eWink Saville                if (DBG) Rlog.d(LOG_TAG, "notifying listener: " + cw.listener.getClass().toString() +
33860d45f0f0320801a16db2ad038453c098e98966cNicolas Catania                             " for token: " + token + mCallerInfo);
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cw.listener.onQueryComplete(token, cw.cookie, mCallerInfo);
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
341fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville
342fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville            if (cursor != null) {
343fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville               cursor.close();
344fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville            }
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3472563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Private constructor for factory methods.
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private CallerInfoAsyncQuery() {
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3542563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Factory method to start query with a Uri query spec
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3582563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville    public static CallerInfoAsyncQuery startQuery(int token, Context context, Uri contactRef,
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            OnQueryCompleteListener listener, Object cookie) {
3602563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CallerInfoAsyncQuery c = new CallerInfoAsyncQuery();
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        c.allocate(context, contactRef);
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
364599a90c2a02645a5f2d189b9065b863397a4076eWink Saville        if (DBG) Rlog.d(LOG_TAG, "starting query for URI: " + contactRef + " handler: " + c.toString());
3652563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //create cookieWrapper, start query
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CookieWrapper cw = new CookieWrapper();
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cw.listener = listener;
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cw.cookie = cookie;
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cw.event = EVENT_NEW_QUERY;
3712563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
372158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown        c.mHandler.startQuery(token, cw, contactRef, null, null, null, null);
3732563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return c;
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3762563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
378158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown     * Factory method to start the query based on a number.
379158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown     *
380158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown     * Note: if the number contains an "@" character we treat it
381158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown     * as a SIP address, and look it up directly in the Data table
382158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown     * rather than using the PhoneLookup table.
383158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown     * TODO: But eventually we should expose two separate methods, one for
384158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown     * numbers and one for SIP addresses, and then have
385158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown     * PhoneUtils.startGetCallerInfo() decide which one to call based on
386158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown     * the phone type of the incoming connection.
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3882563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville    public static CallerInfoAsyncQuery startQuery(int token, Context context, String number,
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            OnQueryCompleteListener listener, Object cookie) {
390fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville
39163f03dd94c43c22f2c77306059b5748e5e1e0e3cWink Saville        int subId = SubscriptionManager.getDefaultSubId();
392fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville        return startQuery(token, context, number, listener, cookie, subId);
393fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville    }
394fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville
395fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville    /**
396fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville     * Factory method to start the query based on a number with specific subscription.
397fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville     *
398fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville     * Note: if the number contains an "@" character we treat it
399fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville     * as a SIP address, and look it up directly in the Data table
400fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville     * rather than using the PhoneLookup table.
401fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville     * TODO: But eventually we should expose two separate methods, one for
402fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville     * numbers and one for SIP addresses, and then have
403fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville     * PhoneUtils.startGetCallerInfo() decide which one to call based on
404fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville     * the phone type of the incoming connection.
405fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville     */
406fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville    public static CallerInfoAsyncQuery startQuery(int token, Context context, String number,
40763f03dd94c43c22f2c77306059b5748e5e1e0e3cWink Saville            OnQueryCompleteListener listener, Object cookie, int subId) {
408fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville
409158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown        if (DBG) {
410599a90c2a02645a5f2d189b9065b863397a4076eWink Saville            Rlog.d(LOG_TAG, "##### CallerInfoAsyncQuery startQuery()... #####");
411599a90c2a02645a5f2d189b9065b863397a4076eWink Saville            Rlog.d(LOG_TAG, "- number: " + /*number*/ "xxxxxxx");
412599a90c2a02645a5f2d189b9065b863397a4076eWink Saville            Rlog.d(LOG_TAG, "- cookie: " + cookie);
413158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown        }
414158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown
415158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown        // Construct the URI object and query params, and start the query.
416158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown
417a2295e65dc0735beee32180ab51b9c0b198287e1Makoto Onuki        final Uri contactRef = PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
418a2295e65dc0735beee32180ab51b9c0b198287e1Makoto Onuki                .appendPath(number)
419a2295e65dc0735beee32180ab51b9c0b198287e1Makoto Onuki                .appendQueryParameter(PhoneLookup.QUERY_PARAMETER_SIP_ADDRESS,
420a2295e65dc0735beee32180ab51b9c0b198287e1Makoto Onuki                        String.valueOf(PhoneNumberUtils.isUriNumber(number)))
421a2295e65dc0735beee32180ab51b9c0b198287e1Makoto Onuki                .build();
422158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown
423158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown        if (DBG) {
424599a90c2a02645a5f2d189b9065b863397a4076eWink Saville            Rlog.d(LOG_TAG, "==> contactRef: " + sanitizeUriToString(contactRef));
425158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown        }
4262563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CallerInfoAsyncQuery c = new CallerInfoAsyncQuery();
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        c.allocate(context, contactRef);
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //create cookieWrapper, start query
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CookieWrapper cw = new CookieWrapper();
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cw.listener = listener;
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cw.cookie = cookie;
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cw.number = number;
435fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville        cw.subId = subId;
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4372563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville        // check to see if these are recognized numbers, and use shortcuts if we can.
438282129fd3f789739c47fe5506bcf29c1a2712b3eYorke Lee        if (PhoneNumberUtils.isLocalEmergencyNumber(context, number)) {
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cw.event = EVENT_EMERGENCY_NUMBER;
440fb40dd4d00bd3361b2535bc866e6c21eadc52558Wink Saville        } else if (PhoneNumberUtils.isVoiceMailNumber(subId, number)) {
44160d45f0f0320801a16db2ad038453c098e98966cNicolas Catania            cw.event = EVENT_VOICEMAIL_NUMBER;
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
44360d45f0f0320801a16db2ad038453c098e98966cNicolas Catania            cw.event = EVENT_NEW_QUERY;
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
446158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown        c.mHandler.startQuery(token,
447158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown                              cw,  // cookie
448158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown                              contactRef,  // uri
449158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown                              null,  // projection
450a2295e65dc0735beee32180ab51b9c0b198287e1Makoto Onuki                              null,  // selection
451a2295e65dc0735beee32180ab51b9c0b198287e1Makoto Onuki                              null,  // selectionArgs
452158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown                              null);  // orderBy
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return c;
454158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown    }
4552563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Method to add listeners to a currently running query
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addQueryListener(int token, OnQueryCompleteListener listener, Object cookie) {
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
461599a90c2a02645a5f2d189b9065b863397a4076eWink Saville        if (DBG) Rlog.d(LOG_TAG, "adding listener to query: " + sanitizeUriToString(mHandler.mQueryUri) +
462a42880749b368e60caee77dd682d434e48ca96bdWink Saville                " handler: " + mHandler.toString());
4632563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //create cookieWrapper, add query request to end of queue.
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CookieWrapper cw = new CookieWrapper();
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cw.listener = listener;
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cw.cookie = cookie;
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cw.event = EVENT_ADD_LISTENER;
4692563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
470158d390f533f927175c5a5a3e5a1a8bc07ca1facDavid Brown        mHandler.startQuery(token, cw, null, null, null, null, null);
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Method to create a new CallerInfoAsyncQueryHandler object, ensuring correct
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * state of context and uri.
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
47794202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown    private void allocate(Context context, Uri contactRef) {
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((context == null) || (contactRef == null)){
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new QueryPoolException("Bad context or query uri.");
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler = new CallerInfoAsyncQueryHandler(context);
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler.mQueryUri = contactRef;
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Releases the relevant data.
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
48894202fe1217b9f63e1f5c314379a9f0021e96ea8David Brown    private void release() {
4895692dcced506cebf2bdb214fb27159cef9f7de2cMakoto Onuki        mHandler.mContext = null;
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler.mQueryUri = null;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler.mCallerInfo = null;
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler = null;
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4942563a3ac05dd3cf8a07203ae682c243f2e793137Wink Saville
495a42880749b368e60caee77dd682d434e48ca96bdWink Saville    private static String sanitizeUriToString(Uri uri) {
496a42880749b368e60caee77dd682d434e48ca96bdWink Saville        if (uri != null) {
497a42880749b368e60caee77dd682d434e48ca96bdWink Saville            String uriString = uri.toString();
498a42880749b368e60caee77dd682d434e48ca96bdWink Saville            int indexOfLastSlash = uriString.lastIndexOf('/');
499a42880749b368e60caee77dd682d434e48ca96bdWink Saville            if (indexOfLastSlash > 0) {
500a42880749b368e60caee77dd682d434e48ca96bdWink Saville                return uriString.substring(0, indexOfLastSlash) + "/xxxxxxx";
501a42880749b368e60caee77dd682d434e48ca96bdWink Saville            } else {
502a42880749b368e60caee77dd682d434e48ca96bdWink Saville                return uriString;
503a42880749b368e60caee77dd682d434e48ca96bdWink Saville            }
504a42880749b368e60caee77dd682d434e48ca96bdWink Saville        } else {
505a42880749b368e60caee77dd682d434e48ca96bdWink Saville            return "";
506a42880749b368e60caee77dd682d434e48ca96bdWink Saville        }
507a42880749b368e60caee77dd682d434e48ca96bdWink Saville    }
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
509