MmsProviderpublic class MmsProvider extends android.content.ContentProvider The class to provide base facility to access MMS related content,
which is stored in a SQLite database and in the file system. |
Fields Summary |
---|
static final String | TABLE_PDU | static final String | TABLE_ADDR | static final String | TABLE_PART | static final String | TABLE_RATE | static final String | TABLE_DRM | private static final String | TAG | private static final String | VND_ANDROID_MMS | private static final String | VND_ANDROID_DIR_MMS | private static final boolean | DEBUG | private static final boolean | LOCAL_LOGV | private static final int | MMS_ALL | private static final int | MMS_ALL_ID | private static final int | MMS_INBOX | private static final int | MMS_INBOX_ID | private static final int | MMS_SENT | private static final int | MMS_SENT_ID | private static final int | MMS_DRAFTS | private static final int | MMS_DRAFTS_ID | private static final int | MMS_OUTBOX | private static final int | MMS_OUTBOX_ID | private static final int | MMS_ALL_PART | private static final int | MMS_MSG_PART | private static final int | MMS_PART_ID | private static final int | MMS_MSG_ADDR | private static final int | MMS_SENDING_RATE | private static final int | MMS_REPORT_STATUS | private static final int | MMS_REPORT_REQUEST | private static final int | MMS_DRM_STORAGE | private static final int | MMS_DRM_STORAGE_ID | private static final android.content.UriMatcher | sURLMatcher | private android.database.sqlite.SQLiteOpenHelper | mOpenHelper |
Methods Summary |
---|
private static java.lang.String | concatSelections(java.lang.String selection1, java.lang.String selection2)
if (TextUtils.isEmpty(selection1)) {
return selection2;
} else if (TextUtils.isEmpty(selection2)) {
return selection1;
} else {
return selection1 + " AND " + selection2;
}
| private void | constructQueryForBox(android.database.sqlite.SQLiteQueryBuilder qb, int msgBox)
qb.setTables(TABLE_PDU);
if (msgBox != Mms.MESSAGE_BOX_ALL) {
qb.appendWhere(Mms.MESSAGE_BOX + "=" + msgBox);
}
| public int | delete(android.net.Uri uri, java.lang.String selection, java.lang.String[] selectionArgs)
int match = sURLMatcher.match(uri);
if (LOCAL_LOGV) {
Log.v(TAG, "Delete uri=" + uri + ", match=" + match);
}
String table, extraSelection = null;
boolean notify = false;
switch (match) {
case MMS_ALL_ID:
case MMS_INBOX_ID:
case MMS_SENT_ID:
case MMS_DRAFTS_ID:
case MMS_OUTBOX_ID:
notify = true;
table = TABLE_PDU;
extraSelection = Mms._ID + "=" + uri.getLastPathSegment();
break;
case MMS_ALL:
case MMS_INBOX:
case MMS_SENT:
case MMS_DRAFTS:
case MMS_OUTBOX:
notify = true;
table = TABLE_PDU;
if (match != MMS_ALL) {
int msgBox = getMessageBoxByMatch(match);
extraSelection = Mms.MESSAGE_BOX + "=" + msgBox;
}
break;
case MMS_ALL_PART:
table = TABLE_PART;
break;
case MMS_MSG_PART:
table = TABLE_PART;
extraSelection = Part.MSG_ID + "=" + uri.getPathSegments().get(0);
break;
case MMS_PART_ID:
table = TABLE_PART;
extraSelection = Part._ID + "=" + uri.getPathSegments().get(1);
break;
case MMS_MSG_ADDR:
table = TABLE_ADDR;
extraSelection = Addr.MSG_ID + "=" + uri.getPathSegments().get(0);
break;
case MMS_DRM_STORAGE:
table = TABLE_DRM;
break;
default:
Log.w(TAG, "No match for URI '" + uri + "'");
return 0;
}
String finalSelection = concatSelections(selection, extraSelection);
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int deletedRows = 0;
if (TABLE_PDU.equals(table)) {
deletedRows = deleteMessages(getContext(), db, finalSelection,
selectionArgs, uri);
} else if (TABLE_PART.equals(table)) {
deletedRows = deleteParts(db, finalSelection, selectionArgs);
} else if (TABLE_DRM.equals(table)) {
deletedRows = deleteTempDrmData(db, finalSelection, selectionArgs);
} else {
deletedRows = db.delete(table, finalSelection, selectionArgs);
}
if ((deletedRows > 0) && notify) {
notifyChange();
}
return deletedRows;
| private static int | deleteDataRows(android.database.sqlite.SQLiteDatabase db, java.lang.String table, java.lang.String selection, java.lang.String[] selectionArgs)
Cursor cursor = db.query(table, new String[] { "_data" },
selection, selectionArgs, null, null, null);
if (cursor == null) {
// FIXME: This might be an error, ignore it may cause
// unpredictable result.
return 0;
}
try {
if (cursor.getCount() == 0) {
return 0;
}
while (cursor.moveToNext()) {
try {
// Delete the associated files saved on file-system.
new File(cursor.getString(0)).delete();
} catch (Throwable ex) {
Log.e(TAG, ex.getMessage(), ex);
}
}
} finally {
cursor.close();
}
return db.delete(table, selection, selectionArgs);
| static int | deleteMessages(android.content.Context context, android.database.sqlite.SQLiteDatabase db, java.lang.String selection, java.lang.String[] selectionArgs, android.net.Uri uri)
Cursor cursor = db.query(TABLE_PDU, new String[] { Mms._ID },
selection, selectionArgs, null, null, null);
if (cursor == null) {
return 0;
}
try {
if (cursor.getCount() == 0) {
return 0;
}
while (cursor.moveToNext()) {
deleteParts(db, Part.MSG_ID + " = ?",
new String[] { String.valueOf(cursor.getLong(0)) });
}
} finally {
cursor.close();
}
int count = db.delete(TABLE_PDU, selection, selectionArgs);
if (count > 0) {
Intent intent = new Intent(Mms.Intents.CONTENT_CHANGED_ACTION);
intent.putExtra(Mms.Intents.DELETED_CONTENTS, uri);
if (LOCAL_LOGV) {
Log.v(TAG, "Broadcasting intent: " + intent);
}
context.sendBroadcast(intent);
}
return count;
| private static int | deleteParts(android.database.sqlite.SQLiteDatabase db, java.lang.String selection, java.lang.String[] selectionArgs)
return deleteDataRows(db, TABLE_PART, selection, selectionArgs);
| private static int | deleteTempDrmData(android.database.sqlite.SQLiteDatabase db, java.lang.String selection, java.lang.String[] selectionArgs)
return deleteDataRows(db, TABLE_DRM, selection, selectionArgs);
| private void | filterUnsupportedKeys(android.content.ContentValues values)
// Some columns are unsupported. They should therefore
// neither be inserted nor updated. Filter them out.
values.remove(Mms.DELIVERY_TIME_TOKEN);
values.remove(Mms.SENDER_VISIBILITY);
values.remove(Mms.REPLY_CHARGING);
values.remove(Mms.REPLY_CHARGING_DEADLINE_TOKEN);
values.remove(Mms.REPLY_CHARGING_DEADLINE);
values.remove(Mms.REPLY_CHARGING_ID);
values.remove(Mms.REPLY_CHARGING_SIZE);
values.remove(Mms.PREVIOUSLY_SENT_BY);
values.remove(Mms.PREVIOUSLY_SENT_DATE);
values.remove(Mms.STORE);
values.remove(Mms.MM_STATE);
values.remove(Mms.MM_FLAGS_TOKEN);
values.remove(Mms.MM_FLAGS);
values.remove(Mms.STORE_STATUS);
values.remove(Mms.STORE_STATUS_TEXT);
values.remove(Mms.STORED);
values.remove(Mms.TOTALS);
values.remove(Mms.MBOX_TOTALS);
values.remove(Mms.MBOX_TOTALS_TOKEN);
values.remove(Mms.QUOTAS);
values.remove(Mms.MBOX_QUOTAS);
values.remove(Mms.MBOX_QUOTAS_TOKEN);
values.remove(Mms.MESSAGE_COUNT);
values.remove(Mms.START);
values.remove(Mms.DISTRIBUTION_INDICATOR);
values.remove(Mms.ELEMENT_DESCRIPTOR);
values.remove(Mms.LIMIT);
values.remove(Mms.RECOMMENDED_RETRIEVAL_MODE);
values.remove(Mms.RECOMMENDED_RETRIEVAL_MODE_TEXT);
values.remove(Mms.STATUS_TEXT);
values.remove(Mms.APPLIC_ID);
values.remove(Mms.REPLY_APPLIC_ID);
values.remove(Mms.AUX_APPLIC_ID);
values.remove(Mms.DRM_CONTENT);
values.remove(Mms.ADAPTATION_ALLOWED);
values.remove(Mms.REPLACE_ID);
values.remove(Mms.CANCEL_ID);
values.remove(Mms.CANCEL_STATUS);
// Keys shouldn't be inserted or updated.
values.remove(Mms._ID);
| private int | getMessageBoxByMatch(int match)
switch (match) {
case MMS_INBOX_ID:
case MMS_INBOX:
return Mms.MESSAGE_BOX_INBOX;
case MMS_SENT_ID:
case MMS_SENT:
return Mms.MESSAGE_BOX_SENT;
case MMS_DRAFTS_ID:
case MMS_DRAFTS:
return Mms.MESSAGE_BOX_DRAFTS;
case MMS_OUTBOX_ID:
case MMS_OUTBOX:
return Mms.MESSAGE_BOX_OUTBOX;
default:
throw new IllegalArgumentException("bad Arg: " + match);
}
| public java.lang.String | getType(android.net.Uri uri)
int match = sURLMatcher.match(uri);
switch (match) {
case MMS_ALL:
case MMS_INBOX:
case MMS_SENT:
case MMS_DRAFTS:
case MMS_OUTBOX:
return VND_ANDROID_DIR_MMS;
case MMS_ALL_ID:
case MMS_INBOX_ID:
case MMS_SENT_ID:
case MMS_DRAFTS_ID:
case MMS_OUTBOX_ID:
return VND_ANDROID_MMS;
case MMS_PART_ID: {
Cursor cursor = mOpenHelper.getReadableDatabase().query(
TABLE_PART, new String[] { Part.CONTENT_TYPE },
Part._ID + " = ?", new String[] { uri.getLastPathSegment() },
null, null, null);
if (cursor != null) {
try {
if ((cursor.getCount() == 1) && cursor.moveToFirst()) {
return cursor.getString(0);
} else {
Log.e(TAG, "cursor.count() != 1: " + uri);
}
} finally {
cursor.close();
}
} else {
Log.e(TAG, "cursor == null: " + uri);
}
return "*/*";
}
case MMS_ALL_PART:
case MMS_MSG_PART:
case MMS_MSG_ADDR:
default:
return "*/*";
}
| public android.net.Uri | insert(android.net.Uri uri, android.content.ContentValues values)
int msgBox = Mms.MESSAGE_BOX_ALL;
boolean notify = true;
int match = sURLMatcher.match(uri);
if (LOCAL_LOGV) {
Log.v(TAG, "Insert uri=" + uri + ", match=" + match);
}
String table = TABLE_PDU;
switch (match) {
case MMS_ALL:
Object msgBoxObj = values.getAsInteger(Mms.MESSAGE_BOX);
if (msgBoxObj != null) {
msgBox = (Integer) msgBoxObj;
}
else {
// default to inbox
msgBox = Mms.MESSAGE_BOX_INBOX;
}
break;
case MMS_INBOX:
msgBox = Mms.MESSAGE_BOX_INBOX;
break;
case MMS_SENT:
msgBox = Mms.MESSAGE_BOX_SENT;
break;
case MMS_DRAFTS:
msgBox = Mms.MESSAGE_BOX_DRAFTS;
break;
case MMS_OUTBOX:
msgBox = Mms.MESSAGE_BOX_OUTBOX;
break;
case MMS_MSG_PART:
notify = false;
table = TABLE_PART;
break;
case MMS_MSG_ADDR:
notify = false;
table = TABLE_ADDR;
break;
case MMS_SENDING_RATE:
notify = false;
table = TABLE_RATE;
break;
case MMS_DRM_STORAGE:
notify = false;
table = TABLE_DRM;
break;
default:
Log.e(TAG, "Invalid request: " + uri);
return null;
}
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
ContentValues finalValues;
Uri res = Mms.CONTENT_URI;
long rowId;
if (table.equals(TABLE_PDU)) {
boolean addDate = !values.containsKey(Mms.DATE);
boolean addMsgBox = !values.containsKey(Mms.MESSAGE_BOX);
// Filter keys we don't support yet.
filterUnsupportedKeys(values);
// TODO: Should initialValues be validated, e.g. if it
// missed some significant keys?
finalValues = new ContentValues(values);
long timeInMillis = System.currentTimeMillis();
if (addDate) {
finalValues.put(Mms.DATE, timeInMillis / 1000L);
}
if (addMsgBox && (msgBox != Mms.MESSAGE_BOX_ALL)) {
finalValues.put(Mms.MESSAGE_BOX, msgBox);
}
if (msgBox != Mms.MESSAGE_BOX_INBOX) {
// Mark all non-inbox messages read.
finalValues.put(Mms.READ, 1);
}
if ((rowId = db.insert(table, null, finalValues)) <= 0) {
Log.e(TAG, "MmsProvider.insert: failed! " + finalValues);
return null;
}
res = Uri.parse(res + "/" + rowId);
} else if (table.equals(TABLE_ADDR)) {
finalValues = new ContentValues(values);
finalValues.put(Addr.MSG_ID, uri.getPathSegments().get(0));
if ((rowId = db.insert(table, null, finalValues)) <= 0) {
Log.e(TAG, "Failed to insert address: " + finalValues);
return null;
}
res = Uri.parse(res + "/addr/" + rowId);
} else if (table.equals(TABLE_PART)) {
finalValues = new ContentValues(values);
if (match == MMS_MSG_PART) {
finalValues.put(Part.MSG_ID, uri.getPathSegments().get(0));
}
// Generate the '_data' field of the part with default
// permission settings.
String path = getContext().getDir("parts", 0).getPath()
+ "/PART_" + System.currentTimeMillis();
finalValues.put(Part._DATA, path);
File partFile = new File(path);
if (!partFile.exists()) {
try {
if (!partFile.createNewFile()) {
throw new IllegalStateException(
"Unable to create new partFile: " + path);
}
} catch (IOException e) {
Log.e(TAG, "createNewFile", e);
throw new IllegalStateException(
"Unable to create new partFile: " + path);
}
}
if ((rowId = db.insert(table, null, finalValues)) <= 0) {
Log.e(TAG, "MmsProvider.insert: failed! " + finalValues);
return null;
}
res = Uri.parse(res + "/part/" + rowId);
} else if (table.equals(TABLE_RATE)) {
long now = values.getAsLong(Rate.SENT_TIME);
long oneHourAgo = now - 1000 * 60 * 60;
// Delete all unused rows (time earlier than one hour ago).
db.delete(table, Rate.SENT_TIME + "<=" + oneHourAgo, null);
db.insert(table, null, values);
} else if (table.equals(TABLE_DRM)) {
String path = getContext().getDir("parts", 0).getPath()
+ "/PART_" + System.currentTimeMillis();
finalValues = new ContentValues(1);
finalValues.put("_data", path);
File partFile = new File(path);
if (!partFile.exists()) {
try {
if (!partFile.createNewFile()) {
throw new IllegalStateException(
"Unable to create new file: " + path);
}
} catch (IOException e) {
Log.e(TAG, "createNewFile", e);
throw new IllegalStateException(
"Unable to create new file: " + path);
}
}
if ((rowId = db.insert(table, null, finalValues)) <= 0) {
Log.e(TAG, "MmsProvider.insert: failed! " + finalValues);
return null;
}
res = Uri.parse(res + "/drm/" + rowId);
} else {
throw new AssertionError("Unknown table type: " + table);
}
if (notify) {
notifyChange();
}
return res;
| private void | notifyChange()
getContext().getContentResolver().notifyChange(
MmsSms.CONTENT_URI, null);
| public boolean | onCreate()
mOpenHelper = MmsSmsDatabaseHelper.getInstance(getContext());
return true;
| public android.os.ParcelFileDescriptor | openFile(android.net.Uri uri, java.lang.String mode)
return openFileHelper(uri, mode);
| public android.database.Cursor | query(android.net.Uri uri, java.lang.String[] projection, java.lang.String selection, java.lang.String[] selectionArgs, java.lang.String sortOrder)
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
// Generate the body of the query.
int match = sURLMatcher.match(uri);
if (LOCAL_LOGV) {
Log.v(TAG, "Query uri=" + uri + ", match=" + match);
}
switch (match) {
case MMS_ALL:
constructQueryForBox(qb, Mms.MESSAGE_BOX_ALL);
break;
case MMS_INBOX:
constructQueryForBox(qb, Mms.MESSAGE_BOX_INBOX);
break;
case MMS_SENT:
constructQueryForBox(qb, Mms.MESSAGE_BOX_SENT);
break;
case MMS_DRAFTS:
constructQueryForBox(qb, Mms.MESSAGE_BOX_DRAFTS);
break;
case MMS_OUTBOX:
constructQueryForBox(qb, Mms.MESSAGE_BOX_OUTBOX);
break;
case MMS_ALL_ID:
qb.setTables(TABLE_PDU);
qb.appendWhere(Mms._ID + "=" + uri.getPathSegments().get(0));
break;
case MMS_INBOX_ID:
case MMS_SENT_ID:
case MMS_DRAFTS_ID:
case MMS_OUTBOX_ID:
qb.setTables(TABLE_PDU);
qb.appendWhere(Mms._ID + "=" + uri.getPathSegments().get(1));
qb.appendWhere(" AND " + Mms.MESSAGE_BOX + "="
+ getMessageBoxByMatch(match));
break;
case MMS_ALL_PART:
qb.setTables(TABLE_PART);
break;
case MMS_MSG_PART:
qb.setTables(TABLE_PART);
qb.appendWhere(Part.MSG_ID + "=" + uri.getPathSegments().get(0));
break;
case MMS_PART_ID:
qb.setTables(TABLE_PART);
qb.appendWhere(Part._ID + "=" + uri.getPathSegments().get(1));
break;
case MMS_MSG_ADDR:
qb.setTables(TABLE_ADDR);
qb.appendWhere(Addr.MSG_ID + "=" + uri.getPathSegments().get(0));
break;
case MMS_REPORT_STATUS:
/*
SELECT DISTINCT address,
T.delivery_status AS delivery_status,
T.read_status AS read_status
FROM addr
INNER JOIN (SELECT P1._id AS id1, P2._id AS id2, P3._id AS id3,
ifnull(P2.st, 0) AS delivery_status,
ifnull(P3.read_status, 0) AS read_status
FROM pdu P1
INNER JOIN pdu P2
ON P1.m_id = P2.m_id AND P2.m_type = 134
LEFT JOIN pdu P3
ON P1.m_id = P3.m_id AND P3.m_type = 136
UNION
SELECT P1._id AS id1, P2._id AS id2, P3._id AS id3,
ifnull(P2.st, 0) AS delivery_status,
ifnull(P3.read_status, 0) AS read_status
FROM pdu P1
INNER JOIN pdu P3
ON P1.m_id = P3.m_id AND P3.m_type = 136
LEFT JOIN pdu P2
ON P1.m_id = P2.m_id AND P2.m_type = 134) T
ON (msg_id = id2 AND type = 151)
OR (msg_id = id3 AND type = 137)
WHERE T.id1 = ?;
*/
qb.setTables("addr INNER JOIN (SELECT P1._id AS id1, P2._id" +
" AS id2, P3._id AS id3, ifnull(P2.st, 0) AS" +
" delivery_status, ifnull(P3.read_status, 0) AS" +
" read_status FROM pdu P1 INNER JOIN pdu P2 ON" +
" P1.m_id=P2.m_id AND P2.m_type=134 LEFT JOIN" +
" pdu P3 ON P1.m_id=P3.m_id AND P3.m_type=136" +
" UNION SELECT P1._id AS id1, P2._id AS id2, P3._id" +
" AS id3, ifnull(P2.st, 0) AS delivery_status," +
" ifnull(P3.read_status, 0) AS read_status FROM" +
" pdu P1 INNER JOIN pdu P3 ON P1.m_id=P3.m_id AND" +
" P3.m_type=136 LEFT JOIN pdu P2 ON P1.m_id=P2.m_id" +
" AND P2.m_type=134) T ON (msg_id=id2 AND type=151)" +
" OR (msg_id=id3 AND type=137)");
qb.appendWhere("T.id1 = " + uri.getLastPathSegment());
qb.setDistinct(true);
break;
case MMS_REPORT_REQUEST:
/*
SELECT address, d_rpt, rr
FROM addr join pdu on pdu._id = addr.msg_id
WHERE pdu._id = messageId AND addr.type = 151
*/
qb.setTables(TABLE_ADDR + " join " +
TABLE_PDU + " on pdu._id = addr.msg_id");
qb.appendWhere("pdu._id = " + uri.getLastPathSegment());
qb.appendWhere(" AND " + "addr.type = " + PduHeaders.TO);
break;
case MMS_SENDING_RATE:
qb.setTables(TABLE_RATE);
break;
case MMS_DRM_STORAGE_ID:
qb.setTables(TABLE_DRM);
qb.appendWhere(BaseColumns._ID + "=" + uri.getLastPathSegment());
break;
default:
Log.e(TAG, "Invalid request: " + uri);
return null;
}
String finalSortOrder = null;
if (TextUtils.isEmpty(sortOrder)) {
if (qb.getTables().equals(TABLE_PDU)) {
finalSortOrder = Mms.DATE + " DESC";
} else if (qb.getTables().equals(TABLE_PART)) {
finalSortOrder = Part.SEQ;
}
} else {
finalSortOrder = sortOrder;
}
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor ret = qb.query(db, projection, selection,
selectionArgs, null, null, finalSortOrder);
// TODO: Does this need to be a URI for this provider.
ret.setNotificationUri(getContext().getContentResolver(), uri);
return ret;
| public int | update(android.net.Uri uri, android.content.ContentValues values, java.lang.String selection, java.lang.String[] selectionArgs)
int match = sURLMatcher.match(uri);
if (LOCAL_LOGV) {
Log.v(TAG, "Update uri=" + uri + ", match=" + match);
}
boolean notify = false;
String msgId = null;
String table;
switch (match) {
case MMS_ALL_ID:
case MMS_INBOX_ID:
case MMS_SENT_ID:
case MMS_DRAFTS_ID:
case MMS_OUTBOX_ID:
msgId = uri.getLastPathSegment();
// fall-through
case MMS_ALL:
case MMS_INBOX:
case MMS_SENT:
case MMS_DRAFTS:
case MMS_OUTBOX:
notify = true;
table = TABLE_PDU;
break;
case MMS_MSG_PART:
case MMS_PART_ID:
table = TABLE_PART;
break;
default:
Log.w(TAG, "Update operation for '" + uri + "' not implemented.");
return 0;
}
String extraSelection = null;
ContentValues finalValues;
if (table.equals(TABLE_PDU)) {
// Filter keys that we don't support yet.
filterUnsupportedKeys(values);
finalValues = new ContentValues(values);
if (msgId != null) {
extraSelection = Mms._ID + "=" + msgId;
}
} else if (table.equals(TABLE_PART)) {
finalValues = new ContentValues(values);
switch (match) {
case MMS_MSG_PART:
extraSelection = Part.MSG_ID + "=" + uri.getPathSegments().get(0);
break;
case MMS_PART_ID:
extraSelection = Part._ID + "=" + uri.getPathSegments().get(1);
break;
default:
break;
}
} else {
return 0;
}
String finalSelection = concatSelections(selection, extraSelection);
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count = db.update(table, finalValues, finalSelection, selectionArgs);
if (notify && (count > 0)) {
notifyChange();
}
return count;
|
|