1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License 15 */ 16 package com.android.providers.contacts; 17 18 import android.content.ContentValues; 19 import android.content.Context; 20 import android.database.Cursor; 21 import android.database.sqlite.SQLiteDatabase; 22 import android.provider.ContactsContract.CommonDataKinds.Phone; 23 import android.telephony.PhoneNumberUtils; 24 import android.text.TextUtils; 25 26 import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns; 27 import com.android.providers.contacts.ContactsDatabaseHelper.Tables; 28 import com.android.providers.contacts.SearchIndexManager.IndexBuilder; 29 import com.android.providers.contacts.aggregation.ContactAggregator; 30 31 /** 32 * Handler for phone number data rows. 33 */ 34 public class DataRowHandlerForPhoneNumber extends DataRowHandlerForCommonDataKind { 35 36 public DataRowHandlerForPhoneNumber(Context context, 37 ContactsDatabaseHelper dbHelper, ContactAggregator aggregator) { 38 super(context, dbHelper, aggregator, Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 39 } 40 41 @Override 42 public long insert(SQLiteDatabase db, TransactionContext txContext, long rawContactId, 43 ContentValues values) { 44 fillNormalizedNumber(values); 45 46 final long dataId = super.insert(db, txContext, rawContactId, values); 47 if (values.containsKey(Phone.NUMBER)) { 48 final String number = values.getAsString(Phone.NUMBER); 49 final String normalizedNumber = values.getAsString(Phone.NORMALIZED_NUMBER); 50 updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 51 mContactAggregator.updateHasPhoneNumber(db, rawContactId); 52 fixRawContactDisplayName(db, txContext, rawContactId); 53 54 triggerAggregation(txContext, rawContactId); 55 } 56 return dataId; 57 } 58 59 @Override 60 public boolean update(SQLiteDatabase db, TransactionContext txContext, ContentValues values, 61 Cursor c, boolean callerIsSyncAdapter) { 62 fillNormalizedNumber(values); 63 64 if (!super.update(db, txContext, values, c, callerIsSyncAdapter)) { 65 return false; 66 } 67 68 if (values.containsKey(Phone.NUMBER)) { 69 long dataId = c.getLong(DataUpdateQuery._ID); 70 long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 71 updatePhoneLookup(db, rawContactId, dataId, 72 values.getAsString(Phone.NUMBER), 73 values.getAsString(Phone.NORMALIZED_NUMBER)); 74 mContactAggregator.updateHasPhoneNumber(db, rawContactId); 75 fixRawContactDisplayName(db, txContext, rawContactId); 76 77 triggerAggregation(txContext, rawContactId); 78 } 79 80 return true; 81 } 82 83 private void fillNormalizedNumber(ContentValues values) { 84 // No NUMBER? Also ignore NORMALIZED_NUMBER 85 if (!values.containsKey(Phone.NUMBER)) { 86 values.remove(Phone.NORMALIZED_NUMBER); 87 return; 88 } 89 90 // NUMBER is given. Try to extract NORMALIZED_NUMBER from it, unless it is also given 91 final String number = values.getAsString(Phone.NUMBER); 92 final String numberE164 = values.getAsString(Phone.NORMALIZED_NUMBER); 93 if (number != null && numberE164 == null) { 94 final String newNumberE164 = PhoneNumberUtils.formatNumberToE164(number, 95 mDbHelper.getCurrentCountryIso()); 96 values.put(Phone.NORMALIZED_NUMBER, newNumberE164); 97 } 98 } 99 100 @Override 101 public int delete(SQLiteDatabase db, TransactionContext txContext, Cursor c) { 102 long dataId = c.getLong(DataDeleteQuery._ID); 103 long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 104 105 int count = super.delete(db, txContext, c); 106 107 updatePhoneLookup(db, rawContactId, dataId, null, null); 108 mContactAggregator.updateHasPhoneNumber(db, rawContactId); 109 fixRawContactDisplayName(db, txContext, rawContactId); 110 triggerAggregation(txContext, rawContactId); 111 return count; 112 } 113 114 private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 115 String number, String numberE164) { 116 mSelectionArgs1[0] = String.valueOf(dataId); 117 db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=?", mSelectionArgs1); 118 if (number != null) { 119 String normalizedNumber = PhoneNumberUtils.normalizeNumber(number); 120 if (!TextUtils.isEmpty(normalizedNumber)) { 121 ContentValues phoneValues = new ContentValues(); 122 phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 123 phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 124 phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 125 phoneValues.put(PhoneLookupColumns.MIN_MATCH, 126 PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber)); 127 db.insert(Tables.PHONE_LOOKUP, null, phoneValues); 128 129 if (numberE164 != null && !numberE164.equals(normalizedNumber)) { 130 phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, numberE164); 131 phoneValues.put(PhoneLookupColumns.MIN_MATCH, 132 PhoneNumberUtils.toCallerIDMinMatch(numberE164)); 133 db.insert(Tables.PHONE_LOOKUP, null, phoneValues); 134 } 135 } 136 } 137 } 138 139 @Override 140 protected int getTypeRank(int type) { 141 switch (type) { 142 case Phone.TYPE_MOBILE: return 0; 143 case Phone.TYPE_WORK: return 1; 144 case Phone.TYPE_HOME: return 2; 145 case Phone.TYPE_PAGER: return 3; 146 case Phone.TYPE_CUSTOM: return 4; 147 case Phone.TYPE_OTHER: return 5; 148 case Phone.TYPE_FAX_WORK: return 6; 149 case Phone.TYPE_FAX_HOME: return 7; 150 default: return 1000; 151 } 152 } 153 154 @Override 155 public boolean containsSearchableColumns(ContentValues values) { 156 return values.containsKey(Phone.NUMBER); 157 } 158 159 @Override 160 public void appendSearchableData(IndexBuilder builder) { 161 String number = builder.getString(Phone.NUMBER); 162 if (TextUtils.isEmpty(number)) { 163 return; 164 } 165 166 String normalizedNumber = PhoneNumberUtils.normalizeNumber(number); 167 if (TextUtils.isEmpty(normalizedNumber)) { 168 return; 169 } 170 171 builder.appendToken(normalizedNumber); 172 173 String numberE164 = PhoneNumberUtils.formatNumberToE164( 174 number, mDbHelper.getCurrentCountryIso()); 175 if (numberE164 != null && !numberE164.equals(normalizedNumber)) { 176 builder.appendToken(numberE164); 177 } 178 } 179 } 180