1 /*
2  * Copyright (C) 2018 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.widget;
18 
19 import android.content.Context;
20 import android.support.annotation.Nullable;
21 import android.util.AttributeSet;
22 import android.view.LayoutInflater;
23 import android.view.View;
24 import android.view.ViewGroup;
25 import android.widget.FrameLayout;
26 import android.widget.ImageView;
27 import android.widget.QuickContactBadge;
28 import com.android.dialer.common.Assert;
29 import com.android.dialer.glidephotomanager.GlidePhotoManager;
30 import com.android.dialer.glidephotomanager.GlidePhotoManagerComponent;
31 import com.android.dialer.glidephotomanager.PhotoInfo;
32 
33 /**
34  * A {@link FrameLayout} for displaying a contact photo and its optional badge (such as one for a
35  * video call).
36  */
37 public final class ContactPhotoView extends FrameLayout {
38   private final QuickContactBadge contactPhoto;
39   private final FrameLayout contactBadgeContainer;
40   private final ImageView videoCallBadge;
41   private final ImageView rttCallBadge;
42 
43   private final GlidePhotoManager glidePhotoManager;
44 
ContactPhotoView(Context context)45   public ContactPhotoView(Context context) {
46     this(context, /* attrs = */ null);
47   }
48 
ContactPhotoView(Context context, @Nullable AttributeSet attrs)49   public ContactPhotoView(Context context, @Nullable AttributeSet attrs) {
50     this(context, attrs, /* defStyleAttr = */ 0);
51   }
52 
ContactPhotoView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)53   public ContactPhotoView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
54     this(context, attrs, defStyleAttr, /* defStyleRes = */ 0);
55   }
56 
ContactPhotoView( Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)57   public ContactPhotoView(
58       Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
59     super(context, attrs, defStyleAttr, defStyleRes);
60 
61     inflateLayout();
62 
63     contactPhoto = findViewById(R.id.quick_contact_photo);
64     contactBadgeContainer = findViewById(R.id.contact_badge_container);
65     videoCallBadge = findViewById(R.id.video_call_badge);
66     rttCallBadge = findViewById(R.id.rtt_call_badge);
67 
68     glidePhotoManager = GlidePhotoManagerComponent.get(context).glidePhotoManager();
69 
70     hideBadge(); // Hide badges by default.
71   }
72 
73   @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)74   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
75     super.onMeasure(widthMeasureSpec, heightMeasureSpec);
76 
77     // We require both the height and the width to be WRAP_CONTENT to prevent users of
78     // this widget from clipping the view (by setting a size that is too small) or altering the
79     // relative position of the contact photo and its badge (by setting a size that is too large).
80     ViewGroup.LayoutParams layoutParams = Assert.isNotNull(getLayoutParams());
81     Assert.checkState(
82         layoutParams.height == LayoutParams.WRAP_CONTENT,
83         "The layout height must be WRAP_CONTENT!");
84     Assert.checkState(
85         layoutParams.width == LayoutParams.WRAP_CONTENT, "The layout width must be WRAP_CONTENT!");
86   }
87 
inflateLayout()88   private void inflateLayout() {
89     LayoutInflater inflater = Assert.isNotNull(getContext().getSystemService(LayoutInflater.class));
90     inflater.inflate(R.layout.contact_photo_view, /* root = */ this);
91   }
92 
hideBadge()93   private void hideBadge() {
94     contactBadgeContainer.setVisibility(View.GONE);
95     videoCallBadge.setVisibility(View.GONE);
96     rttCallBadge.setVisibility(View.GONE);
97   }
98 
99   /** Sets the contact photo and its badge to be displayed. */
setPhoto(PhotoInfo photoInfo)100   public void setPhoto(PhotoInfo photoInfo) {
101     glidePhotoManager.loadQuickContactBadge(contactPhoto, photoInfo);
102     setBadge(photoInfo);
103   }
104 
setBadge(PhotoInfo photoInfo)105   private void setBadge(PhotoInfo photoInfo) {
106     // No badge for spam numbers.
107     if (photoInfo.getIsSpam()) {
108       hideBadge();
109       return;
110     }
111 
112     if (photoInfo.getIsVideo()) {
113       contactBadgeContainer.setVisibility(View.VISIBLE);
114       videoCallBadge.setVisibility(View.VISIBLE);
115       // Normally a video call can't be RTT call and vice versa.
116       // (a bug): In theory a video call could be downgraded to voice and upgraded to RTT call
117       // again, this might end up a call with video and RTT features both set. Update logic here if
118       // that could happen. Also update {@link Coalescer#meetsCallFeatureCriteria}.
119       rttCallBadge.setVisibility(View.GONE);
120     } else if (photoInfo.getIsRtt()) {
121       contactBadgeContainer.setVisibility(View.VISIBLE);
122       videoCallBadge.setVisibility(View.GONE);
123       rttCallBadge.setVisibility(View.VISIBLE);
124     } else {
125       hideBadge();
126     }
127   }
128 }
129