Home | History | Annotate | Download | only in contactinfo
      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.dialer.app.R;
     29 import com.android.dialer.common.Assert;
     30 import com.android.dialer.common.LogUtil;
     31 import com.android.dialer.lettertile.LetterTileDrawable;
     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 context;
     47   private final ContactInfo contactInfo;
     48 
     49   public ContactPhotoLoader(Context context, ContactInfo contactInfo) {
     50     this.context = Objects.requireNonNull(context);
     51     this.contactInfo = Objects.requireNonNull(contactInfo);
     52   }
     53 
     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. */
     63   public Bitmap loadPhotoIcon() {
     64     Assert.isWorkerThread();
     65     int photoSize = context.getResources().getDimensionPixelSize(R.dimen.contact_photo_size);
     66     return drawableToBitmap(getIcon(), photoSize, photoSize);
     67   }
     68 
     69   @VisibleForTesting
     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
     83   private Drawable createPhotoIconDrawable() {
     84     if (contactInfo.photoUri == null) {
     85       return null;
     86     }
     87     try {
     88       InputStream input = context.getContentResolver().openInputStream(contactInfo.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(context.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. */
    116   private Drawable createLetterTileDrawable() {
    117     ContactInfoHelper helper =
    118         new ContactInfoHelper(context, GeoUtil.getCurrentCountryIso(context));
    119     LetterTileDrawable drawable = new LetterTileDrawable(context.getResources());
    120     drawable.setCanonicalDialerLetterTileDetails(
    121         contactInfo.name,
    122         contactInfo.lookupKey,
    123         LetterTileDrawable.SHAPE_CIRCLE,
    124         helper.isBusiness(contactInfo.sourceType)
    125             ? LetterTileDrawable.TYPE_BUSINESS
    126             : LetterTileDrawable.TYPE_DEFAULT);
    127     return drawable;
    128   }
    129 }
    130