diff options
author | Santos Cordon <santoscordon@google.com> | 2015-02-06 04:34:32 -0800 |
---|---|---|
committer | Etan Cohen <etancohen@google.com> | 2015-03-02 10:59:58 -0800 |
commit | 8730ff591ed078b3e81d9dd6a2b36cc620fccb1a (patch) | |
tree | 17fb8b67c68191dacef19ed35c59664a89d4c941 | |
parent | d04f11f09fdec8788297a0cdd1ddeda7c819e038 (diff) |
Add cache for isVoicemail check.
bindView() gets called many times at dialer startup and layout updates.
Besides being costly, it invokes cross-process TelecomManager methods.
This change addresses the cross-process issues by adding a short-lived
cache to isVoicemail() method invocations.
Change-Id: Ib69c0eb3969a1b7d77c9fd1a2aa6e578a31fb5e9
-rw-r--r-- | src/com/android/dialer/calllog/CallLogAdapter.java | 2 | ||||
-rw-r--r-- | src/com/android/dialer/calllog/PhoneNumberUtilsWrapper.java | 51 |
2 files changed, 46 insertions, 7 deletions
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java index bb20a1306..225d34948 100644 --- a/src/com/android/dialer/calllog/CallLogAdapter.java +++ b/src/com/android/dialer/calllog/CallLogAdapter.java @@ -633,6 +633,8 @@ public class CallLogAdapter extends GroupingListAdapter /** * Binds the views in the entry to the data in the call log. + * TODO: This gets called 20-30 times when Dialer starts up for a single call log entry and + * should not. It invokes cross-process methods and the repeat execution can get costly. * * @param callLogItemView the view corresponding to this entry * @param c the cursor pointing to the entry in the call log diff --git a/src/com/android/dialer/calllog/PhoneNumberUtilsWrapper.java b/src/com/android/dialer/calllog/PhoneNumberUtilsWrapper.java index 11f4a67f6..6fa81435f 100644 --- a/src/com/android/dialer/calllog/PhoneNumberUtilsWrapper.java +++ b/src/com/android/dialer/calllog/PhoneNumberUtilsWrapper.java @@ -20,13 +20,15 @@ import android.content.Context; import android.provider.CallLog; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; -import android.telephony.PhoneNumberUtils; 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; /** @@ -34,8 +36,20 @@ import java.util.Set; */ public class PhoneNumberUtilsWrapper { private static final Set<String> 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<Pair<PhoneAccountHandle, CharSequence>, Boolean> mVoicemailQueryCache = + new HashMap<>(); + private long mVoicemailCacheTimestamp = 0; + public PhoneNumberUtilsWrapper(Context context) { mContext = context; } @@ -50,11 +64,34 @@ public class PhoneNumberUtilsWrapper { * 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) { - final TelecomManager telecomManager = - (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); - return number!= null && telecomManager.isVoiceMailNumber(accountHandle, number.toString()); + 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<PhoneAccountHandle, CharSequence> 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; + } } /** |