1afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda/* 2afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * Copyright (C) 2011 The Android Open Source Project 3afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * 4afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * Licensed under the Apache License, Version 2.0 (the "License"); 5afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * you may not use this file except in compliance with the License. 6afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * You may obtain a copy of the License at 7afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * 8afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * http://www.apache.org/licenses/LICENSE-2.0 9afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * 10afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * Unless required by applicable law or agreed to in writing, software 11afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * distributed under the License is distributed on an "AS IS" BASIS, 12afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * See the License for the specific language governing permissions and 14afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * limitations under the License. 15afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda */ 16afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda 17afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdapackage com.android.contacts; 18afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda 19afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.content.res.Resources; 20afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.graphics.Typeface; 21afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.provider.ContactsContract.CommonDataKinds.Phone; 22afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.telephony.PhoneNumberUtils; 23fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerdaimport android.text.SpannableString; 24afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.text.Spanned; 25afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.text.TextUtils; 26afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.text.format.DateUtils; 27fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerdaimport android.text.style.ForegroundColorSpan; 28fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerdaimport android.text.style.StyleSpan; 29afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.view.View; 30b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerdaimport android.widget.TextView; 31afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda 32e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.calllog.CallTypeHelper; 33e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.calllog.PhoneNumberHelper; 34e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.test.NeededForTesting; 35e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 36afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda/** 37afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * Helper class to fill in the views in {@link PhoneCallDetailsViews}. 38afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda */ 39afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdapublic class PhoneCallDetailsHelper { 408e39c71705261fa97adf1b6f39336a7fbd2a2c65Flavio Lerda /** The maximum number of icons will be shown to represent the call types in a group. */ 418e39c71705261fa97adf1b6f39336a7fbd2a2c65Flavio Lerda private static final int MAX_CALL_TYPE_ICONS = 3; 428e39c71705261fa97adf1b6f39336a7fbd2a2c65Flavio Lerda 43d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda private final Resources mResources; 447d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda /** The injected current time in milliseconds since the epoch. Used only by tests. */ 457d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda private Long mCurrentTimeMillisForTest; 46178eeebac88b352c131bd0315a99da16162c986eFlavio Lerda // Helper classes. 479a208cc08567a3d86c7968d7a4f13f5714b9b657Flavio Lerda private final CallTypeHelper mCallTypeHelper; 48178eeebac88b352c131bd0315a99da16162c986eFlavio Lerda private final PhoneNumberHelper mPhoneNumberHelper; 49d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda 50afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda /** 51d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda * Creates a new instance of the helper. 52d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda * <p> 53d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda * Generally you should have a single instance of this helper in any context. 54afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * 55afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * @param resources used to look up strings 56d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda */ 57405695664582b4989cffcf054bf1aceb83dec437Flavio Lerda public PhoneCallDetailsHelper(Resources resources, CallTypeHelper callTypeHelper, 58405695664582b4989cffcf054bf1aceb83dec437Flavio Lerda PhoneNumberHelper phoneNumberHelper) { 59d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda mResources = resources; 609a208cc08567a3d86c7968d7a4f13f5714b9b657Flavio Lerda mCallTypeHelper = callTypeHelper; 61178eeebac88b352c131bd0315a99da16162c986eFlavio Lerda mPhoneNumberHelper = phoneNumberHelper; 62d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda } 63d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda 649de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda /** Fills the call details views with content. */ 654586febe3637303ab6f1b24fc5a23750aa3a6259Flavio Lerda public void setPhoneCallDetails(PhoneCallDetailsViews views, PhoneCallDetails details, 66fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda boolean isHighlighted) { 67fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda // Display up to a given number of icons. 68fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda views.callTypeIcons.clear(); 69fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda int count = details.callTypes.length; 70fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda for (int index = 0; index < count && index < MAX_CALL_TYPE_ICONS; ++index) { 71fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda views.callTypeIcons.add(details.callTypes[index]); 72fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda } 73fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda views.callTypeIcons.setVisibility(View.VISIBLE); 74fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda 75fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda // Show the total call count only if there are more than the maximum number of icons. 76fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda final Integer callCount; 77fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda if (count > MAX_CALL_TYPE_ICONS) { 78fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda callCount = count; 794586febe3637303ab6f1b24fc5a23750aa3a6259Flavio Lerda } else { 80fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda callCount = null; 817d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda } 82fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda // The color to highlight the count and date in, if any. This is based on the first call. 83fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda Integer highlightColor = 84fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda isHighlighted ? mCallTypeHelper.getHighlightedColor(details.callTypes[0]) : null; 854586febe3637303ab6f1b24fc5a23750aa3a6259Flavio Lerda 86fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda // The date of this call, relative to the current time. 87fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda CharSequence dateText = 889de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda DateUtils.getRelativeTimeSpanString(details.date, 897d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda getCurrentTimeMillis(), 90afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda DateUtils.MINUTE_IN_MILLIS, 91afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda DateUtils.FORMAT_ABBREV_RELATIVE); 92afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda 93fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda // Set the call count and date. 94fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda setCallCountAndDate(views, callCount, dateText, highlightColor); 95fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda 96afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda CharSequence numberFormattedLabel = null; 97afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda // Only show a label if the number is shown and it is not a SIP address. 989de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda if (!TextUtils.isEmpty(details.number) 999de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda && !PhoneNumberUtils.isUriNumber(details.number.toString())) { 1009de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda numberFormattedLabel = Phone.getTypeLabel(mResources, details.numberType, 1019de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda details.numberLabel); 102afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda } 103afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda 104b9256f81c0c65da98fb53b7d1879d71183d852b8Flavio Lerda final CharSequence nameText; 105b9256f81c0c65da98fb53b7d1879d71183d852b8Flavio Lerda final CharSequence numberText; 10688be53d18fc3ac194eabda8d811eaab68c3e40c8Flavio Lerda final CharSequence labelText; 107178eeebac88b352c131bd0315a99da16162c986eFlavio Lerda final CharSequence displayNumber = 108178eeebac88b352c131bd0315a99da16162c986eFlavio Lerda mPhoneNumberHelper.getDisplayNumber(details.number, details.formattedNumber); 1099de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda if (TextUtils.isEmpty(details.name)) { 110178eeebac88b352c131bd0315a99da16162c986eFlavio Lerda nameText = displayNumber; 111e4b156d0d3b69e8c8b32c8f601b051d7750a5f84Flavio Lerda if (TextUtils.isEmpty(details.geocode) 112e4b156d0d3b69e8c8b32c8f601b051d7750a5f84Flavio Lerda || mPhoneNumberHelper.isVoicemailNumber(details.number)) { 113be45e0f3d9ba9b0f842174d857a99edeadc0136eFlavio Lerda numberText = mResources.getString(R.string.call_log_empty_gecode); 114be45e0f3d9ba9b0f842174d857a99edeadc0136eFlavio Lerda } else { 11571fc6ec6598aeb8dcad797c05816bab91762e2b3Flavio Lerda numberText = details.geocode; 116be45e0f3d9ba9b0f842174d857a99edeadc0136eFlavio Lerda } 11788be53d18fc3ac194eabda8d811eaab68c3e40c8Flavio Lerda labelText = null; 118afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda } else { 1199de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda nameText = details.name; 12088be53d18fc3ac194eabda8d811eaab68c3e40c8Flavio Lerda numberText = displayNumber; 12188be53d18fc3ac194eabda8d811eaab68c3e40c8Flavio Lerda labelText = numberFormattedLabel; 122afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda } 123afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda 1247d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda views.nameView.setText(nameText); 125b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda views.numberView.setText(numberText); 12688be53d18fc3ac194eabda8d811eaab68c3e40c8Flavio Lerda views.labelView.setText(labelText); 12788be53d18fc3ac194eabda8d811eaab68c3e40c8Flavio Lerda views.labelView.setVisibility(TextUtils.isEmpty(labelText) ? View.GONE : View.VISIBLE); 128b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda } 129b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda 130d5678d3c22b7ab82b3840000704ce10162534d5dFlavio Lerda /** Sets the text of the header view for the details page of a phone call. */ 131d5678d3c22b7ab82b3840000704ce10162534d5dFlavio Lerda public void setCallDetailsHeader(TextView nameView, PhoneCallDetails details) { 132b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda final CharSequence nameText; 133b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda final CharSequence displayNumber = 134d5678d3c22b7ab82b3840000704ce10162534d5dFlavio Lerda mPhoneNumberHelper.getDisplayNumber(details.number, 135d5678d3c22b7ab82b3840000704ce10162534d5dFlavio Lerda mResources.getString(R.string.recentCalls_addToContact)); 136b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda if (TextUtils.isEmpty(details.name)) { 137b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda nameText = displayNumber; 138afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda } else { 139b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda nameText = details.name; 140afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda } 141405695664582b4989cffcf054bf1aceb83dec437Flavio Lerda 142b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda nameView.setText(nameText); 143afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda } 144696e8132c3cc9dd8ef2060a83c9d15f35c2b316bFlavio Lerda 145a0290a4baab4297303cab3664c7abfd548f2e301Makoto Onuki @NeededForTesting 1467d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda public void setCurrentTimeForTest(long currentTimeMillis) { 1477d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda mCurrentTimeMillisForTest = currentTimeMillis; 1487d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda } 1497d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda 1507d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda /** 1517d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda * Returns the current time in milliseconds since the epoch. 1527d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda * <p> 1537d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda * It can be injected in tests using {@link #setCurrentTimeForTest(long)}. 1547d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda */ 1557d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda private long getCurrentTimeMillis() { 1567d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda if (mCurrentTimeMillisForTest == null) { 1577d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda return System.currentTimeMillis(); 1587d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda } else { 1597d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda return mCurrentTimeMillisForTest; 1607d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda } 1617d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda } 162fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda 163fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda /** Sets the call count and date. */ 164fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda private void setCallCountAndDate(PhoneCallDetailsViews views, Integer callCount, 165fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda CharSequence dateText, Integer highlightColor) { 166fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda // Combine the count (if present) and the date. 167fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda final CharSequence text; 168fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda if (callCount != null) { 169fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda text = mResources.getString( 170fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda R.string.call_log_item_count_and_date, callCount.intValue(), dateText); 171fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda } else { 172fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda text = dateText; 173fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda } 174fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda 175fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda // Apply the highlight color if present. 176fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda final CharSequence formattedText; 177fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda if (highlightColor != null) { 178fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda formattedText = addBoldAndColor(text, highlightColor); 179fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda } else { 180fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda formattedText = text; 181fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda } 182fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda 183fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda views.callTypeAndDate.setText(formattedText); 184fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda } 185fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda 186fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda /** Creates a SpannableString for the given text which is bold and in the given color. */ 187fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda private CharSequence addBoldAndColor(CharSequence text, int color) { 188fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda int flags = Spanned.SPAN_INCLUSIVE_INCLUSIVE; 189fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda SpannableString result = new SpannableString(text); 190fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda result.setSpan(new StyleSpan(Typeface.BOLD), 0, text.length(), flags); 191fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda result.setSpan(new ForegroundColorSpan(color), 0, text.length(), flags); 192fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda return result; 193fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda } 194afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda} 195