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

Commit 58fde995 authored by zachh's avatar zachh Committed by android-build-merger
Browse files

Merge "Added is_valid and post_dial_portion fields to DialerPhoneNumber."

am: f27f1bd0

Change-Id: I3342c2647eec18f77af4d97a8e827a8b14701e2a
parents 0307508c f27f1bd0
Loading
Loading
Loading
Loading
+8 −14
Original line number Diff line number Diff line
@@ -42,14 +42,12 @@ import com.android.dialer.phonelookup.PhoneLookupInfo;
import com.android.dialer.phonelookup.consolidator.PhoneLookupInfoConsolidator;
import com.android.dialer.phonelookup.database.contract.PhoneLookupHistoryContract;
import com.android.dialer.phonelookup.database.contract.PhoneLookupHistoryContract.PhoneLookupHistory;
import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.protobuf.InvalidProtocolBufferException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -192,11 +190,8 @@ public final class PhoneLookupDataSource
          populateInserts(originalPhoneLookupHistoryDataByAnnotatedCallLogId.build(), mutations);

          // Compute and save the PhoneLookupHistory rows which can be deleted in onSuccessfulFill.
          DialerPhoneNumberUtil dialerPhoneNumberUtil =
              new DialerPhoneNumberUtil(PhoneNumberUtil.getInstance());
          phoneLookupHistoryRowsToDelete.addAll(
              computePhoneLookupHistoryRowsToDelete(
                  annotatedCallLogIdsByNumber, mutations, dialerPhoneNumberUtil));
              computePhoneLookupHistoryRowsToDelete(annotatedCallLogIdsByNumber, mutations));

          // Now compute the rows to update.
          ImmutableMap.Builder<Long, PhoneLookupInfo> rowsToUpdate = ImmutableMap.builder();
@@ -209,7 +204,8 @@ public final class PhoneLookupDataSource
              }
              // Also save the updated information so that it can be written to PhoneLookupHistory
              // in onSuccessfulFill.
              String normalizedNumber = dialerPhoneNumberUtil.normalizeNumber(dialerPhoneNumber);
              // Note: This loses country info when number is not valid.
              String normalizedNumber = dialerPhoneNumber.getNormalizedNumber();
              phoneLookupHistoryRowsToUpdate.put(normalizedNumber, upToDateInfo);
            }
          }
@@ -417,10 +413,9 @@ public final class PhoneLookupDataSource
  /** Returned map must have same keys as {@code uniqueDialerPhoneNumbers} */
  private ImmutableMap<DialerPhoneNumber, PhoneLookupInfo> queryPhoneLookupHistoryForNumbers(
      Context appContext, Set<DialerPhoneNumber> uniqueDialerPhoneNumbers) {
    DialerPhoneNumberUtil dialerPhoneNumberUtil =
        new DialerPhoneNumberUtil(PhoneNumberUtil.getInstance());
    // Note: This loses country info when number is not valid.
    Map<DialerPhoneNumber, String> dialerPhoneNumberToNormalizedNumbers =
        Maps.asMap(uniqueDialerPhoneNumbers, dialerPhoneNumberUtil::normalizeNumber);
        Maps.asMap(uniqueDialerPhoneNumbers, DialerPhoneNumber::getNormalizedNumber);

    // Convert values to a set to remove any duplicates that are the result of two
    // DialerPhoneNumbers mapping to the same normalized number.
@@ -543,9 +538,7 @@ public final class PhoneLookupDataSource
  }

  private Set<String> computePhoneLookupHistoryRowsToDelete(
      Map<DialerPhoneNumber, Set<Long>> annotatedCallLogIdsByNumber,
      CallLogMutations mutations,
      DialerPhoneNumberUtil dialerPhoneNumberUtil) {
      Map<DialerPhoneNumber, Set<Long>> annotatedCallLogIdsByNumber, CallLogMutations mutations) {
    if (mutations.getDeletes().isEmpty()) {
      return ImmutableSet.of();
    }
@@ -555,7 +548,8 @@ public final class PhoneLookupDataSource
    for (Entry<DialerPhoneNumber, Set<Long>> entry : annotatedCallLogIdsByNumber.entrySet()) {
      DialerPhoneNumber dialerPhoneNumber = entry.getKey();
      Set<Long> idsForDialerPhoneNumber = entry.getValue();
      String normalizedNumber = dialerPhoneNumberUtil.normalizeNumber(dialerPhoneNumber);
      // Note: This loses country info when number is not valid.
      String normalizedNumber = dialerPhoneNumber.getNormalizedNumber();
      Set<Long> idsForNormalizedNumber = idsByNormalizedNumber.get(normalizedNumber);
      if (idsForNormalizedNumber == null) {
        idsForNormalizedNumber = new ArraySet<>();
+2 −6
Original line number Diff line number Diff line
@@ -36,13 +36,11 @@ import com.android.dialer.phonelookup.PhoneLookupInfo;
import com.android.dialer.phonelookup.consolidator.PhoneLookupInfoConsolidator;
import com.android.dialer.phonelookup.database.contract.PhoneLookupHistoryContract;
import com.android.dialer.phonelookup.database.contract.PhoneLookupHistoryContract.PhoneLookupHistory;
import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -151,9 +149,6 @@ public final class RealtimeRowProcessor {
    ListenableFuture<Integer> applyBatchFuture =
        backgroundExecutor.submit(
            () -> {
              DialerPhoneNumberUtil dialerPhoneNumberUtil =
                  new DialerPhoneNumberUtil(PhoneNumberUtil.getInstance());

              ArrayList<ContentProviderOperation> operations = new ArrayList<>();
              long currentTimestamp = System.currentTimeMillis();
              for (Entry<DialerPhoneNumber, PhoneLookupInfo> entry : currentBatch.entrySet()) {
@@ -162,7 +157,8 @@ public final class RealtimeRowProcessor {

                // Note: Multiple DialerPhoneNumbers can map to the same normalized number but we
                // just write them all and the value for the last one will arbitrarily win.
                String normalizedNumber = dialerPhoneNumberUtil.normalizeNumber(dialerPhoneNumber);
                // Note: This loses country info when number is not valid.
                String normalizedNumber = dialerPhoneNumber.getNormalizedNumber();

                ContentValues contentValues = new ContentValues();
                contentValues.put(
+27 −14
Original line number Diff line number Diff line
@@ -39,18 +39,16 @@ import com.android.dialer.phonelookup.PhoneLookupInfo;
import com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info;
import com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info.Cp2ContactInfo;
import com.android.dialer.phonelookup.database.contract.PhoneLookupHistoryContract.PhoneLookupHistory;
import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil;
import com.android.dialer.phonenumberproto.PartitionedNumbers;
import com.android.dialer.storage.Unencrypted;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.protobuf.InvalidProtocolBufferException;
import java.util.ArrayList;
import java.util.List;
@@ -96,21 +94,32 @@ public final class Cp2LocalPhoneLookup implements PhoneLookup<Cp2Info> {
  }

  private Cp2Info lookupInternal(DialerPhoneNumber dialerPhoneNumber) {
    DialerPhoneNumberUtil dialerPhoneNumberUtil =
        new DialerPhoneNumberUtil(PhoneNumberUtil.getInstance());
    String number = dialerPhoneNumberUtil.normalizeNumber(dialerPhoneNumber);
    String number = dialerPhoneNumber.getNormalizedNumber();
    if (TextUtils.isEmpty(number)) {
      return Cp2Info.getDefaultInstance();
    }
    Optional<String> validE164 = dialerPhoneNumberUtil.formatToValidE164(dialerPhoneNumber);

    Set<Cp2ContactInfo> cp2ContactInfos = new ArraySet<>();
    // Note: It would make sense to use PHONE_LOOKUP for E164 numbers as well, but we use PHONE to
    // ensure consistency when the batch methods are used to update data.
    try (Cursor cursor =
        validE164.isPresent()
            ? queryPhoneTableBasedOnE164(
                Cp2Projections.getProjectionForPhoneTable(), ImmutableSet.of(validE164.get()))
            : queryPhoneLookup(Cp2Projections.getProjectionForPhoneLookupTable(), number)) {

    // Even though this is only a single number, use PartitionedNumbers to mimic the logic used
    // during getMostRecentInfo.
    PartitionedNumbers partitionedNumbers =
        new PartitionedNumbers(ImmutableSet.of(dialerPhoneNumber));

    Cursor cursor = null;
    try {
      // Note: It would make sense to use PHONE_LOOKUP for valid numbers as well, but we use PHONE
      // to ensure consistency when the batch methods are used to update data.
      if (!partitionedNumbers.validE164Numbers().isEmpty()) {
        cursor =
            queryPhoneTableBasedOnE164(
                Cp2Projections.getProjectionForPhoneTable(), partitionedNumbers.validE164Numbers());
      } else {
        cursor =
            queryPhoneLookup(
                Cp2Projections.getProjectionForPhoneLookupTable(),
                Iterables.getOnlyElement(partitionedNumbers.invalidNumbers()));
      }
      if (cursor == null) {
        LogUtil.w("Cp2LocalPhoneLookup.lookupInternal", "null cursor");
        return Cp2Info.getDefaultInstance();
@@ -118,6 +127,10 @@ public final class Cp2LocalPhoneLookup implements PhoneLookup<Cp2Info> {
      while (cursor.moveToNext()) {
        cp2ContactInfos.add(Cp2Projections.buildCp2ContactInfoFromCursor(appContext, cursor));
      }
    } finally {
      if (cursor != null) {
        cursor.close();
      }
    }
    return Cp2Info.newBuilder().addAllCp2ContactInfo(cp2ContactInfos).build();
  }
+2 −5
Original line number Diff line number Diff line
@@ -32,14 +32,12 @@ 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.phonenumberproto.DialerPhoneNumberUtil;
import com.android.dialer.phonenumberutil.PhoneNumberHelper;
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 com.google.i18n.phonenumbers.PhoneNumberUtil;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
@@ -114,9 +112,8 @@ public final class Cp2RemotePhoneLookup implements PhoneLookup<Cp2Info> {
      return Futures.immediateFuture(Cp2Info.getDefaultInstance());
    }

    DialerPhoneNumberUtil dialerPhoneNumberUtil =
        new DialerPhoneNumberUtil(PhoneNumberUtil.getInstance());
    String number = dialerPhoneNumberUtil.normalizeNumber(dialerPhoneNumber);
    // Note: This loses country info when number is not valid.
    String number = dialerPhoneNumber.getNormalizedNumber();

    List<ListenableFuture<Cp2Info>> cp2InfoFutures = new ArrayList<>();
    for (long remoteDirectoryId : remoteDirectoryIds) {
+18 −82
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.dialer.phonenumberproto;

import android.support.annotation.AnyThread;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;
@@ -25,9 +24,6 @@ import android.text.TextUtils;
import com.android.dialer.DialerPhoneNumber;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.google.common.base.Optional;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.PhoneNumberUtil.MatchType;
@@ -59,58 +55,30 @@ public class DialerPhoneNumberUtil {
    Assert.isWorkerThread();

    DialerPhoneNumber.Builder dialerPhoneNumber = DialerPhoneNumber.newBuilder();
    // Numbers can be null or empty for incoming "unknown" calls.
    if (numberToParse != null) {
      dialerPhoneNumber.setNormalizedNumber(normalizeNumber(numberToParse, defaultRegion));
    }

    if (defaultRegion != null) {
      dialerPhoneNumber.setCountryIso(defaultRegion);
    }
    return dialerPhoneNumber.build();
  }

  /**
   * Parses the provided raw phone number into a Future result of {@link DialerPhoneNumber}.
   *
   * <p>Work is run on the provided {@link ListeningExecutorService}.
   *
   * @see PhoneNumberUtil#parse(CharSequence, String)
   */
  @AnyThread
  public ListenableFuture<DialerPhoneNumber> parse(
      @Nullable String numberToParse,
      @Nullable String defaultRegion,
      @NonNull ListeningExecutorService service) {
    return service.submit(() -> parse(numberToParse, defaultRegion));
  }

  /**
   * Formats the provided number to E164 format or return a normalized version of the raw number if
   * the number is not valid according to {@link PhoneNumberUtil#isValidNumber(PhoneNumber)}.
   *
   * @see #formatToValidE164(DialerPhoneNumber)
   * @see PhoneNumberUtils#normalizeNumber(String)
   */
  public String normalizeNumber(DialerPhoneNumber number) {
    // TODO(zachh): Inline this method.
    // TODO(zachh): This loses country info when number is not valid.
    return number.getNormalizedNumber();
    // Numbers can be null or empty for incoming "unknown" calls.
    if (numberToParse == null) {
      return dialerPhoneNumber.build();
    }

  @WorkerThread
  private String normalizeNumber(@NonNull String rawNumber, @Nullable String defaultRegion) {
    Assert.isWorkerThread();

    // If the number is a service number, just store the raw number and don't bother trying to parse
    // it. PhoneNumberUtil#parse ignores these characters which can lead to confusing behavior, such
    // as the numbers "#123" and "123" being considered the same. The "#" can appear in the middle
    // of a service number and the "*" can appear at the beginning (see a bug).
    if (isServiceNumber(rawNumber)) {
      return rawNumber;
    if (isServiceNumber(numberToParse)) {
      return dialerPhoneNumber.setNormalizedNumber(numberToParse).build();
    }

    String postDialPortion = PhoneNumberUtils.extractPostDialPortion(numberToParse);
    if (!postDialPortion.isEmpty()) {
      dialerPhoneNumber.setPostDialPortion(postDialPortion);
    }

    String postDialPortion = PhoneNumberUtils.extractPostDialPortion(rawNumber);
    String networkPortion = PhoneNumberUtils.extractNetworkPortion(rawNumber);
    String networkPortion = PhoneNumberUtils.extractNetworkPortion(numberToParse);

    try {
      PhoneNumber phoneNumber = phoneNumberUtil.parse(networkPortion, defaultRegion);
@@ -118,18 +86,18 @@ public class DialerPhoneNumberUtil {
        String validNumber = phoneNumberUtil.format(phoneNumber, PhoneNumberFormat.E164);
        if (TextUtils.isEmpty(validNumber)) {
          throw new IllegalStateException(
              "e164 number should not be empty: " + LogUtil.sanitizePii(rawNumber));
              "e164 number should not be empty: " + LogUtil.sanitizePii(numberToParse));
        }
        // The E164 representation doesn't contain post-dial digits, but we need to preserve them.
        if (postDialPortion != null) {
        if (!postDialPortion.isEmpty()) {
          validNumber += postDialPortion;
        }
        return validNumber;
        return dialerPhoneNumber.setNormalizedNumber(validNumber).setIsValid(true).build();
      }
    } catch (NumberParseException e) {
      // fall through
    }
    return networkPortion + postDialPortion;
    return dialerPhoneNumber.setNormalizedNumber(networkPortion + postDialPortion).build();
  }

  /**
@@ -197,39 +165,7 @@ public class DialerPhoneNumberUtil {
    return (matchType == MatchType.SHORT_NSN_MATCH
            || matchType == MatchType.NSN_MATCH
            || matchType == MatchType.EXACT_MATCH)
        && samePostDialPortion(firstNumberIn, secondNumberIn);
  }

  private static boolean samePostDialPortion(DialerPhoneNumber number1, DialerPhoneNumber number2) {
    return PhoneNumberUtils.extractPostDialPortion(number1.getNormalizedNumber())
        .equals(PhoneNumberUtils.extractPostDialPortion(number2.getNormalizedNumber()));
  }

  /**
   * If the provided number is "valid" (see {@link PhoneNumberUtil#isValidNumber(PhoneNumber)}),
   * formats it to E.164. Otherwise, returns {@link Optional#absent()}.
   *
   * <p>This method is analogous to {@link PhoneNumberUtils#formatNumberToE164(String, String)} (but
   * works with an already parsed {@link DialerPhoneNumber} object).
   *
   * @see PhoneNumberUtil#isValidNumber(PhoneNumber)
   * @see PhoneNumberUtil#format(PhoneNumber, PhoneNumberFormat)
   * @see PhoneNumberUtils#formatNumberToE164(String, String)
   */
  @WorkerThread
  public Optional<String> formatToValidE164(DialerPhoneNumber number) {
    // TODO(zachh): We could do something like store a "valid" bit in DialerPhoneNumber?
    Assert.isWorkerThread();
    PhoneNumber phoneNumber;
    try {
      phoneNumber = phoneNumberUtil.parse(number.getNormalizedNumber(), number.getCountryIso());
    } catch (NumberParseException e) {
      return Optional.absent();
    }
    if (phoneNumberUtil.isValidNumber(phoneNumber)) {
      return Optional.fromNullable(phoneNumberUtil.format(phoneNumber, PhoneNumberFormat.E164));
    }
    return Optional.absent();
        && firstNumberIn.getPostDialPortion().equals(secondNumberIn.getPostDialPortion());
  }

  private boolean isServiceNumber(@NonNull String rawNumber) {
Loading