From b63f4ccc97375947833110dbb910074f122207d3 Mon Sep 17 00:00:00 2001 From: wangqi Date: Mon, 10 Jul 2017 14:27:39 -0700 Subject: Make CallLogCache thread safe. Methods such as getAccountLabel() is called on different threads which may cause race condition issue. This change also delete CallLogCacheLollopopMr1 since it's not necessary that Dialer is targeting M+. Bug: 63415147,63524435 Test: none PiperOrigin-RevId: 161440757 Change-Id: Ia609c52e53dabdce78ffb4320f4cd66e38112e47 --- .../dialer/app/calllog/CallLogFragment.java | 2 +- .../app/calllog/CallLogListItemViewHolder.java | 2 +- .../app/calllog/calllogcache/CallLogCache.java | 62 +++++++++++--- .../calllogcache/CallLogCacheLollipopMr1.java | 96 ---------------------- 4 files changed, 52 insertions(+), 110 deletions(-) delete mode 100644 java/com/android/dialer/app/calllog/calllogcache/CallLogCacheLollipopMr1.java (limited to 'java/com/android/dialer/app') diff --git a/java/com/android/dialer/app/calllog/CallLogFragment.java b/java/com/android/dialer/app/calllog/CallLogFragment.java index 369fbbc91..6d4aea91f 100644 --- a/java/com/android/dialer/app/calllog/CallLogFragment.java +++ b/java/com/android/dialer/app/calllog/CallLogFragment.java @@ -346,7 +346,7 @@ public class CallLogFragment extends Fragment activityType == CallLogAdapter.ACTIVITY_TYPE_DIALTACTS ? (CallLogAdapter.OnActionModeStateChangedListener) getActivity() : null, - CallLogCache.getCallLogCache(getActivity()), + new CallLogCache(getActivity()), mContactInfoCache, getVoicemailPlaybackPresenter(), new FilteredNumberAsyncQueryHandler(getActivity()), diff --git a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java index 27aa82577..884d07d50 100644 --- a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java +++ b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java @@ -353,7 +353,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder View.OnClickListener expandCollapseListener, VoicemailPlaybackPresenter voicemailPlaybackPresenter) { Resources resources = context.getResources(); - CallLogCache callLogCache = CallLogCache.getCallLogCache(context); + CallLogCache callLogCache = new CallLogCache(context); PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(context, resources, callLogCache); diff --git a/java/com/android/dialer/app/calllog/calllogcache/CallLogCache.java b/java/com/android/dialer/app/calllog/calllogcache/CallLogCache.java index 2e7c9339a..15de14318 100644 --- a/java/com/android/dialer/app/calllog/calllogcache/CallLogCache.java +++ b/java/com/android/dialer/app/calllog/calllogcache/CallLogCache.java @@ -19,8 +19,14 @@ package com.android.dialer.app.calllog.calllogcache; import android.content.Context; import android.support.annotation.Nullable; import android.telecom.PhoneAccountHandle; +import android.text.TextUtils; +import android.util.ArrayMap; import com.android.dialer.app.calllog.CallLogAdapter; +import com.android.dialer.calllogutils.PhoneAccountUtils; +import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.util.CallUtil; +import java.util.Map; +import javax.annotation.concurrent.ThreadSafe; /** * This is the base class for the CallLogCaches. @@ -31,7 +37,8 @@ import com.android.dialer.util.CallUtil; * *

This is designed with the specific use case of the {@link CallLogAdapter} in mind. */ -public abstract class CallLogCache { +@ThreadSafe +public class CallLogCache { // 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. @@ -39,17 +46,18 @@ public abstract class CallLogCache { private boolean mHasCheckedForVideoAvailability; private int mVideoAvailability; + private final Map mPhoneAccountLabelCache = new ArrayMap<>(); + private final Map mPhoneAccountColorCache = new ArrayMap<>(); + private final Map mPhoneAccountCallWithNoteCache = new ArrayMap<>(); public CallLogCache(Context context) { mContext = context; } - /** Return the most compatible version of the TelecomCallLogCache. */ - public static CallLogCache getCallLogCache(Context context) { - return new CallLogCacheLollipopMr1(context); - } - - public void reset() { + public synchronized void reset() { + mPhoneAccountLabelCache.clear(); + mPhoneAccountColorCache.clear(); + mPhoneAccountCallWithNoteCache.clear(); mHasCheckedForVideoAvailability = false; mVideoAvailability = 0; } @@ -58,8 +66,13 @@ public abstract class CallLogCache { * 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 abstract boolean isVoicemailNumber( - PhoneAccountHandle accountHandle, @Nullable CharSequence number); + public synchronized boolean isVoicemailNumber( + PhoneAccountHandle accountHandle, @Nullable CharSequence number) { + if (TextUtils.isEmpty(number)) { + return false; + } + return TelecomUtil.isVoicemailNumber(mContext, accountHandle, number.toString()); + } /** * Returns {@code true} when the current sim supports checking video calling capabilities via the @@ -74,10 +87,26 @@ public abstract class CallLogCache { } /** Extract account label from PhoneAccount object. */ - public abstract String getAccountLabel(PhoneAccountHandle accountHandle); + public synchronized 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 abstract int getAccountColor(PhoneAccountHandle accountHandle); + public synchronized 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; + } + } /** * Determines if the PhoneAccount supports specifying a call subject (i.e. calling with a note) @@ -86,5 +115,14 @@ public abstract class CallLogCache { * @param accountHandle The PhoneAccount handle. * @return {@code true} if calling with a note is supported, {@code false} otherwise. */ - public abstract boolean doesAccountSupportCallSubject(PhoneAccountHandle accountHandle); + public synchronized boolean doesAccountSupportCallSubject(PhoneAccountHandle accountHandle) { + if (mPhoneAccountCallWithNoteCache.containsKey(accountHandle)) { + return mPhoneAccountCallWithNoteCache.get(accountHandle); + } else { + Boolean supportsCallWithNote = + PhoneAccountUtils.getAccountSupportsCallSubject(mContext, accountHandle); + mPhoneAccountCallWithNoteCache.put(accountHandle, supportsCallWithNote); + return supportsCallWithNote; + } + } } diff --git a/java/com/android/dialer/app/calllog/calllogcache/CallLogCacheLollipopMr1.java b/java/com/android/dialer/app/calllog/calllogcache/CallLogCacheLollipopMr1.java deleted file mode 100644 index 2424b6dbd..000000000 --- a/java/com/android/dialer/app/calllog/calllogcache/CallLogCacheLollipopMr1.java +++ /dev/null @@ -1,96 +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.app.calllog.calllogcache; - -import android.content.Context; -import android.support.annotation.Nullable; -import android.telecom.PhoneAccountHandle; -import android.text.TextUtils; -import android.util.ArrayMap; -import com.android.dialer.calllogutils.PhoneAccountUtils; -import com.android.dialer.telecom.TelecomUtil; -import java.util.Map; - -/** - * This is the CallLogCache for versions of dialer Lollipop Mr1 and above with support for multi-SIM - * devices. - * - *

This class should not be initialized directly and instead be acquired from {@link - * CallLogCache#getCallLogCache}. - */ -class CallLogCacheLollipopMr1 extends CallLogCache { - - private final Map mPhoneAccountLabelCache = new ArrayMap<>(); - private final Map mPhoneAccountColorCache = new ArrayMap<>(); - private final Map mPhoneAccountCallWithNoteCache = new ArrayMap<>(); - - /* package */ CallLogCacheLollipopMr1(Context context) { - super(context); - } - - @Override - public void reset() { - mPhoneAccountLabelCache.clear(); - mPhoneAccountColorCache.clear(); - mPhoneAccountCallWithNoteCache.clear(); - - super.reset(); - } - - @Override - public boolean isVoicemailNumber( - PhoneAccountHandle accountHandle, @Nullable CharSequence number) { - if (TextUtils.isEmpty(number)) { - return false; - } - return TelecomUtil.isVoicemailNumber(mContext, accountHandle, number.toString()); - } - - @Override - 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; - } - } - - @Override - 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; - } - } - - @Override - public boolean doesAccountSupportCallSubject(PhoneAccountHandle accountHandle) { - if (mPhoneAccountCallWithNoteCache.containsKey(accountHandle)) { - return mPhoneAccountCallWithNoteCache.get(accountHandle); - } else { - Boolean supportsCallWithNote = - PhoneAccountUtils.getAccountSupportsCallSubject(mContext, accountHandle); - mPhoneAccountCallWithNoteCache.put(accountHandle, supportsCallWithNote); - return supportsCallWithNote; - } - } -} -- cgit v1.2.3