107ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor/* 207ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * Copyright (C) 2012 The Android Open Source Project 307ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * 407ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * Licensed under the Apache License, Version 2.0 (the "License"); 507ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * you may not use this file except in compliance with the License. 607ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * You may obtain a copy of the License at 707ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * 807ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * http://www.apache.org/licenses/LICENSE-2.0 907ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * 1007ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * Unless required by applicable law or agreed to in writing, software 1107ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * distributed under the License is distributed on an "AS IS" BASIS, 1207ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1307ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * See the License for the specific language governing permissions and 1407ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * limitations under the License. 1507ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor */ 1607ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 1707ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylorpackage com.android.mms.transaction; 1807ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 1907ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylorimport android.app.IntentService; 2007ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylorimport android.content.ContentUris; 2107ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylorimport android.content.ContentValues; 2207ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylorimport android.content.Context; 2307ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylorimport android.content.Intent; 2407ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylorimport android.database.Cursor; 2507ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylorimport android.database.sqlite.SqliteWrapper; 2607ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylorimport android.net.Uri; 2707ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylorimport android.provider.Telephony.Sms; 2807ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylorimport android.provider.Telephony.Sms.Inbox; 2907ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylorimport android.telephony.SmsMessage; 3007ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylorimport android.util.Log; 3107ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 32d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.LogTag; 33d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chen 3407ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor/** 3507ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * Service that gets started by the MessageStatusReceiver when a message status report is 3607ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor * received. 3707ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor */ 3807ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylorpublic class MessageStatusService extends IntentService { 3907ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor private static final String[] ID_PROJECTION = new String[] { Sms._ID }; 4007ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor private static final String LOG_TAG = "MessageStatusReceiver"; 4107ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor private static final Uri STATUS_URI = Uri.parse("content://sms/status"); 4207ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 4307ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor public MessageStatusService() { 4407ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor // Class name will be the thread name. 4507ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor super(MessageStatusService.class.getName()); 4607ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 4707ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor // Intent should be redelivered if the process gets killed before completing the job. 4807ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor setIntentRedelivery(true); 4907ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor } 5007ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 5107ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor @Override 5207ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor protected void onHandleIntent(Intent intent) { 5307ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor // This method is called on a worker thread. 5407ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 5507ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor Uri messageUri = intent.getData(); 5607ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor byte[] pdu = intent.getByteArrayExtra("pdu"); 5707ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor String format = intent.getStringExtra("format"); 5807ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 5907ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor SmsMessage message = updateMessageStatus(this, messageUri, pdu, format); 6007ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 61c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev // Called on a background thread, so it's OK to block. 62c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev if (message != null && message.getStatus() < Sms.STATUS_PENDING) { 63c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev MessagingNotification.blockingUpdateNewMessageIndicator(this, 64c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev MessagingNotification.THREAD_NONE, message.isStatusReportMessage()); 65c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev } 6607ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor } 6707ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 6807ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor private SmsMessage updateMessageStatus(Context context, Uri messageUri, byte[] pdu, 6907ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor String format) { 7007ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor SmsMessage message = SmsMessage.createFromPdu(pdu, format); 7107ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor if (message == null) { 7207ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor return null; 7307ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor } 7407ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor // Create a "status/#" URL and use it to update the 7507ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor // message's status in the database. 7607ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(), 7707ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor messageUri, ID_PROJECTION, null, null, null); 7807ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 7907ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor try { 8007ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor if (cursor.moveToFirst()) { 8107ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor int messageId = cursor.getInt(0); 8207ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 8307ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor Uri updateUri = ContentUris.withAppendedId(STATUS_URI, messageId); 8407ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor int status = message.getStatus(); 8507ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor boolean isStatusReport = message.isStatusReportMessage(); 8607ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor ContentValues contentValues = new ContentValues(2); 8707ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 8807ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor if (Log.isLoggable(LogTag.TAG, Log.DEBUG)) { 8907ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor log("updateMessageStatus: msgUrl=" + messageUri + ", status=" + status + 9007ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor ", isStatusReport=" + isStatusReport); 9107ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor } 9207ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 9307ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor contentValues.put(Sms.STATUS, status); 9407ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor contentValues.put(Inbox.DATE_SENT, System.currentTimeMillis()); 9507ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor SqliteWrapper.update(context, context.getContentResolver(), 9607ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor updateUri, contentValues, null, null); 9707ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor } else { 9807ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor error("Can't find message for status update: " + messageUri); 9907ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor } 10007ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor } finally { 10107ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor cursor.close(); 10207ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor } 10307ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor return message; 10407ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor } 10507ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 10607ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor private void error(String message) { 10707ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor Log.e(LOG_TAG, "[MessageStatusReceiver] " + message); 10807ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor } 10907ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor 11007ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor private void log(String message) { 11107ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor Log.d(LOG_TAG, "[MessageStatusReceiver] " + message); 11207ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor } 11307ddb5c577a10e5aa3b4442426a055f3b95d5202Tom Taylor} 114