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