summaryrefslogtreecommitdiff
path: root/InCallUI
diff options
context:
space:
mode:
authorNancy Chen <nancychen@google.com>2015-11-11 18:19:35 -0800
committerNancy Chen <nancychen@google.com>2015-11-16 10:22:58 -0800
commit250bbb0e04747f162beb7490ce3f7ef05a0ce841 (patch)
tree03419ca5afb01c643916fb27e0b52c6f23296ef0 /InCallUI
parenta1bccb179974a821a989b459326b182cd07b772e (diff)
Fix NPE with contact cache, and guard against race condition.
Because the image loading and contact interactions information are loaded asynchronously at the same time, one of them may be loaded before the other. To ensure that the main thread is aware when whether one or both of them have completed, keep a flag in ContactCacheInfo. This will prevent the callbacks from being cleared before all callbacks are completed. Also guard against NPEs by making sure the cache entry is added to the map of callIds to cacheEntries and check for null before proceeding in the callback for contact interactions. Bug: 25618632 Change-Id: I7662242e040948a1e445f66c362f2eaea4cf03af
Diffstat (limited to 'InCallUI')
-rw-r--r--InCallUI/src/com/android/incallui/ContactInfoCache.java46
1 files changed, 36 insertions, 10 deletions
diff --git a/InCallUI/src/com/android/incallui/ContactInfoCache.java b/InCallUI/src/com/android/incallui/ContactInfoCache.java
index c5176b1a1..6bbe52f46 100644
--- a/InCallUI/src/com/android/incallui/ContactInfoCache.java
+++ b/InCallUI/src/com/android/incallui/ContactInfoCache.java
@@ -241,6 +241,7 @@ public class ContactInfoCache implements ContactsAsyncHelper.OnImageLoadComplete
Log.d(TAG, "Contact lookup. Local contact found, starting image load");
// Load the image with a callback to update the image state.
// When the load is finished, onImageLoadComplete() will be called.
+ cacheEntry.isLoadingPhoto = true;
ContactsAsyncHelper.startObtainPhotoAsync(TOKEN_UPDATE_PHOTO_FOR_CALL_STATE,
mContext, cacheEntry.displayPhotoUri, ContactInfoCache.this, callId);
} else {
@@ -302,19 +303,21 @@ public class ContactInfoCache implements ContactsAsyncHelper.OnImageLoadComplete
entry.photo = mContext.getResources().getDrawable(R.drawable.img_business);
}
- boolean hasContactInteractions = false;
+ mInfoMap.put(mCallId, entry);
+ sendInfoNotifications(mCallId, entry);
+
if (mContactUtils != null) {
// This method will callback "onContactInteractionsFound".
- hasContactInteractions = mContactUtils.retrieveContactInteractionsFromLookupKey(
- info.getLookupKey(), this);
+ entry.isLoadingContactInteractions =
+ mContactUtils.retrieveContactInteractionsFromLookupKey(
+ info.getLookupKey(), this);
}
- // Add the contact info to the cache.
- mInfoMap.put(mCallId, entry);
- sendInfoNotifications(mCallId, entry);
+ entry.isLoadingPhoto = info.getImageUrl() != null;
- // If there is no image then we should not expect another callback.
- if (info.getImageUrl() == null && !hasContactInteractions) {
+ // If there is no image or contact interactions then we should not expect another
+ // callback.
+ if (!entry.isLoadingPhoto && !entry.isLoadingContactInteractions) {
// We're done, so clear callbacks
clearCallbacks(mCallId);
}
@@ -329,10 +332,23 @@ public class ContactInfoCache implements ContactsAsyncHelper.OnImageLoadComplete
public void onContactInteractionsFound(Address address,
List<Pair<Calendar, Calendar>> openingHours) {
final ContactCacheEntry entry = mInfoMap.get(mCallId);
+ if (entry == null) {
+ Log.e(this, "Contact context received for empty search entry.");
+ clearCallbacks(mCallId);
+ return;
+ }
+
+ entry.isLoadingContactInteractions = false;
+
+ Log.v(ContactInfoCache.this, "Setting contact interactions for entry: ", entry);
+
entry.locationAddress = address;
entry.openingHours = openingHours;
sendContactInteractionsNotifications(mCallId, entry);
- clearCallbacks(mCallId);
+
+ if (!entry.isLoadingPhoto) {
+ clearCallbacks(mCallId);
+ }
}
}
@@ -354,6 +370,9 @@ public class ContactInfoCache implements ContactsAsyncHelper.OnImageLoadComplete
clearCallbacks(callId);
return;
}
+
+ entry.isLoadingPhoto = false;
+
Log.d(this, "setting photo for entry: ", entry);
// Conference call icons are being handled in CallCardPresenter.
@@ -369,7 +388,10 @@ public class ContactInfoCache implements ContactsAsyncHelper.OnImageLoadComplete
}
sendImageNotifications(callId, entry);
- clearCallbacks(callId);
+
+ if (!entry.isLoadingContactInteractions) {
+ clearCallbacks(callId);
+ }
}
/**
@@ -617,6 +639,10 @@ public class ContactInfoCache implements ContactsAsyncHelper.OnImageLoadComplete
public String label;
public Drawable photo;
public boolean isSipCall;
+ // Note in cache entry whether this is a pending async loading action to know whether to
+ // wait for its callback or not.
+ public boolean isLoadingPhoto;
+ public boolean isLoadingContactInteractions;
/** This will be used for the "view" notification. */
public Uri contactUri;
/** Either a display photo or a thumbnail URI. */