From f23375743411d20f76ee5b2a772838f3f230644a Mon Sep 17 00:00:00 2001 From: Rohit Yengisetty Date: Mon, 13 Apr 2015 18:19:21 -0700 Subject: ContactsCommon : Modify ContactPhotoManager to fetch contacts' bitmaps Change-Id: If7279a5a77c9d036c5ffdf0633c7577df30973b4 (cherry picked from commit ad0dff5a4331a1625c51c8b9cbcdbfbe5364dae2) --- .../contacts/common/ContactPhotoManager.java | 121 +++++++++++++++++++-- 1 file changed, 114 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/com/android/contacts/common/ContactPhotoManager.java b/src/com/android/contacts/common/ContactPhotoManager.java index f700fd8a..c7bee4a9 100644 --- a/src/com/android/contacts/common/ContactPhotoManager.java +++ b/src/com/android/contacts/common/ContactPhotoManager.java @@ -531,6 +531,18 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 { defaultImageRequest, defaultProvider); } + /** + * Used to request bitmap of a Contact photo + * + * @param photoUri Uri of the contact's photo + * @param imgView Sentinel used to triage this request through the existing contact bitmap + * loading pipeline. The contact Bitmap won't be loaded into this imageview. + * @param widthHint suggest bitmap dimensions + * @param cb Callback via which a contact's bitmap is made available to the requester + */ + public abstract void getBitmapForContact(Uri photoUri, ImageView imgView, int widthHint, + PhotoFetcherCallback cb); + /** * Calls {@link #loadPhoto(ImageView, Uri, boolean, boolean, DefaultImageRequest, * DefaultImageProvider)} with {@link #DEFAULT_AVATAR} and with the assumption, that @@ -608,6 +620,13 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 { @Override public void onTrimMemory(int level) { } + + /** + * callbacks associated with contact image requests + */ + public interface PhotoFetcherCallback { + public void onFetchComplete(Bitmap bitmap); + } } class ContactPhotoManagerImpl extends ContactPhotoManager implements Callback { @@ -885,6 +904,65 @@ class ContactPhotoManagerImpl extends ContactPhotoManager implements Callback { } } + /** + * Checks the cache to satisfy the bitmap request. If not found, requests the loader for + * the contact's image. + */ + @Override + public void getBitmapForContact(Uri photoUri, ImageView imgView, int widthHint, + PhotoFetcherCallback cb) { + // ensure request is for a valid contact uri before checking for bitmap + // or posting a load request + if (photoUri == null || isDefaultImageUri(photoUri)) return; + + // formulate the contact bitmap request + Request request = Request.createBitmapOnly(photoUri, widthHint, cb); + // check bitmap cache + boolean done = decodeContactBitmapFromCache(request); + + // if not in cache, put request in loading queue + if (!done) { + Request loadRequest = Request.createBitmapOnly(photoUri, widthHint, cb); + mPendingRequests.put(imgView, loadRequest); + if (!mPaused) { + requestLoading(); + } + } + } + + /** + * Checks the cache for the contact bitmap's bytes, decodes those bytes, and sends the + * decoded bitmap to the requester + * + * @return true if the bitmap is present and the cache and has been sent to the requester + */ + private boolean decodeContactBitmapFromCache(Request request) { + Uri photoUri = request.getUri(); + PhotoFetcherCallback cb = request.getCallback(); + + // check cache for the bitmap bytes + BitmapHolder holder = mBitmapHolderCache.get(request.getKey()); + if (holder != null && holder.bytes != null && holder.bytes.length != 0) { + // inflate bitmap from cache bytes + int sampleSize = + BitmapUtil.findOptimalSampleSize(holder.originalSmallerExtent, + request.getRequestedExtent()); + if (holder.decodedSampleSize == sampleSize && holder.bitmapRef != null && + holder.bitmapRef.get() != null) { + // already has a decoded bitmap at the requested size + cb.onFetchComplete(holder.bitmapRef.get()); + } else { + Bitmap bitmap = BitmapUtil.decodeBitmapFromBytes(holder.bytes, sampleSize); + // the decoded bitmap won't be stored in the BitmapHolder cache + cb.onFetchComplete(bitmap); + } + return true; + } + + // cache doesn't contain the requested bitmap + return false; + } + @Override public void removePhoto(ImageView view) { view.setImageDrawable(null); @@ -1159,10 +1237,15 @@ class ContactPhotoManagerImpl extends ContactPhotoManager implements Callback { Iterator iterator = mPendingRequests.keySet().iterator(); while (iterator.hasNext()) { ImageView view = iterator.next(); - Request key = mPendingRequests.get(view); - // TODO: Temporarily disable contact photo fading in, until issues with - // RoundedBitmapDrawables overlapping the default image drawables are resolved. - boolean loaded = loadCachedPhoto(view, key, false); + Request request = mPendingRequests.get(view); + boolean loaded = false; + if (request.isBitmapOnly()) { + decodeContactBitmapFromCache(request); + } else { + // TODO: Temporarily disable contact photo fading in, until issues with + // RoundedBitmapDrawables overlapping the default image drawables are resolved. + loaded = loadCachedPhoto(view, request, false); + } if (loaded) { iterator.remove(); } @@ -1601,11 +1684,14 @@ class ContactPhotoManagerImpl extends ContactPhotoManager implements Callback { private final boolean mDarkTheme; private final int mRequestedExtent; private final DefaultImageProvider mDefaultProvider; - /** - * Whether or not the contact photo is to be displayed as a circle - */ + // Whether or not the contact photo is to be displayed as a circle private final boolean mIsCircular; + // params for bitmap requests + private boolean mIsBitmapOnly; + private PhotoFetcherCallback mCallback; + + private Request(long id, Uri uri, int requestedExtent, boolean darkTheme, boolean isCircular, DefaultImageProvider defaultProvider) { mId = id; @@ -1627,6 +1713,23 @@ class ContactPhotoManagerImpl extends ContactPhotoManager implements Callback { defaultProvider); } + public static Request createBitmapOnly(Uri uri, int requestedExtent, + PhotoFetcherCallback cb) { + Request request = new Request(0, uri, requestedExtent, false, false, null); + request.setBitmapOnly(); + request.mCallback = cb; + + return request; + } + + public boolean isBitmapOnly() { + return mIsBitmapOnly; + } + + public PhotoFetcherCallback getCallback() { + return mCallback; + } + public boolean isUriRequest() { return mUri != null; } @@ -1643,6 +1746,10 @@ class ContactPhotoManagerImpl extends ContactPhotoManager implements Callback { return mRequestedExtent; } + public void setBitmapOnly() { + mIsBitmapOnly = true; + } + @Override public int hashCode() { final int prime = 31; -- cgit v1.2.3