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