From d3f6a6c56dec7d47bae1121ed1030f67c26736fe Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Thu, 25 Jun 2015 16:53:56 -0700 Subject: Cache repeated Telecom requests from call log. This improves call log scrolling performance. + Split "Wrapper" into a utility and a cache. + Use cache for repeated calls related to call logs. + In the process of fixing plumbing and typer, moved some phone call detail classes into the more appropriate call log package. + Update tests. Bug: 20524705 Change-Id: Ib8ee21e417c19f98f6474a5793416e8f99103b55 --- src/com/android/dialer/CallDetailActivity.java | 11 +- src/com/android/dialer/PhoneCallDetailsHelper.java | 267 -------------- src/com/android/dialer/PhoneCallDetailsViews.java | 73 ---- src/com/android/dialer/calllog/CallLogAdapter.java | 30 +- .../dialer/calllog/CallLogAsyncTaskUtil.java | 8 +- .../dialer/calllog/CallLogListItemHelper.java | 16 +- .../dialer/calllog/CallLogListItemViewHolder.java | 30 +- .../android/dialer/calllog/PhoneAccountUtils.java | 4 +- .../dialer/calllog/PhoneCallDetailsHelper.java | 267 ++++++++++++++ .../dialer/calllog/PhoneCallDetailsViews.java | 73 ++++ .../dialer/calllog/PhoneNumberDisplayUtil.java | 3 +- .../dialer/calllog/PhoneNumberUtilsWrapper.java | 131 ------- .../dialer/calllog/TelecomCallLogCache.java | 124 +++++++ src/com/android/dialer/util/PhoneNumberUtil.java | 95 +++++ .../android/dialer/PhoneCallDetailsHelperTest.java | 397 --------------------- .../dialer/calllog/CallLogListItemHelperTest.java | 28 +- .../dialer/calllog/PhoneCallDetailsHelperTest.java | 397 +++++++++++++++++++++ .../calllog/TestPhoneNumberUtilsWrapper.java | 38 -- .../dialer/calllog/TestTelecomCallLogCache.java | 38 ++ .../com/android/dialer/util/DialerUtilsTest.java | 2 +- 20 files changed, 1061 insertions(+), 971 deletions(-) delete mode 100644 src/com/android/dialer/PhoneCallDetailsHelper.java delete mode 100644 src/com/android/dialer/PhoneCallDetailsViews.java create mode 100644 src/com/android/dialer/calllog/PhoneCallDetailsHelper.java create mode 100644 src/com/android/dialer/calllog/PhoneCallDetailsViews.java delete mode 100644 src/com/android/dialer/calllog/PhoneNumberUtilsWrapper.java create mode 100644 src/com/android/dialer/calllog/TelecomCallLogCache.java create mode 100644 src/com/android/dialer/util/PhoneNumberUtil.java delete mode 100644 tests/src/com/android/dialer/PhoneCallDetailsHelperTest.java create mode 100644 tests/src/com/android/dialer/calllog/PhoneCallDetailsHelperTest.java delete mode 100644 tests/src/com/android/dialer/calllog/TestPhoneNumberUtilsWrapper.java create mode 100644 tests/src/com/android/dialer/calllog/TestTelecomCallLogCache.java diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java index b851372c0..734e78f46 100644 --- a/src/com/android/dialer/CallDetailActivity.java +++ b/src/com/android/dialer/CallDetailActivity.java @@ -57,9 +57,9 @@ import com.android.dialer.calllog.ContactInfo; import com.android.dialer.calllog.ContactInfoHelper; import com.android.dialer.calllog.PhoneAccountUtils; import com.android.dialer.calllog.PhoneNumberDisplayUtil; -import com.android.dialer.calllog.PhoneNumberUtilsWrapper; -import com.android.dialer.util.IntentUtil; import com.android.dialer.util.DialerUtils; +import com.android.dialer.util.IntentUtil; +import com.android.dialer.util.PhoneNumberUtil; import com.android.dialer.util.TelecomUtil; import java.util.List; @@ -116,11 +116,10 @@ public class CallDetailActivity extends Activity // Cache the details about the phone number. final boolean canPlaceCallsTo = - PhoneNumberUtilsWrapper.canPlaceCallsTo(mNumber, numberPresentation); - final PhoneNumberUtilsWrapper phoneUtils = new PhoneNumberUtilsWrapper(mContext); + PhoneNumberUtil.canPlaceCallsTo(mNumber, numberPresentation); mIsVoicemailNumber = - phoneUtils.isVoicemailNumber(accountHandle, mNumber); - final boolean isSipNumber = PhoneNumberUtilsWrapper.isSipNumber(mNumber); + PhoneNumberUtil.isVoicemailNumber(mContext, accountHandle, mNumber); + final boolean isSipNumber = PhoneNumberUtil.isSipNumber(mNumber); final CharSequence callLocationOrType = getNumberTypeOrLocation(firstDetails); diff --git a/src/com/android/dialer/PhoneCallDetailsHelper.java b/src/com/android/dialer/PhoneCallDetailsHelper.java deleted file mode 100644 index 2dc0810e8..000000000 --- a/src/com/android/dialer/PhoneCallDetailsHelper.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dialer; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.provider.CallLog; -import android.provider.CallLog.Calls; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.telecom.PhoneAccount; -import android.text.TextUtils; -import android.text.format.DateUtils; -import android.view.View; -import android.widget.TextView; - -import com.android.contacts.common.testing.NeededForTesting; -import com.android.contacts.common.util.PhoneNumberHelper; -import com.android.dialer.calllog.ContactInfo; -import com.android.dialer.calllog.PhoneAccountUtils; -import com.android.dialer.calllog.PhoneNumberUtilsWrapper; -import com.android.dialer.util.DialerUtils; - -import com.google.common.collect.Lists; - -import java.util.ArrayList; - -/** - * Helper class to fill in the views in {@link PhoneCallDetailsViews}. - */ -public class PhoneCallDetailsHelper { - /** The maximum number of icons will be shown to represent the call types in a group. */ - private static final int MAX_CALL_TYPE_ICONS = 3; - - private final Context mContext; - private final Resources mResources; - /** The injected current time in milliseconds since the epoch. Used only by tests. */ - private Long mCurrentTimeMillisForTest; - // Helper classes. - private final PhoneNumberUtilsWrapper mPhoneNumberUtilsWrapper; - - /** - * List of items to be concatenated together for accessibility descriptions - */ - private ArrayList mDescriptionItems = Lists.newArrayList(); - - /** - * Creates a new instance of the helper. - *

- * Generally you should have a single instance of this helper in any context. - * - * @param resources used to look up strings - */ - public PhoneCallDetailsHelper(Context context, Resources resources, - PhoneNumberUtilsWrapper phoneUtils) { - mContext = context; - mResources = resources; - mPhoneNumberUtilsWrapper = phoneUtils; - } - - /** Fills the call details views with content. */ - public void setPhoneCallDetails(PhoneCallDetailsViews views, PhoneCallDetails details) { - // Display up to a given number of icons. - views.callTypeIcons.clear(); - int count = details.callTypes.length; - boolean isVoicemail = false; - for (int index = 0; index < count && index < MAX_CALL_TYPE_ICONS; ++index) { - views.callTypeIcons.add(details.callTypes[index]); - if (index == 0) { - isVoicemail = details.callTypes[index] == Calls.VOICEMAIL_TYPE; - } - } - - // Show the video icon if the call had video enabled. - views.callTypeIcons.setShowVideo( - (details.features & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO); - views.callTypeIcons.requestLayout(); - views.callTypeIcons.setVisibility(View.VISIBLE); - - // Show the total call count only if there are more than the maximum number of icons. - final Integer callCount; - if (count > MAX_CALL_TYPE_ICONS) { - callCount = count; - } else { - callCount = null; - } - - CharSequence callLocationAndDate = getCallLocationAndDate(details); - - // Set the call count, location and date. - setCallCountAndDate(views, callCount, callLocationAndDate); - - // Set the account label if it exists. - String accountLabel = PhoneAccountUtils.getAccountLabel(mContext, details.accountHandle); - - if (accountLabel != null) { - views.callAccountLabel.setVisibility(View.VISIBLE); - views.callAccountLabel.setText(accountLabel); - int color = PhoneAccountUtils.getAccountColor(mContext, details.accountHandle); - if (color == PhoneAccount.NO_HIGHLIGHT_COLOR) { - int defaultColor = R.color.dialtacts_secondary_text_color; - views.callAccountLabel.setTextColor(mContext.getResources().getColor(defaultColor)); - } else { - views.callAccountLabel.setTextColor(color); - } - } else { - views.callAccountLabel.setVisibility(View.GONE); - } - - final CharSequence nameText; - final CharSequence displayNumber = details.displayNumber; - if (TextUtils.isEmpty(details.name)) { - nameText = displayNumber; - // We have a real phone number as "nameView" so make it always LTR - views.nameView.setTextDirection(View.TEXT_DIRECTION_LTR); - } else { - nameText = details.name; - } - - views.nameView.setText(nameText); - - if (isVoicemail && !TextUtils.isEmpty(details.transcription)) { - views.voicemailTranscriptionView.setText(details.transcription); - views.voicemailTranscriptionView.setVisibility(View.VISIBLE); - } else { - views.voicemailTranscriptionView.setText(null); - views.voicemailTranscriptionView.setVisibility(View.GONE); - } - - // Bold if not read - Typeface typeface = details.isRead ? Typeface.SANS_SERIF : Typeface.DEFAULT_BOLD; - views.nameView.setTypeface(typeface); - views.voicemailTranscriptionView.setTypeface(typeface); - views.callLocationAndDate.setTypeface(typeface); - } - - /** - * Builds a string containing the call location and date. - * - * @param details The call details. - * @return The call location and date string. - */ - private CharSequence getCallLocationAndDate(PhoneCallDetails details) { - mDescriptionItems.clear(); - - // Get type of call (ie mobile, home, etc) if known, or the caller's location. - CharSequence callTypeOrLocation = getCallTypeOrLocation(details); - - // Only add the call type or location if its not empty. It will be empty for unknown - // callers. - if (!TextUtils.isEmpty(callTypeOrLocation)) { - mDescriptionItems.add(callTypeOrLocation); - } - // The date of this call, relative to the current time. - mDescriptionItems.add(getCallDate(details)); - - // Create a comma separated list from the call type or location, and call date. - return DialerUtils.join(mResources, mDescriptionItems); - } - - /** - * For a call, if there is an associated contact for the caller, return the known call type - * (e.g. mobile, home, work). If there is no associated contact, attempt to use the caller's - * location if known. - * @param details Call details to use. - * @return Type of call (mobile/home) if known, or the location of the caller (if known). - */ - public CharSequence getCallTypeOrLocation(PhoneCallDetails details) { - CharSequence numberFormattedLabel = null; - // Only show a label if the number is shown and it is not a SIP address. - if (!TextUtils.isEmpty(details.number) - && !PhoneNumberHelper.isUriNumber(details.number.toString()) - && !mPhoneNumberUtilsWrapper.isVoicemailNumber(details.accountHandle, - details.number)) { - - if (TextUtils.isEmpty(details.name) && !TextUtils.isEmpty(details.geocode)) { - numberFormattedLabel = details.geocode; - } else if (!(details.numberType == Phone.TYPE_CUSTOM - && TextUtils.isEmpty(details.numberLabel))) { - // Get type label only if it will not be "Custom" because of an empty number label. - numberFormattedLabel = Phone.getTypeLabel( - mResources, details.numberType, details.numberLabel); - } - } - - if (!TextUtils.isEmpty(details.name) && TextUtils.isEmpty(numberFormattedLabel)) { - numberFormattedLabel = details.displayNumber; - } - return numberFormattedLabel; - } - - /** - * Get the call date/time of the call, relative to the current time. - * e.g. 3 minutes ago - * @param details Call details to use. - * @return String representing when the call occurred. - */ - public CharSequence getCallDate(PhoneCallDetails details) { - return DateUtils.getRelativeTimeSpanString(details.date, - getCurrentTimeMillis(), - DateUtils.MINUTE_IN_MILLIS, - DateUtils.FORMAT_ABBREV_RELATIVE); - } - - /** Sets the text of the header view for the details page of a phone call. */ - @NeededForTesting - public void setCallDetailsHeader(TextView nameView, PhoneCallDetails details) { - final CharSequence nameText; - if (!TextUtils.isEmpty(details.name)) { - nameText = details.name; - } else if (!TextUtils.isEmpty(details.displayNumber)) { - nameText = details.displayNumber; - } else { - nameText = mResources.getString(R.string.unknown); - } - - nameView.setText(nameText); - } - - @NeededForTesting - public void setCurrentTimeForTest(long currentTimeMillis) { - mCurrentTimeMillisForTest = currentTimeMillis; - } - - /** - * Returns the current time in milliseconds since the epoch. - *

- * It can be injected in tests using {@link #setCurrentTimeForTest(long)}. - */ - private long getCurrentTimeMillis() { - if (mCurrentTimeMillisForTest == null) { - return System.currentTimeMillis(); - } else { - return mCurrentTimeMillisForTest; - } - } - - /** Sets the call count and date. */ - private void setCallCountAndDate(PhoneCallDetailsViews views, Integer callCount, - CharSequence dateText) { - // Combine the count (if present) and the date. - final CharSequence text; - if (callCount != null) { - text = mResources.getString( - R.string.call_log_item_count_and_date, callCount.intValue(), dateText); - } else { - text = dateText; - } - - views.callLocationAndDate.setText(text); - } -} diff --git a/src/com/android/dialer/PhoneCallDetailsViews.java b/src/com/android/dialer/PhoneCallDetailsViews.java deleted file mode 100644 index 05026d6ee..000000000 --- a/src/com/android/dialer/PhoneCallDetailsViews.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dialer; - -import android.content.Context; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -import com.android.dialer.calllog.CallTypeIconsView; - -/** - * Encapsulates the views that are used to display the details of a phone call in the call log. - */ -public final class PhoneCallDetailsViews { - public final TextView nameView; - public final View callTypeView; - public final CallTypeIconsView callTypeIcons; - public final TextView callLocationAndDate; - public final TextView voicemailTranscriptionView; - public final TextView callAccountLabel; - - private PhoneCallDetailsViews(TextView nameView, View callTypeView, - CallTypeIconsView callTypeIcons, TextView callLocationAndDate, - TextView voicemailTranscriptionView, TextView callAccountLabel) { - this.nameView = nameView; - this.callTypeView = callTypeView; - this.callTypeIcons = callTypeIcons; - this.callLocationAndDate = callLocationAndDate; - this.voicemailTranscriptionView = voicemailTranscriptionView; - this.callAccountLabel = callAccountLabel; - } - - /** - * Create a new instance by extracting the elements from the given view. - *

- * The view should contain three text views with identifiers {@code R.id.name}, - * {@code R.id.date}, and {@code R.id.number}, and a linear layout with identifier - * {@code R.id.call_types}. - */ - public static PhoneCallDetailsViews fromView(View view) { - return new PhoneCallDetailsViews((TextView) view.findViewById(R.id.name), - view.findViewById(R.id.call_type), - (CallTypeIconsView) view.findViewById(R.id.call_type_icons), - (TextView) view.findViewById(R.id.call_location_and_date), - (TextView) view.findViewById(R.id.voicemail_transcription), - (TextView) view.findViewById(R.id.call_account_label)); - } - - public static PhoneCallDetailsViews createForTest(Context context) { - return new PhoneCallDetailsViews( - new TextView(context), - new View(context), - new CallTypeIconsView(context), - new TextView(context), - new TextView(context), - new TextView(context)); - } -} diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java index 2ba257a3b..bb776d29e 100644 --- a/src/com/android/dialer/calllog/CallLogAdapter.java +++ b/src/com/android/dialer/calllog/CallLogAdapter.java @@ -42,10 +42,10 @@ import android.view.accessibility.AccessibilityEvent; import com.android.contacts.common.util.PermissionsUtil; import com.android.dialer.PhoneCallDetails; -import com.android.dialer.PhoneCallDetailsHelper; import com.android.dialer.R; import com.android.dialer.contactinfo.ContactInfoCache; import com.android.dialer.contactinfo.ContactInfoCache.OnContactInfoChangedListener; +import com.android.dialer.util.PhoneNumberUtil; import com.android.dialer.voicemail.VoicemailPlaybackPresenter; import com.google.common.annotations.VisibleForTesting; @@ -123,10 +123,11 @@ public class CallLogAdapter extends GroupingListAdapter private boolean mShowPromoCard = false; /** Instance of helper class for managing views. */ - private final CallLogListItemHelper mCallLogViewsHelper; + private final CallLogListItemHelper mCallLogListItemHelper; + + /** Cache for repeated requests to TelecomManager. */ + protected final TelecomCallLogCache mTelecomCallLogCache; - /** Helper to access Telephony phone number utils class */ - protected final PhoneNumberUtilsWrapper mPhoneNumberUtilsWrapper; /** Helper to group call log entries. */ private final CallLogGroupBuilder mCallLogGroupBuilder; @@ -256,10 +257,11 @@ public class CallLogAdapter extends GroupingListAdapter Resources resources = mContext.getResources(); CallTypeHelper callTypeHelper = new CallTypeHelper(resources); - mPhoneNumberUtilsWrapper = new PhoneNumberUtilsWrapper(mContext); + mTelecomCallLogCache = new TelecomCallLogCache(mContext); PhoneCallDetailsHelper phoneCallDetailsHelper = - new PhoneCallDetailsHelper(mContext, resources, mPhoneNumberUtilsWrapper); - mCallLogViewsHelper = new CallLogListItemHelper(phoneCallDetailsHelper, resources); + new PhoneCallDetailsHelper(mContext, resources, mTelecomCallLogCache); + mCallLogListItemHelper = + new CallLogListItemHelper(phoneCallDetailsHelper, resources, mTelecomCallLogCache); mCallLogGroupBuilder = new CallLogGroupBuilder(this); mPrefs = PreferenceManager.getDefaultSharedPreferences(context); maybeShowVoicemailPromoCard(); @@ -329,6 +331,7 @@ public class CallLogAdapter extends GroupingListAdapter public void pauseCache() { mContactInfoCache.stop(); + mTelecomCallLogCache.reset(); } @Override @@ -359,8 +362,8 @@ public class CallLogAdapter extends GroupingListAdapter view, mContext, mExpandCollapseListener, - mPhoneNumberUtilsWrapper, - mCallLogViewsHelper, + mTelecomCallLogCache, + mCallLogListItemHelper, mVoicemailPlaybackPresenter); viewHolder.callLogEntryView.setTag(viewHolder); @@ -432,14 +435,13 @@ public class CallLogAdapter extends GroupingListAdapter final String countryIso = c.getString(CallLogQuery.COUNTRY_ISO); final ContactInfo cachedContactInfo = mContactInfoHelper.getContactInfo(c); final boolean isVoicemailNumber = - mPhoneNumberUtilsWrapper.isVoicemailNumber(accountHandle, number); + mTelecomCallLogCache.isVoicemailNumber(accountHandle, number); // Note: Binding of the action buttons is done as required in configureActionViews when the // user expands the actions ViewStub. ContactInfo info = ContactInfo.EMPTY; - if (PhoneNumberUtilsWrapper.canPlaceCallsTo(number, numberPresentation) - && !isVoicemailNumber) { + if (PhoneNumberUtil.canPlaceCallsTo(number, numberPresentation) && !isVoicemailNumber) { // Lookup contacts with this number info = mContactInfoCache.getValue(number, countryIso, cachedContactInfo); } @@ -499,7 +501,7 @@ public class CallLogAdapter extends GroupingListAdapter views.dayGroupHeader.setVisibility(View.GONE); } - mCallLogViewsHelper.setPhoneCallDetails(mContext, views, details); + mCallLogListItemHelper.setPhoneCallDetails(views, details); if (mCurrentlyExpandedRowId == views.rowId) { // In case ViewHolders were added/removed, update the expanded position if the rowIds @@ -522,7 +524,7 @@ public class CallLogAdapter extends GroupingListAdapter views.setPhoto(info.photoId, info.photoUri, info.lookupUri, nameForDefaultImage, isVoicemailNumber, mContactInfoHelper.isBusiness(info.sourceType)); - mCallLogViewsHelper.setPhoneCallDetails(mContext, views, details); + mCallLogListItemHelper.setPhoneCallDetails(views, details); // Listen for the first draw if (mViewTreeObserver == null) { diff --git a/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java b/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java index 812e1a77a..1becc89af 100644 --- a/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java +++ b/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java @@ -32,6 +32,7 @@ import com.android.contacts.common.GeoUtil; import com.android.dialer.PhoneCallDetails; import com.android.dialer.util.AsyncTaskExecutor; import com.android.dialer.util.AsyncTaskExecutors; +import com.android.dialer.util.PhoneNumberUtil; import com.android.dialer.util.TelecomUtil; import com.google.common.annotations.VisibleForTesting; @@ -151,12 +152,9 @@ public class CallLogAsyncTaskUtil { // If this is not a regular number, there is no point in looking it up in the contacts. ContactInfoHelper contactInfoHelper = new ContactInfoHelper(context, GeoUtil.getCurrentCountryIso(context)); - PhoneNumberUtilsWrapper phoneNumberUtilsWrapper = - new PhoneNumberUtilsWrapper(context); - boolean isVoicemail = phoneNumberUtilsWrapper.isVoicemailNumber(accountHandle, number); + boolean isVoicemail = PhoneNumberUtil.isVoicemailNumber(context, accountHandle, number); boolean shouldLookupNumber = - PhoneNumberUtilsWrapper.canPlaceCallsTo(number, numberPresentation) - && !isVoicemail; + PhoneNumberUtil.canPlaceCallsTo(number, numberPresentation) && !isVoicemail; ContactInfo info = shouldLookupNumber ? contactInfoHelper.lookupNumber(number, countryIso) : ContactInfo.EMPTY; diff --git a/src/com/android/dialer/calllog/CallLogListItemHelper.java b/src/com/android/dialer/calllog/CallLogListItemHelper.java index d08810706..1c8e397e4 100644 --- a/src/com/android/dialer/calllog/CallLogListItemHelper.java +++ b/src/com/android/dialer/calllog/CallLogListItemHelper.java @@ -24,7 +24,6 @@ import android.text.TextUtils; import android.util.Log; import com.android.dialer.PhoneCallDetails; -import com.android.dialer.PhoneCallDetailsHelper; import com.android.dialer.R; /** @@ -37,6 +36,7 @@ import com.android.dialer.R; private final PhoneCallDetailsHelper mPhoneCallDetailsHelper; /** Resources to look up strings. */ private final Resources mResources; + private final TelecomCallLogCache mTelecomCallLogCache; /** * Creates a new helper instance. @@ -45,9 +45,12 @@ import com.android.dialer.R; * @param phoneNumberHelper used to process phone number */ public CallLogListItemHelper( - PhoneCallDetailsHelper phoneCallDetailsHelper, Resources resources) { + PhoneCallDetailsHelper phoneCallDetailsHelper, + Resources resources, + TelecomCallLogCache telecomCallLogCache) { mPhoneCallDetailsHelper = phoneCallDetailsHelper; mResources = resources; + mTelecomCallLogCache = telecomCallLogCache; } /** @@ -58,14 +61,15 @@ import com.android.dialer.R; * @param details the details of a phone call needed to fill in the data */ public void setPhoneCallDetails( - Context context, CallLogListItemViewHolder views, PhoneCallDetails details) { + CallLogListItemViewHolder views, + PhoneCallDetails details) { mPhoneCallDetailsHelper.setPhoneCallDetails(views.phoneCallDetailsViews, details); // Set the accessibility text for the contact badge views.quickContactView.setContentDescription(getContactBadgeDescription(details)); // Set the primary action accessibility description - views.primaryActionView.setContentDescription(getCallDescription(context, details)); + views.primaryActionView.setContentDescription(getCallDescription(details)); // Cache name or number of caller. Used when setting the content descriptions of buttons // when the actions ViewStub is inflated. @@ -151,7 +155,7 @@ import com.android.dialer.R; * @param details Details of call. * @return Return call action description. */ - public CharSequence getCallDescription(Context context, PhoneCallDetails details) { + public CharSequence getCallDescription(PhoneCallDetails details) { int lastCallType = getLastCallType(details.callTypes); boolean isVoiceMail = lastCallType == Calls.VOICEMAIL_TYPE; @@ -183,7 +187,7 @@ import com.android.dialer.R; } int stringID = getCallDescriptionStringID(details.callTypes); - String accountLabel = PhoneAccountUtils.getAccountLabel(context, details.accountHandle); + String accountLabel = mTelecomCallLogCache.getAccountLabel(details.accountHandle); // Use chosen string resource to build up the message. CharSequence onAccountLabel = accountLabel == null diff --git a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java index f54720b31..361e1c7a3 100644 --- a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java +++ b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java @@ -39,11 +39,10 @@ import com.android.contacts.common.ContactPhotoManager; import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest; import com.android.contacts.common.testing.NeededForTesting; import com.android.contacts.common.util.UriUtils; -import com.android.dialer.PhoneCallDetailsHelper; -import com.android.dialer.PhoneCallDetailsViews; import com.android.dialer.R; import com.android.dialer.calllog.CallLogAsyncTaskUtil; import com.android.dialer.util.DialerUtils; +import com.android.dialer.util.PhoneNumberUtil; import com.android.dialer.voicemail.VoicemailPlaybackPresenter; import com.android.dialer.voicemail.VoicemailPlaybackLayout; @@ -139,7 +138,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder private static final int VOICEMAIL_TRANSCRIPTION_MAX_LINES = 10; private final Context mContext; - private final PhoneNumberUtilsWrapper mPhoneNumberUtilsWrapper; + private final TelecomCallLogCache mTelecomCallLogCache; private final CallLogListItemHelper mCallLogListItemHelper; private final VoicemailPlaybackPresenter mVoicemailPlaybackPresenter; @@ -151,7 +150,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder private CallLogListItemViewHolder( Context context, View.OnClickListener expandCollapseListener, - PhoneNumberUtilsWrapper phoneNumberUtilsWrapper, + TelecomCallLogCache telecomCallLogCache, CallLogListItemHelper callLogListItemHelper, VoicemailPlaybackPresenter voicemailPlaybackPresenter, View rootView, @@ -165,7 +164,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder mContext = context; mExpandCollapseListener = expandCollapseListener; - mPhoneNumberUtilsWrapper = phoneNumberUtilsWrapper; + mTelecomCallLogCache = telecomCallLogCache; mCallLogListItemHelper = callLogListItemHelper; mVoicemailPlaybackPresenter = voicemailPlaybackPresenter; @@ -194,14 +193,14 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder View view, Context context, View.OnClickListener expandCollapseListener, - PhoneNumberUtilsWrapper phoneNumberUtilsWrapper, + TelecomCallLogCache telecomCallLogCache, CallLogListItemHelper callLogListItemHelper, VoicemailPlaybackPresenter voicemailPlaybackPresenter) { return new CallLogListItemViewHolder( context, expandCollapseListener, - phoneNumberUtilsWrapper, + telecomCallLogCache, callLogListItemHelper, voicemailPlaybackPresenter, view, @@ -263,11 +262,11 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder } else { // Treat as normal list item; show call button, if possible. boolean canPlaceCallToNumber = - PhoneNumberUtilsWrapper.canPlaceCallsTo(number, numberPresentation); + PhoneNumberUtil.canPlaceCallsTo(number, numberPresentation); if (canPlaceCallToNumber) { boolean isVoicemailNumber = - mPhoneNumberUtilsWrapper.isVoicemailNumber(accountHandle, number); + mTelecomCallLogCache.isVoicemailNumber(accountHandle, number); if (isVoicemailNumber) { // Call to generic voicemail number, in case there are multiple accounts. primaryActionButtonView.setTag( @@ -294,8 +293,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder * buttons. */ private void bindActionButtons() { - boolean canPlaceCallToNumber = - PhoneNumberUtilsWrapper.canPlaceCallsTo(number, numberPresentation); + boolean canPlaceCallToNumber = PhoneNumberUtil.canPlaceCallsTo(number, numberPresentation); if (!TextUtils.isEmpty(voicemailUri) && canPlaceCallToNumber) { callButtonView.setTag(IntentProvider.getReturnCallIntentProvider(number)); @@ -309,7 +307,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder } // If one of the calls had video capabilities, show the video call button. - if (CallUtil.isVideoEnabled(mContext) && canPlaceCallToNumber && + if (mTelecomCallLogCache.isVideoEnabled() && canPlaceCallToNumber && phoneCallDetailsViews.callTypeIcons.isVideoShown()) { videoCallButtonView.setTag(IntentProvider.getReturnVideoCallIntentProvider(number)); videoCallButtonView.setVisibility(View.VISIBLE); @@ -440,15 +438,15 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder @NeededForTesting public static CallLogListItemViewHolder createForTest(Context context) { Resources resources = context.getResources(); - PhoneNumberUtilsWrapper phoneNumberUtilsWrapper = new PhoneNumberUtilsWrapper(context); + TelecomCallLogCache telecomCallLogCache = new TelecomCallLogCache(context); PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper( - context, resources, phoneNumberUtilsWrapper); + context, resources, telecomCallLogCache); CallLogListItemViewHolder viewHolder = new CallLogListItemViewHolder( context, null /* expandCollapseListener */, - phoneNumberUtilsWrapper, - new CallLogListItemHelper(phoneCallDetailsHelper, resources), + telecomCallLogCache, + new CallLogListItemHelper(phoneCallDetailsHelper, resources, telecomCallLogCache), null /* voicemailPlaybackPresenter */, new View(context), new QuickContactBadge(context), diff --git a/src/com/android/dialer/calllog/PhoneAccountUtils.java b/src/com/android/dialer/calllog/PhoneAccountUtils.java index d63b940e7..7eaa523f4 100644 --- a/src/com/android/dialer/calllog/PhoneAccountUtils.java +++ b/src/com/android/dialer/calllog/PhoneAccountUtils.java @@ -27,7 +27,7 @@ import java.util.ArrayList; import java.util.List; /** - * Methods to help extract {@code PhoneAccount} information from database and Telecomm sources + * Methods to help extract {@code PhoneAccount} information from database and Telecomm sources. */ public class PhoneAccountUtils { /** @@ -87,7 +87,7 @@ public class PhoneAccountUtils { * Retrieve the account metadata, but if the account does not exist or the device has only a * single registered and enabled account, return null. */ - private static PhoneAccount getAccountOrNull(Context context, + static PhoneAccount getAccountOrNull(Context context, PhoneAccountHandle accountHandle) { TelecomManager telecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); diff --git a/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java b/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java new file mode 100644 index 000000000..df5fe0606 --- /dev/null +++ b/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.dialer.calllog; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.provider.CallLog; +import android.provider.CallLog.Calls; +import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.telecom.PhoneAccount; +import android.text.TextUtils; +import android.text.format.DateUtils; +import android.view.View; +import android.widget.TextView; + +import com.android.contacts.common.testing.NeededForTesting; +import com.android.contacts.common.util.PhoneNumberHelper; +import com.android.dialer.PhoneCallDetails; +import com.android.dialer.R; +import com.android.dialer.util.DialerUtils; +import com.android.dialer.util.PhoneNumberUtil; + +import com.google.common.collect.Lists; + +import java.util.ArrayList; + +/** + * Helper class to fill in the views in {@link PhoneCallDetailsViews}. + */ +public class PhoneCallDetailsHelper { + /** The maximum number of icons will be shown to represent the call types in a group. */ + private static final int MAX_CALL_TYPE_ICONS = 3; + + private final Context mContext; + private final Resources mResources; + /** The injected current time in milliseconds since the epoch. Used only by tests. */ + private Long mCurrentTimeMillisForTest; + private final TelecomCallLogCache mTelecomCallLogCache; + + /** + * List of items to be concatenated together for accessibility descriptions + */ + private ArrayList mDescriptionItems = Lists.newArrayList(); + + /** + * Creates a new instance of the helper. + *

+ * Generally you should have a single instance of this helper in any context. + * + * @param resources used to look up strings + */ + public PhoneCallDetailsHelper( + Context context, + Resources resources, + TelecomCallLogCache telecomCallLogCache) { + mContext = context; + mResources = resources; + mTelecomCallLogCache = telecomCallLogCache; + } + + /** Fills the call details views with content. */ + public void setPhoneCallDetails(PhoneCallDetailsViews views, PhoneCallDetails details) { + // Display up to a given number of icons. + views.callTypeIcons.clear(); + int count = details.callTypes.length; + boolean isVoicemail = false; + for (int index = 0; index < count && index < MAX_CALL_TYPE_ICONS; ++index) { + views.callTypeIcons.add(details.callTypes[index]); + if (index == 0) { + isVoicemail = details.callTypes[index] == Calls.VOICEMAIL_TYPE; + } + } + + // Show the video icon if the call had video enabled. + views.callTypeIcons.setShowVideo( + (details.features & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO); + views.callTypeIcons.requestLayout(); + views.callTypeIcons.setVisibility(View.VISIBLE); + + // Show the total call count only if there are more than the maximum number of icons. + final Integer callCount; + if (count > MAX_CALL_TYPE_ICONS) { + callCount = count; + } else { + callCount = null; + } + + CharSequence callLocationAndDate = getCallLocationAndDate(details); + + // Set the call count, location and date. + setCallCountAndDate(views, callCount, callLocationAndDate); + + // Set the account label if it exists. + String accountLabel = mTelecomCallLogCache.getAccountLabel(details.accountHandle); + + if (accountLabel != null) { + views.callAccountLabel.setVisibility(View.VISIBLE); + views.callAccountLabel.setText(accountLabel); + int color = PhoneAccountUtils.getAccountColor(mContext, details.accountHandle); + if (color == PhoneAccount.NO_HIGHLIGHT_COLOR) { + int defaultColor = R.color.dialtacts_secondary_text_color; + views.callAccountLabel.setTextColor(mContext.getResources().getColor(defaultColor)); + } else { + views.callAccountLabel.setTextColor(color); + } + } else { + views.callAccountLabel.setVisibility(View.GONE); + } + + final CharSequence nameText; + final CharSequence displayNumber = details.displayNumber; + if (TextUtils.isEmpty(details.name)) { + nameText = displayNumber; + // We have a real phone number as "nameView" so make it always LTR + views.nameView.setTextDirection(View.TEXT_DIRECTION_LTR); + } else { + nameText = details.name; + } + + views.nameView.setText(nameText); + + if (isVoicemail && !TextUtils.isEmpty(details.transcription)) { + views.voicemailTranscriptionView.setText(details.transcription); + views.voicemailTranscriptionView.setVisibility(View.VISIBLE); + } else { + views.voicemailTranscriptionView.setText(null); + views.voicemailTranscriptionView.setVisibility(View.GONE); + } + + // Bold if not read + Typeface typeface = details.isRead ? Typeface.SANS_SERIF : Typeface.DEFAULT_BOLD; + views.nameView.setTypeface(typeface); + views.voicemailTranscriptionView.setTypeface(typeface); + views.callLocationAndDate.setTypeface(typeface); + } + + /** + * Builds a string containing the call location and date. + * + * @param details The call details. + * @return The call location and date string. + */ + private CharSequence getCallLocationAndDate(PhoneCallDetails details) { + mDescriptionItems.clear(); + + // Get type of call (ie mobile, home, etc) if known, or the caller's location. + CharSequence callTypeOrLocation = getCallTypeOrLocation(details); + + // Only add the call type or location if its not empty. It will be empty for unknown + // callers. + if (!TextUtils.isEmpty(callTypeOrLocation)) { + mDescriptionItems.add(callTypeOrLocation); + } + // The date of this call, relative to the current time. + mDescriptionItems.add(getCallDate(details)); + + // Create a comma separated list from the call type or location, and call date. + return DialerUtils.join(mResources, mDescriptionItems); + } + + /** + * For a call, if there is an associated contact for the caller, return the known call type + * (e.g. mobile, home, work). If there is no associated contact, attempt to use the caller's + * location if known. + * @param details Call details to use. + * @return Type of call (mobile/home) if known, or the location of the caller (if known). + */ + public CharSequence getCallTypeOrLocation(PhoneCallDetails details) { + CharSequence numberFormattedLabel = null; + // Only show a label if the number is shown and it is not a SIP address. + if (!TextUtils.isEmpty(details.number) + && !PhoneNumberHelper.isUriNumber(details.number.toString()) + && !mTelecomCallLogCache.isVoicemailNumber(details.accountHandle, details.number)) { + + if (TextUtils.isEmpty(details.name) && !TextUtils.isEmpty(details.geocode)) { + numberFormattedLabel = details.geocode; + } else if (!(details.numberType == Phone.TYPE_CUSTOM + && TextUtils.isEmpty(details.numberLabel))) { + // Get type label only if it will not be "Custom" because of an empty number label. + numberFormattedLabel = Phone.getTypeLabel( + mResources, details.numberType, details.numberLabel); + } + } + + if (!TextUtils.isEmpty(details.name) && TextUtils.isEmpty(numberFormattedLabel)) { + numberFormattedLabel = details.displayNumber; + } + return numberFormattedLabel; + } + + /** + * Get the call date/time of the call, relative to the current time. + * e.g. 3 minutes ago + * @param details Call details to use. + * @return String representing when the call occurred. + */ + public CharSequence getCallDate(PhoneCallDetails details) { + return DateUtils.getRelativeTimeSpanString(details.date, + getCurrentTimeMillis(), + DateUtils.MINUTE_IN_MILLIS, + DateUtils.FORMAT_ABBREV_RELATIVE); + } + + /** Sets the text of the header view for the details page of a phone call. */ + @NeededForTesting + public void setCallDetailsHeader(TextView nameView, PhoneCallDetails details) { + final CharSequence nameText; + if (!TextUtils.isEmpty(details.name)) { + nameText = details.name; + } else if (!TextUtils.isEmpty(details.displayNumber)) { + nameText = details.displayNumber; + } else { + nameText = mResources.getString(R.string.unknown); + } + + nameView.setText(nameText); + } + + @NeededForTesting + public void setCurrentTimeForTest(long currentTimeMillis) { + mCurrentTimeMillisForTest = currentTimeMillis; + } + + /** + * Returns the current time in milliseconds since the epoch. + *

+ * It can be injected in tests using {@link #setCurrentTimeForTest(long)}. + */ + private long getCurrentTimeMillis() { + if (mCurrentTimeMillisForTest == null) { + return System.currentTimeMillis(); + } else { + return mCurrentTimeMillisForTest; + } + } + + /** Sets the call count and date. */ + private void setCallCountAndDate(PhoneCallDetailsViews views, Integer callCount, + CharSequence dateText) { + // Combine the count (if present) and the date. + final CharSequence text; + if (callCount != null) { + text = mResources.getString( + R.string.call_log_item_count_and_date, callCount.intValue(), dateText); + } else { + text = dateText; + } + + views.callLocationAndDate.setText(text); + } +} diff --git a/src/com/android/dialer/calllog/PhoneCallDetailsViews.java b/src/com/android/dialer/calllog/PhoneCallDetailsViews.java new file mode 100644 index 000000000..94f4411b0 --- /dev/null +++ b/src/com/android/dialer/calllog/PhoneCallDetailsViews.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.dialer.calllog; + +import android.content.Context; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.android.dialer.R; + +/** + * Encapsulates the views that are used to display the details of a phone call in the call log. + */ +public final class PhoneCallDetailsViews { + public final TextView nameView; + public final View callTypeView; + public final CallTypeIconsView callTypeIcons; + public final TextView callLocationAndDate; + public final TextView voicemailTranscriptionView; + public final TextView callAccountLabel; + + private PhoneCallDetailsViews(TextView nameView, View callTypeView, + CallTypeIconsView callTypeIcons, TextView callLocationAndDate, + TextView voicemailTranscriptionView, TextView callAccountLabel) { + this.nameView = nameView; + this.callTypeView = callTypeView; + this.callTypeIcons = callTypeIcons; + this.callLocationAndDate = callLocationAndDate; + this.voicemailTranscriptionView = voicemailTranscriptionView; + this.callAccountLabel = callAccountLabel; + } + + /** + * Create a new instance by extracting the elements from the given view. + *

+ * The view should contain three text views with identifiers {@code R.id.name}, + * {@code R.id.date}, and {@code R.id.number}, and a linear layout with identifier + * {@code R.id.call_types}. + */ + public static PhoneCallDetailsViews fromView(View view) { + return new PhoneCallDetailsViews((TextView) view.findViewById(R.id.name), + view.findViewById(R.id.call_type), + (CallTypeIconsView) view.findViewById(R.id.call_type_icons), + (TextView) view.findViewById(R.id.call_location_and_date), + (TextView) view.findViewById(R.id.voicemail_transcription), + (TextView) view.findViewById(R.id.call_account_label)); + } + + public static PhoneCallDetailsViews createForTest(Context context) { + return new PhoneCallDetailsViews( + new TextView(context), + new View(context), + new CallTypeIconsView(context), + new TextView(context), + new TextView(context), + new TextView(context)); + } +} diff --git a/src/com/android/dialer/calllog/PhoneNumberDisplayUtil.java b/src/com/android/dialer/calllog/PhoneNumberDisplayUtil.java index f80c2bc6a..5030efd48 100644 --- a/src/com/android/dialer/calllog/PhoneNumberDisplayUtil.java +++ b/src/com/android/dialer/calllog/PhoneNumberDisplayUtil.java @@ -23,6 +23,7 @@ import android.text.TextUtils; import android.util.Log; import com.android.dialer.R; +import com.android.dialer.util.PhoneNumberUtil; /** * Helper for formatting and managing the display of phone numbers. @@ -49,7 +50,7 @@ public class PhoneNumberDisplayUtil { if (isVoicemail) { return context.getResources().getString(R.string.voicemail); } - if (PhoneNumberUtilsWrapper.isLegacyUnknownNumbers(number)) { + if (PhoneNumberUtil.isLegacyUnknownNumbers(number)) { return context.getResources().getString(R.string.unknown); } return ""; diff --git a/src/com/android/dialer/calllog/PhoneNumberUtilsWrapper.java b/src/com/android/dialer/calllog/PhoneNumberUtilsWrapper.java deleted file mode 100644 index 6fa81435f..000000000 --- a/src/com/android/dialer/calllog/PhoneNumberUtilsWrapper.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.dialer.calllog; - -import android.content.Context; -import android.provider.CallLog; -import android.telecom.PhoneAccountHandle; -import android.telecom.TelecomManager; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; - -import com.android.contacts.common.util.PhoneNumberHelper; -import com.google.common.collect.Sets; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * - */ -public class PhoneNumberUtilsWrapper { - private static final Set LEGACY_UNKNOWN_NUMBERS = Sets.newHashSet("-1", "-2", "-3"); - private static final long MAX_VOICEMAIL_CACHE_AGE_IN_MS = 60 * 1000; // 60 seconds - private final Context mContext; - - // Keeps a cache of recently-made voicemail queries. The entire point of this cache is to - // reduce the number of cross-process requests to TelecomManager. - // Maps from a phone-account/number pair to a boolean because multiple numbers could return true - // for the voicemail number if those numbers are not pre-normalized. - // - // TODO: Dialer should be fixed so as not to check isVoicemail() so often but at the time of - // this writing, that was a much larger undertaking than creating this cache. - private final Map, Boolean> mVoicemailQueryCache = - new HashMap<>(); - private long mVoicemailCacheTimestamp = 0; - - public PhoneNumberUtilsWrapper(Context context) { - mContext = context; - } - - /** Returns true if it is possible to place a call to the given number. */ - public static boolean canPlaceCallsTo(CharSequence number, int presentation) { - return presentation == CallLog.Calls.PRESENTATION_ALLOWED - && !TextUtils.isEmpty(number) && !isLegacyUnknownNumbers(number); - } - - /** - * Returns true if the given number is the number of the configured voicemail. To be able to - * mock-out this, it is not a static method. - */ - public boolean isVoicemailNumber(PhoneAccountHandle accountHandle, CharSequence number) { - if (TextUtils.isEmpty(number)) { - return false; - } - - long currentTime = System.currentTimeMillis(); - // check the age of the voicemail cache first. - if (currentTime - mVoicemailCacheTimestamp > MAX_VOICEMAIL_CACHE_AGE_IN_MS) { - mVoicemailQueryCache.clear(); - - // We set the timestamp of the voicemail cache to the point where the cache is recreated - // instead of when an item is added. - // 1) This is easier to write - // 2) Ensures that the oldest entry is never older than MAX_VOICEMAIL_CACHE_AGE - mVoicemailCacheTimestamp = currentTime; - } - - Pair key = new Pair<>(accountHandle, number); - if (mVoicemailQueryCache.containsKey(key)) { - return mVoicemailQueryCache.get(key); - } else { - final TelecomManager telecomManager = - (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); - Boolean isVoicemail = - telecomManager.isVoiceMailNumber(accountHandle, number.toString()); - mVoicemailQueryCache.put(key, isVoicemail); - return isVoicemail; - } - } - - /** - * Returns true if the given number is a SIP address. To be able to mock-out this, it is not a - * static method. - */ - public static boolean isSipNumber(CharSequence number) { - return number != null && PhoneNumberHelper.isUriNumber(number.toString()); - } - - public boolean isUnknownNumberThatCanBeLookedUp(PhoneAccountHandle accountHandle, - CharSequence number, int presentation) { - if (presentation == CallLog.Calls.PRESENTATION_UNKNOWN) { - return false; - } - if (presentation == CallLog.Calls.PRESENTATION_RESTRICTED) { - return false; - } - if (presentation == CallLog.Calls.PRESENTATION_PAYPHONE) { - return false; - } - if (TextUtils.isEmpty(number)) { - return false; - } - if (isVoicemailNumber(accountHandle, number)) { - return false; - } - if (isLegacyUnknownNumbers(number)) { - return false; - } - return true; - } - - public static boolean isLegacyUnknownNumbers(CharSequence number) { - return number != null && LEGACY_UNKNOWN_NUMBERS.contains(number.toString()); - } -} diff --git a/src/com/android/dialer/calllog/TelecomCallLogCache.java b/src/com/android/dialer/calllog/TelecomCallLogCache.java new file mode 100644 index 000000000..ec1d24191 --- /dev/null +++ b/src/com/android/dialer/calllog/TelecomCallLogCache.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.dialer.calllog; + +import android.content.Context; +import android.provider.CallLog; +import android.telecom.PhoneAccount; +import android.telecom.PhoneAccountHandle; +import android.telecom.TelecomManager; +import android.text.TextUtils; +import android.util.Log; +import android.util.Pair; + +import com.android.contacts.common.CallUtil; +import com.android.contacts.common.util.PhoneNumberHelper; +import com.android.dialer.util.PhoneNumberUtil; +import com.google.common.collect.Sets; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Keeps a cache of recently made queries to the Telecom process. The aim of this cache is to + * reduce the number of cross-process requests to TelecomManager, which can negatively affect + * performance. + * + * This is designed with the specific use case of the {@link CallLogAdapter} in mind. + */ +public class TelecomCallLogCache { + private final Context mContext; + + // Maps from a phone-account/number pair to a boolean because multiple numbers could return true + // for the voicemail number if those numbers are not pre-normalized. + // TODO: Dialer should be fixed so as not to check isVoicemail() so often but at the time of + // this writing, that was a much larger undertaking than creating this cache. + private final Map, Boolean> mVoicemailQueryCache = + new HashMap<>(); + private final Map mPhoneAccountLabelCache = new HashMap<>(); + private final Map mPhoneAccountColorCache = new HashMap<>(); + + private boolean mHasCheckedForVideoEnabled; + private boolean mIsVideoEnabled; + + public TelecomCallLogCache(Context context) { + mContext = context; + } + + public void reset() { + mVoicemailQueryCache.clear(); + mPhoneAccountLabelCache.clear(); + mPhoneAccountColorCache.clear(); + + mHasCheckedForVideoEnabled = false; + mIsVideoEnabled = false; + } + + /** + * Returns true if the given number is the number of the configured voicemail. To be able to + * mock-out this, it is not a static method. + */ + public boolean isVoicemailNumber(PhoneAccountHandle accountHandle, CharSequence number) { + if (TextUtils.isEmpty(number)) { + return false; + } + + Pair key = new Pair<>(accountHandle, number); + if (mVoicemailQueryCache.containsKey(key)) { + return mVoicemailQueryCache.get(key); + } else { + Boolean isVoicemail = + PhoneNumberUtil.isVoicemailNumber(mContext, accountHandle, number.toString()); + mVoicemailQueryCache.put(key, isVoicemail); + return isVoicemail; + } + } + + /** + * Extract account label from PhoneAccount object. + */ + public String getAccountLabel(PhoneAccountHandle accountHandle) { + if (mPhoneAccountLabelCache.containsKey(accountHandle)) { + return mPhoneAccountLabelCache.get(accountHandle); + } else { + String label = PhoneAccountUtils.getAccountLabel(mContext, accountHandle); + mPhoneAccountLabelCache.put(accountHandle, label); + return label; + } + } + + /** + * Extract account color from PhoneAccount object. + */ + public int getAccountColor(PhoneAccountHandle accountHandle) { + if (mPhoneAccountColorCache.containsKey(accountHandle)) { + return mPhoneAccountColorCache.get(accountHandle); + } else { + Integer color = PhoneAccountUtils.getAccountColor(mContext, accountHandle); + mPhoneAccountColorCache.put(accountHandle, color); + return color; + } + } + + public boolean isVideoEnabled() { + if (!mHasCheckedForVideoEnabled) { + mIsVideoEnabled = CallUtil.isVideoEnabled(mContext); + } + return mIsVideoEnabled; + } +} diff --git a/src/com/android/dialer/util/PhoneNumberUtil.java b/src/com/android/dialer/util/PhoneNumberUtil.java new file mode 100644 index 000000000..84f58aa85 --- /dev/null +++ b/src/com/android/dialer/util/PhoneNumberUtil.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.dialer.util; + +import android.content.Context; +import android.provider.CallLog; +import android.telecom.PhoneAccountHandle; +import android.telecom.TelecomManager; +import android.text.TextUtils; +import android.util.Log; +import android.util.Pair; + +import com.android.contacts.common.util.PhoneNumberHelper; +import com.google.common.collect.Sets; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class PhoneNumberUtil { + private static final Set LEGACY_UNKNOWN_NUMBERS = Sets.newHashSet("-1", "-2", "-3"); + + /** Returns true if it is possible to place a call to the given number. */ + public static boolean canPlaceCallsTo(CharSequence number, int presentation) { + return presentation == CallLog.Calls.PRESENTATION_ALLOWED + && !TextUtils.isEmpty(number) && !isLegacyUnknownNumbers(number); + } + + /** + * Returns true if the given number is the number of the configured voicemail. To be able to + * mock-out this, it is not a static method. + */ + public static boolean isVoicemailNumber( + Context context, PhoneAccountHandle accountHandle, CharSequence number) { + if (TextUtils.isEmpty(number)) { + return false; + } + + final TelecomManager telecomManager = + (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); + return telecomManager.isVoiceMailNumber(accountHandle, number.toString()); + } + + /** + * Returns true if the given number is a SIP address. To be able to mock-out this, it is not a + * static method. + */ + public static boolean isSipNumber(CharSequence number) { + return number != null && PhoneNumberHelper.isUriNumber(number.toString()); + } + + public static boolean isUnknownNumberThatCanBeLookedUp( + Context context, + PhoneAccountHandle accountHandle, + CharSequence number, + int presentation) { + if (presentation == CallLog.Calls.PRESENTATION_UNKNOWN) { + return false; + } + if (presentation == CallLog.Calls.PRESENTATION_RESTRICTED) { + return false; + } + if (presentation == CallLog.Calls.PRESENTATION_PAYPHONE) { + return false; + } + if (TextUtils.isEmpty(number)) { + return false; + } + if (isVoicemailNumber(context, accountHandle, number)) { + return false; + } + if (isLegacyUnknownNumbers(number)) { + return false; + } + return true; + } + + public static boolean isLegacyUnknownNumbers(CharSequence number) { + return number != null && LEGACY_UNKNOWN_NUMBERS.contains(number.toString()); + } +} diff --git a/tests/src/com/android/dialer/PhoneCallDetailsHelperTest.java b/tests/src/com/android/dialer/PhoneCallDetailsHelperTest.java deleted file mode 100644 index 2ee38cbe5..000000000 --- a/tests/src/com/android/dialer/PhoneCallDetailsHelperTest.java +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dialer; - -import android.content.Context; -import android.content.res.Resources; -import android.provider.CallLog.Calls; -import android.test.AndroidTestCase; -import android.text.Html; -import android.text.Spanned; -import android.view.View; -import android.widget.TextView; - -import com.android.dialer.calllog.ContactInfo; -import com.android.dialer.calllog.TestPhoneNumberUtilsWrapper; -import com.android.dialer.util.LocaleTestUtils; - -import java.util.GregorianCalendar; -import java.util.Locale; - -/** - * Unit tests for {@link PhoneCallDetailsHelper}. - */ -public class PhoneCallDetailsHelperTest extends AndroidTestCase { - /** The number to be used to access the voicemail. */ - private static final String TEST_VOICEMAIL_NUMBER = "125"; - /** The date of the call log entry. */ - private static final long TEST_DATE = - new GregorianCalendar(2011, 5, 3, 13, 0, 0).getTimeInMillis(); - /** A test duration value for phone calls. */ - private static final long TEST_DURATION = 62300; - /** The number of the caller/callee in the log entry. */ - private static final String TEST_NUMBER = "14125555555"; - /** The formatted version of {@link #TEST_NUMBER}. */ - private static final String TEST_FORMATTED_NUMBER = "1-412-255-5555"; - /** The country ISO name used in the tests. */ - private static final String TEST_COUNTRY_ISO = "US"; - /** The geocoded location used in the tests. */ - private static final String TEST_GEOCODE = "United States"; - /** Empty geocode label */ - private static final String EMPTY_GEOCODE = ""; - - /** The object under test. */ - private PhoneCallDetailsHelper mHelper; - /** The views to fill. */ - private PhoneCallDetailsViews mViews; - private TextView mNameView; - private LocaleTestUtils mLocaleTestUtils; - private TestPhoneNumberUtilsWrapper mPhoneUtils; - - private Context mContext; - - @Override - protected void setUp() throws Exception { - super.setUp(); - mContext = getContext(); - Resources resources = mContext.getResources(); - mPhoneUtils = new TestPhoneNumberUtilsWrapper(mContext, TEST_VOICEMAIL_NUMBER); - final TestPhoneNumberUtilsWrapper phoneUtils = new TestPhoneNumberUtilsWrapper( - mContext, TEST_VOICEMAIL_NUMBER); - mHelper = new PhoneCallDetailsHelper(mContext, resources, phoneUtils); - mHelper.setCurrentTimeForTest( - new GregorianCalendar(2011, 5, 4, 13, 0, 0).getTimeInMillis()); - mViews = PhoneCallDetailsViews.createForTest(mContext); - mNameView = new TextView(mContext); - mLocaleTestUtils = new LocaleTestUtils(mContext); - mLocaleTestUtils.setLocale(Locale.US); - } - - @Override - protected void tearDown() throws Exception { - mLocaleTestUtils.restoreLocale(); - mNameView = null; - mViews = null; - mHelper = null; - super.tearDown(); - } - - public void testSetPhoneCallDetails_Unknown() { - setPhoneCallDetailsWithNumber("", Calls.PRESENTATION_UNKNOWN, ""); - assertNameEqualsResource(R.string.unknown); - } - - public void testSetPhoneCallDetails_Private() { - setPhoneCallDetailsWithNumber("", Calls.PRESENTATION_RESTRICTED, ""); - assertNameEqualsResource(R.string.private_num); - } - - public void testSetPhoneCallDetails_Payphone() { - setPhoneCallDetailsWithNumber("", Calls.PRESENTATION_PAYPHONE, ""); - assertNameEqualsResource(R.string.payphone); - } - - public void testSetPhoneCallDetails_Voicemail() { - setPhoneCallDetailsWithNumber(TEST_VOICEMAIL_NUMBER, - Calls.PRESENTATION_ALLOWED, TEST_VOICEMAIL_NUMBER); - assertNameEqualsResource(R.string.voicemail); - } - - public void testSetPhoneCallDetails_Normal() { - setPhoneCallDetailsWithNumber("14125551212", - Calls.PRESENTATION_ALLOWED, "1-412-555-1212"); - assertTrue(mViews.callLocationAndDate.getText().toString().contains("Yesterday")); - } - - /** Asserts that a char sequence is actually a Spanned corresponding to the expected HTML. */ - private void assertEqualsHtml(String expectedHtml, CharSequence actualText) { - // In order to contain HTML, the text should actually be a Spanned. - assertTrue(actualText instanceof Spanned); - Spanned actualSpanned = (Spanned) actualText; - // Convert from and to HTML to take care of alternative formatting of HTML. - assertEquals(Html.toHtml(Html.fromHtml(expectedHtml)), Html.toHtml(actualSpanned)); - - } - - public void testSetPhoneCallDetails_Date() { - mHelper.setCurrentTimeForTest( - new GregorianCalendar(2011, 5, 3, 13, 0, 0).getTimeInMillis()); - - setPhoneCallDetailsWithDate( - new GregorianCalendar(2011, 5, 3, 13, 0, 0).getTimeInMillis()); - assertDateEquals("0 min. ago"); - - setPhoneCallDetailsWithDate( - new GregorianCalendar(2011, 5, 3, 12, 0, 0).getTimeInMillis()); - assertDateEquals("1 hr. ago"); - - setPhoneCallDetailsWithDate( - new GregorianCalendar(2011, 5, 2, 13, 0, 0).getTimeInMillis()); - assertDateEquals("Yesterday"); - - setPhoneCallDetailsWithDate( - new GregorianCalendar(2011, 5, 1, 13, 0, 0).getTimeInMillis()); - assertDateEquals("2 days ago"); - } - - public void testSetPhoneCallDetails_CallTypeIcons() { - setPhoneCallDetailsWithCallTypeIcons(Calls.INCOMING_TYPE); - assertCallTypeIconsEquals(Calls.INCOMING_TYPE); - - setPhoneCallDetailsWithCallTypeIcons(Calls.OUTGOING_TYPE); - assertCallTypeIconsEquals(Calls.OUTGOING_TYPE); - - setPhoneCallDetailsWithCallTypeIcons(Calls.MISSED_TYPE); - assertCallTypeIconsEquals(Calls.MISSED_TYPE); - - setPhoneCallDetailsWithCallTypeIcons(Calls.VOICEMAIL_TYPE); - assertCallTypeIconsEquals(Calls.VOICEMAIL_TYPE); - } - - /** - * Tests a case where the video call feature is present. - */ - public void testSetPhoneCallDetails_Video() { - PhoneCallDetails details = getPhoneCallDetails(); - details.features = Calls.FEATURES_VIDEO; - mHelper.setPhoneCallDetails(mViews, details); - - assertIsVideoCall(true); - } - - /** - * Tests a case where the video call feature is not present. - */ - public void testSetPhoneCallDetails_NoVideo() { - PhoneCallDetails details = getPhoneCallDetails(); - details.features = 0; - mHelper.setPhoneCallDetails(mViews, details); - - assertIsVideoCall(false); - } - - public void testSetPhoneCallDetails_MultipleCallTypeIcons() { - setPhoneCallDetailsWithCallTypeIcons(Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE); - assertCallTypeIconsEquals(Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE); - - setPhoneCallDetailsWithCallTypeIcons(Calls.MISSED_TYPE, Calls.MISSED_TYPE); - assertCallTypeIconsEquals(Calls.MISSED_TYPE, Calls.MISSED_TYPE); - } - - public void testSetPhoneCallDetails_MultipleCallTypeIconsLastOneDropped() { - setPhoneCallDetailsWithCallTypeIcons(Calls.MISSED_TYPE, Calls.MISSED_TYPE, - Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE); - assertCallTypeIconsEqualsPlusOverflow("(4)", - Calls.MISSED_TYPE, Calls.MISSED_TYPE, Calls.INCOMING_TYPE); - } - - public void testSetPhoneCallDetails_Geocode() { - setPhoneCallDetailsWithNumberAndGeocode("+14125555555", "1-412-555-5555", "Pennsylvania"); - assertNameEquals("1-412-555-5555"); // The phone number is shown as the name. - assertLabelEquals("Pennsylvania"); // The geocode is shown as the label. - } - - public void testSetPhoneCallDetails_NoGeocode() { - setPhoneCallDetailsWithNumberAndGeocode("+14125555555", "1-412-555-5555", null); - assertNameEquals("1-412-555-5555"); // The phone number is shown as the name. - assertLabelEquals(EMPTY_GEOCODE); // The empty geocode is shown as the label. - } - - public void testSetPhoneCallDetails_EmptyGeocode() { - setPhoneCallDetailsWithNumberAndGeocode("+14125555555", "1-412-555-5555", ""); - assertNameEquals("1-412-555-5555"); // The phone number is shown as the name. - assertLabelEquals(EMPTY_GEOCODE); // The empty geocode is shown as the label. - } - - public void testSetPhoneCallDetails_NoGeocodeForVoicemail() { - setPhoneCallDetailsWithNumberAndGeocode(TEST_VOICEMAIL_NUMBER, "", "United States"); - assertLabelEquals(EMPTY_GEOCODE); // The empty geocode is shown as the label. - } - - public void testSetPhoneCallDetails_Highlighted() { - setPhoneCallDetailsWithNumber(TEST_VOICEMAIL_NUMBER, - Calls.PRESENTATION_ALLOWED, ""); - } - - public void testSetCallDetailsHeader_NumberOnly() { - setCallDetailsHeaderWithNumber(TEST_NUMBER, Calls.PRESENTATION_ALLOWED); - assertEquals(View.VISIBLE, mNameView.getVisibility()); - assertEquals("1-412-255-5555", mNameView.getText().toString()); - } - - public void testSetCallDetailsHeader_UnknownNumber() { - setCallDetailsHeaderWithNumber("", Calls.PRESENTATION_UNKNOWN); - assertEquals(View.VISIBLE, mNameView.getVisibility()); - assertEquals("Unknown", mNameView.getText().toString()); - } - - public void testSetCallDetailsHeader_PrivateNumber() { - setCallDetailsHeaderWithNumber("", Calls.PRESENTATION_RESTRICTED); - assertEquals(View.VISIBLE, mNameView.getVisibility()); - assertEquals("Private number", mNameView.getText().toString()); - } - - public void testSetCallDetailsHeader_PayphoneNumber() { - setCallDetailsHeaderWithNumber("", Calls.PRESENTATION_PAYPHONE); - assertEquals(View.VISIBLE, mNameView.getVisibility()); - assertEquals("Payphone", mNameView.getText().toString()); - } - - public void testSetCallDetailsHeader_VoicemailNumber() { - PhoneCallDetails details = getPhoneCallDetails( - TEST_VOICEMAIL_NUMBER, - Calls.PRESENTATION_ALLOWED, - TEST_FORMATTED_NUMBER); - mHelper.setCallDetailsHeader(mNameView, details); - assertEquals(View.VISIBLE, mNameView.getVisibility()); - assertEquals("Voicemail", mNameView.getText().toString()); - } - - public void testSetCallDetailsHeader() { - setCallDetailsHeader("John Doe"); - assertEquals(View.VISIBLE, mNameView.getVisibility()); - assertEquals("John Doe", mNameView.getText().toString()); - } - - /** Asserts that the name text field contains the value of the given string resource. */ - private void assertNameEqualsResource(int resId) { - assertNameEquals(getContext().getString(resId)); - } - - /** Asserts that the name text field contains the given string value. */ - private void assertNameEquals(String text) { - assertEquals(text, mViews.nameView.getText().toString()); - } - - /** Asserts that the label text field contains the given string value. */ - private void assertLabelEquals(String text) { - assertTrue(mViews.callLocationAndDate.getText().toString().contains(text)); - } - - /** Asserts that the date text field contains the given string value. */ - private void assertDateEquals(String text) { - assertTrue(mViews.callLocationAndDate.getText().toString().contains(text)); - } - - /** Asserts that the video icon is shown. */ - private void assertIsVideoCall(boolean isVideoCall) { - assertEquals(isVideoCall, mViews.callTypeIcons.isVideoShown()); - } - - /** Asserts that the call type contains the images with the given drawables. */ - private void assertCallTypeIconsEquals(int... ids) { - assertEquals(ids.length, mViews.callTypeIcons.getCount()); - for (int index = 0; index < ids.length; ++index) { - int id = ids[index]; - assertEquals(id, mViews.callTypeIcons.getCallType(index)); - } - assertEquals(View.VISIBLE, mViews.callTypeIcons.getVisibility()); - assertTrue(mViews.callLocationAndDate.getText().toString().contains("Yesterday")); - } - - /** - * Asserts that the call type contains the images with the given drawables and shows the given - * text next to the icons. - */ - private void assertCallTypeIconsEqualsPlusOverflow(String overflowText, int... ids) { - assertEquals(ids.length, mViews.callTypeIcons.getCount()); - for (int index = 0; index < ids.length; ++index) { - int id = ids[index]; - assertEquals(id, mViews.callTypeIcons.getCallType(index)); - } - assertEquals(View.VISIBLE, mViews.callTypeIcons.getVisibility()); - assertTrue(mViews.callLocationAndDate.getText().toString().contains(overflowText)); - assertTrue(mViews.callLocationAndDate.getText().toString().contains("Yesterday")); - } - - /** Sets the phone call details with default values and the given number. */ - private void setPhoneCallDetailsWithNumber(String number, int presentation, - String formattedNumber) { - PhoneCallDetails details = getPhoneCallDetails(number, presentation, formattedNumber); - details.callTypes = new int[]{ Calls.VOICEMAIL_TYPE }; - mHelper.setPhoneCallDetails(mViews, details); - } - - /** Sets the phone call details with default values and the given number. */ - private void setPhoneCallDetailsWithNumberAndGeocode( - String number, String formattedNumber, String geocodedLocation) { - PhoneCallDetails details = getPhoneCallDetails( - number, Calls.PRESENTATION_ALLOWED, formattedNumber); - details.geocode = geocodedLocation; - mHelper.setPhoneCallDetails(mViews, details); - } - - /** Sets the phone call details with default values and the given date. */ - private void setPhoneCallDetailsWithDate(long date) { - PhoneCallDetails details = getPhoneCallDetails(); - details.date = date; - mHelper.setPhoneCallDetails(mViews, details); - } - - /** Sets the phone call details with default values and the given call types using icons. */ - private void setPhoneCallDetailsWithCallTypeIcons(int... callTypes) { - PhoneCallDetails details = getPhoneCallDetails(); - details.callTypes = callTypes; - mHelper.setPhoneCallDetails(mViews, details); - } - - private void setCallDetailsHeaderWithNumber(String number, int presentation) { - mHelper.setCallDetailsHeader(mNameView, - getPhoneCallDetails(number, presentation, TEST_FORMATTED_NUMBER)); - } - - private void setCallDetailsHeader(String name) { - PhoneCallDetails details = getPhoneCallDetails(); - details.name = name; - mHelper.setCallDetailsHeader(mNameView, details); - } - - private PhoneCallDetails getPhoneCallDetails() { - PhoneCallDetails details = new PhoneCallDetails( - mContext, - TEST_NUMBER, - Calls.PRESENTATION_ALLOWED, - TEST_FORMATTED_NUMBER, - false /* isVoicemail */); - setDefaultDetails(details); - return details; - } - - private PhoneCallDetails getPhoneCallDetails( - String number, int presentation, String formattedNumber) { - PhoneCallDetails details = new PhoneCallDetails( - mContext, - number, - presentation, - formattedNumber, - isVoicemail(number)); - setDefaultDetails(details); - return details; - } - - private void setDefaultDetails(PhoneCallDetails details) { - details.callTypes = new int[]{ Calls.INCOMING_TYPE }; - details.countryIso = TEST_COUNTRY_ISO; - details.date = TEST_DATE; - details.duration = TEST_DURATION; - details.geocode = TEST_GEOCODE; - } - - private boolean isVoicemail(String number) { - return number.equals(TEST_VOICEMAIL_NUMBER); - } -} diff --git a/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java b/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java index 8ee85a436..8c2d8e443 100644 --- a/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java +++ b/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java @@ -24,7 +24,6 @@ import android.view.View; import com.android.contacts.common.CallUtil; import com.android.dialer.PhoneCallDetails; -import com.android.dialer.PhoneCallDetailsHelper; import com.android.dialer.R; /** @@ -60,12 +59,13 @@ public class CallLogListItemHelperTest extends AndroidTestCase { super.setUp(); mContext = getContext(); mResources = mContext.getResources(); - final TestPhoneNumberUtilsWrapper phoneUtils = - new TestPhoneNumberUtilsWrapper(mContext, TEST_VOICEMAIL_NUMBER); + final TestTelecomCallLogCache phoneUtils = + new TestTelecomCallLogCache(mContext, TEST_VOICEMAIL_NUMBER); PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(mContext, mResources, phoneUtils); - mHelper = new CallLogListItemHelper(phoneCallDetailsHelper, mResources); + mHelper = new CallLogListItemHelper(phoneCallDetailsHelper, mResources, phoneUtils); mViewHolder = CallLogListItemViewHolder.createForTest(mContext); + } @Override @@ -104,13 +104,13 @@ public class CallLogListItemHelperTest extends AndroidTestCase { public void testSetPhoneCallDetails_ReadVoicemail() { PhoneCallDetails details = getPhoneCallDetailsWithTypes(Calls.VOICEMAIL_TYPE); - mHelper.setPhoneCallDetails(getContext(), mViewHolder, details); + mHelper.setPhoneCallDetails(mViewHolder, details); assertEquals(View.VISIBLE, mViewHolder.voicemailPlaybackView.getVisibility()); } public void testSetPhoneCallDetails_UnreadVoicemail() { PhoneCallDetails details = getPhoneCallDetailsWithTypes(Calls.VOICEMAIL_TYPE); - mHelper.setPhoneCallDetails(getContext(), mViewHolder, details); + mHelper.setPhoneCallDetails(mViewHolder, details); assertEquals(View.VISIBLE, mViewHolder.voicemailPlaybackView.getVisibility()); } @@ -176,7 +176,7 @@ public class CallLogListItemHelperTest extends AndroidTestCase { public void testGetCallDescription_NoVoicemailOutgoing() { PhoneCallDetails details = getPhoneCallDetailsWithTypes(Calls.OUTGOING_TYPE, Calls.OUTGOING_TYPE); - CharSequence description = mHelper.getCallDescription(getContext(), details); + CharSequence description = mHelper.getCallDescription(details); assertFalse(description.toString() .contains(this.mResources.getString(R.string.description_new_voicemail))); } @@ -188,7 +188,7 @@ public class CallLogListItemHelperTest extends AndroidTestCase { public void testGetCallDescription_NoVoicemailIncoming() { PhoneCallDetails details = getPhoneCallDetailsWithTypes(Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE); - CharSequence description = mHelper.getCallDescription(getContext(), details); + CharSequence description = mHelper.getCallDescription(details); assertFalse(description.toString() .contains(this.mResources.getString(R.string.description_new_voicemail))); } @@ -200,7 +200,7 @@ public class CallLogListItemHelperTest extends AndroidTestCase { public void testGetCallDescription_NoVoicemailMissed() { PhoneCallDetails details = getPhoneCallDetailsWithTypes(Calls.MISSED_TYPE, Calls.OUTGOING_TYPE); - CharSequence description = mHelper.getCallDescription(getContext(), details); + CharSequence description = mHelper.getCallDescription(details); assertFalse(description.toString() .contains(this.mResources.getString(R.string.description_new_voicemail))); } @@ -212,7 +212,7 @@ public class CallLogListItemHelperTest extends AndroidTestCase { public void testGetCallDescription_Voicemail() { PhoneCallDetails details = getPhoneCallDetailsWithTypes(Calls.VOICEMAIL_TYPE, Calls.OUTGOING_TYPE); - CharSequence description = mHelper.getCallDescription(getContext(), details); + CharSequence description = mHelper.getCallDescription(details); assertTrue(description.toString() .contains(this.mResources.getString(R.string.description_new_voicemail))); } @@ -223,7 +223,7 @@ public class CallLogListItemHelperTest extends AndroidTestCase { */ public void testGetCallDescription_NumCallsSingle() { PhoneCallDetails details = getPhoneCallDetailsWithTypes(Calls.VOICEMAIL_TYPE); - CharSequence description = mHelper.getCallDescription(getContext(), details); + CharSequence description = mHelper.getCallDescription(details); // Rather than hard coding the "X calls" string message, we'll generate it with an empty // number of calls, and trim the resulting string. This gets us just the word "calls", @@ -240,7 +240,7 @@ public class CallLogListItemHelperTest extends AndroidTestCase { public void testGetCallDescription_NumCallsMultiple() { PhoneCallDetails details = getPhoneCallDetailsWithTypes(Calls.VOICEMAIL_TYPE, Calls.INCOMING_TYPE); - CharSequence description = mHelper.getCallDescription(getContext(), details); + CharSequence description = mHelper.getCallDescription(details); assertTrue(description.toString() .contains(this.mResources.getString(R.string.description_num_calls, 2))); } @@ -254,7 +254,7 @@ public class CallLogListItemHelperTest extends AndroidTestCase { getPhoneCallDetailsWithTypes(Calls.INCOMING_TYPE, Calls.INCOMING_TYPE); details.features = Calls.FEATURES_VIDEO; - CharSequence description = mHelper.getCallDescription(getContext(), details); + CharSequence description = mHelper.getCallDescription(details); final boolean isVideoEnabled = CallUtil.isVideoEnabled(getContext()); assertTrue(description.toString() .contains(this.mResources.getString( @@ -284,7 +284,7 @@ public class CallLogListItemHelperTest extends AndroidTestCase { PhoneCallDetails details = getPhoneCallDetails( number, presentation, formattedNumber); details.callTypes = new int[]{ callType }; - mHelper.setPhoneCallDetails(mContext, mViewHolder, details); + mHelper.setPhoneCallDetails(mViewHolder, details); } private PhoneCallDetails getPhoneCallDetails( diff --git a/tests/src/com/android/dialer/calllog/PhoneCallDetailsHelperTest.java b/tests/src/com/android/dialer/calllog/PhoneCallDetailsHelperTest.java new file mode 100644 index 000000000..318250247 --- /dev/null +++ b/tests/src/com/android/dialer/calllog/PhoneCallDetailsHelperTest.java @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.dialer.calllog; + +import android.content.Context; +import android.content.res.Resources; +import android.provider.CallLog.Calls; +import android.test.AndroidTestCase; +import android.text.Html; +import android.text.Spanned; +import android.view.View; +import android.widget.TextView; + +import com.android.dialer.PhoneCallDetails; +import com.android.dialer.R; +import com.android.dialer.util.LocaleTestUtils; + +import java.util.GregorianCalendar; +import java.util.Locale; + +/** + * Unit tests for {@link PhoneCallDetailsHelper}.m + */ +public class PhoneCallDetailsHelperTest extends AndroidTestCase { + /** The number to be used to access the voicemail. */ + private static final String TEST_VOICEMAIL_NUMBER = "125"; + /** The date of the call log entry. */ + private static final long TEST_DATE = + new GregorianCalendar(2011, 5, 3, 13, 0, 0).getTimeInMillis(); + /** A test duration value for phone calls. */ + private static final long TEST_DURATION = 62300; + /** The number of the caller/callee in the log entry. */ + private static final String TEST_NUMBER = "14125555555"; + /** The formatted version of {@link #TEST_NUMBER}. */ + private static final String TEST_FORMATTED_NUMBER = "1-412-255-5555"; + /** The country ISO name used in the tests. */ + private static final String TEST_COUNTRY_ISO = "US"; + /** The geocoded location used in the tests. */ + private static final String TEST_GEOCODE = "United States"; + /** Empty geocode label */ + private static final String EMPTY_GEOCODE = ""; + + /** The object under test. */ + private PhoneCallDetailsHelper mHelper; + /** The views to fill. */ + private PhoneCallDetailsViews mViews; + private TextView mNameView; + private LocaleTestUtils mLocaleTestUtils; + private TestTelecomCallLogCache mPhoneUtils; + + private Context mContext; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mContext = getContext(); + Resources resources = mContext.getResources(); + mPhoneUtils = new TestTelecomCallLogCache(mContext, TEST_VOICEMAIL_NUMBER); + final TestTelecomCallLogCache phoneUtils = new TestTelecomCallLogCache( + mContext, TEST_VOICEMAIL_NUMBER); + mHelper = new PhoneCallDetailsHelper(mContext, resources, phoneUtils); + mHelper.setCurrentTimeForTest( + new GregorianCalendar(2011, 5, 4, 13, 0, 0).getTimeInMillis()); + mViews = PhoneCallDetailsViews.createForTest(mContext); + mNameView = new TextView(mContext); + mLocaleTestUtils = new LocaleTestUtils(mContext); + mLocaleTestUtils.setLocale(Locale.US); + } + + @Override + protected void tearDown() throws Exception { + mLocaleTestUtils.restoreLocale(); + mNameView = null; + mViews = null; + mHelper = null; + super.tearDown(); + } + + public void testSetPhoneCallDetails_Unknown() { + setPhoneCallDetailsWithNumber("", Calls.PRESENTATION_UNKNOWN, ""); + assertNameEqualsResource(R.string.unknown); + } + + public void testSetPhoneCallDetails_Private() { + setPhoneCallDetailsWithNumber("", Calls.PRESENTATION_RESTRICTED, ""); + assertNameEqualsResource(R.string.private_num); + } + + public void testSetPhoneCallDetails_Payphone() { + setPhoneCallDetailsWithNumber("", Calls.PRESENTATION_PAYPHONE, ""); + assertNameEqualsResource(R.string.payphone); + } + + public void testSetPhoneCallDetails_Voicemail() { + setPhoneCallDetailsWithNumber(TEST_VOICEMAIL_NUMBER, + Calls.PRESENTATION_ALLOWED, TEST_VOICEMAIL_NUMBER); + assertNameEqualsResource(R.string.voicemail); + } + + public void testSetPhoneCallDetails_Normal() { + setPhoneCallDetailsWithNumber("14125551212", + Calls.PRESENTATION_ALLOWED, "1-412-555-1212"); + assertTrue(mViews.callLocationAndDate.getText().toString().contains("Yesterday")); + } + + /** Asserts that a char sequence is actually a Spanned corresponding to the expected HTML. */ + private void assertEqualsHtml(String expectedHtml, CharSequence actualText) { + // In order to contain HTML, the text should actually be a Spanned. + assertTrue(actualText instanceof Spanned); + Spanned actualSpanned = (Spanned) actualText; + // Convert from and to HTML to take care of alternative formatting of HTML. + assertEquals(Html.toHtml(Html.fromHtml(expectedHtml)), Html.toHtml(actualSpanned)); + + } + + public void testSetPhoneCallDetails_Date() { + mHelper.setCurrentTimeForTest( + new GregorianCalendar(2011, 5, 3, 13, 0, 0).getTimeInMillis()); + + setPhoneCallDetailsWithDate( + new GregorianCalendar(2011, 5, 3, 13, 0, 0).getTimeInMillis()); + assertDateEquals("0 min. ago"); + + setPhoneCallDetailsWithDate( + new GregorianCalendar(2011, 5, 3, 12, 0, 0).getTimeInMillis()); + assertDateEquals("1 hr. ago"); + + setPhoneCallDetailsWithDate( + new GregorianCalendar(2011, 5, 2, 13, 0, 0).getTimeInMillis()); + assertDateEquals("Yesterday"); + + setPhoneCallDetailsWithDate( + new GregorianCalendar(2011, 5, 1, 13, 0, 0).getTimeInMillis()); + assertDateEquals("2 days ago"); + } + + public void testSetPhoneCallDetails_CallTypeIcons() { + setPhoneCallDetailsWithCallTypeIcons(Calls.INCOMING_TYPE); + assertCallTypeIconsEquals(Calls.INCOMING_TYPE); + + setPhoneCallDetailsWithCallTypeIcons(Calls.OUTGOING_TYPE); + assertCallTypeIconsEquals(Calls.OUTGOING_TYPE); + + setPhoneCallDetailsWithCallTypeIcons(Calls.MISSED_TYPE); + assertCallTypeIconsEquals(Calls.MISSED_TYPE); + + setPhoneCallDetailsWithCallTypeIcons(Calls.VOICEMAIL_TYPE); + assertCallTypeIconsEquals(Calls.VOICEMAIL_TYPE); + } + + /** + * Tests a case where the video call feature is present. + */ + public void testSetPhoneCallDetails_Video() { + PhoneCallDetails details = getPhoneCallDetails(); + details.features = Calls.FEATURES_VIDEO; + mHelper.setPhoneCallDetails(mViews, details); + + assertIsVideoCall(true); + } + + /** + * Tests a case where the video call feature is not present. + */ + public void testSetPhoneCallDetails_NoVideo() { + PhoneCallDetails details = getPhoneCallDetails(); + details.features = 0; + mHelper.setPhoneCallDetails(mViews, details); + + assertIsVideoCall(false); + } + + public void testSetPhoneCallDetails_MultipleCallTypeIcons() { + setPhoneCallDetailsWithCallTypeIcons(Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE); + assertCallTypeIconsEquals(Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE); + + setPhoneCallDetailsWithCallTypeIcons(Calls.MISSED_TYPE, Calls.MISSED_TYPE); + assertCallTypeIconsEquals(Calls.MISSED_TYPE, Calls.MISSED_TYPE); + } + + public void testSetPhoneCallDetails_MultipleCallTypeIconsLastOneDropped() { + setPhoneCallDetailsWithCallTypeIcons(Calls.MISSED_TYPE, Calls.MISSED_TYPE, + Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE); + assertCallTypeIconsEqualsPlusOverflow("(4)", + Calls.MISSED_TYPE, Calls.MISSED_TYPE, Calls.INCOMING_TYPE); + } + + public void testSetPhoneCallDetails_Geocode() { + setPhoneCallDetailsWithNumberAndGeocode("+14125555555", "1-412-555-5555", "Pennsylvania"); + assertNameEquals("1-412-555-5555"); // The phone number is shown as the name. + assertLabelEquals("Pennsylvania"); // The geocode is shown as the label. + } + + public void testSetPhoneCallDetails_NoGeocode() { + setPhoneCallDetailsWithNumberAndGeocode("+14125555555", "1-412-555-5555", null); + assertNameEquals("1-412-555-5555"); // The phone number is shown as the name. + assertLabelEquals(EMPTY_GEOCODE); // The empty geocode is shown as the label. + } + + public void testSetPhoneCallDetails_EmptyGeocode() { + setPhoneCallDetailsWithNumberAndGeocode("+14125555555", "1-412-555-5555", ""); + assertNameEquals("1-412-555-5555"); // The phone number is shown as the name. + assertLabelEquals(EMPTY_GEOCODE); // The empty geocode is shown as the label. + } + + public void testSetPhoneCallDetails_NoGeocodeForVoicemail() { + setPhoneCallDetailsWithNumberAndGeocode(TEST_VOICEMAIL_NUMBER, "", "United States"); + assertLabelEquals(EMPTY_GEOCODE); // The empty geocode is shown as the label. + } + + public void testSetPhoneCallDetails_Highlighted() { + setPhoneCallDetailsWithNumber(TEST_VOICEMAIL_NUMBER, + Calls.PRESENTATION_ALLOWED, ""); + } + + public void testSetCallDetailsHeader_NumberOnly() { + setCallDetailsHeaderWithNumber(TEST_NUMBER, Calls.PRESENTATION_ALLOWED); + assertEquals(View.VISIBLE, mNameView.getVisibility()); + assertEquals("1-412-255-5555", mNameView.getText().toString()); + } + + public void testSetCallDetailsHeader_UnknownNumber() { + setCallDetailsHeaderWithNumber("", Calls.PRESENTATION_UNKNOWN); + assertEquals(View.VISIBLE, mNameView.getVisibility()); + assertEquals("Unknown", mNameView.getText().toString()); + } + + public void testSetCallDetailsHeader_PrivateNumber() { + setCallDetailsHeaderWithNumber("", Calls.PRESENTATION_RESTRICTED); + assertEquals(View.VISIBLE, mNameView.getVisibility()); + assertEquals("Private number", mNameView.getText().toString()); + } + + public void testSetCallDetailsHeader_PayphoneNumber() { + setCallDetailsHeaderWithNumber("", Calls.PRESENTATION_PAYPHONE); + assertEquals(View.VISIBLE, mNameView.getVisibility()); + assertEquals("Payphone", mNameView.getText().toString()); + } + + public void testSetCallDetailsHeader_VoicemailNumber() { + PhoneCallDetails details = getPhoneCallDetails( + TEST_VOICEMAIL_NUMBER, + Calls.PRESENTATION_ALLOWED, + TEST_FORMATTED_NUMBER); + mHelper.setCallDetailsHeader(mNameView, details); + assertEquals(View.VISIBLE, mNameView.getVisibility()); + assertEquals("Voicemail", mNameView.getText().toString()); + } + + public void testSetCallDetailsHeader() { + setCallDetailsHeader("John Doe"); + assertEquals(View.VISIBLE, mNameView.getVisibility()); + assertEquals("John Doe", mNameView.getText().toString()); + } + + /** Asserts that the name text field contains the value of the given string resource. */ + private void assertNameEqualsResource(int resId) { + assertNameEquals(getContext().getString(resId)); + } + + /** Asserts that the name text field contains the given string value. */ + private void assertNameEquals(String text) { + assertEquals(text, mViews.nameView.getText().toString()); + } + + /** Asserts that the label text field contains the given string value. */ + private void assertLabelEquals(String text) { + assertTrue(mViews.callLocationAndDate.getText().toString().contains(text)); + } + + /** Asserts that the date text field contains the given string value. */ + private void assertDateEquals(String text) { + assertTrue(mViews.callLocationAndDate.getText().toString().contains(text)); + } + + /** Asserts that the video icon is shown. */ + private void assertIsVideoCall(boolean isVideoCall) { + assertEquals(isVideoCall, mViews.callTypeIcons.isVideoShown()); + } + + /** Asserts that the call type contains the images with the given drawables. */ + private void assertCallTypeIconsEquals(int... ids) { + assertEquals(ids.length, mViews.callTypeIcons.getCount()); + for (int index = 0; index < ids.length; ++index) { + int id = ids[index]; + assertEquals(id, mViews.callTypeIcons.getCallType(index)); + } + assertEquals(View.VISIBLE, mViews.callTypeIcons.getVisibility()); + assertTrue(mViews.callLocationAndDate.getText().toString().contains("Yesterday")); + } + + /** + * Asserts that the call type contains the images with the given drawables and shows the given + * text next to the icons. + */ + private void assertCallTypeIconsEqualsPlusOverflow(String overflowText, int... ids) { + assertEquals(ids.length, mViews.callTypeIcons.getCount()); + for (int index = 0; index < ids.length; ++index) { + int id = ids[index]; + assertEquals(id, mViews.callTypeIcons.getCallType(index)); + } + assertEquals(View.VISIBLE, mViews.callTypeIcons.getVisibility()); + assertTrue(mViews.callLocationAndDate.getText().toString().contains(overflowText)); + assertTrue(mViews.callLocationAndDate.getText().toString().contains("Yesterday")); + } + + /** Sets the phone call details with default values and the given number. */ + private void setPhoneCallDetailsWithNumber(String number, int presentation, + String formattedNumber) { + PhoneCallDetails details = getPhoneCallDetails(number, presentation, formattedNumber); + details.callTypes = new int[]{ Calls.VOICEMAIL_TYPE }; + mHelper.setPhoneCallDetails(mViews, details); + } + + /** Sets the phone call details with default values and the given number. */ + private void setPhoneCallDetailsWithNumberAndGeocode( + String number, String formattedNumber, String geocodedLocation) { + PhoneCallDetails details = getPhoneCallDetails( + number, Calls.PRESENTATION_ALLOWED, formattedNumber); + details.geocode = geocodedLocation; + mHelper.setPhoneCallDetails(mViews, details); + } + + /** Sets the phone call details with default values and the given date. */ + private void setPhoneCallDetailsWithDate(long date) { + PhoneCallDetails details = getPhoneCallDetails(); + details.date = date; + mHelper.setPhoneCallDetails(mViews, details); + } + + /** Sets the phone call details with default values and the given call types using icons. */ + private void setPhoneCallDetailsWithCallTypeIcons(int... callTypes) { + PhoneCallDetails details = getPhoneCallDetails(); + details.callTypes = callTypes; + mHelper.setPhoneCallDetails(mViews, details); + } + + private void setCallDetailsHeaderWithNumber(String number, int presentation) { + mHelper.setCallDetailsHeader(mNameView, + getPhoneCallDetails(number, presentation, TEST_FORMATTED_NUMBER)); + } + + private void setCallDetailsHeader(String name) { + PhoneCallDetails details = getPhoneCallDetails(); + details.name = name; + mHelper.setCallDetailsHeader(mNameView, details); + } + + private PhoneCallDetails getPhoneCallDetails() { + PhoneCallDetails details = new PhoneCallDetails( + mContext, + TEST_NUMBER, + Calls.PRESENTATION_ALLOWED, + TEST_FORMATTED_NUMBER, + false /* isVoicemail */); + setDefaultDetails(details); + return details; + } + + private PhoneCallDetails getPhoneCallDetails( + String number, int presentation, String formattedNumber) { + PhoneCallDetails details = new PhoneCallDetails( + mContext, + number, + presentation, + formattedNumber, + isVoicemail(number)); + setDefaultDetails(details); + return details; + } + + private void setDefaultDetails(PhoneCallDetails details) { + details.callTypes = new int[]{ Calls.INCOMING_TYPE }; + details.countryIso = TEST_COUNTRY_ISO; + details.date = TEST_DATE; + details.duration = TEST_DURATION; + details.geocode = TEST_GEOCODE; + } + + private boolean isVoicemail(String number) { + return number.equals(TEST_VOICEMAIL_NUMBER); + } +} diff --git a/tests/src/com/android/dialer/calllog/TestPhoneNumberUtilsWrapper.java b/tests/src/com/android/dialer/calllog/TestPhoneNumberUtilsWrapper.java deleted file mode 100644 index 24916db9e..000000000 --- a/tests/src/com/android/dialer/calllog/TestPhoneNumberUtilsWrapper.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.dialer.calllog; - -import android.content.Context; -import android.telecom.PhoneAccountHandle; - -/** - * Modified version of {@link com.android.dialer.calllog.PhoneNumberDisplayHelper} to be used in - * tests that allows injecting the voicemail number. - */ -public final class TestPhoneNumberUtilsWrapper extends PhoneNumberUtilsWrapper { - private CharSequence mVoicemailNumber; - - public TestPhoneNumberUtilsWrapper(Context context, CharSequence voicemailNumber) { - super(context); - mVoicemailNumber = voicemailNumber; - } - - @Override - public boolean isVoicemailNumber(PhoneAccountHandle accountHandle, CharSequence number) { - return mVoicemailNumber.equals(number); - } -} diff --git a/tests/src/com/android/dialer/calllog/TestTelecomCallLogCache.java b/tests/src/com/android/dialer/calllog/TestTelecomCallLogCache.java new file mode 100644 index 000000000..5475ec337 --- /dev/null +++ b/tests/src/com/android/dialer/calllog/TestTelecomCallLogCache.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.dialer.calllog; + +import android.content.Context; +import android.telecom.PhoneAccountHandle; + +/** + * Modified version of {@link com.android.dialer.calllog.PhoneNumberDisplayHelper} to be used in + * tests that allows injecting the voicemail number. + */ +public final class TestTelecomCallLogCache extends TelecomCallLogCache { + private CharSequence mVoicemailNumber; + + public TestTelecomCallLogCache(Context context, CharSequence voicemailNumber) { + super(context); + mVoicemailNumber = voicemailNumber; + } + + @Override + public boolean isVoicemailNumber(PhoneAccountHandle accountHandle, CharSequence number) { + return mVoicemailNumber.equals(number); + } +} diff --git a/tests/src/com/android/dialer/util/DialerUtilsTest.java b/tests/src/com/android/dialer/util/DialerUtilsTest.java index fdd02c10c..ccd6dfdd5 100644 --- a/tests/src/com/android/dialer/util/DialerUtilsTest.java +++ b/tests/src/com/android/dialer/util/DialerUtilsTest.java @@ -16,7 +16,7 @@ package com.android.dialer.util; -import com.android.dialer.PhoneCallDetailsHelper; +import com.android.dialer.calllog.PhoneCallDetailsHelper; import com.google.common.collect.Lists; import android.content.Context; -- cgit v1.2.3