1 /*
2  * Copyright (C) 2017 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.phonelookup;
18 
19 import android.content.Context;
20 import android.support.annotation.MainThread;
21 import android.telecom.Call;
22 import com.android.dialer.DialerPhoneNumber;
23 import com.android.dialer.common.concurrent.DialerExecutorComponent;
24 import com.android.dialer.location.GeoUtil;
25 import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil;
26 import com.android.dialer.telecom.TelecomCallUtil;
27 import com.google.common.collect.ImmutableMap;
28 import com.google.common.collect.ImmutableSet;
29 import com.google.common.util.concurrent.Futures;
30 import com.google.common.util.concurrent.ListenableFuture;
31 import com.google.common.util.concurrent.ListeningExecutorService;
32 import com.google.common.util.concurrent.MoreExecutors;
33 
34 /**
35  * Provides operations related to retrieving information about phone numbers.
36  *
37  * <p>Some operations defined by this interface are generally targeted towards specific use cases;
38  * for example {@link #isDirty(ImmutableSet)}, {@link #getMostRecentInfo(ImmutableMap)}, and {@link
39  * #onSuccessfulBulkUpdate()} are generally intended to be used by the call log.
40  */
41 public interface PhoneLookup<T> {
42 
43   /**
44    * Returns a future containing a new info for the number associated with the provided call.
45    *
46    * <p>The returned message should contain populated data for the sub-message corresponding to this
47    * {@link PhoneLookup}. For example, the CP2 implementation returns a {@link
48    * PhoneLookupInfo.Cp2Info} sub-message.
49    *
50    * <p>The default implementation is for all {@link PhoneLookup} implementations that don't need
51    * info in the given call, i.e., it simply extracts the phone number from the call and delegates
52    * to {@link #lookup(DialerPhoneNumber)}.
53    *
54    * <p>However, for {@link PhoneLookup} implementations that need info in the call (such as one for
55    * CNAP), they should override this method.
56    */
lookup(Context appContext, Call call)57   default ListenableFuture<T> lookup(Context appContext, Call call) {
58     ListeningExecutorService backgroundExecutor =
59         DialerExecutorComponent.get(appContext).backgroundExecutor();
60 
61     ListenableFuture<DialerPhoneNumber> numberFuture =
62         backgroundExecutor.submit(
63             () -> {
64               DialerPhoneNumberUtil dialerPhoneNumberUtil = new DialerPhoneNumberUtil();
65               return dialerPhoneNumberUtil.parse(
66                   TelecomCallUtil.getNumber(call), GeoUtil.getCurrentCountryIso(appContext));
67             });
68 
69     return Futures.transformAsync(numberFuture, this::lookup, MoreExecutors.directExecutor());
70   }
71 
72   /**
73    * Returns a future containing a new info for the provided number.
74    *
75    * <p>The returned message should contain populated data for the sub-message corresponding to this
76    * {@link PhoneLookup}. For example, the CP2 implementation returns a {@link
77    * PhoneLookupInfo.Cp2Info} sub-message.
78    *
79    * <p>If the lookup can't be done without info in a {@link Call} (e.g., CNAP), this method is
80    * expected to return existing info saved during the most recent lookup for a call to/from the
81    * provided number ({@link #lookup(Context, Call)}).
82    */
lookup(DialerPhoneNumber dialerPhoneNumber)83   ListenableFuture<T> lookup(DialerPhoneNumber dialerPhoneNumber);
84 
85   /**
86    * Returns a future which returns true if the information for any of the provided phone numbers
87    * has changed, usually since {@link #onSuccessfulBulkUpdate()} was last invoked.
88    */
isDirty(ImmutableSet<DialerPhoneNumber> phoneNumbers)89   ListenableFuture<Boolean> isDirty(ImmutableSet<DialerPhoneNumber> phoneNumbers);
90 
91   /**
92    * Get the most recent phone lookup information for this {@link PhoneLookup}. The returned map
93    * must contain the exact same keys as the provided map. Most implementations will rely on last
94    * modified timestamps to efficiently only update the data which needs to be updated.
95    *
96    * <p>If there are no changes required, it is valid for this method to simply return the provided
97    * {@code existingInfoMap}.
98    *
99    * <p>If there is no longer information associated with a number (for example, a local contact was
100    * deleted) the returned map should contain an empty info for that number.
101    */
getMostRecentInfo( ImmutableMap<DialerPhoneNumber, T> existingInfoMap)102   ListenableFuture<ImmutableMap<DialerPhoneNumber, T>> getMostRecentInfo(
103       ImmutableMap<DialerPhoneNumber, T> existingInfoMap);
104 
105   /**
106    * Populates the sub-message that this {@link PhoneLookup} is responsible for by copying {@code
107    * subMessage} into the provided {@code phoneLookupInfo} builder.
108    */
setSubMessage(PhoneLookupInfo.Builder phoneLookupInfo, T subMessage)109   void setSubMessage(PhoneLookupInfo.Builder phoneLookupInfo, T subMessage);
110 
111   /**
112    * Gets the sub-message that this {@link PhoneLookup} is responsible for from the provided {@code
113    * phoneLookupInfo}.
114    */
getSubMessage(PhoneLookupInfo phoneLookupInfo)115   T getSubMessage(PhoneLookupInfo phoneLookupInfo);
116 
117   /**
118    * Called when the results of the {@link #getMostRecentInfo(ImmutableMap)} have been applied by
119    * the caller.
120    *
121    * <p>Typically implementations will use this to store a "last processed" timestamp so that future
122    * invocations of {@link #isDirty(ImmutableSet)} and {@link #getMostRecentInfo(ImmutableMap)} can
123    * be efficiently implemented.
124    */
onSuccessfulBulkUpdate()125   ListenableFuture<Void> onSuccessfulBulkUpdate();
126 
127   @MainThread
registerContentObservers()128   void registerContentObservers();
129 
130   @MainThread
unregisterContentObservers()131   void unregisterContentObservers();
132 
133   /**
134    * Clear any data written by this lookup. This is called when the new call log framework has been
135    * disabled (because for example there was a problem with it).
136    */
clearData()137   ListenableFuture<Void> clearData();
138 
139   /**
140    * The name of this lookup for logging purposes. This is generally the same as the class name (but
141    * should not use methods from {@link Class} because the class names are generally obfuscated by
142    * Proguard.
143    */
getLoggingName()144   String getLoggingName();
145 }
146