@Override public int update(Uri url, ContentValues values, String where, String[] whereArgs) { final int callerUid = Binder.getCallingUid(); int count = 0; String table = TABLE_SMS; String extraWhere = null; SQLiteDatabase db = mOpenHelper.getWritableDatabase(); switch (sURLMatcher.match(url)) { case SMS_RAW_MESSAGE: table = TABLE_RAW; break; case SMS_STATUS_PENDING: table = TABLE_SR_PENDING; break; case SMS_ALL: case SMS_FAILED: case SMS_QUEUED: case SMS_INBOX: case SMS_SENT: case SMS_DRAFT: case SMS_OUTBOX: case SMS_CONVERSATIONS: break; case SMS_ALL_ID: extraWhere = "_id=" + url.getPathSegments().get(0); break; case SMS_INBOX_ID: case SMS_FAILED_ID: case SMS_SENT_ID: case SMS_DRAFT_ID: case SMS_OUTBOX_ID: extraWhere = "_id=" + url.getPathSegments().get(1); break; case SMS_CONVERSATIONS_ID: { String threadId = url.getPathSegments().get(1); try { Integer.parseInt(threadId); } catch (Exception ex) { Log.e(TAG, "Bad conversation thread id: " + threadId); break; } extraWhere = "thread_id=" + threadId; break; } case SMS_STATUS_ID: extraWhere = "_id=" + url.getPathSegments().get(1); break; default: throw new UnsupportedOperationException("URI " + url + " not supported"); } if (table.equals(TABLE_SMS) && 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(Sms.CREATOR); } where = DatabaseUtils.concatenateWhere(where, extraWhere); count = db.update(table, values, where, whereArgs); if (count > 0) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.d(TAG, "update " + url + " succeeded"); } notifyChange(url); } return count; }
private Uri insertInner(Uri url, ContentValues initialValues, int callerUid) { ContentValues values; long rowID; int type = Sms.MESSAGE_TYPE_ALL; int match = sURLMatcher.match(url); String table = TABLE_SMS; switch (match) { case SMS_ALL: Integer typeObj = initialValues.getAsInteger(Sms.TYPE); if (typeObj != null) { type = typeObj.intValue(); } else { // default to inbox type = Sms.MESSAGE_TYPE_INBOX; } break; case SMS_INBOX: type = Sms.MESSAGE_TYPE_INBOX; break; case SMS_FAILED: type = Sms.MESSAGE_TYPE_FAILED; break; case SMS_QUEUED: type = Sms.MESSAGE_TYPE_QUEUED; break; case SMS_SENT: type = Sms.MESSAGE_TYPE_SENT; break; case SMS_DRAFT: type = Sms.MESSAGE_TYPE_DRAFT; break; case SMS_OUTBOX: type = Sms.MESSAGE_TYPE_OUTBOX; break; case SMS_RAW_MESSAGE: table = "raw"; break; case SMS_STATUS_PENDING: table = "sr_pending"; break; case SMS_ATTACHMENT: table = "attachments"; break; case SMS_NEW_THREAD_ID: table = "canonical_addresses"; break; default: Log.e(TAG, "Invalid request: " + url); return null; } SQLiteDatabase db = mOpenHelper.getWritableDatabase(); if (table.equals(TABLE_SMS)) { boolean addDate = false; boolean addType = false; // Make sure that the date and type are set if (initialValues == null) { values = new ContentValues(1); addDate = true; addType = true; } else { values = new ContentValues(initialValues); if (!initialValues.containsKey(Sms.DATE)) { addDate = true; } if (!initialValues.containsKey(Sms.TYPE)) { addType = true; } } if (addDate) { values.put(Sms.DATE, new Long(System.currentTimeMillis())); } if (addType && (type != Sms.MESSAGE_TYPE_ALL)) { values.put(Sms.TYPE, Integer.valueOf(type)); } // thread_id Long threadId = values.getAsLong(Sms.THREAD_ID); String address = values.getAsString(Sms.ADDRESS); if (((threadId == null) || (threadId == 0)) && (!TextUtils.isEmpty(address))) { values.put(Sms.THREAD_ID, Threads.getOrCreateThreadId(getContext(), address)); } // If this message is going in as a draft, it should replace any // other draft messages in the thread. Just delete all draft // messages with this thread ID. We could add an OR REPLACE to // the insert below, but we'd have to query to find the old _id // to produce a conflict anyway. if (values.getAsInteger(Sms.TYPE) == Sms.MESSAGE_TYPE_DRAFT) { db.delete( TABLE_SMS, "thread_id=? AND type=?", new String[] { values.getAsString(Sms.THREAD_ID), Integer.toString(Sms.MESSAGE_TYPE_DRAFT) }); } if (type == Sms.MESSAGE_TYPE_INBOX) { // Look up the person if not already filled in. if ((values.getAsLong(Sms.PERSON) == null) && (!TextUtils.isEmpty(address))) { Cursor cursor = null; Uri uri = Uri.withAppendedPath(Contacts.Phones.CONTENT_FILTER_URL, Uri.encode(address)); try { cursor = getContext() .getContentResolver() .query(uri, CONTACT_QUERY_PROJECTION, null, null, null); if (cursor.moveToFirst()) { Long id = Long.valueOf(cursor.getLong(PERSON_ID_COLUMN)); values.put(Sms.PERSON, id); } } catch (Exception ex) { Log.e(TAG, "insert: query contact uri " + uri + " caught ", ex); } finally { if (cursor != null) { cursor.close(); } } } } else { // Mark all non-inbox messages read. values.put(Sms.READ, ONE); } if (ProviderUtil.shouldSetCreator(values, 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 values.put(Sms.CREATOR, ProviderUtil.getPackageNamesByUid(getContext(), callerUid)); } } else { if (initialValues == null) { values = new ContentValues(1); } else { values = initialValues; } } rowID = db.insert(table, "body", values); // 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 (table == TABLE_SMS) { // 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(); cv.put(Telephony.MmsSms.WordsTable.ID, rowID); cv.put(Telephony.MmsSms.WordsTable.INDEXED_TEXT, values.getAsString("body")); cv.put(Telephony.MmsSms.WordsTable.SOURCE_ROW_ID, rowID); cv.put(Telephony.MmsSms.WordsTable.TABLE_ID, 1); db.insert(TABLE_WORDS, Telephony.MmsSms.WordsTable.INDEXED_TEXT, cv); } if (rowID > 0) { Uri uri = Uri.parse("content://" + table + "/" + rowID); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.d(TAG, "insert " + uri + " succeeded"); } notifyChange(uri); return uri; } else { Log.e(TAG, "insert: failed!"); } return null; }