MmsSmsDatabaseHelper.java revision 09710cec4926bcd3708376face04507e661bcc02
17236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project/*
27236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
37236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project *
47236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
57236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * you may not use this file except in compliance with the License.
67236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * You may obtain a copy of the License at
77236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project *
87236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
97236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project *
107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * See the License for the specific language governing permissions and
147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * limitations under the License.
157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */
167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectpackage com.android.providers.telephony;
187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
19f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagnerimport java.io.IOException;
20f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagnerimport java.io.InputStream;
21f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagnerimport java.io.FileInputStream;
22f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagnerimport java.io.File;
23f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagnerimport java.util.ArrayList;
24f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
2510faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylorimport android.content.BroadcastReceiver;
268e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagnerimport android.content.ContentValues;
277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.content.Context;
2810faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylorimport android.content.Intent;
2910faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylorimport android.content.IntentFilter;
307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.Cursor;
317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase;
327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.sqlite.SQLiteOpenHelper;
337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.BaseColumns;
348e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagnerimport android.provider.Telephony;
357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Mms;
367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.MmsSms;
377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Sms;
387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Threads;
397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Mms.Addr;
407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Mms.Part;
417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Mms.Rate;
427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.MmsSms.PendingMessages;
437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.util.Log;
447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
45b1bae65bf18dc22762cf7b8210fdad836b3e4ee5Tom Taylorimport com.google.android.mms.pdu.EncodedStringValue;
46b1bae65bf18dc22762cf7b8210fdad836b3e4ee5Tom Taylorimport com.google.android.mms.pdu.PduHeaders;
47c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor
487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectpublic class MmsSmsDatabaseHelper extends SQLiteOpenHelper {
497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String TAG = "MmsSmsDatabaseHelper";
507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String SMS_UPDATE_THREAD_READ_BODY =
527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET read = " +
537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    CASE (SELECT COUNT(*)" +
547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "          FROM sms" +
557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "          WHERE " + Sms.READ + " = 0" +
567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "            AND " + Sms.THREAD_ID + " = threads._id)" +
577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      WHEN 0 THEN 1" +
587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      ELSE 0" +
597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    END" +
607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = new." + Sms.THREAD_ID + "; ";
617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String UPDATE_THREAD_COUNT_ON_NEW =
637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET message_count = " +
647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "     (SELECT COUNT(sms._id) FROM sms LEFT JOIN threads " +
657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      ON threads._id = " + Sms.THREAD_ID +
667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      WHERE " + Sms.THREAD_ID + " = new.thread_id" +
677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "        AND sms." + Sms.TYPE + " != 3) + " +
687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "     (SELECT COUNT(pdu._id) FROM pdu LEFT JOIN threads " +
697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      ON threads._id = " + Mms.THREAD_ID +
707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      WHERE " + Mms.THREAD_ID + " = new.thread_id" +
717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "        AND (m_type=132 OR m_type=130 OR m_type=128)" +
727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "        AND " + Mms.MESSAGE_BOX + " != 3) " +
737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = new.thread_id; ";
747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String UPDATE_THREAD_COUNT_ON_OLD =
767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET message_count = " +
777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "     (SELECT COUNT(sms._id) FROM sms LEFT JOIN threads " +
787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      ON threads._id = " + Sms.THREAD_ID +
797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      WHERE " + Sms.THREAD_ID + " = old.thread_id" +
807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "        AND sms." + Sms.TYPE + " != 3) + " +
817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "     (SELECT COUNT(pdu._id) FROM pdu LEFT JOIN threads " +
827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      ON threads._id = " + Mms.THREAD_ID +
837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      WHERE " + Mms.THREAD_ID + " = old.thread_id" +
847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "        AND (m_type=132 OR m_type=130 OR m_type=128)" +
857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "        AND " + Mms.MESSAGE_BOX + " != 3) " +
867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = old.thread_id; ";
877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE =
897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "BEGIN" +
907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET" +
917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    date = (strftime('%s','now') * 1000), " +
927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    snippet = new." + Sms.BODY + ", " +
937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    snippet_cs = 0" +
947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = new." + Sms.THREAD_ID + "; " +
957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        UPDATE_THREAD_COUNT_ON_NEW +
967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        SMS_UPDATE_THREAD_READ_BODY +
977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "END;";
987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String PDU_UPDATE_THREAD_CONSTRAINTS =
100c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                        "  WHEN new." + Mms.MESSAGE_TYPE + "=" +
101c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                        PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF +
102c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                        "    OR new." + Mms.MESSAGE_TYPE + "=" +
103c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                        PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND +
104c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                        "    OR new." + Mms.MESSAGE_TYPE + "=" +
105c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                        PduHeaders.MESSAGE_TYPE_SEND_REQ + " ";
1067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1071e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor    // When looking in the pdu table for unread messages, only count messages that
1081e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor    // are displayed to the user. The constants are defined in PduHeaders and could be used
1091e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor    // here, but the string "(m_type=132 OR m_type=130 OR m_type=128)" is used throughout this
1101e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor    // file and so it is used here to be consistent.
1111e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor    //     m_type=128   = MESSAGE_TYPE_SEND_REQ
1121e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor    //     m_type=130   = MESSAGE_TYPE_NOTIFICATION_IND
1131e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor    //     m_type=132   = MESSAGE_TYPE_RETRIEVE_CONF
1147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String PDU_UPDATE_THREAD_READ_BODY =
1157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET read = " +
1167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    CASE (SELECT COUNT(*)" +
1177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "          FROM " + MmsProvider.TABLE_PDU +
1187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "          WHERE " + Mms.READ + " = 0" +
1191e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                        "            AND " + Mms.THREAD_ID + " = threads._id " +
1201e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                        "            AND (m_type=132 OR m_type=130 OR m_type=128)) " +
1217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      WHEN 0 THEN 1" +
1227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      ELSE 0" +
1237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    END" +
1247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = new." + Mms.THREAD_ID + "; ";
1257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String PDU_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE =
1277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "BEGIN" +
1287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET" +
1297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    date = (strftime('%s','now') * 1000), " +
1307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    snippet = new." + Mms.SUBJECT + ", " +
1317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    snippet_cs = new." + Mms.SUBJECT_CHARSET +
1327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = new." + Mms.THREAD_ID + "; " +
1337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        UPDATE_THREAD_COUNT_ON_NEW +
1347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        PDU_UPDATE_THREAD_READ_BODY +
1357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "END;";
1367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String UPDATE_THREAD_SNIPPET_SNIPPET_CS_ON_DELETE =
1387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET snippet = " +
1397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "   (SELECT snippet FROM" +
1407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "     (SELECT date * 1000 AS date, sub AS snippet, thread_id FROM pdu" +
1417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      UNION SELECT date, body AS snippet, thread_id FROM sms)" +
1427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    WHERE thread_id = OLD.thread_id ORDER BY date DESC LIMIT 1) " +
1437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = OLD.thread_id; " +
1447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET snippet_cs = " +
1457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "   (SELECT snippet_cs FROM" +
1467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "     (SELECT date * 1000 AS date, sub_cs AS snippet_cs, thread_id FROM pdu" +
1477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      UNION SELECT date, 0 AS snippet_cs, thread_id FROM sms)" +
1487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    WHERE thread_id = OLD.thread_id ORDER BY date DESC LIMIT 1) " +
1497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = OLD.thread_id; ";
1507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1515f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project
1525f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // When a part is inserted, if it is not text/plain or application/smil
1535f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // (which both can exist with text-only MMSes), then there is an attachment.
1545f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // Set has_attachment=1 in the threads table for the thread in question.
1555f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    private static final String PART_UPDATE_THREADS_ON_INSERT_TRIGGER =
1565f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "CREATE TRIGGER update_threads_on_insert_part " +
1575f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " AFTER INSERT ON part " +
1585f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " WHEN new.ct != 'text/plain' AND new.ct != 'application/smil' " +
1595f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " BEGIN " +
1605f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "  UPDATE threads SET has_attachment=1 WHERE _id IN " +
1615f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "   (SELECT pdu.thread_id FROM part JOIN pdu ON pdu._id=part.mid " +
1625f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "     WHERE part._id=new._id LIMIT 1); " +
1635f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " END";
1642ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang
1652ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang    // When the 'mid' column in the part table is updated, we need to run the trigger to update
1662ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang    // the threads table's has_attachment column, if the part is an attachment.
1672ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang    private static final String PART_UPDATE_THREADS_ON_UPDATE_TRIGGER =
1682ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        "CREATE TRIGGER update_threads_on_update_part " +
1692ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        " AFTER UPDATE of " + Part.MSG_ID + " ON part " +
1702ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        " WHEN new.ct != 'text/plain' AND new.ct != 'application/smil' " +
1712ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        " BEGIN " +
1722ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        "  UPDATE threads SET has_attachment=1 WHERE _id IN " +
1732ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        "   (SELECT pdu.thread_id FROM part JOIN pdu ON pdu._id=part.mid " +
1742ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        "     WHERE part._id=new._id LIMIT 1); " +
1752ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        " END";
1762ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang
1772ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang
1785f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // When a part is deleted (with the same non-text/SMIL constraint as when
1795f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // we set has_attachment), update the threads table for all threads.
1805f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // Unfortunately we cannot update only the thread that the part was
1815f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // attached to, as it is possible that the part has been orphaned and
1825f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // the message it was attached to is already gone.
1835f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    private static final String PART_UPDATE_THREADS_ON_DELETE_TRIGGER =
1845f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "CREATE TRIGGER update_threads_on_delete_part " +
1855f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " AFTER DELETE ON part " +
1865f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " WHEN old.ct != 'text/plain' AND old.ct != 'application/smil' " +
1875f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " BEGIN " +
1885f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "  UPDATE threads SET has_attachment = " +
1895f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "   CASE " +
19094489f821be2401e4a9045901d9112d42273b362Tom Taylor                        "    (SELECT COUNT(*) FROM part JOIN pdu " +
1915f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "     WHERE pdu.thread_id = threads._id " +
19294489f821be2401e4a9045901d9112d42273b362Tom Taylor                        "     AND part.ct != 'text/plain' AND part.ct != 'application/smil' " +
19394489f821be2401e4a9045901d9112d42273b362Tom Taylor                        "     AND part.mid = pdu._id)" +
1945f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "   WHEN 0 THEN 0 " +
1955f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "   ELSE 1 " +
1965f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "   END; " +
1975f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " END";
198f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
1991047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang    // When the 'thread_id' column in the pdu table is updated, we need to run the trigger to update
2001047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang    // the threads table's has_attachment column, if the message has an attachment in 'part' table
2011047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang    private static final String PDU_UPDATE_THREADS_ON_UPDATE_TRIGGER =
2021047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                        "CREATE TRIGGER update_threads_on_update_pdu " +
2031047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                        " AFTER UPDATE of thread_id ON pdu " +
2041047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                        " BEGIN " +
2051047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                        "  UPDATE threads SET has_attachment=1 WHERE _id IN " +
20694489f821be2401e4a9045901d9112d42273b362Tom Taylor                        "   (SELECT pdu.thread_id FROM part JOIN pdu " +
20794489f821be2401e4a9045901d9112d42273b362Tom Taylor                        "     WHERE part.ct != 'text/plain' AND part.ct != 'application/smil' " +
20894489f821be2401e4a9045901d9112d42273b362Tom Taylor                        "     AND part.mid = pdu._id);" +
2091047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                        " END";
2101047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang
21110faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor    private static MmsSmsDatabaseHelper sInstance = null;
21210faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor    private static boolean sTriedAutoIncrement = false;
21310faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor    private static boolean sFakeLowStorageTest = false;     // for testing only
2147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    static final String DATABASE_NAME = "mmssms.db";
216527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor    static final int DATABASE_VERSION = 55;
21710faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor    private final Context mContext;
21810faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor    private LowStorageMonitor mLowStorageMonitor;
2191ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor
2207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private MmsSmsDatabaseHelper(Context context) {
2227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        super(context, DATABASE_NAME, null, DATABASE_VERSION);
22310faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor
22410faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        mContext = context;
2257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
2267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
2287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Return a singleton helper for the combined MMS and SMS
2297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * database.
2307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
2317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /* package */ static synchronized MmsSmsDatabaseHelper getInstance(Context context) {
23210faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        if (sInstance == null) {
23310faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor            sInstance = new MmsSmsDatabaseHelper(context);
2347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
23510faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        return sInstance;
2367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
2377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public static void updateThread(SQLiteDatabase db, long thread_id) {
2397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        if (thread_id < 0) {
2407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            updateAllThreads(db, null, null);
2417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            return;
2427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
243f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
2447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Delete the row for this thread in the threads table if
2457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // there are no more messages attached to it in either
2467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // the sms or pdu tables.
2477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int rows = db.delete("threads",
2487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                  "_id = ? AND _id NOT IN" +
2497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                  "          (SELECT thread_id FROM sms " +
2507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                  "           UNION SELECT thread_id FROM pdu)",
2517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                  new String[] { String.valueOf(thread_id) });
2527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        if (rows > 0) {
2533ce9cb8e04c821453dd7731b30309d508017f89cTom Taylor            // If this deleted a row, let's remove orphaned canonical_addresses and get outta here
2543ce9cb8e04c821453dd7731b30309d508017f89cTom Taylor            db.delete("canonical_addresses",
2553ce9cb8e04c821453dd7731b30309d508017f89cTom Taylor                    "_id NOT IN (SELECT DISTINCT recipient_ids FROM threads)", null);
2567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            return;
2577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
2587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Update the message count in the threads table as the sum
2597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // of all messages in both the sms and pdu tables.
2607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL(
2617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            "  UPDATE threads SET message_count = " +
2627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            "     (SELECT COUNT(sms._id) FROM sms LEFT JOIN threads " +
2637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            "      ON threads._id = " + Sms.THREAD_ID +
2647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            "      WHERE " + Sms.THREAD_ID + " = " + thread_id +
2657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            "        AND sms." + Sms.TYPE + " != 3) + " +
2667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            "     (SELECT COUNT(pdu._id) FROM pdu LEFT JOIN threads " +
2677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            "      ON threads._id = " + Mms.THREAD_ID +
2687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            "      WHERE " + Mms.THREAD_ID + " = " + thread_id +
2697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            "        AND (m_type=132 OR m_type=130 OR m_type=128)" +
2707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            "        AND " + Mms.MESSAGE_BOX + " != 3) " +
2717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            "  WHERE threads._id = " + thread_id + ";");
2727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Update the date and the snippet (and its character set) in
2747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // the threads table to be that of the most recent message in
2757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // the thread.
2767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL(
277f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "  UPDATE threads" +
278f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "  SET" +
279f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "  date =" +
280f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "    (SELECT date FROM" +
281f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "        (SELECT date * 1000 AS date, thread_id FROM pdu" +
282f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "         UNION SELECT date, thread_id FROM sms)" +
283f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "     WHERE thread_id = " + thread_id + " ORDER BY date DESC LIMIT 1)," +
284f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "  snippet =" +
285f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "    (SELECT snippet FROM" +
286f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "        (SELECT date * 1000 AS date, sub AS snippet, thread_id FROM pdu" +
287f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "         UNION SELECT date, body AS snippet, thread_id FROM sms)" +
288f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "     WHERE thread_id = " + thread_id + " ORDER BY date DESC LIMIT 1)," +
289f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "  snippet_cs =" +
290f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "    (SELECT snippet_cs FROM" +
291f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "        (SELECT date * 1000 AS date, sub_cs AS snippet_cs, thread_id FROM pdu" +
292f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "         UNION SELECT date, 0 AS snippet_cs, thread_id FROM sms)" +
293f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "     WHERE thread_id = " + thread_id + " ORDER BY date DESC LIMIT 1)" +
294f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            "  WHERE threads._id = " + thread_id + ";");
2957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Update the error column of the thread to indicate if there
2977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // are any messages in it that have failed to send.
2989565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor        // First check to see if there are any messages with errors in this thread.
2999565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor        String query = "SELECT thread_id FROM sms WHERE type=" +
3009565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor            Telephony.TextBasedSmsColumns.MESSAGE_TYPE_FAILED +
3019565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor            " AND thread_id = " + thread_id +
3029565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                                " LIMIT 1";
3039565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor        int setError = 0;
3049565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor        Cursor c = db.rawQuery(query, null);
3059565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor        if (c != null) {
3069565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor            try {
3079565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                setError = c.getCount();    // Because of the LIMIT 1, count will be 1 or 0.
3089565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor            } finally {
3099565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                c.close();
3109565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor            }
3119565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor        }
3129565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor        // What's the current state of the error flag in the threads table?
3139565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor        String errorQuery = "SELECT error FROM threads WHERE _id = " + thread_id;
3149565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor        c = db.rawQuery(errorQuery, null);
3159565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor        if (c != null) {
3169565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor            try {
3179565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                if (c.moveToNext()) {
3189565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                    int curError = c.getInt(0);
3199565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                    if (curError != setError) {
3209565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                        // The current thread error column differs, update it.
3219565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                        db.execSQL("UPDATE threads SET error=" + setError +
3229565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                                " WHERE _id = " + thread_id);
3239565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                    }
3249565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                }
3259565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor            } finally {
3269565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                c.close();
3279565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor            }
3289565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor        }
3297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
330f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
3317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public static void updateAllThreads(SQLiteDatabase db, String where, String[] whereArgs) {
3327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        if (where == null) {
3337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            where = "";
3347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        } else {
3357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            where = "WHERE (" + where + ")";
3367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
3377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String query = "SELECT _id FROM threads WHERE _id IN " +
3387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                       "(SELECT DISTINCT thread_id FROM sms " + where + ")";
3397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Cursor c = db.rawQuery(query, whereArgs);
3407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        if (c != null) {
3419565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor            try {
3429565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                while (c.moveToNext()) {
3439565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                    updateThread(db, c.getInt(0));
3449565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                }
3459565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor            } finally {
3469565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                c.close();
3477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            }
3487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
3493ce9cb8e04c821453dd7731b30309d508017f89cTom Taylor        // TODO: there are several db operations in this function. Lets wrap them in a
3503ce9cb8e04c821453dd7731b30309d508017f89cTom Taylor        // transaction to make it faster.
3517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // remove orphaned threads
3527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.delete("threads",
3537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                "_id NOT IN (SELECT DISTINCT thread_id FROM sms " +
3547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                "UNION SELECT DISTINCT thread_id FROM pdu)", null);
3553ce9cb8e04c821453dd7731b30309d508017f89cTom Taylor
3563ce9cb8e04c821453dd7731b30309d508017f89cTom Taylor        // remove orphaned canonical_addresses
3573ce9cb8e04c821453dd7731b30309d508017f89cTom Taylor        db.delete("canonical_addresses",
3583ce9cb8e04c821453dd7731b30309d508017f89cTom Taylor                "_id NOT IN (SELECT DISTINCT recipient_ids FROM threads)", null);
3597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
360f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
3617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public static int deleteOneSms(SQLiteDatabase db, int message_id) {
3627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int thread_id = -1;
3637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Find the thread ID that the specified SMS belongs to.
3647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Cursor c = db.query("sms", new String[] { "thread_id" },
3657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                            "_id=" + message_id, null, null, null, null);
3667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        if (c != null) {
3677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            if (c.moveToFirst()) {
3687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                thread_id = c.getInt(0);
3697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            }
3707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            c.close();
3717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
3727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
3737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Delete the specified message.
3747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int rows = db.delete("sms", "_id=" + message_id, null);
3757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        if (thread_id > 0) {
3767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            // Update its thread.
3777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            updateThread(db, thread_id);
3787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
3797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return rows;
3807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
3817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
3827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    @Override
3837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public void onCreate(SQLiteDatabase db) {
3847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        createMmsTables(db);
3857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        createSmsTables(db);
3867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        createCommonTables(db);
3877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        createCommonTriggers(db);
3887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        createMmsTriggers(db);
3898e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        createWordsTables(db);
390a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor        createIndices(db);
3918e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    }
3928e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
3938e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    // When upgrading the database we need to populate the words
3948e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    // table with the rows out of sms and part.
3958e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    private void populateWordsTable(SQLiteDatabase db) {
3968e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        final String TABLE_WORDS = "words";
3978e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        {
3988e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            Cursor smsRows = db.query(
3998e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    "sms",
4008e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    new String[] { Sms._ID, Sms.BODY },
4018e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null,
4028e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null,
4038e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null,
4048e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null,
4058e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null);
4068e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            try {
4078e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                if (smsRows != null) {
4088e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    smsRows.moveToPosition(-1);
4098e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    ContentValues cv = new ContentValues();
4108e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    while (smsRows.moveToNext()) {
4118e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.clear();
4128e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4138e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        long id = smsRows.getLong(0);        // 0 for Sms._ID
4148e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        String body = smsRows.getString(1);  // 1 for Sms.BODY
4158e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4168e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.ID, id);
4178e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.INDEXED_TEXT, body);
4188e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.SOURCE_ROW_ID, id);
4198e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.TABLE_ID, 1);
4208e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        db.insert(TABLE_WORDS, Telephony.MmsSms.WordsTable.INDEXED_TEXT, cv);
4218e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    }
4228e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                }
4238e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            } finally {
4248e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                if (smsRows != null) {
4258e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    smsRows.close();
4268e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                }
4278e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            }
4288e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        }
4298e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4308e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        {
4318e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            Cursor mmsRows = db.query(
4328e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    "part",
4338e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    new String[] { Part._ID, Part.TEXT },
4348e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    "ct = 'text/plain'",
4358e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null,
4368e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null,
4378e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null,
4388e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null);
4398e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            try {
4408e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                if (mmsRows != null) {
4418e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    mmsRows.moveToPosition(-1);
4428e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    ContentValues cv = new ContentValues();
4438e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    while (mmsRows.moveToNext()) {
4448e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.clear();
4458e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4468e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        long id = mmsRows.getLong(0);         // 0 for Part._ID
4478e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        String body = mmsRows.getString(1);   // 1 for Part.TEXT
4488e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4498e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.ID, id);
4508e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.INDEXED_TEXT, body);
4518e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.SOURCE_ROW_ID, id);
4528e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.TABLE_ID, 1);
4538e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        db.insert(TABLE_WORDS, Telephony.MmsSms.WordsTable.INDEXED_TEXT, cv);
4548e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    }
4558e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                }
4568e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            } finally {
4578e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                if (mmsRows != null) {
4588e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    mmsRows.close();
4598e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                }
4608e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            }
4618e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        }
4628e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    }
4638e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4648e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    private void createWordsTables(SQLiteDatabase db) {
4658e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        try {
4668e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            db.execSQL("CREATE VIRTUAL TABLE words USING FTS3 (_id INTEGER PRIMARY KEY, index_text TEXT, source_id INTEGER, table_to_use INTEGER);");
4678e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4688e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            // monitor the sms table
4698e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            // NOTE don't handle inserts using a trigger because it has an unwanted
4708e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            // side effect:  the value returned for the last row ends up being the
4718e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            // id of one of the trigger insert not the original row insert.
4728e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            // Handle inserts manually in the provider.
4738e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            db.execSQL("CREATE TRIGGER sms_words_update AFTER UPDATE ON sms BEGIN UPDATE words " +
4748e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    " SET index_text = NEW.body WHERE (source_id=NEW._id AND table_to_use=1); " +
4758e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    " END;");
4768e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            db.execSQL("CREATE TRIGGER sms_words_delete AFTER DELETE ON sms BEGIN DELETE FROM " +
4778e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    "  words WHERE source_id = OLD._id AND table_to_use = 1; END;");
4788e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4798e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            // monitor the mms table
4808e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            db.execSQL("CREATE TRIGGER mms_words_update AFTER UPDATE ON part BEGIN UPDATE words " +
481a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor                    " SET index_text = NEW.text WHERE (source_id=NEW._id AND table_to_use=2); " +
482a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor                    " END;");
4838e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            db.execSQL("CREATE TRIGGER mms_words_delete AFTER DELETE ON part BEGIN DELETE FROM " +
4848e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    " words WHERE source_id = OLD._id AND table_to_use = 2; END;");
4858e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4868e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            populateWordsTable(db);
4878e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        } catch (Exception ex) {
4888e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            Log.e(TAG, "got exception creating words table: " + ex.toString());
4898e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        }
4907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
4917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
492a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor    private void createIndices(SQLiteDatabase db) {
493a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor        createThreadIdIndex(db);
494a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor    }
495a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor
496a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor    private void createThreadIdIndex(SQLiteDatabase db) {
497a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor        try {
498a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            db.execSQL("CREATE INDEX IF NOT EXISTS typeThreadIdIndex ON sms" +
499a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            " (type, thread_id);");
500a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor        } catch (Exception ex) {
501a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            Log.e(TAG, "got exception creating indices: " + ex.toString());
502a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor        }
503a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor    }
504a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor
5057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void createMmsTables(SQLiteDatabase db) {
5067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // N.B.: Whenever the columns here are changed, the columns in
5077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // {@ref MmsSmsProvider} must be changed to match.
5087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE " + MmsProvider.TABLE_PDU + " (" +
5097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms._ID + " INTEGER PRIMARY KEY," +
5107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.THREAD_ID + " INTEGER," +
5117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.DATE + " INTEGER," +
512ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   Mms.DATE_SENT + " INTEGER DEFAULT 0," +
5137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.MESSAGE_BOX + " INTEGER," +
5147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.READ + " INTEGER DEFAULT 0," +
5157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.MESSAGE_ID + " TEXT," +
5167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.SUBJECT + " TEXT," +
5177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.SUBJECT_CHARSET + " INTEGER," +
5187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.CONTENT_TYPE + " TEXT," +
5197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.CONTENT_LOCATION + " TEXT," +
5207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.EXPIRY + " INTEGER," +
5217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.MESSAGE_CLASS + " TEXT," +
5227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.MESSAGE_TYPE + " INTEGER," +
5237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.MMS_VERSION + " INTEGER," +
5247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.MESSAGE_SIZE + " INTEGER," +
5257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.PRIORITY + " INTEGER," +
5267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.READ_REPORT + " INTEGER," +
5277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.REPORT_ALLOWED + " INTEGER," +
5287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.RESPONSE_STATUS + " INTEGER," +
5297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.STATUS + " INTEGER," +
5307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.TRANSACTION_ID + " TEXT," +
5317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.RETRIEVE_STATUS + " INTEGER," +
5327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.RETRIEVE_TEXT + " TEXT," +
5337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.RETRIEVE_TEXT_CHARSET + " INTEGER," +
5347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.READ_STATUS + " INTEGER," +
5357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.CONTENT_CLASS + " INTEGER," +
5367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.RESPONSE_TEXT + " TEXT," +
5377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.DELIVERY_TIME + " INTEGER," +
538a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                   Mms.DELIVERY_REPORT + " INTEGER," +
539dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                   Mms.LOCKED + " INTEGER DEFAULT 0," +
5408a4060ec0c2433ceeb619a3a35fba5aabedbc1c6Tom Taylor                   Mms.SEEN + " INTEGER DEFAULT 0" +
541a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                   ");");
5427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE " + MmsProvider.TABLE_ADDR + " (" +
5447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Addr._ID + " INTEGER PRIMARY KEY," +
5457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Addr.MSG_ID + " INTEGER," +
5467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Addr.CONTACT_ID + " INTEGER," +
5477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Addr.ADDRESS + " TEXT," +
5487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Addr.TYPE + " INTEGER," +
5497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Addr.CHARSET + " INTEGER);");
5507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE " + MmsProvider.TABLE_PART + " (" +
5527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part._ID + " INTEGER PRIMARY KEY," +
5537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.MSG_ID + " INTEGER," +
5547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.SEQ + " INTEGER DEFAULT 0," +
5557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.CONTENT_TYPE + " TEXT," +
5567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.NAME + " TEXT," +
5577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.CHARSET + " INTEGER," +
5587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.CONTENT_DISPOSITION + " TEXT," +
5597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.FILENAME + " TEXT," +
5607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.CONTENT_ID + " TEXT," +
5617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.CONTENT_LOCATION + " TEXT," +
5627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.CT_START + " INTEGER," +
5637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.CT_TYPE + " TEXT," +
564f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                   Part._DATA + " TEXT," +
565f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                   Part.TEXT + " TEXT);");
5667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE " + MmsProvider.TABLE_RATE + " (" +
5687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Rate.SENT_TIME + " INTEGER);");
5697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE " + MmsProvider.TABLE_DRM + " (" +
5717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   BaseColumns._ID + " INTEGER PRIMARY KEY," +
5727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "_data TEXT);");
5737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
5747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void createMmsTriggers(SQLiteDatabase db) {
5767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Cleans up parts when a MM is deleted.
5777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER part_cleanup DELETE ON " + MmsProvider.TABLE_PDU + " " +
5787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
5797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  DELETE FROM " + MmsProvider.TABLE_PART +
5807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHERE " + Part.MSG_ID + "=old._id;" +
5817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
5827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Cleans up address info when a MM is deleted.
5847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER addr_cleanup DELETE ON " + MmsProvider.TABLE_PDU + " " +
5857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
5867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  DELETE FROM " + MmsProvider.TABLE_ADDR +
5877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHERE " + Addr.MSG_ID + "=old._id;" +
5887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
5897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Delete obsolete delivery-report, read-report while deleting their
5917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // associated Send.req.
5927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER cleanup_delivery_and_read_report " +
5937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "AFTER DELETE ON " + MmsProvider.TABLE_PDU + " " +
594c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                   "WHEN old." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_SEND_REQ + " " +
5957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
5967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  DELETE FROM " + MmsProvider.TABLE_PDU +
597c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                   "  WHERE (" + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_DELIVERY_IND +
598c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                   "    OR " + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_READ_ORIG_IND +
599c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                   ")" +
6007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    AND " + Mms.MESSAGE_ID + "=old." + Mms.MESSAGE_ID + "; " +
6017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
602f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
6035f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        // Update threads table to indicate whether attachments exist when
6045f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        // parts are inserted or deleted.
6055f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        db.execSQL(PART_UPDATE_THREADS_ON_INSERT_TRIGGER);
6062ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang        db.execSQL(PART_UPDATE_THREADS_ON_UPDATE_TRIGGER);
6075f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        db.execSQL(PART_UPDATE_THREADS_ON_DELETE_TRIGGER);
6081047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        db.execSQL(PDU_UPDATE_THREADS_ON_UPDATE_TRIGGER);
6097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
6107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void createSmsTables(SQLiteDatabase db) {
6127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // N.B.: Whenever the columns here are changed, the columns in
6137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // {@ref MmsSmsProvider} must be changed to match.
6147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE sms (" +
6157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "_id INTEGER PRIMARY KEY," +
6167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "thread_id INTEGER," +
6177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "address TEXT," +
6187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "person INTEGER," +
6197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "date INTEGER," +
620ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   "date_sent INTEGER DEFAULT 0," +
6217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "protocol INTEGER," +
6227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "read INTEGER DEFAULT 0," +
6237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "status INTEGER DEFAULT -1," + // a TP-Status value
6247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                                                  // or -1 if it
6257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                                                  // status hasn't
6267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                                                  // been received
6277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "type INTEGER," +
6287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "reply_path_present INTEGER," +
6297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "subject TEXT," +
6307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "body TEXT," +
631a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                   "service_center TEXT," +
6327d4e56b5fb5726342a3e0ebfba91dac48f56c107Tom Taylor                   "locked INTEGER DEFAULT 0," +
633dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                   "error_code INTEGER DEFAULT 0," +
6348a4060ec0c2433ceeb619a3a35fba5aabedbc1c6Tom Taylor                   "seen INTEGER DEFAULT 0" +
635a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                   ");");
6367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        /**
6387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * This table is used by the SMS dispatcher to hold
6397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * incomplete partial messages until all the parts arrive.
6407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         */
6417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE raw (" +
6427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "_id INTEGER PRIMARY KEY," +
6437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "date INTEGER," +
6447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "reference_number INTEGER," + // one per full message
6457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "count INTEGER," + // the number of parts
6467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "sequence INTEGER," + // the part number of this message
6477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "destination_port INTEGER," +
6487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "address TEXT," +
6497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "pdu TEXT);"); // the raw PDU for this part
6507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE attachments (" +
6527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "sms_id INTEGER," +
6537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "content_url TEXT," +
6547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "offset INTEGER);");
6557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        /**
6577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * This table is used by the SMS dispatcher to hold pending
6587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * delivery status report intents.
6597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         */
6607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE sr_pending (" +
6617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "reference_number INTEGER," +
6627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "action TEXT," +
6637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "data TEXT);");
6647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
6657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void createCommonTables(SQLiteDatabase db) {
6677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // TODO Ensure that each entry is removed when the last use of
6687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // any address equivalent to its address is removed.
6697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        /**
6717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * This table maps the first instance seen of any particular
6727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * MMS/SMS address to an ID, which is then used as its
6737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * canonical representation.  If the same address or an
6747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * equivalent address (as determined by our Sqlite
6757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * PHONE_NUMBERS_EQUAL extension) is seen later, this same ID
67609710cec4926bcd3708376face04507e661bcc02Tom Taylor         * will be used. The _id is created with AUTOINCREMENT so it
67709710cec4926bcd3708376face04507e661bcc02Tom Taylor         * will never be reused again if a recipient is deleted.
6787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         */
6797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE canonical_addresses (" +
68009710cec4926bcd3708376face04507e661bcc02Tom Taylor                   "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
6817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "address TEXT);");
6827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        /**
6847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * This table maps the subject and an ordered set of recipient
6857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * IDs, separated by spaces, to a unique thread ID.  The IDs
6867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * come from the canonical_addresses table.  This works
6877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * because messages are considered to be part of the same
6887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * thread if they have the same subject (or a null subject)
6897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * and the same set of recipients.
6907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         */
6917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE threads (" +
6921ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                   Threads._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
6937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Threads.DATE + " INTEGER DEFAULT 0," +
6947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Threads.MESSAGE_COUNT + " INTEGER DEFAULT 0," +
6957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Threads.RECIPIENT_IDS + " TEXT," +
6967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Threads.SNIPPET + " TEXT," +
6977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Threads.SNIPPET_CHARSET + " INTEGER DEFAULT 0," +
6987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Threads.READ + " INTEGER DEFAULT 1," +
6997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Threads.TYPE + " INTEGER DEFAULT 0," +
7005f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                   Threads.ERROR + " INTEGER DEFAULT 0," +
7015f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                   Threads.HAS_ATTACHMENT + " INTEGER DEFAULT 0);");
7027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        /**
7047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * This table stores the queue of messages to be sent/downloaded.
7057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         */
7067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE " + MmsSmsProvider.TABLE_PENDING_MSG +" (" +
7077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages._ID + " INTEGER PRIMARY KEY," +
7087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.PROTO_TYPE + " INTEGER," +
7097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.MSG_ID + " INTEGER," +
7107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.MSG_TYPE + " INTEGER," +
7117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.ERROR_TYPE + " INTEGER," +
7127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.ERROR_CODE + " INTEGER," +
7137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.RETRY_INDEX + " INTEGER NOT NULL DEFAULT 0," +
7147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.DUE_TIME + " INTEGER," +
7157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.LAST_TRY + " INTEGER);");
7167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
7187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // TODO Check the query plans for these triggers.
7207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void createCommonTriggers(SQLiteDatabase db) {
7217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Updates threads table whenever a message is added to pdu.
7227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER pdu_update_thread_on_insert AFTER INSERT ON " +
7237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   MmsProvider.TABLE_PDU + " " +
7247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PDU_UPDATE_THREAD_CONSTRAINTS +
7257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PDU_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE);
7267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Updates threads table whenever a message is added to sms.
7287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER sms_update_thread_on_insert AFTER INSERT ON sms " +
7297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE);
7307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Updates threads table whenever a message in pdu is updated.
7327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER pdu_update_thread_date_subject_on_update AFTER" +
7337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE OF " + Mms.DATE + ", " + Mms.SUBJECT + ", " + Mms.MESSAGE_BOX +
7347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  ON " + MmsProvider.TABLE_PDU + " " +
7357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PDU_UPDATE_THREAD_CONSTRAINTS +
7367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PDU_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE);
7377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Updates threads table whenever a message in sms is updated.
7397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER sms_update_thread_date_subject_on_update AFTER" +
7407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE OF " + Sms.DATE + ", " + Sms.BODY + ", " + Sms.TYPE +
7417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  ON sms " +
7427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE);
7437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Updates threads table whenever a message in pdu is updated.
7457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER pdu_update_thread_read_on_update AFTER" +
7467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE OF " + Mms.READ +
7477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  ON " + MmsProvider.TABLE_PDU + " " +
7487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PDU_UPDATE_THREAD_CONSTRAINTS +
7497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
7507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PDU_UPDATE_THREAD_READ_BODY +
7517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
7527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Updates threads table whenever a message in sms is updated.
7547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER sms_update_thread_read_on_update AFTER" +
7557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE OF " + Sms.READ +
7567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  ON sms " +
7577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
7587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   SMS_UPDATE_THREAD_READ_BODY +
7597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
7607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Update threads table whenever a message in pdu is deleted
7627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER pdu_update_thread_on_delete " +
7637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "AFTER DELETE ON pdu " +
7647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
7657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE threads SET " +
7667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "     date = (strftime('%s','now') * 1000)" +
7677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHERE threads._id = old." + Mms.THREAD_ID + "; " +
7687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   UPDATE_THREAD_COUNT_ON_OLD +
7697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   UPDATE_THREAD_SNIPPET_SNIPPET_CS_ON_DELETE +
7707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
7717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
772527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        // As of DATABASE_VERSION 55, we've removed these triggers that delete empty threads.
773527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        // These triggers interfere with saving drafts on brand new threads. Instead of
774527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        // triggers cleaning up empty threads, the empty threads should be cleaned up by
775527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        // an explicit call to delete with Threads.OBSOLETE_THREADS_URI.
776527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor
777527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//        // When the last message in a thread is deleted, these
778527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//        // triggers ensure that the entry for its thread ID is removed
779527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//        // from the threads table.
780527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//        db.execSQL("CREATE TRIGGER delete_obsolete_threads_pdu " +
781527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "AFTER DELETE ON pdu " +
782527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "BEGIN " +
783527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "  DELETE FROM threads " +
784527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "  WHERE " +
785527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "    _id = old.thread_id " +
786527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "    AND _id NOT IN " +
787527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "    (SELECT thread_id FROM sms " +
788527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "     UNION SELECT thread_id from pdu); " +
789527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "END;");
790527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//
791527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//        db.execSQL("CREATE TRIGGER delete_obsolete_threads_when_update_pdu " +
792527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "AFTER UPDATE OF " + Mms.THREAD_ID + " ON pdu " +
793527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "WHEN old." + Mms.THREAD_ID + " != new." + Mms.THREAD_ID + " " +
794527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "BEGIN " +
795527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "  DELETE FROM threads " +
796527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "  WHERE " +
797527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "    _id = old.thread_id " +
798527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "    AND _id NOT IN " +
799527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "    (SELECT thread_id FROM sms " +
800527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "     UNION SELECT thread_id from pdu); " +
801527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "END;");
8027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Insert pending status for M-Notification.ind or M-ReadRec.ind
8047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // when they are inserted into Inbox/Outbox.
8057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER insert_mms_pending_on_insert " +
8067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "AFTER INSERT ON pdu " +
807c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                   "WHEN new." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND +
808c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                   "  OR new." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_READ_REC_IND +
809c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                   " " +
8107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
8117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  INSERT INTO " + MmsSmsProvider.TABLE_PENDING_MSG +
8127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    (" + PendingMessages.PROTO_TYPE + "," +
8137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "     " + PendingMessages.MSG_ID + "," +
8147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "     " + PendingMessages.MSG_TYPE + "," +
8157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "     " + PendingMessages.ERROR_TYPE + "," +
8167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "     " + PendingMessages.ERROR_CODE + "," +
8177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "     " + PendingMessages.RETRY_INDEX + "," +
8187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "     " + PendingMessages.DUE_TIME + ") " +
8197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  VALUES " +
8207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    (" + MmsSms.MMS_PROTO + "," +
8217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "      new." + BaseColumns._ID + "," +
8227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "      new." + Mms.MESSAGE_TYPE + ",0,0,0,0);" +
8237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
8247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Insert pending status for M-Send.req when it is moved into Outbox.
8267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER insert_mms_pending_on_update " +
8277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "AFTER UPDATE ON pdu " +
828c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                   "WHEN new." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_SEND_REQ +
8297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  AND new." + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_OUTBOX +
8307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  AND old." + Mms.MESSAGE_BOX + "!=" + Mms.MESSAGE_BOX_OUTBOX + " " +
8317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
8327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  INSERT INTO " + MmsSmsProvider.TABLE_PENDING_MSG +
8337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    (" + PendingMessages.PROTO_TYPE + "," +
8347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "     " + PendingMessages.MSG_ID + "," +
8357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "     " + PendingMessages.MSG_TYPE + "," +
8367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "     " + PendingMessages.ERROR_TYPE + "," +
8377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "     " + PendingMessages.ERROR_CODE + "," +
8387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "     " + PendingMessages.RETRY_INDEX + "," +
8397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "     " + PendingMessages.DUE_TIME + ") " +
8407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  VALUES " +
8417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    (" + MmsSms.MMS_PROTO + "," +
8427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "      new." + BaseColumns._ID + "," +
8437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "      new." + Mms.MESSAGE_TYPE + ",0,0,0,0);" +
8447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
8457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // When a message is moved out of Outbox, delete its pending status.
8477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER delete_mms_pending_on_update " +
8487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "AFTER UPDATE ON " + MmsProvider.TABLE_PDU + " " +
8497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "WHEN old." + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_OUTBOX +
8507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  AND new." + Mms.MESSAGE_BOX + "!=" + Mms.MESSAGE_BOX_OUTBOX + " " +
8517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
8527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  DELETE FROM " + MmsSmsProvider.TABLE_PENDING_MSG +
8537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHERE " + PendingMessages.MSG_ID + "=new._id; " +
8547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
8557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Delete pending status for a message when it is deleted.
8577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER delete_mms_pending_on_delete " +
8587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "AFTER DELETE ON " + MmsProvider.TABLE_PDU + " " +
8597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
8607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  DELETE FROM " + MmsSmsProvider.TABLE_PENDING_MSG +
8617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHERE " + PendingMessages.MSG_ID + "=old._id; " +
8627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
8637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // TODO Add triggers for SMS retry-status management.
8657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Update the error flag of threads when the error type of
8677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // a pending MM is updated.
8687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER update_threads_error_on_update_mms " +
8697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  AFTER UPDATE OF err_type ON pending_msgs " +
8707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHEN (OLD.err_type < 10 AND NEW.err_type >= 10)" +
8717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    OR (OLD.err_type >= 10 AND NEW.err_type < 10) " +
8727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN" +
8737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE threads SET error = " +
8747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    CASE" +
8757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "      WHEN NEW.err_type >= 10 THEN error + 1" +
8767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "      ELSE error - 1" +
8777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    END " +
8787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHERE _id =" +
8797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "   (SELECT DISTINCT thread_id" +
8807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    FROM pdu" +
8817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    WHERE _id = NEW.msg_id); " +
8827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
8837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Update the error flag of threads when delete pending message.
8857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER update_threads_error_on_delete_mms " +
8867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  BEFORE DELETE ON pdu" +
8877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHEN OLD._id IN (SELECT DISTINCT msg_id" +
8887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "                   FROM pending_msgs" +
8897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "                   WHERE err_type >= 10) " +
8907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
8917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE threads SET error = error - 1" +
8927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHERE _id = OLD.thread_id; " +
8937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
8947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Update the error flag of threads while moving an MM out of Outbox,
8967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // which was failed to be sent permanently.
8977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER update_threads_error_on_move_mms " +
8987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  BEFORE UPDATE OF msg_box ON pdu " +
8997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHEN (OLD.msg_box = 4 AND NEW.msg_box != 4) " +
9007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  AND (OLD._id IN (SELECT DISTINCT msg_id" +
9017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "                   FROM pending_msgs" +
9027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "                   WHERE err_type >= 10)) " +
9037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
9047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE threads SET error = error - 1" +
9057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHERE _id = OLD.thread_id; " +
9067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
9077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Update the error flag of threads after a text message was
9097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // failed to send/receive.
9107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER update_threads_error_on_update_sms " +
9117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  AFTER UPDATE OF type ON sms" +
9127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHEN (OLD.type != 5 AND NEW.type = 5)" +
9137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    OR (OLD.type = 5 AND NEW.type != 5) " +
9147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
9157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE threads SET error = " +
9167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    CASE" +
9177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "      WHEN NEW.type = 5 THEN error + 1" +
9187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "      ELSE error - 1" +
9197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    END " +
9207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHERE _id = NEW.thread_id; " +
9217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
9227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
9237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    @Override
9257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
9267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Log.w(TAG, "Upgrading database from version " + oldVersion
9277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                + " to " + currentVersion + ".");
9287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        switch (oldVersion) {
9305f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        case 40:
9315f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            if (currentVersion <= 40) {
9325f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                return;
9335f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            }
9345f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project
9355f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            db.beginTransaction();
9365f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            try {
9375f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                upgradeDatabaseToVersion41(db);
9385f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                db.setTransactionSuccessful();
9395f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            } catch (Throwable ex) {
9405f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                Log.e(TAG, ex.getMessage(), ex);
9415f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                break;
9425f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            } finally {
9435f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                db.endTransaction();
9445f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            }
9455f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            // fall through
9465f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        case 41:
9475f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            if (currentVersion <= 41) {
9485f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                return;
9495f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            }
950f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
9515f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            db.beginTransaction();
9525f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            try {
9535f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                upgradeDatabaseToVersion42(db);
9545f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                db.setTransactionSuccessful();
9555f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            } catch (Throwable ex) {
9565f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                Log.e(TAG, ex.getMessage(), ex);
9575f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                break;
9585f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            } finally {
9595f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                db.endTransaction();
9605f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            }
9615f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            // fall through
9625f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        case 42:
9635f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            if (currentVersion <= 42) {
9647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                return;
9655f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            }
966f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
9675f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            db.beginTransaction();
9685f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            try {
9695f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                upgradeDatabaseToVersion43(db);
9705f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                db.setTransactionSuccessful();
9715f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            } catch (Throwable ex) {
9725f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                Log.e(TAG, ex.getMessage(), ex);
9735f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                break;
9745f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            } finally {
9755f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                db.endTransaction();
9765f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            }
9772ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            // fall through
9782ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang        case 43:
9792ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            if (currentVersion <= 43) {
9802ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                return;
9812ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            }
9822ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang
9832ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            db.beginTransaction();
9842ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            try {
9852ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                upgradeDatabaseToVersion44(db);
9862ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                db.setTransactionSuccessful();
9872ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            } catch (Throwable ex) {
9882ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                Log.e(TAG, ex.getMessage(), ex);
9892ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                break;
9902ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            } finally {
9912ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                db.endTransaction();
9922ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            }
993ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            // fall through
994a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor        case 44:
995a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor            if (currentVersion <= 44) {
996a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                return;
997a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor            }
998a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor
999a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor            db.beginTransaction();
1000a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor            try {
1001a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                upgradeDatabaseToVersion45(db);
1002a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                db.setTransactionSuccessful();
1003a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor            } catch (Throwable ex) {
1004a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                Log.e(TAG, ex.getMessage(), ex);
1005a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                break;
1006a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor            } finally {
1007a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                db.endTransaction();
1008a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor            }
1009ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            // fall through
1010f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        case 45:
1011f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            if (currentVersion <= 45) {
1012f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                return;
1013f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            }
1014f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            db.beginTransaction();
1015f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            try {
1016f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                upgradeDatabaseToVersion46(db);
1017f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                db.setTransactionSuccessful();
1018f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            } catch (Throwable ex) {
1019f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                Log.e(TAG, ex.getMessage(), ex);
1020f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                break;
1021f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            } finally {
1022f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                db.endTransaction();
1023f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            }
10241047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            // fall through
10251047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        case 46:
10261047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            if (currentVersion <= 46) {
10271047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                return;
10281047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            }
10291047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang
10301047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            db.beginTransaction();
10311047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            try {
10321047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                upgradeDatabaseToVersion47(db);
10331047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                db.setTransactionSuccessful();
10341047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            } catch (Throwable ex) {
10351047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                Log.e(TAG, ex.getMessage(), ex);
10361047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                break;
10371047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            } finally {
10381047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                db.endTransaction();
10391047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            }
1040ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            // fall through
1041ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor        case 47:
1042ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            if (currentVersion <= 47) {
1043ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor                return;
1044ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            }
1045ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor
1046ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            db.beginTransaction();
1047ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            try {
1048ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor                upgradeDatabaseToVersion48(db);
1049ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor                db.setTransactionSuccessful();
1050ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            } catch (Throwable ex) {
1051ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor                Log.e(TAG, ex.getMessage(), ex);
1052ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor                break;
1053ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            } finally {
1054ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor                db.endTransaction();
1055ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            }
1056dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            // fall through
10578e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        case 48:
10588e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            if (currentVersion <= 48) {
10598e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                return;
10608e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            }
10618e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
10628e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            db.beginTransaction();
10638e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            try {
10647ad939ed205080002ab32d318414337fc9c3ce1fTom Taylor                createWordsTables(db);
10658e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                db.setTransactionSuccessful();
10668e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            } catch (Throwable ex) {
10678e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                Log.e(TAG, ex.getMessage(), ex);
10688e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                break;
10698e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            } finally {
10708e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                db.endTransaction();
10718e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            }
1072dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            // fall through
1073a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor        case 49:
1074a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            if (currentVersion <= 49) {
1075a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor                return;
1076a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            }
1077a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            db.beginTransaction();
1078a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            try {
1079a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor                createThreadIdIndex(db);
1080a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor                db.setTransactionSuccessful();
1081a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            } catch (Throwable ex) {
1082a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor                Log.e(TAG, ex.getMessage(), ex);
1083a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor                break; // force to destroy all old data;
1084a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            } finally {
1085a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor                db.endTransaction();
1086a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            }
1087dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            // fall through
1088dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang        case 50:
1089dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            if (currentVersion <= 50) {
1090dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                return;
1091dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            }
10927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1093dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            db.beginTransaction();
1094dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            try {
1095dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                upgradeDatabaseToVersion51(db);
1096dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                db.setTransactionSuccessful();
1097dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            } catch (Throwable ex) {
1098dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                Log.e(TAG, ex.getMessage(), ex);
1099dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                break;
1100dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            } finally {
1101dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                db.endTransaction();
1102dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            }
1103fc0eb2f2905477c7200eb54584d2c104cd6d1adbTom Taylor            // fall through
1104fc0eb2f2905477c7200eb54584d2c104cd6d1adbTom Taylor        case 51:
1105fc0eb2f2905477c7200eb54584d2c104cd6d1adbTom Taylor            if (currentVersion <= 51) {
1106fc0eb2f2905477c7200eb54584d2c104cd6d1adbTom Taylor                return;
1107fc0eb2f2905477c7200eb54584d2c104cd6d1adbTom Taylor            }
11088a4060ec0c2433ceeb619a3a35fba5aabedbc1c6Tom Taylor            // 52 was adding a new meta_data column, but that was removed.
1109fc0eb2f2905477c7200eb54584d2c104cd6d1adbTom Taylor            // fall through
11101e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor        case 52:
11111e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor            if (currentVersion <= 52) {
11121e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                return;
11131e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor            }
1114dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang
11151e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor            db.beginTransaction();
11161e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor            try {
11171e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                upgradeDatabaseToVersion53(db);
11181e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                db.setTransactionSuccessful();
11191e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor            } catch (Throwable ex) {
11201e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                Log.e(TAG, ex.getMessage(), ex);
11211e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                break;
11221e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor            } finally {
11231e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                db.endTransaction();
11241e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor            }
1125ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            // fall through
1126ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        case 53:
1127ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            if (currentVersion <= 53) {
1128ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                return;
1129ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            }
1130ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert
1131ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            db.beginTransaction();
1132ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            try {
1133ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                upgradeDatabaseToVersion54(db);
1134ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                db.setTransactionSuccessful();
1135ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            } catch (Throwable ex) {
1136ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                Log.e(TAG, ex.getMessage(), ex);
1137ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                break;
1138ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            } finally {
1139ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                db.endTransaction();
1140ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            }
1141527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            // fall through
1142527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        case 54:
1143527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            if (currentVersion <= 54) {
1144527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor                return;
1145527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            }
1146527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor
1147527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            db.beginTransaction();
1148527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            try {
1149527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor                upgradeDatabaseToVersion55(db);
1150527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor                db.setTransactionSuccessful();
1151527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            } catch (Throwable ex) {
1152527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor                Log.e(TAG, ex.getMessage(), ex);
1153527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor                break;
1154527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            } finally {
1155527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor                db.endTransaction();
1156527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            }
1157dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            return;
1158a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor        }
1159f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
11605f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        Log.e(TAG, "Destroying all old data.");
11615f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        dropAll(db);
11627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        onCreate(db);
11637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
11647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11655f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    private void dropAll(SQLiteDatabase db) {
11665f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        // Clean the database out in order to start over from scratch.
11675f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        // We don't need to drop our triggers here because SQLite automatically
11685f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        // drops a trigger when its attached database is dropped.
11697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS canonical_addresses");
11707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS threads");
11717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS " + MmsSmsProvider.TABLE_PENDING_MSG);
11727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS sms");
11737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS raw");
11747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS attachments");
11757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS thread_ids");
11767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS sr_pending");
11777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_PDU + ";");
11787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_ADDR + ";");
11797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_PART + ";");
11807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_RATE + ";");
11817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_DRM + ";");
11827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
11837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void upgradeDatabaseToVersion41(SQLiteDatabase db) {
11857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TRIGGER IF EXISTS update_threads_error_on_move_mms");
11867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER update_threads_error_on_move_mms " +
11877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  BEFORE UPDATE OF msg_box ON pdu " +
11887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHEN (OLD.msg_box = 4 AND NEW.msg_box != 4) " +
11897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  AND (OLD._id IN (SELECT DISTINCT msg_id" +
11907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "                   FROM pending_msgs" +
11917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "                   WHERE err_type >= 10)) " +
11927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
11937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE threads SET error = error - 1" +
11947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHERE _id = OLD.thread_id; " +
11957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
11967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
1197f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
11987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void upgradeDatabaseToVersion42(SQLiteDatabase db) {
11997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TRIGGER IF EXISTS sms_update_thread_on_delete");
12007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TRIGGER IF EXISTS delete_obsolete_threads_sms");
12017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TRIGGER IF EXISTS update_threads_error_on_delete_sms");
12027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
1203f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
12045f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    private void upgradeDatabaseToVersion43(SQLiteDatabase db) {
12055f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        // Add 'has_attachment' column to threads table.
12065f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        db.execSQL("ALTER TABLE threads ADD COLUMN has_attachment INTEGER DEFAULT 0");
12075f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project
12081047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        updateThreadsAttachmentColumn(db);
12095f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project
12105f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        // Add insert and delete triggers for keeping it up to date.
12115f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        db.execSQL(PART_UPDATE_THREADS_ON_INSERT_TRIGGER);
12125f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        db.execSQL(PART_UPDATE_THREADS_ON_DELETE_TRIGGER);
12135f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    }
12142ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang
12152ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang    private void upgradeDatabaseToVersion44(SQLiteDatabase db) {
12161047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        updateThreadsAttachmentColumn(db);
12172ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang
12182ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang        // add the update trigger for keeping the threads up to date.
12192ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang        db.execSQL(PART_UPDATE_THREADS_ON_UPDATE_TRIGGER);
12202ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang    }
1221a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor
1222a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor    private void upgradeDatabaseToVersion45(SQLiteDatabase db) {
1223a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor        // Add 'locked' column to sms table.
1224fc0eb2f2905477c7200eb54584d2c104cd6d1adbTom Taylor        db.execSQL("ALTER TABLE sms ADD COLUMN " + Sms.LOCKED + " INTEGER DEFAULT 0");
1225a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor
1226a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor        // Add 'locked' column to pdu table.
1227a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor        db.execSQL("ALTER TABLE pdu ADD COLUMN " + Mms.LOCKED + " INTEGER DEFAULT 0");
1228a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor    }
1229a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor
1230f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner    private void upgradeDatabaseToVersion46(SQLiteDatabase db) {
1231f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        // add the "text" column for caching inline text (e.g. strings) instead of
1232f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        // putting them in an external file
1233f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        db.execSQL("ALTER TABLE part ADD COLUMN " + Part.TEXT + " TEXT");
1234f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
1235f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        Cursor textRows = db.query(
1236f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                "part",
1237f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                new String[] { Part._ID, Part._DATA, Part.TEXT},
1238f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                "ct = 'text/plain' OR ct == 'application/smil'",
1239f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                null,
1240f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                null,
1241f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                null,
1242f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                null);
1243f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        ArrayList<String> filesToDelete = new ArrayList<String>();
1244f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        try {
12450ebbb48f9f83ad65d738d1910a38e4fbdb920ac7Jeff Hamilton            db.beginTransaction();
1246f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            if (textRows != null) {
1247f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                int partDataColumn = textRows.getColumnIndex(Part._DATA);
1248f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
1249f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                // This code is imperfect in that we can't guarantee that all the
1250f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                // backing files get deleted.  For example if the system aborts after
1251f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                // the database is updated but before we complete the process of
1252f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                // deleting files.
1253f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                while (textRows.moveToNext()) {
1254f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                    String path = textRows.getString(partDataColumn);
1255f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                    if (path != null) {
1256f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                        try {
1257f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            InputStream is = new FileInputStream(path);
1258f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            byte [] data = new byte[is.available()];
1259f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            is.read(data);
1260f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            EncodedStringValue v = new EncodedStringValue(data);
12610ebbb48f9f83ad65d738d1910a38e4fbdb920ac7Jeff Hamilton                            db.execSQL("UPDATE part SET " + Part._DATA + " = NULL, " +
12620ebbb48f9f83ad65d738d1910a38e4fbdb920ac7Jeff Hamilton                                    Part.TEXT + " = ?", new String[] { v.getString() });
1263f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            is.close();
1264f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            filesToDelete.add(path);
1265f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                        } catch (IOException e) {
1266f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            // TODO Auto-generated catch block
1267f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            e.printStackTrace();
1268f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                        }
1269f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                    }
1270f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                }
1271f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            }
12720ebbb48f9f83ad65d738d1910a38e4fbdb920ac7Jeff Hamilton            db.setTransactionSuccessful();
1273f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        } finally {
12740ebbb48f9f83ad65d738d1910a38e4fbdb920ac7Jeff Hamilton            db.endTransaction();
1275f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            for (String pathToDelete : filesToDelete) {
1276f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                try {
1277f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                    (new File(pathToDelete)).delete();
1278f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                } catch (SecurityException ex) {
1279f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                    Log.e(TAG, "unable to clean up old mms file for " + pathToDelete, ex);
1280f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                }
1281f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            }
1282f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            if (textRows != null) {
1283f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                textRows.close();
1284f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            }
1285f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        }
1286f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner    }
12871047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang
12881047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang    private void upgradeDatabaseToVersion47(SQLiteDatabase db) {
12891047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        updateThreadsAttachmentColumn(db);
12901047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang
12911047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        // add the update trigger for keeping the threads up to date.
12921047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        db.execSQL(PDU_UPDATE_THREADS_ON_UPDATE_TRIGGER);
12931047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang    }
12941047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang
1295ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor    private void upgradeDatabaseToVersion48(SQLiteDatabase db) {
1296ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor        // Add 'error_code' column to sms table.
1297ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor        db.execSQL("ALTER TABLE sms ADD COLUMN error_code INTEGER DEFAULT 0");
1298ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor    }
1299ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor
1300dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang    private void upgradeDatabaseToVersion51(SQLiteDatabase db) {
1301dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang        db.execSQL("ALTER TABLE sms add COLUMN seen INTEGER DEFAULT 0");
1302dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang        db.execSQL("ALTER TABLE pdu add COLUMN seen INTEGER DEFAULT 0");
1303a882662df39eb5af84cc386fc09df4636166f48fWei Huang
1304a882662df39eb5af84cc386fc09df4636166f48fWei Huang        try {
1305a882662df39eb5af84cc386fc09df4636166f48fWei Huang            // update the existing sms and pdu tables so the new "seen" column is the same as
1306a882662df39eb5af84cc386fc09df4636166f48fWei Huang            // the "read" column for each row.
1307a882662df39eb5af84cc386fc09df4636166f48fWei Huang            ContentValues contentValues = new ContentValues();
1308a882662df39eb5af84cc386fc09df4636166f48fWei Huang            contentValues.put("seen", 1);
1309a882662df39eb5af84cc386fc09df4636166f48fWei Huang            int count = db.update("sms", contentValues, "read=1", null);
1310a882662df39eb5af84cc386fc09df4636166f48fWei Huang            Log.d(TAG, "[MmsSmsDb] upgradeDatabaseToVersion51: updated " + count +
1311a882662df39eb5af84cc386fc09df4636166f48fWei Huang                    " rows in sms table to have READ=1");
1312a882662df39eb5af84cc386fc09df4636166f48fWei Huang            count = db.update("pdu", contentValues, "read=1", null);
1313a882662df39eb5af84cc386fc09df4636166f48fWei Huang            Log.d(TAG, "[MmsSmsDb] upgradeDatabaseToVersion51: updated " + count +
1314a882662df39eb5af84cc386fc09df4636166f48fWei Huang                    " rows in pdu table to have READ=1");
1315a882662df39eb5af84cc386fc09df4636166f48fWei Huang        } catch (Exception ex) {
1316a882662df39eb5af84cc386fc09df4636166f48fWei Huang            Log.e(TAG, "[MmsSmsDb] upgradeDatabaseToVersion51 caught ", ex);
1317a882662df39eb5af84cc386fc09df4636166f48fWei Huang        }
1318dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang    }
1319dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang
1320ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert    private void upgradeDatabaseToVersion53(SQLiteDatabase db) {
1321ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        db.execSQL("DROP TRIGGER IF EXISTS pdu_update_thread_read_on_update");
1322ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert
1323ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        // Updates threads table whenever a message in pdu is updated.
1324ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        db.execSQL("CREATE TRIGGER pdu_update_thread_read_on_update AFTER" +
1325ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   "  UPDATE OF " + Mms.READ +
1326ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   "  ON " + MmsProvider.TABLE_PDU + " " +
1327ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   PDU_UPDATE_THREAD_CONSTRAINTS +
1328ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   "BEGIN " +
1329ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   PDU_UPDATE_THREAD_READ_BODY +
1330ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   "END;");
1331ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert    }
1332ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert
1333ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert    private void upgradeDatabaseToVersion54(SQLiteDatabase db) {
1334ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        // Add 'date_sent' column to sms table.
1335ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        db.execSQL("ALTER TABLE sms ADD COLUMN " + Sms.DATE_SENT + " INTEGER DEFAULT 0");
1336ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert
1337ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        // Add 'date_sent' column to pdu table.
1338ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        db.execSQL("ALTER TABLE pdu ADD COLUMN " + Mms.DATE_SENT + " INTEGER DEFAULT 0");
1339ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert    }
1340ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert
1341527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor    private void upgradeDatabaseToVersion55(SQLiteDatabase db) {
1342527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        // Drop removed triggers
1343527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS delete_obsolete_threads_pdu");
1344527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS delete_obsolete_threads_when_update_pdu");
1345527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor    }
1346527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor
13471ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    @Override
13481ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    public synchronized SQLiteDatabase getWritableDatabase() {
13491ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        SQLiteDatabase db = super.getWritableDatabase();
13501ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor
135110faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        if (!sTriedAutoIncrement) {
135210faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor            sTriedAutoIncrement = true;
135309710cec4926bcd3708376face04507e661bcc02Tom Taylor            boolean hasAutoIncrementThreads = hasAutoIncrement(db, "threads");
135409710cec4926bcd3708376face04507e661bcc02Tom Taylor            boolean hasAutoIncrementAddresses = hasAutoIncrement(db, "canonical_addresses");
135509710cec4926bcd3708376face04507e661bcc02Tom Taylor            Log.d(TAG, "[getWritableDatabase] hasAutoIncrementThreads: " + hasAutoIncrementThreads +
135609710cec4926bcd3708376face04507e661bcc02Tom Taylor                    " hasAutoIncrementAddresses: " + hasAutoIncrementAddresses);
135709710cec4926bcd3708376face04507e661bcc02Tom Taylor            boolean autoIncrementThreadsSuccess = true;
135809710cec4926bcd3708376face04507e661bcc02Tom Taylor            boolean autoIncrementAddressesSuccess = true;
135909710cec4926bcd3708376face04507e661bcc02Tom Taylor            if (!hasAutoIncrementThreads) {
13601ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                db.beginTransaction();
13611ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                try {
136210faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor                    if (false && sFakeLowStorageTest) {
136310faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor                        Log.d(TAG, "[getWritableDatabase] mFakeLowStorageTest is true " +
136410faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor                                " - fake exception");
136510faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor                        throw new Exception("FakeLowStorageTest");
136610faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor                    }
136709710cec4926bcd3708376face04507e661bcc02Tom Taylor                    upgradeThreadsTableToAutoIncrement(db);     // a no-op if already upgraded
13681ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                    db.setTransactionSuccessful();
13691ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                } catch (Throwable ex) {
137009710cec4926bcd3708376face04507e661bcc02Tom Taylor                    Log.e(TAG, "Failed to add autoIncrement to threads;: " + ex.getMessage(), ex);
137109710cec4926bcd3708376face04507e661bcc02Tom Taylor                    autoIncrementThreadsSuccess = false;
137209710cec4926bcd3708376face04507e661bcc02Tom Taylor                } finally {
137309710cec4926bcd3708376face04507e661bcc02Tom Taylor                    db.endTransaction();
137409710cec4926bcd3708376face04507e661bcc02Tom Taylor                }
137509710cec4926bcd3708376face04507e661bcc02Tom Taylor            }
137609710cec4926bcd3708376face04507e661bcc02Tom Taylor            if (!hasAutoIncrementAddresses) {
137709710cec4926bcd3708376face04507e661bcc02Tom Taylor                db.beginTransaction();
137809710cec4926bcd3708376face04507e661bcc02Tom Taylor                try {
137909710cec4926bcd3708376face04507e661bcc02Tom Taylor                    if (false && sFakeLowStorageTest) {
138009710cec4926bcd3708376face04507e661bcc02Tom Taylor                        Log.d(TAG, "[getWritableDatabase] mFakeLowStorageTest is true " +
138109710cec4926bcd3708376face04507e661bcc02Tom Taylor                        " - fake exception");
138209710cec4926bcd3708376face04507e661bcc02Tom Taylor                        throw new Exception("FakeLowStorageTest");
138310faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor                    }
138409710cec4926bcd3708376face04507e661bcc02Tom Taylor                    upgradeAddressTableToAutoIncrement(db);     // a no-op if already upgraded
138509710cec4926bcd3708376face04507e661bcc02Tom Taylor                    db.setTransactionSuccessful();
138609710cec4926bcd3708376face04507e661bcc02Tom Taylor                } catch (Throwable ex) {
138709710cec4926bcd3708376face04507e661bcc02Tom Taylor                    Log.e(TAG, "Failed to add autoIncrement to canonical_addresses: " +
138809710cec4926bcd3708376face04507e661bcc02Tom Taylor                            ex.getMessage(), ex);
138909710cec4926bcd3708376face04507e661bcc02Tom Taylor                    autoIncrementAddressesSuccess = false;
13901ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                } finally {
13911ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                    db.endTransaction();
13921ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                }
13931ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor            }
139409710cec4926bcd3708376face04507e661bcc02Tom Taylor            if (autoIncrementThreadsSuccess && autoIncrementAddressesSuccess) {
139509710cec4926bcd3708376face04507e661bcc02Tom Taylor                if (mLowStorageMonitor != null) {
139609710cec4926bcd3708376face04507e661bcc02Tom Taylor                    // We've already updated the database. This receiver is no longer necessary.
139709710cec4926bcd3708376face04507e661bcc02Tom Taylor                    Log.d(TAG, "Unregistering mLowStorageMonitor - we've upgraded");
139809710cec4926bcd3708376face04507e661bcc02Tom Taylor                    mContext.unregisterReceiver(mLowStorageMonitor);
139909710cec4926bcd3708376face04507e661bcc02Tom Taylor                    mLowStorageMonitor = null;
140009710cec4926bcd3708376face04507e661bcc02Tom Taylor                }
140109710cec4926bcd3708376face04507e661bcc02Tom Taylor            } else {
140209710cec4926bcd3708376face04507e661bcc02Tom Taylor                if (sFakeLowStorageTest) {
140309710cec4926bcd3708376face04507e661bcc02Tom Taylor                    sFakeLowStorageTest = false;
140409710cec4926bcd3708376face04507e661bcc02Tom Taylor                }
140509710cec4926bcd3708376face04507e661bcc02Tom Taylor
140609710cec4926bcd3708376face04507e661bcc02Tom Taylor                // We failed, perhaps because of low storage. Turn on a receiver to watch for
140709710cec4926bcd3708376face04507e661bcc02Tom Taylor                // storage space.
140809710cec4926bcd3708376face04507e661bcc02Tom Taylor                if (mLowStorageMonitor == null) {
140909710cec4926bcd3708376face04507e661bcc02Tom Taylor                    Log.d(TAG, "[getWritableDatabase] turning on storage monitor");
141009710cec4926bcd3708376face04507e661bcc02Tom Taylor                    mLowStorageMonitor = new LowStorageMonitor();
141109710cec4926bcd3708376face04507e661bcc02Tom Taylor                    IntentFilter intentFilter = new IntentFilter();
141209710cec4926bcd3708376face04507e661bcc02Tom Taylor                    intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_LOW);
141309710cec4926bcd3708376face04507e661bcc02Tom Taylor                    intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
141409710cec4926bcd3708376face04507e661bcc02Tom Taylor                    mContext.registerReceiver(mLowStorageMonitor, intentFilter);
141509710cec4926bcd3708376face04507e661bcc02Tom Taylor                }
141609710cec4926bcd3708376face04507e661bcc02Tom Taylor            }
14171ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        }
14181ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        return db;
14191ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    }
14201ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor
142109710cec4926bcd3708376face04507e661bcc02Tom Taylor    // Determine whether a particular table has AUTOINCREMENT in its schema.
142209710cec4926bcd3708376face04507e661bcc02Tom Taylor    private boolean hasAutoIncrement(SQLiteDatabase db, String tableName) {
14231ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        boolean result = false;
142409710cec4926bcd3708376face04507e661bcc02Tom Taylor        String query = "SELECT sql FROM sqlite_master WHERE type='table' AND name='" +
142509710cec4926bcd3708376face04507e661bcc02Tom Taylor                        tableName + "'";
14261ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        Cursor c = db.rawQuery(query, null);
14271ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        if (c != null) {
14281ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor            try {
14291ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                if (c.moveToFirst()) {
14301ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                    String schema = c.getString(0);
14311ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                    result = schema != null ? schema.contains("AUTOINCREMENT") : false;
143209710cec4926bcd3708376face04507e661bcc02Tom Taylor                    Log.d(TAG, "[MmsSmsDb] tableName: " + tableName + " hasAutoIncrement: " +
143309710cec4926bcd3708376face04507e661bcc02Tom Taylor                            schema + " result: " + result);
14341ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                }
14351ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor            } finally {
14361ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                c.close();
14371ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor            }
14381ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        }
14391ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        return result;
14401ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    }
14411ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor
14421ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    // upgradeThreadsTableToAutoIncrement() is called to add the AUTOINCREMENT keyword to
14431ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    // the threads table. This could fail if the user has a lot of conversations and not enough
14441ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    // storage to make a copy of the threads table. That's ok. This upgrade is optional. It'll
14451ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    // be called again next time the device is rebooted.
14461ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    private void upgradeThreadsTableToAutoIncrement(SQLiteDatabase db) {
144709710cec4926bcd3708376face04507e661bcc02Tom Taylor        if (hasAutoIncrement(db, "threads")) {
14481ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor            Log.d(TAG, "[MmsSmsDb] upgradeThreadsTableToAutoIncrement: already upgraded");
14491ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor            return;
14501ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        }
14511ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        Log.d(TAG, "[MmsSmsDb] upgradeThreadsTableToAutoIncrement: upgrading");
14521ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor
14531ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        // Make the _id of the threads table autoincrement so we never re-use thread ids
14541ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        // Have to create a new temp threads table. Copy all the info from the old table.
14551ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        // Drop the old table and rename the new table to that of the old.
14561ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        db.execSQL("CREATE TABLE threads_temp (" +
14571ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
14581ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.DATE + " INTEGER DEFAULT 0," +
14591ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.MESSAGE_COUNT + " INTEGER DEFAULT 0," +
14601ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.RECIPIENT_IDS + " TEXT," +
14611ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.SNIPPET + " TEXT," +
14621ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.SNIPPET_CHARSET + " INTEGER DEFAULT 0," +
14631ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.READ + " INTEGER DEFAULT 1," +
14641ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.TYPE + " INTEGER DEFAULT 0," +
14651ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.ERROR + " INTEGER DEFAULT 0," +
14661ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.HAS_ATTACHMENT + " INTEGER DEFAULT 0);");
14671ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor
14681ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        db.execSQL("INSERT INTO threads_temp SELECT * from threads;");
14691ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        db.execSQL("DROP TABLE threads;");
14701ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        db.execSQL("ALTER TABLE threads_temp RENAME TO threads;");
14711ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    }
14721ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor
147309710cec4926bcd3708376face04507e661bcc02Tom Taylor    // upgradeAddressTableToAutoIncrement() is called to add the AUTOINCREMENT keyword to
147409710cec4926bcd3708376face04507e661bcc02Tom Taylor    // the canonical_addresses table. This could fail if the user has a lot of people they've
147509710cec4926bcd3708376face04507e661bcc02Tom Taylor    // messaged with and not enough storage to make a copy of the canonical_addresses table.
147609710cec4926bcd3708376face04507e661bcc02Tom Taylor    // That's ok. This upgrade is optional. It'll be called again next time the device is rebooted.
147709710cec4926bcd3708376face04507e661bcc02Tom Taylor    private void upgradeAddressTableToAutoIncrement(SQLiteDatabase db) {
147809710cec4926bcd3708376face04507e661bcc02Tom Taylor        if (hasAutoIncrement(db, "canonical_addresses")) {
147909710cec4926bcd3708376face04507e661bcc02Tom Taylor            Log.d(TAG, "[MmsSmsDb] upgradeAddressTableToAutoIncrement: already upgraded");
148009710cec4926bcd3708376face04507e661bcc02Tom Taylor            return;
148109710cec4926bcd3708376face04507e661bcc02Tom Taylor        }
148209710cec4926bcd3708376face04507e661bcc02Tom Taylor        Log.d(TAG, "[MmsSmsDb] upgradeAddressTableToAutoIncrement: upgrading");
148309710cec4926bcd3708376face04507e661bcc02Tom Taylor
148409710cec4926bcd3708376face04507e661bcc02Tom Taylor        // Make the _id of the canonical_addresses table autoincrement so we never re-use ids
148509710cec4926bcd3708376face04507e661bcc02Tom Taylor        // Have to create a new temp canonical_addresses table. Copy all the info from the old
148609710cec4926bcd3708376face04507e661bcc02Tom Taylor        // table. Drop the old table and rename the new table to that of the old.
148709710cec4926bcd3708376face04507e661bcc02Tom Taylor        db.execSQL("CREATE TABLE canonical_addresses_temp (_id INTEGER PRIMARY KEY AUTOINCREMENT," +
148809710cec4926bcd3708376face04507e661bcc02Tom Taylor                "address TEXT);");
148909710cec4926bcd3708376face04507e661bcc02Tom Taylor
149009710cec4926bcd3708376face04507e661bcc02Tom Taylor        db.execSQL("INSERT INTO canonical_addresses_temp SELECT * from canonical_addresses;");
149109710cec4926bcd3708376face04507e661bcc02Tom Taylor        db.execSQL("DROP TABLE canonical_addresses;");
149209710cec4926bcd3708376face04507e661bcc02Tom Taylor        db.execSQL("ALTER TABLE canonical_addresses_temp RENAME TO canonical_addresses;");
149309710cec4926bcd3708376face04507e661bcc02Tom Taylor    }
149409710cec4926bcd3708376face04507e661bcc02Tom Taylor
149510faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor    private class LowStorageMonitor extends BroadcastReceiver {
149610faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor
149710faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        public LowStorageMonitor() {
149810faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        }
149910faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor
150010faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        public void onReceive(Context context, Intent intent) {
150110faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor            String action = intent.getAction();
150210faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor
150310faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor            Log.d(TAG, "[LowStorageMonitor] onReceive intent " + action);
150410faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor
150510faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor            if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) {
150610faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor                sTriedAutoIncrement = false;    // try to upgrade on the next getWriteableDatabase
150710faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor            }
150810faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        }
150910faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor    }
151010faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor
15111047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang    private void updateThreadsAttachmentColumn(SQLiteDatabase db) {
15121047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        // Set the values of that column correctly based on the current
15131047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        // contents of the database.
15141047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        db.execSQL("UPDATE threads SET has_attachment=1 WHERE _id IN " +
15151047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                   "  (SELECT DISTINCT pdu.thread_id FROM part " +
15161047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                   "   JOIN pdu ON pdu._id=part.mid " +
15171047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                   "   WHERE part.ct != 'text/plain' AND part.ct != 'application/smil')");
15181047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang    }
15197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project}
1520