1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.dialer.app.contactinfo; 18 19 import android.content.Context; 20 import android.graphics.Bitmap; 21 import android.graphics.BitmapFactory; 22 import android.graphics.Canvas; 23 import android.graphics.drawable.Drawable; 24 import android.support.annotation.Nullable; 25 import android.support.annotation.VisibleForTesting; 26 import android.support.v4.graphics.drawable.RoundedBitmapDrawable; 27 import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; 28 import com.android.contacts.common.lettertiles.LetterTileDrawable; 29 import com.android.dialer.app.R; 30 import com.android.dialer.common.Assert; 31 import com.android.dialer.common.LogUtil; 32 import com.android.dialer.location.GeoUtil; 33 import com.android.dialer.phonenumbercache.ContactInfo; 34 import com.android.dialer.phonenumbercache.ContactInfoHelper; 35 import java.io.IOException; 36 import java.io.InputStream; 37 import java.util.Objects; 38 39 /** 40 * Class to create the appropriate contact icon from a ContactInfo. This class is for synchronous, 41 * blocking calls to generate bitmaps, while ContactCommons.ContactPhotoManager is to cache, manage 42 * and update a ImageView asynchronously. 43 */ 44 public class ContactPhotoLoader { 45 46 private final Context mContext; 47 private final ContactInfo mContactInfo; 48 ContactPhotoLoader(Context context, ContactInfo contactInfo)49 public ContactPhotoLoader(Context context, ContactInfo contactInfo) { 50 mContext = Objects.requireNonNull(context); 51 mContactInfo = Objects.requireNonNull(contactInfo); 52 } 53 drawableToBitmap(Drawable drawable, int width, int height)54 private static Bitmap drawableToBitmap(Drawable drawable, int width, int height) { 55 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 56 Canvas canvas = new Canvas(bitmap); 57 drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 58 drawable.draw(canvas); 59 return bitmap; 60 } 61 62 /** Create a contact photo icon bitmap appropriate for the ContactInfo. */ loadPhotoIcon()63 public Bitmap loadPhotoIcon() { 64 Assert.isWorkerThread(); 65 int photoSize = mContext.getResources().getDimensionPixelSize(R.dimen.contact_photo_size); 66 return drawableToBitmap(getIcon(), photoSize, photoSize); 67 } 68 69 @VisibleForTesting getIcon()70 Drawable getIcon() { 71 Drawable drawable = createPhotoIconDrawable(); 72 if (drawable == null) { 73 drawable = createLetterTileDrawable(); 74 } 75 return drawable; 76 } 77 78 /** 79 * @return a {@link Drawable} of circular photo icon if the photo can be loaded, {@code null} 80 * otherwise. 81 */ 82 @Nullable createPhotoIconDrawable()83 private Drawable createPhotoIconDrawable() { 84 if (mContactInfo.photoUri == null) { 85 return null; 86 } 87 try { 88 InputStream input = mContext.getContentResolver().openInputStream(mContactInfo.photoUri); 89 if (input == null) { 90 LogUtil.w( 91 "ContactPhotoLoader.createPhotoIconDrawable", 92 "createPhotoIconDrawable: InputStream is null"); 93 return null; 94 } 95 Bitmap bitmap = BitmapFactory.decodeStream(input); 96 input.close(); 97 98 if (bitmap == null) { 99 LogUtil.w( 100 "ContactPhotoLoader.createPhotoIconDrawable", 101 "createPhotoIconDrawable: Bitmap is null"); 102 return null; 103 } 104 final RoundedBitmapDrawable drawable = 105 RoundedBitmapDrawableFactory.create(mContext.getResources(), bitmap); 106 drawable.setAntiAlias(true); 107 drawable.setCircular(true); 108 return drawable; 109 } catch (IOException e) { 110 LogUtil.e("ContactPhotoLoader.createPhotoIconDrawable", e.toString()); 111 return null; 112 } 113 } 114 115 /** @return a {@link LetterTileDrawable} based on the ContactInfo. */ createLetterTileDrawable()116 private Drawable createLetterTileDrawable() { 117 ContactInfoHelper helper = 118 new ContactInfoHelper(mContext, GeoUtil.getCurrentCountryIso(mContext)); 119 LetterTileDrawable drawable = new LetterTileDrawable(mContext.getResources()); 120 drawable.setCanonicalDialerLetterTileDetails( 121 mContactInfo.name, 122 mContactInfo.lookupKey, 123 LetterTileDrawable.SHAPE_CIRCLE, 124 helper.isBusiness(mContactInfo.sourceType) 125 ? LetterTileDrawable.TYPE_BUSINESS 126 : LetterTileDrawable.TYPE_DEFAULT); 127 return drawable; 128 } 129 } 130