199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon/* 299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Copyright (C) 2014 The Android Open Source Project 399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * 499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Licensed under the Apache License, Version 2.0 (the "License"); 599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * you may not use this file except in compliance with the License. 699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * You may obtain a copy of the License at 799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * 899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * http://www.apache.org/licenses/LICENSE-2.0 999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * 1099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Unless required by applicable law or agreed to in writing, software 1199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * distributed under the License is distributed on an "AS IS" BASIS, 1299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * See the License for the specific language governing permissions and 1499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * limitations under the License. 1599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon */ 1699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 177cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnpackage com.android.server.telecom; 1899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 1999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.app.Notification; 2099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.content.Context; 2199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.graphics.Bitmap; 2299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.graphics.drawable.BitmapDrawable; 2399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.graphics.drawable.Drawable; 2499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.net.Uri; 2599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.os.Handler; 2699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.os.HandlerThread; 2799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.os.Looper; 2899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.os.Message; 2999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 3091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn// TODO: Needed for move to system service: import com.android.internal.R; 3191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn 329ccc43d63648800e92396c430228772f8d0738cdHall Liuimport java.io.FileNotFoundException; 3399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport java.io.IOException; 3499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport java.io.InputStream; 3599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 3699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon/** 3799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Helper class for loading contacts photo asynchronously. 3899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon */ 395b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liupublic class ContactsAsyncHelper { 4099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon private static final String LOG_TAG = ContactsAsyncHelper.class.getSimpleName(); 4199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 4299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon /** 4399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Interface for a WorkerHandler result return. 4499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon */ 4599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon public interface OnImageLoadCompleteListener { 4699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon /** 4799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Called when the image load is complete. 4899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * 4999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * @param token Integer passed in {@link ContactsAsyncHelper#startObtainPhotoAsync(int, 5099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Context, Uri, OnImageLoadCompleteListener, Object)}. 5199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * @param photo Drawable object obtained by the async load. 5299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * @param photoIcon Bitmap object obtained by the async load. 5399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * @param cookie Object passed in {@link ContactsAsyncHelper#startObtainPhotoAsync(int, 5499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Context, Uri, OnImageLoadCompleteListener, Object)}. Can be null iff. the original 5599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * cookie is null. 5699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon */ 5799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon public void onImageLoadComplete(int token, Drawable photo, Bitmap photoIcon, 5899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon Object cookie); 5999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 6099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 619ccc43d63648800e92396c430228772f8d0738cdHall Liu /** 629ccc43d63648800e92396c430228772f8d0738cdHall Liu * Interface to enable stubbing of the call to openInputStream 639ccc43d63648800e92396c430228772f8d0738cdHall Liu */ 649ccc43d63648800e92396c430228772f8d0738cdHall Liu public interface ContentResolverAdapter { 659ccc43d63648800e92396c430228772f8d0738cdHall Liu InputStream openInputStream(Context context, Uri uri) throws FileNotFoundException; 669ccc43d63648800e92396c430228772f8d0738cdHall Liu } 679ccc43d63648800e92396c430228772f8d0738cdHall Liu 6899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // constants 6999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon private static final int EVENT_LOAD_IMAGE = 1; 7099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 7199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon /** Handler run on a worker thread to load photo asynchronously. */ 728d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad private Handler mThreadHandler; 739ccc43d63648800e92396c430228772f8d0738cdHall Liu private final ContentResolverAdapter mContentResolverAdapter; 7499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 759ccc43d63648800e92396c430228772f8d0738cdHall Liu public ContactsAsyncHelper(ContentResolverAdapter contentResolverAdapter) { 769ccc43d63648800e92396c430228772f8d0738cdHall Liu mContentResolverAdapter = contentResolverAdapter; 7799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 7899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 7999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon private static final class WorkerArgs { 8099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon public Context context; 81a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki public Uri displayPhotoUri; 8299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon public Drawable photo; 8399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon public Bitmap photoIcon; 8499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon public Object cookie; 8599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon public OnImageLoadCompleteListener listener; 8699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 8799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 8899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon /** 8999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Thread worker class that handles the task of opening the stream and loading 9099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * the images. 9199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon */ 928d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad private class WorkerHandler extends Handler { 9399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon public WorkerHandler(Looper looper) { 9499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon super(looper); 9599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 9699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 9799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon @Override 9899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon public void handleMessage(Message msg) { 9999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon WorkerArgs args = (WorkerArgs) msg.obj; 10099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 10199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon switch (msg.arg1) { 10299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon case EVENT_LOAD_IMAGE: 10399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon InputStream inputStream = null; 10499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon try { 10599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon try { 1069ccc43d63648800e92396c430228772f8d0738cdHall Liu inputStream = mContentResolverAdapter.openInputStream( 1079ccc43d63648800e92396c430228772f8d0738cdHall Liu args.context, args.displayPhotoUri); 10899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } catch (Exception e) { 10999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon Log.e(this, e, "Error opening photo input stream"); 11099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 11199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 11299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon if (inputStream != null) { 11399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon args.photo = Drawable.createFromStream(inputStream, 114a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki args.displayPhotoUri.toString()); 11599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 11699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // This assumes Drawable coming from contact database is usually 11799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // BitmapDrawable and thus we can have (down)scaled version of it. 11899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon args.photoIcon = getPhotoIconWhenAppropriate(args.context, args.photo); 11999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 12099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon Log.d(this, "Loading image: " + msg.arg1 + 121a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki " token: " + msg.what + " image URI: " + args.displayPhotoUri); 12299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } else { 12399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon args.photo = null; 12499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon args.photoIcon = null; 12599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon Log.d(this, "Problem with image: " + msg.arg1 + 126a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki " token: " + msg.what + " image URI: " + args.displayPhotoUri + 12799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon ", using default image."); 12899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 12999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } finally { 13099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon if (inputStream != null) { 13199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon try { 13299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon inputStream.close(); 13399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } catch (IOException e) { 13499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon Log.e(this, e, "Unable to close input stream."); 13599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 13699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 13799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 138abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad 139abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad // Listener will synchronize as needed 140abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad Log.d(this, "Notifying listener: " + args.listener.toString() + 141abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad " image: " + args.displayPhotoUri + " completed"); 142abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad args.listener.onImageLoadComplete(msg.what, args.photo, args.photoIcon, 1438d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad args.cookie); 14499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon break; 14599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon default: 1468d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad break; 14799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 14899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 14999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 15099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon /** 15199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Returns a Bitmap object suitable for {@link Notification}'s large icon. This might 15299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * return null when the given Drawable isn't BitmapDrawable, or if the system fails to 15399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * create a scaled Bitmap for the Drawable. 15499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon */ 15599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon private Bitmap getPhotoIconWhenAppropriate(Context context, Drawable photo) { 15699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon if (!(photo instanceof BitmapDrawable)) { 15799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon return null; 15899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 15999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon int iconSize = context.getResources() 16099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon .getDimensionPixelSize(R.dimen.notification_icon_size); 16199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon Bitmap orgBitmap = ((BitmapDrawable) photo).getBitmap(); 16299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon int orgWidth = orgBitmap.getWidth(); 16399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon int orgHeight = orgBitmap.getHeight(); 16499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon int longerEdge = orgWidth > orgHeight ? orgWidth : orgHeight; 16599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // We want downscaled one only when the original icon is too big. 16699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon if (longerEdge > iconSize) { 16799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon float ratio = ((float) longerEdge) / iconSize; 16899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon int newWidth = (int) (orgWidth / ratio); 16999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon int newHeight = (int) (orgHeight / ratio); 17099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // If the longer edge is much longer than the shorter edge, the latter may 17199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // become 0 which will cause a crash. 17299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon if (newWidth <= 0 || newHeight <= 0) { 17399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon Log.w(this, "Photo icon's width or height become 0."); 17499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon return null; 17599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 17699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 17799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // It is sure ratio >= 1.0f in any case and thus the newly created Bitmap 17899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // should be smaller than the original. 17999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon return Bitmap.createScaledBitmap(orgBitmap, newWidth, newHeight, true); 18099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } else { 18199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon return orgBitmap; 18299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 18399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 18499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 18599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 18699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon /** 18799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Starts an asynchronous image load. After finishing the load, 18899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * {@link OnImageLoadCompleteListener#onImageLoadComplete(int, Drawable, Bitmap, Object)} 18999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * will be called. 19099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * 19199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * @param token Arbitrary integer which will be returned as the first argument of 19299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * {@link OnImageLoadCompleteListener#onImageLoadComplete(int, Drawable, Bitmap, Object)} 19399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * @param context Context object used to do the time-consuming operation. 194a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki * @param displayPhotoUri Uri to be used to fetch the photo 19599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * @param listener Callback object which will be used when the asynchronous load is done. 19699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Can be null, which means only the asynchronous load is done while there's no way to 19799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * obtain the loaded photos. 19899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * @param cookie Arbitrary object the caller wants to remember, which will become the 19999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * fourth argument of {@link OnImageLoadCompleteListener#onImageLoadComplete(int, Drawable, 20099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Bitmap, Object)}. Can be null, at which the callback will also has null for the argument. 20199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon */ 2025b70c1c2ef08f06bacd4156b266e8ce5b3ccdc07Hall Liu public void startObtainPhotoAsync(int token, Context context, Uri displayPhotoUri, 20399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon OnImageLoadCompleteListener listener, Object cookie) { 2048d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad ensureAsyncHandlerStarted(); 20599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 20699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // in case the source caller info is null, the URI will be null as well. 20799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // just update using the placeholder image in this case. 208a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki if (displayPhotoUri == null) { 20999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon Log.wtf(LOG_TAG, "Uri is missing"); 21099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon return; 21199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 21299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 21399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // Added additional Cookie field in the callee to handle arguments 21499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // sent to the callback function. 21599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 21699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // setup arguments 21799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon WorkerArgs args = new WorkerArgs(); 21899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon args.cookie = cookie; 21999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon args.context = context; 220a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki args.displayPhotoUri = displayPhotoUri; 22199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon args.listener = listener; 22299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 22399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // setup message arguments 2248d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad Message msg = mThreadHandler.obtainMessage(token); 22599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon msg.arg1 = EVENT_LOAD_IMAGE; 22699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon msg.obj = args; 22799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 228a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki Log.d(LOG_TAG, "Begin loading image: " + args.displayPhotoUri + 22999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon ", displaying default image for now."); 23099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 23199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon // notify the thread to begin working 2328d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad mThreadHandler.sendMessage(msg); 2338d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad } 2348d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad 2358d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad private void ensureAsyncHandlerStarted() { 2368d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad if (mThreadHandler == null) { 2378d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad HandlerThread thread = new HandlerThread("ContactsAsyncWorker"); 2388d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad thread.start(); 2398d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad mThreadHandler = new WorkerHandler(thread.getLooper()); 2408d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad } 24199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 24299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon} 243