15b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu/* 25b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * Copyright (C) 2016 The Android Open Source Project 35b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * 45b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * Licensed under the Apache License, Version 2.0 (the "License"); 55b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * you may not use this file except in compliance with the License. 65b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * You may obtain a copy of the License at 75b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * 85b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * http://www.apache.org/licenses/LICENSE-2.0 95b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * 105b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * Unless required by applicable law or agreed to in writing, software 115b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * distributed under the License is distributed on an "AS IS" BASIS, 125b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * See the License for the specific language governing permissions and 145b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * limitations under the License 155b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu */ 165b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 175b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liupackage com.android.server.telecom; 185b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 19f2373e177b6e122b84dd1a22320629d0280de1c6Shigeru Muraiimport android.annotation.Nullable; 205b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport android.content.Context; 215b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport android.graphics.Bitmap; 225b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport android.graphics.drawable.Drawable; 235b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport android.net.Uri; 245b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport android.os.Handler; 255b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport android.os.Looper; 26a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebingerimport android.telecom.Log; 27a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebingerimport android.telecom.Logging.Runnable; 28a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebingerimport android.telecom.Logging.Session; 295b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport android.text.TextUtils; 305b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 315b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport com.android.internal.annotations.VisibleForTesting; 325b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport com.android.internal.telephony.CallerInfo; 335b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport com.android.internal.telephony.CallerInfoAsyncQuery; 345b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 355b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport java.io.InputStream; 365b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport java.util.HashMap; 375b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport java.util.LinkedList; 385b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport java.util.List; 395b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liuimport java.util.Map; 405b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 415b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liupublic class CallerInfoLookupHelper { 425b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu public interface OnQueryCompleteListener { 435b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu /** 445b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * Called when the query returns with the caller info 455b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * @param info 465b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu * @return true if the value should be cached, false otherwise. 475b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu */ 48f2373e177b6e122b84dd1a22320629d0280de1c6Shigeru Murai void onCallerInfoQueryComplete(Uri handle, @Nullable CallerInfo info); 495b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu void onContactPhotoQueryComplete(Uri handle, CallerInfo info); 505b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 515b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 525b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu private static class CallerInfoQueryInfo { 535b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu public CallerInfo callerInfo; 545b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu public List<OnQueryCompleteListener> listeners; 555b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu public boolean imageQueryPending = false; 565b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 575b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu public CallerInfoQueryInfo() { 585b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu listeners = new LinkedList<>(); 595b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 605b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 61f2373e177b6e122b84dd1a22320629d0280de1c6Shigeru Murai 625b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu private final Map<Uri, CallerInfoQueryInfo> mQueryEntries = new HashMap<>(); 635b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 645b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu private final CallerInfoAsyncQueryFactory mCallerInfoAsyncQueryFactory; 655b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu private final ContactsAsyncHelper mContactsAsyncHelper; 665b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu private final Context mContext; 67465982730ff480ff3037cbc22c9dcae005346971Hall Liu private final TelecomSystem.SyncRoot mLock; 685b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu private final Handler mHandler = new Handler(Looper.getMainLooper()); 695b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 705b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu public CallerInfoLookupHelper(Context context, 715b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory, 72465982730ff480ff3037cbc22c9dcae005346971Hall Liu ContactsAsyncHelper contactsAsyncHelper, 73465982730ff480ff3037cbc22c9dcae005346971Hall Liu TelecomSystem.SyncRoot lock) { 745b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu mCallerInfoAsyncQueryFactory = callerInfoAsyncQueryFactory; 755b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu mContactsAsyncHelper = contactsAsyncHelper; 765b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu mContext = context; 77465982730ff480ff3037cbc22c9dcae005346971Hall Liu mLock = lock; 785b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 795b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 805b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu public void startLookup(final Uri handle, OnQueryCompleteListener listener) { 815b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu if (handle == null) { 82f2373e177b6e122b84dd1a22320629d0280de1c6Shigeru Murai listener.onCallerInfoQueryComplete(handle, null); 835b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu return; 845b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 855b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 865b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu final String number = handle.getSchemeSpecificPart(); 875b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu if (TextUtils.isEmpty(number)) { 88f2373e177b6e122b84dd1a22320629d0280de1c6Shigeru Murai listener.onCallerInfoQueryComplete(handle, null); 895b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu return; 905b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 915b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 925b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu synchronized (mLock) { 935b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu if (mQueryEntries.containsKey(handle)) { 945b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu CallerInfoQueryInfo info = mQueryEntries.get(handle); 955b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu if (info.callerInfo != null) { 965b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Log.i(this, "Caller info already exists for handle %s; using cached value", 975b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Log.piiHandle(handle)); 985b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu listener.onCallerInfoQueryComplete(handle, info.callerInfo); 995b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu if (!info.imageQueryPending && (info.callerInfo.cachedPhoto != null || 1005b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu info.callerInfo.cachedPhotoIcon != null)) { 1015b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu listener.onContactPhotoQueryComplete(handle, info.callerInfo); 1025b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } else if (info.imageQueryPending) { 10336b4ee2a5ee416b359f167604900c35ffe100ba2Hall Liu Log.i(this, "There is a pending photo query for handle %s. " + 1045b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu "Adding to listeners for this query.", Log.piiHandle(handle)); 1055b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu info.listeners.add(listener); 1065b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1075b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } else { 1085b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Log.i(this, "There is a previously incomplete query for handle %s. Adding to " + 1095b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu "listeners for this query.", Log.piiHandle(handle)); 1105b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu info.listeners.add(listener); 1115b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu return; 1125b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1135b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } else { 1145b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu CallerInfoQueryInfo info = new CallerInfoQueryInfo(); 1155b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu info.listeners.add(listener); 1165b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu mQueryEntries.put(handle, info); 1175b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1185b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1195b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 120f5e066609d0acc7ff53752bd6b9e3f2634bd0746Brad Ebinger mHandler.post(new Runnable("CILH.sL", mLock) { 1215b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu @Override 1225b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu public void loggedRun() { 1235b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Session continuedSession = Log.createSubsession(); 1245b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu try { 1255b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu CallerInfoAsyncQuery query = mCallerInfoAsyncQueryFactory.startQuery( 1265b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 0, mContext, number, 1275b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu makeCallerInfoQueryListener(handle), continuedSession); 1285b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu if (query == null) { 1295b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Log.w(this, "Lookup failed for %s.", Log.piiHandle(handle)); 1305b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Log.cancelSubsession(continuedSession); 1315b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1325b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } catch (Throwable t) { 1335b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Log.cancelSubsession(continuedSession); 1345b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu throw t; 1355b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1365b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1375b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu }.prepare()); 1385b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1395b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 1405b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu private CallerInfoAsyncQuery.OnQueryCompleteListener makeCallerInfoQueryListener( 1415b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu final Uri handle) { 1425b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu return (token, cookie, ci) -> { 1435b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu synchronized (mLock) { 1445b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Log.continueSession((Session) cookie, "CILH.oQC"); 1455b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu try { 1465b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu if (mQueryEntries.containsKey(handle)) { 14736b4ee2a5ee416b359f167604900c35ffe100ba2Hall Liu Log.i(CallerInfoLookupHelper.this, "CI query for handle %s has completed;" + 14836b4ee2a5ee416b359f167604900c35ffe100ba2Hall Liu " notifying all listeners.", Log.piiHandle(handle)); 1495b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu CallerInfoQueryInfo info = mQueryEntries.get(handle); 1505b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu for (OnQueryCompleteListener l : info.listeners) { 1515b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu l.onCallerInfoQueryComplete(handle, ci); 1525b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1535b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu if (ci.contactDisplayPhotoUri == null) { 15436b4ee2a5ee416b359f167604900c35ffe100ba2Hall Liu Log.i(CallerInfoLookupHelper.this, "There is no photo for this " + 15536b4ee2a5ee416b359f167604900c35ffe100ba2Hall Liu "contact, skipping photo query"); 1565b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu mQueryEntries.remove(handle); 1575b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } else { 1585b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu info.callerInfo = ci; 1595b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu info.imageQueryPending = true; 1605b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu startPhotoLookup(handle, ci.contactDisplayPhotoUri); 1615b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1625b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } else { 1635b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Log.i(CallerInfoLookupHelper.this, "CI query for handle %s has completed," + 16413a96cec066e0275cc07c7f8cafc57585c735833Brad Ebinger " but there are no listeners left.", Log.piiHandle(handle)); 1655b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1665b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } finally { 1675b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Log.endSession(); 1685b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1695b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1705b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu }; 1715b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1725b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 1735b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu private void startPhotoLookup(final Uri handle, final Uri contactPhotoUri) { 174f5e066609d0acc7ff53752bd6b9e3f2634bd0746Brad Ebinger mHandler.post(new Runnable("CILH.sPL", mLock) { 1755b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu @Override 1765b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu public void loggedRun() { 1775b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Session continuedSession = Log.createSubsession(); 1785b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu try { 1795b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu mContactsAsyncHelper.startObtainPhotoAsync( 1805b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 0, mContext, contactPhotoUri, 1815b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu makeContactPhotoListener(handle), continuedSession); 1825b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } catch (Throwable t) { 1835b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Log.cancelSubsession(continuedSession); 1845b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu throw t; 1855b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1865b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1875b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu }.prepare()); 1885b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 1895b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 1905b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu private ContactsAsyncHelper.OnImageLoadCompleteListener makeContactPhotoListener( 1915b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu final Uri handle) { 1925b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu return (token, photo, photoIcon, cookie) -> { 1935b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu synchronized (mLock) { 1945b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Log.continueSession((Session) cookie, "CLIH.oILC"); 1955b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu try { 1965b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu if (mQueryEntries.containsKey(handle)) { 1975b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu CallerInfoQueryInfo info = mQueryEntries.get(handle); 1985b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu if (info.callerInfo == null) { 1995b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Log.w(CallerInfoLookupHelper.this, "Photo query finished, but the " + 2005b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu "CallerInfo object previously looked up was not cached."); 20136b4ee2a5ee416b359f167604900c35ffe100ba2Hall Liu mQueryEntries.remove(handle); 2025b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu return; 2035b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 2045b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu info.callerInfo.cachedPhoto = photo; 2055b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu info.callerInfo.cachedPhotoIcon = photoIcon; 2065b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu for (OnQueryCompleteListener l : info.listeners) { 2075b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu l.onContactPhotoQueryComplete(handle, info.callerInfo); 2085b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 2095b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu mQueryEntries.remove(handle); 2105b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } else { 2115b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Log.i(CallerInfoLookupHelper.this, "Photo query for handle %s has" + 21213a96cec066e0275cc07c7f8cafc57585c735833Brad Ebinger " completed, but there are no listeners left.", 21313a96cec066e0275cc07c7f8cafc57585c735833Brad Ebinger Log.piiHandle(handle)); 2145b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 2155b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } finally { 2165b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu Log.endSession(); 2175b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 2185b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 2195b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu }; 2205b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 2215b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 2225b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu @VisibleForTesting 2235b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu public Map<Uri, CallerInfoQueryInfo> getCallerInfoEntries() { 2245b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu return mQueryEntries; 2255b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 2265b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu 2275b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu @VisibleForTesting 2285b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu public Handler getHandler() { 2295b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu return mHandler; 2305b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu } 2315b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu} 232