Merge "Adding DELETED column to SMS raw table to support message de-duping." into nyc-dev
diff --git a/src/com/android/providers/telephony/TelephonyBackupAgent.java b/src/com/android/providers/telephony/TelephonyBackupAgent.java
index 5956d33..748a703 100644
--- a/src/com/android/providers/telephony/TelephonyBackupAgent.java
+++ b/src/com/android/providers/telephony/TelephonyBackupAgent.java
@@ -28,7 +28,7 @@
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.FullBackupDataOutput;
-import android.content.ContentProvider;
+import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
@@ -39,6 +39,7 @@
import android.net.Uri;
import android.os.Build;
import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
import android.provider.BaseColumns;
import android.provider.Telephony;
import android.telephony.PhoneNumberUtils;
@@ -224,8 +225,9 @@
// Maximum messages for one backup file. After reaching the limit the agent backs up the file,
// deletes it and creates a new one with the same name.
+ // Not final for the testing.
@VisibleForTesting
- static int MAX_MSG_PER_FILE = 1000;
+ int mMaxMsgPerFile = 1000;
// Default values for SMS, MMS, Addresses restore.
@@ -263,23 +265,19 @@
}
- private final SparseArray<String> subId2phone = new SparseArray<String>();
+ private SparseArray<String> mSubId2phone = new SparseArray<String>();
+ private Map<String, Integer> mPhone2subId = new ArrayMap<String, Integer>();
- // It's static cause it's used by DeferredSmsMmsRestoreService.
- private static final Map<String, Integer> sPhone2subId = new ArrayMap<String, Integer>();
- private ContentProvider mSmsProvider;
- private ContentProvider mMmsProvider;
- private ContentProvider mMmsSmsProvider;
-
+ private ContentResolver mContentResolver;
// How many bytes we can backup to fit into quota.
private long mBytesOverQuota;
// Cache list of recipients by threadId. It reduces db requests heavily. Used during backup.
@VisibleForTesting
- static Map<Long, List<String>> sCacheRecipientsByThread;
+ Map<Long, List<String>> mCacheRecipientsByThread = null;
// Cache threadId by list of recipients. Used during restore.
@VisibleForTesting
- static Map<Set<String>, Long> sCacheGetOrCreateThreadId;
+ Map<Set<String>, Long> mCacheGetOrCreateThreadId = null;
@Override
public void onCreate() {
@@ -292,35 +290,22 @@
if (subInfo != null) {
for (SubscriptionInfo sub : subInfo) {
final String phoneNumber = getNormalizedNumber(sub);
- subId2phone.append(sub.getSubscriptionId(), phoneNumber);
- sPhone2subId.put(phoneNumber, sub.getSubscriptionId());
+ mSubId2phone.append(sub.getSubscriptionId(), phoneNumber);
+ mPhone2subId.put(phoneNumber, sub.getSubscriptionId());
}
}
}
-
- mSmsProvider = new SmsProvider();
- mSmsProvider.attachInfo(this, null);
- mSmsProvider.onCreate();
-
- mMmsProvider = new MmsProvider();
- mMmsProvider.attachInfo(this, null);
- mMmsProvider.onCreate();
-
- mMmsSmsProvider = new MmsSmsProvider();
- mMmsSmsProvider.attachInfo(this, null);
- mMmsSmsProvider.onCreate();
-
- sCacheRecipientsByThread = null;
- sCacheGetOrCreateThreadId = null;
+ mContentResolver = getContentResolver();
}
@VisibleForTesting
- void setProviders(ContentProvider smsProvider,
- ContentProvider mmsProvider,
- ContentProvider mmsSmsProvider) {
- mSmsProvider = smsProvider;
- mMmsProvider = mmsProvider;
- mMmsSmsProvider = mmsSmsProvider;
+ void setContentResolver(ContentResolver contentResolver) {
+ mContentResolver = contentResolver;
+ }
+ @VisibleForTesting
+ void setSubId(SparseArray<String> subId2Phone, Map<String, Integer> phone2subId) {
+ mSubId2phone = subId2Phone;
+ mPhone2subId = phone2subId;
}
@Override
@@ -338,10 +323,10 @@
}
try (
- Cursor smsCursor = mSmsProvider.query(Telephony.Sms.CONTENT_URI, SMS_PROJECTION,
+ Cursor smsCursor = mContentResolver.query(Telephony.Sms.CONTENT_URI, SMS_PROJECTION,
null, null, ORDER_BY_DATE);
// Do not backup non text-only MMS's.
- Cursor mmsCursor = mMmsProvider.query(Telephony.Mms.CONTENT_URI, MMS_PROJECTION,
+ Cursor mmsCursor = mContentResolver.query(Telephony.Mms.CONTENT_URI, MMS_PROJECTION,
Telephony.Mms.TEXT_ONLY+"=1", null, ORDER_BY_DATE)) {
if (smsCursor != null) {
@@ -415,41 +400,35 @@
int messagesWritten = 0;
try (JsonWriter jsonWriter = getJsonWriter(fileName)) {
if (fileName.endsWith(SMS_BACKUP_FILE_SUFFIX)) {
- messagesWritten = putSmsMessagesToJson(cursor, mMmsSmsProvider,
- subId2phone, jsonWriter, MAX_MSG_PER_FILE);
+ messagesWritten = putSmsMessagesToJson(cursor, jsonWriter);
} else {
- messagesWritten = putMmsMessagesToJson(cursor, mMmsProvider,
- mMmsSmsProvider, subId2phone, jsonWriter, MAX_MSG_PER_FILE);
+ messagesWritten = putMmsMessagesToJson(cursor, jsonWriter);
}
}
backupFile(messagesWritten, fileName, data);
}
@VisibleForTesting
- static int putMmsMessagesToJson(Cursor cursor, ContentProvider mmsProvider,
- ContentProvider threadProvider,
- SparseArray<String> subId2phone, JsonWriter jsonWriter,
- int maxMsgPerFile) throws IOException {
+ int putMmsMessagesToJson(Cursor cursor,
+ JsonWriter jsonWriter) throws IOException {
jsonWriter.beginArray();
int msgCount;
- for (msgCount = 0; msgCount < maxMsgPerFile && !cursor.isAfterLast(); cursor.moveToNext()) {
- msgCount +=
- writeMmsToWriter(cursor, mmsProvider, threadProvider, subId2phone, jsonWriter);
+ for (msgCount = 0; msgCount < mMaxMsgPerFile && !cursor.isAfterLast();
+ cursor.moveToNext()) {
+ msgCount += writeMmsToWriter(jsonWriter, cursor);
}
jsonWriter.endArray();
return msgCount;
}
@VisibleForTesting
- static int putSmsMessagesToJson(Cursor cursor, ContentProvider threadProvider,
- SparseArray<String> subId2phone, JsonWriter jsonWriter,
- int maxMsgPerFile) throws IOException {
+ int putSmsMessagesToJson(Cursor cursor, JsonWriter jsonWriter) throws IOException {
jsonWriter.beginArray();
int msgCount;
- for (msgCount = 0; msgCount < maxMsgPerFile && !cursor.isAfterLast();
+ for (msgCount = 0; msgCount < mMaxMsgPerFile && !cursor.isAfterLast();
++msgCount, cursor.moveToNext()) {
- writeSmsToWriter(jsonWriter, cursor, threadProvider, subId2phone);
+ writeSmsToWriter(jsonWriter, cursor);
}
jsonWriter.endArray();
return msgCount;
@@ -474,8 +453,6 @@
public static class DeferredSmsMmsRestoreService extends IntentService {
private static final String TAG = "DeferredSmsMmsRestoreService";
- private ContentProvider mSmsProvider, mMmsProvider, mMmsSmsProvider;
-
private final Comparator<File> mFileComparator = new Comparator<File>() {
@Override
public int compare(File lhs, File rhs) {
@@ -488,49 +465,60 @@
setIntentRedelivery(true);
}
+ private TelephonyBackupAgent mTelephonyBackupAgent;
+ private PowerManager.WakeLock mWakeLock;
+
@Override
protected void onHandleIntent(Intent intent) {
- File[] files = getFilesDir().listFiles(new FileFilter() {
- @Override
- public boolean accept(File file) {
- return file.getName().endsWith(SMS_BACKUP_FILE_SUFFIX) ||
- file.getName().endsWith(MMS_BACKUP_FILE_SUFFIX);
+ try {
+ mWakeLock.acquire();
+ File[] files = getFilesDir().listFiles(new FileFilter() {
+ @Override
+ public boolean accept(File file) {
+ return file.getName().endsWith(SMS_BACKUP_FILE_SUFFIX) ||
+ file.getName().endsWith(MMS_BACKUP_FILE_SUFFIX);
+ }
+ });
+
+ if (files == null) {
+ return;
}
- });
+ Arrays.sort(files, mFileComparator);
- if (files == null) {
- return;
- }
- Arrays.sort(files, mFileComparator);
-
- for (File file : files) {
- final String fileName = file.getName();
- try (FileInputStream fileInputStream = new FileInputStream(file)) {
- TelephonyBackupAgent.doRestoreFile(fileName, fileInputStream.getFD(),
- mSmsProvider, mMmsProvider, mMmsSmsProvider);
- file.delete();
- } catch (IOException e) {
- if (DEBUG) {
- Log.e(TAG, e.toString());
+ for (File file : files) {
+ final String fileName = file.getName();
+ try (FileInputStream fileInputStream = new FileInputStream(file)) {
+ mTelephonyBackupAgent.doRestoreFile(fileName, fileInputStream.getFD());
+ file.delete();
+ } catch (IOException e) {
+ if (DEBUG) {
+ Log.e(TAG, e.toString());
+ }
}
}
+ } finally {
+ mWakeLock.release();
}
}
@Override
public void onCreate() {
super.onCreate();
- mSmsProvider = new SmsProvider();
- mSmsProvider.attachInfo(this, null);
- mSmsProvider.onCreate();
+ mTelephonyBackupAgent = new TelephonyBackupAgent();
+ mTelephonyBackupAgent.attach(this);
+ mTelephonyBackupAgent.onCreate();
- mMmsProvider = new MmsProvider();
- mMmsProvider.attachInfo(this, null);
- mMmsProvider.onCreate();
+ PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+ }
- mMmsSmsProvider = new MmsSmsProvider();
- mMmsSmsProvider.attachInfo(this, null);
- mMmsSmsProvider.onCreate();
+ @Override
+ public void onDestroy() {
+ if (mTelephonyBackupAgent != null) {
+ mTelephonyBackupAgent.onDestroy();
+ mTelephonyBackupAgent = null;
+ }
+ super.onDestroy();
}
public static Intent getIntent(Context context) {
@@ -544,9 +532,7 @@
startService(DeferredSmsMmsRestoreService.getIntent(this));
}
- private static void doRestoreFile(String fileName, FileDescriptor fd,
- ContentProvider smsProvider, ContentProvider mmsProvider,
- ContentProvider mmsSmsProvider) throws IOException {
+ private void doRestoreFile(String fileName, FileDescriptor fd) throws IOException {
if (DEBUG) {
Log.i(TAG, "Restoring file " + fileName);
}
@@ -556,12 +542,12 @@
if (DEBUG) {
Log.i(TAG, "Restoring SMS");
}
- putSmsMessagesToProvider(jsonReader, smsProvider, mmsSmsProvider, sPhone2subId);
+ putSmsMessagesToProvider(jsonReader);
} else if (fileName.endsWith(MMS_BACKUP_FILE_SUFFIX)) {
if (DEBUG) {
Log.i(TAG, "Restoring text MMS");
}
- putMmsMessagesToProvider(jsonReader, mmsProvider, mmsSmsProvider, sPhone2subId);
+ putMmsMessagesToProvider(jsonReader);
} else {
if (DEBUG) {
Log.e(TAG, "Unknown file to restore:" + fileName);
@@ -571,44 +557,40 @@
}
@VisibleForTesting
- static void putSmsMessagesToProvider(JsonReader jsonReader, ContentProvider smsProvider,
- ContentProvider threadProvider,
- Map<String, Integer> phone2subId) throws IOException {
+ void putSmsMessagesToProvider(JsonReader jsonReader) throws IOException {
jsonReader.beginArray();
int msgCount = 0;
- final int bulkInsertSize = MAX_MSG_PER_FILE;
+ final int bulkInsertSize = mMaxMsgPerFile;
ContentValues[] values = new ContentValues[bulkInsertSize];
while (jsonReader.hasNext()) {
- ContentValues cv = readSmsValuesFromReader(jsonReader, threadProvider, phone2subId);
- if (doesSmsExist(smsProvider, cv)) {
+ ContentValues cv = readSmsValuesFromReader(jsonReader);
+ if (doesSmsExist(cv)) {
continue;
}
values[(msgCount++) % bulkInsertSize] = cv;
if (msgCount % bulkInsertSize == 0) {
- smsProvider.bulkInsert(Telephony.Sms.CONTENT_URI, values);
+ mContentResolver.bulkInsert(Telephony.Sms.CONTENT_URI, values);
}
}
if (msgCount % bulkInsertSize > 0) {
- smsProvider.bulkInsert(Telephony.Sms.CONTENT_URI,
+ mContentResolver.bulkInsert(Telephony.Sms.CONTENT_URI,
Arrays.copyOf(values, msgCount % bulkInsertSize));
}
jsonReader.endArray();
}
@VisibleForTesting
- static void putMmsMessagesToProvider(JsonReader jsonReader, ContentProvider mmsProvider,
- ContentProvider threadProvider,
- Map<String, Integer> phone2subId) throws IOException {
+ void putMmsMessagesToProvider(JsonReader jsonReader) throws IOException {
jsonReader.beginArray();
while (jsonReader.hasNext()) {
- final Mms mms = readMmsFromReader(jsonReader, threadProvider, phone2subId);
- if (doesMmsExist(mmsProvider, mms)) {
+ final Mms mms = readMmsFromReader(jsonReader);
+ if (doesMmsExist(mms)) {
if (DEBUG) {
Log.e(TAG, String.format("Mms: %s already exists", mms.toString()));
}
continue;
}
- addMmsMessage(mmsProvider, mms);
+ addMmsMessage(mms);
}
}
@@ -616,26 +598,26 @@
static final String[] PROJECTION_ID = {BaseColumns._ID};
private static final int ID_IDX = 0;
- private static boolean doesSmsExist(ContentProvider smsProvider, ContentValues smsValues) {
+ private boolean doesSmsExist(ContentValues smsValues) {
final String where = String.format("%s = %d and %s = %s",
Telephony.Sms.DATE, smsValues.getAsLong(Telephony.Sms.DATE),
Telephony.Sms.BODY,
DatabaseUtils.sqlEscapeString(smsValues.getAsString(Telephony.Sms.BODY)));
- try (Cursor cursor = smsProvider.query(Telephony.Sms.CONTENT_URI, PROJECTION_ID, where,
+ try (Cursor cursor = mContentResolver.query(Telephony.Sms.CONTENT_URI, PROJECTION_ID, where,
null, null)) {
return cursor != null && cursor.getCount() > 0;
}
}
- private static boolean doesMmsExist(ContentProvider mmsProvider, Mms mms) {
+ private boolean doesMmsExist(Mms mms) {
final String where = String.format("%s = %d",
Telephony.Sms.DATE, mms.values.getAsLong(Telephony.Mms.DATE));
- try (Cursor cursor = mmsProvider.query(Telephony.Mms.CONTENT_URI, PROJECTION_ID, where,
+ try (Cursor cursor = mContentResolver.query(Telephony.Mms.CONTENT_URI, PROJECTION_ID, where,
null, null)) {
if (cursor != null && cursor.moveToFirst()) {
do {
final int mmsId = cursor.getInt(ID_IDX);
- final MmsBody body = getMmsBody(mmsProvider, mmsId);
+ final MmsBody body = getMmsBody(mmsId);
if (body != null && body.equals(mms.body)) {
return true;
}
@@ -653,9 +635,7 @@
subscriptionInfo.getCountryIso().toUpperCase(Locale.US));
}
- private static void writeSmsToWriter(JsonWriter jsonWriter, Cursor cursor,
- ContentProvider threadProvider,
- SparseArray<String> subId2phone) throws IOException {
+ private void writeSmsToWriter(JsonWriter jsonWriter, Cursor cursor) throws IOException {
jsonWriter.beginObject();
for (int i=0; i<cursor.getColumnCount(); ++i) {
@@ -667,7 +647,7 @@
switch (name) {
case Telephony.Sms.SUBSCRIPTION_ID:
final int subId = cursor.getInt(i);
- final String selfNumber = subId2phone.get(subId);
+ final String selfNumber = mSubId2phone.get(subId);
if (selfNumber != null) {
jsonWriter.name(SELF_PHONE_KEY).value(selfNumber);
}
@@ -675,7 +655,7 @@
case Telephony.Sms.THREAD_ID:
final long threadId = cursor.getLong(i);
writeRecipientsToWriter(jsonWriter.name(RECIPIENTS),
- getRecipientsByThread(threadProvider, threadId));
+ getRecipientsByThread(threadId));
break;
case Telephony.Sms._ID:
break;
@@ -699,10 +679,7 @@
jsonWriter.endArray();
}
- @VisibleForTesting
- static ContentValues readSmsValuesFromReader(JsonReader jsonReader,
- ContentProvider threadProvider,
- Map<String, Integer> phone2id)
+ private ContentValues readSmsValuesFromReader(JsonReader jsonReader)
throws IOException {
ContentValues values = new ContentValues(8+sDefaultValuesSms.size());
values.putAll(sDefaultValuesSms);
@@ -721,12 +698,12 @@
break;
case RECIPIENTS:
values.put(Telephony.Sms.THREAD_ID,
- getOrCreateThreadId(threadProvider, getRecipients(jsonReader)));
+ getOrCreateThreadId(getRecipients(jsonReader)));
break;
case SELF_PHONE_KEY:
final String selfPhone = jsonReader.nextString();
- if (phone2id.containsKey(selfPhone)) {
- values.put(Telephony.Sms.SUBSCRIPTION_ID, phone2id.get(selfPhone));
+ if (mPhone2subId.containsKey(selfPhone)) {
+ values.put(Telephony.Sms.SUBSCRIPTION_ID, mPhone2subId.get(selfPhone));
}
break;
default:
@@ -751,12 +728,9 @@
return recipients;
}
- private static int writeMmsToWriter(Cursor cursor, ContentProvider mmsProvider,
- ContentProvider threadProvider,
- SparseArray<String> subId2phone,
- JsonWriter jsonWriter) throws IOException {
+ private int writeMmsToWriter(JsonWriter jsonWriter, Cursor cursor) throws IOException {
final int mmsId = cursor.getInt(ID_IDX);
- final MmsBody body = getMmsBody(mmsProvider, mmsId);
+ final MmsBody body = getMmsBody(mmsId);
if (body == null || body.text == null) {
return 0;
}
@@ -772,7 +746,7 @@
switch (name) {
case Telephony.Mms.SUBSCRIPTION_ID:
final int subId = cursor.getInt(i);
- final String selfNumber = subId2phone.get(subId);
+ final String selfNumber = mSubId2phone.get(subId);
if (selfNumber != null) {
jsonWriter.name(SELF_PHONE_KEY).value(selfNumber);
}
@@ -780,7 +754,7 @@
case Telephony.Mms.THREAD_ID:
final long threadId = cursor.getLong(i);
writeRecipientsToWriter(jsonWriter.name(RECIPIENTS),
- getRecipientsByThread(threadProvider, threadId));
+ getRecipientsByThread(threadId));
break;
case Telephony.Mms._ID:
case Telephony.Mms.SUBJECT_CHARSET:
@@ -793,7 +767,7 @@
}
}
// Addresses.
- writeMmsAddresses(jsonWriter.name(MMS_ADDRESSES_KEY), mmsProvider, mmsId);
+ writeMmsAddresses(jsonWriter.name(MMS_ADDRESSES_KEY), mmsId);
// Body (text of the message).
jsonWriter.name(MMS_BODY_KEY).value(body.text);
// Charset of the body text.
@@ -807,8 +781,7 @@
return 1;
}
- private static Mms readMmsFromReader(JsonReader jsonReader, ContentProvider threadProvider,
- Map<String, Integer> phone2id) throws IOException {
+ private Mms readMmsFromReader(JsonReader jsonReader) throws IOException {
Mms mms = new Mms();
mms.values = new ContentValues(6+sDefaultValuesMms.size());
mms.values.putAll(sDefaultValuesMms);
@@ -820,8 +793,8 @@
switch (name) {
case SELF_PHONE_KEY:
final String selfPhone = jsonReader.nextString();
- if (phone2id.containsKey(selfPhone)) {
- mms.values.put(Telephony.Mms.SUBSCRIPTION_ID, phone2id.get(selfPhone));
+ if (mPhone2subId.containsKey(selfPhone)) {
+ mms.values.put(Telephony.Mms.SUBSCRIPTION_ID, mPhone2subId.get(selfPhone));
}
break;
case MMS_ADDRESSES_KEY:
@@ -835,7 +808,7 @@
break;
case RECIPIENTS:
mms.values.put(Telephony.Sms.THREAD_ID,
- getOrCreateThreadId(threadProvider, getRecipients(jsonReader)));
+ getOrCreateThreadId(getRecipients(jsonReader)));
break;
case Telephony.Mms.SUBJECT:
case Telephony.Mms.SUBJECT_CHARSET:
@@ -870,14 +843,14 @@
return mms;
}
- private static MmsBody getMmsBody(ContentProvider mmsProvider, int mmsId) {
+ private MmsBody getMmsBody(int mmsId) {
Uri MMS_PART_CONTENT_URI = Telephony.Mms.CONTENT_URI.buildUpon()
.appendPath(String.valueOf(mmsId)).appendPath("part").build();
String body = null;
int charSet = 0;
- try (Cursor cursor = mmsProvider.query(MMS_PART_CONTENT_URI, MMS_TEXT_PROJECTION,
+ try (Cursor cursor = mContentResolver.query(MMS_PART_CONTENT_URI, MMS_TEXT_PROJECTION,
Telephony.Mms.Part.CONTENT_TYPE + "=?", new String[]{ContentType.TEXT_PLAIN},
ORDER_BY_ID)) {
if (cursor != null && cursor.moveToFirst()) {
@@ -891,14 +864,13 @@
return (body == null ? null : new MmsBody(body, charSet));
}
- private static void writeMmsAddresses(JsonWriter jsonWriter, ContentProvider mmsProvider,
- int mmsId) throws IOException {
+ private void writeMmsAddresses(JsonWriter jsonWriter, int mmsId) throws IOException {
Uri.Builder builder = Telephony.Mms.CONTENT_URI.buildUpon();
builder.appendPath(String.valueOf(mmsId)).appendPath("addr");
Uri uriAddrPart = builder.build();
jsonWriter.beginArray();
- try (Cursor cursor = mmsProvider.query(uriAddrPart, MMS_ADDR_PROJECTION,
+ try (Cursor cursor = mContentResolver.query(uriAddrPart, MMS_ADDR_PROJECTION,
null/*selection*/, null/*selectionArgs*/, ORDER_BY_ID)) {
if (cursor != null && cursor.moveToFirst()) {
do {
@@ -949,7 +921,7 @@
jsonReader.endArray();
}
- private static void addMmsMessage(ContentProvider mmsProvider, Mms mms) {
+ private void addMmsMessage(Mms mms) {
if (DEBUG) {
Log.e(TAG, "Add mms:\n" + mms.toString());
}
@@ -969,7 +941,7 @@
values.put(Telephony.Mms.Part.CONTENT_ID, "<smil>");
values.put(Telephony.Mms.Part.CONTENT_LOCATION, "smil.xml");
values.put(Telephony.Mms.Part.TEXT, smil);
- if (mmsProvider.insert(partUri, values) == null) {
+ if (mContentResolver.insert(partUri, values) == null) {
if (DEBUG) {
Log.e(TAG, "Could not insert SMIL part");
}
@@ -987,7 +959,7 @@
values.put(Telephony.Mms.Part.CONTENT_LOCATION, srcName);
values.put(Telephony.Mms.Part.CHARSET, mms.body.charSet);
values.put(Telephony.Mms.Part.TEXT, mms.body.text);
- if (mmsProvider.insert(partUri, values) == null) {
+ if (mContentResolver.insert(partUri, values) == null) {
if (DEBUG) {
Log.e(TAG, "Could not insert body part");
}
@@ -996,7 +968,7 @@
}
// Insert mms.
- final Uri mmsUri = mmsProvider.insert(Telephony.Mms.CONTENT_URI, mms.values);
+ final Uri mmsUri = mContentResolver.insert(Telephony.Mms.CONTENT_URI, mms.values);
if (mmsUri == null) {
if (DEBUG) {
Log.e(TAG, "Could not insert mms");
@@ -1008,7 +980,7 @@
{ // Update parts with the right mms id.
ContentValues values = new ContentValues(1);
values.put(Telephony.Mms.Part.MSG_ID, mmsId);
- mmsProvider.update(partUri, values, null, null);
+ mContentResolver.update(partUri, values, null, null);
}
{ // Insert adderesses into "addr".
@@ -1016,7 +988,7 @@
for (ContentValues mmsAddress : mms.addresses) {
ContentValues values = new ContentValues(mmsAddress);
values.put(Telephony.Mms.Addr.MSG_ID, mmsId);
- mmsProvider.insert(addrUri, values);
+ mContentResolver.insert(addrUri, values);
}
}
}
@@ -1083,70 +1055,38 @@
}
}
+ private long getOrCreateThreadId(Set<String> recipients) {
+ if (mCacheGetOrCreateThreadId == null) {
+ mCacheGetOrCreateThreadId = new HashMap<>();
+ }
+
+ if (!mCacheGetOrCreateThreadId.containsKey(recipients)) {
+ mCacheGetOrCreateThreadId.put(recipients,
+ Telephony.Threads.getOrCreateThreadId(this, recipients));
+ }
+
+ return mCacheGetOrCreateThreadId.get(recipients);
+ }
+
@VisibleForTesting
static final Uri THREAD_ID_CONTENT_URI = Uri.parse("content://mms-sms/threadID");
- // Copied from frameworks/opt/telephony/src/java/android/provider/Telephony.java because we
- // can't use ContentResolver during backup/restore.
- private static long getOrCreateThreadId(
- ContentProvider contentProvider, Set<String> recipients) {
- if (sCacheGetOrCreateThreadId == null) {
- sCacheGetOrCreateThreadId = new HashMap<>();
- }
-
- if (sCacheGetOrCreateThreadId.containsKey(recipients)) {
- return sCacheGetOrCreateThreadId.get(recipients);
- }
-
- Uri.Builder uriBuilder = THREAD_ID_CONTENT_URI.buildUpon();
-
- for (String recipient : recipients) {
- if (Telephony.Mms.isEmailAddress(recipient)) {
- recipient = Telephony.Mms.extractAddrSpec(recipient);
- }
-
- uriBuilder.appendQueryParameter("recipient", recipient);
- }
-
- Uri uri = uriBuilder.build();
-
- try (Cursor cursor = contentProvider.query(uri, PROJECTION_ID, null, null, null)) {
- if (cursor != null) {
- if (cursor.moveToFirst()) {
- final long threadId = cursor.getLong(ID_IDX);
- sCacheGetOrCreateThreadId.put(recipients, threadId);
- return threadId;
- } else {
- if (DEBUG) {
- Log.e(TAG, "getOrCreateThreadId returned no rows!");
- }
- }
- }
- }
-
- if (DEBUG) {
- Log.e(TAG, "getOrCreateThreadId failed with " + recipients.size() + " recipients");
- }
- throw new IllegalArgumentException("Unable to find or allocate a thread ID.");
- }
-
// Mostly copied from packages/apps/Messaging/src/com/android/messaging/sms/MmsUtils.java.
- private static List<String> getRecipientsByThread(final ContentProvider threadProvider,
- final long threadId) {
- if (sCacheRecipientsByThread == null) {
- sCacheRecipientsByThread = new HashMap<>();
+ private List<String> getRecipientsByThread(final long threadId) {
+ if (mCacheRecipientsByThread == null) {
+ mCacheRecipientsByThread = new HashMap<>();
}
- if (!sCacheRecipientsByThread.containsKey(threadId)) {
- final String spaceSepIds = getRawRecipientIdsForThread(threadProvider, threadId);
+ if (!mCacheRecipientsByThread.containsKey(threadId)) {
+ final String spaceSepIds = getRawRecipientIdsForThread(threadId);
if (!TextUtils.isEmpty(spaceSepIds)) {
- sCacheRecipientsByThread.put(threadId, getAddresses(threadProvider, spaceSepIds));
+ mCacheRecipientsByThread.put(threadId, getAddresses(spaceSepIds));
} else {
- sCacheRecipientsByThread.put(threadId, new ArrayList<String>());
+ mCacheRecipientsByThread.put(threadId, new ArrayList<String>());
}
}
- return sCacheRecipientsByThread.get(threadId);
+ return mCacheRecipientsByThread.get(threadId);
}
@VisibleForTesting
@@ -1158,12 +1098,11 @@
// Copied from packages/apps/Messaging/src/com/android/messaging/sms/MmsUtils.java.
// NOTE: There are phones on which you can't get the recipients from the thread id for SMS
// until you have a message in the conversation!
- private static String getRawRecipientIdsForThread(final ContentProvider threadProvider,
- final long threadId) {
+ private String getRawRecipientIdsForThread(final long threadId) {
if (threadId <= 0) {
return null;
}
- final Cursor thread = threadProvider.query(
+ final Cursor thread = mContentResolver.query(
ALL_THREADS_URI,
SMS_RECIPIENTS_PROJECTION, "_id=?", new String[]{String.valueOf(threadId)}, null);
if (thread != null) {
@@ -1185,8 +1124,7 @@
Uri.parse("content://mms-sms/canonical-address");
// Copied from packages/apps/Messaging/src/com/android/messaging/sms/MmsUtils.java.
- private static List<String> getAddresses(final ContentProvider threadProvider,
- final String spaceSepIds) {
+ private List<String> getAddresses(final String spaceSepIds) {
final List<String> numbers = new ArrayList<String>();
final String[] ids = spaceSepIds.split(" ");
for (final String id : ids) {
@@ -1211,7 +1149,7 @@
// TODO: build a single query where we get all the addresses at once.
Cursor c = null;
try {
- c = threadProvider.query(
+ c = mContentResolver.query(
ContentUris.withAppendedId(SINGLE_CANONICAL_ADDRESS_URI, longId),
null, null, null, null);
} catch (final Exception e) {
diff --git a/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java b/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java
index 288b36b..8bf45c9 100644
--- a/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java
@@ -18,8 +18,11 @@
import android.annotation.TargetApi;
import android.app.backup.FullBackupDataOutput;
+import android.content.ContentProvider;
+import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
+import android.content.ContextWrapper;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
@@ -27,13 +30,19 @@
import android.provider.Telephony;
import android.test.AndroidTestCase;
import android.test.mock.MockContentProvider;
+import android.test.mock.MockContentResolver;
import android.test.mock.MockCursor;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.JsonReader;
import android.util.JsonWriter;
+import android.util.Log;
import android.util.SparseArray;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
@@ -42,6 +51,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
/**
@@ -72,15 +82,15 @@
private StringWriter mStringWriter;
+ /* Content resolver passed to the backupAgent */
+ private MockContentResolver mMockContentResolver = new MockContentResolver();
+
/* Map uri -> cursors. Being used for contentprovider. */
private Map<Uri, FakeCursor> mCursors;
- /* Content provider passed to the backupAgent */
- private MockContentProvider mContentProvider;
/* Content provider with threadIds.*/
private ThreadProvider mThreadProvider = new ThreadProvider();
private static final String EMPTY_JSON_ARRAY = "[]";
- private int mStoredMaxMsgPerFile;
TelephonyBackupAgent mTelephonyBackupAgent;
@@ -88,9 +98,6 @@
protected void setUp() throws Exception {
super.setUp();
- mTelephonyBackupAgent = new TelephonyBackupAgent();
- mTelephonyBackupAgent.attach(getContext());
-
/* Filling up subscription maps */
mStringWriter = new StringWriter();
mSubId2Phone = new SparseArray<String>();
@@ -199,7 +206,7 @@
"\"sub_cs\":\"10\"}";
mAllMmsJson = makeJsonArray(mMmsJson);
- mContentProvider = new MockContentProvider() {
+ ContentProvider contentProvider = new MockContentProvider() {
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
@@ -211,19 +218,31 @@
fakeCursor.nextRow = 0;
return fakeCursor;
}
- return super.query(uri, projection, selection, selectionArgs, sortOrder);
+ fail("No cursor for " + uri.toString());
+ return null;
}
};
- mStoredMaxMsgPerFile = TelephonyBackupAgent.MAX_MSG_PER_FILE;
- TelephonyBackupAgent.sCacheGetOrCreateThreadId = null;
- TelephonyBackupAgent.sCacheRecipientsByThread = null;
+ mMockContentResolver.addProvider("sms", contentProvider);
+ mMockContentResolver.addProvider("mms", contentProvider);
+ mMockContentResolver.addProvider("mms-sms", mThreadProvider);
+
+ mTelephonyBackupAgent = new TelephonyBackupAgent();
+ mTelephonyBackupAgent.attach(new ContextWrapper(getContext()) {
+ @Override
+ public ContentResolver getContentResolver() {
+ return mMockContentResolver;
+ }
+ });
+
+
mTelephonyBackupAgent.clearSharedPreferences();
+ mTelephonyBackupAgent.setContentResolver(mMockContentResolver);
+ mTelephonyBackupAgent.setSubId(mSubId2Phone, mPhone2SubId);
}
@Override
protected void tearDown() throws Exception {
- TelephonyBackupAgent.MAX_MSG_PER_FILE = mStoredMaxMsgPerFile;
mTelephonyBackupAgent.clearSharedPreferences();
super.tearDown();
}
@@ -351,8 +370,7 @@
* @throws Exception
*/
public void testBackupSms_NoSms() throws Exception {
- TelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, new ThreadProvider(), mSubId2Phone,
- new JsonWriter(mStringWriter), 1);
+ mTelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, new JsonWriter(mStringWriter));
assertEquals(EMPTY_JSON_ARRAY, mStringWriter.toString());
}
@@ -361,9 +379,9 @@
* @throws Exception
*/
public void testBackupSms_AllSms() throws Exception {
+ mTelephonyBackupAgent.mMaxMsgPerFile = 4;
mSmsTable.addAll(Arrays.asList(mSmsRows));
- TelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, mThreadProvider, mSubId2Phone,
- new JsonWriter(mStringWriter), 4);
+ mTelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, new JsonWriter(mStringWriter));
assertEquals(mAllSmsJson, mStringWriter.toString());
}
@@ -372,9 +390,9 @@
* @throws Exception
*/
public void testBackupSms_AllSmsWithExactFileLimit() throws Exception {
+ mTelephonyBackupAgent.mMaxMsgPerFile = 3;
mSmsTable.addAll(Arrays.asList(mSmsRows));
- TelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, mThreadProvider, mSubId2Phone,
- new JsonWriter(mStringWriter), 3);
+ mTelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, new JsonWriter(mStringWriter));
assertEquals(mAllSmsJson, mStringWriter.toString());
}
@@ -383,20 +401,18 @@
* @throws Exception
*/
public void testBackupSms_AllSmsOneMessagePerFile() throws Exception {
+ mTelephonyBackupAgent.mMaxMsgPerFile = 1;
mSmsTable.addAll(Arrays.asList(mSmsRows));
- TelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, mThreadProvider, mSubId2Phone,
- new JsonWriter(mStringWriter), 1);
+ mTelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, new JsonWriter(mStringWriter));
assertEquals("[" + mSmsJson[0] + "]", mStringWriter.toString());
mStringWriter = new StringWriter();
- TelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, mThreadProvider, mSubId2Phone,
- new JsonWriter(mStringWriter), 1);
+ mTelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, new JsonWriter(mStringWriter));
assertEquals("[" + mSmsJson[1] + "]", mStringWriter.toString());
mStringWriter = new StringWriter();
- TelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, mThreadProvider, mSubId2Phone,
- new JsonWriter(mStringWriter), 1);
+ mTelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, new JsonWriter(mStringWriter));
assertEquals("[" + mSmsJson[2] + "]", mStringWriter.toString());
}
@@ -405,8 +421,7 @@
* @throws Exception
*/
public void testBackupMms_NoMms() throws Exception {
- TelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, mContentProvider,
- mThreadProvider, mSubId2Phone, new JsonWriter(mStringWriter), 4);
+ mTelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, new JsonWriter(mStringWriter));
assertEquals(EMPTY_JSON_ARRAY, mStringWriter.toString());
}
@@ -415,9 +430,9 @@
* @throws Exception
*/
public void testBackupMms_AllMms() throws Exception {
+ mTelephonyBackupAgent.mMaxMsgPerFile = 4;
mMmsTable.addAll(Arrays.asList(mMmsRows));
- TelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, mContentProvider,
- mThreadProvider, mSubId2Phone, new JsonWriter(mStringWriter), 4);
+ mTelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, new JsonWriter(mStringWriter));
assertEquals(mAllMmsJson, mStringWriter.toString());
}
@@ -426,19 +441,17 @@
* @throws Exception
*/
public void testBackupMms_OneMessagePerFile() throws Exception {
+ mTelephonyBackupAgent.mMaxMsgPerFile = 1;
mMmsTable.addAll(Arrays.asList(mMmsRows));
- TelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, mContentProvider,
- mThreadProvider, mSubId2Phone, new JsonWriter(mStringWriter), 1);
+ mTelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, new JsonWriter(mStringWriter));
assertEquals("[" + mMmsJson[0] + "]", mStringWriter.toString());
mStringWriter = new StringWriter();
- TelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, mContentProvider,
- mThreadProvider, mSubId2Phone, new JsonWriter(mStringWriter), 1);
+ mTelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, new JsonWriter(mStringWriter));
assertEquals("[" + mMmsJson[1] + "]", mStringWriter.toString());
mStringWriter = new StringWriter();
- TelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, mContentProvider,
- mThreadProvider, mSubId2Phone, new JsonWriter(mStringWriter), 1);
+ mTelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, new JsonWriter(mStringWriter));
assertEquals("[" + mMmsJson[2] + "]", mStringWriter.toString());
}
@@ -448,8 +461,8 @@
*/
public void testBackupMms_WithExactFileLimit() throws Exception {
mMmsTable.addAll(Arrays.asList(mMmsRows));
- TelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, mContentProvider,
- mThreadProvider, mSubId2Phone, new JsonWriter(mStringWriter), 3);
+ mTelephonyBackupAgent.mMaxMsgPerFile = 3;
+ mTelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, new JsonWriter(mStringWriter));
assertEquals(mAllMmsJson, mStringWriter.toString());
}
@@ -460,8 +473,8 @@
public void testRestoreSms_NoSms() throws Exception {
JsonReader jsonReader = new JsonReader(new StringReader(EMPTY_JSON_ARRAY));
FakeSmsProvider smsProvider = new FakeSmsProvider(null);
- TelephonyBackupAgent.putSmsMessagesToProvider(jsonReader, smsProvider,
- new ThreadProvider(), mPhone2SubId);
+ mMockContentResolver.addProvider("sms", smsProvider);
+ mTelephonyBackupAgent.putSmsMessagesToProvider(jsonReader);
assertEquals(0, smsProvider.getRowsAdded());
}
@@ -470,10 +483,10 @@
* @throws Exception
*/
public void testRestoreSms_AllSms() throws Exception {
- JsonReader jsonReader = new JsonReader(new StringReader(mAllSmsJson));
+ JsonReader jsonReader = new JsonReader(new StringReader(addRandomDataToJson(mAllSmsJson)));
FakeSmsProvider smsProvider = new FakeSmsProvider(mSmsRows);
- TelephonyBackupAgent.putSmsMessagesToProvider(jsonReader, smsProvider,
- new ThreadProvider(), mPhone2SubId);
+ mMockContentResolver.addProvider("sms", smsProvider);
+ mTelephonyBackupAgent.putSmsMessagesToProvider(jsonReader);
assertEquals(mSmsRows.length, smsProvider.getRowsAdded());
}
@@ -484,26 +497,37 @@
public void testRestoreMms_NoMms() throws Exception {
JsonReader jsonReader = new JsonReader(new StringReader(EMPTY_JSON_ARRAY));
FakeMmsProvider mmsProvider = new FakeMmsProvider(null);
- TelephonyBackupAgent.putMmsMessagesToProvider(jsonReader, mmsProvider,
- new ThreadProvider(), mPhone2SubId);
+ mMockContentResolver.addProvider("mms", mmsProvider);
+ mTelephonyBackupAgent.putMmsMessagesToProvider(jsonReader);
assertEquals(0, mmsProvider.getRowsAdded());
}
/**
+ * Test restore sms with three mms json object in the array.
+ * @throws Exception
+ */
+ public void testRestoreMms_AllMms() throws Exception {
+ JsonReader jsonReader = new JsonReader(new StringReader(addRandomDataToJson(mAllMmsJson)));
+ FakeMmsProvider mmsProvider = new FakeMmsProvider(mMmsAllContentValues);
+ mMockContentResolver.addProvider("mms", mmsProvider);
+ mTelephonyBackupAgent.putMmsMessagesToProvider(jsonReader);
+ assertEquals(18, mmsProvider.getRowsAdded());
+ }
+
+ /**
* Test with quota exceeded. Checking size of the backup before it hits quota and after.
* It still backs up more than a quota since there is meta-info which matters with small amounts
* of data. The agent does not take backup meta-info into consideration.
* @throws Exception
*/
public void testBackup_WithQuotaExceeded() throws Exception {
- TelephonyBackupAgent.MAX_MSG_PER_FILE = 1;
+ mTelephonyBackupAgent.mMaxMsgPerFile = 1;
final int backupSize = 6144;
final int backupSizeAfterFirstQuotaHit = 5120;
final int backupSizeAfterSecondQuotaHit = 4096;
mSmsTable.addAll(Arrays.asList(mSmsRows));
mMmsTable.addAll(Arrays.asList(mMmsRows));
- mTelephonyBackupAgent.setProviders(mContentProvider, mContentProvider, mThreadProvider);
FullBackupDataOutput fullBackupDataOutput = new FullBackupDataOutput();
mTelephonyBackupAgent.onFullBackup(fullBackupDataOutput);
@@ -521,16 +545,16 @@
assertEquals(backupSizeAfterSecondQuotaHit, fullBackupDataOutput.getSize());
}
- /**
- * Test restore sms with three mms json object in the array.
- * @throws Exception
- */
- public void testRestoreMms_AllMms() throws Exception {
- JsonReader jsonReader = new JsonReader(new StringReader(mAllMmsJson));
- FakeMmsProvider mmsProvider = new FakeMmsProvider(mMmsAllContentValues);
- TelephonyBackupAgent.putMmsMessagesToProvider(jsonReader, mmsProvider,
- mThreadProvider, mPhone2SubId);
- assertEquals(18, mmsProvider.getRowsAdded());
+ // Adding random keys to JSON to test handling it by the BackupAgent on restore.
+ private String addRandomDataToJson(String jsonString) throws JSONException {
+ JSONArray jsonArray = new JSONArray(jsonString);
+ JSONArray res = new JSONArray();
+ for (int i = 0; i < jsonArray.length(); ++i) {
+ JSONObject jsonObject = jsonArray.getJSONObject(i);
+ jsonObject.put(UUID.randomUUID().toString(), UUID.randomUUID().toString());
+ res = res.put(jsonObject);
+ }
+ return res.toString();
}
/**