diff options
-rw-r--r-- | Android.mk | 13 | ||||
-rw-r--r-- | libs/picasso-2.5.2.jar | bin | 0 -> 120459 bytes | |||
-rw-r--r-- | res/layout/call_log_list_item.xml | 12 | ||||
-rw-r--r-- | res/values/cm_dimens.xml | 2 | ||||
-rw-r--r-- | res/values/cm_strings.xml | 2 | ||||
-rw-r--r-- | src/com/android/dialer/calllog/CallLogAdapter.java | 8 | ||||
-rw-r--r-- | src/com/android/dialer/calllog/CallLogListItemHelper.java | 7 | ||||
-rw-r--r-- | src/com/android/dialer/calllog/CallLogListItemViewHolder.java | 20 | ||||
-rw-r--r-- | src/com/android/dialer/calllog/ContactInfo.java | 12 | ||||
-rw-r--r-- | src/com/android/dialer/calllog/ContactInfoHelper.java | 31 | ||||
-rw-r--r-- | src/com/android/dialer/calllog/LookupInfoPresenter.java | 52 | ||||
-rw-r--r-- | src/com/android/dialer/calllog/LookupInfoViews.java | 37 | ||||
-rw-r--r-- | src/com/android/dialer/util/ImageUtils.java | 182 | ||||
-rw-r--r-- | src/com/android/dialer/util/RoundedTransformation.java | 48 | ||||
-rw-r--r-- | tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java | 4 |
15 files changed, 417 insertions, 13 deletions
diff --git a/Android.mk b/Android.mk index 364d95564..3be5d73b2 100644 --- a/Android.mk +++ b/Android.mk @@ -44,9 +44,6 @@ LOCAL_AAPT_FLAGS := \ --extra-packages com.android.phone.common \ --extra-packages com.cyanogen.ambient -LOCAL_STATIC_JAVA_AAR_LIBRARIES := \ - ambientsdk - LOCAL_JAVA_LIBRARIES := telephony-common LOCAL_FULL_LIBS_MANIFEST_FILES := $(LOCAL_PATH)/AndroidManifest_cm.xml @@ -63,7 +60,8 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ guava \ libphonenumber \ org.cyanogenmod.platform.sdk \ - dialernext-android-support-design + dialernext-android-support-design \ + picasso-dialer LOCAL_PACKAGE_NAME := Dialer LOCAL_CERTIFICATE := shared @@ -71,6 +69,10 @@ LOCAL_PRIVILEGED_MODULE := true LOCAL_PROGUARD_FLAG_FILES := proguard.flags $(incallui_dir)/proguard.flags +# utilize ContactsCommon's phone-number-based contact-info lookup +CONTACTS_COMMON_LOOKUP_PROVIDER ?= $(LOCAL_PATH)/$(contacts_common_dir)/info_lookup +include $(CONTACTS_COMMON_LOOKUP_PROVIDER)/phonenumber_lookup_provider.mk + # Uncomment the following line to build against the current SDK # This is required for building an unbundled app. #LOCAL_SDK_VERSION := current @@ -80,7 +82,8 @@ include $(BUILD_PACKAGE) include $(CLEAR_VARS) LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \ dialernext-android-support-design:$(supportdesign_dir)/android-support-design.jar \ - dialernext-android-support-v7-appcompat:$(appcompat_dir)/android-support-v7-appcompat.jar + dialernext-android-support-v7-appcompat:$(appcompat_dir)/android-support-v7-appcompat.jar \ + picasso-dialer:libs/picasso-2.5.2.jar include $(BUILD_MULTI_PREBUILT) diff --git a/libs/picasso-2.5.2.jar b/libs/picasso-2.5.2.jar Binary files differnew file mode 100644 index 000000000..6acbaa14d --- /dev/null +++ b/libs/picasso-2.5.2.jar diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml index 927152440..8a3d44f5b 100644 --- a/res/layout/call_log_list_item.xml +++ b/res/layout/call_log_list_item.xml @@ -98,6 +98,18 @@ android:singleLine="true" /> </LinearLayout> + + <TextView + android:id="@+id/spamInfo" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/call_log_name_margin_bottom" + android:layout_marginEnd="@dimen/call_log_icon_margin" + android:textColor="@color/spam_contact_color" + android:textSize="@dimen/call_log_spam_info_text_size" + android:singleLine="true" + android:visibility="gone" /> + <TextView android:id="@+id/voicemail_transcription" android:layout_width="wrap_content" diff --git a/res/values/cm_dimens.xml b/res/values/cm_dimens.xml index b93f721f6..1cc5d1b41 100644 --- a/res/values/cm_dimens.xml +++ b/res/values/cm_dimens.xml @@ -2,4 +2,6 @@ <resources> <dimen name="contact_list_badge_margin">1dp</dimen> <dimen name="dialpad_credits_padding">14dp</dimen> + + <dimen name="call_log_spam_info_text_size">10sp</dimen> </resources>
\ No newline at end of file diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml index 0177a0ee1..e74e6b348 100644 --- a/res/values/cm_strings.xml +++ b/res/values/cm_strings.xml @@ -170,4 +170,6 @@ <string name="provider_disable_title">Disable %1$s?</string> <string name="provider_disable_message">By disabling %1$s, you will not have caller ID.</string> <string name="provider_disable_spam_message">By disabling %1$s, you will not have spam protection or caller ID.</string> + + <string name="powered_by_provider">Powered by <xliff:g id="provider">%s</xliff:g></string> </resources> diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java index 5e89e8b72..cde87d0e4 100644 --- a/src/com/android/dialer/calllog/CallLogAdapter.java +++ b/src/com/android/dialer/calllog/CallLogAdapter.java @@ -320,8 +320,10 @@ public class CallLogAdapter extends GroupingListAdapter mTelecomCallLogCache = new TelecomCallLogCache(mContext); PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(mContext, resources, mTelecomCallLogCache); + LookupInfoPresenter lookupInfoPresenter = new LookupInfoPresenter(mContext, resources); mCallLogListItemHelper = - new CallLogListItemHelper(phoneCallDetailsHelper, resources, mTelecomCallLogCache); + new CallLogListItemHelper(phoneCallDetailsHelper, lookupInfoPresenter, + resources, mTelecomCallLogCache); mCallLogGroupBuilder = new CallLogGroupBuilder(this); mPrefs = PreferenceManager.getDefaultSharedPreferences(context); maybeShowVoicemailPromoCard(); @@ -407,7 +409,8 @@ public class CallLogAdapter extends GroupingListAdapter mExpandCollapseListener, mTelecomCallLogCache, mCallLogListItemHelper, - mVoicemailPlaybackPresenter); + mVoicemailPlaybackPresenter, + mContactInfoHelper); viewHolder.callLogEntryView.setTag(viewHolder); viewHolder.callLogEntryView.setAccessibilityDelegate(mAccessibilityDelegate); @@ -580,6 +583,7 @@ public class CallLogAdapter extends GroupingListAdapter views.setAttributionImage(views.inCallComponentName); mCallLogListItemHelper.setPhoneCallDetails(views, details); + mCallLogListItemHelper.setLookupInfoDetails(views, info); } @Override diff --git a/src/com/android/dialer/calllog/CallLogListItemHelper.java b/src/com/android/dialer/calllog/CallLogListItemHelper.java index 1c8e397e4..938300a8c 100644 --- a/src/com/android/dialer/calllog/CallLogListItemHelper.java +++ b/src/com/android/dialer/calllog/CallLogListItemHelper.java @@ -37,6 +37,7 @@ import com.android.dialer.R; /** Resources to look up strings. */ private final Resources mResources; private final TelecomCallLogCache mTelecomCallLogCache; + private final LookupInfoPresenter mLookupInfoPresenter; /** * Creates a new helper instance. @@ -46,9 +47,11 @@ import com.android.dialer.R; */ public CallLogListItemHelper( PhoneCallDetailsHelper phoneCallDetailsHelper, + LookupInfoPresenter lookupInfoPresenter, Resources resources, TelecomCallLogCache telecomCallLogCache) { mPhoneCallDetailsHelper = phoneCallDetailsHelper; + mLookupInfoPresenter = lookupInfoPresenter; mResources = resources; mTelecomCallLogCache = telecomCallLogCache; } @@ -76,6 +79,10 @@ import com.android.dialer.R; views.nameOrNumber = getNameOrNumber(details); } + public void setLookupInfoDetails(CallLogListItemViewHolder views, ContactInfo info) { + mLookupInfoPresenter.bindContactLookupInfo(views.lookupInfoViews, info); + } + /** * Sets the accessibility descriptions for the action buttons in the action button ViewStub. * diff --git a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java index 21343c80b..2e45d3c3e 100644 --- a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java +++ b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java @@ -75,6 +75,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder public final View primaryActionView; /** The details of the phone call. */ public final PhoneCallDetailsViews phoneCallDetailsViews; + public final LookupInfoViews lookupInfoViews; /** The text of the header for a day grouping. */ public final TextView dayGroupHeader; /** The view containing the details for the call log row, including the action buttons. */ @@ -203,10 +204,12 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder TelecomCallLogCache telecomCallLogCache, CallLogListItemHelper callLogListItemHelper, VoicemailPlaybackPresenter voicemailPlaybackPresenter, + ContactInfoHelper contactInfoHelper, View rootView, DialerQuickContact dialerQuickContact, View primaryActionView, PhoneCallDetailsViews phoneCallDetailsViews, + LookupInfoViews lookupInfoViews, CardView callLogEntryView, TextView dayGroupHeader, ImageView primaryActionButtonView) { @@ -217,11 +220,13 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder mTelecomCallLogCache = telecomCallLogCache; mCallLogListItemHelper = callLogListItemHelper; mVoicemailPlaybackPresenter = voicemailPlaybackPresenter; + mContactInfoHelper = contactInfoHelper; this.rootView = rootView; this.dialerQuickContact = dialerQuickContact; this.primaryActionView = primaryActionView; this.phoneCallDetailsViews = phoneCallDetailsViews; + this.lookupInfoViews = lookupInfoViews; this.callLogEntryView = callLogEntryView; this.dayGroupHeader = dayGroupHeader; this.primaryActionButtonView = primaryActionButtonView; @@ -238,9 +243,6 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder primaryActionButtonView.setOnClickListener(this); primaryActionView.setOnClickListener(mExpandCollapseListener); - - mContactInfoHelper = new ContactInfoHelper(mContext, - GeoUtil.getCurrentCountryIso(mContext)); } public static CallLogListItemViewHolder create( @@ -249,7 +251,8 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder View.OnClickListener expandCollapseListener, TelecomCallLogCache telecomCallLogCache, CallLogListItemHelper callLogListItemHelper, - VoicemailPlaybackPresenter voicemailPlaybackPresenter) { + VoicemailPlaybackPresenter voicemailPlaybackPresenter, + ContactInfoHelper contactInfoHelper) { return new CallLogListItemViewHolder( context, @@ -257,10 +260,12 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder telecomCallLogCache, callLogListItemHelper, voicemailPlaybackPresenter, + contactInfoHelper, view, (DialerQuickContact) view.findViewById(R.id.quick_contact_photo), view.findViewById(R.id.primary_action_view), PhoneCallDetailsViews.fromView(view), + LookupInfoViews.fromView(view), (CardView) view.findViewById(R.id.call_log_row), (TextView) view.findViewById(R.id.call_log_day_group_label), (ImageView) view.findViewById(R.id.primary_action_button)); @@ -603,17 +608,22 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder TelecomCallLogCache telecomCallLogCache = new TelecomCallLogCache(context); PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper( context, resources, telecomCallLogCache); + LookupInfoPresenter lookupInfoPresenter = new LookupInfoPresenter(context, + context.getResources()); CallLogListItemViewHolder viewHolder = new CallLogListItemViewHolder( context, null /* expandCollapseListener */, telecomCallLogCache, - new CallLogListItemHelper(phoneCallDetailsHelper, resources, telecomCallLogCache), + new CallLogListItemHelper(phoneCallDetailsHelper, lookupInfoPresenter, + resources, telecomCallLogCache), null /* voicemailPlaybackPresenter */, + null /* ContactInfoHelper */, new View(context), new DialerQuickContact(context), new View(context), PhoneCallDetailsViews.createForTest(context), + LookupInfoViews.createForText(context), new CardView(context), new TextView(context), new ImageView(context)); diff --git a/src/com/android/dialer/calllog/ContactInfo.java b/src/com/android/dialer/calllog/ContactInfo.java index 357c832cf..bbcf1b482 100644 --- a/src/com/android/dialer/calllog/ContactInfo.java +++ b/src/com/android/dialer/calllog/ContactInfo.java @@ -16,6 +16,7 @@ package com.android.dialer.calllog; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.text.TextUtils; @@ -46,6 +47,17 @@ public class ContactInfo { public boolean isBadData; public String objectId; + // the following fields are pertinent only in the presence of a + // valid {@link com.cyanogen.lookup.phonenumber.contract.LookupProvider} + public String city; + public String country; + public String address; + public boolean isSpam; + public int spamCount; + public String photoUrl; + public String lookupProviderName; + public Drawable attributionDrawable; + public static ContactInfo EMPTY = new ContactInfo(); public int sourceType = 0; diff --git a/src/com/android/dialer/calllog/ContactInfoHelper.java b/src/com/android/dialer/calllog/ContactInfoHelper.java index 7f82a3712..382680573 100644 --- a/src/com/android/dialer/calllog/ContactInfoHelper.java +++ b/src/com/android/dialer/calllog/ContactInfoHelper.java @@ -43,6 +43,10 @@ import com.android.dialer.service.CachedNumberLookupService.CachedContactInfo; import com.android.dialer.util.TelecomUtil; import com.android.dialerbind.ObjectFactory; +import com.cyanogen.lookup.phonenumber.contract.LookupProvider; +import com.cyanogen.lookup.phonenumber.provider.LookupProviderImpl; +import com.cyanogen.lookup.phonenumber.request.LookupRequest; +import com.cyanogen.lookup.phonenumber.response.LookupResponse; import org.json.JSONException; import org.json.JSONObject; @@ -56,6 +60,7 @@ public class ContactInfoHelper { private final Context mContext; private final String mCurrentCountryIso; + private final LookupProvider mLookupProvider; private static final CachedNumberLookupService mCachedNumberLookupService = ObjectFactory.newCachedNumberLookupService(); @@ -63,6 +68,12 @@ public class ContactInfoHelper { public ContactInfoHelper(Context context, String currentCountryIso) { mContext = context; mCurrentCountryIso = currentCountryIso; + LookupProvider lookupProvider = new LookupProviderImpl(context); + if (lookupProvider.initialize()) { + mLookupProvider = lookupProvider; + } else { + mLookupProvider = null; + } } /** @@ -287,6 +298,26 @@ public class ContactInfoHelper { info = null; } } + // always do a LookupProvider search, if available + if (mLookupProvider != null) { + LookupResponse response = mLookupProvider.blockingFetchInfo( + new LookupRequest(PhoneNumberUtils.formatNumberToE164(number, countryIso), null)); + if (response != null) { + // map LookupResponse to ContactInfo + ContactInfo contactInfo = new ContactInfo(); + contactInfo.lookupProviderName = response.mProviderName; + contactInfo.name = response.mName; + contactInfo.number = formatPhoneNumber(response.mNumber, null, countryIso); + contactInfo.city = response.mCity; + contactInfo.country = response.mCountry; + contactInfo.address = response.mAddress; + contactInfo.photoUrl = response.mPhotoUrl; + contactInfo.isSpam = response.mIsSpam; + contactInfo.spamCount = response.mSpamCount; + contactInfo.attributionDrawable = response.mAttributionLogo; + info = contactInfo; + } + } return info; } diff --git a/src/com/android/dialer/calllog/LookupInfoPresenter.java b/src/com/android/dialer/calllog/LookupInfoPresenter.java new file mode 100644 index 000000000..ec8d7b6e1 --- /dev/null +++ b/src/com/android/dialer/calllog/LookupInfoPresenter.java @@ -0,0 +1,52 @@ + package com.android.dialer.calllog; + + import android.content.Context; + import android.content.res.Resources; + import android.content.res.TypedArray; + import android.text.TextUtils; + import android.view.View; + import com.android.dialer.R; + import com.android.dialer.util.ImageUtils; + + /** + * Helper class that manages the call log list item based on the Lookup Response + */ +public class LookupInfoPresenter { + private final Context mContext; + private final Resources mResources; + private final int mNameColorAttributeId; + + public LookupInfoPresenter(Context context, Resources res) { + mContext = context; + mResources = res; + TypedArray a = mContext.getTheme().obtainStyledAttributes(R.style.DialtactsTheme, + new int[]{R.attr.call_log_primary_text_color}); + mNameColorAttributeId = a.getResourceId(0, 0); + a.recycle(); + } + + public void bindContactLookupInfo(LookupInfoViews views, ContactInfo info) { + if (info.isSpam) { + views.nameView.setTextColor( + mResources.getColor(R.color.spam_contact_color, mContext.getTheme())); + + views.spamInfo.setVisibility(View.VISIBLE); + views.spamInfo.setText(mContext.getResources().getQuantityString( + R.plurals.spam_count_text, info.spamCount, info.spamCount)); + } else { + // reset the views in case the ViewHolder was recycled + views.spamInfo.setVisibility(View.GONE); + views.nameView.setTextColor(mResources.getColor(mNameColorAttributeId, + mContext.getTheme())); + } + + if (!TextUtils.isEmpty(info.photoUrl)) { + ImageUtils.loadBitampFromUrl(mContext, info.photoUrl, + views.contactPhotoView.getQuickContactBadge()); + } + + if (!TextUtils.isEmpty(info.lookupProviderName )) { + views.contactPhotoView.setAttributionBadge(info.attributionDrawable); + } + } +} diff --git a/src/com/android/dialer/calllog/LookupInfoViews.java b/src/com/android/dialer/calllog/LookupInfoViews.java new file mode 100644 index 000000000..ebe03abb8 --- /dev/null +++ b/src/com/android/dialer/calllog/LookupInfoViews.java @@ -0,0 +1,37 @@ +package com.android.dialer.calllog; + +import android.content.Context; +import android.view.View; +import android.widget.TextView; +import com.android.dialer.R; +import com.android.dialer.widget.DialerQuickContact; + +/** +* ADT that stores the views affected by {@link com.cyanogen.lookup.phonenumber.contract.LookupProvider} +*/ +public class LookupInfoViews { + public final TextView nameView; + public final DialerQuickContact contactPhotoView; + public final TextView spamInfo; + + private LookupInfoViews(TextView nameView, DialerQuickContact contactPhotoView, + TextView spamInfo) { + this.nameView = nameView; + this.contactPhotoView = contactPhotoView; + this.spamInfo = spamInfo; + } + + public static LookupInfoViews fromView(View view) { + return new LookupInfoViews( + (TextView) view.findViewById(R.id.name), + (DialerQuickContact) view.findViewById(R.id.quick_contact_photo), + (TextView) view.findViewById(R.id.spamInfo) ); + } + + public static LookupInfoViews createForText(Context context) { + return new LookupInfoViews( + new TextView(context), + new DialerQuickContact(context), + new TextView(context) ); + } +} diff --git a/src/com/android/dialer/util/ImageUtils.java b/src/com/android/dialer/util/ImageUtils.java new file mode 100644 index 000000000..65fe4a55e --- /dev/null +++ b/src/com/android/dialer/util/ImageUtils.java @@ -0,0 +1,182 @@ +package com.android.dialer.util; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.TransitionDrawable; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; +import com.squareup.picasso.Picasso; +import com.squareup.picasso.Target; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * Utility class around Image loading and Bitmap effects + */ +public class ImageUtils { + private static boolean DEBUG = true; + private static String TAG = ImageUtils.class.getSimpleName(); + + public interface BitmapLoadRequest extends Target {} + + public static void loadBitampFromUrl(Context ctx, String url, ImageView imageView) { + Picasso.with(ctx) + .load(url) + .noPlaceholder() + .fit() + .transform(new RoundedTransformation(ctx)) + .into(imageView); + } + + /** + * Since Picasso only maintains a weak reference to the target, the caller of this + * function MUST maintain a reference to the BitmapLoadRequest until the callback + * is invoked. + */ + public static BitmapLoadRequest getBitmapFromUrl(Context ctx, String url, + final ImageLoadCallback<Bitmap> cb) { + BitmapLoadRequest t = new BitmapLoadRequest() { + @Override + public void onPrepareLoad(Drawable d){} + + @Override + public void onBitmapLoaded(Bitmap result, Picasso.LoadedFrom from) { + cb.onCompleted(null, result); + } + + @Override + public void onBitmapFailed(Drawable drawable) { + cb.onCompleted(null, null); + } + }; + + Picasso.with(ctx).load(url).into(t); + return t; + } + + public static void cancelRequest(Context ctx, BitmapLoadRequest request) { + Picasso.with(ctx).cancelRequest(request); + } + + public static void cancelRequest(ImageView contactImageSlot) { + Picasso.with(contactImageSlot.getContext()).cancelRequest(contactImageSlot); + } + + // doesn't offer much besides encapsulation of img loading library for easy swapping later + public static abstract class ImageLoadCallback<T> { + public abstract void onCompleted(Exception e, T result); + } + + /** + * Scale bitmap to the defined bounds. The bitmap will be scaled while maintaining the + * aspect ratio and center-cropped(vertically and horizontally) if it exceeds the + * defined bounds. + */ + public static Bitmap scaleAndCropBitmapToTarget(Bitmap bitmap, int targetHeight, + int targetWidth) { + if (bitmap == null) { + return bitmap; + } + // get bitmap properties + int bitmapHeight = bitmap.getHeight(); + int bitmapWidth = bitmap.getWidth(); + + int deltaWidth = targetWidth - bitmapWidth; + int deltaHeight = targetHeight - bitmapHeight; + + // nothing to do if src bitmap is bigger than or equal to the target + if (deltaWidth <= 0 && deltaHeight <= 0) + return bitmap; + + // scale bitmap along the dimension that is lacking the greatest + float scale = Math.max( ((float)targetWidth) / bitmapWidth, + ((float)targetHeight) / bitmapHeight); + + // calculate the new bitmap dimensions + int newHeight = (int) Math.ceil(bitmapHeight * scale); + int newWidth = (int) Math.ceil(bitmapWidth * scale); + Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, false); + + // center the bitmap vertically and horizontally + int startX = Math.max(0, (newWidth - targetWidth) / 2); + int startY = Math.max(0, (newHeight - targetHeight) / 2); + if (DEBUG) { + Log.i(TAG, "bitmapWidth : " + bitmapWidth); + Log.i(TAG, "bitmapHeight : " + bitmapHeight); + Log.i(TAG, "deltaWidth : " + deltaWidth); + Log.i(TAG, "deltaHeight : " + deltaHeight); + Log.i(TAG, "newWidth : " + newWidth); + Log.i(TAG, "newHeight : " + newHeight); + Log.i(TAG, "startX : " + startX); + Log.i(TAG, "startY : " + startY); + } + + return Bitmap.createBitmap(scaledBitmap, startX, startY, targetWidth, targetHeight); + } + + /** + * Used to convert a drawable into a bitmap. + * + * Drawables that don't have intrinsic dimensions are excluded from this conversion. This + * includes drawables such as ColorDrawables + */ + public static Bitmap drawableToBitmap (Drawable drawable) { + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable)drawable).getBitmap(); + } + + if (drawable.getIntrinsicHeight() <= 0 || drawable.getIntrinsicWidth() <= 0) { + return null; + } + + Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), + drawable.getMinimumHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + + return bitmap; + } + + public static byte[] bitmapToByteArray(Bitmap bitmap) { + if (bitmap == null) { + return null; + } + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream); + byte[] result = stream.toByteArray(); + try { + stream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return result; + } + + /** + * Sets the background for view(v) to a transition drawable that transitions from + * the current background to drawable(d) + */ + public static void setBackgroundWithTransition(View v, Drawable d) { + Drawable from = v.getBackground(); + + // quick solution to prevent memory leak from chaining transition drawables + if (from instanceof TransitionDrawable) { + TransitionDrawable t = (TransitionDrawable)from; + from = t.getDrawable(t.getNumberOfLayers() - 1); + } + + Drawable backgrounds[] = new Drawable[2]; + backgrounds[0] = from; + backgrounds[1] = d; + TransitionDrawable transitionDrawable = new TransitionDrawable(backgrounds); + transitionDrawable.setCrossFadeEnabled(true); + v.setBackground(transitionDrawable); + transitionDrawable.startTransition(200); + } +} diff --git a/src/com/android/dialer/util/RoundedTransformation.java b/src/com/android/dialer/util/RoundedTransformation.java new file mode 100644 index 000000000..4a5ffd50b --- /dev/null +++ b/src/com/android/dialer/util/RoundedTransformation.java @@ -0,0 +1,48 @@ +package com.android.dialer.util; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader; +import com.android.dialer.R; +import com.squareup.picasso.Transformation; + +public class RoundedTransformation implements Transformation { + private static int sRadius = 0; + + RoundedTransformation(Context context) { + if (sRadius == 0) { + Resources resources = context.getResources(); + sRadius = resources.getDimensionPixelSize(R.dimen.contact_photo_size); + sRadius /= 2; + } + } + + @Override + public Bitmap transform(final Bitmap source) { + Paint paint = new Paint(); + paint.setAntiAlias(true); + paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); + + Bitmap output = Bitmap.createBitmap(source.getWidth(), source.getHeight(), + Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(output); + canvas.drawRoundRect(new RectF(0, 0, source.getWidth(), source.getHeight()), sRadius, + sRadius, paint); + + if (source != output) { + source.recycle(); + } + + return output; + } + + @Override + public String key() { + return "RoundedTransformation(radius=" + sRadius + ")"; + } +}
\ No newline at end of file diff --git a/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java b/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java index 8c2d8e443..57dc12c18 100644 --- a/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java +++ b/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java @@ -63,7 +63,9 @@ public class CallLogListItemHelperTest extends AndroidTestCase { new TestTelecomCallLogCache(mContext, TEST_VOICEMAIL_NUMBER); PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(mContext, mResources, phoneUtils); - mHelper = new CallLogListItemHelper(phoneCallDetailsHelper, mResources, phoneUtils); + LookupInfoPresenter lookupInfoPresenter = new LookupInfoPresenter(mContext, mResources); + mHelper = new CallLogListItemHelper(phoneCallDetailsHelper, lookupInfoPresenter, + mResources, phoneUtils); mViewHolder = CallLogListItemViewHolder.createForTest(mContext); } |