Skip to content
This repository has been archived by the owner on Nov 15, 2022. It is now read-only.

Commit

Permalink
bug 2236535: find a way to update the stale canonical_addresses entri…
Browse files Browse the repository at this point in the history
…es with new SMS/MMS number.

- when the user sends a message, let's check if the new message's address is different than the one
stored in the recipientId's cache. If it is, let's update the cache and the underlying canonical_addresses
table in the db, so we wouldn't keep using a bad number for future references.

Change-Id: I3ac9940fa3c37d29c7398cac4535915249469563
  • Loading branch information
Wei Huang committed Nov 8, 2009
1 parent 963f4a9 commit 431e11d
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 16 deletions.
24 changes: 22 additions & 2 deletions src/com/android/mms/data/Contact.java
Expand Up @@ -54,6 +54,9 @@ public void onChange(boolean selfUpdate) {
private String mNumber;
private String mName;
private String mNameAndNumber; // for display, e.g. Fred Flintstone <670-782-1123>
private boolean mNumberIsModified; // true if the number is modified

private long mRecipientId; // used to find the Recipient cache entry
private String mLabel;
private long mPersonId;
private int mPresenceResId; // TODO: make this a state instead of a res ID
Expand All @@ -72,9 +75,9 @@ public interface UpdateListener {
}

private Contact(String number) {
mNumber = number;
mName = "";
updateNameAndNumber();
setNumber(number);
mNumberIsModified = false;
mLabel = "";
mPersonId = 0;
mPresenceResId = 0;
Expand Down Expand Up @@ -273,6 +276,15 @@ public synchronized String getNumber() {
public synchronized void setNumber(String number) {
mNumber = number;
updateNameAndNumber();
mNumberIsModified = true;
}

public boolean isNumberModified() {
return mNumberIsModified;
}

public void setIsNumberModified(boolean flag) {
mNumberIsModified = flag;
}

public synchronized String getName() {
Expand All @@ -291,6 +303,14 @@ private void updateNameAndNumber() {
mNameAndNumber = formatNameAndNumber(mName, mNumber);
}

public synchronized long getRecipientId() {
return mRecipientId;
}

public synchronized void setRecipientId(long id) {
mRecipientId = id;
}

public synchronized String getLabel() {
return mLabel;
}
Expand Down
12 changes: 9 additions & 3 deletions src/com/android/mms/data/ContactList.java
Expand Up @@ -39,11 +39,17 @@ public static ContactList getByNumbers(String semiSepNumbers,
return list;
}

/**
* Returns a ContactList for the corresponding recipient ids passed in. This method will
* create the contact if it doesn't exist, and would inject the recipient id into the contact.
*/
public static ContactList getByIds(String spaceSepIds, boolean canBlock) {
ContactList list = new ContactList();
for (String number : RecipientIdCache.getNumbers(spaceSepIds)) {
if (!TextUtils.isEmpty(number)) {
list.add(Contact.get(number, canBlock));
for (RecipientIdCache.Entry entry : RecipientIdCache.getAddresses(spaceSepIds)) {
if (entry != null && !TextUtils.isEmpty(entry.number)) {
Contact contact = Contact.get(entry.number, canBlock);
contact.setRecipientId(entry.id);
list.add(contact);
}
}
return list;
Expand Down
103 changes: 92 additions & 11 deletions src/com/android/mms/data/RecipientIdCache.java
Expand Up @@ -6,22 +6,41 @@
import java.util.Map;

import android.content.Context;
import android.content.ContentValues;
import android.content.ContentUris;
import android.database.Cursor;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import android.provider.Telephony;

import com.google.android.mms.util.SqliteWrapper;
import com.android.mms.LogTag;

public class RecipientIdCache {
private static final String TAG = "RecipientIdCache";
private static final String TAG = "Mms/cache";

private static Uri sAllCanonical =
Uri.parse("content://mms-sms/canonical-addresses");

private static Uri sSingleCanonicalAddressUri =
Uri.parse("content://mms-sms/canonical-address");

private static Uri sAllCanonical = Uri.parse("content://mms-sms/canonical-addresses");
private static RecipientIdCache sInstance;
static RecipientIdCache getInstance() { return sInstance; }
private final Map<String, String> mCache;
private final Map<Long, String> mCache;
private final Context mContext;

public static class Entry {
public long id;
public String number;

public Entry(long id, String number) {
this.id = id;
this.number = number;
}
};

static void init(Context context) {
sInstance = new RecipientIdCache(context);
new Thread(new Runnable() {
Expand All @@ -32,21 +51,23 @@ public void run() {
}

RecipientIdCache(Context context) {
mCache = new HashMap<String, String>();
mCache = new HashMap<Long, String>();
mContext = context;
}

public static void fill() {
Context context = sInstance.mContext;
Cursor c = SqliteWrapper.query(context, context.getContentResolver(),
sAllCanonical, null, null, null, null);

try {
synchronized (sInstance) {
// Technically we don't have to clear this because the stupid
// canonical_addresses table is never GC'ed.
sInstance.mCache.clear();
while (c.moveToNext()) {
String id = c.getString(0);
// TODO: don't hardcode the column indices
long id = c.getLong(0);
String number = c.getString(1);
sInstance.mCache.put(id, number);
}
Expand All @@ -56,32 +77,92 @@ public static void fill() {
}
}

public static List<String> getNumbers(String spaceSepIds) {
public static List<Entry> getAddresses(String spaceSepIds) {
synchronized (sInstance) {
List<String> numbers = new ArrayList<String>();
List<Entry> numbers = new ArrayList<Entry>();
String[] ids = spaceSepIds.split(" ");
for (String id : ids) {
String number = sInstance.mCache.get(id);
long longId;

try {
longId = Long.parseLong(id);
} catch (NumberFormatException ex) {
// skip this id
continue;
}

String number = sInstance.mCache.get(longId);

if (number == null) {
Log.w(TAG, "Recipient ID " + id + " not in DB!");
dump();
fill();
number = sInstance.mCache.get(id);
}
}

if (TextUtils.isEmpty(number)) {
Log.w(TAG, "Recipient ID " + id + " has empty number!");
} else {
numbers.add(number);
numbers.add(new Entry(longId, number));
}
}
return numbers;
}
}

public static void updateNumbers(long threadId, ContactList contacts) {
long recipientId = 0;

for (Contact contact : contacts) {
if (contact.isNumberModified()) {
contact.setIsNumberModified(false);
} else {
// if the contact's number wasn't modified, don't bother.
continue;
}

recipientId = contact.getRecipientId();
if (recipientId == 0) {
continue;
}

String number1 = contact.getNumber();
String number2 = sInstance.mCache.get(recipientId);

if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
Log.d(TAG, "[RecipientIdCache] updateNumbers: comparing " + number1 +
" with " + number2);
}

// if the numbers don't match, let's update the RecipientIdCache's number
// with the new number in the contact.
if (!number1.equalsIgnoreCase(number2)) {
sInstance.mCache.put(recipientId, number1);
sInstance.updateCanonicalAddressInDb(recipientId, number1);
}
}
}

private void updateCanonicalAddressInDb(long id, String number) {
if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
Log.d(TAG, "[RecipientIdCache] updateCanonicalAddressInDb: id=" + id +
", number=" + number);
}

ContentValues values = new ContentValues();
values.put(Telephony.CanonicalAddressesColumns.ADDRESS, number);

StringBuilder buf = new StringBuilder(Telephony.CanonicalAddressesColumns._ID);
buf.append('=').append(id);

Uri uri = ContentUris.withAppendedId(sSingleCanonicalAddressUri, id);
mContext.getContentResolver().update(uri, values, buf.toString(), null);
}

public static void dump() {
synchronized (sInstance) {
Log.d(TAG, "*** Recipient ID cache dump ***");
for (String id : sInstance.mCache.keySet()) {
for (Long id : sInstance.mCache.keySet()) {
Log.d(TAG, id + ": " + sInstance.mCache.get(id));
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/com/android/mms/data/WorkingMessage.java
Expand Up @@ -932,6 +932,9 @@ public void run() {
}).start();
}

// update the Recipient cache with the new to address, if it's different
RecipientIdCache.updateNumbers(conv.getThreadId(), conv.getRecipients());

// Mark the message as discarded because it is "off the market" after being sent.
mDiscarded = true;
}
Expand Down

0 comments on commit 431e11d

Please sign in to comment.