1 /* 2 * Copyright (C) 2019 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.car.dialer.ui.activecall; 18 19 import android.graphics.drawable.Drawable; 20 import android.os.Bundle; 21 import android.os.SystemClock; 22 import android.telecom.Call; 23 import android.text.TextUtils; 24 import android.view.View; 25 import android.widget.Chronometer; 26 import android.widget.ImageView; 27 import android.widget.TextView; 28 29 import androidx.annotation.NonNull; 30 import androidx.annotation.Nullable; 31 import androidx.core.util.Pair; 32 import androidx.fragment.app.Fragment; 33 34 import com.android.car.apps.common.BackgroundImageView; 35 import com.android.car.apps.common.LetterTileDrawable; 36 import com.android.car.dialer.R; 37 import com.android.car.dialer.log.L; 38 import com.android.car.dialer.ui.view.ContactAvatarOutputlineProvider; 39 import com.android.car.telephony.common.CallDetail; 40 import com.android.car.telephony.common.TelecomUtils; 41 42 import com.bumptech.glide.Glide; 43 import com.bumptech.glide.request.RequestOptions; 44 import com.bumptech.glide.request.target.SimpleTarget; 45 import com.bumptech.glide.request.transition.Transition; 46 47 import java.util.concurrent.CompletableFuture; 48 49 /** A fragment that displays information about a call with actions. */ 50 public abstract class InCallFragment extends Fragment { 51 private static final String TAG = "CD.InCallFragment"; 52 53 private View mUserProfileContainerView; 54 private TextView mPhoneNumberView; 55 private Chronometer mUserProfileCallStateText; 56 private TextView mNameView; 57 private ImageView mAvatarView; 58 private BackgroundImageView mBackgroundImage; 59 private LetterTileDrawable mDefaultAvatar; 60 private CompletableFuture<Void> mPhoneNumberInfoFuture; 61 private String mCurrentNumber; 62 63 @Override onCreate(Bundle savedInstanceState)64 public void onCreate(Bundle savedInstanceState) { 65 super.onCreate(savedInstanceState); 66 mDefaultAvatar = TelecomUtils.createLetterTile(getContext(), null, null); 67 } 68 69 /** 70 * Shared UI elements between ongoing call and incoming call page: {@link BackgroundImageView} 71 * and {@link R.layout#user_profile_large}. 72 */ 73 @Override onViewCreated(@onNull View view, @Nullable Bundle savedInstanceState)74 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 75 mUserProfileContainerView = view.findViewById(R.id.user_profile_container); 76 mNameView = mUserProfileContainerView.findViewById(R.id.user_profile_title); 77 mAvatarView = mUserProfileContainerView.findViewById(R.id.user_profile_avatar); 78 mAvatarView.setOutlineProvider(ContactAvatarOutputlineProvider.get()); 79 mPhoneNumberView = mUserProfileContainerView.findViewById(R.id.user_profile_phone_number); 80 mUserProfileCallStateText = mUserProfileContainerView.findViewById( 81 R.id.user_profile_call_state); 82 mBackgroundImage = view.findViewById(R.id.background_image); 83 } 84 85 /** Presents the user profile. */ bindUserProfileView(@ullable CallDetail callDetail)86 protected void bindUserProfileView(@Nullable CallDetail callDetail) { 87 L.i(TAG, "bindUserProfileView: %s", callDetail); 88 if (callDetail == null) { 89 return; 90 } 91 92 String number = callDetail.getNumber(); 93 if (mCurrentNumber != null && mCurrentNumber.equals(number)) { 94 return; 95 } 96 mCurrentNumber = number; 97 98 if (mPhoneNumberInfoFuture != null) { 99 mPhoneNumberInfoFuture.cancel(true); 100 } 101 102 mNameView.setText(TelecomUtils.getFormattedNumber(getContext(), number)); 103 mPhoneNumberView.setVisibility(View.GONE); 104 mAvatarView.setImageDrawable(mDefaultAvatar); 105 106 mPhoneNumberInfoFuture = TelecomUtils.getPhoneNumberInfo(getContext(), number) 107 .thenAcceptAsync((info) -> { 108 if (getContext() == null) { 109 return; 110 } 111 112 mNameView.setText(info.getDisplayName()); 113 114 String phoneNumberLabel = info.getTypeLabel(); 115 if (!phoneNumberLabel.isEmpty()) { 116 phoneNumberLabel += " "; 117 } 118 phoneNumberLabel += TelecomUtils.getFormattedNumber(getContext(), number); 119 if (!TextUtils.isEmpty(phoneNumberLabel) 120 && !phoneNumberLabel.equals(info.getDisplayName())) { 121 mPhoneNumberView.setText(phoneNumberLabel); 122 mPhoneNumberView.setVisibility(View.VISIBLE); 123 } else { 124 mPhoneNumberView.setVisibility(View.GONE); 125 } 126 127 LetterTileDrawable letterTile = TelecomUtils.createLetterTile( 128 getContext(), info.getInitials(), info.getDisplayName()); 129 130 Glide.with(this) 131 .load(info.getAvatarUri()) 132 .apply(new RequestOptions().centerCrop().error(letterTile)) 133 .into(new SimpleTarget<Drawable>() { 134 @Override 135 public void onResourceReady(Drawable resource, 136 Transition<? super Drawable> glideAnimation) { 137 mBackgroundImage.setAlpha(getResources().getFloat( 138 R.dimen.config_background_image_alpha)); 139 mBackgroundImage.setBackgroundDrawable(resource, false); 140 mAvatarView.setImageDrawable(resource); 141 } 142 143 @Override 144 public void onLoadFailed(Drawable errorDrawable) { 145 mBackgroundImage.setAlpha(getResources().getFloat( 146 R.dimen.config_background_image_error_alpha)); 147 mBackgroundImage.setBackgroundColor(letterTile.getColor()); 148 mAvatarView.setImageDrawable(letterTile); 149 } 150 }); 151 }, getContext().getMainExecutor()); 152 } 153 154 /** Presents the call state and call duration. */ updateCallDescription(@ullable Pair<Integer, Long> callStateAndConnectTime)155 protected void updateCallDescription(@Nullable Pair<Integer, Long> callStateAndConnectTime) { 156 if (callStateAndConnectTime == null || callStateAndConnectTime.first == null) { 157 mUserProfileCallStateText.stop(); 158 mUserProfileCallStateText.setText(""); 159 return; 160 } 161 if (callStateAndConnectTime.first == Call.STATE_ACTIVE) { 162 mUserProfileCallStateText.setBase(callStateAndConnectTime.second 163 - System.currentTimeMillis() + SystemClock.elapsedRealtime()); 164 mUserProfileCallStateText.start(); 165 } else { 166 mUserProfileCallStateText.stop(); 167 mUserProfileCallStateText.setText( 168 TelecomUtils.callStateToUiString(getContext(), 169 callStateAndConnectTime.first)); 170 } 171 } 172 173 @Override onStop()174 public void onStop() { 175 super.onStop(); 176 if (mPhoneNumberInfoFuture != null) { 177 mPhoneNumberInfoFuture.cancel(true); 178 } 179 } 180 } 181