diff options
author | Brian Attwell <brianattwell@google.com> | 2014-02-27 12:19:46 -0800 |
---|---|---|
committer | Brian Attwell <brianattwell@google.com> | 2014-02-28 16:52:58 -0800 |
commit | bf98e55afd5f39f72dc05c704409655b89a7fa25 (patch) | |
tree | 9aa421b6c5e51c9e901491602e31a99b39ae3590 /src/com/android/providers/contacts/PhoneLookupWithStarPrefix.java | |
parent | 120ca86ad7873be1bc02a4228035749f60358024 (diff) | |
download | packages_providers_ContactsProvider-bf98e55afd5f39f72dc05c704409655b89a7fa25.zip packages_providers_ContactsProvider-bf98e55afd5f39f72dc05c704409655b89a7fa25.tar.gz packages_providers_ContactsProvider-bf98e55afd5f39f72dc05c704409655b89a7fa25.tar.bz2 |
Do not ignore leading "*"s in phone lookups
After a phone lookup, "remove" entries from the cursor that
don't match the queried number w.r.t. to whether it has a leading
"*". "Removing" entries from a cursor involves making a partial
copy of the cursor.
This CL affects as little functionality as possible, so that it
can make it into MR2. Ie, we continue to ignore leading "*"s
in other CP2 queries.
MANUAL TESTS:
-Add a "*123" Emergency contact and "123" Voicemail contact
-Call "*123", then call "123". You should see two seperate
entries in your call log. In addition, the incall screens
should show Emergency and Voicemail respectively (although
the "123" call doesn't work properly inside the incall
UI right now. This is a seperate bug b/13195342).
Bug: 13195334
Change-Id: I7e1938ccb085630072611eb63148c5714b62fee8
Diffstat (limited to 'src/com/android/providers/contacts/PhoneLookupWithStarPrefix.java')
-rw-r--r-- | src/com/android/providers/contacts/PhoneLookupWithStarPrefix.java | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/src/com/android/providers/contacts/PhoneLookupWithStarPrefix.java b/src/com/android/providers/contacts/PhoneLookupWithStarPrefix.java new file mode 100644 index 0000000..a05dd05 --- /dev/null +++ b/src/com/android/providers/contacts/PhoneLookupWithStarPrefix.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2014 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.providers.contacts; + +import com.android.internal.annotations.VisibleForTesting; + +import android.database.Cursor; +import android.database.MatrixCursor; +import android.provider.ContactsContract.PhoneLookup; +import android.telephony.PhoneNumberUtils; +import android.text.TextUtils; +import android.util.Log; + +/** + * Helper class for PHONE_LOOKUP's that involve numbers with "*" prefixes. + */ +/* package-protected */ final class PhoneLookupWithStarPrefix { + private static final String TAG = "PhoneLookupWSP"; + + /** + * Returns a cursor with a subset of the rows passed into this function. If {@param number} + * starts with a "*" then only rows from {@param cursor} that have a number equal to + * {@param number} will be returned. If {@param number} doesn't start with a "*", then + * only rows from {@param cursor} that have numbers without starting "*" characters + * will be returned. + * + * This function is used to resolve b/13195334. + * + * @param number unnormalized phone number. + * @param cursor this function takes ownership of the cursor. The calling scope MUST NOT + * use or close() the cursor passed into this function. The cursor must contain + * PhoneLookup.NUMBER. + * + * @return a cursor that the calling context owns + */ + public static Cursor removeNonStarMatchesFromCursor(String number, Cursor cursor) { + + // Close cursors that we don't return. + Cursor unreturnedCursor = cursor; + + try { + if (TextUtils.isEmpty(number)) { + unreturnedCursor = null; + return cursor; + } + + final String queryPhoneNumberNormalized = normalizeNumberWithStar(number); + if (!queryPhoneNumberNormalized.startsWith("*") + && !matchingNumberStartsWithStar(cursor)) { + cursor.moveToPosition(-1); + unreturnedCursor = null; + return cursor; + } + + final MatrixCursor matrixCursor = new MatrixCursor(cursor.getColumnNames()); + + // Close cursors that we don't return. + Cursor unreturnedMatrixCursor = matrixCursor; + + try { + cursor.moveToPosition(-1); + while (cursor.moveToNext()) { + final int numberIndex = cursor.getColumnIndex(PhoneLookup.NUMBER); + final String matchingNumberNormalized + = normalizeNumberWithStar(cursor.getString(numberIndex)); + if (!matchingNumberNormalized.startsWith("*") + && !queryPhoneNumberNormalized.startsWith("*") + || matchingNumberNormalized.equals(queryPhoneNumberNormalized)) { + // Copy row from cursor into matrixCursor + final MatrixCursor.RowBuilder b = matrixCursor.newRow(); + for (int column = 0; column < cursor.getColumnCount(); column++) { + b.add(cursor.getColumnName(column), cursorValue(cursor, column)); + } + } + } + unreturnedMatrixCursor = null; + return matrixCursor; + } finally { + if (unreturnedMatrixCursor != null) { + unreturnedMatrixCursor.close(); + } + } + } finally { + if (unreturnedCursor != null) { + unreturnedCursor.close(); + } + } + } + + @VisibleForTesting + static String normalizeNumberWithStar(String phoneNumber) { + if (TextUtils.isEmpty(phoneNumber)) { + return phoneNumber; + } + if (phoneNumber.startsWith("*")) { + // Use PhoneNumberUtils.normalizeNumber() to normalize the rest of the number after + // the leading "*". Strip out the "+" since "+"s are only allowed as leading + // characters. NOTE: This statement has poor performance. Fortunately, it won't be + // called very often. + return "*" + PhoneNumberUtils.normalizeNumber( + phoneNumber.substring(1).replace("+", "")); + } + return PhoneNumberUtils.normalizeNumber(phoneNumber); + } + + /** + * @return whether {@param cursor} contain any numbers that start with "*" + */ + private static boolean matchingNumberStartsWithStar(Cursor cursor) { + cursor.moveToPosition(-1); + while (cursor.moveToNext()) { + final int numberIndex = cursor.getColumnIndex(PhoneLookup.NUMBER); + final String phoneNumber = normalizeNumberWithStar(cursor.getString(numberIndex)); + if (phoneNumber.startsWith("*")) { + return true; + } + } + return false; + } + + private static Object cursorValue(Cursor cursor, int column) { + switch(cursor.getType(column)) { + case Cursor.FIELD_TYPE_BLOB: + return cursor.getBlob(column); + case Cursor.FIELD_TYPE_INTEGER: + return cursor.getInt(column); + case Cursor.FIELD_TYPE_FLOAT: + return cursor.getFloat(column); + case Cursor.FIELD_TYPE_STRING: + return cursor.getString(column); + case Cursor.FIELD_TYPE_NULL: + return null; + default: + Log.d(TAG, "Invalid value in cursor: " + cursor.getType(column)); + return null; + } + } +} |