PhoneCallDetailsHelper.java revision 24ec319f8d410be8a1923c4033f927165876cbab
1/* 2 * Copyright (C) 2011 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 17package com.android.dialer; 18 19import android.content.res.Resources; 20import android.graphics.Typeface; 21import android.provider.ContactsContract; 22import android.provider.ContactsContract.CommonDataKinds.Phone; 23import android.telephony.PhoneNumberUtils; 24import android.text.SpannableString; 25import android.text.Spanned; 26import android.text.TextUtils; 27import android.text.format.DateUtils; 28import android.text.style.ForegroundColorSpan; 29import android.text.style.StyleSpan; 30import android.view.View; 31import android.widget.TextView; 32 33import com.android.contacts.common.test.NeededForTesting; 34import com.android.dialer.calllog.CallTypeHelper; 35import com.android.dialer.calllog.ContactInfo; 36import com.android.dialer.calllog.PhoneNumberDisplayHelper; 37import com.android.dialer.calllog.PhoneNumberUtilsWrapper; 38 39/** 40 * Helper class to fill in the views in {@link PhoneCallDetailsViews}. 41 */ 42public class PhoneCallDetailsHelper { 43 /** The maximum number of icons will be shown to represent the call types in a group. */ 44 private static final int MAX_CALL_TYPE_ICONS = 3; 45 46 private final Resources mResources; 47 /** The injected current time in milliseconds since the epoch. Used only by tests. */ 48 private Long mCurrentTimeMillisForTest; 49 // Helper classes. 50 private final CallTypeHelper mCallTypeHelper; 51 private final PhoneNumberDisplayHelper mPhoneNumberHelper; 52 private final PhoneNumberUtilsWrapper mPhoneNumberUtilsWrapper; 53 54 /** 55 * Creates a new instance of the helper. 56 * <p> 57 * Generally you should have a single instance of this helper in any context. 58 * 59 * @param resources used to look up strings 60 */ 61 public PhoneCallDetailsHelper(Resources resources, CallTypeHelper callTypeHelper, 62 PhoneNumberUtilsWrapper phoneUtils) { 63 mResources = resources; 64 mCallTypeHelper = callTypeHelper; 65 mPhoneNumberHelper = new PhoneNumberDisplayHelper(resources); 66 mPhoneNumberUtilsWrapper = phoneUtils; 67 } 68 69 /** Fills the call details views with content. */ 70 public void setPhoneCallDetails(PhoneCallDetailsViews views, PhoneCallDetails details, 71 boolean isHighlighted) { 72 // Display up to a given number of icons. 73 views.callTypeIcons.clear(); 74 int count = details.callTypes.length; 75 for (int index = 0; index < count && index < MAX_CALL_TYPE_ICONS; ++index) { 76 views.callTypeIcons.add(details.callTypes[index]); 77 } 78 views.callTypeIcons.requestLayout(); 79 views.callTypeIcons.setVisibility(View.VISIBLE); 80 81 // Show the total call count only if there are more than the maximum number of icons. 82 final Integer callCount; 83 if (count > MAX_CALL_TYPE_ICONS) { 84 callCount = count; 85 } else { 86 callCount = null; 87 } 88 // The color to highlight the count and date in, if any. This is based on the first call. 89 Integer highlightColor = 90 isHighlighted ? mCallTypeHelper.getHighlightedColor(details.callTypes[0]) : null; 91 92 // The date of this call, relative to the current time. 93 CharSequence dateText = 94 DateUtils.getRelativeTimeSpanString(details.date, 95 getCurrentTimeMillis(), 96 DateUtils.MINUTE_IN_MILLIS, 97 DateUtils.FORMAT_ABBREV_RELATIVE); 98 99 // Set the call count and date. 100 setCallCountAndDate(views, callCount, dateText, highlightColor); 101 102 CharSequence numberFormattedLabel = null; 103 // Only show a label if the number is shown and it is not a SIP address. 104 if (!TextUtils.isEmpty(details.number) 105 && !PhoneNumberUtils.isUriNumber(details.number.toString())) { 106 if (details.numberLabel == ContactInfo.GEOCODE_AS_LABEL) { 107 numberFormattedLabel = details.geocode; 108 } else { 109 numberFormattedLabel = Phone.getTypeLabel(mResources, details.numberType, 110 details.numberLabel); 111 } 112 } 113 114 final CharSequence nameText; 115 final CharSequence numberText; 116 final CharSequence labelText; 117 final CharSequence displayNumber = 118 mPhoneNumberHelper.getDisplayNumber(details.number, 119 details.numberPresentation, details.formattedNumber); 120 if (TextUtils.isEmpty(details.name)) { 121 nameText = displayNumber; 122 if (TextUtils.isEmpty(details.geocode) 123 || mPhoneNumberUtilsWrapper.isVoicemailNumber(details.number)) { 124 numberText = mResources.getString(R.string.call_log_empty_gecode); 125 } else { 126 numberText = details.geocode; 127 } 128 labelText = numberText; 129 // We have a real phone number as "nameView" so make it always LTR 130 views.nameView.setTextDirection(View.TEXT_DIRECTION_LTR); 131 } else { 132 nameText = details.name; 133 numberText = displayNumber; 134 labelText = TextUtils.isEmpty(numberFormattedLabel) ? numberText : 135 numberFormattedLabel; 136 } 137 138 views.nameView.setText(nameText); 139 140 views.labelView.setText(labelText); 141 views.labelView.setVisibility(TextUtils.isEmpty(labelText) ? View.GONE : View.VISIBLE); 142 } 143 144 /** Sets the text of the header view for the details page of a phone call. */ 145 public void setCallDetailsHeader(TextView nameView, PhoneCallDetails details) { 146 final CharSequence nameText; 147 final CharSequence displayNumber = 148 mPhoneNumberHelper.getDisplayNumber(details.number, details.numberPresentation, 149 mResources.getString(R.string.recentCalls_addToContact)); 150 if (TextUtils.isEmpty(details.name)) { 151 nameText = displayNumber; 152 } else { 153 nameText = details.name; 154 } 155 156 nameView.setText(nameText); 157 } 158 159 @NeededForTesting 160 public void setCurrentTimeForTest(long currentTimeMillis) { 161 mCurrentTimeMillisForTest = currentTimeMillis; 162 } 163 164 /** 165 * Returns the current time in milliseconds since the epoch. 166 * <p> 167 * It can be injected in tests using {@link #setCurrentTimeForTest(long)}. 168 */ 169 private long getCurrentTimeMillis() { 170 if (mCurrentTimeMillisForTest == null) { 171 return System.currentTimeMillis(); 172 } else { 173 return mCurrentTimeMillisForTest; 174 } 175 } 176 177 /** Sets the call count and date. */ 178 private void setCallCountAndDate(PhoneCallDetailsViews views, Integer callCount, 179 CharSequence dateText, Integer highlightColor) { 180 // Combine the count (if present) and the date. 181 final CharSequence text; 182 if (callCount != null) { 183 text = mResources.getString( 184 R.string.call_log_item_count_and_date, callCount.intValue(), dateText); 185 } else { 186 text = dateText; 187 } 188 189 // Apply the highlight color if present. 190 final CharSequence formattedText; 191 if (highlightColor != null) { 192 formattedText = addBoldAndColor(text, highlightColor); 193 } else { 194 formattedText = text; 195 } 196 197 views.callTypeAndDate.setText(formattedText); 198 } 199 200 /** Creates a SpannableString for the given text which is bold and in the given color. */ 201 private CharSequence addBoldAndColor(CharSequence text, int color) { 202 int flags = Spanned.SPAN_INCLUSIVE_INCLUSIVE; 203 SpannableString result = new SpannableString(text); 204 result.setSpan(new StyleSpan(Typeface.BOLD), 0, text.length(), flags); 205 result.setSpan(new ForegroundColorSpan(color), 0, text.length(), flags); 206 return result; 207 } 208} 209