From 98280255db8824cb58caac596cb4f9febcf57306 Mon Sep 17 00:00:00 2001 From: twyen Date: Thu, 11 Jan 2018 14:21:46 -0800 Subject: Attempt to place call even call permission is missing Telecom might still allow emergency calls to be placed if dialer is the default dialer. Bug: 71739167 Test: Unit tests. PiperOrigin-RevId: 181661814 Change-Id: I24063ee42d646c4b614f3fdeb5685490f064a898 --- java/com/android/dialer/precall/impl/PermissionCheckAction.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'java/com/android/dialer') diff --git a/java/com/android/dialer/precall/impl/PermissionCheckAction.java b/java/com/android/dialer/precall/impl/PermissionCheckAction.java index b57b37a6f..85e9ceb9c 100644 --- a/java/com/android/dialer/precall/impl/PermissionCheckAction.java +++ b/java/com/android/dialer/precall/impl/PermissionCheckAction.java @@ -21,14 +21,14 @@ import android.widget.Toast; import com.android.dialer.callintent.CallIntentBuilder; import com.android.dialer.precall.PreCallAction; import com.android.dialer.precall.PreCallCoordinator; -import com.android.dialer.util.PermissionsUtil; +import com.android.dialer.telecom.TelecomUtil; /** Aborts call and show a toast if phone permissions are missing. */ public class PermissionCheckAction implements PreCallAction { @Override public boolean requiresUi(Context context, CallIntentBuilder builder) { - return !PermissionsUtil.hasPhonePermissions(context); + return !TelecomUtil.hasCallPhonePermission(context); } @Override -- cgit v1.2.3 From 188b42fd10644373175fc204b48da98125004985 Mon Sep 17 00:00:00 2001 From: twyen Date: Thu, 11 Jan 2018 16:03:11 -0800 Subject: Merge PhoneLookupDataSource results into a proto in annotated call log. This allow extra information from PhoneLookup to be more easily added. Only PhoneLookupSelector and the proto will be affected for new attributes. Test: Unit tests. PiperOrigin-RevId: 181675568 Change-Id: I4e0bc1c6005b58a9b684b030b55bea6223af9ce3 --- .../database/AnnotatedCallLogDatabaseHelper.java | 10 +-- .../contract/AnnotatedCallLogContract.java | 80 ++-------------------- .../phonelookup/PhoneLookupDataSource.java | 36 +++++----- .../android/dialer/calllog/model/CoalescedRow.java | 47 ++----------- .../dialer/calllog/model/number_attributes.proto | 61 +++++++++++++++++ .../ui/CoalescedAnnotatedCallLogCursorLoader.java | 52 ++++++-------- .../dialer/calllog/ui/NewCallLogViewHolder.java | 12 +++- .../dialer/calllog/ui/RealtimeRowProcessor.java | 20 ++++-- .../android/dialer/calllog/ui/menu/Modules.java | 28 ++++---- .../dialer/calllog/ui/menu/PrimaryAction.java | 6 +- .../dialer/calllogutils/CallLogEntryText.java | 8 +-- .../phonelookup/selector/PhoneLookupSelector.java | 16 ++++- .../voicemail/listui/NewVoicemailViewHolder.java | 14 ++-- .../voicemail/listui/VoicemailCursorLoader.java | 40 +++++------ .../voicemail/listui/VoicemailEntryText.java | 4 +- .../dialer/voicemail/listui/menu/Modules.java | 4 +- .../voicemail/listui/menu/PrimaryAction.java | 10 +-- .../dialer/voicemail/model/VoicemailEntry.java | 25 ++----- 18 files changed, 214 insertions(+), 259 deletions(-) create mode 100644 java/com/android/dialer/calllog/model/number_attributes.proto (limited to 'java/com/android/dialer') diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java index f90d657b8..da93ff8a3 100644 --- a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java +++ b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java @@ -38,15 +38,10 @@ class AnnotatedCallLogDatabaseHelper extends SQLiteOpenHelper { + " (" + (AnnotatedCallLog._ID + " integer primary key, ") + (AnnotatedCallLog.TIMESTAMP + " integer, ") - + (AnnotatedCallLog.NAME + " text, ") + (AnnotatedCallLog.NUMBER + " blob, ") + (AnnotatedCallLog.FORMATTED_NUMBER + " text, ") - + (AnnotatedCallLog.PHOTO_URI + " text, ") - + (AnnotatedCallLog.PHOTO_ID + " integer, ") - + (AnnotatedCallLog.LOOKUP_URI + " text, ") + (AnnotatedCallLog.DURATION + " integer, ") + (AnnotatedCallLog.DATA_USAGE + " integer, ") - + (AnnotatedCallLog.NUMBER_TYPE_LABEL + " text, ") + (AnnotatedCallLog.IS_READ + " integer, ") + (AnnotatedCallLog.NEW + " integer, ") + (AnnotatedCallLog.GEOCODED_LOCATION + " text, ") @@ -55,13 +50,10 @@ class AnnotatedCallLogDatabaseHelper extends SQLiteOpenHelper { + (AnnotatedCallLog.PHONE_ACCOUNT_LABEL + " text, ") + (AnnotatedCallLog.PHONE_ACCOUNT_COLOR + " integer, ") + (AnnotatedCallLog.FEATURES + " integer, ") - + (AnnotatedCallLog.IS_BUSINESS + " integer, ") - + (AnnotatedCallLog.IS_VOICEMAIL + " integer, ") + (AnnotatedCallLog.TRANSCRIPTION + " integer, ") + (AnnotatedCallLog.VOICEMAIL_URI + " text, ") + (AnnotatedCallLog.CALL_TYPE + " integer, ") - + (AnnotatedCallLog.CAN_REPORT_AS_INVALID_NUMBER + " integer, ") - + (AnnotatedCallLog.CP2_INFO_INCOMPLETE + " integer") + + (AnnotatedCallLog.NUMBER_ATTRIBUTES + " blob ") + ");"; /** Deletes all but the first maxRows rows (by timestamp) to keep the table a manageable size. */ diff --git a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java index 9161d6087..d382517cd 100644 --- a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java +++ b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java @@ -41,15 +41,6 @@ public class AnnotatedCallLogContract { */ String TIMESTAMP = "timestamp"; - /** - * The name (which may be a person's name or business name, but not a number) formatted exactly - * as it should appear to the user. If the user's locale or name display preferences change, - * this column should be rewritten. - * - *

Type: TEXT - */ - String NAME = "name"; - /** * The phone number called or number the call came from, encoded as a {@link * com.android.dialer.DialerPhoneNumber} proto. The number may be empty if it was an incoming @@ -67,38 +58,6 @@ public class AnnotatedCallLogContract { */ String FORMATTED_NUMBER = "formatted_number"; - /** - * A photo URI for the contact to display in the call log list view. - * - *

TYPE: TEXT - */ - String PHOTO_URI = "photo_uri"; - - /** - * A photo ID (from the contacts provider) for the contact to display in the call log list view. - * - *

Type: INTEGER (long) - */ - String PHOTO_ID = "photo_id"; - - /** - * The contacts provider lookup URI for the contact associated with the call. - * - *

TYPE: TEXT - */ - String LOOKUP_URI = "lookup_uri"; - - // TODO(zachh): If we need to support photos other than local contacts', add a (blob?) column. - - /** - * The number type as a string to be displayed to the user, for example "Home" or "Mobile". - * - *

This column should be updated for the appropriate language when the locale changes. - * - *

TYPE: TEXT - */ - String NUMBER_TYPE_LABEL = "number_type_label"; - /** * See {@link android.provider.CallLog.Calls#IS_READ}. * @@ -156,20 +115,13 @@ public class AnnotatedCallLogContract { String FEATURES = "features"; /** - * True if a caller ID data source informed us that this is a business number. This is used to - * determine if a generic business avatar should be shown vs. a generic person avatar. + * Additional attributes about the number. * - *

TYPE: INTEGER (boolean) - */ - String IS_BUSINESS = "is_business"; - - /** - * True if this was a call to voicemail. This is used to determine if the voicemail avatar - * should be displayed. + *

TYPE: BLOB * - *

TYPE: INTEGER (boolean) + * @see com.android.dialer.calllog.model.NumberAttributes */ - String IS_VOICEMAIL = "is_voicemail"; + String NUMBER_ATTRIBUTES = "number_attributes"; /** * Copied from {@link android.provider.CallLog.Calls#TYPE}. @@ -178,31 +130,12 @@ public class AnnotatedCallLogContract { */ String CALL_TYPE = "call_type"; - /** - * True if the number can be reported as invalid. - * - *

TYPE: INTEGER (boolean) - */ - String CAN_REPORT_AS_INVALID_NUMBER = "can_report_as_invalid_number"; - - /** - * True if the CP2 information is incomplete and needs to be queried at display time. - * - *

TYPE: INTEGER (boolean) - */ - String CP2_INFO_INCOMPLETE = "cp2_info_incomplete"; - String[] ALL_COMMON_COLUMNS = new String[] { _ID, TIMESTAMP, - NAME, NUMBER, FORMATTED_NUMBER, - PHOTO_URI, - PHOTO_ID, - LOOKUP_URI, - NUMBER_TYPE_LABEL, IS_READ, NEW, GEOCODED_LOCATION, @@ -211,11 +144,8 @@ public class AnnotatedCallLogContract { PHONE_ACCOUNT_LABEL, PHONE_ACCOUNT_COLOR, FEATURES, - IS_BUSINESS, - IS_VOICEMAIL, + NUMBER_ATTRIBUTES, CALL_TYPE, - CAN_REPORT_AS_INVALID_NUMBER, - CP2_INFO_INCOMPLETE }; } diff --git a/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java b/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java index 30461a4be..b73c169b9 100644 --- a/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java +++ b/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java @@ -28,6 +28,7 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import com.android.dialer.DialerPhoneNumber; +import com.android.dialer.NumberAttributes; import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog; import com.android.dialer.calllog.datasources.CallLogDataSource; import com.android.dialer.calllog.datasources.CallLogMutations; @@ -286,13 +287,7 @@ public final class PhoneLookupDataSource @Override public ContentValues coalesce(List individualRowsSortedByTimestampDesc) { return new RowCombiner(individualRowsSortedByTimestampDesc) - .useMostRecentString(AnnotatedCallLog.NAME) - .useMostRecentString(AnnotatedCallLog.NUMBER_TYPE_LABEL) - .useMostRecentString(AnnotatedCallLog.PHOTO_URI) - .useMostRecentLong(AnnotatedCallLog.PHOTO_ID) - .useMostRecentString(AnnotatedCallLog.LOOKUP_URI) - .useMostRecentInt(AnnotatedCallLog.CAN_REPORT_AS_INVALID_NUMBER) - .useMostRecentInt(AnnotatedCallLog.CP2_INFO_INCOMPLETE) + .useMostRecentBlob(AnnotatedCallLog.NUMBER_ATTRIBUTES) .combine(); } @@ -584,19 +579,20 @@ public final class PhoneLookupDataSource } private void updateContentValues(ContentValues contentValues, PhoneLookupInfo phoneLookupInfo) { - contentValues.put(AnnotatedCallLog.NAME, phoneLookupSelector.selectName(phoneLookupInfo)); contentValues.put( - AnnotatedCallLog.PHOTO_URI, phoneLookupSelector.selectPhotoUri(phoneLookupInfo)); - contentValues.put( - AnnotatedCallLog.PHOTO_ID, phoneLookupSelector.selectPhotoId(phoneLookupInfo)); - contentValues.put( - AnnotatedCallLog.LOOKUP_URI, phoneLookupSelector.selectLookupUri(phoneLookupInfo)); - contentValues.put( - AnnotatedCallLog.NUMBER_TYPE_LABEL, phoneLookupSelector.selectNumberLabel(phoneLookupInfo)); - contentValues.put( - AnnotatedCallLog.CAN_REPORT_AS_INVALID_NUMBER, - PhoneLookupSelector.canReportAsInvalidNumber(phoneLookupInfo)); - contentValues.put( - AnnotatedCallLog.CP2_INFO_INCOMPLETE, phoneLookupInfo.getCp2LocalInfo().getIsIncomplete()); + AnnotatedCallLog.NUMBER_ATTRIBUTES, + NumberAttributes.newBuilder() + .setName(phoneLookupSelector.selectName(phoneLookupInfo)) + .setPhotoUri(phoneLookupSelector.selectPhotoUri(phoneLookupInfo)) + .setPhotoId(phoneLookupSelector.selectPhotoId(phoneLookupInfo)) + .setLookupUri(phoneLookupSelector.selectLookupUri(phoneLookupInfo)) + .setNumberTypeLabel(phoneLookupSelector.selectNumberLabel(phoneLookupInfo)) + .setIsBusiness(phoneLookupSelector.selectIsBusiness(phoneLookupInfo)) + .setIsVoicemail(phoneLookupSelector.selectIsVoicemail(phoneLookupInfo)) + .setCanReportAsInvalidNumber( + phoneLookupSelector.canReportAsInvalidNumber(phoneLookupInfo)) + .setIsCp2InfoIncomplete(phoneLookupSelector.selectIsCp2InfoIncomplete(phoneLookupInfo)) + .build() + .toByteArray()); } } diff --git a/java/com/android/dialer/calllog/model/CoalescedRow.java b/java/com/android/dialer/calllog/model/CoalescedRow.java index 2520d996a..312c29cc0 100644 --- a/java/com/android/dialer/calllog/model/CoalescedRow.java +++ b/java/com/android/dialer/calllog/model/CoalescedRow.java @@ -20,6 +20,7 @@ import android.support.annotation.ColorInt; import android.support.annotation.Nullable; import com.android.dialer.CoalescedIds; import com.android.dialer.DialerPhoneNumber; +import com.android.dialer.NumberAttributes; import com.google.auto.value.AutoValue; /** Data class containing the contents of a row from the CoalescedAnnotatedCallLog. */ @@ -31,16 +32,12 @@ public abstract class CoalescedRow { .setId(0) .setTimestamp(0) .setNumber(DialerPhoneNumber.getDefaultInstance()) - .setPhotoId(0) .setIsRead(false) .setIsNew(false) .setPhoneAccountColor(0) .setFeatures(0) - .setIsBusiness(false) - .setIsVoicemail(false) .setCallType(0) - .setCanReportAsInvalidNumber(false) - .setCp2InfoIncomplete(false) + .setNumberAttributes(NumberAttributes.getDefaultInstance()) .setCoalescedIds(CoalescedIds.getDefaultInstance()); } @@ -52,23 +49,9 @@ public abstract class CoalescedRow { public abstract DialerPhoneNumber number(); - @Nullable - public abstract String name(); - @Nullable public abstract String formattedNumber(); - @Nullable - public abstract String photoUri(); - - public abstract long photoId(); - - @Nullable - public abstract String lookupUri(); - - @Nullable - public abstract String numberTypeLabel(); - public abstract boolean isRead(); public abstract boolean isNew(); @@ -90,15 +73,9 @@ public abstract class CoalescedRow { public abstract int features(); - public abstract boolean isBusiness(); - - public abstract boolean isVoicemail(); - public abstract int callType(); - public abstract boolean canReportAsInvalidNumber(); - - public abstract boolean cp2InfoIncomplete(); + public abstract NumberAttributes numberAttributes(); public abstract CoalescedIds coalescedIds(); @@ -112,18 +89,8 @@ public abstract class CoalescedRow { public abstract Builder setNumber(DialerPhoneNumber number); - public abstract Builder setName(@Nullable String name); - public abstract Builder setFormattedNumber(@Nullable String formattedNumber); - public abstract Builder setPhotoUri(@Nullable String photoUri); - - public abstract Builder setPhotoId(long photoId); - - public abstract Builder setLookupUri(@Nullable String lookupUri); - - public abstract Builder setNumberTypeLabel(@Nullable String numberTypeLabel); - public abstract Builder setIsRead(boolean isRead); public abstract Builder setIsNew(boolean isNew); @@ -141,15 +108,9 @@ public abstract class CoalescedRow { public abstract Builder setFeatures(int features); - public abstract Builder setIsBusiness(boolean isBusiness); - - public abstract Builder setIsVoicemail(boolean isVoicemail); - public abstract Builder setCallType(int callType); - public abstract Builder setCanReportAsInvalidNumber(boolean canReportAsInvalidNumber); - - public abstract Builder setCp2InfoIncomplete(boolean cp2InfoIncomplete); + public abstract Builder setNumberAttributes(NumberAttributes numberAttributes); public abstract Builder setCoalescedIds(CoalescedIds coalescedIds); diff --git a/java/com/android/dialer/calllog/model/number_attributes.proto b/java/com/android/dialer/calllog/model/number_attributes.proto new file mode 100644 index 000000000..64f8f180e --- /dev/null +++ b/java/com/android/dialer/calllog/model/number_attributes.proto @@ -0,0 +1,61 @@ +// Copyright (C) 2018 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 + +syntax = "proto2"; + +option java_package = "com.android.dialer"; +option java_multiple_files = true; +option optimize_for = LITE_RUNTIME; + + +package com.android.dialer; + +// Information related to the phone number of the call. +message NumberAttributes { + // The name (which may be a person's name or business name, but not a number) + // formatted exactly as it should appear to the user. If the user's locale or + // name display preferences change, this field should be rewritten. + optional string name = 1; + + // A photo URI for the contact to display in the call log list view. + optional string photo_uri = 2; + + // A photo ID (from the contacts provider) for the contact to display in the + // call log list view. + optional int64 photo_id = 3; + + // TODO(zachh): If we need to support photos other than local contacts', add a + // (blob?) column. + + // The contacts provider lookup URI for the contact associated with the call. + optional string lookup_uri = 4; + + // The number type as a string to be displayed to the user, for example "Home" + // or "Mobile". This column should be updated for the appropriate language + // when the locale changes. + optional string number_type_label = 5; + + // The number is a call to a business from nearby places lookup. + optional bool is_business = 6; + + // The number is a call to the voicemail inbox. + optional bool is_voicemail = 7; + + // Can the number be reported as invalid through People API + optional bool can_report_as_invalid_number = 8; + + // True if the CP2 information is incomplete and needs to be queried at + // display time. + optional bool is_cp2_info_incomplete = 9; +} \ No newline at end of file diff --git a/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java b/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java index 5c0ce2816..d72544b56 100644 --- a/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java +++ b/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java @@ -21,6 +21,7 @@ import android.database.Cursor; import android.support.v4.content.CursorLoader; import com.android.dialer.CoalescedIds; import com.android.dialer.DialerPhoneNumber; +import com.android.dialer.NumberAttributes; import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog; import com.android.dialer.calllog.model.CoalescedRow; import com.google.protobuf.InvalidProtocolBufferException; @@ -31,27 +32,19 @@ final class CoalescedAnnotatedCallLogCursorLoader extends CursorLoader { // Indexes for CoalescedAnnotatedCallLog.ALL_COLUMNS private static final int ID = 0; private static final int TIMESTAMP = 1; - private static final int NAME = 2; - private static final int NUMBER = 3; - private static final int FORMATTED_NUMBER = 4; - private static final int PHOTO_URI = 5; - private static final int PHOTO_ID = 6; - private static final int LOOKUP_URI = 7; - private static final int NUMBER_TYPE_LABEL = 8; - private static final int IS_READ = 9; - private static final int NEW = 10; - private static final int GEOCODED_LOCATION = 11; - private static final int PHONE_ACCOUNT_COMPONENT_NAME = 12; - private static final int PHONE_ACCOUNT_ID = 13; - private static final int PHONE_ACCOUNT_LABEL = 14; - private static final int PHONE_ACCOUNT_COLOR = 15; - private static final int FEATURES = 16; - private static final int IS_BUSINESS = 17; - private static final int IS_VOICEMAIL = 18; - private static final int CALL_TYPE = 19; - private static final int CAN_REPORT_AS_INVALID_NUMBER = 20; - private static final int CP2_INFO_INCOMPLETE = 21; - private static final int COALESCED_IDS = 22; + private static final int NUMBER = 2; + private static final int FORMATTED_NUMBER = 3; + private static final int IS_READ = 4; + private static final int NEW = 5; + private static final int GEOCODED_LOCATION = 6; + private static final int PHONE_ACCOUNT_COMPONENT_NAME = 7; + private static final int PHONE_ACCOUNT_ID = 8; + private static final int PHONE_ACCOUNT_LABEL = 9; + private static final int PHONE_ACCOUNT_COLOR = 10; + private static final int FEATURES = 11; + private static final int NUMBER_ATTRIBUTES = 12; + private static final int CALL_TYPE = 13; + private static final int COALESCED_IDS = 14; CoalescedAnnotatedCallLogCursorLoader(Context context) { // CoalescedAnnotatedCallLog requires that PROJECTION be ALL_COLUMNS and the following params be @@ -81,16 +74,18 @@ final class CoalescedAnnotatedCallLogCursorLoader extends CursorLoader { throw new IllegalStateException("Couldn't parse CoalescedIds bytes"); } + NumberAttributes numberAttributes; + try { + numberAttributes = NumberAttributes.parseFrom(cursor.getBlob(NUMBER_ATTRIBUTES)); + } catch (InvalidProtocolBufferException e) { + throw new IllegalStateException("Couldn't parse NumberAttributes bytes"); + } + return CoalescedRow.builder() .setId(cursor.getInt(ID)) .setTimestamp(cursor.getLong(TIMESTAMP)) - .setName(cursor.getString(NAME)) .setNumber(number) .setFormattedNumber(cursor.getString(FORMATTED_NUMBER)) - .setPhotoUri(cursor.getString(PHOTO_URI)) - .setPhotoId(cursor.getLong(PHOTO_ID)) - .setLookupUri(cursor.getString(LOOKUP_URI)) - .setNumberTypeLabel(cursor.getString(NUMBER_TYPE_LABEL)) .setIsRead(cursor.getInt(IS_READ) == 1) .setIsNew(cursor.getInt(NEW) == 1) .setGeocodedLocation(cursor.getString(GEOCODED_LOCATION)) @@ -99,11 +94,8 @@ final class CoalescedAnnotatedCallLogCursorLoader extends CursorLoader { .setPhoneAccountLabel(cursor.getString(PHONE_ACCOUNT_LABEL)) .setPhoneAccountColor(cursor.getInt(PHONE_ACCOUNT_COLOR)) .setFeatures(cursor.getInt(FEATURES)) - .setIsBusiness(cursor.getInt(IS_BUSINESS) == 1) - .setIsVoicemail(cursor.getInt(IS_VOICEMAIL) == 1) .setCallType(cursor.getInt(CALL_TYPE)) - .setCanReportAsInvalidNumber(cursor.getInt(CAN_REPORT_AS_INVALID_NUMBER) == 1) - .setCp2InfoIncomplete(cursor.getInt(CP2_INFO_INCOMPLETE) == 1) + .setNumberAttributes(numberAttributes) .setCoalescedIds(coalescedIds) .build(); } diff --git a/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java b/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java index 7482efdea..5b526b49d 100644 --- a/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java +++ b/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java @@ -20,6 +20,7 @@ import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.provider.CallLog.Calls; +import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.view.View; @@ -134,13 +135,18 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder { ContactPhotoManager.getInstance(context) .loadDialerThumbnailOrPhoto( quickContactBadge, - TextUtils.isEmpty(row.lookupUri()) ? null : Uri.parse(row.lookupUri()), - row.photoId(), - TextUtils.isEmpty(row.photoUri()) ? null : Uri.parse(row.photoUri()), + parseUri(row.numberAttributes().getLookupUri()), + row.numberAttributes().getPhotoId(), + parseUri(row.numberAttributes().getPhotoUri()), CallLogEntryText.buildPrimaryText(context, row).toString(), CallLogContactTypes.getContactType(row)); } + @Nullable + private static Uri parseUri(@Nullable String uri) { + return TextUtils.isEmpty(uri) ? null : Uri.parse(uri); + } + private void setPrimaryCallTypes(CoalescedRow row) { primaryCallTypeIconsView.setShowHd( (row.features() & Calls.FEATURES_HD_CALL) == Calls.FEATURES_HD_CALL); diff --git a/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java b/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java index 74b7defb0..2cfe0b4ad 100644 --- a/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java +++ b/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java @@ -19,6 +19,7 @@ package com.android.dialer.calllog.ui; import android.support.annotation.MainThread; import android.util.ArrayMap; import com.android.dialer.DialerPhoneNumber; +import com.android.dialer.NumberAttributes; import com.android.dialer.calllog.model.CoalescedRow; import com.android.dialer.common.concurrent.Annotations.Ui; import com.android.dialer.phonelookup.PhoneLookupInfo; @@ -68,7 +69,7 @@ public final class RealtimeRowProcessor { @MainThread ListenableFuture> applyRealtimeProcessing(final CoalescedRow row) { // Cp2LocalPhoneLookup can not always efficiently process all rows. - if (!row.cp2InfoIncomplete()) { + if (!row.numberAttributes().getIsCp2InfoIncomplete()) { return Futures.immediateFuture(Optional.absent()); } @@ -97,11 +98,18 @@ public final class RealtimeRowProcessor { PhoneLookupInfo phoneLookupInfo = PhoneLookupInfo.newBuilder().setCp2LocalInfo(cp2Info).build(); // It is safe to overwrite any existing data because CP2 always has highest priority. return row.toBuilder() - .setName(phoneLookupSelector.selectName(phoneLookupInfo)) - .setPhotoUri(phoneLookupSelector.selectPhotoUri(phoneLookupInfo)) - .setPhotoId(phoneLookupSelector.selectPhotoId(phoneLookupInfo)) - .setLookupUri(phoneLookupSelector.selectLookupUri(phoneLookupInfo)) - .setNumberTypeLabel(phoneLookupSelector.selectNumberLabel(phoneLookupInfo)) + .setNumberAttributes( + NumberAttributes.newBuilder() + .setName(phoneLookupSelector.selectName(phoneLookupInfo)) + .setPhotoUri(phoneLookupSelector.selectPhotoUri(phoneLookupInfo)) + .setPhotoId(phoneLookupSelector.selectPhotoId(phoneLookupInfo)) + .setLookupUri(phoneLookupSelector.selectLookupUri(phoneLookupInfo)) + .setNumberTypeLabel(phoneLookupSelector.selectNumberLabel(phoneLookupInfo)) + .setIsBusiness(phoneLookupSelector.selectIsBusiness(phoneLookupInfo)) + .setIsVoicemail(phoneLookupSelector.selectIsVoicemail(phoneLookupInfo)) + .setCanReportAsInvalidNumber( + phoneLookupSelector.canReportAsInvalidNumber(phoneLookupInfo)) + .build()) .build(); } } diff --git a/java/com/android/dialer/calllog/ui/menu/Modules.java b/java/com/android/dialer/calllog/ui/menu/Modules.java index 3d667fc79..92dd41163 100644 --- a/java/com/android/dialer/calllog/ui/menu/Modules.java +++ b/java/com/android/dialer/calllog/ui/menu/Modules.java @@ -45,7 +45,11 @@ final class Modules { maybeAddModuleForVideoOrAudioCall(context, modules, row); SharedModules.maybeAddModuleForAddingToContacts( - context, modules, row.number(), row.name(), row.lookupUri()); + context, + modules, + row.number(), + row.numberAttributes().getName(), + row.numberAttributes().getLookupUri()); String originalNumber = row.number().getRawInput().getNumber(); SharedModules.maybeAddModuleForSendingTextMessage(context, modules, originalNumber); @@ -98,8 +102,8 @@ final class Modules { private static void addModuleForAccessingCallDetails( Context context, List modules, CoalescedRow row) { - boolean canReportAsInvalidNumber = row.canReportAsInvalidNumber(); - boolean canSupportAssistedDialing = !TextUtils.isEmpty(row.lookupUri()); + boolean canReportAsInvalidNumber = row.numberAttributes().getCanReportAsInvalidNumber(); + boolean canSupportAssistedDialing = !TextUtils.isEmpty(row.numberAttributes().getLookupUri()); modules.add( new IntentModule( @@ -122,21 +126,21 @@ final class Modules { DialerContact.newBuilder() .setNumber(originalNumber) .setContactType(LetterTileDrawable.TYPE_DEFAULT) // TODO(zachh): Use proper type. - .setPhotoId(row.photoId()); + .setPhotoId(row.numberAttributes().getPhotoId()); - if (!TextUtils.isEmpty(row.name())) { - dialerContactBuilder.setNameOrNumber(row.name()); + if (!TextUtils.isEmpty(row.numberAttributes().getName())) { + dialerContactBuilder.setNameOrNumber(row.numberAttributes().getName()); } else if (!TextUtils.isEmpty(originalNumber)) { dialerContactBuilder.setNameOrNumber(originalNumber); } - if (row.numberTypeLabel() != null) { - dialerContactBuilder.setNumberLabel(row.numberTypeLabel()); + if (row.numberAttributes().hasNumberTypeLabel()) { + dialerContactBuilder.setNumberLabel(row.numberAttributes().getNumberTypeLabel()); } - if (row.photoUri() != null) { - dialerContactBuilder.setPhotoUri(row.photoUri()); + if (row.numberAttributes().hasPhotoUri()) { + dialerContactBuilder.setPhotoUri(row.numberAttributes().getPhotoUri()); } - if (row.lookupUri() != null) { - dialerContactBuilder.setContactUri(row.lookupUri()); + if (row.numberAttributes().hasLookupUri()) { + dialerContactBuilder.setContactUri(row.numberAttributes().getLookupUri()); } if (row.formattedNumber() != null) { dialerContactBuilder.setDisplayNumber(row.formattedNumber()); diff --git a/java/com/android/dialer/calllog/ui/menu/PrimaryAction.java b/java/com/android/dialer/calllog/ui/menu/PrimaryAction.java index faedc8f62..c7126e9dc 100644 --- a/java/com/android/dialer/calllog/ui/menu/PrimaryAction.java +++ b/java/com/android/dialer/calllog/ui/menu/PrimaryAction.java @@ -34,9 +34,9 @@ final class PrimaryAction { .setNumber(row.number()) .setPhotoInfo( PhotoInfo.builder() - .setPhotoId(row.photoId()) - .setPhotoUri(row.photoUri()) - .setLookupUri(row.lookupUri()) + .setPhotoId(row.numberAttributes().getPhotoId()) + .setPhotoUri(row.numberAttributes().getPhotoUri()) + .setLookupUri(row.numberAttributes().getLookupUri()) .setIsVideo((row.features() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO) .setContactType(CallLogContactTypes.getContactType(row)) .setDisplayName(primaryText.toString()) diff --git a/java/com/android/dialer/calllogutils/CallLogEntryText.java b/java/com/android/dialer/calllogutils/CallLogEntryText.java index 873f9ebd0..1df44583f 100644 --- a/java/com/android/dialer/calllogutils/CallLogEntryText.java +++ b/java/com/android/dialer/calllogutils/CallLogEntryText.java @@ -38,8 +38,8 @@ public final class CallLogEntryText { */ public static CharSequence buildPrimaryText(Context context, CoalescedRow row) { StringBuilder primaryText = new StringBuilder(); - if (!TextUtils.isEmpty(row.name())) { - primaryText.append(row.name()); + if (!TextUtils.isEmpty(row.numberAttributes().getName())) { + primaryText.append(row.numberAttributes().getName()); } else if (!TextUtils.isEmpty(row.formattedNumber())) { primaryText.append(row.formattedNumber()); } else { @@ -98,7 +98,7 @@ public final class CallLogEntryText { */ StringBuilder secondaryText = secondaryTextPrefix(context, row); - if (TextUtils.isEmpty(row.name())) { + if (TextUtils.isEmpty(row.numberAttributes().getName())) { // If the name is empty the number is shown as the primary text and there's nothing to add. return secondaryText.toString(); } @@ -128,7 +128,7 @@ public final class CallLogEntryText { // TODO(zachh): Add "Duo" prefix? secondaryText.append(context.getText(R.string.new_call_log_video)); } - String numberTypeLabel = row.numberTypeLabel(); + String numberTypeLabel = row.numberAttributes().getNumberTypeLabel(); if (!TextUtils.isEmpty(numberTypeLabel)) { if (secondaryText.length() > 0) { secondaryText.append(", "); diff --git a/java/com/android/dialer/phonelookup/selector/PhoneLookupSelector.java b/java/com/android/dialer/phonelookup/selector/PhoneLookupSelector.java index 6b217e951..8d082911c 100644 --- a/java/com/android/dialer/phonelookup/selector/PhoneLookupSelector.java +++ b/java/com/android/dialer/phonelookup/selector/PhoneLookupSelector.java @@ -127,6 +127,20 @@ public final class PhoneLookupSelector { return ""; } + public boolean selectIsBusiness(PhoneLookupInfo phoneLookupInfo) { + return phoneLookupInfo.hasPeopleApiInfo() + && phoneLookupInfo.getPeopleApiInfo().getInfoType() == InfoType.NEARBY_BUSINESS; + } + + public boolean selectIsVoicemail(PhoneLookupInfo unused) { + // TODO(twyen): implement + return false; + } + + public boolean selectIsCp2InfoIncomplete(PhoneLookupInfo phoneLookupInfo) { + return phoneLookupInfo.getCp2LocalInfo().getIsIncomplete(); + } + /** * Returns true if the number associated with the given {@link PhoneLookupInfo} can be reported as * invalid. @@ -134,7 +148,7 @@ public final class PhoneLookupSelector { *

As we currently report invalid numbers via the People API, only numbers from the People API * can be reported as invalid. */ - public static boolean canReportAsInvalidNumber(PhoneLookupInfo phoneLookupInfo) { + public boolean canReportAsInvalidNumber(PhoneLookupInfo phoneLookupInfo) { // The presence of Cp2ContactInfo means the number associated with the given PhoneLookupInfo // matches that of a Cp2 (local) contact, and PeopleApiInfo will not be used to display // information like name, photo, etc. We should not allow the user to report the number in this diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java b/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java index 90581580d..46e29956d 100644 --- a/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java +++ b/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java @@ -27,6 +27,7 @@ import android.graphics.Typeface; import android.net.Uri; import android.provider.VoicemailContract.Voicemails; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.annotation.WorkerThread; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; @@ -205,13 +206,18 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On ContactPhotoManager.getInstance(context) .loadDialerThumbnailOrPhoto( quickContactBadge, - voicemailEntry.lookupUri() == null ? null : Uri.parse(voicemailEntry.lookupUri()), - voicemailEntry.photoId(), - voicemailEntry.photoUri() == null ? null : Uri.parse(voicemailEntry.photoUri()), - voicemailEntry.name(), + parseUri(voicemailEntry.numberAttributes().getLookupUri()), + voicemailEntry.numberAttributes().getPhotoId(), + parseUri(voicemailEntry.numberAttributes().getPhotoUri()), + VoicemailEntryText.buildPrimaryVoicemailText(context, voicemailEntry), LetterTileDrawable.TYPE_DEFAULT); } + @Nullable + private static Uri parseUri(@Nullable String string) { + return TextUtils.isEmpty(string) ? null : Uri.parse(string); + } + void collapseViewHolder() { LogUtil.i( "NewVoicemailViewHolder.collapseViewHolder", diff --git a/java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java b/java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java index 55d36b364..7e0381871 100644 --- a/java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java +++ b/java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java @@ -21,6 +21,7 @@ import android.database.Cursor; import android.provider.CallLog.Calls; import android.support.v4.content.CursorLoader; import com.android.dialer.DialerPhoneNumber; +import com.android.dialer.NumberAttributes; import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog; import com.android.dialer.voicemail.model.VoicemailEntry; import com.google.protobuf.InvalidProtocolBufferException; @@ -33,35 +34,29 @@ final class VoicemailCursorLoader extends CursorLoader { new String[] { AnnotatedCallLog._ID, AnnotatedCallLog.TIMESTAMP, - AnnotatedCallLog.NAME, AnnotatedCallLog.NUMBER, AnnotatedCallLog.FORMATTED_NUMBER, - AnnotatedCallLog.PHOTO_URI, - AnnotatedCallLog.PHOTO_ID, - AnnotatedCallLog.LOOKUP_URI, AnnotatedCallLog.DURATION, AnnotatedCallLog.GEOCODED_LOCATION, AnnotatedCallLog.CALL_TYPE, AnnotatedCallLog.TRANSCRIPTION, AnnotatedCallLog.VOICEMAIL_URI, - AnnotatedCallLog.IS_READ + AnnotatedCallLog.IS_READ, + AnnotatedCallLog.NUMBER_ATTRIBUTES, }; // Indexes for VOICEMAIL_COLUMNS private static final int ID = 0; private static final int TIMESTAMP = 1; - private static final int NAME = 2; - private static final int NUMBER = 3; - private static final int FORMATTED_NUMBER = 4; - private static final int PHOTO_URI = 5; - private static final int PHOTO_ID = 6; - private static final int LOOKUP_URI = 7; - private static final int DURATION = 8; - private static final int GEOCODED_LOCATION = 9; - private static final int CALL_TYPE = 10; - private static final int TRANSCRIPTION = 11; - private static final int VOICEMAIL_URI = 12; - private static final int IS_READ = 13; + private static final int NUMBER = 2; + private static final int FORMATTED_NUMBER = 3; + private static final int DURATION = 4; + private static final int GEOCODED_LOCATION = 5; + private static final int CALL_TYPE = 6; + private static final int TRANSCRIPTION = 7; + private static final int VOICEMAIL_URI = 8; + private static final int IS_READ = 9; + private static final int NUMBER_ATTRIBUTES = 10; // TODO(zachh): Optimize indexes VoicemailCursorLoader(Context context) { @@ -82,22 +77,25 @@ final class VoicemailCursorLoader extends CursorLoader { } catch (InvalidProtocolBufferException e) { throw new IllegalStateException("Couldn't parse DialerPhoneNumber bytes"); } + NumberAttributes numberAttributes; + try { + numberAttributes = NumberAttributes.parseFrom(cursor.getBlob(NUMBER_ATTRIBUTES)); + } catch (InvalidProtocolBufferException e) { + throw new IllegalStateException("Couldn't parse NumberAttributes bytes"); + } return VoicemailEntry.builder() .setId(cursor.getInt(ID)) .setTimestamp(cursor.getLong(TIMESTAMP)) - .setName(cursor.getString(NAME)) .setNumber(number) .setFormattedNumber(cursor.getString(FORMATTED_NUMBER)) - .setPhotoUri(cursor.getString(PHOTO_URI)) - .setPhotoId(cursor.getLong(PHOTO_ID)) - .setLookupUri(cursor.getString(LOOKUP_URI)) .setDuration(cursor.getLong(DURATION)) .setTranscription(cursor.getString(TRANSCRIPTION)) .setVoicemailUri(cursor.getString(VOICEMAIL_URI)) .setGeocodedLocation(cursor.getString(GEOCODED_LOCATION)) .setCallType(cursor.getInt(CALL_TYPE)) .setIsRead(cursor.getInt(IS_READ)) + .setNumberAttributes(numberAttributes) .build(); } diff --git a/java/com/android/dialer/voicemail/listui/VoicemailEntryText.java b/java/com/android/dialer/voicemail/listui/VoicemailEntryText.java index d73d1f0de..4aaf2d1e7 100644 --- a/java/com/android/dialer/voicemail/listui/VoicemailEntryText.java +++ b/java/com/android/dialer/voicemail/listui/VoicemailEntryText.java @@ -33,8 +33,8 @@ public class VoicemailEntryText { public static String buildPrimaryVoicemailText(Context context, VoicemailEntry data) { StringBuilder primaryText = new StringBuilder(); - if (!TextUtils.isEmpty(data.name())) { - primaryText.append(data.name()); + if (!TextUtils.isEmpty(data.numberAttributes().getName())) { + primaryText.append(data.numberAttributes().getName()); } else if (!TextUtils.isEmpty(data.formattedNumber())) { primaryText.append(data.formattedNumber()); } else { diff --git a/java/com/android/dialer/voicemail/listui/menu/Modules.java b/java/com/android/dialer/voicemail/listui/menu/Modules.java index bb98d76eb..bd79932e7 100644 --- a/java/com/android/dialer/voicemail/listui/menu/Modules.java +++ b/java/com/android/dialer/voicemail/listui/menu/Modules.java @@ -40,8 +40,8 @@ final class Modules { context, modules, voicemailEntry.number(), - voicemailEntry.name(), - voicemailEntry.lookupUri()); + voicemailEntry.numberAttributes().getName(), + voicemailEntry.numberAttributes().getLookupUri()); String originalNumber = voicemailEntry.number().getRawInput().getNumber(); SharedModules.maybeAddModuleForSendingTextMessage(context, modules, originalNumber); diff --git a/java/com/android/dialer/voicemail/listui/menu/PrimaryAction.java b/java/com/android/dialer/voicemail/listui/menu/PrimaryAction.java index 7f4ac8052..7b8adfe30 100644 --- a/java/com/android/dialer/voicemail/listui/menu/PrimaryAction.java +++ b/java/com/android/dialer/voicemail/listui/menu/PrimaryAction.java @@ -38,12 +38,12 @@ final class PrimaryAction { .setNumber(voicemailEntry.number()) .setPhotoInfo( PhotoInfo.builder() - .setPhotoId(voicemailEntry.photoId()) - .setPhotoUri(voicemailEntry.photoUri()) + .setPhotoId(voicemailEntry.numberAttributes().getPhotoId()) + .setPhotoUri(voicemailEntry.numberAttributes().getPhotoUri()) .setIsVideo(false) .setContactType( LetterTileDrawable.TYPE_DEFAULT) // TODO(uabdullah): Use proper type. - .setDisplayName(voicemailEntry.name()) + .setDisplayName(voicemailEntry.numberAttributes().getName()) .build()) .setPrimaryText(buildPrimaryVoicemailText(context, voicemailEntry)) .setSecondaryText(buildSecondaryVoicemailText(voicemailEntry)) @@ -56,8 +56,8 @@ final class PrimaryAction { public static String buildPrimaryVoicemailText(Context context, VoicemailEntry data) { StringBuilder primaryText = new StringBuilder(); - if (!TextUtils.isEmpty(data.name())) { - primaryText.append(data.name()); + if (!TextUtils.isEmpty(data.numberAttributes().getName())) { + primaryText.append(data.numberAttributes().getName()); } else if (!TextUtils.isEmpty(data.formattedNumber())) { primaryText.append(data.formattedNumber()); } else { diff --git a/java/com/android/dialer/voicemail/model/VoicemailEntry.java b/java/com/android/dialer/voicemail/model/VoicemailEntry.java index 702f52d17..f17a23e54 100644 --- a/java/com/android/dialer/voicemail/model/VoicemailEntry.java +++ b/java/com/android/dialer/voicemail/model/VoicemailEntry.java @@ -19,6 +19,7 @@ package com.android.dialer.voicemail.model; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.android.dialer.DialerPhoneNumber; +import com.android.dialer.NumberAttributes; import com.google.auto.value.AutoValue; /** Data class containing the contents of a voicemail entry from the AnnotatedCallLog. */ @@ -30,7 +31,7 @@ public abstract class VoicemailEntry { .setId(0) .setTimestamp(0) .setNumber(DialerPhoneNumber.getDefaultInstance()) - .setPhotoId(0) + .setNumberAttributes(NumberAttributes.getDefaultInstance()) .setDuration(0) .setCallType(0) .setIsRead(0); @@ -43,20 +44,10 @@ public abstract class VoicemailEntry { @NonNull public abstract DialerPhoneNumber number(); - @Nullable - public abstract String name(); @Nullable public abstract String formattedNumber(); - @Nullable - public abstract String photoUri(); - - public abstract long photoId(); - - @Nullable - public abstract String lookupUri(); - @Nullable public abstract String geocodedLocation(); @@ -72,6 +63,8 @@ public abstract class VoicemailEntry { public abstract int isRead(); + public abstract NumberAttributes numberAttributes(); + /** Builder for {@link VoicemailEntry}. */ @AutoValue.Builder public abstract static class Builder { @@ -82,16 +75,8 @@ public abstract class VoicemailEntry { public abstract Builder setNumber(@NonNull DialerPhoneNumber number); - public abstract Builder setName(@Nullable String name); - public abstract Builder setFormattedNumber(@Nullable String formattedNumber); - public abstract Builder setPhotoUri(@Nullable String photoUri); - - public abstract Builder setPhotoId(long photoId); - - public abstract Builder setLookupUri(@Nullable String lookupUri); - public abstract Builder setDuration(long duration); public abstract Builder setTranscription(@Nullable String transcription); @@ -104,6 +89,8 @@ public abstract class VoicemailEntry { public abstract Builder setIsRead(int isRead); + public abstract Builder setNumberAttributes(NumberAttributes numberAttributes); + public abstract VoicemailEntry build(); } } -- cgit v1.2.3 From 01aac5de58903555a089d16a58b9346d34d54e7b Mon Sep 17 00:00:00 2001 From: linyuh Date: Thu, 11 Jan 2018 16:50:48 -0800 Subject: Implement PhoneLookup for CP2 remote contacts Bug: 71763594 Test: Cp2LocalPhoneLookupTest, Cp2RemotePhoneLookupTest PiperOrigin-RevId: 181681435 Change-Id: I2e091371b6705390adf4be63c78344f78bd19d6e --- .../dialer/phonelookup/PhoneLookupModule.java | 5 +- .../phonelookup/cp2/Cp2LocalPhoneLookup.java | 104 ++------- .../dialer/phonelookup/cp2/Cp2Projections.java | 119 ++++++++++ .../phonelookup/cp2/Cp2RemotePhoneLookup.java | 248 +++++++++++++++++++++ .../dialer/phonelookup/phone_lookup_info.proto | 49 +++- 5 files changed, 428 insertions(+), 97 deletions(-) create mode 100644 java/com/android/dialer/phonelookup/cp2/Cp2Projections.java create mode 100644 java/com/android/dialer/phonelookup/cp2/Cp2RemotePhoneLookup.java (limited to 'java/com/android/dialer') diff --git a/java/com/android/dialer/phonelookup/PhoneLookupModule.java b/java/com/android/dialer/phonelookup/PhoneLookupModule.java index 5e215bafe..e93ca0f77 100644 --- a/java/com/android/dialer/phonelookup/PhoneLookupModule.java +++ b/java/com/android/dialer/phonelookup/PhoneLookupModule.java @@ -19,6 +19,7 @@ package com.android.dialer.phonelookup; import com.android.dialer.phonelookup.blockednumber.DialerBlockedNumberPhoneLookup; import com.android.dialer.phonelookup.composite.CompositePhoneLookup; import com.android.dialer.phonelookup.cp2.Cp2LocalPhoneLookup; +import com.android.dialer.phonelookup.cp2.Cp2RemotePhoneLookup; import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; @@ -31,8 +32,10 @@ public abstract class PhoneLookupModule { @SuppressWarnings({"unchecked", "rawtype"}) static ImmutableList providePhoneLookupList( Cp2LocalPhoneLookup cp2LocalPhoneLookup, + Cp2RemotePhoneLookup cp2RemotePhoneLookup, DialerBlockedNumberPhoneLookup dialerBlockedNumberPhoneLookup) { - return ImmutableList.of(cp2LocalPhoneLookup, dialerBlockedNumberPhoneLookup); + return ImmutableList.of( + cp2LocalPhoneLookup, cp2RemotePhoneLookup, dialerBlockedNumberPhoneLookup); } @Provides diff --git a/java/com/android/dialer/phonelookup/cp2/Cp2LocalPhoneLookup.java b/java/com/android/dialer/phonelookup/cp2/Cp2LocalPhoneLookup.java index 727977f5c..8879fee06 100644 --- a/java/com/android/dialer/phonelookup/cp2/Cp2LocalPhoneLookup.java +++ b/java/com/android/dialer/phonelookup/cp2/Cp2LocalPhoneLookup.java @@ -66,45 +66,7 @@ import javax.inject.Inject; public final class Cp2LocalPhoneLookup implements PhoneLookup { private static final String PREF_LAST_TIMESTAMP_PROCESSED = - "cp2PhoneLookupLastTimestampProcessed"; - - /** Projection for performing batch lookups based on E164 numbers using the PHONE table. */ - private static final String[] PHONE_PROJECTION = - new String[] { - Phone.DISPLAY_NAME_PRIMARY, // 0 - Phone.PHOTO_THUMBNAIL_URI, // 1 - Phone.PHOTO_ID, // 2 - Phone.TYPE, // 3 - Phone.LABEL, // 4 - Phone.NORMALIZED_NUMBER, // 5 - Phone.CONTACT_ID, // 6 - Phone.LOOKUP_KEY // 7 - }; - - /** - * Projection for performing individual lookups of non-E164 numbers using the PHONE_LOOKUP table. - */ - private static final String[] PHONE_LOOKUP_PROJECTION = - new String[] { - ContactsContract.PhoneLookup.DISPLAY_NAME_PRIMARY, // 0 - ContactsContract.PhoneLookup.PHOTO_THUMBNAIL_URI, // 1 - ContactsContract.PhoneLookup.PHOTO_ID, // 2 - ContactsContract.PhoneLookup.TYPE, // 3 - ContactsContract.PhoneLookup.LABEL, // 4 - ContactsContract.PhoneLookup.NORMALIZED_NUMBER, // 5 - ContactsContract.PhoneLookup.CONTACT_ID, // 6 - ContactsContract.PhoneLookup.LOOKUP_KEY // 7 - }; - - // The following indexes should match both PHONE_PROJECTION and PHONE_LOOKUP_PROJECTION above. - private static final int CP2_INFO_NAME_INDEX = 0; - private static final int CP2_INFO_PHOTO_URI_INDEX = 1; - private static final int CP2_INFO_PHOTO_ID_INDEX = 2; - private static final int CP2_INFO_TYPE_INDEX = 3; - private static final int CP2_INFO_LABEL_INDEX = 4; - private static final int CP2_INFO_NORMALIZED_NUMBER_INDEX = 5; - private static final int CP2_INFO_CONTACT_ID_INDEX = 6; - private static final int CP2_INFO_LOOKUP_KEY_INDEX = 7; + "cp2LocalPhoneLookupLastTimestampProcessed"; // We cannot efficiently process invalid numbers because batch queries cannot be constructed which // accomplish the necessary loose matching. We'll attempt to process a limited number of them, @@ -146,14 +108,15 @@ public final class Cp2LocalPhoneLookup implements PhoneLookup { // ensure consistency when the batch methods are used to update data. try (Cursor cursor = e164.isPresent() - ? queryPhoneTableBasedOnE164(PHONE_PROJECTION, ImmutableSet.of(e164.get())) - : queryPhoneLookup(PHONE_LOOKUP_PROJECTION, rawNumber)) { + ? queryPhoneTableBasedOnE164( + Cp2Projections.getProjectionForPhoneTable(), ImmutableSet.of(e164.get())) + : queryPhoneLookup(Cp2Projections.getProjectionForPhoneLookupTable(), rawNumber)) { if (cursor == null) { LogUtil.w("Cp2LocalPhoneLookup.lookupInternal", "null cursor"); return Cp2Info.getDefaultInstance(); } while (cursor.moveToNext()) { - cp2ContactInfos.add(buildCp2ContactInfoFromPhoneCursor(appContext, cursor)); + cp2ContactInfos.add(Cp2Projections.buildCp2ContactInfoFromCursor(appContext, cursor)); } } return Cp2Info.newBuilder().addAllCp2ContactInfo(cp2ContactInfos).build(); @@ -174,13 +137,14 @@ public final class Cp2LocalPhoneLookup implements PhoneLookup { return Cp2Info.getDefaultInstance(); } Set cp2ContactInfos = new ArraySet<>(); - try (Cursor cursor = queryPhoneLookup(PHONE_LOOKUP_PROJECTION, rawNumber)) { + try (Cursor cursor = + queryPhoneLookup(Cp2Projections.getProjectionForPhoneLookupTable(), rawNumber)) { if (cursor == null) { LogUtil.w("Cp2LocalPhoneLookup.lookup", "null cursor"); return Cp2Info.getDefaultInstance(); } while (cursor.moveToNext()) { - cp2ContactInfos.add(buildCp2ContactInfoFromPhoneCursor(appContext, cursor)); + cp2ContactInfos.add(Cp2Projections.buildCp2ContactInfoFromCursor(appContext, cursor)); } } return Cp2Info.newBuilder().addAllCp2ContactInfo(cp2ContactInfos).build(); @@ -767,18 +731,21 @@ public final class Cp2LocalPhoneLookup implements PhoneLookup { if (e164Numbers.isEmpty()) { return cp2ContactInfosByNumber; } - try (Cursor cursor = queryPhoneTableBasedOnE164(PHONE_PROJECTION, e164Numbers)) { + try (Cursor cursor = + queryPhoneTableBasedOnE164( + Cp2Projections.getProjectionForPhoneTable(), e164Numbers)) { if (cursor == null) { LogUtil.w("Cp2LocalPhoneLookup.batchQueryForValidNumbers", "null cursor"); } else { while (cursor.moveToNext()) { - String e164Number = cursor.getString(CP2_INFO_NORMALIZED_NUMBER_INDEX); + String e164Number = Cp2Projections.getNormalizedNumberFromCursor(cursor); Set cp2ContactInfos = cp2ContactInfosByNumber.get(e164Number); if (cp2ContactInfos == null) { cp2ContactInfos = new ArraySet<>(); cp2ContactInfosByNumber.put(e164Number, cp2ContactInfos); } - cp2ContactInfos.add(buildCp2ContactInfoFromPhoneCursor(appContext, cursor)); + cp2ContactInfos.add( + Cp2Projections.buildCp2ContactInfoFromCursor(appContext, cursor)); } } } @@ -794,12 +761,14 @@ public final class Cp2LocalPhoneLookup implements PhoneLookup { if (invalidNumber.isEmpty()) { return cp2ContactInfos; } - try (Cursor cursor = queryPhoneLookup(PHONE_LOOKUP_PROJECTION, invalidNumber)) { + try (Cursor cursor = + queryPhoneLookup(Cp2Projections.getProjectionForPhoneLookupTable(), invalidNumber)) { if (cursor == null) { LogUtil.w("Cp2LocalPhoneLookup.individualQueryForInvalidNumber", "null cursor"); } else { while (cursor.moveToNext()) { - cp2ContactInfos.add(buildCp2ContactInfoFromPhoneCursor(appContext, cursor)); + cp2ContactInfos.add( + Cp2Projections.buildCp2ContactInfoFromCursor(appContext, cursor)); } } } @@ -843,43 +812,6 @@ public final class Cp2LocalPhoneLookup implements PhoneLookup { return appContext.getContentResolver().query(uri, projection, null, null, null); } - /** - * @param cursor with projection {@link #PHONE_PROJECTION}. - * @return new {@link Cp2ContactInfo} based on current row of {@code cursor}. - */ - private static Cp2ContactInfo buildCp2ContactInfoFromPhoneCursor( - Context appContext, Cursor cursor) { - String displayName = cursor.getString(CP2_INFO_NAME_INDEX); - String photoUri = cursor.getString(CP2_INFO_PHOTO_URI_INDEX); - int photoId = cursor.getInt(CP2_INFO_PHOTO_ID_INDEX); - int type = cursor.getInt(CP2_INFO_TYPE_INDEX); - String label = cursor.getString(CP2_INFO_LABEL_INDEX); - int contactId = cursor.getInt(CP2_INFO_CONTACT_ID_INDEX); - String lookupKey = cursor.getString(CP2_INFO_LOOKUP_KEY_INDEX); - - Cp2ContactInfo.Builder infoBuilder = Cp2ContactInfo.newBuilder(); - if (!TextUtils.isEmpty(displayName)) { - infoBuilder.setName(displayName); - } - if (!TextUtils.isEmpty(photoUri)) { - infoBuilder.setPhotoUri(photoUri); - } - if (photoId > 0) { - infoBuilder.setPhotoId(photoId); - } - - // Phone.getTypeLabel returns "Custom" if given (0, null) which is not of any use. Just - // omit setting the label if there's no information for it. - if (type != 0 || !TextUtils.isEmpty(label)) { - infoBuilder.setLabel(Phone.getTypeLabel(appContext.getResources(), type, label).toString()); - } - infoBuilder.setContactId(contactId); - if (!TextUtils.isEmpty(lookupKey)) { - infoBuilder.setLookupUri(Contacts.getLookupUri(contactId, lookupKey).toString()); - } - return infoBuilder.build(); - } - /** Returns set of DialerPhoneNumbers that were associated with now deleted contacts. */ private ListenableFuture> getDeletedPhoneNumbers( ImmutableMap existingInfoMap, long lastModified) { diff --git a/java/com/android/dialer/phonelookup/cp2/Cp2Projections.java b/java/com/android/dialer/phonelookup/cp2/Cp2Projections.java new file mode 100644 index 000000000..e3929990e --- /dev/null +++ b/java/com/android/dialer/phonelookup/cp2/Cp2Projections.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2018 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.phonelookup.cp2; + +import android.content.Context; +import android.database.Cursor; +import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.provider.ContactsContract.Contacts; +import android.provider.ContactsContract.PhoneLookup; +import android.text.TextUtils; +import com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info.Cp2ContactInfo; + +/** + * A class providing projection-related functionality for {@link + * com.android.dialer.phonelookup.PhoneLookup} implementations for ContactsProvider2 (CP2). + */ +final class Cp2Projections { + + // Projection for performing lookups using the PHONE table + private static final String[] PHONE_PROJECTION = + new String[] { + Phone.DISPLAY_NAME_PRIMARY, // 0 + Phone.PHOTO_THUMBNAIL_URI, // 1 + Phone.PHOTO_ID, // 2 + Phone.TYPE, // 3 + Phone.LABEL, // 4 + Phone.NORMALIZED_NUMBER, // 5 + Phone.CONTACT_ID, // 6 + Phone.LOOKUP_KEY // 7 + }; + + // Projection for performing lookups using the PHONE_LOOKUP table + private static final String[] PHONE_LOOKUP_PROJECTION = + new String[] { + PhoneLookup.DISPLAY_NAME_PRIMARY, // 0 + PhoneLookup.PHOTO_THUMBNAIL_URI, // 1 + PhoneLookup.PHOTO_ID, // 2 + PhoneLookup.TYPE, // 3 + PhoneLookup.LABEL, // 4 + PhoneLookup.NORMALIZED_NUMBER, // 5 + PhoneLookup.CONTACT_ID, // 6 + PhoneLookup.LOOKUP_KEY // 7 + }; + + // The following indexes should match both PHONE_PROJECTION and PHONE_LOOKUP_PROJECTION above. + private static final int CP2_INFO_NAME_INDEX = 0; + private static final int CP2_INFO_PHOTO_URI_INDEX = 1; + private static final int CP2_INFO_PHOTO_ID_INDEX = 2; + private static final int CP2_INFO_TYPE_INDEX = 3; + private static final int CP2_INFO_LABEL_INDEX = 4; + private static final int CP2_INFO_NORMALIZED_NUMBER_INDEX = 5; + private static final int CP2_INFO_CONTACT_ID_INDEX = 6; + private static final int CP2_INFO_LOOKUP_KEY_INDEX = 7; + + private Cp2Projections() {} + + static String[] getProjectionForPhoneTable() { + return PHONE_PROJECTION; + } + + static String[] getProjectionForPhoneLookupTable() { + return PHONE_LOOKUP_PROJECTION; + } + + /** + * Builds a {@link Cp2ContactInfo} based on the current row of {@code cursor}, of which the + * projection is either {@link #PHONE_PROJECTION} or {@link #PHONE_LOOKUP_PROJECTION}. + */ + static Cp2ContactInfo buildCp2ContactInfoFromCursor(Context appContext, Cursor cursor) { + String displayName = cursor.getString(CP2_INFO_NAME_INDEX); + String photoUri = cursor.getString(CP2_INFO_PHOTO_URI_INDEX); + int photoId = cursor.getInt(CP2_INFO_PHOTO_ID_INDEX); + int type = cursor.getInt(CP2_INFO_TYPE_INDEX); + String label = cursor.getString(CP2_INFO_LABEL_INDEX); + int contactId = cursor.getInt(CP2_INFO_CONTACT_ID_INDEX); + String lookupKey = cursor.getString(CP2_INFO_LOOKUP_KEY_INDEX); + + Cp2ContactInfo.Builder infoBuilder = Cp2ContactInfo.newBuilder(); + if (!TextUtils.isEmpty(displayName)) { + infoBuilder.setName(displayName); + } + if (!TextUtils.isEmpty(photoUri)) { + infoBuilder.setPhotoUri(photoUri); + } + if (photoId > 0) { + infoBuilder.setPhotoId(photoId); + } + + // Phone.getTypeLabel returns "Custom" if given (0, null) which is not of any use. Just + // omit setting the label if there's no information for it. + if (type != 0 || !TextUtils.isEmpty(label)) { + infoBuilder.setLabel(Phone.getTypeLabel(appContext.getResources(), type, label).toString()); + } + infoBuilder.setContactId(contactId); + if (!TextUtils.isEmpty(lookupKey)) { + infoBuilder.setLookupUri(Contacts.getLookupUri(contactId, lookupKey).toString()); + } + return infoBuilder.build(); + } + + /** Returns the normalized number in the current row of {@code cursor}. */ + static String getNormalizedNumberFromCursor(Cursor cursor) { + return cursor.getString(CP2_INFO_NORMALIZED_NUMBER_INDEX); + } +} diff --git a/java/com/android/dialer/phonelookup/cp2/Cp2RemotePhoneLookup.java b/java/com/android/dialer/phonelookup/cp2/Cp2RemotePhoneLookup.java new file mode 100644 index 000000000..6a4682958 --- /dev/null +++ b/java/com/android/dialer/phonelookup/cp2/Cp2RemotePhoneLookup.java @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2018 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.phonelookup.cp2; + +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import android.provider.ContactsContract; +import android.provider.ContactsContract.Directory; +import android.support.annotation.VisibleForTesting; +import android.telecom.Call; +import com.android.dialer.DialerPhoneNumber; +import com.android.dialer.common.LogUtil; +import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor; +import com.android.dialer.common.concurrent.Annotations.LightweightExecutor; +import com.android.dialer.inject.ApplicationContext; +import com.android.dialer.phonelookup.PhoneLookup; +import com.android.dialer.phonelookup.PhoneLookupInfo; +import com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info; +import com.android.dialer.phonenumberutil.PhoneNumberHelper; +import com.android.dialer.telecom.TelecomCallUtil; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import java.util.ArrayList; +import java.util.List; +import javax.inject.Inject; + +/** PhoneLookup implementation for remote contacts. */ +public final class Cp2RemotePhoneLookup implements PhoneLookup { + + private final Context appContext; + private final ListeningExecutorService backgroundExecutorService; + private final ListeningExecutorService lightweightExecutorService; + + @Inject + Cp2RemotePhoneLookup( + @ApplicationContext Context appContext, + @BackgroundExecutor ListeningExecutorService backgroundExecutorService, + @LightweightExecutor ListeningExecutorService lightweightExecutorService) { + this.appContext = appContext; + this.backgroundExecutorService = backgroundExecutorService; + this.lightweightExecutorService = lightweightExecutorService; + } + + @Override + public ListenableFuture lookup(Call call) { + String number = TelecomCallUtil.getNumber(call); + if (number == null) { + return Futures.immediateFuture(Cp2Info.getDefaultInstance()); + } + + return Futures.transformAsync( + queryCp2ForRemoteDirectoryIds(), + remoteDirectoryIds -> queryCp2ForRemoteContact(number, remoteDirectoryIds), + lightweightExecutorService); + } + + private ListenableFuture> queryCp2ForRemoteDirectoryIds() { + return backgroundExecutorService.submit( + () -> { + List remoteDirectoryIds = new ArrayList<>(); + try (Cursor cursor = + appContext + .getContentResolver() + .query( + getContentUriForDirectoryIds(), + /* projection = */ new String[] {ContactsContract.Directory._ID}, + /* selection = */ null, + /* selectionArgs = */ null, + /* sortOrder = */ ContactsContract.Directory._ID)) { + if (cursor == null) { + LogUtil.e("Cp2RemotePhoneLookup.queryCp2ForDirectoryIds", "null cursor"); + return remoteDirectoryIds; + } + + if (!cursor.moveToFirst()) { + LogUtil.i("Cp2RemotePhoneLookup.queryCp2ForDirectoryIds", "empty cursor"); + return remoteDirectoryIds; + } + + int idColumnIndex = cursor.getColumnIndexOrThrow(ContactsContract.Directory._ID); + do { + long directoryId = cursor.getLong(idColumnIndex); + + // Note that IDs of non-remote directories will be included in the result, such as + // android.provider.ContactsContract.Directory.DEFAULT (the default directory that + // represents locally stored contacts). + if (isRemoteDirectory(directoryId)) { + remoteDirectoryIds.add(cursor.getLong(idColumnIndex)); + } + } while (cursor.moveToNext()); + return remoteDirectoryIds; + } + }); + } + + private ListenableFuture queryCp2ForRemoteContact( + String number, List remoteDirectoryIds) { + if (remoteDirectoryIds.isEmpty()) { + return Futures.immediateFuture(Cp2Info.getDefaultInstance()); + } + + List> cp2InfoFutures = new ArrayList<>(); + for (long remoteDirectoryId : remoteDirectoryIds) { + cp2InfoFutures.add(queryCp2ForRemoteContact(number, remoteDirectoryId)); + } + + return Futures.transform( + Futures.allAsList(cp2InfoFutures), + cp2InfoList -> { + Cp2Info.Builder cp2InfoBuilder = Cp2Info.newBuilder(); + for (Cp2Info cp2Info : cp2InfoList) { + cp2InfoBuilder.addAllCp2ContactInfo(cp2Info.getCp2ContactInfoList()); + } + return cp2InfoBuilder.build(); + }, + lightweightExecutorService); + } + + private ListenableFuture queryCp2ForRemoteContact( + String number, long remoteDirectoryId) { + return backgroundExecutorService.submit( + () -> { + Cp2Info.Builder cp2InfoBuilder = Cp2Info.newBuilder(); + try (Cursor cursor = + appContext + .getContentResolver() + .query( + getContentUriForContacts(number, remoteDirectoryId), + Cp2Projections.getProjectionForPhoneLookupTable(), + /* selection = */ null, + /* selectionArgs = */ null, + /* sortOrder = */ null)) { + if (cursor == null) { + LogUtil.e( + "Cp2RemotePhoneLookup.queryCp2ForRemoteContact", + "null cursor returned when querying directory %d", + remoteDirectoryId); + return cp2InfoBuilder.build(); + } + + if (!cursor.moveToFirst()) { + LogUtil.i( + "Cp2RemotePhoneLookup.queryCp2ForRemoteContact", + "empty cursor returned when querying directory %d", + remoteDirectoryId); + return cp2InfoBuilder.build(); + } + + do { + cp2InfoBuilder.addCp2ContactInfo( + Cp2Projections.buildCp2ContactInfoFromCursor(appContext, cursor)); + } while (cursor.moveToNext()); + } + + return cp2InfoBuilder.build(); + }); + } + + @VisibleForTesting + static Uri getContentUriForDirectoryIds() { + return VERSION.SDK_INT >= VERSION_CODES.N + ? ContactsContract.Directory.ENTERPRISE_CONTENT_URI + : ContactsContract.Directory.CONTENT_URI; + } + + @VisibleForTesting + static Uri getContentUriForContacts(String number, long directoryId) { + Uri baseUri = + VERSION.SDK_INT >= VERSION_CODES.N + ? ContactsContract.PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI + : ContactsContract.PhoneLookup.CONTENT_FILTER_URI; + + Uri.Builder builder = + baseUri + .buildUpon() + .appendPath(number) + .appendQueryParameter( + ContactsContract.PhoneLookup.QUERY_PARAMETER_SIP_ADDRESS, + String.valueOf(PhoneNumberHelper.isUriNumber(number))) + .appendQueryParameter( + ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)); + + return builder.build(); + } + + private static boolean isRemoteDirectory(long directoryId) { + return VERSION.SDK_INT >= VERSION_CODES.N + ? Directory.isRemoteDirectoryId(directoryId) + : (directoryId != Directory.DEFAULT + && directoryId != Directory.LOCAL_INVISIBLE + // Directory.ENTERPRISE_DEFAULT is the default work profile directory for locally stored + // contacts + && directoryId != Directory.ENTERPRISE_DEFAULT + && directoryId != Directory.ENTERPRISE_LOCAL_INVISIBLE); + } + + @Override + public ListenableFuture isDirty(ImmutableSet phoneNumbers) { + return Futures.immediateFuture(false); + } + + @Override + public ListenableFuture> getMostRecentInfo( + ImmutableMap existingInfoMap) { + return Futures.immediateFuture(existingInfoMap); + } + + @Override + public void setSubMessage(PhoneLookupInfo.Builder destination, Cp2Info subMessage) { + destination.setCp2RemoteInfo(subMessage); + } + + @Override + public Cp2Info getSubMessage(PhoneLookupInfo phoneLookupInfo) { + return phoneLookupInfo.getCp2RemoteInfo(); + } + + @Override + public ListenableFuture onSuccessfulBulkUpdate() { + return Futures.immediateFuture(null); + } + + @Override + public void registerContentObservers( + Context appContext, ContentObserverCallbacks contentObserverCallbacks) { + // No content observer needed for remote contacts + } +} diff --git a/java/com/android/dialer/phonelookup/phone_lookup_info.proto b/java/com/android/dialer/phonelookup/phone_lookup_info.proto index f1497bdca..b5e73ccbe 100644 --- a/java/com/android/dialer/phonelookup/phone_lookup_info.proto +++ b/java/com/android/dialer/phonelookup/phone_lookup_info.proto @@ -13,29 +13,51 @@ package com.android.dialer.phonelookup; // to an implementation of PhoneLookup. For example, field "cp2_local_info" // corresponds to class Cp2LocalPhoneLookup, and class Cp2LocalPhoneLookup // alone is responsible for populating it. +// Next ID: 7 message PhoneLookupInfo { - // Information about a PhoneNumber retrieved from CP2. Cp2LocalPhoneLookup is - // responsible for populating the data in this message. + // Information about a PhoneNumber retrieved from CP2. message Cp2Info { - // Information about a single local contact. + // Information about a single contact, which can be a local contact or a + // remote one. message Cp2ContactInfo { - // android.provider.ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY + // For a local contact: + // android.provider.ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY + // For a remote contact: + // android.provider.ContactsContract.PhoneLookup.DISPLAY_NAME_PRIMARY optional string name = 1; - // android.provider.ContactsContract.CommonDataKinds.Phone.PHOTO_THUMBNAIL_URI + // For a local contact: + // android.provider.ContactsContract.CommonDataKinds.Phone.PHOTO_THUMBNAIL_URI + // For a remote contact: + // android.provider.ContactsContract.PhoneLookup.PHOTO_THUMBNAIL_URI optional string photo_uri = 2; - // android.provider.ContactsContract.CommonDataKinds.Phone.PHOTO_ID + // For a local contact: + // android.provider.ContactsContract.CommonDataKinds.Phone.PHOTO_ID + // For a remote contact: + // android.provider.ContactsContract.PhoneLookup.PHOTO_ID optional fixed64 photo_id = 3; - // android.provider.ContactsContract.CommonDataKinds.Phone.LABEL - // "Home", "Mobile", ect. + // For a local contact: + // android.provider.ContactsContract.CommonDataKinds.Phone.LABEL + // For a remote contact: + // android.provider.ContactsContract.PhoneLookup.LABEL + // + // The value can be "Home", "Mobile", ect. optional string label = 4; - // android.provider.ContactsContract.CommonDataKinds.Phone.CONTACT_ID + // For a local contact: + // android.provider.ContactsContract.CommonDataKinds.Phone.CONTACT_ID + // For a remote contact: + // android.provider.ContactsContract.PhoneLookup.CONTACT_ID optional fixed64 contact_id = 5; - // android.provider.ContactsContract.CONTENT_LOOKUP_URI + // For a local contact: + // constructed based on + // android.provider.ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY + // For a remote contact: + // constructed based on + // android.provider.ContactsContract.PhoneLookup.LOOKUP_KEY optional string lookup_uri = 6; } // Repeated because one phone number can be associated with multiple CP2 @@ -50,8 +72,15 @@ message PhoneLookupInfo { // log needs to query for the CP2 information at render time. optional bool is_incomplete = 2; } + + // Information about a local contact retrieved via CP2. + // Cp2LocalPhoneLookup is responsible for populating this field. optional Cp2Info cp2_local_info = 1; + // Information about a remote contact retrieved via CP2. + // Cp2RemotePhoneLookup is responsible for populating this field. + optional Cp2Info cp2_remote_info = 6; + // Message for APDL, a lookup for the proprietary Google dialer. message ApdlInfo { optional bool is_spam = 1; -- cgit v1.2.3