blob: 548fb30f28f70038666ed20e063c364676760c7b [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car.dialer.telecom;
import android.content.ContentResolver;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.support.annotation.MainThread;
import android.support.annotation.Nullable;
import android.widget.ImageView;
import java.lang.ref.WeakReference;
/**
* Helper task that retrieves a Contact photo from the local Contacts store. The loading task
* is tied to an ImageView that allows a lightweight management of the task upon update of the view.
*
* TODO(mcrico): Using a View's TAG to store and manage Async task loading is pretty brittle.
* Vanagon is not depending on this logic and projected shouldn't either.
*/
public class ContactBitmapWorker extends AsyncTask<Void, Void, Bitmap> {
private final WeakReference<ImageView> mImageViewReference;
private final WeakReference<ContentResolver> mContentResolverReference;
private final String mNumber;
private final BitmapWorkerListener mListener;
/** Interface to receive updates from this worker */
public interface BitmapWorkerListener {
/** Called in the main thread upon bitmap load finish */
@MainThread
void onBitmapLoaded(@Nullable Bitmap bitmap);
}
/**
* @return A worker task if a new one was needed to load the bitmap.
*/
@Nullable public static ContactBitmapWorker loadBitmap(
ContentResolver contentResolver,
ImageView imageView,
String number,
BitmapWorkerListener listener) {
// This work may be underway already.
if (!cancelPotentialWork(number, imageView)) {
return null;
}
ContactBitmapWorker task =
new ContactBitmapWorker(contentResolver, imageView, number, listener);
imageView.setTag(task);
imageView.setImageResource(0);
task.execute();
return task;
}
/** Use {@link #loadBitmap} instead, as it guarantees de-duplication of work */
private ContactBitmapWorker(
ContentResolver contentResolver,
ImageView imageView,
String number,
BitmapWorkerListener listener) {
mImageViewReference = new WeakReference<>(imageView);
mContentResolverReference = new WeakReference<>(contentResolver);
mNumber = number;
mListener = listener;
}
@Override
protected Bitmap doInBackground(Void... voids) {
final ContentResolver contentResolver = mContentResolverReference.get();
if (contentResolver != null) {
return TelecomUtils.getContactPhotoFromNumber(contentResolver, mNumber);
}
return null;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
return;
}
if (mImageViewReference.get() != null) {
mListener.onBitmapLoaded(bitmap);
}
}
/**
* @return Whether a new Bitmap loading should continue for this imageView.
*/
private static boolean cancelPotentialWork(String number, ImageView imageView) {
final ContactBitmapWorker bitmapWorkerTask = (ContactBitmapWorker) imageView.getTag();
if (bitmapWorkerTask != null) {
if (bitmapWorkerTask.mNumber != number) {
bitmapWorkerTask.cancel(true);
imageView.setTag(null);
} else {
// The same work is already in progress
return false;
}
}
return true;
}
}