Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Copyright (C) 2007 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.telephony;
- import android.app.AppOpsManager;
- import android.content.ContentProvider;
- import android.content.ContentValues;
- import android.content.Context;
- import android.content.Intent;
- import android.content.UriMatcher;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteException;
- import android.database.sqlite.SQLiteOpenHelper;
- import android.database.sqlite.SQLiteQueryBuilder;
- import android.net.Uri;
- import android.os.Binder;
- import android.os.FileUtils;
- import android.os.ParcelFileDescriptor;
- import android.os.UserHandle;
- import android.provider.BaseColumns;
- import android.provider.Telephony;
- import android.provider.Telephony.CanonicalAddressesColumns;
- import android.provider.Telephony.Mms;
- import android.provider.Telephony.Mms.Addr;
- import android.provider.Telephony.Mms.Part;
- import android.provider.Telephony.Mms.Rate;
- import android.provider.Telephony.MmsSms;
- import android.provider.Telephony.Threads;
- import android.text.TextUtils;
- import android.util.Log;
- import com.google.android.mms.pdu.PduHeaders;
- import com.google.android.mms.util.DownloadDrmHelper;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.util.HashSet;
- /**
- * The class to provide base facility to access MMS related content,
- * which is stored in a SQLite database and in the file system.
- */
- public class MmsProvider extends ContentProvider {
- static final String TABLE_PDU = "pdu";
- static final String TABLE_ADDR = "addr";
- static final String TABLE_PART = "part";
- static final String TABLE_RATE = "rate";
- static final String TABLE_DRM = "drm";
- static final String TABLE_WORDS = "words";
- @Override
- public boolean onCreate() {
- setAppOps(AppOpsManager.OP_READ_MMS, AppOpsManager.OP_WRITE_MMS);
- mOpenHelper = MmsSmsDatabaseHelper.getInstance(getContext());
- return true;
- }
- @Override
- public Cursor query(Uri uri, String[] projection,
- String selection, String[] selectionArgs, 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;
- case MMS_THREADS:
- qb.setTables("pdu group by thread_id");
- break;
- default:
- Log.e(TAG, "query: 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;
- }
- if (projection != null) {
- for (int i = 0; i < projection.length; i++) {
- if (projection[i].equals("sub_id"))
- projection[i] = "phone_id";
- }
- }
- Cursor ret;
- try {
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- ret = qb.query(db, projection, selection,
- selectionArgs, null, null, finalSortOrder);
- } catch (SQLiteException e) {
- Log.e(TAG, "returning NULL cursor, query: " + uri, e);
- return null;
- }
- // TODO: Does this need to be a URI for this provider.
- ret.setNotificationUri(getContext().getContentResolver(), uri);
- return ret;
- }
- private void constructQueryForBox(SQLiteQueryBuilder qb, int msgBox) {
- qb.setTables(TABLE_PDU);
- if (msgBox != Mms.MESSAGE_BOX_ALL) {
- qb.appendWhere(Mms.MESSAGE_BOX + "=" + msgBox);
- }
- }
- @Override
- public String getType(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 "*/*";
- }
- }
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- // Don't let anyone insert anything with the _data column
- if (values != null && values.containsKey(Part._DATA)) {
- return null;
- }
- final int callerUid = Binder.getCallingUid();
- 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, "insert: 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);
- }
- // thread_id
- Long threadId = values.getAsLong(Mms.THREAD_ID);
- String address = values.getAsString(CanonicalAddressesColumns.ADDRESS);
- if (((threadId == null) || (threadId == 0)) && (!TextUtils.isEmpty(address))) {
- finalValues.put(Mms.THREAD_ID, Threads.getOrCreateThreadId(getContext(), address));
- }
- if (ProviderUtil.shouldSetCreator(finalValues, callerUid)) {
- // Only SYSTEM or PHONE can set CREATOR
- // If caller is not SYSTEM or PHONE, or SYSTEM or PHONE does not set CREATOR
- // set CREATOR using the truth on caller.
- // Note: Inferring package name from UID may include unrelated package names
- finalValues.put(Telephony.Mms.CREATOR,
- ProviderUtil.getPackageNamesByUid(getContext(), callerUid));
- }
- if (finalValues.containsKey("sub_id"))
- {
- int val = finalValues.getAsInteger("sub_id");
- finalValues.remove("sub_id");
- finalValues.put("phone_id", val);
- }
- if ((rowId = db.insert(table, null, finalValues)) <= 0) {
- Log.e(TAG, "MmsProvider.insert: failed!");
- 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 (finalValues.containsKey("sub_id"))
- {
- int val = finalValues.getAsInteger("sub_id");
- finalValues.remove("sub_id");
- finalValues.put("phone_id", val);
- }
- if ((rowId = db.insert(table, null, finalValues)) <= 0) {
- Log.e(TAG, "Failed to insert address");
- 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));
- }
- String contentType = values.getAsString("ct");
- // text/plain and app application/smil store their "data" inline in the
- // table so there's no need to create the file
- boolean plainText = false;
- boolean smilText = false;
- if ("text/plain".equals(contentType)) {
- plainText = true;
- } else if ("application/smil".equals(contentType)) {
- smilText = true;
- }
- if (!plainText && !smilText) {
- // Use the filename if possible, otherwise use the current time as the name.
- String contentLocation = values.getAsString("cl");
- if (!TextUtils.isEmpty(contentLocation)) {
- File f = new File(contentLocation);
- contentLocation = "_" + f.getName();
- } else {
- contentLocation = "";
- }
- // Generate the '_data' field of the part with default
- // permission settings.
- String path = getContext().getDir("parts", 0).getPath()
- + "/PART_" + System.currentTimeMillis() + contentLocation;
- if (DownloadDrmHelper.isDrmConvertNeeded(contentType)) {
- // Adds the .fl extension to the filename if contentType is
- // "application/vnd.oma.drm.message"
- path = DownloadDrmHelper.modifyDrmFwLockFileExtension(path);
- }
- 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);
- }
- // Give everyone rw permission until we encrypt the file
- // (in PduPersister.persistData). Once the file is encrypted, the
- // permissions will be set to 0644.
- int result = FileUtils.setPermissions(path, 0666, -1, -1);
- if (LOCAL_LOGV) {
- Log.d(TAG, "MmsProvider.insert setPermissions result: " + result);
- }
- } catch (IOException e) {
- Log.e(TAG, "createNewFile", e);
- throw new IllegalStateException(
- "Unable to create new partFile: " + path);
- }
- }
- }
- if (finalValues.containsKey("sub_id"))
- {
- int val = finalValues.getAsInteger("sub_id");
- finalValues.remove("sub_id");
- finalValues.put("phone_id", val);
- }
- if ((rowId = db.insert(table, null, finalValues)) <= 0) {
- Log.e(TAG, "MmsProvider.insert: failed!");
- return null;
- }
- res = Uri.parse(res + "/part/" + rowId);
- // Don't use a trigger for updating the words table because of a bug
- // in FTS3. The bug is such that the call to get the last inserted
- // row is incorrect.
- if (plainText) {
- // Update the words table with a corresponding row. The words table
- // allows us to search for words quickly, without scanning the whole
- // table;
- ContentValues cv = new ContentValues();
- // we're using the row id of the part table row but we're also using ids
- // from the sms table so this divides the space into two large chunks.
- // The row ids from the part table start at 2 << 32.
- cv.put(Telephony.MmsSms.WordsTable.ID, (2 << 32) + rowId);
- cv.put(Telephony.MmsSms.WordsTable.INDEXED_TEXT, values.getAsString("text"));
- cv.put(Telephony.MmsSms.WordsTable.SOURCE_ROW_ID, rowId);
- cv.put(Telephony.MmsSms.WordsTable.TABLE_ID, 2);
- db.insert(TABLE_WORDS, Telephony.MmsSms.WordsTable.INDEXED_TEXT, cv);
- }
- } 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!");
- return null;
- }
- res = Uri.parse(res + "/drm/" + rowId);
- } else {
- throw new AssertionError("Unknown table type: " + table);
- }
- if (notify) {
- notifyChange();
- }
- return res;
- }
- 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);
- }
- }
- @Override
- public int delete(Uri uri, String selection,
- 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;
- case MMS_THREAD_ID:
- notify = true;
- table = TABLE_PDU;
- extraSelection = Mms.THREAD_ID + "=" + uri.getLastPathSegment();
- 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);
- cleanUpWords(db);
- updateHasAttachment(db);
- } 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;
- }
- static int deleteMessages(Context context, SQLiteDatabase db,
- String selection, String[] selectionArgs, Uri uri) {
- Cursor cursor = db.query(TABLE_PDU, new String[] { Mms._ID, Mms.THREAD_ID },
- selection, selectionArgs, null, null, null);
- if (cursor == null) {
- return 0;
- }
- HashSet<Long> threadIds = new HashSet<Long>();
- try {
- if (cursor.getCount() == 0) {
- return 0;
- }
- while (cursor.moveToNext()) {
- deleteParts(db, Part.MSG_ID + " = ?",
- new String[] { String.valueOf(cursor.getLong(0)) });
- threadIds.add(cursor.getLong(1));
- }
- cleanUpWords(db);
- updateHasAttachment(db);
- } finally {
- cursor.close();
- }
- int count = db.delete(TABLE_PDU, selection, selectionArgs);
- for (long thread : threadIds) {
- MmsSmsDatabaseHelper.updateThread(db, thread);
- }
- 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 void cleanUpWords(SQLiteDatabase db) {
- db.execSQL("DELETE FROM words WHERE source_id not in (select _id from part) AND "
- + "table_to_use = 2");
- }
- private static void updateHasAttachment(SQLiteDatabase db) {
- db.execSQL("UPDATE threads SET has_attachment = CASE "
- + "(SELECT COUNT(*) FROM part JOIN pdu WHERE part.mid = pdu._id AND "
- + "pdu.thread_id = threads._id AND part.ct != 'text/plain' "
- + "AND part.ct != 'application/smil') WHEN 0 THEN 0 ELSE 1 END");
- }
- private static int deleteParts(SQLiteDatabase db, String selection,
- String[] selectionArgs) {
- return deleteDataRows(db, TABLE_PART, selection, selectionArgs);
- }
- private static int deleteTempDrmData(SQLiteDatabase db, String selection,
- String[] selectionArgs) {
- return deleteDataRows(db, TABLE_DRM, selection, selectionArgs);
- }
- private static int deleteDataRows(SQLiteDatabase db, String table,
- String selection, 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.
- String path = cursor.getString(0);
- if (path != null) {
- new File(path).delete();
- }
- } catch (Throwable ex) {
- Log.e(TAG, ex.getMessage(), ex);
- }
- }
- } finally {
- cursor.close();
- }
- return db.delete(table, selection, selectionArgs);
- }
- @Override
- public int update(Uri uri, ContentValues values,
- String selection, String[] selectionArgs) {
- // Don't let anyone update the _data column
- if (values != null && values.containsKey(Part._DATA)) {
- return 0;
- }
- final int callerUid = Binder.getCallingUid();
- 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;
- case MMS_PART_RESET_FILE_PERMISSION:
- String path = getContext().getDir("parts", 0).getPath() + '/' +
- uri.getPathSegments().get(1);
- // Reset the file permission back to read for everyone but me.
- int result = FileUtils.setPermissions(path, 0644, -1, -1);
- if (LOCAL_LOGV) {
- Log.d(TAG, "MmsProvider.update setPermissions result: " + result +
- " for path: " + path);
- }
- return 0;
- 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);
- if (ProviderUtil.shouldRemoveCreator(values, callerUid)) {
- // CREATOR should not be changed by non-SYSTEM/PHONE apps
- Log.w(TAG, ProviderUtil.getPackageNamesByUid(getContext(), callerUid) +
- " tries to update CREATOR");
- values.remove(Mms.CREATOR);
- }
- 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;
- }
- @Override
- public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
- int match = sURLMatcher.match(uri);
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.d(TAG, "openFile: uri=" + uri + ", mode=" + mode + ", match=" + match);
- }
- if (match != MMS_PART_ID) {
- return null;
- }
- // Verify that the _data path points to mms data
- Cursor c = query(uri, new String[]{"_data"}, null, null, null);
- int count = (c != null) ? c.getCount() : 0;
- if (count != 1) {
- // If there is not exactly one result, throw an appropriate
- // exception.
- if (c != null) {
- c.close();
- }
- if (count == 0) {
- throw new FileNotFoundException("No entry for " + uri);
- }
- throw new FileNotFoundException("Multiple items at " + uri);
- }
- c.moveToFirst();
- int i = c.getColumnIndex("_data");
- String path = (i >= 0 ? c.getString(i) : null);
- c.close();
- if (path == null) {
- return null;
- }
- try {
- File filePath = new File(path);
- if (!filePath.getCanonicalPath()
- .startsWith(getContext().getApplicationInfo().dataDir + "/app_parts/")) {
- return null;
- }
- } catch (IOException e) {
- return null;
- }
- return openFileHelper(uri, mode);
- }
- private void filterUnsupportedKeys(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 void notifyChange() {
- getContext().getContentResolver().notifyChange(
- MmsSms.CONTENT_URI, null, true, UserHandle.USER_ALL);
- }
- private final static String TAG = "MmsProvider";
- private final static String VND_ANDROID_MMS = "vnd.android/mms";
- private final static String VND_ANDROID_DIR_MMS = "vnd.android-dir/mms";
- private final static boolean DEBUG = false;
- private final static boolean LOCAL_LOGV = false;
- private static final int MMS_ALL = 0;
- private static final int MMS_ALL_ID = 1;
- private static final int MMS_INBOX = 2;
- private static final int MMS_INBOX_ID = 3;
- private static final int MMS_SENT = 4;
- private static final int MMS_SENT_ID = 5;
- private static final int MMS_DRAFTS = 6;
- private static final int MMS_DRAFTS_ID = 7;
- private static final int MMS_OUTBOX = 8;
- private static final int MMS_OUTBOX_ID = 9;
- private static final int MMS_ALL_PART = 10;
- private static final int MMS_MSG_PART = 11;
- private static final int MMS_PART_ID = 12;
- private static final int MMS_MSG_ADDR = 13;
- private static final int MMS_SENDING_RATE = 14;
- private static final int MMS_REPORT_STATUS = 15;
- private static final int MMS_REPORT_REQUEST = 16;
- private static final int MMS_DRM_STORAGE = 17;
- private static final int MMS_DRM_STORAGE_ID = 18;
- private static final int MMS_THREADS = 19;
- private static final int MMS_PART_RESET_FILE_PERMISSION = 20;
- private static final int MMS_THREAD_ID = 21;
- private static final UriMatcher
- sURLMatcher = new UriMatcher(UriMatcher.NO_MATCH);
- static {
- sURLMatcher.addURI("mms", null, MMS_ALL);
- sURLMatcher.addURI("mms", "#", MMS_ALL_ID);
- sURLMatcher.addURI("mms", "inbox", MMS_INBOX);
- sURLMatcher.addURI("mms", "inbox/#", MMS_INBOX_ID);
- sURLMatcher.addURI("mms", "sent", MMS_SENT);
- sURLMatcher.addURI("mms", "sent/#", MMS_SENT_ID);
- sURLMatcher.addURI("mms", "drafts", MMS_DRAFTS);
- sURLMatcher.addURI("mms", "drafts/#", MMS_DRAFTS_ID);
- sURLMatcher.addURI("mms", "outbox", MMS_OUTBOX);
- sURLMatcher.addURI("mms", "outbox/#", MMS_OUTBOX_ID);
- sURLMatcher.addURI("mms", "part", MMS_ALL_PART);
- sURLMatcher.addURI("mms", "#/part", MMS_MSG_PART);
- sURLMatcher.addURI("mms", "part/#", MMS_PART_ID);
- sURLMatcher.addURI("mms", "#/addr", MMS_MSG_ADDR);
- sURLMatcher.addURI("mms", "rate", MMS_SENDING_RATE);
- sURLMatcher.addURI("mms", "report-status/#", MMS_REPORT_STATUS);
- sURLMatcher.addURI("mms", "report-request/#", MMS_REPORT_REQUEST);
- sURLMatcher.addURI("mms", "drm", MMS_DRM_STORAGE);
- sURLMatcher.addURI("mms", "drm/#", MMS_DRM_STORAGE_ID);
- sURLMatcher.addURI("mms", "threads", MMS_THREADS);
- sURLMatcher.addURI("mms", "resetFilePerm/*", MMS_PART_RESET_FILE_PERMISSION);
- sURLMatcher.addURI("mms", "thread/#", MMS_THREAD_ID);
- }
- private SQLiteOpenHelper mOpenHelper;
- private static String concatSelections(String selection1, String selection2) {
- if (TextUtils.isEmpty(selection1)) {
- return selection2;
- } else if (TextUtils.isEmpty(selection2)) {
- return selection1;
- } else {
- return selection1 + " AND " + selection2;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment