/** * This method is used if this is a "replace short message" SMS. We find any existing message that * matches the incoming message's originating address and protocol identifier. If there is one, we * replace its fields with those of the new message. Otherwise, we store the new message as usual. * * <p>See TS 23.040 9.2.3.9. */ private Uri replaceMessage(Context context, SmsMessage[] msgs, int error) { SmsMessage sms = msgs[0]; ContentValues values = extractContentValues(sms); values.put(Sms.ERROR_CODE, error); int pduCount = msgs.length; if (pduCount == 1) { // There is only one part, so grab the body directly. values.put(Inbox.BODY, replaceFormFeeds(sms.getDisplayMessageBody())); } else { // Build up the body from the parts. StringBuilder body = new StringBuilder(); for (int i = 0; i < pduCount; i++) { sms = msgs[i]; if (sms.mWrappedSmsMessage != null) { body.append(sms.getDisplayMessageBody()); } } values.put(Inbox.BODY, replaceFormFeeds(body.toString())); } ContentResolver resolver = context.getContentResolver(); String originatingAddress = sms.getOriginatingAddress(); int protocolIdentifier = sms.getProtocolIdentifier(); String selection = Sms.ADDRESS + " = ? AND " + Sms.PROTOCOL + " = ?"; String[] selectionArgs = new String[] {originatingAddress, Integer.toString(protocolIdentifier)}; Cursor cursor = SqliteWrapper.query( context, resolver, Inbox.CONTENT_URI, REPLACE_PROJECTION, selection, selectionArgs, null); if (cursor != null) { try { if (cursor.moveToFirst()) { long messageId = cursor.getLong(REPLACE_COLUMN_ID); Uri messageUri = ContentUris.withAppendedId(Sms.CONTENT_URI, messageId); SqliteWrapper.update(context, resolver, messageUri, values, null, null); return messageUri; } } finally { cursor.close(); } } return storeMessage(context, msgs, error); }
/// M:Code analyze 011,add for setting the mms being downloading when shutdown to unrecognized /// after boot complete again,have to manual download @{ public static void setNotificationIndUnstarted(final Context context) { MmsLog.d(MmsApp.TXN_TAG, "setNotificationIndUnstarted"); Cursor cursor = SqliteWrapper.query( context, context.getContentResolver(), Mms.CONTENT_URI, new String[] {Mms._ID, Mms.STATUS}, Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND, null, null); if (cursor != null) { try { int count = cursor.getCount(); MmsLog.d(MmsApp.TXN_TAG, "setNotificationIndUnstarted: Message Size=" + count); if (count == 0) { return; } ContentValues values = null; int id = 0; int status = 0; while (cursor.moveToNext()) { id = cursor.getInt(0); status = cursor.getInt(1); MmsLog.d( MmsApp.TXN_TAG, "setNotificationIndUnstarted: MsgId=" + id + "; status=" + status); if (DownloadManager.STATE_DOWNLOADING == (status & ~DownloadManager.DEFERRED_MASK)) { values = new ContentValues(1); values.put(Mms.STATUS, PduHeaders.STATUS_UNRECOGNIZED); SqliteWrapper.update( context, context.getContentResolver(), Mms.CONTENT_URI, values, Mms._ID + "=" + id, null); } } } catch (SQLiteDiskIOException e) { // Ignore MmsLog.e( MmsApp.TXN_TAG, "SQLiteDiskIOException caught while set notification ind unstart", e); } finally { cursor.close(); } } else { MmsLog.d(MmsApp.TXN_TAG, "setNotificationIndUnstarted: no pending messages."); } }
public static void setPendingSmsFailed(final Context context) { Xlog.d(MmsApp.TXN_TAG, "setPendingSmsFailed"); Cursor cursor = SqliteWrapper.query( context, context.getContentResolver(), Sms.CONTENT_URI, new String[] {Sms._ID}, Sms.TYPE + "=" + Sms.MESSAGE_TYPE_OUTBOX + " OR " + Sms.TYPE + "=" + Sms.MESSAGE_TYPE_QUEUED, null, null); if (cursor != null) { try { int count = cursor.getCount(); Xlog.d(MmsApp.TXN_TAG, "setPendingSmsFailed: Message Size=" + count); if (count == 0) { return; } ContentValues values = null; int id = 0; while (cursor.moveToNext()) { id = cursor.getInt(0); Xlog.d(MmsApp.TXN_TAG, "setPendingSmsFailed: MsgId=" + id); values = new ContentValues(1); values.put(Sms.TYPE, Sms.MESSAGE_TYPE_FAILED); SqliteWrapper.update( context, context.getContentResolver(), Sms.CONTENT_URI, values, Sms._ID + "=" + id, null); } } catch (SQLiteDiskIOException e) { Xlog.e(MmsApp.TXN_TAG, "SQLiteDiskIOException caught while set sms failed", e); } finally { cursor.close(); } } else { Xlog.d(MmsApp.TXN_TAG, "setPendingSmsFailed: no pending messages."); } }
private void startMsgListQuery() { try { mMsgListView.setVisibility(View.GONE); mMessage.setVisibility(View.GONE); setTitle(getString(R.string.refreshing)); setProgressBarIndeterminateVisibility(true); if (mManageMode == MessageUtils.FORWARD_MODE) { mBackgroundQueryHandler.startQuery( 0, null, Sms.CONTENT_URI, FORWARD_PROJECTION, Conversations.THREAD_ID + "=?", new String[] {String.valueOf(mThreadId)}, SORT_ORDER); } else if (mManageMode == MessageUtils.SIM_MESSAGE_MODE) { mBackgroundQueryHandler.startQuery(0, null, mIccUri, null, null, null, null); } else if (mManageMode == MessageUtils.BATCH_DELETE_MODE) { Uri uri = ContentUris.withAppendedId(Threads.CONTENT_URI, mThreadId); mBackgroundQueryHandler.startQuery( 0, null, uri, MessageListAdapter.PROJECTION, null, null, null); } } catch (SQLiteException e) { SqliteWrapper.checkSQLiteException(this, e); } }
private static int getDownloadFailedMessageCount(Context context) { // Look for any messages in the MMS Inbox that are of the type // NOTIFICATION_IND (i.e. not already downloaded) and in the // permanent failure state. If there are none, cancel any // failed download notification. Cursor c = SqliteWrapper.query( context, context.getContentResolver(), Mms.Inbox.CONTENT_URI, null, Mms.MESSAGE_TYPE + "=" + String.valueOf(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND) + " AND " + Mms.STATUS + "=" + String.valueOf(DownloadManager.STATE_PERMANENT_FAILURE), null, null); if (c == null) { return 0; } int count = c.getCount(); c.close(); return count; }
private static boolean isDuplicateNotification(Context context, NotificationInd nInd) { byte[] rawLocation = nInd.getContentLocation(); if (rawLocation != null) { String location = new String(rawLocation); String selection = Mms.CONTENT_LOCATION + " = ?"; String[] selectionArgs = new String[] {location}; Cursor cursor = SqliteWrapper.query( context, context.getContentResolver(), Mms.CONTENT_URI, new String[] {Mms._ID}, selection, selectionArgs, null); if (cursor != null) { try { if (cursor.getCount() > 0) { cursor.moveToFirst(); Xlog.d(MmsApp.TXN_TAG, "duplicate, location=" + location + ", id=" + cursor.getLong(0)); // We already received the same notification before. return true; } } finally { cursor.close(); } } } return false; }
private void startQuery() { try { mQueryHandler.startQuery(0, null, ICC_URI, null, null, null, null); } catch (SQLiteException e) { SqliteWrapper.checkSQLiteException(this, e); } }
private static boolean isDuplicateNotification(Context context, NotificationInd nInd) { final byte[] rawLocation = nInd.getContentLocation(); if (rawLocation != null) { String location = new String(rawLocation); String[] selectionArgs = new String[] {location}; Cursor cursor = null; try { cursor = SqliteWrapper.query( context, context.getContentResolver(), Telephony.Mms.CONTENT_URI, new String[] {Telephony.Mms._ID}, LOCATION_SELECTION, new String[] { Integer.toString(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND), new String(rawLocation) }, null /*sortOrder*/); if (cursor != null && cursor.getCount() > 0) { // We already received the same notification before. return true; } } catch (SQLiteException e) { Rlog.e(TAG, "failed to query existing notification ind", e); } finally { if (cursor != null) { cursor.close(); } } } return false; }
private static final MmsSmsDeliveryInfo getSmsNewDeliveryInfo(Context context) { ContentResolver resolver = context.getContentResolver(); Cursor cursor = SqliteWrapper.query( context, resolver, Sms.CONTENT_URI, SMS_STATUS_PROJECTION, NEW_DELIVERY_SM_CONSTRAINT, null, Sms.DATE); if (cursor == null) return null; try { if (!cursor.moveToLast()) return null; String address = cursor.getString(COLUMN_SMS_ADDRESS); long timeMillis = 3000; return new MmsSmsDeliveryInfo( String.format(context.getString(R.string.delivery_toast_body), address), timeMillis); } finally { cursor.close(); } }
/** * Query the DB and return the number of undelivered messages (total for both SMS and MMS) * * @param context The context * @param threadIdResult A container to put the result in, according to the following rules: * threadIdResult[0] contains the thread id of the first message. threadIdResult[1] is nonzero * if the thread ids of all the messages are the same. You can pass in null for * threadIdResult. You can pass in a threadIdResult of size 1 to avoid the comparison of each * thread id. */ private static int getUndeliveredMessageCount(Context context, long[] threadIdResult) { Cursor undeliveredCursor = SqliteWrapper.query( context, context.getContentResolver(), UNDELIVERED_URI, new String[] {Mms.THREAD_ID}, "read=0", null, null); if (undeliveredCursor == null) { return 0; } int count = undeliveredCursor.getCount(); try { if (threadIdResult != null && undeliveredCursor.moveToFirst()) { threadIdResult[0] = undeliveredCursor.getLong(0); if (threadIdResult.length >= 2) { // Test to see if all the undelivered messages belong to the same thread. long firstId = threadIdResult[0]; while (undeliveredCursor.moveToNext()) { if (undeliveredCursor.getLong(0) != firstId) { firstId = 0; break; } } threadIdResult[1] = firstId; // non-zero if all ids are the same } } } finally { undeliveredCursor.close(); } return count; }
private static final MmsSmsNotificationInfo getSmsNewMessageNotificationInfo( Context context, Set<Long> threads) { ContentResolver resolver = context.getContentResolver(); Cursor cursor = SqliteWrapper.query( context, resolver, Sms.CONTENT_URI, SMS_STATUS_PROJECTION, NEW_INCOMING_SM_CONSTRAINT, null, Sms.DATE + " desc"); if (cursor == null) { return null; } try { if (!cursor.moveToFirst()) { return null; } String address = cursor.getString(COLUMN_SMS_ADDRESS); String body = cursor.getString(COLUMN_SMS_BODY); long threadId = cursor.getLong(COLUMN_THREAD_ID); long timeMillis = cursor.getLong(COLUMN_DATE); if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { Log.d( TAG, "getSmsNewMessageNotificationInfo: count=" + cursor.getCount() + ", first addr=" + address + ", thread_id=" + threadId); } MmsSmsNotificationInfo info = getNewMessageNotificationInfo( address, body, context, R.drawable.stat_notify_sms, null, threadId, timeMillis, cursor.getCount()); threads.add(threadId); while (cursor.moveToNext()) { threads.add(cursor.getLong(COLUMN_THREAD_ID)); } return info; } finally { cursor.close(); } }
/// M:Code analyze 009,add for setting the pending mms failed,mainly using after boot complete @{ public static void setPendingMmsFailed(final Context context) { MmsLog.d(MmsApp.TXN_TAG, "setPendingMmsFailed"); Cursor cursor = PduPersister.getPduPersister(context) .getPendingMessages(Long.MAX_VALUE /*System.currentTimeMillis()*/); if (cursor != null) { try { int count = cursor.getCount(); MmsLog.d(MmsApp.TXN_TAG, "setPendingMmsFailed: Pending Message Size=" + count); if (count == 0) { return; } DefaultRetryScheme scheme = new DefaultRetryScheme(context, 100); ContentValues values = null; int columnIndex = 0; int columnType = 0; int id = 0; int type = 0; while (cursor.moveToNext()) { columnIndex = cursor.getColumnIndexOrThrow(PendingMessages._ID); id = cursor.getInt(columnIndex); columnType = cursor.getColumnIndexOrThrow(PendingMessages.MSG_TYPE); type = cursor.getInt(columnType); MmsLog.d(MmsApp.TXN_TAG, "setPendingMmsFailed: type=" + type + "; MsgId=" + id); if (type == PduHeaders.MESSAGE_TYPE_SEND_REQ) { values = new ContentValues(2); values.put(PendingMessages.ERROR_TYPE, MmsSms.ERR_TYPE_GENERIC_PERMANENT); values.put(PendingMessages.RETRY_INDEX, scheme.getRetryLimit()); SqliteWrapper.update( context, context.getContentResolver(), PendingMessages.CONTENT_URI, values, PendingMessages._ID + "=" + id, null); } } } catch (SQLiteDiskIOException e) { // Ignore MmsLog.e( MmsApp.TXN_TAG, "SQLiteDiskIOException caught while set pending message failed", e); } finally { cursor.close(); } } else { MmsLog.d(MmsApp.TXN_TAG, "setPendingMmsFailed: no pending MMS."); } }
private void deleteMessages() { for (String uri : mSelectedUris) { if (mIsDeleteLockChecked || !mSelectedLockedUris.contains(uri)) { SqliteWrapper.delete( ManageMultiSelectAction.this, mContentResolver, Uri.parse(uri), null, null); } } Message msg = Message.obtain(); msg.what = SHOW_TOAST; msg.obj = getString(R.string.operate_success); mUiHandler.sendMessage(msg); }
private void copyToPhoneMemory(Cursor cursor) { String address = cursor.getString(cursor.getColumnIndexOrThrow("address")); String body = cursor.getString(cursor.getColumnIndexOrThrow("body")); Long date = cursor.getLong(cursor.getColumnIndexOrThrow("date")); try { if (isIncomingMessage(cursor)) { Sms.Inbox.addMessage(mContentResolver, address, body, null, date, true /* read */); } else { Sms.Sent.addMessage(mContentResolver, address, body, null, date); } } catch (SQLiteException e) { SqliteWrapper.checkSQLiteException(this, e); } }
/** * Move all messages that are in the outbox to the queued state * * @return The number of messages that were actually moved */ private int moveOutboxMessagesToQueuedBox() { ContentValues values = new ContentValues(1); values.put(Sms.TYPE, Sms.MESSAGE_TYPE_QUEUED); int messageCount = SqliteWrapper.update( getApplicationContext(), getContentResolver(), Outbox.CONTENT_URI, values, "type = " + Sms.MESSAGE_TYPE_OUTBOX, null); if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) { Log.v(TAG, "moveOutboxMessagesToQueuedBox messageCount: " + messageCount); } return messageCount; }
/** * Move all messages that are in the outbox to the failed state and set them to unread. * * @return The number of messages that were actually moved */ private int moveOutboxMessagesToFailedBox() { ContentValues values = new ContentValues(3); values.put(Sms.TYPE, Sms.MESSAGE_TYPE_FAILED); values.put(Sms.ERROR_CODE, SmsManager.RESULT_ERROR_GENERIC_FAILURE); values.put(Sms.READ, Integer.valueOf(0)); int messageCount = SqliteWrapper.update( getApplicationContext(), getContentResolver(), Outbox.CONTENT_URI, values, "type = " + Sms.MESSAGE_TYPE_OUTBOX, null); if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) { Log.v(TAG, "moveOutboxMessagesToFailedBox messageCount: " + messageCount); } return messageCount; }
private static long findThreadId(Context context, GenericPdu pdu, int type) { String messageId; if (type == MESSAGE_TYPE_DELIVERY_IND) { messageId = new String(((DeliveryInd) pdu).getMessageId()); } else { messageId = new String(((ReadOrigInd) pdu).getMessageId()); } StringBuilder sb = new StringBuilder('('); sb.append(Mms.MESSAGE_ID); sb.append('='); sb.append(DatabaseUtils.sqlEscapeString(messageId)); sb.append(" AND "); sb.append(Mms.MESSAGE_TYPE); sb.append('='); sb.append(PduHeaders.MESSAGE_TYPE_SEND_REQ); // TODO ContentResolver.query() appends closing ')' to the selection argument // sb.append(')'); Cursor cursor = SqliteWrapper.query( context, context.getContentResolver(), Mms.CONTENT_URI, new String[] {Mms.THREAD_ID}, sb.toString(), null, null); if (cursor != null) { try { if ((cursor.getCount() == 1) && cursor.moveToFirst()) { return cursor.getLong(0); } } finally { cursor.close(); } } return -1; }
private static long getDeliveryOrReadReportThreadId(Context context, GenericPdu pdu) { String messageId; if (pdu instanceof DeliveryInd) { messageId = new String(((DeliveryInd) pdu).getMessageId()); } else if (pdu instanceof ReadOrigInd) { messageId = new String(((ReadOrigInd) pdu).getMessageId()); } else { Rlog.e( TAG, "WAP Push data is neither delivery or read report type: " + pdu.getClass().getCanonicalName()); return -1L; } Cursor cursor = null; try { cursor = SqliteWrapper.query( context, context.getContentResolver(), Telephony.Mms.CONTENT_URI, new String[] {Telephony.Mms.THREAD_ID}, THREAD_ID_SELECTION, new String[] { DatabaseUtils.sqlEscapeString(messageId), Integer.toString(PduHeaders.MESSAGE_TYPE_SEND_REQ) }, null /*sortOrder*/); if (cursor != null && cursor.moveToFirst()) { return cursor.getLong(0); } } catch (SQLiteException e) { Rlog.e(TAG, "Failed to query delivery or read report thread id", e); } finally { if (cursor != null) { cursor.close(); } } return -1L; }
private void writeInboxMessage(long subId, byte[] pushData) { final GenericPdu pdu = new PduParser(pushData).parse(); if (pdu == null) { Rlog.e(TAG, "Invalid PUSH PDU"); } final PduPersister persister = PduPersister.getPduPersister(mContext); final int type = pdu.getMessageType(); try { switch (type) { case MESSAGE_TYPE_DELIVERY_IND: case MESSAGE_TYPE_READ_ORIG_IND: { final long threadId = getDeliveryOrReadReportThreadId(mContext, pdu); if (threadId == -1) { // The associated SendReq isn't found, therefore skip // processing this PDU. Rlog.e(TAG, "Failed to find delivery or read report's thread id"); break; } final Uri uri = persister.persist( pdu, Telephony.Mms.Inbox.CONTENT_URI, true /*createThreadId*/, true /*groupMmsEnabled*/, null /*preOpenedFiles*/); if (uri == null) { Rlog.e(TAG, "Failed to persist delivery or read report"); break; } // Update thread ID for ReadOrigInd & DeliveryInd. final ContentValues values = new ContentValues(1); values.put(Telephony.Mms.THREAD_ID, threadId); if (SqliteWrapper.update( mContext, mContext.getContentResolver(), uri, values, null /*where*/, null /*selectionArgs*/) != 1) { Rlog.e(TAG, "Failed to update delivery or read report thread id"); } break; } case MESSAGE_TYPE_NOTIFICATION_IND: { final NotificationInd nInd = (NotificationInd) pdu; Bundle configs = SmsManager.getSmsManagerForSubscriber(subId).getCarrierConfigValues(); if (configs != null && configs.getBoolean(SmsManager.MMS_CONFIG_APPEND_TRANSACTION_ID, false)) { final byte[] contentLocation = nInd.getContentLocation(); if ('=' == contentLocation[contentLocation.length - 1]) { byte[] transactionId = nInd.getTransactionId(); byte[] contentLocationWithId = new byte[contentLocation.length + transactionId.length]; System.arraycopy( contentLocation, 0, contentLocationWithId, 0, contentLocation.length); System.arraycopy( transactionId, 0, contentLocationWithId, contentLocation.length, transactionId.length); nInd.setContentLocation(contentLocationWithId); } } if (!isDuplicateNotification(mContext, nInd)) { final Uri uri = persister.persist( pdu, Telephony.Mms.Inbox.CONTENT_URI, true /*createThreadId*/, true /*groupMmsEnabled*/, null /*preOpenedFiles*/); if (uri == null) { Rlog.e(TAG, "Failed to save MMS WAP push notification ind"); } } else { Rlog.d( TAG, "Skip storing duplicate MMS WAP push notification ind: " + new String(nInd.getContentLocation())); } break; } default: Log.e(TAG, "Received unrecognized WAP Push PDU."); } } catch (MmsException e) { Log.e(TAG, "Failed to save MMS WAP push data: type=" + type, e); } catch (RuntimeException e) { Log.e(TAG, "Unexpected RuntimeException in persisting MMS WAP push data", e); } }
private void deleteFromSim(Cursor cursor) { String messageIndexString = cursor.getString(cursor.getColumnIndexOrThrow("index_on_icc")); Uri simUri = ICC_URI.buildUpon().appendPath(messageIndexString).build(); SqliteWrapper.delete(this, mContentResolver, simUri, null, null); }
private static final MmsSmsNotificationInfo getMmsNewMessageNotificationInfo( Context context, Set<Long> threads) { ContentResolver resolver = context.getContentResolver(); // This query looks like this when logged: // I/Database( 147): elapsedTime4Sql|/data/data/com.android.providers.telephony/databases/ // mmssms.db|0.362 ms|SELECT thread_id, date, _id, sub, sub_cs FROM pdu WHERE ((msg_box=1 // AND seen=0 AND (m_type=130 OR m_type=132))) ORDER BY date desc Cursor cursor = SqliteWrapper.query( context, resolver, Mms.CONTENT_URI, MMS_STATUS_PROJECTION, NEW_INCOMING_MM_CONSTRAINT, null, Mms.DATE + " desc"); if (cursor == null) { return null; } try { if (!cursor.moveToFirst()) { return null; } long msgId = cursor.getLong(COLUMN_MMS_ID); Uri msgUri = Mms.CONTENT_URI.buildUpon().appendPath(Long.toString(msgId)).build(); String address = AddressUtils.getFrom(context, msgUri); String subject = getMmsSubject(cursor.getString(COLUMN_SUBJECT), cursor.getInt(COLUMN_SUBJECT_CS)); long threadId = cursor.getLong(COLUMN_THREAD_ID); long timeMillis = cursor.getLong(COLUMN_DATE) * 1000; if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { Log.d( TAG, "getMmsNewMessageNotificationInfo: count=" + cursor.getCount() + ", first addr = " + address + ", thread_id=" + threadId); } MmsSmsNotificationInfo info = getNewMessageNotificationInfo( address, subject, context, R.drawable.stat_notify_mms, null, threadId, timeMillis, cursor.getCount()); threads.add(threadId); while (cursor.moveToNext()) { threads.add(cursor.getLong(COLUMN_THREAD_ID)); } return info; } finally { cursor.close(); } }
/** * Constructor that uses the default settings of the MMS Client. * * @param context The context of the MMS Client */ public TransactionSettings(Context context, String apnName) { if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) { Log.v(TAG, "TransactionSettings: apnName: " + apnName); } String selection = Telephony.Carriers.CURRENT + " IS NOT NULL"; String[] selectionArgs = null; if (!TextUtils.isEmpty(apnName)) { selection += " AND " + Telephony.Carriers.APN + "=?"; selectionArgs = new String[] {apnName.trim()}; } Cursor cursor = SqliteWrapper.query( context, context.getContentResolver(), Telephony.Carriers.CONTENT_URI, APN_PROJECTION, selection, selectionArgs, null); if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) { Log.v( TAG, "TransactionSettings looking for apn: " + selection + " returned: " + (cursor == null ? "null cursor" : (cursor.getCount() + " hits"))); } if (cursor == null) { Log.e(TAG, "Apn is not found in Database!"); return; } boolean sawValidApn = false; try { while (cursor.moveToNext() && TextUtils.isEmpty(mServiceCenter)) { // Read values from APN settings if (isValidApnType(cursor.getString(COLUMN_TYPE), PhoneConstants.APN_TYPE_MMS)) { sawValidApn = true; String mmsc = cursor.getString(COLUMN_MMSC); if (mmsc == null) { continue; } mServiceCenter = NetworkUtils.trimV4AddrZeros(mmsc.trim()); mProxyAddress = NetworkUtils.trimV4AddrZeros(cursor.getString(COLUMN_MMSPROXY)); if (isProxySet()) { String portString = cursor.getString(COLUMN_MMSPORT); try { mProxyPort = Integer.parseInt(portString); } catch (NumberFormatException e) { if (TextUtils.isEmpty(portString)) { Log.w(TAG, "mms port not set!"); } else { Log.e(TAG, "Bad port number format: " + portString, e); } } } } } } finally { cursor.close(); } Log.v(TAG, "APN setting: MMSC: " + mServiceCenter + " looked for: " + selection); if (sawValidApn && TextUtils.isEmpty(mServiceCenter)) { Log.e(TAG, "Invalid APN setting: MMSC is empty"); } }
public static void handleReadReport( final Context context, final Collection<Long> threadIds, final int status, final Runnable callback) { StringBuilder selectionBuilder = new StringBuilder( Mms.MESSAGE_TYPE + " = " + PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF + " AND " + Mms.READ + " = 0" + " AND " + Mms.READ_REPORT + " = " + PduHeaders.VALUE_YES); String[] selectionArgs = null; if (threadIds != null) { String threadIdSelection = null; StringBuilder buf = new StringBuilder(); selectionArgs = new String[threadIds.size()]; int i = 0; for (long threadId : threadIds) { if (i > 0) { buf.append(" OR "); } buf.append(Mms.THREAD_ID).append("=?"); selectionArgs[i++] = Long.toString(threadId); } threadIdSelection = buf.toString(); selectionBuilder.append(" AND (" + threadIdSelection + ")"); } final Cursor c = SqliteWrapper.query( context, context.getContentResolver(), Mms.Inbox.CONTENT_URI, new String[] {Mms._ID, Mms.MESSAGE_ID}, selectionBuilder.toString(), selectionArgs, null); if (c == null) { return; } final Map<String, String> map = new HashMap<String, String>(); try { if (c.getCount() == 0) { if (callback != null) { callback.run(); } return; } while (c.moveToNext()) { Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, c.getLong(0)); map.put(c.getString(1), AddressUtils.getFrom(context, uri)); } } finally { c.close(); } OnClickListener positiveListener = new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { for (final Map.Entry<String, String> entry : map.entrySet()) { MmsMessageSender.sendReadRec(context, entry.getValue(), entry.getKey(), status); } if (callback != null) { callback.run(); } dialog.dismiss(); } }; OnClickListener negativeListener = new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (callback != null) { callback.run(); } dialog.dismiss(); } }; OnCancelListener cancelListener = new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { if (callback != null) { callback.run(); } dialog.dismiss(); } }; confirmReadReportDialog(context, positiveListener, negativeListener, cancelListener); }
/** * Load APN settings from system * * @param context * @param apnName the optional APN name to match */ public static ApnSettings load(Context context, String apnName, int subId) throws ApnException { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "ApnSettings: apnName " + apnName); } // TODO: CURRENT semantics is currently broken in telephony. Revive this when it is fixed. // String selection = Telephony.Carriers.CURRENT + " IS NOT NULL"; String selection = null; String[] selectionArgs = null; apnName = apnName != null ? apnName.trim() : null; if (!TextUtils.isEmpty(apnName)) { // selection += " AND " + Telephony.Carriers.APN + "=?"; selection = Telephony.Carriers.APN + "=?"; selectionArgs = new String[] {apnName}; } Cursor cursor = null; try { cursor = SqliteWrapper.query( context, context.getContentResolver(), Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "/subId/" + subId), APN_PROJECTION, selection, selectionArgs, null /*sortOrder*/); if (cursor != null) { String mmscUrl = null; String proxyAddress = null; int proxyPort = -1; while (cursor.moveToNext()) { // Read values from APN settings if (isValidApnType(cursor.getString(COLUMN_TYPE), PhoneConstants.APN_TYPE_MMS)) { mmscUrl = trimWithNullCheck(cursor.getString(COLUMN_MMSC)); if (TextUtils.isEmpty(mmscUrl)) { continue; } mmscUrl = NetworkUtils.trimV4AddrZeros(mmscUrl); try { new URI(mmscUrl); } catch (URISyntaxException e) { throw new ApnException("Invalid MMSC url " + mmscUrl); } proxyAddress = trimWithNullCheck(cursor.getString(COLUMN_MMSPROXY)); if (!TextUtils.isEmpty(proxyAddress)) { proxyAddress = NetworkUtils.trimV4AddrZeros(proxyAddress); final String portString = trimWithNullCheck(cursor.getString(COLUMN_MMSPORT)); if (portString != null) { try { proxyPort = Integer.parseInt(portString); } catch (NumberFormatException e) { Log.e(TAG, "Invalid port " + portString); throw new ApnException("Invalid port " + portString); } } } return new ApnSettings(mmscUrl, proxyAddress, proxyPort, getDebugText(cursor)); } } } } finally { if (cursor != null) { cursor.close(); } } throw new ApnException("Can not find valid APN"); }
@Override protected Void doInBackground(Intent... intents) { Intent intent = intents[0]; Xlog.d( MmsApp.TXN_TAG, "do In Background, slotId=" + intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, 0)); // Get raw PDU push-data from the message and parse it byte[] pushData = intent.getByteArrayExtra("data"); PduParser parser = new PduParser(pushData); GenericPdu pdu = parser.parse(); if (null == pdu) { Log.e(TAG, "Invalid PUSH data"); return null; } PduPersister p = PduPersister.getPduPersister(mContext); ContentResolver cr = mContext.getContentResolver(); int type = pdu.getMessageType(); long threadId = -1; try { switch (type) { case MESSAGE_TYPE_DELIVERY_IND: Xlog.d(MmsApp.TXN_TAG, "type=MESSAGE_TYPE_DELIVERY_IND"); case MESSAGE_TYPE_READ_ORIG_IND: { if (type == MESSAGE_TYPE_READ_ORIG_IND) { Xlog.d(MmsApp.TXN_TAG, "type=MESSAGE_TYPE_READ_ORIG_IND"); } threadId = findThreadId(mContext, pdu, type); if (threadId == -1) { // The associated SendReq isn't found, therefore skip // processing this PDU. break; } Uri uri = p.persist(pdu, Inbox.CONTENT_URI); // Update thread ID for ReadOrigInd & DeliveryInd. ContentValues values = new ContentValues(1); values.put(Mms.THREAD_ID, threadId); SqliteWrapper.update(mContext, cr, uri, values, null, null); break; } case MESSAGE_TYPE_NOTIFICATION_IND: { Xlog.d(MmsApp.TXN_TAG, "type=MESSAGE_TYPE_NOTIFICATION_IND"); NotificationInd nInd = (NotificationInd) pdu; if (MmsConfig.getTransIdEnabled()) { byte[] contentLocation = nInd.getContentLocation(); if ('=' == contentLocation[contentLocation.length - 1]) { byte[] transactionId = nInd.getTransactionId(); byte[] contentLocationWithId = new byte[contentLocation.length + transactionId.length]; System.arraycopy( contentLocation, 0, contentLocationWithId, 0, contentLocation.length); System.arraycopy( transactionId, 0, contentLocationWithId, contentLocation.length, transactionId.length); nInd.setContentLocation(contentLocationWithId); } } if (!isDuplicateNotification(mContext, nInd)) { Uri uri = p.persist(pdu, Inbox.CONTENT_URI); // add for gemini if (FeatureOption.MTK_GEMINI_SUPPORT) { // update pdu ContentValues values = new ContentValues(2); SIMInfo si = SIMInfo.getSIMInfoBySlot( mContext, intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, -1)); if (null == si) { Xlog.e( MmsApp.TXN_TAG, "PushReceiver:SIMInfo is null for slot " + intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, -1)); break; } values.put(Mms.SIM_ID, si.mSimId); values.put(WapPush.SERVICE_ADDR, intent.getStringExtra(WapPush.SERVICE_ADDR)); SqliteWrapper.update(mContext, cr, uri, values, null, null); Xlog.d( MmsApp.TXN_TAG, "save notification slotId=" + intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, 0) + "\tsimId=" + si.mSimId + "\tsc=" + intent.getStringExtra(WapPush.SERVICE_ADDR) + "\taddr=" + intent.getStringExtra(WapPush.ADDR)); // update pending messages long msgId = 0; Cursor cursor = SqliteWrapper.query( mContext, mContext.getContentResolver(), uri, new String[] {Mms._ID}, null, null, null); if (cursor != null && cursor.getCount() == 1 && cursor.moveToFirst()) { try { msgId = cursor.getLong(0); Xlog.d(MmsApp.TXN_TAG, "msg id = " + msgId); } finally { cursor.close(); } } Uri.Builder uriBuilder = PendingMessages.CONTENT_URI.buildUpon(); uriBuilder.appendQueryParameter("protocol", "mms"); uriBuilder.appendQueryParameter("message", String.valueOf(msgId)); Cursor pendingCs = SqliteWrapper.query( mContext, mContext.getContentResolver(), uriBuilder.build(), null, null, null, null); if (pendingCs != null) { try { if ((pendingCs.getCount() == 1) && pendingCs.moveToFirst()) { ContentValues valuesforPending = new ContentValues(); valuesforPending.put(PendingMessages.SIM_ID, si.mSimId); int columnIndex = pendingCs.getColumnIndexOrThrow(PendingMessages._ID); long id = pendingCs.getLong(columnIndex); SqliteWrapper.update( mContext, mContext.getContentResolver(), PendingMessages.CONTENT_URI, valuesforPending, PendingMessages._ID + "=" + id, null); } else { Xlog.w( MmsApp.TXN_TAG, "can not find message to set pending sim id, msgId=" + msgId); } } finally { pendingCs.close(); } } } else { ContentValues value = new ContentValues(1); value.put(WapPush.SERVICE_ADDR, intent.getStringExtra(WapPush.SERVICE_ADDR)); SqliteWrapper.update(mContext, cr, uri, value, null, null); Xlog.d( MmsApp.TXN_TAG, "save notification," + "\tsc=" + intent.getStringExtra(WapPush.SERVICE_ADDR) + "\taddr=" + intent.getStringExtra(WapPush.ADDR)); } // Start service to finish the notification transaction. Intent svc = new Intent(mContext, TransactionService.class); svc.putExtra(TransactionBundle.URI, uri.toString()); svc.putExtra( TransactionBundle.TRANSACTION_TYPE, Transaction.NOTIFICATION_TRANSACTION); if (FeatureOption.MTK_GEMINI_SUPPORT) { SIMInfo si = SIMInfo.getSIMInfoBySlot( mContext, intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, -1)); if (null == si) { Xlog.e( MmsApp.TXN_TAG, "PushReceiver: SIMInfo is null for slot " + intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, -1)); break; } int simId = (int) si.mSimId; svc.putExtra(Phone.GEMINI_SIM_ID_KEY, simId); // svc.putExtra(Phone.GEMINI_SIM_ID_KEY, // intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, 0)); } mContext.startService(svc); } else if (LOCAL_LOGV) { Log.v( TAG, "Skip downloading duplicate message: " + new String(nInd.getContentLocation())); } break; } default: Log.e(TAG, "Received unrecognized PDU."); } } catch (MmsException e) { Log.e(TAG, "Failed to save the data from PUSH: type=" + type, e); } catch (RuntimeException e) { Log.e(TAG, "Unexpected RuntimeException.", e); } finally { raisePriority(mContext, false); Xlog.d(MmsApp.TXN_TAG, "Normal priority"); } if (LOCAL_LOGV) { Log.v(TAG, "PUSH Intent processed."); } return null; }
public void run() { Xlog.d(MmsApp.TXN_TAG, "NotificationTransaction: run()"); DownloadManager downloadManager = DownloadManager.getInstance(); // boolean autoDownload = downloadManager.isAuto(); // boolean dataSuspended = (MmsApp.getApplication().getTelephonyManager().getDataState() == // TelephonyManager.DATA_SUSPENDED); boolean autoDownload = false; boolean dataSuspended = false; // add for gemini if (FeatureOption.MTK_GEMINI_SUPPORT) { autoDownload = downloadManager.isAuto(mSimId); int datastate = MmsApp.getApplication() .getTelephonyManager() .getDataStateGemini(SIMInfo.getSlotById(mContext, mSimId)); dataSuspended = (datastate == TelephonyManager.DATA_SUSPENDED || datastate == TelephonyManager.DATA_DISCONNECTED); } else { autoDownload = downloadManager.isAuto(); dataSuspended = (MmsApp.getApplication().getTelephonyManager().getDataState() == TelephonyManager.DATA_SUSPENDED); } try { if (LOCAL_LOGV) { Log.v(TAG, "Notification transaction launched: " + this); } // By default, we set status to STATUS_DEFERRED because we // should response MMSC with STATUS_DEFERRED when we cannot // download a MM immediately. int status = STATUS_DEFERRED; // Check expiry state Date CurrentDate = new Date(System.currentTimeMillis()); Date ExpiryDate = new Date(mNotificationInd.getExpiry() * 1000); Xlog.d( MmsApp.TXN_TAG, "expiry time=" + ExpiryDate.toLocaleString() + "\t current=" + CurrentDate.toLocaleString()); // MTK_OP01_PROTECT_START /* String optr = SystemProperties.get("ro.operator.optr"); if (optr.equals("OP01")) { // Check Message size int msgSize = 0; Cursor cursor = SqliteWrapper.query(mContext, mContext.getContentResolver(), mUri, new String[] {Mms.MESSAGE_SIZE}, null, null, null); if (cursor != null && cursor.getCount() == 1 && cursor.moveToFirst()) { try{ msgSize = cursor.getInt(0); Xlog.v(MmsApp.TXN_TAG, "msg Size = " + msgSize); }finally{ cursor.close(); } } String netWorkType = null; int slotId = -1; if (FeatureOption.MTK_GEMINI_SUPPORT) { // convert sim id to slot id slotId = SIMInfo.getSlotById(mContext, mSimId); netWorkType = SystemProperties.get(slotId == 0 ? TelephonyProperties.PROPERTY_CS_NETWORK_TYPE : TelephonyProperties.PROPERTY_CS_NETWORK_TYPE_2); } else { netWorkType = SystemProperties.get(TelephonyProperties.PROPERTY_CS_NETWORK_TYPE); } boolean bTDNetwork = Integer.parseInt(netWorkType) > 2 ? true : false; if ((!bTDNetwork && MmsConfig.getReceiveMmsLimitFor2G() < msgSize/1024) || (bTDNetwork && MmsConfig.getReceiveMmsLimitForTD() < msgSize/1024)) { Xlog.v(MmsApp.TXN_TAG, "Message size exceed limitation, rejected."); status = STATUS_REJECTED; sendNotifyRespInd(status); return; } } */ // MTK_OP01_PROTECT_END // Don't try to download when data is suspended, as it will fail, so defer download if (!autoDownload || dataSuspended) { Xlog.d( MmsApp.TXN_TAG, "Not autoDownload! autoDonwload=" + autoDownload + ", dataSuspended=" + dataSuspended); if (FeatureOption.MTK_GEMINI_SUPPORT) { downloadManager.markState(mUri, DownloadManager.STATE_UNSTARTED, mSimId); } else { downloadManager.markState(mUri, DownloadManager.STATE_UNSTARTED); } sendNotifyRespInd(status); return; } if (FeatureOption.MTK_GEMINI_SUPPORT) { downloadManager.markState(mUri, DownloadManager.STATE_DOWNLOADING, mSimId); } else { downloadManager.markState(mUri, DownloadManager.STATE_DOWNLOADING); } if (LOCAL_LOGV) { Log.v(TAG, "Content-Location: " + mContentLocation); } byte[] retrieveConfData = null; // We should catch exceptions here to response MMSC // with STATUS_DEFERRED. try { Xlog.d(MmsApp.TXN_TAG, "NotificationTransaction: before getpdu"); retrieveConfData = getPdu(mContentLocation); Xlog.d(MmsApp.TXN_TAG, "NotificationTransaction: after getpdu"); } catch (IOException e) { mTransactionState.setState(FAILED); } if (retrieveConfData != null) { GenericPdu pdu = new PduParser(retrieveConfData).parse(); if ((pdu == null) || (pdu.getMessageType() != MESSAGE_TYPE_RETRIEVE_CONF)) { Log.e(TAG, "Invalid M-RETRIEVE.CONF PDU."); mTransactionState.setState(FAILED); status = STATUS_UNRECOGNIZED; } else { // Save the received PDU (must be a M-RETRIEVE.CONF). PduPersister p = PduPersister.getPduPersister(mContext); Uri uri = p.persist(pdu, Inbox.CONTENT_URI); Xlog.d(MmsApp.TXN_TAG, "PDU Saved, Uri=" + uri + "\nDelete Notify Ind, Uri=" + mUri); // add for gemini if (FeatureOption.MTK_GEMINI_SUPPORT) { ContentResolver cr = mContext.getContentResolver(); ContentValues values = new ContentValues(1); values.put(Mms.SIM_ID, mSimId); SqliteWrapper.update(mContext, cr, uri, values, null, null); } // set message size int messageSize = retrieveConfData.length; ContentValues sizeValue = new ContentValues(); sizeValue.put(Mms.MESSAGE_SIZE, messageSize); SqliteWrapper.update(mContext, mContext.getContentResolver(), uri, sizeValue, null, null); // We have successfully downloaded the new MM. Delete the // M-NotifyResp.ind from Inbox. String notifId = mUri.getLastPathSegment(); String msgId = uri.getLastPathSegment(); if (!notifId.equals(msgId)) { SqliteWrapper.delete(mContext, mContext.getContentResolver(), mUri, null, null); } // Notify observers with newly received MM. mUri = uri; status = STATUS_RETRIEVED; } } else { Xlog.e(MmsApp.TXN_TAG, "retrieveConfData is null"); mTransactionState.setState(FAILED); status = STATUS_UNRECOGNIZED; } // Check the status and update the result state of this Transaction. switch (status) { case STATUS_RETRIEVED: mTransactionState.setState(SUCCESS); break; case STATUS_DEFERRED: // STATUS_DEFERRED, may be a failed immediate retrieval. if (mTransactionState.getState() == INITIALIZED) { mTransactionState.setState(SUCCESS); } break; } // if the status is STATUS_UNRECOGNIZED, this happened when we don't get mms pdu from server, // this may be a server problem or network problem. // our policy is will retry later, so we must response a deferred status not this one. // otherwise the server may delete this mms, and when we retry it, it's another mms created by // server to // inform us that the old mms is not exist yet. if (status == STATUS_UNRECOGNIZED) { status = STATUS_DEFERRED; } sendNotifyRespInd(status); // Make sure this thread isn't over the limits in message count. Recycler.getMmsRecycler().deleteOldMessagesInSameThreadAsMessage(mContext, mUri); } catch (Throwable t) { Log.e(TAG, Log.getStackTraceString(t)); if (null != mUri) { Recycler.getMmsRecycler().deleteOldMessagesInSameThreadAsMessage(mContext, mUri); } } finally { mTransactionState.setContentUri(mUri); if (!autoDownload /*|| dataSuspended*/ /*comment this case for 81452*/) { // Always mark the transaction successful for deferred // download since any error here doesn't make sense. mTransactionState.setState(SUCCESS); } if (mTransactionState.getState() != SUCCESS) { mTransactionState.setState(FAILED); Xlog.w(MmsApp.TXN_TAG, "NotificationTransaction failed."); } notifyObservers(); } }
private void initModelFromUri(Uri uri) throws MmsException { ContentResolver cr = mContext.getContentResolver(); Cursor c = SqliteWrapper.query(mContext, cr, uri, null, null, null, null); if (c != null) { try { if (c.moveToFirst()) { String path; boolean isFromMms = isMmsUri(uri); // FIXME We suppose that there should be only two sources // of the audio, one is the media store, the other is // our MMS database. if (isFromMms) { path = c.getString(c.getColumnIndexOrThrow(Part._DATA)); mContentType = c.getString(c.getColumnIndexOrThrow(Part.CONTENT_TYPE)); } else { path = c.getString(c.getColumnIndexOrThrow(Audio.Media.DATA)); mContentType = c.getString(c.getColumnIndexOrThrow(Audio.Media.MIME_TYPE)); // Get more extras information which would be useful // to the user. String album = c.getString(c.getColumnIndexOrThrow("album")); if (!TextUtils.isEmpty(album)) { mExtras.put("album", album); } String artist = c.getString(c.getColumnIndexOrThrow("artist")); if (!TextUtils.isEmpty(artist)) { mExtras.put("artist", artist); } } if (FeatureOption.MTK_DRM_APP) { if (MessageUtils.checkUriContainsDrm(mContext, uri)) { path += ".dcf"; } } mSrc = path.substring(path.lastIndexOf('/') + 1).replace(' ', '_'); Log.i(TAG, "path: " + path); Log.i(TAG, "mSrc: " + mSrc); if (TextUtils.isEmpty(mContentType)) { throw new MmsException("Type of media is unknown."); } if (LOCAL_LOGV) { Log.v( TAG, "New AudioModel created:" + " mSrc=" + mSrc + " mContentType=" + mContentType + " mUri=" + uri + " mExtras=" + mExtras); } } else { throw new MmsException("Nothing found: " + uri); } } finally { c.close(); } } else { throw new MmsException("Bad URI: " + uri); } initMediaDuration(); }
private Uri storeMessage(Context context, SmsMessage[] msgs, int error) { SmsMessage sms = msgs[0]; // Store the message in the content provider. ContentValues values = extractContentValues(sms); values.put(Sms.ERROR_CODE, error); int pduCount = msgs.length; if (pduCount == 1) { // There is only one part, so grab the body directly. values.put(Inbox.BODY, replaceFormFeeds(sms.getDisplayMessageBody())); } else { // Build up the body from the parts. StringBuilder body = new StringBuilder(); for (int i = 0; i < pduCount; i++) { sms = msgs[i]; if (sms.mWrappedSmsMessage != null) { body.append(sms.getDisplayMessageBody()); } } values.put(Inbox.BODY, replaceFormFeeds(body.toString())); } // Make sure we've got a thread id so after the insert we'll be able to delete // excess messages. Long threadId = values.getAsLong(Sms.THREAD_ID); String address = values.getAsString(Sms.ADDRESS); // Code for debugging and easy injection of short codes, non email addresses, etc. // See Contact.isAlphaNumber() for further comments and results. // switch (count++ % 8) { // case 0: address = "AB12"; break; // case 1: address = "12"; break; // case 2: address = "Jello123"; break; // case 3: address = "T-Mobile"; break; // case 4: address = "Mobile1"; break; // case 5: address = "Dogs77"; break; // case 6: address = "****1"; break; // case 7: address = "#4#5#6#"; break; // } if (!TextUtils.isEmpty(address)) { Contact cacheContact = Contact.get(address, true); if (cacheContact != null) { address = cacheContact.getNumber(); } } else { address = getString(R.string.unknown_sender); values.put(Sms.ADDRESS, address); } if (((threadId == null) || (threadId == 0)) && (address != null)) { threadId = Conversation.getOrCreateThreadId(context, address); values.put(Sms.THREAD_ID, threadId); } ContentResolver resolver = context.getContentResolver(); Uri insertedUri = SqliteWrapper.insert(context, resolver, Inbox.CONTENT_URI, values); // Now make sure we're not over the limit in stored messages Recycler.getSmsRecycler().deleteOldMessagesByThreadId(context, threadId); MmsWidgetProvider.notifyDatasetChanged(context); return insertedUri; }
/** Does the actual work of rebuilding the draft cache. */ private synchronized void rebuildCache() { if (Log.isLoggable(LogTag.APP, Log.DEBUG)) { log("rebuildCache"); } HashSet<Long> oldDraftSet = mDraftSet; HashSet<Long> newDraftSet = new HashSet<Long>(oldDraftSet.size()); Cursor cursor = SqliteWrapper.query( mContext, mContext.getContentResolver(), MmsSms.CONTENT_DRAFT_URI, DRAFT_PROJECTION, null, null, null); if (cursor != null) { try { if (cursor.moveToFirst()) { for (; !cursor.isAfterLast(); cursor.moveToNext()) { long threadId = cursor.getLong(COLUMN_DRAFT_THREAD_ID); newDraftSet.add(threadId); if (Log.isLoggable(LogTag.APP, Log.DEBUG)) { log("rebuildCache: add tid=" + threadId); } } } } finally { cursor.close(); } } mDraftSet = newDraftSet; if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { dump(); } // If nobody's interested in finding out about changes, // just bail out early. if (mChangeListeners.size() < 1) { return; } // Find out which drafts were removed and added and notify // listeners. Set<Long> added = new HashSet<Long>(newDraftSet); added.removeAll(oldDraftSet); Set<Long> removed = new HashSet<Long>(oldDraftSet); removed.removeAll(newDraftSet); for (OnDraftChangedListener l : mChangeListeners) { for (long threadId : added) { l.onDraftChanged(threadId, true); } for (long threadId : removed) { l.onDraftChanged(threadId, false); } } }
public synchronized void sendFirstQueuedMessage() { boolean success = true; // get all the queued messages from the database final Uri uri = Uri.parse("content://sms/queued"); ContentResolver resolver = getContentResolver(); Cursor c = SqliteWrapper.query( this, resolver, uri, SEND_PROJECTION, null, null, "date ASC"); // date ASC so we send out in // same order the user tried // to send messages. if (c != null) { try { if (c.moveToFirst()) { String msgText = c.getString(SEND_COLUMN_BODY); String address = c.getString(SEND_COLUMN_ADDRESS); int threadId = c.getInt(SEND_COLUMN_THREAD_ID); int status = c.getInt(SEND_COLUMN_STATUS); int msgId = c.getInt(SEND_COLUMN_ID); Uri msgUri = ContentUris.withAppendedId(Sms.CONTENT_URI, msgId); SmsMessageSender sender = new SmsSingleRecipientSender( this, address, msgText, threadId, status == Sms.STATUS_PENDING, msgUri); if (LogTag.DEBUG_SEND || LogTag.VERBOSE || Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) { Log.v( TAG, "sendFirstQueuedMessage " + msgUri + ", address: " + address + ", threadId: " + threadId); } try { sender.sendMessage(SendingProgressTokenManager.NO_TOKEN); ; mSending = true; } catch (MmsException e) { Log.e(TAG, "sendFirstQueuedMessage: failed to send message " + msgUri + ", caught ", e); mSending = false; messageFailedToSend(msgUri, SmsManager.RESULT_ERROR_GENERIC_FAILURE); success = false; // Sending current message fails. Try to send more pending messages // if there is any. sendBroadcast( new Intent(SmsReceiverService.ACTION_SEND_MESSAGE, null, this, SmsReceiver.class)); } } } finally { c.close(); } } if (success) { // We successfully sent all the messages in the queue. We don't need to // be notified of any service changes any longer. unRegisterForServiceStateChanges(); } }