172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/*
272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2007-2008 Esmertec AG.
372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2007-2008 The Android Open Source Project
472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * you may not use this file except in compliance with the License.
772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * You may obtain a copy of the License at
872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
1072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
1172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * See the License for the specific language governing permissions and
1572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * limitations under the License.
1672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
1772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
1872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpackage com.android.mms.transaction;
1972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
2072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport static android.content.Intent.ACTION_BOOT_COMPLETED;
21009ad1b491c876feadb50964645c38e002a114a1David Braunimport static android.provider.Telephony.Sms.Intents.SMS_DELIVER_ACTION;
2237321876549776417f035118f157d9531f73de6bWink Saville
2304db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylorimport java.util.Calendar;
2404db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylorimport java.util.GregorianCalendar;
2504db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor
2672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.Activity;
2772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.Service;
2872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.ContentResolver;
2972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.ContentUris;
3072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.ContentValues;
3172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Context;
3272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Intent;
33cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylorimport android.content.IntentFilter;
3472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.database.Cursor;
35d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.database.sqlite.SqliteWrapper;
3672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.net.Uri;
3772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.Handler;
3872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.HandlerThread;
3972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.IBinder;
4072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.Looper;
4172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.Message;
4272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.Process;
43f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Sms;
44f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Sms.Inbox;
45f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Sms.Intents;
46f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Sms.Outbox;
4772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.telephony.ServiceState;
4837321876549776417f035118f157d9531f73de6bWink Savilleimport android.telephony.SmsManager;
4937321876549776417f035118f157d9531f73de6bWink Savilleimport android.telephony.SmsMessage;
506a7ba7cf4d775dbb29f3cafbee67d823149da5f1Naveen Kallaimport android.text.TextUtils;
5172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Log;
5272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.widget.Toast;
5372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
54f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport com.android.internal.telephony.TelephonyIntents;
55812391ad832f3fdac054ad3a50af563da16e99b5Wei Huangimport com.android.mms.LogTag;
569dc65e65a3968cfdca8d4611eba93cf2e0a1df05David Braunimport com.android.mms.MmsConfig;
57d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.R;
58d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.data.Contact;
59d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.data.Conversation;
60d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.ui.ClassZeroActivity;
61d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.util.Recycler;
62d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.util.SendingProgressTokenManager;
63d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.widget.MmsWidgetProvider;
64d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.MmsException;
6537321876549776417f035118f157d9531f73de6bWink Saville
6672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/**
6772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * This service essentially plays the role of a "worker thread", allowing us to store
6872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * incoming messages to the database, update notifications, etc. without blocking the
6972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * main thread that SmsReceiver runs on.
7072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
7172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpublic class SmsReceiverService extends Service {
7272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final String TAG = "SmsReceiverService";
7372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
7472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private ServiceHandler mServiceHandler;
7572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private Looper mServiceLooper;
7652b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao    private boolean mSending;
7772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
7872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static final String MESSAGE_SENT_ACTION =
7972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        "com.android.mms.transaction.MESSAGE_SENT";
8072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
8152b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao    // Indicates next message can be picked up and sent out.
8252b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao    public static final String EXTRA_MESSAGE_SENT_SEND_NEXT ="SendNextMsg";
8352b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao
8452b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao    public static final String ACTION_SEND_MESSAGE =
85087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen            "com.android.mms.transaction.SEND_MESSAGE";
86087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen    public static final String ACTION_SEND_INACTIVE_MESSAGE =
87087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen            "com.android.mms.transaction.SEND_INACTIVE_MESSAGE";
8852b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao
8972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // This must match the column IDs below.
9072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final String[] SEND_PROJECTION = new String[] {
9172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Sms._ID,        //0
9272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Sms.THREAD_ID,  //1
9372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Sms.ADDRESS,    //2
9472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Sms.BODY,       //3
9552b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao        Sms.STATUS,     //4
9672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
9772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    };
9872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
99f31df323b2dc4b668d91b24dd3a5d34f5ccbb14cTom Taylor    public Handler mToastHandler = new Handler();
10072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
10172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // This must match SEND_PROJECTION.
10272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int SEND_COLUMN_ID         = 0;
10372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int SEND_COLUMN_THREAD_ID  = 1;
10472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int SEND_COLUMN_ADDRESS    = 2;
10572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int SEND_COLUMN_BODY       = 3;
10652b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao    private static final int SEND_COLUMN_STATUS     = 4;
10772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
10872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private int mResultCode;
109f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor
11072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
11172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public void onCreate() {
112f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor        // Temporarily removed for this duplicate message track down.
113c33ee154b6fd872439fd24a073f947339bbe4d22Tom Taylor//        if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) {
114f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor//            Log.v(TAG, "onCreate");
115f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor//        }
11672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
11772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Start up the thread running the service.  Note that we create a
11872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // separate thread because the service normally runs in the process's
11972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // main thread, which we don't want to block.
12072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        HandlerThread thread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
12172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        thread.start();
12272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
12372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mServiceLooper = thread.getLooper();
12472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mServiceHandler = new ServiceHandler(mServiceLooper);
12572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
12672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
12772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
12835de139283bfeca8b2360c8b13b9cd8dee8e039bTom Taylor    public int onStartCommand(Intent intent, int flags, int startId) {
129f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor        // Temporarily removed for this duplicate message track down.
13072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
1312c77f17bc77af92e57c82cc1bfa44de2979e505aTom Taylor        mResultCode = intent != null ? intent.getIntExtra("result", 0) : 0;
13272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
13368be4f572123274aa67e13544482ca4d99e7b235Tom Taylor        if (mResultCode != 0) {
1340856dec418d9838e09b1609439279e248355e0c4Tom Taylor            Log.v(TAG, "onStart: #" + startId + " mResultCode: " + mResultCode +
1350856dec418d9838e09b1609439279e248355e0c4Tom Taylor                    " = " + translateResultCode(mResultCode));
1360856dec418d9838e09b1609439279e248355e0c4Tom Taylor        }
1370856dec418d9838e09b1609439279e248355e0c4Tom Taylor
13872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Message msg = mServiceHandler.obtainMessage();
13972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        msg.arg1 = startId;
14072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        msg.obj = intent;
14172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mServiceHandler.sendMessage(msg);
14235de139283bfeca8b2360c8b13b9cd8dee8e039bTom Taylor        return Service.START_NOT_STICKY;
14372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
14472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
1450856dec418d9838e09b1609439279e248355e0c4Tom Taylor    private static String translateResultCode(int resultCode) {
1460856dec418d9838e09b1609439279e248355e0c4Tom Taylor        switch (resultCode) {
1470856dec418d9838e09b1609439279e248355e0c4Tom Taylor            case Activity.RESULT_OK:
1480856dec418d9838e09b1609439279e248355e0c4Tom Taylor                return "Activity.RESULT_OK";
1490856dec418d9838e09b1609439279e248355e0c4Tom Taylor            case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
1500856dec418d9838e09b1609439279e248355e0c4Tom Taylor                return "SmsManager.RESULT_ERROR_GENERIC_FAILURE";
1510856dec418d9838e09b1609439279e248355e0c4Tom Taylor            case SmsManager.RESULT_ERROR_RADIO_OFF:
1520856dec418d9838e09b1609439279e248355e0c4Tom Taylor                return "SmsManager.RESULT_ERROR_RADIO_OFF";
1530856dec418d9838e09b1609439279e248355e0c4Tom Taylor            case SmsManager.RESULT_ERROR_NULL_PDU:
1540856dec418d9838e09b1609439279e248355e0c4Tom Taylor                return "SmsManager.RESULT_ERROR_NULL_PDU";
1550856dec418d9838e09b1609439279e248355e0c4Tom Taylor            case SmsManager.RESULT_ERROR_NO_SERVICE:
1560856dec418d9838e09b1609439279e248355e0c4Tom Taylor                return "SmsManager.RESULT_ERROR_NO_SERVICE";
1570856dec418d9838e09b1609439279e248355e0c4Tom Taylor            case SmsManager.RESULT_ERROR_LIMIT_EXCEEDED:
1580856dec418d9838e09b1609439279e248355e0c4Tom Taylor                return "SmsManager.RESULT_ERROR_LIMIT_EXCEEDED";
1590856dec418d9838e09b1609439279e248355e0c4Tom Taylor            case SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE:
1600856dec418d9838e09b1609439279e248355e0c4Tom Taylor                return "SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE";
1610856dec418d9838e09b1609439279e248355e0c4Tom Taylor            default:
1620856dec418d9838e09b1609439279e248355e0c4Tom Taylor                return "Unknown error code";
1630856dec418d9838e09b1609439279e248355e0c4Tom Taylor        }
1640856dec418d9838e09b1609439279e248355e0c4Tom Taylor    }
1650856dec418d9838e09b1609439279e248355e0c4Tom Taylor
16672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
16772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public void onDestroy() {
168f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor        // Temporarily removed for this duplicate message track down.
169c33ee154b6fd872439fd24a073f947339bbe4d22Tom Taylor//        if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) {
170f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor//            Log.v(TAG, "onDestroy");
171f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor//        }
17272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mServiceLooper.quit();
17372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
17472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
17572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
17672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public IBinder onBind(Intent intent) {
17772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return null;
17872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
17972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
18072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private final class ServiceHandler extends Handler {
18172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public ServiceHandler(Looper looper) {
18272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            super(looper);
18372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
18472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
18572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        /**
18672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project         * Handle incoming transaction requests.
1870d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang         * The incoming requests are initiated by the MMSC Server or by the MMS Client itself.
18872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project         */
18972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        @Override
19072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public void handleMessage(Message msg) {
19172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            int serviceId = msg.arg1;
19272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Intent intent = (Intent)msg.obj;
1930856dec418d9838e09b1609439279e248355e0c4Tom Taylor            if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
1940d2c0042be90f42635e3bc301f2a2e37460e6344Tom Taylor                Log.v(TAG, "handleMessage serviceId: " + serviceId + " intent: " + intent);
1950d2c0042be90f42635e3bc301f2a2e37460e6344Tom Taylor            }
1969dc65e65a3968cfdca8d4611eba93cf2e0a1df05David Braun            if (intent != null && MmsConfig.isSmsEnabled(getApplicationContext())) {
1972c77f17bc77af92e57c82cc1bfa44de2979e505aTom Taylor                String action = intent.getAction();
1982c77f17bc77af92e57c82cc1bfa44de2979e505aTom Taylor
199161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor                int error = intent.getIntExtra("errorCode", 0);
200161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor
2010856dec418d9838e09b1609439279e248355e0c4Tom Taylor                if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
2020d2c0042be90f42635e3bc301f2a2e37460e6344Tom Taylor                    Log.v(TAG, "handleMessage action: " + action + " error: " + error);
2030d2c0042be90f42635e3bc301f2a2e37460e6344Tom Taylor                }
2040d2c0042be90f42635e3bc301f2a2e37460e6344Tom Taylor
2052c77f17bc77af92e57c82cc1bfa44de2979e505aTom Taylor                if (MESSAGE_SENT_ACTION.equals(intent.getAction())) {
206161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor                    handleSmsSent(intent, error);
207009ad1b491c876feadb50964645c38e002a114a1David Braun                } else if (SMS_DELIVER_ACTION.equals(action)) {
208161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor                    handleSmsReceived(intent, error);
2092c77f17bc77af92e57c82cc1bfa44de2979e505aTom Taylor                } else if (ACTION_BOOT_COMPLETED.equals(action)) {
2102c77f17bc77af92e57c82cc1bfa44de2979e505aTom Taylor                    handleBootCompleted();
211f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylor                } else if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(action)) {
2122c77f17bc77af92e57c82cc1bfa44de2979e505aTom Taylor                    handleServiceStateChanged(intent);
21352b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao                } else if (ACTION_SEND_MESSAGE.endsWith(action)) {
21452b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao                    handleSendMessage();
215087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen                } else if (ACTION_SEND_INACTIVE_MESSAGE.equals(action)) {
216087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen                    handleSendInactiveMessage();
2172c77f17bc77af92e57c82cc1bfa44de2979e505aTom Taylor                }
21872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
21972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // NOTE: We MUST not call stopSelf() directly, since we need to
22072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // make sure the wake lock acquired by AlertReceiver is released.
22172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            SmsReceiver.finishStartingService(SmsReceiverService.this, serviceId);
22272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
22372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
22472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
22572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void handleServiceStateChanged(Intent intent) {
22672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // If service just returned, start sending out the queued messages
22772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ServiceState serviceState = ServiceState.newFromBundle(intent.getExtras());
22872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (serviceState.getState() == ServiceState.STATE_IN_SERVICE) {
22972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            sendFirstQueuedMessage();
23072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
23172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
23272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
23352b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao    private void handleSendMessage() {
23452b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao        if (!mSending) {
23552b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao            sendFirstQueuedMessage();
23652b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao        }
23752b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao    }
23852b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao
239087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen    private void handleSendInactiveMessage() {
240087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen        // Inactive messages includes all messages in outbox and queued box.
241087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen        moveOutboxMessagesToQueuedBox();
242087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen        sendFirstQueuedMessage();
243087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen    }
244087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen
24572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public synchronized void sendFirstQueuedMessage() {
246cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor        boolean success = true;
24772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // get all the queued messages from the database
24872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        final Uri uri = Uri.parse("content://sms/queued");
24972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ContentResolver resolver = getContentResolver();
25072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Cursor c = SqliteWrapper.query(this, resolver, uri,
25123142979f43786098655229416cf1d07c5f78e09Tom Taylor                        SEND_PROJECTION, null, null, "date ASC");   // date ASC so we send out in
25223142979f43786098655229416cf1d07c5f78e09Tom Taylor                                                                    // same order the user tried
25323142979f43786098655229416cf1d07c5f78e09Tom Taylor                                                                    // to send messages.
25472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (c != null) {
25572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            try {
25672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (c.moveToFirst()) {
25772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    String msgText = c.getString(SEND_COLUMN_BODY);
25852b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao                    String address = c.getString(SEND_COLUMN_ADDRESS);
25972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    int threadId = c.getInt(SEND_COLUMN_THREAD_ID);
26052b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao                    int status = c.getInt(SEND_COLUMN_STATUS);
26172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
2620d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang                    int msgId = c.getInt(SEND_COLUMN_ID);
2630d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang                    Uri msgUri = ContentUris.withAppendedId(Sms.CONTENT_URI, msgId);
2640d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang
2654020be563f457ed2251b43928f14770246c886a2Tom Taylor                    SmsMessageSender sender = new SmsSingleRecipientSender(this,
2664020be563f457ed2251b43928f14770246c886a2Tom Taylor                            address, msgText, threadId, status == Sms.STATUS_PENDING,
2674020be563f457ed2251b43928f14770246c886a2Tom Taylor                            msgUri);
2684020be563f457ed2251b43928f14770246c886a2Tom Taylor
269a0bda6a838d0c9bff996aa39d4f9750faa00addaTom Taylor                    if (LogTag.DEBUG_SEND ||
270a0bda6a838d0c9bff996aa39d4f9750faa00addaTom Taylor                            LogTag.VERBOSE ||
271a0bda6a838d0c9bff996aa39d4f9750faa00addaTom Taylor                            Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
2724020be563f457ed2251b43928f14770246c886a2Tom Taylor                        Log.v(TAG, "sendFirstQueuedMessage " + msgUri +
2730d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang                                ", address: " + address +
274858d59e9f4b0839ee014e52e0744ea910d9830ffWei Huang                                ", threadId: " + threadId);
2750d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang                    }
276858d59e9f4b0839ee014e52e0744ea910d9830ffWei Huang
27772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    try {
27852b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao                        sender.sendMessage(SendingProgressTokenManager.NO_TOKEN);;
27952b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao                        mSending = true;
28067ec6c54e11c19caf894b4ffce7250fb3fd96d30Wei Huang                    } catch (MmsException e) {
28167ec6c54e11c19caf894b4ffce7250fb3fd96d30Wei Huang                        Log.e(TAG, "sendFirstQueuedMessage: failed to send message " + msgUri
28267ec6c54e11c19caf894b4ffce7250fb3fd96d30Wei Huang                                + ", caught ", e);
28313848bd88f29a358d13c2ce49f5c90c5858296f2Tom Taylor                        mSending = false;
28413848bd88f29a358d13c2ce49f5c90c5858296f2Tom Taylor                        messageFailedToSend(msgUri, SmsManager.RESULT_ERROR_GENERIC_FAILURE);
285cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor                        success = false;
286ddd2fdd5e80aa9d689c9ed982e1e003028fa8628Bin Li                        // Sending current message fails. Try to send more pending messages
287ddd2fdd5e80aa9d689c9ed982e1e003028fa8628Bin Li                        // if there is any.
288ddd2fdd5e80aa9d689c9ed982e1e003028fa8628Bin Li                        sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE,
289ddd2fdd5e80aa9d689c9ed982e1e003028fa8628Bin Li                                null,
290ddd2fdd5e80aa9d689c9ed982e1e003028fa8628Bin Li                                this,
291ddd2fdd5e80aa9d689c9ed982e1e003028fa8628Bin Li                                SmsReceiver.class));
29272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
29372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
29472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } finally {
29572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                c.close();
29672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
29772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
298cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor        if (success) {
299cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor            // We successfully sent all the messages in the queue. We don't need to
300cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor            // be notified of any service changes any longer.
301cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor            unRegisterForServiceStateChanges();
302cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor        }
30372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
30472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
305161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor    private void handleSmsSent(Intent intent, int error) {
30672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Uri uri = intent.getData();
30752b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao        mSending = false;
30852b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao        boolean sendNextMsg = intent.getBooleanExtra(EXTRA_MESSAGE_SENT_SEND_NEXT, false);
30972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
310c33ee154b6fd872439fd24a073f947339bbe4d22Tom Taylor        if (LogTag.DEBUG_SEND) {
311a0bda6a838d0c9bff996aa39d4f9750faa00addaTom Taylor            Log.v(TAG, "handleSmsSent uri: " + uri + " sendNextMsg: " + sendNextMsg +
312a0bda6a838d0c9bff996aa39d4f9750faa00addaTom Taylor                    " mResultCode: " + mResultCode +
313a0bda6a838d0c9bff996aa39d4f9750faa00addaTom Taylor                    " = " + translateResultCode(mResultCode) + " error: " + error);
314c33ee154b6fd872439fd24a073f947339bbe4d22Tom Taylor        }
315c33ee154b6fd872439fd24a073f947339bbe4d22Tom Taylor
31672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (mResultCode == Activity.RESULT_OK) {
317a0bda6a838d0c9bff996aa39d4f9750faa00addaTom Taylor            if (LogTag.DEBUG_SEND || Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
318a0bda6a838d0c9bff996aa39d4f9750faa00addaTom Taylor                Log.v(TAG, "handleSmsSent move message to sent folder uri: " + uri);
319f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor            }
320161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor            if (!Sms.moveMessageToFolder(this, uri, Sms.MESSAGE_TYPE_SENT, error)) {
3210d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang                Log.e(TAG, "handleSmsSent: failed to move message " + uri + " to sent folder");
3220d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang            }
32352b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao            if (sendNextMsg) {
32452b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao                sendFirstQueuedMessage();
32552b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao            }
32672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
3270d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang            // Update the notification for failed messages since they may be deleted.
328b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor            MessagingNotification.nonBlockingUpdateSendFailedNotification(this);
32972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else if ((mResultCode == SmsManager.RESULT_ERROR_RADIO_OFF) ||
33072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                (mResultCode == SmsManager.RESULT_ERROR_NO_SERVICE)) {
331f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor            if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
332f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor                Log.v(TAG, "handleSmsSent: no service, queuing message w/ uri: " + uri);
333f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor            }
334cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor            // We got an error with no service or no radio. Register for state changes so
335cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor            // when the status of the connection/radio changes, we can try to send the
336cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor            // queued up messages.
337cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor            registerForServiceStateChanges();
338cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor            // We couldn't send the message, put in the queue to retry later.
339161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor            Sms.moveMessageToFolder(this, uri, Sms.MESSAGE_TYPE_QUEUED, error);
340f31df323b2dc4b668d91b24dd3a5d34f5ccbb14cTom Taylor            mToastHandler.post(new Runnable() {
341f31df323b2dc4b668d91b24dd3a5d34f5ccbb14cTom Taylor                public void run() {
342f31df323b2dc4b668d91b24dd3a5d34f5ccbb14cTom Taylor                    Toast.makeText(SmsReceiverService.this, getString(R.string.message_queued),
343f31df323b2dc4b668d91b24dd3a5d34f5ccbb14cTom Taylor                            Toast.LENGTH_SHORT).show();
344f31df323b2dc4b668d91b24dd3a5d34f5ccbb14cTom Taylor                }
345f31df323b2dc4b668d91b24dd3a5d34f5ccbb14cTom Taylor            });
346f97cdd928bbc1953d422466d62807f07ae66119eNaveen Kalla        } else if (mResultCode == SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE) {
34748aacaa96f6864172ac7657380f4fcb17ba24431Jeevaka Badrappan            messageFailedToSend(uri, mResultCode);
3483c6eacd7f75aef4109f6ba8f1fbf2c957bd58ae2The Android Open Source Project            mToastHandler.post(new Runnable() {
3493c6eacd7f75aef4109f6ba8f1fbf2c957bd58ae2The Android Open Source Project                public void run() {
3503c6eacd7f75aef4109f6ba8f1fbf2c957bd58ae2The Android Open Source Project                    Toast.makeText(SmsReceiverService.this, getString(R.string.fdn_check_failure),
3513c6eacd7f75aef4109f6ba8f1fbf2c957bd58ae2The Android Open Source Project                            Toast.LENGTH_SHORT).show();
3523c6eacd7f75aef4109f6ba8f1fbf2c957bd58ae2The Android Open Source Project                }
3533c6eacd7f75aef4109f6ba8f1fbf2c957bd58ae2The Android Open Source Project            });
35472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
35513848bd88f29a358d13c2ce49f5c90c5858296f2Tom Taylor            messageFailedToSend(uri, error);
35652b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao            if (sendNextMsg) {
35752b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao                sendFirstQueuedMessage();
35852b0fc717011d84dd25c1e88998eaae97c8161a8Bai Tao            }
35972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
36072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
36172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
36213848bd88f29a358d13c2ce49f5c90c5858296f2Tom Taylor    private void messageFailedToSend(Uri uri, int error) {
363c33ee154b6fd872439fd24a073f947339bbe4d22Tom Taylor        if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) {
364c33ee154b6fd872439fd24a073f947339bbe4d22Tom Taylor            Log.v(TAG, "messageFailedToSend msg failed uri: " + uri + " error: " + error);
36513848bd88f29a358d13c2ce49f5c90c5858296f2Tom Taylor        }
36613848bd88f29a358d13c2ce49f5c90c5858296f2Tom Taylor        Sms.moveMessageToFolder(this, uri, Sms.MESSAGE_TYPE_FAILED, error);
36713848bd88f29a358d13c2ce49f5c90c5858296f2Tom Taylor        MessagingNotification.notifySendFailed(getApplicationContext(), true);
36813848bd88f29a358d13c2ce49f5c90c5858296f2Tom Taylor    }
36913848bd88f29a358d13c2ce49f5c90c5858296f2Tom Taylor
370161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor    private void handleSmsReceived(Intent intent, int error) {
37172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        SmsMessage[] msgs = Intents.getMessagesFromIntent(intent);
372104d391ddcc251c4c26975c093d2df5dea9b15c1Tom Taylor        String format = intent.getStringExtra("format");
373104d391ddcc251c4c26975c093d2df5dea9b15c1Tom Taylor        Uri messageUri = insertMessage(this, msgs, error, format);
37472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
375c33ee154b6fd872439fd24a073f947339bbe4d22Tom Taylor        if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) {
3760d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang            SmsMessage sms = msgs[0];
3770d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang            Log.v(TAG, "handleSmsReceived" + (sms.isReplace() ? "(replace)" : "") +
37823142979f43786098655229416cf1d07c5f78e09Tom Taylor                    " messageUri: " + messageUri +
3790d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang                    ", address: " + sms.getOriginatingAddress() +
3800d798c0853ead129b245ac7e8700f3a4aba92ecbWei Huang                    ", body: " + sms.getMessageBody());
381f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor        }
382f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor
38372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (messageUri != null) {
384c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            long threadId = MessagingNotification.getSmsThreadId(this, messageUri);
3853b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor            // Called off of the UI thread so ok to block.
386d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor            Log.d(TAG, "handleSmsReceived messageUri: " + messageUri + " threadId: " + threadId);
387c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev            MessagingNotification.blockingUpdateNewMessageIndicator(this, threadId, false);
38872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
38972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
39072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
39172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void handleBootCompleted() {
3927015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        // Some messages may get stuck in the outbox. At this point, they're probably irrelevant
3937015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        // to the user, so mark them as failed and notify the user, who can then decide whether to
3947015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        // resend them manually.
3957015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        int numMoved = moveOutboxMessagesToFailedBox();
3967015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        if (numMoved > 0) {
3977015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev            MessagingNotification.notifySendFailed(getApplicationContext(), true);
3987015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        }
3997015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev
4007015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        // Send any queued messages that were waiting from before the reboot.
40172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        sendFirstQueuedMessage();
4023b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor
4033b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor        // Called off of the UI thread so ok to block.
404c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev        MessagingNotification.blockingUpdateNewMessageIndicator(
405c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                this, MessagingNotification.THREAD_ALL, false);
40672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
40772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
4087015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev    /**
409087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen     * Move all messages that are in the outbox to the queued state
410087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen     * @return The number of messages that were actually moved
411087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen     */
412087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen    private int moveOutboxMessagesToQueuedBox() {
413087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen        ContentValues values = new ContentValues(1);
414087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen
415087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen        values.put(Sms.TYPE, Sms.MESSAGE_TYPE_QUEUED);
416087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen
417087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen        int messageCount = SqliteWrapper.update(
418087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen                getApplicationContext(), getContentResolver(), Outbox.CONTENT_URI,
419087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen                values, "type = " + Sms.MESSAGE_TYPE_OUTBOX, null);
420087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen        if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) {
421087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen            Log.v(TAG, "moveOutboxMessagesToQueuedBox messageCount: " + messageCount);
422087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen        }
423087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen        return messageCount;
424087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen    }
425087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen
426087ef9de80082cd001e75c15e1f93cc65d50ed27Roger Chen    /**
4277015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev     * Move all messages that are in the outbox to the failed state and set them to unread.
4287015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev     * @return The number of messages that were actually moved
4297015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev     */
4307015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev    private int moveOutboxMessagesToFailedBox() {
4317015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        ContentValues values = new ContentValues(3);
43272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
4337015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        values.put(Sms.TYPE, Sms.MESSAGE_TYPE_FAILED);
4347015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        values.put(Sms.ERROR_CODE, SmsManager.RESULT_ERROR_GENERIC_FAILURE);
4357015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        values.put(Sms.READ, Integer.valueOf(0));
43672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
437a0bda6a838d0c9bff996aa39d4f9750faa00addaTom Taylor        int messageCount = SqliteWrapper.update(
43872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                getApplicationContext(), getContentResolver(), Outbox.CONTENT_URI,
43972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                values, "type = " + Sms.MESSAGE_TYPE_OUTBOX, null);
440a0bda6a838d0c9bff996aa39d4f9750faa00addaTom Taylor        if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) {
4417015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev            Log.v(TAG, "moveOutboxMessagesToFailedBox messageCount: " + messageCount);
442a0bda6a838d0c9bff996aa39d4f9750faa00addaTom Taylor        }
4437015fa3f96383fa8a34d6b9e28f61d228e234d7eTodor Kalaydjiev        return messageCount;
44472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
44572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
44672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static final String CLASS_ZERO_BODY_KEY = "CLASS_ZERO_BODY";
44772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
44872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // This must match the column IDs below.
44972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private final static String[] REPLACE_PROJECTION = new String[] {
45072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Sms._ID,
45172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Sms.ADDRESS,
45272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Sms.PROTOCOL
45372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    };
45472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
45572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // This must match REPLACE_PROJECTION.
45672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int REPLACE_COLUMN_ID = 0;
45772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
45872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
45972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * If the message is a class-zero message, display it immediately
46072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * and return null.  Otherwise, store it using the
46172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * <code>ContentResolver</code> and return the
46272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * <code>Uri</code> of the thread containing this message
46372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * so that we can use it for notification.
46472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
465104d391ddcc251c4c26975c093d2df5dea9b15c1Tom Taylor    private Uri insertMessage(Context context, SmsMessage[] msgs, int error, String format) {
46672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Build the helper classes to parse the messages.
46772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        SmsMessage sms = msgs[0];
46872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
46972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (sms.getMessageClass() == SmsMessage.MessageClass.CLASS_0) {
470104d391ddcc251c4c26975c093d2df5dea9b15c1Tom Taylor            displayClassZeroMessage(context, sms, format);
47172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return null;
47272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else if (sms.isReplace()) {
473161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor            return replaceMessage(context, msgs, error);
47472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
475161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor            return storeMessage(context, msgs, error);
47672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
47772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
47872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
47972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
48072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * This method is used if this is a "replace short message" SMS.
48172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * We find any existing message that matches the incoming
48272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * message's originating address and protocol identifier.  If
48372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * there is one, we replace its fields with those of the new
48472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * message.  Otherwise, we store the new message as usual.
48572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     *
48672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * See TS 23.040 9.2.3.9.
48772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
488161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor    private Uri replaceMessage(Context context, SmsMessage[] msgs, int error) {
48972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        SmsMessage sms = msgs[0];
49072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ContentValues values = extractContentValues(sms);
491161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor        values.put(Sms.ERROR_CODE, error);
492dc0014f123be2c475bdeed2aef09566b5127e2a2bi        int pduCount = msgs.length;
493dc0014f123be2c475bdeed2aef09566b5127e2a2bi
494dc0014f123be2c475bdeed2aef09566b5127e2a2bi        if (pduCount == 1) {
495dc0014f123be2c475bdeed2aef09566b5127e2a2bi            // There is only one part, so grab the body directly.
496dc0014f123be2c475bdeed2aef09566b5127e2a2bi            values.put(Inbox.BODY, replaceFormFeeds(sms.getDisplayMessageBody()));
497dc0014f123be2c475bdeed2aef09566b5127e2a2bi        } else {
498dc0014f123be2c475bdeed2aef09566b5127e2a2bi            // Build up the body from the parts.
499dc0014f123be2c475bdeed2aef09566b5127e2a2bi            StringBuilder body = new StringBuilder();
500dc0014f123be2c475bdeed2aef09566b5127e2a2bi            for (int i = 0; i < pduCount; i++) {
501dc0014f123be2c475bdeed2aef09566b5127e2a2bi                sms = msgs[i];
502dc0014f123be2c475bdeed2aef09566b5127e2a2bi                if (sms.mWrappedSmsMessage != null) {
503dc0014f123be2c475bdeed2aef09566b5127e2a2bi                    body.append(sms.getDisplayMessageBody());
504dc0014f123be2c475bdeed2aef09566b5127e2a2bi                }
505dc0014f123be2c475bdeed2aef09566b5127e2a2bi            }
506dc0014f123be2c475bdeed2aef09566b5127e2a2bi            values.put(Inbox.BODY, replaceFormFeeds(body.toString()));
507dc0014f123be2c475bdeed2aef09566b5127e2a2bi        }
50872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
50972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ContentResolver resolver = context.getContentResolver();
51072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        String originatingAddress = sms.getOriginatingAddress();
51172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int protocolIdentifier = sms.getProtocolIdentifier();
51272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        String selection =
51372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Sms.ADDRESS + " = ? AND " +
51472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Sms.PROTOCOL + " = ?";
51572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        String[] selectionArgs = new String[] {
51672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            originatingAddress, Integer.toString(protocolIdentifier)
51772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        };
51872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
51972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Cursor cursor = SqliteWrapper.query(context, resolver, Inbox.CONTENT_URI,
52072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            REPLACE_PROJECTION, selection, selectionArgs, null);
52172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
52272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (cursor != null) {
52372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            try {
52472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (cursor.moveToFirst()) {
52572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    long messageId = cursor.getLong(REPLACE_COLUMN_ID);
52672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    Uri messageUri = ContentUris.withAppendedId(
52772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            Sms.CONTENT_URI, messageId);
52872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
52972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    SqliteWrapper.update(context, resolver, messageUri,
53072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        values, null, null);
53172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    return messageUri;
53272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
53372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } finally {
53472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                cursor.close();
53572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
53672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
537161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor        return storeMessage(context, msgs, error);
53872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
53972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
540beb7834e73f6bc94938cb448522df19edb60d8c8Tom Taylor    public static String replaceFormFeeds(String s) {
541beb7834e73f6bc94938cb448522df19edb60d8c8Tom Taylor        // Some providers send formfeeds in their messages. Convert those formfeeds to newlines.
5424c6c7c65a1033d5cc0d87cc8b0e07a69db1842e8Tom Taylor        return s == null ? "" : s.replace('\f', '\n');
543beb7834e73f6bc94938cb448522df19edb60d8c8Tom Taylor    }
544beb7834e73f6bc94938cb448522df19edb60d8c8Tom Taylor
5456ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor//    private static int count = 0;
5466ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor
547161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor    private Uri storeMessage(Context context, SmsMessage[] msgs, int error) {
54872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        SmsMessage sms = msgs[0];
54972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
55072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Store the message in the content provider.
55172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ContentValues values = extractContentValues(sms);
552161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor        values.put(Sms.ERROR_CODE, error);
55372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int pduCount = msgs.length;
55472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
55572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (pduCount == 1) {
55672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // There is only one part, so grab the body directly.
557beb7834e73f6bc94938cb448522df19edb60d8c8Tom Taylor            values.put(Inbox.BODY, replaceFormFeeds(sms.getDisplayMessageBody()));
55872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
55972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Build up the body from the parts.
56072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            StringBuilder body = new StringBuilder();
56172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            for (int i = 0; i < pduCount; i++) {
56272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                sms = msgs[i];
563dca923722b6eb0bb3cd8ca1d4d7b478c2fa4352bTom Taylor                if (sms.mWrappedSmsMessage != null) {
564dca923722b6eb0bb3cd8ca1d4d7b478c2fa4352bTom Taylor                    body.append(sms.getDisplayMessageBody());
565dca923722b6eb0bb3cd8ca1d4d7b478c2fa4352bTom Taylor                }
56672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
567beb7834e73f6bc94938cb448522df19edb60d8c8Tom Taylor            values.put(Inbox.BODY, replaceFormFeeds(body.toString()));
56872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
569f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor
57023da10700b189ccca64b8e729631763572a0f15fTom Taylor        // Make sure we've got a thread id so after the insert we'll be able to delete
57123da10700b189ccca64b8e729631763572a0f15fTom Taylor        // excess messages.
57223da10700b189ccca64b8e729631763572a0f15fTom Taylor        Long threadId = values.getAsLong(Sms.THREAD_ID);
57323da10700b189ccca64b8e729631763572a0f15fTom Taylor        String address = values.getAsString(Sms.ADDRESS);
5746ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor
5756ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor        // Code for debugging and easy injection of short codes, non email addresses, etc.
5766ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor        // See Contact.isAlphaNumber() for further comments and results.
5776ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor//        switch (count++ % 8) {
5786ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor//            case 0: address = "AB12"; break;
5796ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor//            case 1: address = "12"; break;
5806ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor//            case 2: address = "Jello123"; break;
5816ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor//            case 3: address = "T-Mobile"; break;
5826ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor//            case 4: address = "Mobile1"; break;
5836ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor//            case 5: address = "Dogs77"; break;
5846ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor//            case 6: address = "****1"; break;
5856ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor//            case 7: address = "#4#5#6#"; break;
5866ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor//        }
5876ac26ca62ba1e4252bf93672abd370966d3fb7c3Tom Taylor
5886a7ba7cf4d775dbb29f3cafbee67d823149da5f1Naveen Kalla        if (!TextUtils.isEmpty(address)) {
5896a7ba7cf4d775dbb29f3cafbee67d823149da5f1Naveen Kalla            Contact cacheContact = Contact.get(address,true);
5906a7ba7cf4d775dbb29f3cafbee67d823149da5f1Naveen Kalla            if (cacheContact != null) {
5916a7ba7cf4d775dbb29f3cafbee67d823149da5f1Naveen Kalla                address = cacheContact.getNumber();
5926a7ba7cf4d775dbb29f3cafbee67d823149da5f1Naveen Kalla            }
5936a7ba7cf4d775dbb29f3cafbee67d823149da5f1Naveen Kalla        } else {
5946a7ba7cf4d775dbb29f3cafbee67d823149da5f1Naveen Kalla            address = getString(R.string.unknown_sender);
5956a7ba7cf4d775dbb29f3cafbee67d823149da5f1Naveen Kalla            values.put(Sms.ADDRESS, address);
596baf7fec7d1a5b8d52ae7be04865f9e869742c261repo sync        }
59723da10700b189ccca64b8e729631763572a0f15fTom Taylor
59823da10700b189ccca64b8e729631763572a0f15fTom Taylor        if (((threadId == null) || (threadId == 0)) && (address != null)) {
5996bbfdd3cc9cbe6b31dc64f122f3308563d19e077Tom Taylor            threadId = Conversation.getOrCreateThreadId(context, address);
600627007213deb59ef938c80353c8f3598b01478b3Wei Huang            values.put(Sms.THREAD_ID, threadId);
60123da10700b189ccca64b8e729631763572a0f15fTom Taylor        }
60272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
60372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ContentResolver resolver = context.getContentResolver();
60472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
60523da10700b189ccca64b8e729631763572a0f15fTom Taylor        Uri insertedUri = SqliteWrapper.insert(context, resolver, Inbox.CONTENT_URI, values);
606f3d4a23a76a4bbe0d48503ad7abf5d8f4fc38c31Tom Taylor
60723da10700b189ccca64b8e729631763572a0f15fTom Taylor        // Now make sure we're not over the limit in stored messages
608c7aa632be8e7d3ebe71f236f534ea2f0af71e04aTom Taylor        Recycler.getSmsRecycler().deleteOldMessagesByThreadId(context, threadId);
609c7aa632be8e7d3ebe71f236f534ea2f0af71e04aTom Taylor        MmsWidgetProvider.notifyDatasetChanged(context);
61023da10700b189ccca64b8e729631763572a0f15fTom Taylor
61123da10700b189ccca64b8e729631763572a0f15fTom Taylor        return insertedUri;
61272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
61372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
61472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
61572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Extract all the content values except the body from an SMS
61672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * message.
61772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
61872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private ContentValues extractContentValues(SmsMessage sms) {
61972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Store the message in the content provider.
62072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ContentValues values = new ContentValues();
62172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
62272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        values.put(Inbox.ADDRESS, sms.getDisplayOriginatingAddress());
62372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
62472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Use now for the timestamp to avoid confusion with clock
62572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // drift between the handset and the SMSC.
62604db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor        // Check to make sure the system is giving us a non-bogus time.
62704db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor        Calendar buildDate = new GregorianCalendar(2011, 8, 18);    // 18 Sep 2011
62804db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor        Calendar nowDate = new GregorianCalendar();
62904db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor        long now = System.currentTimeMillis();
63004db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor        nowDate.setTimeInMillis(now);
63104db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor
63204db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor        if (nowDate.before(buildDate)) {
63304db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor            // It looks like our system clock isn't set yet because the current time right now
63404db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor            // is before an arbitrary time we made this build. Instead of inserting a bogus
63504db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor            // receive time in this case, use the timestamp of when the message was sent.
63604db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor            now = sms.getTimestampMillis();
63704db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor        }
63804db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor
63904db56904da453ac04f9f9d05fe1c2ce7a3d952fTom Taylor        values.put(Inbox.DATE, new Long(now));
64054711acb7191269e0a4723320bd74f29dd2c9223Fredrik Roubert        values.put(Inbox.DATE_SENT, Long.valueOf(sms.getTimestampMillis()));
64172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        values.put(Inbox.PROTOCOL, sms.getProtocolIdentifier());
642627007213deb59ef938c80353c8f3598b01478b3Wei Huang        values.put(Inbox.READ, 0);
643627007213deb59ef938c80353c8f3598b01478b3Wei Huang        values.put(Inbox.SEEN, 0);
64472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (sms.getPseudoSubject().length() > 0) {
64572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            values.put(Inbox.SUBJECT, sms.getPseudoSubject());
64672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
64772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        values.put(Inbox.REPLY_PATH_PRESENT, sms.isReplyPathPresent() ? 1 : 0);
64872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        values.put(Inbox.SERVICE_CENTER, sms.getServiceCenterAddress());
64972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return values;
65072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
65172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
65272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
65372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Displays a class-zero message immediately in a pop-up window
65472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * with the number from where it received the Notification with
65572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * the body of the message
65672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     *
65772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
658104d391ddcc251c4c26975c093d2df5dea9b15c1Tom Taylor    private void displayClassZeroMessage(Context context, SmsMessage sms, String format) {
65972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Using NEW_TASK here is necessary because we're calling
66072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // startActivity from outside an activity.
66172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Intent smsDialogIntent = new Intent(context, ClassZeroActivity.class)
6624da6513065fbcfbf7fee9a18176ce62d2f62c825Yong Liu                .putExtra("pdu", sms.getPdu())
663104d391ddcc251c4c26975c093d2df5dea9b15c1Tom Taylor                .putExtra("format", format)
66472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
66572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                          | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
66672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
66772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        context.startActivity(smsDialogIntent);
66872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
66972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
670cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor    private void registerForServiceStateChanges() {
671cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor        Context context = getApplicationContext();
672cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor        unRegisterForServiceStateChanges();
673cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor
674cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor        IntentFilter intentFilter = new IntentFilter();
675f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylor        intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
676c33ee154b6fd872439fd24a073f947339bbe4d22Tom Taylor        if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) {
677cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor            Log.v(TAG, "registerForServiceStateChanges");
678cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor        }
679cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor
680cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor        context.registerReceiver(SmsReceiver.getInstance(), intentFilter);
681cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor    }
682cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor
683cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor    private void unRegisterForServiceStateChanges() {
684c33ee154b6fd872439fd24a073f947339bbe4d22Tom Taylor        if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) {
685cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor            Log.v(TAG, "unRegisterForServiceStateChanges");
686cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor        }
687cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor        try {
688cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor            Context context = getApplicationContext();
689cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor            context.unregisterReceiver(SmsReceiver.getInstance());
690cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor        } catch (IllegalArgumentException e) {
691cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor            // Allow un-matched register-unregister calls
692cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor        }
693cd88c0f1da9bc67a67dd7174428ab3195a2dc11fTom Taylor    }
69472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project}
69537321876549776417f035118f157d9531f73de6bWink Saville
69637321876549776417f035118f157d9531f73de6bWink Saville
697