Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01aac5de authored by linyuh's avatar linyuh Committed by Copybara-Service
Browse files

Implement PhoneLookup for CP2 remote contacts

Bug: 71763594
Test: Cp2LocalPhoneLookupTest, Cp2RemotePhoneLookupTest
PiperOrigin-RevId: 181681435
Change-Id: I2e091371b6705390adf4be63c78344f78bd19d6e
parent 188b42fd
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -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<PhoneLookup> providePhoneLookupList(
      Cp2LocalPhoneLookup cp2LocalPhoneLookup,
      Cp2RemotePhoneLookup cp2RemotePhoneLookup,
      DialerBlockedNumberPhoneLookup dialerBlockedNumberPhoneLookup) {
    return ImmutableList.of(cp2LocalPhoneLookup, dialerBlockedNumberPhoneLookup);
    return ImmutableList.of(
        cp2LocalPhoneLookup, cp2RemotePhoneLookup, dialerBlockedNumberPhoneLookup);
  }

  @Provides
+18 −86
Original line number Diff line number Diff line
@@ -66,45 +66,7 @@ import javax.inject.Inject;
public final class Cp2LocalPhoneLookup implements PhoneLookup<Cp2Info> {

  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<Cp2Info> {
    // 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<Cp2Info> {
            return Cp2Info.getDefaultInstance();
          }
          Set<Cp2ContactInfo> 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<Cp2Info> {
          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<Cp2ContactInfo> 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<Cp2Info> {
          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<Cp2Info> {
    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<Set<DialerPhoneNumber>> getDeletedPhoneNumbers(
      ImmutableMap<DialerPhoneNumber, Cp2Info> existingInfoMap, long lastModified) {
+119 −0
Original line number Diff line number Diff line
/*
 * 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);
  }
}
+248 −0
Original line number Diff line number Diff line
/*
 * 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<Cp2Info> {

  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<Cp2Info> 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<List<Long>> queryCp2ForRemoteDirectoryIds() {
    return backgroundExecutorService.submit(
        () -> {
          List<Long> 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<Cp2Info> queryCp2ForRemoteContact(
      String number, List<Long> remoteDirectoryIds) {
    if (remoteDirectoryIds.isEmpty()) {
      return Futures.immediateFuture(Cp2Info.getDefaultInstance());
    }

    List<ListenableFuture<Cp2Info>> 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<Cp2Info> 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<Boolean> isDirty(ImmutableSet<DialerPhoneNumber> phoneNumbers) {
    return Futures.immediateFuture(false);
  }

  @Override
  public ListenableFuture<ImmutableMap<DialerPhoneNumber, Cp2Info>> getMostRecentInfo(
      ImmutableMap<DialerPhoneNumber, Cp2Info> 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<Void> onSuccessfulBulkUpdate() {
    return Futures.immediateFuture(null);
  }

  @Override
  public void registerContentObservers(
      Context appContext, ContentObserverCallbacks contentObserverCallbacks) {
    // No content observer needed for remote contacts
  }
}
+39 −10

File changed.

Preview size limit exceeded, changes collapsed.