The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2008 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.android.providers.telephony; |
| 18 | |
Tom Taylor | 10faf3f | 2011-04-27 10:05:03 -0700 | [diff] [blame] | 19 | import android.content.BroadcastReceiver; |
Mark Wagner | 8e5ee78 | 2010-01-04 17:39:06 -0800 | [diff] [blame] | 20 | import android.content.ContentValues; |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 21 | import android.content.Context; |
Tom Taylor | 10faf3f | 2011-04-27 10:05:03 -0700 | [diff] [blame] | 22 | import android.content.Intent; |
| 23 | import android.content.IntentFilter; |
Prasath Balakrishnan | 1dfaed1 | 2015-11-18 20:36:17 +0530 | [diff] [blame] | 24 | import android.content.SharedPreferences; |
| 25 | import android.content.SharedPreferences.Editor; |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 26 | import android.database.Cursor; |
| 27 | import android.database.sqlite.SQLiteDatabase; |
yanglv | 3dd0bab | 2015-08-24 10:40:19 +0800 | [diff] [blame] | 28 | import android.database.sqlite.SQLiteException; |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 29 | import android.database.sqlite.SQLiteOpenHelper; |
| 30 | import android.provider.BaseColumns; |
Mark Wagner | 8e5ee78 | 2010-01-04 17:39:06 -0800 | [diff] [blame] | 31 | import android.provider.Telephony; |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 32 | import android.provider.Telephony.Mms; |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 33 | import android.provider.Telephony.Mms.Addr; |
| 34 | import android.provider.Telephony.Mms.Part; |
| 35 | import android.provider.Telephony.Mms.Rate; |
Ye Wen | 72f1355 | 2015-03-10 14:17:13 -0700 | [diff] [blame] | 36 | import android.provider.Telephony.MmsSms; |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 37 | import android.provider.Telephony.MmsSms.PendingMessages; |
Ye Wen | 72f1355 | 2015-03-10 14:17:13 -0700 | [diff] [blame] | 38 | import android.provider.Telephony.Sms; |
| 39 | import android.provider.Telephony.Threads; |
Shri Borde | a58acf3 | 2014-09-17 15:18:01 -0700 | [diff] [blame] | 40 | import android.telephony.SubscriptionManager; |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 41 | import android.util.Log; |
| 42 | |
Tom Taylor | b1bae65 | 2010-03-08 16:33:42 -0800 | [diff] [blame] | 43 | import com.google.android.mms.pdu.EncodedStringValue; |
| 44 | import com.google.android.mms.pdu.PduHeaders; |
Tom Taylor | c71e770 | 2010-01-28 09:23:12 -0800 | [diff] [blame] | 45 | |
Ye Wen | 72f1355 | 2015-03-10 14:17:13 -0700 | [diff] [blame] | 46 | import java.io.File; |
| 47 | import java.io.FileInputStream; |
| 48 | import java.io.IOException; |
| 49 | import java.io.InputStream; |
| 50 | import java.util.ArrayList; |
| 51 | import java.util.HashSet; |
| 52 | import java.util.Iterator; |
| 53 | |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 54 | public class MmsSmsDatabaseHelper extends SQLiteOpenHelper { |
| 55 | private static final String TAG = "MmsSmsDatabaseHelper"; |
| 56 | |
| 57 | private static final String SMS_UPDATE_THREAD_READ_BODY = |
| 58 | " UPDATE threads SET read = " + |
| 59 | " CASE (SELECT COUNT(*)" + |
| 60 | " FROM sms" + |
| 61 | " WHERE " + Sms.READ + " = 0" + |
| 62 | " AND " + Sms.THREAD_ID + " = threads._id)" + |
| 63 | " WHEN 0 THEN 1" + |
| 64 | " ELSE 0" + |
| 65 | " END" + |
| 66 | " WHERE threads._id = new." + Sms.THREAD_ID + "; "; |
| 67 | |
| 68 | private static final String UPDATE_THREAD_COUNT_ON_NEW = |
| 69 | " UPDATE threads SET message_count = " + |
| 70 | " (SELECT COUNT(sms._id) FROM sms LEFT JOIN threads " + |
| 71 | " ON threads._id = " + Sms.THREAD_ID + |
| 72 | " WHERE " + Sms.THREAD_ID + " = new.thread_id" + |
| 73 | " AND sms." + Sms.TYPE + " != 3) + " + |
| 74 | " (SELECT COUNT(pdu._id) FROM pdu LEFT JOIN threads " + |
| 75 | " ON threads._id = " + Mms.THREAD_ID + |
| 76 | " WHERE " + Mms.THREAD_ID + " = new.thread_id" + |
| 77 | " AND (m_type=132 OR m_type=130 OR m_type=128)" + |
| 78 | " AND " + Mms.MESSAGE_BOX + " != 3) " + |
| 79 | " WHERE threads._id = new.thread_id; "; |
| 80 | |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 81 | private static final String SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE = |
| 82 | "BEGIN" + |
| 83 | " UPDATE threads SET" + |
| 84 | " date = (strftime('%s','now') * 1000), " + |
| 85 | " snippet = new." + Sms.BODY + ", " + |
| 86 | " snippet_cs = 0" + |
| 87 | " WHERE threads._id = new." + Sms.THREAD_ID + "; " + |
| 88 | UPDATE_THREAD_COUNT_ON_NEW + |
| 89 | SMS_UPDATE_THREAD_READ_BODY + |
| 90 | "END;"; |
| 91 | |
| 92 | private static final String PDU_UPDATE_THREAD_CONSTRAINTS = |
Tom Taylor | c71e770 | 2010-01-28 09:23:12 -0800 | [diff] [blame] | 93 | " WHEN new." + Mms.MESSAGE_TYPE + "=" + |
| 94 | PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF + |
| 95 | " OR new." + Mms.MESSAGE_TYPE + "=" + |
| 96 | PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND + |
| 97 | " OR new." + Mms.MESSAGE_TYPE + "=" + |
| 98 | PduHeaders.MESSAGE_TYPE_SEND_REQ + " "; |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 99 | |
Tom Taylor | 1e47c48 | 2010-03-12 16:14:50 -0800 | [diff] [blame] | 100 | // When looking in the pdu table for unread messages, only count messages that |
| 101 | // are displayed to the user. The constants are defined in PduHeaders and could be used |
| 102 | // here, but the string "(m_type=132 OR m_type=130 OR m_type=128)" is used throughout this |
| 103 | // file and so it is used here to be consistent. |
| 104 | // m_type=128 = MESSAGE_TYPE_SEND_REQ |
| 105 | // m_type=130 = MESSAGE_TYPE_NOTIFICATION_IND |
| 106 | // m_type=132 = MESSAGE_TYPE_RETRIEVE_CONF |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 107 | private static final String PDU_UPDATE_THREAD_READ_BODY = |
| 108 | " UPDATE threads SET read = " + |
| 109 | " CASE (SELECT COUNT(*)" + |
| 110 | " FROM " + MmsProvider.TABLE_PDU + |
| 111 | " WHERE " + Mms.READ + " = 0" + |
Tom Taylor | 1e47c48 | 2010-03-12 16:14:50 -0800 | [diff] [blame] | 112 | " AND " + Mms.THREAD_ID + " = threads._id " + |
| 113 | " AND (m_type=132 OR m_type=130 OR m_type=128)) " + |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 114 | " WHEN 0 THEN 1" + |
| 115 | " ELSE 0" + |
| 116 | " END" + |
| 117 | " WHERE threads._id = new." + Mms.THREAD_ID + "; "; |
| 118 | |
| 119 | private static final String PDU_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE = |
| 120 | "BEGIN" + |
| 121 | " UPDATE threads SET" + |
| 122 | " date = (strftime('%s','now') * 1000), " + |
| 123 | " snippet = new." + Mms.SUBJECT + ", " + |
| 124 | " snippet_cs = new." + Mms.SUBJECT_CHARSET + |
| 125 | " WHERE threads._id = new." + Mms.THREAD_ID + "; " + |
| 126 | UPDATE_THREAD_COUNT_ON_NEW + |
| 127 | PDU_UPDATE_THREAD_READ_BODY + |
| 128 | "END;"; |
| 129 | |
The Android Open Source Project | 5f1e43f | 2009-03-05 14:34:39 -0800 | [diff] [blame] | 130 | // When a part is inserted, if it is not text/plain or application/smil |
| 131 | // (which both can exist with text-only MMSes), then there is an attachment. |
| 132 | // Set has_attachment=1 in the threads table for the thread in question. |
| 133 | private static final String PART_UPDATE_THREADS_ON_INSERT_TRIGGER = |
| 134 | "CREATE TRIGGER update_threads_on_insert_part " + |
| 135 | " AFTER INSERT ON part " + |
| 136 | " WHEN new.ct != 'text/plain' AND new.ct != 'application/smil' " + |
| 137 | " BEGIN " + |
| 138 | " UPDATE threads SET has_attachment=1 WHERE _id IN " + |
| 139 | " (SELECT pdu.thread_id FROM part JOIN pdu ON pdu._id=part.mid " + |
| 140 | " WHERE part._id=new._id LIMIT 1); " + |
| 141 | " END"; |
Wei Huang | 2ad5ba8 | 2009-03-24 20:01:04 -0700 | [diff] [blame] | 142 | |
| 143 | // When the 'mid' column in the part table is updated, we need to run the trigger to update |
| 144 | // the threads table's has_attachment column, if the part is an attachment. |
| 145 | private static final String PART_UPDATE_THREADS_ON_UPDATE_TRIGGER = |
| 146 | "CREATE TRIGGER update_threads_on_update_part " + |
| 147 | " AFTER UPDATE of " + Part.MSG_ID + " ON part " + |
| 148 | " WHEN new.ct != 'text/plain' AND new.ct != 'application/smil' " + |
| 149 | " BEGIN " + |
| 150 | " UPDATE threads SET has_attachment=1 WHERE _id IN " + |
| 151 | " (SELECT pdu.thread_id FROM part JOIN pdu ON pdu._id=part.mid " + |
| 152 | " WHERE part._id=new._id LIMIT 1); " + |
| 153 | " END"; |
| 154 | |
Wei Huang | 1047ab4 | 2009-09-29 20:53:26 -0700 | [diff] [blame] | 155 | // When the 'thread_id' column in the pdu table is updated, we need to run the trigger to update |
| 156 | // the threads table's has_attachment column, if the message has an attachment in 'part' table |
| 157 | private static final String PDU_UPDATE_THREADS_ON_UPDATE_TRIGGER = |
| 158 | "CREATE TRIGGER update_threads_on_update_pdu " + |
| 159 | " AFTER UPDATE of thread_id ON pdu " + |
| 160 | " BEGIN " + |
| 161 | " UPDATE threads SET has_attachment=1 WHERE _id IN " + |
Tom Taylor | 94489f8 | 2010-02-22 16:25:10 -0800 | [diff] [blame] | 162 | " (SELECT pdu.thread_id FROM part JOIN pdu " + |
| 163 | " WHERE part.ct != 'text/plain' AND part.ct != 'application/smil' " + |
| 164 | " AND part.mid = pdu._id);" + |
Wei Huang | 1047ab4 | 2009-09-29 20:53:26 -0700 | [diff] [blame] | 165 | " END"; |
| 166 | |
Tom Taylor | 10faf3f | 2011-04-27 10:05:03 -0700 | [diff] [blame] | 167 | private static MmsSmsDatabaseHelper sInstance = null; |
| 168 | private static boolean sTriedAutoIncrement = false; |
| 169 | private static boolean sFakeLowStorageTest = false; // for testing only |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 170 | |
yanglv | 3dd0bab | 2015-08-24 10:40:19 +0800 | [diff] [blame] | 171 | private static final String NO_SUCH_COLUMN_EXCEPTION_MESSAGE = "no such column"; |
| 172 | private static final String NO_SUCH_TABLE_EXCEPTION_MESSAGE = "no such table"; |
| 173 | |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 174 | static final String DATABASE_NAME = "mmssms.db"; |
Ye Wen | 72f1355 | 2015-03-10 14:17:13 -0700 | [diff] [blame] | 175 | static final int DATABASE_VERSION = 61; |
Tom Taylor | 10faf3f | 2011-04-27 10:05:03 -0700 | [diff] [blame] | 176 | private final Context mContext; |
| 177 | private LowStorageMonitor mLowStorageMonitor; |
Tom Taylor | 1ab4800 | 2011-04-19 14:15:06 -0700 | [diff] [blame] | 178 | |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 179 | private MmsSmsDatabaseHelper(Context context) { |
| 180 | super(context, DATABASE_NAME, null, DATABASE_VERSION); |
Tom Taylor | 10faf3f | 2011-04-27 10:05:03 -0700 | [diff] [blame] | 181 | |
| 182 | mContext = context; |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 183 | } |
| 184 | |
| 185 | /** |
| 186 | * Return a singleton helper for the combined MMS and SMS |
| 187 | * database. |
| 188 | */ |
| 189 | /* package */ static synchronized MmsSmsDatabaseHelper getInstance(Context context) { |
Tom Taylor | 10faf3f | 2011-04-27 10:05:03 -0700 | [diff] [blame] | 190 | if (sInstance == null) { |
| 191 | sInstance = new MmsSmsDatabaseHelper(context); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 192 | } |
Tom Taylor | 10faf3f | 2011-04-27 10:05:03 -0700 | [diff] [blame] | 193 | return sInstance; |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 194 | } |
| 195 | |
Tom Taylor | f409b0e | 2011-12-19 12:52:18 -0800 | [diff] [blame] | 196 | /** |
| 197 | * Look through all the recipientIds referenced by the threads and then delete any |
| 198 | * unreferenced rows from the canonical_addresses table. |
| 199 | */ |
| 200 | private static void removeUnferencedCanonicalAddresses(SQLiteDatabase db) { |
Tom Taylor | 15156cd | 2012-11-15 14:15:46 -0800 | [diff] [blame] | 201 | Cursor c = db.query(MmsSmsProvider.TABLE_THREADS, new String[] { "recipient_ids" }, |
Tom Taylor | f409b0e | 2011-12-19 12:52:18 -0800 | [diff] [blame] | 202 | null, null, null, null, null); |
| 203 | if (c != null) { |
| 204 | try { |
| 205 | if (c.getCount() == 0) { |
| 206 | // no threads, delete all addresses |
| 207 | int rows = db.delete("canonical_addresses", null, null); |
| 208 | } else { |
| 209 | // Find all the referenced recipient_ids from the threads. recipientIds is |
| 210 | // a space-separated list of recipient ids: "1 14 21" |
| 211 | HashSet<Integer> recipientIds = new HashSet<Integer>(); |
| 212 | while (c.moveToNext()) { |
| 213 | String[] recips = c.getString(0).split(" "); |
| 214 | for (String recip : recips) { |
| 215 | try { |
| 216 | int recipientId = Integer.parseInt(recip); |
| 217 | recipientIds.add(recipientId); |
| 218 | } catch (Exception e) { |
| 219 | } |
| 220 | } |
| 221 | } |
| 222 | // Now build a selection string of all the unique recipient ids |
kaiyiz | 6d65c1e | 2014-11-17 18:29:40 +0800 | [diff] [blame] | 223 | StringBuilder sb = new StringBuilder("_id not in ("); |
Tom Taylor | f409b0e | 2011-12-19 12:52:18 -0800 | [diff] [blame] | 224 | Iterator<Integer> iter = recipientIds.iterator(); |
| 225 | while (iter.hasNext()) { |
kaiyiz | 6d65c1e | 2014-11-17 18:29:40 +0800 | [diff] [blame] | 226 | sb.append(iter.next()); |
Tom Taylor | f409b0e | 2011-12-19 12:52:18 -0800 | [diff] [blame] | 227 | if (iter.hasNext()) { |
kaiyiz | 6d65c1e | 2014-11-17 18:29:40 +0800 | [diff] [blame] | 228 | sb.append(","); |
Tom Taylor | f409b0e | 2011-12-19 12:52:18 -0800 | [diff] [blame] | 229 | } |
| 230 | } |
kaiyiz | 6d65c1e | 2014-11-17 18:29:40 +0800 | [diff] [blame] | 231 | sb.append(")"); |
| 232 | if (recipientIds.size() > 0) { |
Tom Taylor | f409b0e | 2011-12-19 12:52:18 -0800 | [diff] [blame] | 233 | int rows = db.delete("canonical_addresses", sb.toString(), null); |
| 234 | } |
| 235 | } |
| 236 | } finally { |
| 237 | c.close(); |
| 238 | } |
| 239 | } |
| 240 | } |
| 241 | |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 242 | public static void updateThread(SQLiteDatabase db, long thread_id) { |
| 243 | if (thread_id < 0) { |
| 244 | updateAllThreads(db, null, null); |
| 245 | return; |
| 246 | } |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 247 | |
Tom Taylor | 842e311 | 2012-09-26 15:01:42 -0700 | [diff] [blame] | 248 | db.beginTransaction(); |
| 249 | try { |
| 250 | // Delete the row for this thread in the threads table if |
| 251 | // there are no more messages attached to it in either |
| 252 | // the sms or pdu tables. |
Tom Taylor | 15156cd | 2012-11-15 14:15:46 -0800 | [diff] [blame] | 253 | int rows = db.delete(MmsSmsProvider.TABLE_THREADS, |
Tom Taylor | 842e311 | 2012-09-26 15:01:42 -0700 | [diff] [blame] | 254 | "_id = ? AND _id NOT IN" + |
| 255 | " (SELECT thread_id FROM sms " + |
| 256 | " UNION SELECT thread_id FROM pdu)", |
| 257 | new String[] { String.valueOf(thread_id) }); |
| 258 | if (rows > 0) { |
| 259 | // If this deleted a row, let's remove orphaned canonical_addresses and get outta here |
| 260 | removeUnferencedCanonicalAddresses(db); |
| 261 | } else { |
| 262 | // Update the message count in the threads table as the sum |
| 263 | // of all messages in both the sms and pdu tables. |
| 264 | db.execSQL( |
| 265 | " UPDATE threads SET message_count = " + |
| 266 | " (SELECT COUNT(sms._id) FROM sms LEFT JOIN threads " + |
| 267 | " ON threads._id = " + Sms.THREAD_ID + |
| 268 | " WHERE " + Sms.THREAD_ID + " = " + thread_id + |
| 269 | " AND sms." + Sms.TYPE + " != 3) + " + |
| 270 | " (SELECT COUNT(pdu._id) FROM pdu LEFT JOIN threads " + |
| 271 | " ON threads._id = " + Mms.THREAD_ID + |
| 272 | " WHERE " + Mms.THREAD_ID + " = " + thread_id + |
| 273 | " AND (m_type=132 OR m_type=130 OR m_type=128)" + |
| 274 | " AND " + Mms.MESSAGE_BOX + " != 3) " + |
| 275 | " WHERE threads._id = " + thread_id + ";"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 276 | |
Tom Taylor | 842e311 | 2012-09-26 15:01:42 -0700 | [diff] [blame] | 277 | // Update the date and the snippet (and its character set) in |
| 278 | // the threads table to be that of the most recent message in |
| 279 | // the thread. |
| 280 | db.execSQL( |
| 281 | " UPDATE threads" + |
| 282 | " SET" + |
| 283 | " date =" + |
| 284 | " (SELECT date FROM" + |
| 285 | " (SELECT date * 1000 AS date, thread_id FROM pdu" + |
| 286 | " UNION SELECT date, thread_id FROM sms)" + |
| 287 | " WHERE thread_id = " + thread_id + " ORDER BY date DESC LIMIT 1)," + |
| 288 | " snippet =" + |
| 289 | " (SELECT snippet FROM" + |
| 290 | " (SELECT date * 1000 AS date, sub AS snippet, thread_id FROM pdu" + |
| 291 | " UNION SELECT date, body AS snippet, thread_id FROM sms)" + |
| 292 | " WHERE thread_id = " + thread_id + " ORDER BY date DESC LIMIT 1)," + |
| 293 | " snippet_cs =" + |
| 294 | " (SELECT snippet_cs FROM" + |
| 295 | " (SELECT date * 1000 AS date, sub_cs AS snippet_cs, thread_id FROM pdu" + |
| 296 | " UNION SELECT date, 0 AS snippet_cs, thread_id FROM sms)" + |
| 297 | " WHERE thread_id = " + thread_id + " ORDER BY date DESC LIMIT 1)" + |
| 298 | " WHERE threads._id = " + thread_id + ";"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 299 | |
Tom Taylor | 842e311 | 2012-09-26 15:01:42 -0700 | [diff] [blame] | 300 | // Update the error column of the thread to indicate if there |
| 301 | // are any messages in it that have failed to send. |
| 302 | // First check to see if there are any messages with errors in this thread. |
| 303 | String query = "SELECT thread_id FROM sms WHERE type=" + |
| 304 | Telephony.TextBasedSmsColumns.MESSAGE_TYPE_FAILED + |
| 305 | " AND thread_id = " + thread_id + |
| 306 | " LIMIT 1"; |
| 307 | int setError = 0; |
| 308 | Cursor c = db.rawQuery(query, null); |
| 309 | if (c != null) { |
| 310 | try { |
| 311 | setError = c.getCount(); // Because of the LIMIT 1, count will be 1 or 0. |
| 312 | } finally { |
| 313 | c.close(); |
Tom Taylor | 9565e7f | 2010-03-01 14:05:46 -0800 | [diff] [blame] | 314 | } |
| 315 | } |
Tom Taylor | 842e311 | 2012-09-26 15:01:42 -0700 | [diff] [blame] | 316 | // What's the current state of the error flag in the threads table? |
| 317 | String errorQuery = "SELECT error FROM threads WHERE _id = " + thread_id; |
| 318 | c = db.rawQuery(errorQuery, null); |
| 319 | if (c != null) { |
| 320 | try { |
| 321 | if (c.moveToNext()) { |
| 322 | int curError = c.getInt(0); |
| 323 | if (curError != setError) { |
| 324 | // The current thread error column differs, update it. |
| 325 | db.execSQL("UPDATE threads SET error=" + setError + |
| 326 | " WHERE _id = " + thread_id); |
| 327 | } |
| 328 | } |
| 329 | } finally { |
| 330 | c.close(); |
| 331 | } |
| 332 | } |
Tom Taylor | 9565e7f | 2010-03-01 14:05:46 -0800 | [diff] [blame] | 333 | } |
Tom Taylor | 842e311 | 2012-09-26 15:01:42 -0700 | [diff] [blame] | 334 | db.setTransactionSuccessful(); |
| 335 | } catch (Throwable ex) { |
| 336 | Log.e(TAG, ex.getMessage(), ex); |
| 337 | } finally { |
| 338 | db.endTransaction(); |
Tom Taylor | 9565e7f | 2010-03-01 14:05:46 -0800 | [diff] [blame] | 339 | } |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 340 | } |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 341 | |
kaiyiz | a423857 | 2014-08-09 15:07:18 +0800 | [diff] [blame] | 342 | private static void updateThreadDate(SQLiteDatabase db, long thread_id) { |
| 343 | if (thread_id <= 0) { |
| 344 | return; |
| 345 | } |
| 346 | |
| 347 | try { |
| 348 | db.execSQL( |
| 349 | " UPDATE threads" + |
| 350 | " SET" + |
| 351 | " date =" + |
| 352 | " (SELECT date FROM" + |
| 353 | " (SELECT date * 1000 AS date, thread_id FROM pdu" + |
| 354 | " UNION SELECT date, thread_id FROM sms)" + |
| 355 | " WHERE thread_id = " + thread_id + " ORDER BY date DESC LIMIT 1)" + |
| 356 | " WHERE threads._id = " + thread_id + ";"); |
| 357 | } catch (Throwable ex) { |
| 358 | Log.e(TAG, ex.getMessage(), ex); |
| 359 | } |
| 360 | } |
| 361 | |
| 362 | public static void updateThreadsDate(SQLiteDatabase db, String where, String[] whereArgs) { |
| 363 | db.beginTransaction(); |
| 364 | try { |
| 365 | if (where == null) { |
| 366 | where = ""; |
| 367 | } else { |
| 368 | where = "WHERE (" + where + ")"; |
| 369 | } |
| 370 | String query = "SELECT _id FROM threads " + where; |
| 371 | Cursor c = db.rawQuery(query, whereArgs); |
| 372 | if (c != null) { |
| 373 | try { |
| 374 | Log.d(TAG, "updateThread count : " + c.getCount()); |
| 375 | while (c.moveToNext()) { |
| 376 | updateThreadDate(db, c.getInt(0)); |
| 377 | } |
| 378 | } finally { |
| 379 | c.close(); |
| 380 | } |
| 381 | } |
| 382 | db.setTransactionSuccessful(); |
| 383 | } catch (Throwable ex) { |
| 384 | Log.e(TAG, ex.getMessage(), ex); |
| 385 | } finally { |
| 386 | db.endTransaction(); |
| 387 | } |
| 388 | } |
| 389 | |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 390 | public static void updateAllThreads(SQLiteDatabase db, String where, String[] whereArgs) { |
Tom Taylor | 842e311 | 2012-09-26 15:01:42 -0700 | [diff] [blame] | 391 | db.beginTransaction(); |
| 392 | try { |
| 393 | if (where == null) { |
| 394 | where = ""; |
| 395 | } else { |
| 396 | where = "WHERE (" + where + ")"; |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 397 | } |
Tom Taylor | 842e311 | 2012-09-26 15:01:42 -0700 | [diff] [blame] | 398 | String query = "SELECT _id FROM threads WHERE _id IN " + |
| 399 | "(SELECT DISTINCT thread_id FROM sms " + where + ")"; |
| 400 | Cursor c = db.rawQuery(query, whereArgs); |
| 401 | if (c != null) { |
| 402 | try { |
| 403 | while (c.moveToNext()) { |
| 404 | updateThread(db, c.getInt(0)); |
| 405 | } |
| 406 | } finally { |
| 407 | c.close(); |
| 408 | } |
| 409 | } |
| 410 | // TODO: there are several db operations in this function. Lets wrap them in a |
| 411 | // transaction to make it faster. |
| 412 | // remove orphaned threads |
Tom Taylor | 15156cd | 2012-11-15 14:15:46 -0800 | [diff] [blame] | 413 | db.delete(MmsSmsProvider.TABLE_THREADS, |
Tom Taylor | 842e311 | 2012-09-26 15:01:42 -0700 | [diff] [blame] | 414 | "_id NOT IN (SELECT DISTINCT thread_id FROM sms where thread_id NOT NULL " + |
| 415 | "UNION SELECT DISTINCT thread_id FROM pdu where thread_id NOT NULL)", null); |
Tom Taylor | 3ce9cb8 | 2011-09-27 15:14:58 -0700 | [diff] [blame] | 416 | |
Tom Taylor | 842e311 | 2012-09-26 15:01:42 -0700 | [diff] [blame] | 417 | // remove orphaned canonical_addresses |
| 418 | removeUnferencedCanonicalAddresses(db); |
| 419 | |
| 420 | db.setTransactionSuccessful(); |
| 421 | } catch (Throwable ex) { |
| 422 | Log.e(TAG, ex.getMessage(), ex); |
| 423 | } finally { |
| 424 | db.endTransaction(); |
| 425 | } |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 426 | } |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 427 | |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 428 | public static int deleteOneSms(SQLiteDatabase db, int message_id) { |
| 429 | int thread_id = -1; |
| 430 | // Find the thread ID that the specified SMS belongs to. |
| 431 | Cursor c = db.query("sms", new String[] { "thread_id" }, |
| 432 | "_id=" + message_id, null, null, null, null); |
| 433 | if (c != null) { |
| 434 | if (c.moveToFirst()) { |
| 435 | thread_id = c.getInt(0); |
| 436 | } |
| 437 | c.close(); |
| 438 | } |
| 439 | |
| 440 | // Delete the specified message. |
| 441 | int rows = db.delete("sms", "_id=" + message_id, null); |
| 442 | if (thread_id > 0) { |
| 443 | // Update its thread. |
| 444 | updateThread(db, thread_id); |
| 445 | } |
| 446 | return rows; |
| 447 | } |
| 448 | |
| 449 | @Override |
| 450 | public void onCreate(SQLiteDatabase db) { |
| 451 | createMmsTables(db); |
| 452 | createSmsTables(db); |
| 453 | createCommonTables(db); |
| 454 | createCommonTriggers(db); |
| 455 | createMmsTriggers(db); |
Mark Wagner | 8e5ee78 | 2010-01-04 17:39:06 -0800 | [diff] [blame] | 456 | createWordsTables(db); |
Tom Taylor | a6e44cb | 2010-03-01 09:58:36 -0800 | [diff] [blame] | 457 | createIndices(db); |
Mark Wagner | 8e5ee78 | 2010-01-04 17:39:06 -0800 | [diff] [blame] | 458 | } |
| 459 | |
yanglv | 3dd0bab | 2015-08-24 10:40:19 +0800 | [diff] [blame] | 460 | @Override |
| 461 | public void onOpen(SQLiteDatabase db) { |
| 462 | try { |
| 463 | // Try to access the table and create it if "no such table" |
| 464 | db.query(SmsProvider.TABLE_SMS, null, null, null, null, null, null); |
| 465 | checkAndUpdateSmsTable(db); |
| 466 | } catch (SQLiteException e) { |
| 467 | Log.e(TAG, "onOpen: ex. ", e); |
| 468 | if (e.getMessage().startsWith(NO_SUCH_TABLE_EXCEPTION_MESSAGE)) { |
| 469 | createSmsTables(db); |
| 470 | } |
| 471 | } |
kaiyiz | cd21c4f | 2015-01-30 11:22:36 +0800 | [diff] [blame] | 472 | |
| 473 | // Improve the performance of deleting Mms. |
| 474 | dropMmsTriggers(db); |
Prasath Balakrishnan | 1dfaed1 | 2015-11-18 20:36:17 +0530 | [diff] [blame] | 475 | |
| 476 | // Upgrade SMS/MMS database |
| 477 | upgradeSmsMmsDb(db); |
kaiyiz | cd21c4f | 2015-01-30 11:22:36 +0800 | [diff] [blame] | 478 | } |
| 479 | |
| 480 | private void dropMmsTriggers(SQLiteDatabase db) { |
| 481 | db.execSQL("DROP TRIGGER IF EXISTS update_threads_on_delete_part"); |
| 482 | db.execSQL("DROP TRIGGER IF EXISTS mms_words_delete"); |
| 483 | db.execSQL("DROP TRIGGER IF EXISTS pdu_update_thread_on_delete"); |
yanglv | 3dd0bab | 2015-08-24 10:40:19 +0800 | [diff] [blame] | 484 | } |
| 485 | |
Mark Wagner | 8e5ee78 | 2010-01-04 17:39:06 -0800 | [diff] [blame] | 486 | // When upgrading the database we need to populate the words |
| 487 | // table with the rows out of sms and part. |
| 488 | private void populateWordsTable(SQLiteDatabase db) { |
| 489 | final String TABLE_WORDS = "words"; |
| 490 | { |
| 491 | Cursor smsRows = db.query( |
| 492 | "sms", |
| 493 | new String[] { Sms._ID, Sms.BODY }, |
| 494 | null, |
| 495 | null, |
| 496 | null, |
| 497 | null, |
| 498 | null); |
| 499 | try { |
| 500 | if (smsRows != null) { |
| 501 | smsRows.moveToPosition(-1); |
| 502 | ContentValues cv = new ContentValues(); |
| 503 | while (smsRows.moveToNext()) { |
| 504 | cv.clear(); |
| 505 | |
| 506 | long id = smsRows.getLong(0); // 0 for Sms._ID |
| 507 | String body = smsRows.getString(1); // 1 for Sms.BODY |
| 508 | |
| 509 | cv.put(Telephony.MmsSms.WordsTable.ID, id); |
| 510 | cv.put(Telephony.MmsSms.WordsTable.INDEXED_TEXT, body); |
| 511 | cv.put(Telephony.MmsSms.WordsTable.SOURCE_ROW_ID, id); |
| 512 | cv.put(Telephony.MmsSms.WordsTable.TABLE_ID, 1); |
| 513 | db.insert(TABLE_WORDS, Telephony.MmsSms.WordsTable.INDEXED_TEXT, cv); |
| 514 | } |
| 515 | } |
| 516 | } finally { |
| 517 | if (smsRows != null) { |
| 518 | smsRows.close(); |
| 519 | } |
| 520 | } |
| 521 | } |
| 522 | |
| 523 | { |
| 524 | Cursor mmsRows = db.query( |
| 525 | "part", |
| 526 | new String[] { Part._ID, Part.TEXT }, |
| 527 | "ct = 'text/plain'", |
| 528 | null, |
| 529 | null, |
| 530 | null, |
| 531 | null); |
| 532 | try { |
| 533 | if (mmsRows != null) { |
| 534 | mmsRows.moveToPosition(-1); |
| 535 | ContentValues cv = new ContentValues(); |
| 536 | while (mmsRows.moveToNext()) { |
| 537 | cv.clear(); |
| 538 | |
| 539 | long id = mmsRows.getLong(0); // 0 for Part._ID |
| 540 | String body = mmsRows.getString(1); // 1 for Part.TEXT |
| 541 | |
| 542 | cv.put(Telephony.MmsSms.WordsTable.ID, id); |
| 543 | cv.put(Telephony.MmsSms.WordsTable.INDEXED_TEXT, body); |
| 544 | cv.put(Telephony.MmsSms.WordsTable.SOURCE_ROW_ID, id); |
| 545 | cv.put(Telephony.MmsSms.WordsTable.TABLE_ID, 1); |
| 546 | db.insert(TABLE_WORDS, Telephony.MmsSms.WordsTable.INDEXED_TEXT, cv); |
| 547 | } |
| 548 | } |
| 549 | } finally { |
| 550 | if (mmsRows != null) { |
| 551 | mmsRows.close(); |
| 552 | } |
| 553 | } |
| 554 | } |
| 555 | } |
| 556 | |
| 557 | private void createWordsTables(SQLiteDatabase db) { |
| 558 | try { |
| 559 | db.execSQL("CREATE VIRTUAL TABLE words USING FTS3 (_id INTEGER PRIMARY KEY, index_text TEXT, source_id INTEGER, table_to_use INTEGER);"); |
| 560 | |
| 561 | // monitor the sms table |
| 562 | // NOTE don't handle inserts using a trigger because it has an unwanted |
| 563 | // side effect: the value returned for the last row ends up being the |
| 564 | // id of one of the trigger insert not the original row insert. |
| 565 | // Handle inserts manually in the provider. |
| 566 | db.execSQL("CREATE TRIGGER sms_words_update AFTER UPDATE ON sms BEGIN UPDATE words " + |
| 567 | " SET index_text = NEW.body WHERE (source_id=NEW._id AND table_to_use=1); " + |
| 568 | " END;"); |
| 569 | db.execSQL("CREATE TRIGGER sms_words_delete AFTER DELETE ON sms BEGIN DELETE FROM " + |
| 570 | " words WHERE source_id = OLD._id AND table_to_use = 1; END;"); |
| 571 | |
Mark Wagner | 8e5ee78 | 2010-01-04 17:39:06 -0800 | [diff] [blame] | 572 | populateWordsTable(db); |
| 573 | } catch (Exception ex) { |
| 574 | Log.e(TAG, "got exception creating words table: " + ex.toString()); |
| 575 | } |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 576 | } |
| 577 | |
Tom Taylor | a6e44cb | 2010-03-01 09:58:36 -0800 | [diff] [blame] | 578 | private void createIndices(SQLiteDatabase db) { |
| 579 | createThreadIdIndex(db); |
kaiyiz | cd21c4f | 2015-01-30 11:22:36 +0800 | [diff] [blame] | 580 | createPduPartIndex(db); |
Tom Taylor | a6e44cb | 2010-03-01 09:58:36 -0800 | [diff] [blame] | 581 | } |
| 582 | |
kaiyiz | cd21c4f | 2015-01-30 11:22:36 +0800 | [diff] [blame] | 583 | private void createPduPartIndex(SQLiteDatabase db) { |
| 584 | try { |
| 585 | db.execSQL("CREATE INDEX IF NOT EXISTS index_part ON " + MmsProvider.TABLE_PART + |
| 586 | " (mid);"); |
| 587 | } catch (Exception ex) { |
| 588 | Log.e(TAG, "got exception creating indices: " + ex.toString()); |
| 589 | } |
| 590 | } |
| 591 | |
Tom Taylor | a6e44cb | 2010-03-01 09:58:36 -0800 | [diff] [blame] | 592 | private void createThreadIdIndex(SQLiteDatabase db) { |
| 593 | try { |
| 594 | db.execSQL("CREATE INDEX IF NOT EXISTS typeThreadIdIndex ON sms" + |
| 595 | " (type, thread_id);"); |
| 596 | } catch (Exception ex) { |
| 597 | Log.e(TAG, "got exception creating indices: " + ex.toString()); |
| 598 | } |
| 599 | } |
| 600 | |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 601 | private void createMmsTables(SQLiteDatabase db) { |
| 602 | // N.B.: Whenever the columns here are changed, the columns in |
| 603 | // {@ref MmsSmsProvider} must be changed to match. |
| 604 | db.execSQL("CREATE TABLE " + MmsProvider.TABLE_PDU + " (" + |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 605 | Mms._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 606 | Mms.THREAD_ID + " INTEGER," + |
| 607 | Mms.DATE + " INTEGER," + |
Fredrik Roubert | ea5c40c | 2010-11-18 17:16:23 +0100 | [diff] [blame] | 608 | Mms.DATE_SENT + " INTEGER DEFAULT 0," + |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 609 | Mms.MESSAGE_BOX + " INTEGER," + |
| 610 | Mms.READ + " INTEGER DEFAULT 0," + |
| 611 | Mms.MESSAGE_ID + " TEXT," + |
| 612 | Mms.SUBJECT + " TEXT," + |
| 613 | Mms.SUBJECT_CHARSET + " INTEGER," + |
| 614 | Mms.CONTENT_TYPE + " TEXT," + |
| 615 | Mms.CONTENT_LOCATION + " TEXT," + |
| 616 | Mms.EXPIRY + " INTEGER," + |
| 617 | Mms.MESSAGE_CLASS + " TEXT," + |
| 618 | Mms.MESSAGE_TYPE + " INTEGER," + |
| 619 | Mms.MMS_VERSION + " INTEGER," + |
| 620 | Mms.MESSAGE_SIZE + " INTEGER," + |
| 621 | Mms.PRIORITY + " INTEGER," + |
| 622 | Mms.READ_REPORT + " INTEGER," + |
| 623 | Mms.REPORT_ALLOWED + " INTEGER," + |
| 624 | Mms.RESPONSE_STATUS + " INTEGER," + |
| 625 | Mms.STATUS + " INTEGER," + |
| 626 | Mms.TRANSACTION_ID + " TEXT," + |
| 627 | Mms.RETRIEVE_STATUS + " INTEGER," + |
| 628 | Mms.RETRIEVE_TEXT + " TEXT," + |
| 629 | Mms.RETRIEVE_TEXT_CHARSET + " INTEGER," + |
| 630 | Mms.READ_STATUS + " INTEGER," + |
| 631 | Mms.CONTENT_CLASS + " INTEGER," + |
| 632 | Mms.RESPONSE_TEXT + " TEXT," + |
| 633 | Mms.DELIVERY_TIME + " INTEGER," + |
Tom Taylor | a48a966 | 2009-06-04 14:05:05 -0700 | [diff] [blame] | 634 | Mms.DELIVERY_REPORT + " INTEGER," + |
Wei Huang | dfac576 | 2010-02-25 17:23:51 -0800 | [diff] [blame] | 635 | Mms.LOCKED + " INTEGER DEFAULT 0," + |
Wink Saville | a42e417 | 2014-12-09 18:55:22 -0800 | [diff] [blame] | 636 | Mms.SUBSCRIPTION_ID + " INTEGER DEFAULT " |
| 637 | + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " + |
Suresh Koleti | 02354f1 | 2014-08-19 16:21:45 +0530 | [diff] [blame] | 638 | Mms.PHONE_ID + " INTEGER DEFAULT -1, " + |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 639 | Mms.SEEN + " INTEGER DEFAULT 0," + |
Ye Wen | 4977641 | 2014-07-09 16:57:32 -0700 | [diff] [blame] | 640 | Mms.CREATOR + " TEXT," + |
Tom Taylor | f88d1d6 | 2012-09-07 13:38:39 -0700 | [diff] [blame] | 641 | Mms.TEXT_ONLY + " INTEGER DEFAULT 0" + |
Tom Taylor | a48a966 | 2009-06-04 14:05:05 -0700 | [diff] [blame] | 642 | ");"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 643 | |
| 644 | db.execSQL("CREATE TABLE " + MmsProvider.TABLE_ADDR + " (" + |
| 645 | Addr._ID + " INTEGER PRIMARY KEY," + |
| 646 | Addr.MSG_ID + " INTEGER," + |
| 647 | Addr.CONTACT_ID + " INTEGER," + |
| 648 | Addr.ADDRESS + " TEXT," + |
| 649 | Addr.TYPE + " INTEGER," + |
| 650 | Addr.CHARSET + " INTEGER);"); |
| 651 | |
| 652 | db.execSQL("CREATE TABLE " + MmsProvider.TABLE_PART + " (" + |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 653 | Part._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 654 | Part.MSG_ID + " INTEGER," + |
| 655 | Part.SEQ + " INTEGER DEFAULT 0," + |
| 656 | Part.CONTENT_TYPE + " TEXT," + |
| 657 | Part.NAME + " TEXT," + |
| 658 | Part.CHARSET + " INTEGER," + |
| 659 | Part.CONTENT_DISPOSITION + " TEXT," + |
| 660 | Part.FILENAME + " TEXT," + |
| 661 | Part.CONTENT_ID + " TEXT," + |
| 662 | Part.CONTENT_LOCATION + " TEXT," + |
| 663 | Part.CT_START + " INTEGER," + |
| 664 | Part.CT_TYPE + " TEXT," + |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 665 | Part._DATA + " TEXT," + |
| 666 | Part.TEXT + " TEXT);"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 667 | |
| 668 | db.execSQL("CREATE TABLE " + MmsProvider.TABLE_RATE + " (" + |
| 669 | Rate.SENT_TIME + " INTEGER);"); |
| 670 | |
| 671 | db.execSQL("CREATE TABLE " + MmsProvider.TABLE_DRM + " (" + |
| 672 | BaseColumns._ID + " INTEGER PRIMARY KEY," + |
| 673 | "_data TEXT);"); |
Ye Wen | 72f1355 | 2015-03-10 14:17:13 -0700 | [diff] [blame] | 674 | |
| 675 | // Restricted view of pdu table, only sent/received messages without wap pushes |
| 676 | db.execSQL("CREATE VIEW " + MmsProvider.VIEW_PDU_RESTRICTED + " AS " + |
| 677 | "SELECT * FROM " + MmsProvider.TABLE_PDU + " WHERE " + |
| 678 | "(" + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_INBOX + |
| 679 | " OR " + |
| 680 | Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_SENT + ")" + |
| 681 | " AND " + |
| 682 | "(" + Mms.MESSAGE_TYPE + "!=" + PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND + ");"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 683 | } |
| 684 | |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 685 | // Unlike the other trigger-creating functions, this function can be called multiple times |
| 686 | // without harm. |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 687 | private void createMmsTriggers(SQLiteDatabase db) { |
| 688 | // Cleans up parts when a MM is deleted. |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 689 | db.execSQL("DROP TRIGGER IF EXISTS part_cleanup"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 690 | db.execSQL("CREATE TRIGGER part_cleanup DELETE ON " + MmsProvider.TABLE_PDU + " " + |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 691 | "BEGIN " + |
| 692 | " DELETE FROM " + MmsProvider.TABLE_PART + |
| 693 | " WHERE " + Part.MSG_ID + "=old._id;" + |
| 694 | "END;"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 695 | |
| 696 | // Cleans up address info when a MM is deleted. |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 697 | db.execSQL("DROP TRIGGER IF EXISTS addr_cleanup"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 698 | db.execSQL("CREATE TRIGGER addr_cleanup DELETE ON " + MmsProvider.TABLE_PDU + " " + |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 699 | "BEGIN " + |
| 700 | " DELETE FROM " + MmsProvider.TABLE_ADDR + |
| 701 | " WHERE " + Addr.MSG_ID + "=old._id;" + |
| 702 | "END;"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 703 | |
| 704 | // Delete obsolete delivery-report, read-report while deleting their |
| 705 | // associated Send.req. |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 706 | db.execSQL("DROP TRIGGER IF EXISTS cleanup_delivery_and_read_report"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 707 | db.execSQL("CREATE TRIGGER cleanup_delivery_and_read_report " + |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 708 | "AFTER DELETE ON " + MmsProvider.TABLE_PDU + " " + |
| 709 | "WHEN old." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_SEND_REQ + " " + |
| 710 | "BEGIN " + |
| 711 | " DELETE FROM " + MmsProvider.TABLE_PDU + |
| 712 | " WHERE (" + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_DELIVERY_IND + |
| 713 | " OR " + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_READ_ORIG_IND + |
| 714 | ")" + |
| 715 | " AND " + Mms.MESSAGE_ID + "=old." + Mms.MESSAGE_ID + "; " + |
| 716 | "END;"); |
| 717 | |
| 718 | db.execSQL("DROP TRIGGER IF EXISTS update_threads_on_insert_part"); |
| 719 | db.execSQL(PART_UPDATE_THREADS_ON_INSERT_TRIGGER); |
| 720 | |
| 721 | db.execSQL("DROP TRIGGER IF EXISTS update_threads_on_update_part"); |
| 722 | db.execSQL(PART_UPDATE_THREADS_ON_UPDATE_TRIGGER); |
| 723 | |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 724 | db.execSQL("DROP TRIGGER IF EXISTS update_threads_on_update_pdu"); |
| 725 | db.execSQL(PDU_UPDATE_THREADS_ON_UPDATE_TRIGGER); |
| 726 | |
| 727 | // Delete pending status for a message when it is deleted. |
| 728 | db.execSQL("DROP TRIGGER IF EXISTS delete_mms_pending_on_delete"); |
| 729 | db.execSQL("CREATE TRIGGER delete_mms_pending_on_delete " + |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 730 | "AFTER DELETE ON " + MmsProvider.TABLE_PDU + " " + |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 731 | "BEGIN " + |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 732 | " DELETE FROM " + MmsSmsProvider.TABLE_PENDING_MSG + |
| 733 | " WHERE " + PendingMessages.MSG_ID + "=old._id; " + |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 734 | "END;"); |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 735 | |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 736 | // When a message is moved out of Outbox, delete its pending status. |
| 737 | db.execSQL("DROP TRIGGER IF EXISTS delete_mms_pending_on_update"); |
| 738 | db.execSQL("CREATE TRIGGER delete_mms_pending_on_update " + |
| 739 | "AFTER UPDATE ON " + MmsProvider.TABLE_PDU + " " + |
| 740 | "WHEN old." + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_OUTBOX + |
| 741 | " AND new." + Mms.MESSAGE_BOX + "!=" + Mms.MESSAGE_BOX_OUTBOX + " " + |
| 742 | "BEGIN " + |
| 743 | " DELETE FROM " + MmsSmsProvider.TABLE_PENDING_MSG + |
| 744 | " WHERE " + PendingMessages.MSG_ID + "=new._id; " + |
| 745 | "END;"); |
| 746 | |
| 747 | // Insert pending status for M-Notification.ind or M-ReadRec.ind |
| 748 | // when they are inserted into Inbox/Outbox. |
| 749 | db.execSQL("DROP TRIGGER IF EXISTS insert_mms_pending_on_insert"); |
| 750 | db.execSQL("CREATE TRIGGER insert_mms_pending_on_insert " + |
| 751 | "AFTER INSERT ON pdu " + |
| 752 | "WHEN new." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND + |
| 753 | " OR new." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_READ_REC_IND + |
| 754 | " " + |
| 755 | "BEGIN " + |
| 756 | " INSERT INTO " + MmsSmsProvider.TABLE_PENDING_MSG + |
| 757 | " (" + PendingMessages.PROTO_TYPE + "," + |
| 758 | " " + PendingMessages.MSG_ID + "," + |
| 759 | " " + PendingMessages.MSG_TYPE + "," + |
| 760 | " " + PendingMessages.ERROR_TYPE + "," + |
| 761 | " " + PendingMessages.ERROR_CODE + "," + |
| 762 | " " + PendingMessages.RETRY_INDEX + "," + |
| 763 | " " + PendingMessages.DUE_TIME + ") " + |
| 764 | " VALUES " + |
| 765 | " (" + MmsSms.MMS_PROTO + "," + |
| 766 | " new." + BaseColumns._ID + "," + |
| 767 | " new." + Mms.MESSAGE_TYPE + ",0,0,0,0);" + |
| 768 | "END;"); |
| 769 | |
| 770 | |
| 771 | // Insert pending status for M-Send.req when it is moved into Outbox. |
| 772 | db.execSQL("DROP TRIGGER IF EXISTS insert_mms_pending_on_update"); |
| 773 | db.execSQL("CREATE TRIGGER insert_mms_pending_on_update " + |
| 774 | "AFTER UPDATE ON pdu " + |
| 775 | "WHEN new." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_SEND_REQ + |
| 776 | " AND new." + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_OUTBOX + |
| 777 | " AND old." + Mms.MESSAGE_BOX + "!=" + Mms.MESSAGE_BOX_OUTBOX + " " + |
| 778 | "BEGIN " + |
| 779 | " INSERT INTO " + MmsSmsProvider.TABLE_PENDING_MSG + |
| 780 | " (" + PendingMessages.PROTO_TYPE + "," + |
| 781 | " " + PendingMessages.MSG_ID + "," + |
| 782 | " " + PendingMessages.MSG_TYPE + "," + |
| 783 | " " + PendingMessages.ERROR_TYPE + "," + |
| 784 | " " + PendingMessages.ERROR_CODE + "," + |
| 785 | " " + PendingMessages.RETRY_INDEX + "," + |
| 786 | " " + PendingMessages.DUE_TIME + ") " + |
| 787 | " VALUES " + |
| 788 | " (" + MmsSms.MMS_PROTO + "," + |
| 789 | " new." + BaseColumns._ID + "," + |
| 790 | " new." + Mms.MESSAGE_TYPE + ",0,0,0,0);" + |
| 791 | "END;"); |
| 792 | |
| 793 | // monitor the mms table |
| 794 | db.execSQL("DROP TRIGGER IF EXISTS mms_words_update"); |
| 795 | db.execSQL("CREATE TRIGGER mms_words_update AFTER UPDATE ON part BEGIN UPDATE words " + |
| 796 | " SET index_text = NEW.text WHERE (source_id=NEW._id AND table_to_use=2); " + |
| 797 | " END;"); |
| 798 | |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 799 | // Updates threads table whenever a message in pdu is updated. |
| 800 | db.execSQL("DROP TRIGGER IF EXISTS pdu_update_thread_date_subject_on_update"); |
| 801 | db.execSQL("CREATE TRIGGER pdu_update_thread_date_subject_on_update AFTER" + |
| 802 | " UPDATE OF " + Mms.DATE + ", " + Mms.SUBJECT + ", " + Mms.MESSAGE_BOX + |
| 803 | " ON " + MmsProvider.TABLE_PDU + " " + |
| 804 | PDU_UPDATE_THREAD_CONSTRAINTS + |
| 805 | PDU_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE); |
| 806 | |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 807 | // Updates threads table whenever a message is added to pdu. |
| 808 | db.execSQL("DROP TRIGGER IF EXISTS pdu_update_thread_on_insert"); |
| 809 | db.execSQL("CREATE TRIGGER pdu_update_thread_on_insert AFTER INSERT ON " + |
| 810 | MmsProvider.TABLE_PDU + " " + |
| 811 | PDU_UPDATE_THREAD_CONSTRAINTS + |
| 812 | PDU_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE); |
| 813 | |
| 814 | // Updates threads table whenever a message in pdu is updated. |
| 815 | db.execSQL("DROP TRIGGER IF EXISTS pdu_update_thread_read_on_update"); |
| 816 | db.execSQL("CREATE TRIGGER pdu_update_thread_read_on_update AFTER" + |
| 817 | " UPDATE OF " + Mms.READ + |
| 818 | " ON " + MmsProvider.TABLE_PDU + " " + |
| 819 | PDU_UPDATE_THREAD_CONSTRAINTS + |
| 820 | "BEGIN " + |
| 821 | PDU_UPDATE_THREAD_READ_BODY + |
| 822 | "END;"); |
| 823 | |
| 824 | // Update the error flag of threads when delete pending message. |
| 825 | db.execSQL("DROP TRIGGER IF EXISTS update_threads_error_on_delete_mms"); |
| 826 | db.execSQL("CREATE TRIGGER update_threads_error_on_delete_mms " + |
| 827 | " BEFORE DELETE ON pdu" + |
| 828 | " WHEN OLD._id IN (SELECT DISTINCT msg_id" + |
| 829 | " FROM pending_msgs" + |
| 830 | " WHERE err_type >= 10) " + |
| 831 | "BEGIN " + |
| 832 | " UPDATE threads SET error = error - 1" + |
| 833 | " WHERE _id = OLD.thread_id; " + |
| 834 | "END;"); |
| 835 | |
| 836 | // Update the error flag of threads while moving an MM out of Outbox, |
| 837 | // which was failed to be sent permanently. |
| 838 | db.execSQL("DROP TRIGGER IF EXISTS update_threads_error_on_move_mms"); |
| 839 | db.execSQL("CREATE TRIGGER update_threads_error_on_move_mms " + |
| 840 | " BEFORE UPDATE OF msg_box ON pdu " + |
| 841 | " WHEN (OLD.msg_box = 4 AND NEW.msg_box != 4) " + |
| 842 | " AND (OLD._id IN (SELECT DISTINCT msg_id" + |
| 843 | " FROM pending_msgs" + |
| 844 | " WHERE err_type >= 10)) " + |
| 845 | "BEGIN " + |
| 846 | " UPDATE threads SET error = error - 1" + |
| 847 | " WHERE _id = OLD.thread_id; " + |
| 848 | "END;"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 849 | } |
| 850 | |
| 851 | private void createSmsTables(SQLiteDatabase db) { |
| 852 | // N.B.: Whenever the columns here are changed, the columns in |
| 853 | // {@ref MmsSmsProvider} must be changed to match. |
| 854 | db.execSQL("CREATE TABLE sms (" + |
| 855 | "_id INTEGER PRIMARY KEY," + |
| 856 | "thread_id INTEGER," + |
| 857 | "address TEXT," + |
| 858 | "person INTEGER," + |
| 859 | "date INTEGER," + |
Fredrik Roubert | ea5c40c | 2010-11-18 17:16:23 +0100 | [diff] [blame] | 860 | "date_sent INTEGER DEFAULT 0," + |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 861 | "protocol INTEGER," + |
| 862 | "read INTEGER DEFAULT 0," + |
| 863 | "status INTEGER DEFAULT -1," + // a TP-Status value |
| 864 | // or -1 if it |
| 865 | // status hasn't |
| 866 | // been received |
| 867 | "type INTEGER," + |
| 868 | "reply_path_present INTEGER," + |
| 869 | "subject TEXT," + |
| 870 | "body TEXT," + |
Tom Taylor | a48a966 | 2009-06-04 14:05:05 -0700 | [diff] [blame] | 871 | "service_center TEXT," + |
Tom Taylor | 7d4e56b | 2009-11-03 17:23:20 -0800 | [diff] [blame] | 872 | "locked INTEGER DEFAULT 0," + |
Wink Saville | 72b1473 | 2014-11-20 13:06:04 -0800 | [diff] [blame] | 873 | "sub_id INTEGER DEFAULT " + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " + |
Suresh Koleti | 02354f1 | 2014-08-19 16:21:45 +0530 | [diff] [blame] | 874 | "phone_id INTEGER DEFAULT -1, " + |
Wei Huang | dfac576 | 2010-02-25 17:23:51 -0800 | [diff] [blame] | 875 | "error_code INTEGER DEFAULT 0," + |
Ye Wen | 4977641 | 2014-07-09 16:57:32 -0700 | [diff] [blame] | 876 | "creator TEXT," + |
yanglv | 3dd0bab | 2015-08-24 10:40:19 +0800 | [diff] [blame] | 877 | "seen INTEGER DEFAULT 0," + |
| 878 | "priority INTEGER DEFAULT -1" + |
Tom Taylor | a48a966 | 2009-06-04 14:05:05 -0700 | [diff] [blame] | 879 | ");"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 880 | |
| 881 | /** |
| 882 | * This table is used by the SMS dispatcher to hold |
| 883 | * incomplete partial messages until all the parts arrive. |
| 884 | */ |
| 885 | db.execSQL("CREATE TABLE raw (" + |
| 886 | "_id INTEGER PRIMARY KEY," + |
| 887 | "date INTEGER," + |
| 888 | "reference_number INTEGER," + // one per full message |
| 889 | "count INTEGER," + // the number of parts |
| 890 | "sequence INTEGER," + // the part number of this message |
| 891 | "destination_port INTEGER," + |
| 892 | "address TEXT," + |
Wink Saville | 72b1473 | 2014-11-20 13:06:04 -0800 | [diff] [blame] | 893 | "sub_id INTEGER DEFAULT " + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " + |
Suresh Koleti | 02354f1 | 2014-08-19 16:21:45 +0530 | [diff] [blame] | 894 | "phone_id INTEGER DEFAULT -1, " + |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 895 | "pdu TEXT);"); // the raw PDU for this part |
| 896 | |
| 897 | db.execSQL("CREATE TABLE attachments (" + |
| 898 | "sms_id INTEGER," + |
| 899 | "content_url TEXT," + |
| 900 | "offset INTEGER);"); |
| 901 | |
| 902 | /** |
| 903 | * This table is used by the SMS dispatcher to hold pending |
| 904 | * delivery status report intents. |
| 905 | */ |
| 906 | db.execSQL("CREATE TABLE sr_pending (" + |
| 907 | "reference_number INTEGER," + |
| 908 | "action TEXT," + |
| 909 | "data TEXT);"); |
Ye Wen | 72f1355 | 2015-03-10 14:17:13 -0700 | [diff] [blame] | 910 | |
| 911 | // Restricted view of sms table, only sent/received messages |
| 912 | db.execSQL("CREATE VIEW " + SmsProvider.VIEW_SMS_RESTRICTED + " AS " + |
| 913 | "SELECT * FROM " + SmsProvider.TABLE_SMS + " WHERE " + |
| 914 | Sms.TYPE + "=" + Sms.MESSAGE_TYPE_INBOX + |
| 915 | " OR " + |
| 916 | Sms.TYPE + "=" + Sms.MESSAGE_TYPE_SENT + ";"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 917 | } |
| 918 | |
| 919 | private void createCommonTables(SQLiteDatabase db) { |
| 920 | // TODO Ensure that each entry is removed when the last use of |
| 921 | // any address equivalent to its address is removed. |
| 922 | |
| 923 | /** |
| 924 | * This table maps the first instance seen of any particular |
| 925 | * MMS/SMS address to an ID, which is then used as its |
| 926 | * canonical representation. If the same address or an |
| 927 | * equivalent address (as determined by our Sqlite |
| 928 | * PHONE_NUMBERS_EQUAL extension) is seen later, this same ID |
Tom Taylor | 09710ce | 2011-12-06 16:10:34 -0800 | [diff] [blame] | 929 | * will be used. The _id is created with AUTOINCREMENT so it |
| 930 | * will never be reused again if a recipient is deleted. |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 931 | */ |
| 932 | db.execSQL("CREATE TABLE canonical_addresses (" + |
Tom Taylor | 09710ce | 2011-12-06 16:10:34 -0800 | [diff] [blame] | 933 | "_id INTEGER PRIMARY KEY AUTOINCREMENT," + |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 934 | "address TEXT);"); |
| 935 | |
| 936 | /** |
| 937 | * This table maps the subject and an ordered set of recipient |
| 938 | * IDs, separated by spaces, to a unique thread ID. The IDs |
| 939 | * come from the canonical_addresses table. This works |
| 940 | * because messages are considered to be part of the same |
| 941 | * thread if they have the same subject (or a null subject) |
| 942 | * and the same set of recipients. |
| 943 | */ |
| 944 | db.execSQL("CREATE TABLE threads (" + |
Tom Taylor | 1ab4800 | 2011-04-19 14:15:06 -0700 | [diff] [blame] | 945 | Threads._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 946 | Threads.DATE + " INTEGER DEFAULT 0," + |
| 947 | Threads.MESSAGE_COUNT + " INTEGER DEFAULT 0," + |
| 948 | Threads.RECIPIENT_IDS + " TEXT," + |
| 949 | Threads.SNIPPET + " TEXT," + |
| 950 | Threads.SNIPPET_CHARSET + " INTEGER DEFAULT 0," + |
| 951 | Threads.READ + " INTEGER DEFAULT 1," + |
Ye Wen | 82fc72b | 2014-07-29 10:42:54 -0700 | [diff] [blame] | 952 | Threads.ARCHIVED + " INTEGER DEFAULT 0," + |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 953 | Threads.TYPE + " INTEGER DEFAULT 0," + |
The Android Open Source Project | 5f1e43f | 2009-03-05 14:34:39 -0800 | [diff] [blame] | 954 | Threads.ERROR + " INTEGER DEFAULT 0," + |
| 955 | Threads.HAS_ATTACHMENT + " INTEGER DEFAULT 0);"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 956 | |
| 957 | /** |
| 958 | * This table stores the queue of messages to be sent/downloaded. |
| 959 | */ |
| 960 | db.execSQL("CREATE TABLE " + MmsSmsProvider.TABLE_PENDING_MSG +" (" + |
| 961 | PendingMessages._ID + " INTEGER PRIMARY KEY," + |
| 962 | PendingMessages.PROTO_TYPE + " INTEGER," + |
| 963 | PendingMessages.MSG_ID + " INTEGER," + |
| 964 | PendingMessages.MSG_TYPE + " INTEGER," + |
| 965 | PendingMessages.ERROR_TYPE + " INTEGER," + |
| 966 | PendingMessages.ERROR_CODE + " INTEGER," + |
| 967 | PendingMessages.RETRY_INDEX + " INTEGER NOT NULL DEFAULT 0," + |
| 968 | PendingMessages.DUE_TIME + " INTEGER," + |
Wink Saville | 72b1473 | 2014-11-20 13:06:04 -0800 | [diff] [blame] | 969 | PendingMessages.SUBSCRIPTION_ID + " INTEGER DEFAULT " + |
Wink Saville | a42e417 | 2014-12-09 18:55:22 -0800 | [diff] [blame] | 970 | SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " + |
Suresh Koleti | 02354f1 | 2014-08-19 16:21:45 +0530 | [diff] [blame] | 971 | PendingMessages.PHONE_ID + " INTEGER DEFAULT 0, " + |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 972 | PendingMessages.LAST_TRY + " INTEGER);"); |
| 973 | |
| 974 | } |
| 975 | |
| 976 | // TODO Check the query plans for these triggers. |
| 977 | private void createCommonTriggers(SQLiteDatabase db) { |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 978 | // Updates threads table whenever a message is added to sms. |
| 979 | db.execSQL("CREATE TRIGGER sms_update_thread_on_insert AFTER INSERT ON sms " + |
| 980 | SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE); |
| 981 | |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 982 | // Updates threads table whenever a message in sms is updated. |
| 983 | db.execSQL("CREATE TRIGGER sms_update_thread_date_subject_on_update AFTER" + |
| 984 | " UPDATE OF " + Sms.DATE + ", " + Sms.BODY + ", " + Sms.TYPE + |
| 985 | " ON sms " + |
| 986 | SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE); |
| 987 | |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 988 | // Updates threads table whenever a message in sms is updated. |
| 989 | db.execSQL("CREATE TRIGGER sms_update_thread_read_on_update AFTER" + |
| 990 | " UPDATE OF " + Sms.READ + |
| 991 | " ON sms " + |
| 992 | "BEGIN " + |
| 993 | SMS_UPDATE_THREAD_READ_BODY + |
| 994 | "END;"); |
| 995 | |
Tom Taylor | 527fcce | 2011-09-21 16:03:40 -0700 | [diff] [blame] | 996 | // As of DATABASE_VERSION 55, we've removed these triggers that delete empty threads. |
| 997 | // These triggers interfere with saving drafts on brand new threads. Instead of |
| 998 | // triggers cleaning up empty threads, the empty threads should be cleaned up by |
| 999 | // an explicit call to delete with Threads.OBSOLETE_THREADS_URI. |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 1000 | |
Tom Taylor | 527fcce | 2011-09-21 16:03:40 -0700 | [diff] [blame] | 1001 | // // When the last message in a thread is deleted, these |
| 1002 | // // triggers ensure that the entry for its thread ID is removed |
| 1003 | // // from the threads table. |
| 1004 | // db.execSQL("CREATE TRIGGER delete_obsolete_threads_pdu " + |
| 1005 | // "AFTER DELETE ON pdu " + |
| 1006 | // "BEGIN " + |
| 1007 | // " DELETE FROM threads " + |
| 1008 | // " WHERE " + |
| 1009 | // " _id = old.thread_id " + |
| 1010 | // " AND _id NOT IN " + |
| 1011 | // " (SELECT thread_id FROM sms " + |
| 1012 | // " UNION SELECT thread_id from pdu); " + |
| 1013 | // "END;"); |
| 1014 | // |
| 1015 | // db.execSQL("CREATE TRIGGER delete_obsolete_threads_when_update_pdu " + |
| 1016 | // "AFTER UPDATE OF " + Mms.THREAD_ID + " ON pdu " + |
| 1017 | // "WHEN old." + Mms.THREAD_ID + " != new." + Mms.THREAD_ID + " " + |
| 1018 | // "BEGIN " + |
| 1019 | // " DELETE FROM threads " + |
| 1020 | // " WHERE " + |
| 1021 | // " _id = old.thread_id " + |
| 1022 | // " AND _id NOT IN " + |
| 1023 | // " (SELECT thread_id FROM sms " + |
| 1024 | // " UNION SELECT thread_id from pdu); " + |
| 1025 | // "END;"); |
| 1026 | |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 1027 | // TODO Add triggers for SMS retry-status management. |
| 1028 | |
| 1029 | // Update the error flag of threads when the error type of |
| 1030 | // a pending MM is updated. |
| 1031 | db.execSQL("CREATE TRIGGER update_threads_error_on_update_mms " + |
| 1032 | " AFTER UPDATE OF err_type ON pending_msgs " + |
| 1033 | " WHEN (OLD.err_type < 10 AND NEW.err_type >= 10)" + |
| 1034 | " OR (OLD.err_type >= 10 AND NEW.err_type < 10) " + |
| 1035 | "BEGIN" + |
| 1036 | " UPDATE threads SET error = " + |
| 1037 | " CASE" + |
| 1038 | " WHEN NEW.err_type >= 10 THEN error + 1" + |
| 1039 | " ELSE error - 1" + |
| 1040 | " END " + |
| 1041 | " WHERE _id =" + |
| 1042 | " (SELECT DISTINCT thread_id" + |
| 1043 | " FROM pdu" + |
| 1044 | " WHERE _id = NEW.msg_id); " + |
| 1045 | "END;"); |
| 1046 | |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 1047 | // Update the error flag of threads after a text message was |
| 1048 | // failed to send/receive. |
| 1049 | db.execSQL("CREATE TRIGGER update_threads_error_on_update_sms " + |
| 1050 | " AFTER UPDATE OF type ON sms" + |
| 1051 | " WHEN (OLD.type != 5 AND NEW.type = 5)" + |
| 1052 | " OR (OLD.type = 5 AND NEW.type != 5) " + |
| 1053 | "BEGIN " + |
| 1054 | " UPDATE threads SET error = " + |
| 1055 | " CASE" + |
| 1056 | " WHEN NEW.type = 5 THEN error + 1" + |
| 1057 | " ELSE error - 1" + |
| 1058 | " END " + |
| 1059 | " WHERE _id = NEW.thread_id; " + |
| 1060 | "END;"); |
| 1061 | } |
| 1062 | |
| 1063 | @Override |
| 1064 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) { |
| 1065 | Log.w(TAG, "Upgrading database from version " + oldVersion |
| 1066 | + " to " + currentVersion + "."); |
| 1067 | |
| 1068 | switch (oldVersion) { |
The Android Open Source Project | 5f1e43f | 2009-03-05 14:34:39 -0800 | [diff] [blame] | 1069 | case 40: |
| 1070 | if (currentVersion <= 40) { |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 1071 | return; |
The Android Open Source Project | 5f1e43f | 2009-03-05 14:34:39 -0800 | [diff] [blame] | 1072 | } |
| 1073 | |
| 1074 | db.beginTransaction(); |
| 1075 | try { |
| 1076 | upgradeDatabaseToVersion41(db); |
| 1077 | db.setTransactionSuccessful(); |
| 1078 | } catch (Throwable ex) { |
| 1079 | Log.e(TAG, ex.getMessage(), ex); |
| 1080 | break; |
| 1081 | } finally { |
| 1082 | db.endTransaction(); |
| 1083 | } |
| 1084 | // fall through |
| 1085 | case 41: |
| 1086 | if (currentVersion <= 41) { |
| 1087 | return; |
| 1088 | } |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 1089 | |
The Android Open Source Project | 5f1e43f | 2009-03-05 14:34:39 -0800 | [diff] [blame] | 1090 | db.beginTransaction(); |
| 1091 | try { |
| 1092 | upgradeDatabaseToVersion42(db); |
| 1093 | db.setTransactionSuccessful(); |
| 1094 | } catch (Throwable ex) { |
| 1095 | Log.e(TAG, ex.getMessage(), ex); |
| 1096 | break; |
| 1097 | } finally { |
| 1098 | db.endTransaction(); |
| 1099 | } |
| 1100 | // fall through |
| 1101 | case 42: |
| 1102 | if (currentVersion <= 42) { |
| 1103 | return; |
| 1104 | } |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 1105 | |
The Android Open Source Project | 5f1e43f | 2009-03-05 14:34:39 -0800 | [diff] [blame] | 1106 | db.beginTransaction(); |
| 1107 | try { |
| 1108 | upgradeDatabaseToVersion43(db); |
| 1109 | db.setTransactionSuccessful(); |
| 1110 | } catch (Throwable ex) { |
| 1111 | Log.e(TAG, ex.getMessage(), ex); |
| 1112 | break; |
| 1113 | } finally { |
| 1114 | db.endTransaction(); |
| 1115 | } |
Wei Huang | 2ad5ba8 | 2009-03-24 20:01:04 -0700 | [diff] [blame] | 1116 | // fall through |
| 1117 | case 43: |
| 1118 | if (currentVersion <= 43) { |
| 1119 | return; |
| 1120 | } |
| 1121 | |
| 1122 | db.beginTransaction(); |
| 1123 | try { |
| 1124 | upgradeDatabaseToVersion44(db); |
| 1125 | db.setTransactionSuccessful(); |
| 1126 | } catch (Throwable ex) { |
| 1127 | Log.e(TAG, ex.getMessage(), ex); |
| 1128 | break; |
| 1129 | } finally { |
| 1130 | db.endTransaction(); |
| 1131 | } |
Tom Taylor | ddf267c | 2009-10-28 18:14:55 -0700 | [diff] [blame] | 1132 | // fall through |
Tom Taylor | a48a966 | 2009-06-04 14:05:05 -0700 | [diff] [blame] | 1133 | case 44: |
| 1134 | if (currentVersion <= 44) { |
| 1135 | return; |
| 1136 | } |
| 1137 | |
| 1138 | db.beginTransaction(); |
| 1139 | try { |
| 1140 | upgradeDatabaseToVersion45(db); |
| 1141 | db.setTransactionSuccessful(); |
| 1142 | } catch (Throwable ex) { |
| 1143 | Log.e(TAG, ex.getMessage(), ex); |
| 1144 | break; |
| 1145 | } finally { |
| 1146 | db.endTransaction(); |
| 1147 | } |
Tom Taylor | ddf267c | 2009-10-28 18:14:55 -0700 | [diff] [blame] | 1148 | // fall through |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 1149 | case 45: |
| 1150 | if (currentVersion <= 45) { |
| 1151 | return; |
| 1152 | } |
| 1153 | db.beginTransaction(); |
| 1154 | try { |
| 1155 | upgradeDatabaseToVersion46(db); |
| 1156 | db.setTransactionSuccessful(); |
| 1157 | } catch (Throwable ex) { |
| 1158 | Log.e(TAG, ex.getMessage(), ex); |
| 1159 | break; |
| 1160 | } finally { |
| 1161 | db.endTransaction(); |
| 1162 | } |
Wei Huang | 1047ab4 | 2009-09-29 20:53:26 -0700 | [diff] [blame] | 1163 | // fall through |
| 1164 | case 46: |
| 1165 | if (currentVersion <= 46) { |
| 1166 | return; |
| 1167 | } |
| 1168 | |
| 1169 | db.beginTransaction(); |
| 1170 | try { |
| 1171 | upgradeDatabaseToVersion47(db); |
| 1172 | db.setTransactionSuccessful(); |
| 1173 | } catch (Throwable ex) { |
| 1174 | Log.e(TAG, ex.getMessage(), ex); |
| 1175 | break; |
| 1176 | } finally { |
| 1177 | db.endTransaction(); |
| 1178 | } |
Tom Taylor | ddf267c | 2009-10-28 18:14:55 -0700 | [diff] [blame] | 1179 | // fall through |
| 1180 | case 47: |
| 1181 | if (currentVersion <= 47) { |
| 1182 | return; |
| 1183 | } |
| 1184 | |
| 1185 | db.beginTransaction(); |
| 1186 | try { |
| 1187 | upgradeDatabaseToVersion48(db); |
| 1188 | db.setTransactionSuccessful(); |
| 1189 | } catch (Throwable ex) { |
| 1190 | Log.e(TAG, ex.getMessage(), ex); |
| 1191 | break; |
| 1192 | } finally { |
| 1193 | db.endTransaction(); |
| 1194 | } |
Wei Huang | dfac576 | 2010-02-25 17:23:51 -0800 | [diff] [blame] | 1195 | // fall through |
Mark Wagner | 8e5ee78 | 2010-01-04 17:39:06 -0800 | [diff] [blame] | 1196 | case 48: |
| 1197 | if (currentVersion <= 48) { |
| 1198 | return; |
| 1199 | } |
| 1200 | |
| 1201 | db.beginTransaction(); |
| 1202 | try { |
Tom Taylor | 7ad939e | 2010-01-15 14:03:29 -0800 | [diff] [blame] | 1203 | createWordsTables(db); |
Mark Wagner | 8e5ee78 | 2010-01-04 17:39:06 -0800 | [diff] [blame] | 1204 | db.setTransactionSuccessful(); |
| 1205 | } catch (Throwable ex) { |
| 1206 | Log.e(TAG, ex.getMessage(), ex); |
| 1207 | break; |
| 1208 | } finally { |
| 1209 | db.endTransaction(); |
| 1210 | } |
Wei Huang | dfac576 | 2010-02-25 17:23:51 -0800 | [diff] [blame] | 1211 | // fall through |
Tom Taylor | a6e44cb | 2010-03-01 09:58:36 -0800 | [diff] [blame] | 1212 | case 49: |
| 1213 | if (currentVersion <= 49) { |
| 1214 | return; |
| 1215 | } |
| 1216 | db.beginTransaction(); |
| 1217 | try { |
| 1218 | createThreadIdIndex(db); |
| 1219 | db.setTransactionSuccessful(); |
| 1220 | } catch (Throwable ex) { |
| 1221 | Log.e(TAG, ex.getMessage(), ex); |
| 1222 | break; // force to destroy all old data; |
| 1223 | } finally { |
| 1224 | db.endTransaction(); |
| 1225 | } |
Wei Huang | dfac576 | 2010-02-25 17:23:51 -0800 | [diff] [blame] | 1226 | // fall through |
| 1227 | case 50: |
| 1228 | if (currentVersion <= 50) { |
| 1229 | return; |
| 1230 | } |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 1231 | |
Wei Huang | dfac576 | 2010-02-25 17:23:51 -0800 | [diff] [blame] | 1232 | db.beginTransaction(); |
| 1233 | try { |
| 1234 | upgradeDatabaseToVersion51(db); |
| 1235 | db.setTransactionSuccessful(); |
| 1236 | } catch (Throwable ex) { |
| 1237 | Log.e(TAG, ex.getMessage(), ex); |
| 1238 | break; |
| 1239 | } finally { |
| 1240 | db.endTransaction(); |
| 1241 | } |
Tom Taylor | fc0eb2f | 2010-03-11 15:54:15 -0800 | [diff] [blame] | 1242 | // fall through |
| 1243 | case 51: |
| 1244 | if (currentVersion <= 51) { |
| 1245 | return; |
| 1246 | } |
Tom Taylor | 8a4060e | 2010-03-22 17:08:55 -0700 | [diff] [blame] | 1247 | // 52 was adding a new meta_data column, but that was removed. |
Tom Taylor | fc0eb2f | 2010-03-11 15:54:15 -0800 | [diff] [blame] | 1248 | // fall through |
Tom Taylor | 1e47c48 | 2010-03-12 16:14:50 -0800 | [diff] [blame] | 1249 | case 52: |
| 1250 | if (currentVersion <= 52) { |
| 1251 | return; |
| 1252 | } |
Wei Huang | dfac576 | 2010-02-25 17:23:51 -0800 | [diff] [blame] | 1253 | |
Tom Taylor | 1e47c48 | 2010-03-12 16:14:50 -0800 | [diff] [blame] | 1254 | db.beginTransaction(); |
| 1255 | try { |
| 1256 | upgradeDatabaseToVersion53(db); |
| 1257 | db.setTransactionSuccessful(); |
| 1258 | } catch (Throwable ex) { |
| 1259 | Log.e(TAG, ex.getMessage(), ex); |
| 1260 | break; |
| 1261 | } finally { |
| 1262 | db.endTransaction(); |
| 1263 | } |
Fredrik Roubert | ea5c40c | 2010-11-18 17:16:23 +0100 | [diff] [blame] | 1264 | // fall through |
| 1265 | case 53: |
| 1266 | if (currentVersion <= 53) { |
| 1267 | return; |
| 1268 | } |
| 1269 | |
| 1270 | db.beginTransaction(); |
| 1271 | try { |
| 1272 | upgradeDatabaseToVersion54(db); |
| 1273 | db.setTransactionSuccessful(); |
| 1274 | } catch (Throwable ex) { |
| 1275 | Log.e(TAG, ex.getMessage(), ex); |
| 1276 | break; |
| 1277 | } finally { |
| 1278 | db.endTransaction(); |
| 1279 | } |
Tom Taylor | 527fcce | 2011-09-21 16:03:40 -0700 | [diff] [blame] | 1280 | // fall through |
| 1281 | case 54: |
| 1282 | if (currentVersion <= 54) { |
| 1283 | return; |
| 1284 | } |
| 1285 | |
| 1286 | db.beginTransaction(); |
| 1287 | try { |
| 1288 | upgradeDatabaseToVersion55(db); |
| 1289 | db.setTransactionSuccessful(); |
| 1290 | } catch (Throwable ex) { |
| 1291 | Log.e(TAG, ex.getMessage(), ex); |
| 1292 | break; |
| 1293 | } finally { |
| 1294 | db.endTransaction(); |
| 1295 | } |
Tom Taylor | f88d1d6 | 2012-09-07 13:38:39 -0700 | [diff] [blame] | 1296 | // fall through |
| 1297 | case 55: |
| 1298 | if (currentVersion <= 55) { |
| 1299 | return; |
| 1300 | } |
| 1301 | |
| 1302 | db.beginTransaction(); |
| 1303 | try { |
| 1304 | upgradeDatabaseToVersion56(db); |
| 1305 | db.setTransactionSuccessful(); |
| 1306 | } catch (Throwable ex) { |
| 1307 | Log.e(TAG, ex.getMessage(), ex); |
| 1308 | break; |
| 1309 | } finally { |
| 1310 | db.endTransaction(); |
| 1311 | } |
Tom Taylor | 1a45ce5 | 2012-10-17 11:36:26 -0700 | [diff] [blame] | 1312 | // fall through |
| 1313 | case 56: |
| 1314 | if (currentVersion <= 56) { |
| 1315 | return; |
| 1316 | } |
| 1317 | |
| 1318 | db.beginTransaction(); |
| 1319 | try { |
| 1320 | upgradeDatabaseToVersion57(db); |
| 1321 | db.setTransactionSuccessful(); |
| 1322 | } catch (Throwable ex) { |
| 1323 | Log.e(TAG, ex.getMessage(), ex); |
| 1324 | break; |
| 1325 | } finally { |
| 1326 | db.endTransaction(); |
| 1327 | } |
Ye Wen | cfb8bbd | 2014-06-17 09:00:38 -0700 | [diff] [blame] | 1328 | // fall through |
| 1329 | case 57: |
| 1330 | if (currentVersion <= 57) { |
| 1331 | return; |
| 1332 | } |
| 1333 | |
| 1334 | db.beginTransaction(); |
| 1335 | try { |
| 1336 | upgradeDatabaseToVersion58(db); |
| 1337 | db.setTransactionSuccessful(); |
| 1338 | } catch (Throwable ex) { |
| 1339 | Log.e(TAG, ex.getMessage(), ex); |
| 1340 | break; |
| 1341 | } finally { |
| 1342 | db.endTransaction(); |
| 1343 | } |
Ye Wen | 4977641 | 2014-07-09 16:57:32 -0700 | [diff] [blame] | 1344 | // fall through |
| 1345 | case 58: |
| 1346 | if (currentVersion <= 58) { |
| 1347 | return; |
| 1348 | } |
| 1349 | |
| 1350 | db.beginTransaction(); |
| 1351 | try { |
| 1352 | upgradeDatabaseToVersion59(db); |
| 1353 | db.setTransactionSuccessful(); |
| 1354 | } catch (Throwable ex) { |
| 1355 | Log.e(TAG, ex.getMessage(), ex); |
| 1356 | break; |
| 1357 | } finally { |
| 1358 | db.endTransaction(); |
| 1359 | } |
Ye Wen | 82fc72b | 2014-07-29 10:42:54 -0700 | [diff] [blame] | 1360 | // fall through |
| 1361 | case 59: |
| 1362 | if (currentVersion <= 59) { |
| 1363 | return; |
| 1364 | } |
| 1365 | |
| 1366 | db.beginTransaction(); |
| 1367 | try { |
| 1368 | upgradeDatabaseToVersion60(db); |
| 1369 | db.setTransactionSuccessful(); |
| 1370 | } catch (Throwable ex) { |
| 1371 | Log.e(TAG, ex.getMessage(), ex); |
| 1372 | break; |
| 1373 | } finally { |
| 1374 | db.endTransaction(); |
| 1375 | } |
Ye Wen | 72f1355 | 2015-03-10 14:17:13 -0700 | [diff] [blame] | 1376 | // fall through |
| 1377 | case 60: |
| 1378 | if (currentVersion <= 60) { |
| 1379 | return; |
| 1380 | } |
| 1381 | |
| 1382 | db.beginTransaction(); |
| 1383 | try { |
| 1384 | upgradeDatabaseToVersion61(db); |
| 1385 | db.setTransactionSuccessful(); |
| 1386 | } catch (Throwable ex) { |
| 1387 | Log.e(TAG, ex.getMessage(), ex); |
| 1388 | break; |
| 1389 | } finally { |
| 1390 | db.endTransaction(); |
| 1391 | } |
Wei Huang | dfac576 | 2010-02-25 17:23:51 -0800 | [diff] [blame] | 1392 | return; |
Tom Taylor | a6e44cb | 2010-03-01 09:58:36 -0800 | [diff] [blame] | 1393 | } |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 1394 | |
The Android Open Source Project | 5f1e43f | 2009-03-05 14:34:39 -0800 | [diff] [blame] | 1395 | Log.e(TAG, "Destroying all old data."); |
| 1396 | dropAll(db); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 1397 | onCreate(db); |
| 1398 | } |
| 1399 | |
Prasath Balakrishnan | 1dfaed1 | 2015-11-18 20:36:17 +0530 | [diff] [blame] | 1400 | @Override |
| 1401 | public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { |
| 1402 | // Do Nothing |
| 1403 | Log.i(TAG, "oldVersion: " + oldVersion + " newVersion: " + newVersion); |
| 1404 | } |
| 1405 | |
The Android Open Source Project | 5f1e43f | 2009-03-05 14:34:39 -0800 | [diff] [blame] | 1406 | private void dropAll(SQLiteDatabase db) { |
| 1407 | // Clean the database out in order to start over from scratch. |
| 1408 | // We don't need to drop our triggers here because SQLite automatically |
| 1409 | // drops a trigger when its attached database is dropped. |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 1410 | db.execSQL("DROP TABLE IF EXISTS canonical_addresses"); |
| 1411 | db.execSQL("DROP TABLE IF EXISTS threads"); |
| 1412 | db.execSQL("DROP TABLE IF EXISTS " + MmsSmsProvider.TABLE_PENDING_MSG); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 1413 | db.execSQL("DROP TABLE IF EXISTS sms"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 1414 | db.execSQL("DROP TABLE IF EXISTS raw"); |
| 1415 | db.execSQL("DROP TABLE IF EXISTS attachments"); |
| 1416 | db.execSQL("DROP TABLE IF EXISTS thread_ids"); |
| 1417 | db.execSQL("DROP TABLE IF EXISTS sr_pending"); |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 1418 | db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_PDU + ";"); |
| 1419 | db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_ADDR + ";"); |
| 1420 | db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_PART + ";"); |
| 1421 | db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_RATE + ";"); |
| 1422 | db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_DRM + ";"); |
| 1423 | } |
| 1424 | |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 1425 | private void upgradeDatabaseToVersion41(SQLiteDatabase db) { |
| 1426 | db.execSQL("DROP TRIGGER IF EXISTS update_threads_error_on_move_mms"); |
| 1427 | db.execSQL("CREATE TRIGGER update_threads_error_on_move_mms " + |
| 1428 | " BEFORE UPDATE OF msg_box ON pdu " + |
| 1429 | " WHEN (OLD.msg_box = 4 AND NEW.msg_box != 4) " + |
| 1430 | " AND (OLD._id IN (SELECT DISTINCT msg_id" + |
| 1431 | " FROM pending_msgs" + |
| 1432 | " WHERE err_type >= 10)) " + |
| 1433 | "BEGIN " + |
| 1434 | " UPDATE threads SET error = error - 1" + |
| 1435 | " WHERE _id = OLD.thread_id; " + |
| 1436 | "END;"); |
| 1437 | } |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 1438 | |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 1439 | private void upgradeDatabaseToVersion42(SQLiteDatabase db) { |
| 1440 | db.execSQL("DROP TRIGGER IF EXISTS sms_update_thread_on_delete"); |
| 1441 | db.execSQL("DROP TRIGGER IF EXISTS delete_obsolete_threads_sms"); |
| 1442 | db.execSQL("DROP TRIGGER IF EXISTS update_threads_error_on_delete_sms"); |
| 1443 | } |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 1444 | |
The Android Open Source Project | 5f1e43f | 2009-03-05 14:34:39 -0800 | [diff] [blame] | 1445 | private void upgradeDatabaseToVersion43(SQLiteDatabase db) { |
| 1446 | // Add 'has_attachment' column to threads table. |
| 1447 | db.execSQL("ALTER TABLE threads ADD COLUMN has_attachment INTEGER DEFAULT 0"); |
| 1448 | |
Wei Huang | 1047ab4 | 2009-09-29 20:53:26 -0700 | [diff] [blame] | 1449 | updateThreadsAttachmentColumn(db); |
The Android Open Source Project | 5f1e43f | 2009-03-05 14:34:39 -0800 | [diff] [blame] | 1450 | |
kaiyiz | cd21c4f | 2015-01-30 11:22:36 +0800 | [diff] [blame] | 1451 | // Add insert triggers for keeping it up to date. |
The Android Open Source Project | 5f1e43f | 2009-03-05 14:34:39 -0800 | [diff] [blame] | 1452 | db.execSQL(PART_UPDATE_THREADS_ON_INSERT_TRIGGER); |
The Android Open Source Project | 5f1e43f | 2009-03-05 14:34:39 -0800 | [diff] [blame] | 1453 | } |
Wei Huang | 2ad5ba8 | 2009-03-24 20:01:04 -0700 | [diff] [blame] | 1454 | |
| 1455 | private void upgradeDatabaseToVersion44(SQLiteDatabase db) { |
Wei Huang | 1047ab4 | 2009-09-29 20:53:26 -0700 | [diff] [blame] | 1456 | updateThreadsAttachmentColumn(db); |
Wei Huang | 2ad5ba8 | 2009-03-24 20:01:04 -0700 | [diff] [blame] | 1457 | |
| 1458 | // add the update trigger for keeping the threads up to date. |
| 1459 | db.execSQL(PART_UPDATE_THREADS_ON_UPDATE_TRIGGER); |
| 1460 | } |
Tom Taylor | a48a966 | 2009-06-04 14:05:05 -0700 | [diff] [blame] | 1461 | |
| 1462 | private void upgradeDatabaseToVersion45(SQLiteDatabase db) { |
| 1463 | // Add 'locked' column to sms table. |
Tom Taylor | fc0eb2f | 2010-03-11 15:54:15 -0800 | [diff] [blame] | 1464 | db.execSQL("ALTER TABLE sms ADD COLUMN " + Sms.LOCKED + " INTEGER DEFAULT 0"); |
Tom Taylor | a48a966 | 2009-06-04 14:05:05 -0700 | [diff] [blame] | 1465 | |
| 1466 | // Add 'locked' column to pdu table. |
| 1467 | db.execSQL("ALTER TABLE pdu ADD COLUMN " + Mms.LOCKED + " INTEGER DEFAULT 0"); |
| 1468 | } |
| 1469 | |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 1470 | private void upgradeDatabaseToVersion46(SQLiteDatabase db) { |
| 1471 | // add the "text" column for caching inline text (e.g. strings) instead of |
| 1472 | // putting them in an external file |
| 1473 | db.execSQL("ALTER TABLE part ADD COLUMN " + Part.TEXT + " TEXT"); |
| 1474 | |
| 1475 | Cursor textRows = db.query( |
| 1476 | "part", |
| 1477 | new String[] { Part._ID, Part._DATA, Part.TEXT}, |
| 1478 | "ct = 'text/plain' OR ct == 'application/smil'", |
| 1479 | null, |
| 1480 | null, |
| 1481 | null, |
| 1482 | null); |
| 1483 | ArrayList<String> filesToDelete = new ArrayList<String>(); |
| 1484 | try { |
Jeff Hamilton | 0ebbb48 | 2010-05-13 02:08:56 -0500 | [diff] [blame] | 1485 | db.beginTransaction(); |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 1486 | if (textRows != null) { |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 1487 | int partDataColumn = textRows.getColumnIndex(Part._DATA); |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 1488 | |
| 1489 | // This code is imperfect in that we can't guarantee that all the |
| 1490 | // backing files get deleted. For example if the system aborts after |
| 1491 | // the database is updated but before we complete the process of |
| 1492 | // deleting files. |
| 1493 | while (textRows.moveToNext()) { |
| 1494 | String path = textRows.getString(partDataColumn); |
| 1495 | if (path != null) { |
| 1496 | try { |
| 1497 | InputStream is = new FileInputStream(path); |
| 1498 | byte [] data = new byte[is.available()]; |
| 1499 | is.read(data); |
| 1500 | EncodedStringValue v = new EncodedStringValue(data); |
Jeff Hamilton | 0ebbb48 | 2010-05-13 02:08:56 -0500 | [diff] [blame] | 1501 | db.execSQL("UPDATE part SET " + Part._DATA + " = NULL, " + |
| 1502 | Part.TEXT + " = ?", new String[] { v.getString() }); |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 1503 | is.close(); |
| 1504 | filesToDelete.add(path); |
| 1505 | } catch (IOException e) { |
| 1506 | // TODO Auto-generated catch block |
| 1507 | e.printStackTrace(); |
| 1508 | } |
| 1509 | } |
| 1510 | } |
| 1511 | } |
Jeff Hamilton | 0ebbb48 | 2010-05-13 02:08:56 -0500 | [diff] [blame] | 1512 | db.setTransactionSuccessful(); |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 1513 | } finally { |
Jeff Hamilton | 0ebbb48 | 2010-05-13 02:08:56 -0500 | [diff] [blame] | 1514 | db.endTransaction(); |
Mark Wagner | f0a9e90 | 2009-06-19 16:00:13 -0700 | [diff] [blame] | 1515 | for (String pathToDelete : filesToDelete) { |
| 1516 | try { |
| 1517 | (new File(pathToDelete)).delete(); |
| 1518 | } catch (SecurityException ex) { |
| 1519 | Log.e(TAG, "unable to clean up old mms file for " + pathToDelete, ex); |
| 1520 | } |
| 1521 | } |
| 1522 | if (textRows != null) { |
| 1523 | textRows.close(); |
| 1524 | } |
| 1525 | } |
| 1526 | } |
Wei Huang | 1047ab4 | 2009-09-29 20:53:26 -0700 | [diff] [blame] | 1527 | |
| 1528 | private void upgradeDatabaseToVersion47(SQLiteDatabase db) { |
| 1529 | updateThreadsAttachmentColumn(db); |
| 1530 | |
| 1531 | // add the update trigger for keeping the threads up to date. |
| 1532 | db.execSQL(PDU_UPDATE_THREADS_ON_UPDATE_TRIGGER); |
| 1533 | } |
| 1534 | |
Tom Taylor | ddf267c | 2009-10-28 18:14:55 -0700 | [diff] [blame] | 1535 | private void upgradeDatabaseToVersion48(SQLiteDatabase db) { |
| 1536 | // Add 'error_code' column to sms table. |
| 1537 | db.execSQL("ALTER TABLE sms ADD COLUMN error_code INTEGER DEFAULT 0"); |
| 1538 | } |
| 1539 | |
Wei Huang | dfac576 | 2010-02-25 17:23:51 -0800 | [diff] [blame] | 1540 | private void upgradeDatabaseToVersion51(SQLiteDatabase db) { |
| 1541 | db.execSQL("ALTER TABLE sms add COLUMN seen INTEGER DEFAULT 0"); |
| 1542 | db.execSQL("ALTER TABLE pdu add COLUMN seen INTEGER DEFAULT 0"); |
Wei Huang | a882662 | 2010-03-31 11:33:57 -0700 | [diff] [blame] | 1543 | |
| 1544 | try { |
| 1545 | // update the existing sms and pdu tables so the new "seen" column is the same as |
| 1546 | // the "read" column for each row. |
| 1547 | ContentValues contentValues = new ContentValues(); |
| 1548 | contentValues.put("seen", 1); |
| 1549 | int count = db.update("sms", contentValues, "read=1", null); |
| 1550 | Log.d(TAG, "[MmsSmsDb] upgradeDatabaseToVersion51: updated " + count + |
| 1551 | " rows in sms table to have READ=1"); |
| 1552 | count = db.update("pdu", contentValues, "read=1", null); |
| 1553 | Log.d(TAG, "[MmsSmsDb] upgradeDatabaseToVersion51: updated " + count + |
| 1554 | " rows in pdu table to have READ=1"); |
| 1555 | } catch (Exception ex) { |
| 1556 | Log.e(TAG, "[MmsSmsDb] upgradeDatabaseToVersion51 caught ", ex); |
| 1557 | } |
Wei Huang | dfac576 | 2010-02-25 17:23:51 -0800 | [diff] [blame] | 1558 | } |
| 1559 | |
Fredrik Roubert | ea5c40c | 2010-11-18 17:16:23 +0100 | [diff] [blame] | 1560 | private void upgradeDatabaseToVersion53(SQLiteDatabase db) { |
| 1561 | db.execSQL("DROP TRIGGER IF EXISTS pdu_update_thread_read_on_update"); |
| 1562 | |
| 1563 | // Updates threads table whenever a message in pdu is updated. |
| 1564 | db.execSQL("CREATE TRIGGER pdu_update_thread_read_on_update AFTER" + |
| 1565 | " UPDATE OF " + Mms.READ + |
| 1566 | " ON " + MmsProvider.TABLE_PDU + " " + |
| 1567 | PDU_UPDATE_THREAD_CONSTRAINTS + |
| 1568 | "BEGIN " + |
| 1569 | PDU_UPDATE_THREAD_READ_BODY + |
| 1570 | "END;"); |
| 1571 | } |
| 1572 | |
| 1573 | private void upgradeDatabaseToVersion54(SQLiteDatabase db) { |
| 1574 | // Add 'date_sent' column to sms table. |
| 1575 | db.execSQL("ALTER TABLE sms ADD COLUMN " + Sms.DATE_SENT + " INTEGER DEFAULT 0"); |
| 1576 | |
| 1577 | // Add 'date_sent' column to pdu table. |
| 1578 | db.execSQL("ALTER TABLE pdu ADD COLUMN " + Mms.DATE_SENT + " INTEGER DEFAULT 0"); |
| 1579 | } |
| 1580 | |
Tom Taylor | 527fcce | 2011-09-21 16:03:40 -0700 | [diff] [blame] | 1581 | private void upgradeDatabaseToVersion55(SQLiteDatabase db) { |
| 1582 | // Drop removed triggers |
| 1583 | db.execSQL("DROP TRIGGER IF EXISTS delete_obsolete_threads_pdu"); |
| 1584 | db.execSQL("DROP TRIGGER IF EXISTS delete_obsolete_threads_when_update_pdu"); |
| 1585 | } |
| 1586 | |
Tom Taylor | f88d1d6 | 2012-09-07 13:38:39 -0700 | [diff] [blame] | 1587 | private void upgradeDatabaseToVersion56(SQLiteDatabase db) { |
| 1588 | // Add 'text_only' column to pdu table. |
| 1589 | db.execSQL("ALTER TABLE " + MmsProvider.TABLE_PDU + " ADD COLUMN " + Mms.TEXT_ONLY + |
| 1590 | " INTEGER DEFAULT 0"); |
| 1591 | } |
| 1592 | |
Tom Taylor | 1a45ce5 | 2012-10-17 11:36:26 -0700 | [diff] [blame] | 1593 | private void upgradeDatabaseToVersion57(SQLiteDatabase db) { |
| 1594 | // Clear out bad rows, those with empty threadIds, from the pdu table. |
| 1595 | db.execSQL("DELETE FROM " + MmsProvider.TABLE_PDU + " WHERE " + Mms.THREAD_ID + " IS NULL"); |
| 1596 | } |
| 1597 | |
Ye Wen | cfb8bbd | 2014-06-17 09:00:38 -0700 | [diff] [blame] | 1598 | private void upgradeDatabaseToVersion58(SQLiteDatabase db) { |
Wink Saville | a42e417 | 2014-12-09 18:55:22 -0800 | [diff] [blame] | 1599 | db.execSQL("ALTER TABLE " + MmsProvider.TABLE_PDU + |
| 1600 | " ADD COLUMN " + Mms.SUBSCRIPTION_ID |
| 1601 | + " INTEGER DEFAULT " + SubscriptionManager.INVALID_SUBSCRIPTION_ID); |
| 1602 | db.execSQL("ALTER TABLE " + MmsSmsProvider.TABLE_PENDING_MSG |
| 1603 | +" ADD COLUMN " + "pending_sub_id" |
| 1604 | + " INTEGER DEFAULT " + SubscriptionManager.INVALID_SUBSCRIPTION_ID); |
| 1605 | db.execSQL("ALTER TABLE " + SmsProvider.TABLE_SMS |
| 1606 | + " ADD COLUMN " + Sms.SUBSCRIPTION_ID |
| 1607 | + " INTEGER DEFAULT " + SubscriptionManager.INVALID_SUBSCRIPTION_ID); |
| 1608 | db.execSQL("ALTER TABLE " + SmsProvider.TABLE_RAW |
| 1609 | +" ADD COLUMN " + Sms.SUBSCRIPTION_ID |
| 1610 | + " INTEGER DEFAULT " + SubscriptionManager.INVALID_SUBSCRIPTION_ID); |
Ye Wen | cfb8bbd | 2014-06-17 09:00:38 -0700 | [diff] [blame] | 1611 | } |
| 1612 | |
Ye Wen | 4977641 | 2014-07-09 16:57:32 -0700 | [diff] [blame] | 1613 | private void upgradeDatabaseToVersion59(SQLiteDatabase db) { |
| 1614 | db.execSQL("ALTER TABLE " + MmsProvider.TABLE_PDU +" ADD COLUMN " |
Ye Wen | 4977641 | 2014-07-09 16:57:32 -0700 | [diff] [blame] | 1615 | + Mms.CREATOR + " TEXT"); |
| 1616 | db.execSQL("ALTER TABLE " + SmsProvider.TABLE_SMS +" ADD COLUMN " |
Ye Wen | 4977641 | 2014-07-09 16:57:32 -0700 | [diff] [blame] | 1617 | + Sms.CREATOR + " TEXT"); |
| 1618 | } |
| 1619 | |
Ye Wen | 82fc72b | 2014-07-29 10:42:54 -0700 | [diff] [blame] | 1620 | private void upgradeDatabaseToVersion60(SQLiteDatabase db) { |
| 1621 | db.execSQL("ALTER TABLE " + MmsSmsProvider.TABLE_THREADS +" ADD COLUMN " |
| 1622 | + Threads.ARCHIVED + " INTEGER DEFAULT 0"); |
| 1623 | } |
| 1624 | |
Ye Wen | 72f1355 | 2015-03-10 14:17:13 -0700 | [diff] [blame] | 1625 | private void upgradeDatabaseToVersion61(SQLiteDatabase db) { |
| 1626 | db.execSQL("CREATE VIEW " + SmsProvider.VIEW_SMS_RESTRICTED + " AS " + |
| 1627 | "SELECT * FROM " + SmsProvider.TABLE_SMS + " WHERE " + |
| 1628 | Sms.TYPE + "=" + Sms.MESSAGE_TYPE_INBOX + |
| 1629 | " OR " + |
| 1630 | Sms.TYPE + "=" + Sms.MESSAGE_TYPE_SENT + ";"); |
| 1631 | db.execSQL("CREATE VIEW " + MmsProvider.VIEW_PDU_RESTRICTED + " AS " + |
| 1632 | "SELECT * FROM " + MmsProvider.TABLE_PDU + " WHERE " + |
| 1633 | "(" + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_INBOX + |
| 1634 | " OR " + |
| 1635 | Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_SENT + ")" + |
| 1636 | " AND " + |
| 1637 | "(" + Mms.MESSAGE_TYPE + "!=" + PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND + ");"); |
Suresh Koleti | 02354f1 | 2014-08-19 16:21:45 +0530 | [diff] [blame] | 1638 | db.execSQL("ALTER TABLE " + MmsProvider.TABLE_PDU + |
| 1639 | " ADD COLUMN " + Mms.PHONE_ID |
| 1640 | + " INTEGER DEFAULT -1"); |
| 1641 | db.execSQL("ALTER TABLE " + MmsSmsProvider.TABLE_PENDING_MSG |
| 1642 | +" ADD COLUMN " + "pending_sub_id" |
| 1643 | + " INTEGER DEFAULT 0"); |
| 1644 | db.execSQL("ALTER TABLE " + SmsProvider.TABLE_SMS |
| 1645 | + " ADD COLUMN " + Sms.PHONE_ID |
| 1646 | + " INTEGER DEFAULT -1"); |
| 1647 | db.execSQL("ALTER TABLE " + SmsProvider.TABLE_RAW |
| 1648 | +" ADD COLUMN " + Sms.PHONE_ID |
| 1649 | + " INTEGER DEFAULT -1"); |
Ye Wen | 72f1355 | 2015-03-10 14:17:13 -0700 | [diff] [blame] | 1650 | } |
| 1651 | |
yanglv | 3dd0bab | 2015-08-24 10:40:19 +0800 | [diff] [blame] | 1652 | private void checkAndUpdateSmsTable(SQLiteDatabase db) { |
| 1653 | try { |
| 1654 | db.query(SmsProvider.TABLE_SMS, new String[] {"priority"}, null, null, null, null, |
| 1655 | null); |
| 1656 | } catch (SQLiteException e) { |
| 1657 | Log.e(TAG, "checkAndUpgradeSmsTable: ex. ", e); |
| 1658 | if (e.getMessage().startsWith(NO_SUCH_COLUMN_EXCEPTION_MESSAGE)) { |
| 1659 | db.execSQL("ALTER TABLE " + SmsProvider.TABLE_SMS + " ADD COLUMN " |
| 1660 | + "priority INTEGER DEFAULT -1"); |
| 1661 | } |
| 1662 | } |
| 1663 | } |
| 1664 | |
Tom Taylor | 1ab4800 | 2011-04-19 14:15:06 -0700 | [diff] [blame] | 1665 | @Override |
| 1666 | public synchronized SQLiteDatabase getWritableDatabase() { |
| 1667 | SQLiteDatabase db = super.getWritableDatabase(); |
| 1668 | |
Tom Taylor | 10faf3f | 2011-04-27 10:05:03 -0700 | [diff] [blame] | 1669 | if (!sTriedAutoIncrement) { |
| 1670 | sTriedAutoIncrement = true; |
Tom Taylor | 15156cd | 2012-11-15 14:15:46 -0800 | [diff] [blame] | 1671 | boolean hasAutoIncrementThreads = hasAutoIncrement(db, MmsSmsProvider.TABLE_THREADS); |
Tom Taylor | 09710ce | 2011-12-06 16:10:34 -0800 | [diff] [blame] | 1672 | boolean hasAutoIncrementAddresses = hasAutoIncrement(db, "canonical_addresses"); |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 1673 | boolean hasAutoIncrementPart = hasAutoIncrement(db, "part"); |
| 1674 | boolean hasAutoIncrementPdu = hasAutoIncrement(db, "pdu"); |
Tom Taylor | 09710ce | 2011-12-06 16:10:34 -0800 | [diff] [blame] | 1675 | Log.d(TAG, "[getWritableDatabase] hasAutoIncrementThreads: " + hasAutoIncrementThreads + |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 1676 | " hasAutoIncrementAddresses: " + hasAutoIncrementAddresses + |
| 1677 | " hasAutoIncrementPart: " + hasAutoIncrementPart + |
| 1678 | " hasAutoIncrementPdu: " + hasAutoIncrementPdu); |
Tom Taylor | 09710ce | 2011-12-06 16:10:34 -0800 | [diff] [blame] | 1679 | boolean autoIncrementThreadsSuccess = true; |
| 1680 | boolean autoIncrementAddressesSuccess = true; |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 1681 | boolean autoIncrementPartSuccess = true; |
| 1682 | boolean autoIncrementPduSuccess = true; |
Tom Taylor | 09710ce | 2011-12-06 16:10:34 -0800 | [diff] [blame] | 1683 | if (!hasAutoIncrementThreads) { |
Tom Taylor | 1ab4800 | 2011-04-19 14:15:06 -0700 | [diff] [blame] | 1684 | db.beginTransaction(); |
| 1685 | try { |
Tom Taylor | 10faf3f | 2011-04-27 10:05:03 -0700 | [diff] [blame] | 1686 | if (false && sFakeLowStorageTest) { |
| 1687 | Log.d(TAG, "[getWritableDatabase] mFakeLowStorageTest is true " + |
| 1688 | " - fake exception"); |
| 1689 | throw new Exception("FakeLowStorageTest"); |
| 1690 | } |
Tom Taylor | 09710ce | 2011-12-06 16:10:34 -0800 | [diff] [blame] | 1691 | upgradeThreadsTableToAutoIncrement(db); // a no-op if already upgraded |
Tom Taylor | 1ab4800 | 2011-04-19 14:15:06 -0700 | [diff] [blame] | 1692 | db.setTransactionSuccessful(); |
| 1693 | } catch (Throwable ex) { |
Tom Taylor | 09710ce | 2011-12-06 16:10:34 -0800 | [diff] [blame] | 1694 | Log.e(TAG, "Failed to add autoIncrement to threads;: " + ex.getMessage(), ex); |
| 1695 | autoIncrementThreadsSuccess = false; |
Tom Taylor | 1ab4800 | 2011-04-19 14:15:06 -0700 | [diff] [blame] | 1696 | } finally { |
| 1697 | db.endTransaction(); |
| 1698 | } |
| 1699 | } |
Tom Taylor | 09710ce | 2011-12-06 16:10:34 -0800 | [diff] [blame] | 1700 | if (!hasAutoIncrementAddresses) { |
| 1701 | db.beginTransaction(); |
| 1702 | try { |
| 1703 | if (false && sFakeLowStorageTest) { |
| 1704 | Log.d(TAG, "[getWritableDatabase] mFakeLowStorageTest is true " + |
| 1705 | " - fake exception"); |
| 1706 | throw new Exception("FakeLowStorageTest"); |
| 1707 | } |
| 1708 | upgradeAddressTableToAutoIncrement(db); // a no-op if already upgraded |
| 1709 | db.setTransactionSuccessful(); |
| 1710 | } catch (Throwable ex) { |
| 1711 | Log.e(TAG, "Failed to add autoIncrement to canonical_addresses: " + |
| 1712 | ex.getMessage(), ex); |
| 1713 | autoIncrementAddressesSuccess = false; |
| 1714 | } finally { |
| 1715 | db.endTransaction(); |
| 1716 | } |
| 1717 | } |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 1718 | if (!hasAutoIncrementPart) { |
| 1719 | db.beginTransaction(); |
| 1720 | try { |
| 1721 | if (false && sFakeLowStorageTest) { |
| 1722 | Log.d(TAG, "[getWritableDatabase] mFakeLowStorageTest is true " + |
| 1723 | " - fake exception"); |
| 1724 | throw new Exception("FakeLowStorageTest"); |
| 1725 | } |
| 1726 | upgradePartTableToAutoIncrement(db); // a no-op if already upgraded |
| 1727 | db.setTransactionSuccessful(); |
| 1728 | } catch (Throwable ex) { |
| 1729 | Log.e(TAG, "Failed to add autoIncrement to part: " + |
| 1730 | ex.getMessage(), ex); |
| 1731 | autoIncrementPartSuccess = false; |
| 1732 | } finally { |
| 1733 | db.endTransaction(); |
| 1734 | } |
| 1735 | } |
| 1736 | if (!hasAutoIncrementPdu) { |
| 1737 | db.beginTransaction(); |
| 1738 | try { |
| 1739 | if (false && sFakeLowStorageTest) { |
| 1740 | Log.d(TAG, "[getWritableDatabase] mFakeLowStorageTest is true " + |
| 1741 | " - fake exception"); |
| 1742 | throw new Exception("FakeLowStorageTest"); |
| 1743 | } |
| 1744 | upgradePduTableToAutoIncrement(db); // a no-op if already upgraded |
| 1745 | db.setTransactionSuccessful(); |
| 1746 | } catch (Throwable ex) { |
| 1747 | Log.e(TAG, "Failed to add autoIncrement to pdu: " + |
| 1748 | ex.getMessage(), ex); |
| 1749 | autoIncrementPduSuccess = false; |
| 1750 | } finally { |
| 1751 | db.endTransaction(); |
| 1752 | } |
| 1753 | } |
| 1754 | if (autoIncrementThreadsSuccess && |
| 1755 | autoIncrementAddressesSuccess && |
| 1756 | autoIncrementPartSuccess && |
| 1757 | autoIncrementPduSuccess) { |
Tom Taylor | 09710ce | 2011-12-06 16:10:34 -0800 | [diff] [blame] | 1758 | if (mLowStorageMonitor != null) { |
| 1759 | // We've already updated the database. This receiver is no longer necessary. |
| 1760 | Log.d(TAG, "Unregistering mLowStorageMonitor - we've upgraded"); |
| 1761 | mContext.unregisterReceiver(mLowStorageMonitor); |
| 1762 | mLowStorageMonitor = null; |
| 1763 | } |
| 1764 | } else { |
| 1765 | if (sFakeLowStorageTest) { |
| 1766 | sFakeLowStorageTest = false; |
| 1767 | } |
| 1768 | |
| 1769 | // We failed, perhaps because of low storage. Turn on a receiver to watch for |
| 1770 | // storage space. |
| 1771 | if (mLowStorageMonitor == null) { |
| 1772 | Log.d(TAG, "[getWritableDatabase] turning on storage monitor"); |
| 1773 | mLowStorageMonitor = new LowStorageMonitor(); |
| 1774 | IntentFilter intentFilter = new IntentFilter(); |
| 1775 | intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_LOW); |
| 1776 | intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK); |
| 1777 | mContext.registerReceiver(mLowStorageMonitor, intentFilter); |
| 1778 | } |
| 1779 | } |
Tom Taylor | 1ab4800 | 2011-04-19 14:15:06 -0700 | [diff] [blame] | 1780 | } |
| 1781 | return db; |
| 1782 | } |
| 1783 | |
Tom Taylor | 09710ce | 2011-12-06 16:10:34 -0800 | [diff] [blame] | 1784 | // Determine whether a particular table has AUTOINCREMENT in its schema. |
| 1785 | private boolean hasAutoIncrement(SQLiteDatabase db, String tableName) { |
Tom Taylor | 1ab4800 | 2011-04-19 14:15:06 -0700 | [diff] [blame] | 1786 | boolean result = false; |
Tom Taylor | 09710ce | 2011-12-06 16:10:34 -0800 | [diff] [blame] | 1787 | String query = "SELECT sql FROM sqlite_master WHERE type='table' AND name='" + |
| 1788 | tableName + "'"; |
Tom Taylor | 1ab4800 | 2011-04-19 14:15:06 -0700 | [diff] [blame] | 1789 | Cursor c = db.rawQuery(query, null); |
| 1790 | if (c != null) { |
| 1791 | try { |
| 1792 | if (c.moveToFirst()) { |
| 1793 | String schema = c.getString(0); |
| 1794 | result = schema != null ? schema.contains("AUTOINCREMENT") : false; |
Tom Taylor | 09710ce | 2011-12-06 16:10:34 -0800 | [diff] [blame] | 1795 | Log.d(TAG, "[MmsSmsDb] tableName: " + tableName + " hasAutoIncrement: " + |
| 1796 | schema + " result: " + result); |
Tom Taylor | 1ab4800 | 2011-04-19 14:15:06 -0700 | [diff] [blame] | 1797 | } |
| 1798 | } finally { |
| 1799 | c.close(); |
| 1800 | } |
| 1801 | } |
| 1802 | return result; |
| 1803 | } |
| 1804 | |
| 1805 | // upgradeThreadsTableToAutoIncrement() is called to add the AUTOINCREMENT keyword to |
| 1806 | // the threads table. This could fail if the user has a lot of conversations and not enough |
| 1807 | // storage to make a copy of the threads table. That's ok. This upgrade is optional. It'll |
| 1808 | // be called again next time the device is rebooted. |
| 1809 | private void upgradeThreadsTableToAutoIncrement(SQLiteDatabase db) { |
Tom Taylor | 15156cd | 2012-11-15 14:15:46 -0800 | [diff] [blame] | 1810 | if (hasAutoIncrement(db, MmsSmsProvider.TABLE_THREADS)) { |
Tom Taylor | 1ab4800 | 2011-04-19 14:15:06 -0700 | [diff] [blame] | 1811 | Log.d(TAG, "[MmsSmsDb] upgradeThreadsTableToAutoIncrement: already upgraded"); |
| 1812 | return; |
| 1813 | } |
| 1814 | Log.d(TAG, "[MmsSmsDb] upgradeThreadsTableToAutoIncrement: upgrading"); |
| 1815 | |
| 1816 | // Make the _id of the threads table autoincrement so we never re-use thread ids |
| 1817 | // Have to create a new temp threads table. Copy all the info from the old table. |
| 1818 | // Drop the old table and rename the new table to that of the old. |
| 1819 | db.execSQL("CREATE TABLE threads_temp (" + |
| 1820 | Threads._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + |
| 1821 | Threads.DATE + " INTEGER DEFAULT 0," + |
| 1822 | Threads.MESSAGE_COUNT + " INTEGER DEFAULT 0," + |
| 1823 | Threads.RECIPIENT_IDS + " TEXT," + |
| 1824 | Threads.SNIPPET + " TEXT," + |
| 1825 | Threads.SNIPPET_CHARSET + " INTEGER DEFAULT 0," + |
| 1826 | Threads.READ + " INTEGER DEFAULT 1," + |
| 1827 | Threads.TYPE + " INTEGER DEFAULT 0," + |
| 1828 | Threads.ERROR + " INTEGER DEFAULT 0," + |
| 1829 | Threads.HAS_ATTACHMENT + " INTEGER DEFAULT 0);"); |
| 1830 | |
| 1831 | db.execSQL("INSERT INTO threads_temp SELECT * from threads;"); |
| 1832 | db.execSQL("DROP TABLE threads;"); |
| 1833 | db.execSQL("ALTER TABLE threads_temp RENAME TO threads;"); |
| 1834 | } |
| 1835 | |
Tom Taylor | 09710ce | 2011-12-06 16:10:34 -0800 | [diff] [blame] | 1836 | // upgradeAddressTableToAutoIncrement() is called to add the AUTOINCREMENT keyword to |
| 1837 | // the canonical_addresses table. This could fail if the user has a lot of people they've |
| 1838 | // messaged with and not enough storage to make a copy of the canonical_addresses table. |
| 1839 | // That's ok. This upgrade is optional. It'll be called again next time the device is rebooted. |
| 1840 | private void upgradeAddressTableToAutoIncrement(SQLiteDatabase db) { |
| 1841 | if (hasAutoIncrement(db, "canonical_addresses")) { |
| 1842 | Log.d(TAG, "[MmsSmsDb] upgradeAddressTableToAutoIncrement: already upgraded"); |
| 1843 | return; |
| 1844 | } |
| 1845 | Log.d(TAG, "[MmsSmsDb] upgradeAddressTableToAutoIncrement: upgrading"); |
| 1846 | |
| 1847 | // Make the _id of the canonical_addresses table autoincrement so we never re-use ids |
| 1848 | // Have to create a new temp canonical_addresses table. Copy all the info from the old |
| 1849 | // table. Drop the old table and rename the new table to that of the old. |
| 1850 | db.execSQL("CREATE TABLE canonical_addresses_temp (_id INTEGER PRIMARY KEY AUTOINCREMENT," + |
| 1851 | "address TEXT);"); |
| 1852 | |
| 1853 | db.execSQL("INSERT INTO canonical_addresses_temp SELECT * from canonical_addresses;"); |
| 1854 | db.execSQL("DROP TABLE canonical_addresses;"); |
| 1855 | db.execSQL("ALTER TABLE canonical_addresses_temp RENAME TO canonical_addresses;"); |
| 1856 | } |
| 1857 | |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 1858 | // upgradePartTableToAutoIncrement() is called to add the AUTOINCREMENT keyword to |
| 1859 | // the part table. This could fail if the user has a lot of sound/video/picture attachments |
| 1860 | // and not enough storage to make a copy of the part table. |
| 1861 | // That's ok. This upgrade is optional. It'll be called again next time the device is rebooted. |
| 1862 | private void upgradePartTableToAutoIncrement(SQLiteDatabase db) { |
| 1863 | if (hasAutoIncrement(db, "part")) { |
| 1864 | Log.d(TAG, "[MmsSmsDb] upgradePartTableToAutoIncrement: already upgraded"); |
| 1865 | return; |
| 1866 | } |
| 1867 | Log.d(TAG, "[MmsSmsDb] upgradePartTableToAutoIncrement: upgrading"); |
| 1868 | |
| 1869 | // Make the _id of the part table autoincrement so we never re-use ids |
| 1870 | // Have to create a new temp part table. Copy all the info from the old |
| 1871 | // table. Drop the old table and rename the new table to that of the old. |
| 1872 | db.execSQL("CREATE TABLE part_temp (" + |
| 1873 | Part._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + |
| 1874 | Part.MSG_ID + " INTEGER," + |
| 1875 | Part.SEQ + " INTEGER DEFAULT 0," + |
| 1876 | Part.CONTENT_TYPE + " TEXT," + |
| 1877 | Part.NAME + " TEXT," + |
| 1878 | Part.CHARSET + " INTEGER," + |
| 1879 | Part.CONTENT_DISPOSITION + " TEXT," + |
| 1880 | Part.FILENAME + " TEXT," + |
| 1881 | Part.CONTENT_ID + " TEXT," + |
| 1882 | Part.CONTENT_LOCATION + " TEXT," + |
| 1883 | Part.CT_START + " INTEGER," + |
| 1884 | Part.CT_TYPE + " TEXT," + |
| 1885 | Part._DATA + " TEXT," + |
| 1886 | Part.TEXT + " TEXT);"); |
| 1887 | |
| 1888 | db.execSQL("INSERT INTO part_temp SELECT * from part;"); |
| 1889 | db.execSQL("DROP TABLE part;"); |
| 1890 | db.execSQL("ALTER TABLE part_temp RENAME TO part;"); |
| 1891 | |
| 1892 | // part-related triggers get tossed when the part table is dropped -- rebuild them. |
| 1893 | createMmsTriggers(db); |
| 1894 | } |
| 1895 | |
| 1896 | // upgradePduTableToAutoIncrement() is called to add the AUTOINCREMENT keyword to |
| 1897 | // the pdu table. This could fail if the user has a lot of mms messages |
| 1898 | // and not enough storage to make a copy of the pdu table. |
| 1899 | // That's ok. This upgrade is optional. It'll be called again next time the device is rebooted. |
| 1900 | private void upgradePduTableToAutoIncrement(SQLiteDatabase db) { |
| 1901 | if (hasAutoIncrement(db, "pdu")) { |
| 1902 | Log.d(TAG, "[MmsSmsDb] upgradePduTableToAutoIncrement: already upgraded"); |
| 1903 | return; |
| 1904 | } |
| 1905 | Log.d(TAG, "[MmsSmsDb] upgradePduTableToAutoIncrement: upgrading"); |
| 1906 | |
| 1907 | // Make the _id of the part table autoincrement so we never re-use ids |
| 1908 | // Have to create a new temp part table. Copy all the info from the old |
| 1909 | // table. Drop the old table and rename the new table to that of the old. |
| 1910 | db.execSQL("CREATE TABLE pdu_temp (" + |
| 1911 | Mms._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + |
| 1912 | Mms.THREAD_ID + " INTEGER," + |
| 1913 | Mms.DATE + " INTEGER," + |
| 1914 | Mms.DATE_SENT + " INTEGER DEFAULT 0," + |
| 1915 | Mms.MESSAGE_BOX + " INTEGER," + |
| 1916 | Mms.READ + " INTEGER DEFAULT 0," + |
| 1917 | Mms.MESSAGE_ID + " TEXT," + |
| 1918 | Mms.SUBJECT + " TEXT," + |
| 1919 | Mms.SUBJECT_CHARSET + " INTEGER," + |
| 1920 | Mms.CONTENT_TYPE + " TEXT," + |
| 1921 | Mms.CONTENT_LOCATION + " TEXT," + |
| 1922 | Mms.EXPIRY + " INTEGER," + |
| 1923 | Mms.MESSAGE_CLASS + " TEXT," + |
| 1924 | Mms.MESSAGE_TYPE + " INTEGER," + |
| 1925 | Mms.MMS_VERSION + " INTEGER," + |
| 1926 | Mms.MESSAGE_SIZE + " INTEGER," + |
| 1927 | Mms.PRIORITY + " INTEGER," + |
| 1928 | Mms.READ_REPORT + " INTEGER," + |
| 1929 | Mms.REPORT_ALLOWED + " INTEGER," + |
| 1930 | Mms.RESPONSE_STATUS + " INTEGER," + |
| 1931 | Mms.STATUS + " INTEGER," + |
| 1932 | Mms.TRANSACTION_ID + " TEXT," + |
| 1933 | Mms.RETRIEVE_STATUS + " INTEGER," + |
| 1934 | Mms.RETRIEVE_TEXT + " TEXT," + |
| 1935 | Mms.RETRIEVE_TEXT_CHARSET + " INTEGER," + |
| 1936 | Mms.READ_STATUS + " INTEGER," + |
| 1937 | Mms.CONTENT_CLASS + " INTEGER," + |
| 1938 | Mms.RESPONSE_TEXT + " TEXT," + |
| 1939 | Mms.DELIVERY_TIME + " INTEGER," + |
| 1940 | Mms.DELIVERY_REPORT + " INTEGER," + |
| 1941 | Mms.LOCKED + " INTEGER DEFAULT 0," + |
Wink Saville | a42e417 | 2014-12-09 18:55:22 -0800 | [diff] [blame] | 1942 | Mms.SUBSCRIPTION_ID + " INTEGER DEFAULT " |
| 1943 | + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " + |
Suresh Koleti | 02354f1 | 2014-08-19 16:21:45 +0530 | [diff] [blame] | 1944 | Mms.PHONE_ID + " INTEGER DEFAULT -1," + |
Tom Taylor | 49c9ede | 2012-09-09 09:41:50 -0700 | [diff] [blame] | 1945 | Mms.SEEN + " INTEGER DEFAULT 0," + |
| 1946 | Mms.TEXT_ONLY + " INTEGER DEFAULT 0" + |
| 1947 | ");"); |
| 1948 | |
| 1949 | db.execSQL("INSERT INTO pdu_temp SELECT * from pdu;"); |
| 1950 | db.execSQL("DROP TABLE pdu;"); |
| 1951 | db.execSQL("ALTER TABLE pdu_temp RENAME TO pdu;"); |
| 1952 | |
| 1953 | // pdu-related triggers get tossed when the part table is dropped -- rebuild them. |
| 1954 | createMmsTriggers(db); |
| 1955 | } |
| 1956 | |
Prasath Balakrishnan | 1dfaed1 | 2015-11-18 20:36:17 +0530 | [diff] [blame] | 1957 | private boolean createSharedPrefForUpgrade() { |
| 1958 | String FILENAME = "upgradeSmsMmsDb"; |
| 1959 | File prefFile = new File("/data/data/" + mContext.getPackageName() |
| 1960 | + "/shared_prefs/" + FILENAME + ".xml"); |
| 1961 | |
| 1962 | if (!prefFile.exists()) { |
| 1963 | Editor editor; |
| 1964 | Log.d(TAG, "Shared Preference Created with name: " + FILENAME); |
| 1965 | SharedPreferences pref = mContext.getSharedPreferences(FILENAME, |
| 1966 | mContext.MODE_PRIVATE); |
| 1967 | editor = pref.edit(); |
| 1968 | editor.putBoolean("isupgraded", true); |
| 1969 | editor.commit(); |
| 1970 | return true; |
| 1971 | } else { |
| 1972 | Log.d(TAG, "Skipping upgrade/Upgrade already Done"); |
| 1973 | return false; |
| 1974 | } |
| 1975 | } |
| 1976 | |
| 1977 | private void upgradeSmsMmsDb(SQLiteDatabase db) { |
| 1978 | if (createSharedPrefForUpgrade()) { |
| 1979 | db.beginTransaction(); |
| 1980 | try { |
| 1981 | upgradeDatabaseSmsMms(db); |
| 1982 | db.setTransactionSuccessful(); |
| 1983 | } catch (Throwable ex) { |
| 1984 | Log.e(TAG, ex.getMessage(), ex); |
| 1985 | } finally { |
| 1986 | db.endTransaction(); |
| 1987 | } |
| 1988 | } |
| 1989 | } |
| 1990 | |
| 1991 | private void upgradeDatabaseSmsMms(SQLiteDatabase db) { |
| 1992 | db.execSQL("CREATE VIEW IF NOT EXISTS " + SmsProvider.VIEW_SMS_RESTRICTED + |
| 1993 | " AS " + "SELECT * FROM " + SmsProvider.TABLE_SMS + " WHERE " + |
| 1994 | Sms.TYPE + "=" + Sms.MESSAGE_TYPE_INBOX + |
| 1995 | " OR " + |
| 1996 | Sms.TYPE + "=" + Sms.MESSAGE_TYPE_SENT + ";"); |
| 1997 | db.execSQL("CREATE VIEW IF NOT EXISTS " + MmsProvider.VIEW_PDU_RESTRICTED + |
| 1998 | " AS " + "SELECT * FROM " + MmsProvider.TABLE_PDU + " WHERE " + |
| 1999 | "(" + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_INBOX + |
| 2000 | " OR " + |
| 2001 | Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_SENT + ")" + |
| 2002 | " AND " + |
| 2003 | "(" + Mms.MESSAGE_TYPE + "!=" + |
| 2004 | PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND + ");"); |
| 2005 | } |
| 2006 | |
Tom Taylor | 10faf3f | 2011-04-27 10:05:03 -0700 | [diff] [blame] | 2007 | private class LowStorageMonitor extends BroadcastReceiver { |
| 2008 | |
| 2009 | public LowStorageMonitor() { |
| 2010 | } |
| 2011 | |
| 2012 | public void onReceive(Context context, Intent intent) { |
| 2013 | String action = intent.getAction(); |
| 2014 | |
| 2015 | Log.d(TAG, "[LowStorageMonitor] onReceive intent " + action); |
| 2016 | |
| 2017 | if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) { |
| 2018 | sTriedAutoIncrement = false; // try to upgrade on the next getWriteableDatabase |
| 2019 | } |
| 2020 | } |
| 2021 | } |
| 2022 | |
Wei Huang | 1047ab4 | 2009-09-29 20:53:26 -0700 | [diff] [blame] | 2023 | private void updateThreadsAttachmentColumn(SQLiteDatabase db) { |
| 2024 | // Set the values of that column correctly based on the current |
| 2025 | // contents of the database. |
| 2026 | db.execSQL("UPDATE threads SET has_attachment=1 WHERE _id IN " + |
| 2027 | " (SELECT DISTINCT pdu.thread_id FROM part " + |
| 2028 | " JOIN pdu ON pdu._id=part.mid " + |
| 2029 | " WHERE part.ct != 'text/plain' AND part.ct != 'application/smil')"); |
| 2030 | } |
The Android Open Source Project | 7236c3a | 2009-03-03 19:32:44 -0800 | [diff] [blame] | 2031 | } |