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