1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.dialer.app.calllog.calllogcache;
18 
19 import android.content.Context;
20 import android.support.annotation.Nullable;
21 import android.telecom.PhoneAccountHandle;
22 import android.text.TextUtils;
23 import android.util.ArrayMap;
24 import com.android.dialer.app.calllog.CallLogAdapter;
25 import com.android.dialer.calllogutils.PhoneAccountUtils;
26 import com.android.dialer.telecom.TelecomUtil;
27 import com.android.dialer.util.CallUtil;
28 import java.util.Map;
29 import javax.annotation.concurrent.ThreadSafe;
30 
31 /**
32  * This is the base class for the CallLogCaches.
33  *
34  * <p>Keeps a cache of recently made queries to the Telecom/Telephony processes. The aim of this
35  * cache is to reduce the number of cross-process requests to TelecomManager, which can negatively
36  * affect performance.
37  *
38  * <p>This is designed with the specific use case of the {@link CallLogAdapter} in mind.
39  */
40 @ThreadSafe
41 public class CallLogCache {
42   // TODO: Dialer should be fixed so as not to check isVoicemail() so often but at the time of
43   // this writing, that was a much larger undertaking than creating this cache.
44 
45   protected final Context context;
46 
47   private boolean hasCheckedForVideoAvailability;
48   private int videoAvailability;
49   private final Map<PhoneAccountHandle, String> phoneAccountLabelCache = new ArrayMap<>();
50   private final Map<PhoneAccountHandle, Integer> phoneAccountColorCache = new ArrayMap<>();
51   private final Map<PhoneAccountHandle, Boolean> phoneAccountCallWithNoteCache = new ArrayMap<>();
52 
CallLogCache(Context context)53   public CallLogCache(Context context) {
54     this.context = context;
55   }
56 
reset()57   public synchronized void reset() {
58     phoneAccountLabelCache.clear();
59     phoneAccountColorCache.clear();
60     phoneAccountCallWithNoteCache.clear();
61     hasCheckedForVideoAvailability = false;
62     videoAvailability = 0;
63   }
64 
65   /**
66    * Returns true if the given number is the number of the configured voicemail. To be able to
67    * mock-out this, it is not a static method.
68    */
isVoicemailNumber( PhoneAccountHandle accountHandle, @Nullable CharSequence number)69   public synchronized boolean isVoicemailNumber(
70       PhoneAccountHandle accountHandle, @Nullable CharSequence number) {
71     if (TextUtils.isEmpty(number)) {
72       return false;
73     }
74     return TelecomUtil.isVoicemailNumber(context, accountHandle, number.toString());
75   }
76 
77   /**
78    * Returns {@code true} when the current sim supports checking video calling capabilities via the
79    * {@link android.provider.ContactsContract.CommonDataKinds.Phone#CARRIER_PRESENCE} column.
80    */
canRelyOnVideoPresence()81   public boolean canRelyOnVideoPresence() {
82     if (!hasCheckedForVideoAvailability) {
83       videoAvailability = CallUtil.getVideoCallingAvailability(context);
84       hasCheckedForVideoAvailability = true;
85     }
86     return (videoAvailability & CallUtil.VIDEO_CALLING_PRESENCE) != 0;
87   }
88 
89   /** Extract account label from PhoneAccount object. */
getAccountLabel(PhoneAccountHandle accountHandle)90   public synchronized String getAccountLabel(PhoneAccountHandle accountHandle) {
91     if (phoneAccountLabelCache.containsKey(accountHandle)) {
92       return phoneAccountLabelCache.get(accountHandle);
93     } else {
94       String label = PhoneAccountUtils.getAccountLabel(context, accountHandle);
95       phoneAccountLabelCache.put(accountHandle, label);
96       return label;
97     }
98   }
99 
100   /** Extract account color from PhoneAccount object. */
getAccountColor(PhoneAccountHandle accountHandle)101   public synchronized int getAccountColor(PhoneAccountHandle accountHandle) {
102     if (phoneAccountColorCache.containsKey(accountHandle)) {
103       return phoneAccountColorCache.get(accountHandle);
104     } else {
105       Integer color = PhoneAccountUtils.getAccountColor(context, accountHandle);
106       phoneAccountColorCache.put(accountHandle, color);
107       return color;
108     }
109   }
110 
111   /**
112    * Determines if the PhoneAccount supports specifying a call subject (i.e. calling with a note)
113    * for outgoing calls.
114    *
115    * @param accountHandle The PhoneAccount handle.
116    * @return {@code true} if calling with a note is supported, {@code false} otherwise.
117    */
doesAccountSupportCallSubject(PhoneAccountHandle accountHandle)118   public synchronized boolean doesAccountSupportCallSubject(PhoneAccountHandle accountHandle) {
119     if (phoneAccountCallWithNoteCache.containsKey(accountHandle)) {
120       return phoneAccountCallWithNoteCache.get(accountHandle);
121     } else {
122       Boolean supportsCallWithNote =
123           PhoneAccountUtils.getAccountSupportsCallSubject(context, accountHandle);
124       phoneAccountCallWithNoteCache.put(accountHandle, supportsCallWithNote);
125       return supportsCallWithNote;
126     }
127   }
128 }
129