summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSantos Cordon <santoscordon@google.com>2015-02-06 04:34:32 -0800
committerSantos Cordon <santoscordon@google.com>2015-02-19 22:46:01 -0800
commita9a82f52cbcadd0b9a4aafa0c785c0d6af629f1c (patch)
tree4d399f2124cc4a3aa6da2558392faf0d72f2a72e
parente65f03182eb76fabe8337a82fc3eef7230b669a1 (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.java2
-rw-r--r--src/com/android/dialer/calllog/PhoneNumberUtilsWrapper.java51
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 9c50a3b73..b6f91e75b 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -631,6 +631,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;
+ }
}
/**