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

Commit 7c98fd60 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Take into consideration special characters when we do contact match."

parents 35363b34 2d5167b4
Loading
Loading
Loading
Loading
+15 −2
Original line number Diff line number Diff line
@@ -189,13 +189,26 @@ public class CallLogGroupBuilder {
    mGroupCreator.addGroup(count - groupSize, groupSize);
  }

  /**
   * Returns true when the two input numbers can be considered identical enough for caller ID
   * purposes and put in a call log group.
   */
  @VisibleForTesting
  boolean equalNumbers(@Nullable String number1, @Nullable String number2) {
    if (PhoneNumberHelper.isUriNumber(number1) || PhoneNumberHelper.isUriNumber(number2)) {
      return compareSipAddresses(number1, number2);
    } else {
      return PhoneNumberUtils.compare(number1, number2);
    }

    // PhoneNumberUtils.compare(String, String) ignores special characters such as '#'. For example,
    // it thinks "123" and "#123" are identical enough for caller ID purposes.
    // When either input number contains special characters, we put the two in the same group iff
    // their raw numbers are exactly the same.
    if (PhoneNumberHelper.numberHasSpecialChars(number1)
        || PhoneNumberHelper.numberHasSpecialChars(number2)) {
      return PhoneNumberHelper.sameRawNumbers(number1, number2);
    }

    return PhoneNumberUtils.compare(number1, number2);
  }

  private boolean isSameAccount(String name1, String name2, String id1, String id2) {
+11 −0
Original line number Diff line number Diff line
@@ -355,6 +355,17 @@ public class ContactInfoHelper {
        return ContactInfo.EMPTY;
      }

      // The Contacts provider ignores special characters in phone numbers when searching for a
      // contact. For example, number "123" is considered a match with a contact with number "#123".
      // We need to check whether the result contains a number that truly matches the query and move
      // the cursor to that position before building a ContactInfo.
      boolean hasNumberMatch =
          PhoneNumberHelper.updateCursorToMatchContactLookupUri(
              phoneLookupCursor, PhoneQuery.MATCHED_NUMBER, uri);
      if (!hasNumberMatch) {
        return ContactInfo.EMPTY;
      }

      String lookupKey = phoneLookupCursor.getString(PhoneQuery.LOOKUP_KEY);
      ContactInfo contactInfo = createPhoneLookupContactInfo(phoneLookupCursor, lookupKey);
      fillAdditionalContactInfo(mContext, contactInfo);
+88 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.dialer.phonenumberutil;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Trace;
import android.provider.CallLog;
import android.support.annotation.NonNull;
@@ -27,6 +29,7 @@ import android.telephony.TelephonyManager;
import android.text.BidiFormatter;
import android.text.TextDirectionHeuristics;
import android.text.TextUtils;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.compat.CompatUtils;
import com.android.dialer.compat.telephony.TelephonyManagerCompat;
@@ -49,6 +52,91 @@ public class PhoneNumberHelper {
        && !isLegacyUnknownNumbers(number);
  }

  /**
   * Move the given cursor to a position where the number it points to matches the number in a
   * contact lookup URI.
   *
   * <p>We assume the cursor is one returned by the Contacts Provider when the URI asks for a
   * specific number. This method's behavior is undefined when the cursor doesn't meet the
   * assumption.
   *
   * <p>When determining whether two phone numbers are identical enough for caller ID purposes, the
   * Contacts Provider ignores special characters such as '#'. This makes it possible for the cursor
   * returned by the Contacts Provider to have multiple rows even when the URI asks for a specific
   * number.
   *
   * <p>For example, suppose the user has two contacts whose numbers are "#123" and "123",
   * respectively. When the URI asks for number "123", both numbers will be returned. Therefore, the
   * following strategy is employed to find a match.
   *
   * <p>In the following description, we use E to denote a number the cursor points to (an existing
   * contact number), and L to denote the number in the contact lookup URI.
   *
   * <p>If neither E nor L contains special characters, return true to indicate a match is found.
   *
   * <p>If either E or L contains special characters, return true when the raw numbers of E and L
   * are the same. Otherwise, move the cursor to its next position and start over.
   *
   * <p>Return false in all other circumstances to indicate that no match can be found.
   *
   * <p>When no match can be found, the cursor is after the last result when the method returns.
   *
   * @param cursor A cursor returned by the Contacts Provider.
   * @param columnIndexForNumber The index of the column where phone numbers are stored. It is the
   *     caller's responsibility to pass the correct column index.
   * @param contactLookupUri A URI used to retrieve a contact via the Contacts Provider. It is the
   *     caller's responsibility to ensure the URI is one that asks for a specific phone number.
   * @return true if a match can be found.
   */
  public static boolean updateCursorToMatchContactLookupUri(
      @Nullable Cursor cursor, int columnIndexForNumber, @Nullable Uri contactLookupUri) {
    if (cursor == null || contactLookupUri == null) {
      return false;
    }

    if (!cursor.moveToFirst()) {
      return false;
    }

    Assert.checkArgument(
        0 <= columnIndexForNumber && columnIndexForNumber < cursor.getColumnCount());

    String lookupNumber = contactLookupUri.getLastPathSegment();
    if (TextUtils.isEmpty(lookupNumber)) {
      return false;
    }

    boolean lookupNumberHasSpecialChars = numberHasSpecialChars(lookupNumber);

    do {
      String existingContactNumber = cursor.getString(columnIndexForNumber);
      boolean existingContactNumberHasSpecialChars = numberHasSpecialChars(existingContactNumber);

      if ((!lookupNumberHasSpecialChars && !existingContactNumberHasSpecialChars)
          || sameRawNumbers(existingContactNumber, lookupNumber)) {
        return true;
      }

    } while (cursor.moveToNext());

    return false;
  }

  /** Returns true if the input phone number contains special characters. */
  public static boolean numberHasSpecialChars(String number) {
    return !TextUtils.isEmpty(number) && number.contains("#");
  }

  /** Returns true if the raw numbers of the two input phone numbers are the same. */
  public static boolean sameRawNumbers(String number1, String number2) {
    String rawNumber1 =
        PhoneNumberUtils.stripSeparators(PhoneNumberUtils.convertKeypadLettersToDigits(number1));
    String rawNumber2 =
        PhoneNumberUtils.stripSeparators(PhoneNumberUtils.convertKeypadLettersToDigits(number2));

    return rawNumber1.equals(rawNumber2);
  }

  /**
   * Returns true if the given number is the number of the configured voicemail. To be able to
   * mock-out this, it is not a static method.
+16 −6
Original line number Diff line number Diff line
@@ -223,16 +223,26 @@ public class CallerInfo {
    long contactId = 0L;
    int columnIndex;

    // Look for the name
    columnIndex = cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME);
    if (columnIndex != -1) {
      info.name = normalize(cursor.getString(columnIndex));
    }

    // Look for the number
    columnIndex = cursor.getColumnIndex(PhoneLookup.NUMBER);
    if (columnIndex != -1) {
      // The Contacts provider ignores special characters in phone numbers when searching for a
      // contact. For example, number "123" is considered a match with a contact with number "#123".
      // We need to check whether the result contains a number that truly matches the query and move
      // the cursor to that position before filling in the fields in CallerInfo.
      boolean hasNumberMatch =
          PhoneNumberHelper.updateCursorToMatchContactLookupUri(cursor, columnIndex, contactRef);
      if (hasNumberMatch) {
        info.phoneNumber = cursor.getString(columnIndex);
      } else {
        return info;
      }
    }

    // Look for the name
    columnIndex = cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME);
    if (columnIndex != -1) {
      info.name = normalize(cursor.getString(columnIndex));
    }

    // Look for the normalized number