MmsSmsProvider.java revision 5926996da70fff9275e948d1cf8a0f17b52a5e14
17236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project/* 27236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 37236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 47236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 57236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * you may not use this file except in compliance with the License. 67236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * You may obtain a copy of the License at 77236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 87236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 97236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * See the License for the specific language governing permissions and 147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * limitations under the License. 157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectpackage com.android.providers.telephony; 187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1966d373c4797c53207e8f1ea97f3dc5541f390152Mark Wagnerimport java.util.Arrays; 2066d373c4797c53207e8f1ea97f3dc5541f390152Mark Wagnerimport java.util.HashSet; 2166d373c4797c53207e8f1ea97f3dc5541f390152Mark Wagnerimport java.util.List; 2266d373c4797c53207e8f1ea97f3dc5541f390152Mark Wagnerimport java.util.Set; 237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.content.ContentProvider; 257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.content.ContentValues; 267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.content.Context; 277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.content.UriMatcher; 287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.Cursor; 297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.DatabaseUtils; 307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase; 317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.sqlite.SQLiteOpenHelper; 327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.sqlite.SQLiteQueryBuilder; 337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.net.Uri; 347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.BaseColumns; 357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.CanonicalAddressesColumns; 367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Mms; 377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.MmsSms; 387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Sms; 397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Threads; 407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.ThreadsColumns; 417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.MmsSms.PendingMessages; 427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Sms.Conversations; 437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.text.TextUtils; 447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.util.Log; 457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 46b1bae65bf18dc22762cf7b8210fdad836b3e4ee5Tom Taylorimport com.google.android.mms.pdu.PduHeaders; 477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project/** 497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * This class provides the ability to query the MMS and SMS databases 507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * at the same time, mixing messages from both in a single thread 517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * (A.K.A. conversation). 527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * A virtual column, MmsSms.TYPE_DISCRIMINATOR_COLUMN, may be 547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * requested in the projection for a query. Its value is either "mms" 557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * or "sms", depending on whether the message represented by the row 567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * is an MMS message or an SMS message, respectively. 577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * This class also provides the ability to find out what addresses 597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * participated in a particular thread. It doesn't support updates 607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * for either of these. 617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * This class provides a way to allocate and retrieve thread IDs. 637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * This is done atomically through a query. There is no insert URI 647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * for this. 657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Finally, this class provides a way to delete or update all messages 677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * in a thread. 687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectpublic class MmsSmsProvider extends ContentProvider { 707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final UriMatcher URI_MATCHER = 717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project new UriMatcher(UriMatcher.NO_MATCH); 727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String LOG_TAG = "MmsSmsProvider"; 73816e934a43bf705835bdb24503a85a14c4861991Tom Taylor private static final boolean DEBUG = false; 747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String NO_DELETES_INSERTS_OR_UPDATES = 767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "MmsSmsProvider does not support deletes, inserts, or updates for this URI."; 77f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_CONVERSATIONS = 0; 78f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_CONVERSATIONS_MESSAGES = 1; 79f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_CONVERSATIONS_RECIPIENTS = 2; 80f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_MESSAGES_BY_PHONE = 3; 81f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_THREAD_ID = 4; 82f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_CANONICAL_ADDRESS = 5; 83f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_PENDING_MSG = 6; 84f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_COMPLETE_CONVERSATIONS = 7; 85f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_UNDELIVERED_MSG = 8; 86f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_CONVERSATIONS_SUBJECT = 9; 87f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_NOTIFICATIONS = 10; 88f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_OBSOLETE_THREADS = 11; 89f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_DRAFT = 12; 90f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_CANONICAL_ADDRESSES = 13; 91f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_SEARCH = 14; 928e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner private static final int URI_SEARCH_SUGGEST = 15; 938e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner private static final int URI_FIRST_LOCKED_MESSAGE_ALL = 16; 948e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner private static final int URI_FIRST_LOCKED_MESSAGE_BY_THREAD_ID = 17; 956a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner private static final int URI_MESSAGE_ID_TO_THREAD = 18; 967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * the name of the table that is used to store the queue of 997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * messages(both MMS and SMS) to be sent/downloaded. 1007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 1017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project public static final String TABLE_PENDING_MSG = "pending_msgs"; 1027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1031ecf192c60625c5227336430ee36705c13ae06e2Wei Huang /** 1041ecf192c60625c5227336430ee36705c13ae06e2Wei Huang * the name of the table that is used to store the canonical addresses for both SMS and MMS. 1051ecf192c60625c5227336430ee36705c13ae06e2Wei Huang */ 1061ecf192c60625c5227336430ee36705c13ae06e2Wei Huang private static final String TABLE_CANONICAL_ADDRESSES = "canonical_addresses"; 1071ecf192c60625c5227336430ee36705c13ae06e2Wei Huang 1087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These constants are used to construct union queries across the 1097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // MMS and SMS base tables. 1107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These are the columns that appear in both the MMS ("pdu") and 1127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // SMS ("sms") message tables. 1137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String[] MMS_SMS_COLUMNS = 114ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert { BaseColumns._ID, Mms.DATE, Mms.DATE_SENT, Mms.READ, Mms.THREAD_ID, Mms.LOCKED }; 1157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These are the columns that appear only in the MMS message 1177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // table. 1187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String[] MMS_ONLY_COLUMNS = { 1197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.CONTENT_CLASS, Mms.CONTENT_LOCATION, Mms.CONTENT_TYPE, 1207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.DELIVERY_REPORT, Mms.EXPIRY, Mms.MESSAGE_CLASS, Mms.MESSAGE_ID, 1217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.MESSAGE_SIZE, Mms.MESSAGE_TYPE, Mms.MESSAGE_BOX, Mms.PRIORITY, 1227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.READ_STATUS, Mms.RESPONSE_STATUS, Mms.RESPONSE_TEXT, 1237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.RETRIEVE_STATUS, Mms.RETRIEVE_TEXT_CHARSET, Mms.REPORT_ALLOWED, 1247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.READ_REPORT, Mms.STATUS, Mms.SUBJECT, Mms.SUBJECT_CHARSET, 1257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.TRANSACTION_ID, Mms.MMS_VERSION }; 1267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These are the columns that appear only in the SMS message 1287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // table. 1297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String[] SMS_ONLY_COLUMNS = 1307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project { "address", "body", "person", "reply_path_present", 131ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor "service_center", "status", "subject", "type", "error_code" }; 1327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These are all the columns that appear in the "threads" table. 1347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String[] THREADS_COLUMNS = { 1357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project BaseColumns._ID, 1367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ThreadsColumns.DATE, 1377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ThreadsColumns.RECIPIENT_IDS, 1387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ThreadsColumns.MESSAGE_COUNT 1397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project }; 1407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1411ecf192c60625c5227336430ee36705c13ae06e2Wei Huang private static final String[] CANONICAL_ADDRESSES_COLUMNS_1 = 1421ecf192c60625c5227336430ee36705c13ae06e2Wei Huang new String[] { CanonicalAddressesColumns.ADDRESS }; 1431ecf192c60625c5227336430ee36705c13ae06e2Wei Huang 1441ecf192c60625c5227336430ee36705c13ae06e2Wei Huang private static final String[] CANONICAL_ADDRESSES_COLUMNS_2 = 1451ecf192c60625c5227336430ee36705c13ae06e2Wei Huang new String[] { CanonicalAddressesColumns._ID, 1461ecf192c60625c5227336430ee36705c13ae06e2Wei Huang CanonicalAddressesColumns.ADDRESS }; 1471ecf192c60625c5227336430ee36705c13ae06e2Wei Huang 1487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These are all the columns that appear in the MMS and SMS 1497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // message tables. 1507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String[] UNION_COLUMNS = 1517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project new String[MMS_SMS_COLUMNS.length 1527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + MMS_ONLY_COLUMNS.length 1537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + SMS_ONLY_COLUMNS.length]; 1547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These are all the columns that appear in the MMS table. 1567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final Set<String> MMS_COLUMNS = new HashSet<String>(); 1577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These are all the columns that appear in the SMS table. 1597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final Set<String> SMS_COLUMNS = new HashSet<String>(); 1607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String VND_ANDROID_DIR_MMS_SMS = 1627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "vnd.android-dir/mms-sms"; 1637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String[] ID_PROJECTION = { BaseColumns._ID }; 1657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String[] EMPTY_STRING_ARRAY = new String[0]; 1677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String SMS_CONVERSATION_CONSTRAINT = "(" + 1697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Sms.TYPE + " != " + Sms.MESSAGE_TYPE_DRAFT + ")"; 1707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String MMS_CONVERSATION_CONSTRAINT = "(" + 1727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.MESSAGE_BOX + " != " + Mms.MESSAGE_BOX_DRAFTS + " AND (" + 1737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.MESSAGE_TYPE + " = " + PduHeaders.MESSAGE_TYPE_SEND_REQ + " OR " + 1747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.MESSAGE_TYPE + " = " + PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF + " OR " + 1757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.MESSAGE_TYPE + " = " + PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND + "))"; 1767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 17701c75ba95b875674a83128defc6b267e522db346Chen Mike // Search on the words table but return the rows from the corresponding sms table 17801c75ba95b875674a83128defc6b267e522db346Chen Mike private static final String SMS_QUERY = 179ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert "SELECT sms._id AS _id,thread_id,address,body,date,date_sent,index_text,words._id " + 18076e665b3042222aa6d65eccb0f84618f387837aaMark Wagner "FROM sms,words WHERE (index_text MATCH ? " + 18101c75ba95b875674a83128defc6b267e522db346Chen Mike "AND sms._id=words.source_id AND words.table_to_use=1)"; 18201c75ba95b875674a83128defc6b267e522db346Chen Mike 18301c75ba95b875674a83128defc6b267e522db346Chen Mike // Search on the words table but return the rows from the corresponding parts table 18401c75ba95b875674a83128defc6b267e522db346Chen Mike private static final String MMS_QUERY = 18501c75ba95b875674a83128defc6b267e522db346Chen Mike "SELECT pdu._id,thread_id,addr.address,part.text " + 186ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert "AS body,pdu.date,pdu.date_sent,index_text,words._id " + 18701c75ba95b875674a83128defc6b267e522db346Chen Mike "FROM pdu,part,addr,words WHERE ((part.mid=pdu._id) AND " + 18801c75ba95b875674a83128defc6b267e522db346Chen Mike "(addr.msg_id=pdu._id) AND " + 18901c75ba95b875674a83128defc6b267e522db346Chen Mike "(addr.type=" + PduHeaders.TO + ") AND " + 19001c75ba95b875674a83128defc6b267e522db346Chen Mike "(part.ct='text/plain') AND " + 19176e665b3042222aa6d65eccb0f84618f387837aaMark Wagner "(index_text MATCH ?) AND " + 19201c75ba95b875674a83128defc6b267e522db346Chen Mike "(part._id = words.source_id) AND " + 19301c75ba95b875674a83128defc6b267e522db346Chen Mike "(words.table_to_use=2))"; 19401c75ba95b875674a83128defc6b267e522db346Chen Mike 19501c75ba95b875674a83128defc6b267e522db346Chen Mike // This code queries the sms and mms tables and returns a unified result set 19601c75ba95b875674a83128defc6b267e522db346Chen Mike // of text matches. We query the sms table which is pretty simple. We also 1979081ab6bd08fa66bac28d65f0ce4fca14b6954a6Jean-Baptiste Queru // query the pdu, part and addr table to get the mms result. Notet we're 19801c75ba95b875674a83128defc6b267e522db346Chen Mike // using a UNION so we have to have the same number of result columns from 19901c75ba95b875674a83128defc6b267e522db346Chen Mike // both queries. 20001c75ba95b875674a83128defc6b267e522db346Chen Mike private static final String SMS_MMS_QUERY = 20101c75ba95b875674a83128defc6b267e522db346Chen Mike SMS_QUERY + " UNION " + MMS_QUERY + 20201c75ba95b875674a83128defc6b267e522db346Chen Mike " GROUP BY thread_id ORDER BY thread_id ASC, date DESC"; 20301c75ba95b875674a83128defc6b267e522db346Chen Mike 2047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String AUTHORITY = "mms-sms"; 2057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project static { 2077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "conversations", URI_CONVERSATIONS); 2087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "complete-conversations", URI_COMPLETE_CONVERSATIONS); 2097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // In these patterns, "#" is the thread ID. 2117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI( 2127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project AUTHORITY, "conversations/#", URI_CONVERSATIONS_MESSAGES); 2137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI( 2147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project AUTHORITY, "conversations/#/recipients", 2157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_CONVERSATIONS_RECIPIENTS); 2167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI( 2187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project AUTHORITY, "conversations/#/subject", 2197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_CONVERSATIONS_SUBJECT); 2207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // URI for deleting obsolete threads. 2227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "conversations/obsolete", URI_OBSOLETE_THREADS); 2237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI( 2257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project AUTHORITY, "messages/byphone/*", 2267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MESSAGES_BY_PHONE); 2277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // In this pattern, two query parameter names are expected: 2297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // "subject" and "recipient." Multiple "recipient" parameters 2307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // may be present. 2317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "threadID", URI_THREAD_ID); 2327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // Use this pattern to query the canonical address by given ID. 2347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "canonical-address/#", URI_CANONICAL_ADDRESS); 2357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 23637e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick // Use this pattern to query all canonical addresses. 23737e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick URI_MATCHER.addURI(AUTHORITY, "canonical-addresses", URI_CANONICAL_ADDRESSES); 238f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner 23966d373c4797c53207e8f1ea97f3dc5541f390152Mark Wagner URI_MATCHER.addURI(AUTHORITY, "search", URI_SEARCH); 2408e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner URI_MATCHER.addURI(AUTHORITY, "searchSuggest", URI_SEARCH_SUGGEST); 24137e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick 2427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // In this pattern, two query parameters may be supplied: 2437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // "protocol" and "message." For example: 2447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // content://mms-sms/pending? 2457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // -> Return all pending messages; 2467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // content://mms-sms/pending?protocol=sms 2477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // -> Only return pending SMs; 2487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // content://mms-sms/pending?protocol=mms&message=1 2497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // -> Return the the pending MM which ID equals '1'. 2507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // 2517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "pending", URI_PENDING_MSG); 2527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // Use this pattern to get a list of undelivered messages. 2547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "undelivered", URI_UNDELIVERED_MSG); 2557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // Use this pattern to see what delivery status reports (for 2577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // both MMS and SMS) have not been delivered to the user. 2587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "notifications", URI_NOTIFICATIONS); 2597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "draft", URI_DRAFT); 261f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 262f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor URI_MATCHER.addURI(AUTHORITY, "locked", URI_FIRST_LOCKED_MESSAGE_ALL); 263f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 264f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor URI_MATCHER.addURI(AUTHORITY, "locked/#", URI_FIRST_LOCKED_MESSAGE_BY_THREAD_ID); 265f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 2666a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner URI_MATCHER.addURI(AUTHORITY, "messageIdToThread", URI_MESSAGE_ID_TO_THREAD); 2677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project initializeColumnSets(); 2687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 2697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private SQLiteOpenHelper mOpenHelper; 2717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 272845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa private boolean mUseStrictPhoneNumberComparation; 273845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa 2747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project @Override 2757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project public boolean onCreate() { 2767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mOpenHelper = MmsSmsDatabaseHelper.getInstance(getContext()); 277845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa mUseStrictPhoneNumberComparation = 278845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa getContext().getResources().getBoolean( 279845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa com.android.internal.R.bool.config_use_strict_phone_number_comparation); 2807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return true; 2817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 2827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project @Override 2847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project public Cursor query(Uri uri, String[] projection, 2857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String selection, String[] selectionArgs, String sortOrder) { 2867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 2877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Cursor cursor = null; 2887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project switch(URI_MATCHER.match(uri)) { 2897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_COMPLETE_CONVERSATIONS: 290f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor cursor = getCompleteConversations(projection, selection, sortOrder); 2917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 2927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CONVERSATIONS: 2937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String simple = uri.getQueryParameter("simple"); 2947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if ((simple != null) && simple.equals("true")) { 2957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String threadType = uri.getQueryParameter("thread_type"); 2967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (!TextUtils.isEmpty(threadType)) { 2977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection = concatSelections( 2987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, Threads.TYPE + "=" + threadType); 2997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 3007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = getSimpleConversations( 3017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project projection, selection, selectionArgs, sortOrder); 3027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } else { 3037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = getConversations( 304f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor projection, selection, sortOrder); 3057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 3067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CONVERSATIONS_MESSAGES: 308f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor cursor = getConversationMessages(uri.getPathSegments().get(1), projection, 309f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor selection, sortOrder); 3107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CONVERSATIONS_RECIPIENTS: 3127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = getConversationById( 3137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project uri.getPathSegments().get(1), projection, selection, 3147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selectionArgs, sortOrder); 3157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CONVERSATIONS_SUBJECT: 3177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = getConversationById( 3187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project uri.getPathSegments().get(1), projection, selection, 3197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selectionArgs, sortOrder); 3207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_MESSAGES_BY_PHONE: 3227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = getMessagesByPhoneNumber( 323f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor uri.getPathSegments().get(2), projection, selection, sortOrder); 3247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_THREAD_ID: 3267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project List<String> recipients = uri.getQueryParameters("recipient"); 3277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 3287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = getThreadId(recipients); 3297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CANONICAL_ADDRESS: { 3317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String extraSelection = "_id=" + uri.getPathSegments().get(1); 3327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSelection = TextUtils.isEmpty(selection) 3337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ? extraSelection : extraSelection + " AND " + selection; 3341ecf192c60625c5227336430ee36705c13ae06e2Wei Huang cursor = db.query(TABLE_CANONICAL_ADDRESSES, 3351ecf192c60625c5227336430ee36705c13ae06e2Wei Huang CANONICAL_ADDRESSES_COLUMNS_1, 3361ecf192c60625c5227336430ee36705c13ae06e2Wei Huang finalSelection, 3371ecf192c60625c5227336430ee36705c13ae06e2Wei Huang selectionArgs, 3381ecf192c60625c5227336430ee36705c13ae06e2Wei Huang null, null, 3391ecf192c60625c5227336430ee36705c13ae06e2Wei Huang sortOrder); 3407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 34237e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick case URI_CANONICAL_ADDRESSES: 3431ecf192c60625c5227336430ee36705c13ae06e2Wei Huang cursor = db.query(TABLE_CANONICAL_ADDRESSES, 3441ecf192c60625c5227336430ee36705c13ae06e2Wei Huang CANONICAL_ADDRESSES_COLUMNS_2, 3451ecf192c60625c5227336430ee36705c13ae06e2Wei Huang selection, 3461ecf192c60625c5227336430ee36705c13ae06e2Wei Huang selectionArgs, 3471ecf192c60625c5227336430ee36705c13ae06e2Wei Huang null, null, 3481ecf192c60625c5227336430ee36705c13ae06e2Wei Huang sortOrder); 34937e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick break; 3508e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner case URI_SEARCH_SUGGEST: { 3518e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner String searchString = uri.getQueryParameter("pattern"); 3529e1fd44679b2de6df6af2c1e8b6bf191e799f4a9Mark Wagner 3539e1fd44679b2de6df6af2c1e8b6bf191e799f4a9Mark Wagner // find the words which match the pattern using the snippet function. The 3549e1fd44679b2de6df6af2c1e8b6bf191e799f4a9Mark Wagner // snippet function parameters mainly describe how to format the result. 3559e1fd44679b2de6df6af2c1e8b6bf191e799f4a9Mark Wagner // See http://www.sqlite.org/fts3.html#section_4_2 for details. 3569e1fd44679b2de6df6af2c1e8b6bf191e799f4a9Mark Wagner String query = String.format("SELECT snippet(words, '', ' ', '', 1, 1) as snippet FROM words WHERE index_text MATCH '%s*' ORDER BY snippet LIMIT 50;", searchString); 3578e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner if ( sortOrder != null 3588e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner || selection != null 3598e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner || selectionArgs != null 3608e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner || projection != null) { 3618e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner throw new IllegalArgumentException( 3628e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner "do not specify sortOrder, selection, selectionArgs, or projection" + 3638e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner "with this query"); 3648e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner } 3658e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner 3668e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner cursor = db.rawQuery(query, null); 3678e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner break; 3688e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner } 3696a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner case URI_MESSAGE_ID_TO_THREAD: { 3706a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner // Given a message ID and an indicator for SMS vs. MMS return 3716a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner // the thread id of the corresponding thread. 3726a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner try { 3736a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner long id = Long.parseLong(uri.getQueryParameter("row_id")); 3746a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner switch (Integer.parseInt(uri.getQueryParameter("table_to_use"))) { 3756a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner case 1: // sms 3766a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner cursor = db.query( 3776a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner "sms", 3786a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner new String[] { "thread_id" }, 3796a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner "_id=?", 3806a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner new String[] { String.valueOf(id) }, 3816a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner null, 3826a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner null, 3836a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner null); 3846a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner break; 3856a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner case 2: // mms 3866a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner String mmsQuery = 3876a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner "SELECT thread_id FROM pdu,part WHERE ((part.mid=pdu._id) AND " + 3886a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner "(part._id=?))"; 3896a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner cursor = db.rawQuery(mmsQuery, new String[] { String.valueOf(id) }); 3906a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner break; 3916a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner } 3926a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner } catch (NumberFormatException ex) { 3936a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner // ignore... return empty cursor 3946a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner } 3956a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner break; 3966a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner } 3978e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner case URI_SEARCH: { 39887bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor if ( sortOrder != null 39987bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor || selection != null 40087bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor || selectionArgs != null 401f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner || projection != null) { 402f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner throw new IllegalArgumentException( 403f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner "do not specify sortOrder, selection, selectionArgs, or projection" + 404f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner "with this query"); 40566d373c4797c53207e8f1ea97f3dc5541f390152Mark Wagner } 40687bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor 4078e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner String searchString = uri.getQueryParameter("pattern") + "*"; 4088e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner 4098e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner try { 41001c75ba95b875674a83128defc6b267e522db346Chen Mike cursor = db.rawQuery(SMS_MMS_QUERY, new String[] { searchString, searchString }); 4118e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner } catch (Exception ex) { 4128e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner Log.e(LOG_TAG, "got exception: " + ex.toString()); 4138e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner } 41466d373c4797c53207e8f1ea97f3dc5541f390152Mark Wagner break; 4158e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner } 4167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_PENDING_MSG: { 4177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String protoName = uri.getQueryParameter("protocol"); 4187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String msgId = uri.getQueryParameter("message"); 4197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int proto = TextUtils.isEmpty(protoName) ? -1 4207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project : (protoName.equals("sms") ? MmsSms.SMS_PROTO : MmsSms.MMS_PROTO); 4217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 4227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String extraSelection = (proto != -1) ? 4237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project (PendingMessages.PROTO_TYPE + "=" + proto) : " 0=0 "; 4247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (!TextUtils.isEmpty(msgId)) { 4257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project extraSelection += " AND " + PendingMessages.MSG_ID + "=" + msgId; 4267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 4277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 4287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSelection = TextUtils.isEmpty(selection) 4297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ? extraSelection : ("(" + extraSelection + ") AND " + selection); 4307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalOrder = TextUtils.isEmpty(sortOrder) 4317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ? PendingMessages.DUE_TIME : sortOrder; 4327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = db.query(TABLE_PENDING_MSG, null, 4337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project finalSelection, selectionArgs, null, null, finalOrder); 4347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 4357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 4367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_UNDELIVERED_MSG: { 4377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = getUndeliveredMessages(projection, selection, 4387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selectionArgs, sortOrder); 4397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 4407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 4417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_DRAFT: { 442f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor cursor = getDraftThread(projection, selection, sortOrder); 4437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 4447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 445f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor case URI_FIRST_LOCKED_MESSAGE_BY_THREAD_ID: { 446f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor long threadId; 447f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor try { 448f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor threadId = Long.parseLong(uri.getLastPathSegment()); 449f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor } catch (NumberFormatException e) { 450f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor Log.e(LOG_TAG, "Thread ID must be a long."); 451f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor break; 452f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor } 453f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor cursor = getFirstLockedMessage(projection, "thread_id=" + Long.toString(threadId), 454f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor sortOrder); 455f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor break; 456f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor } 457f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor case URI_FIRST_LOCKED_MESSAGE_ALL: { 458f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor cursor = getFirstLockedMessage(projection, selection, sortOrder); 459f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor break; 460f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor } 4617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project default: 4627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project throw new IllegalStateException("Unrecognized URI:" + uri); 4637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 4647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 4655926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor if (cursor != null) { 4665926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor cursor.setNotificationUri(getContext().getContentResolver(), MmsSms.CONTENT_URI); 4675926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor } 4687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return cursor; 4697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 4707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 4717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 4727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the canonical address ID for this address. 4737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 4747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private long getSingleAddressId(String address) { 4757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project boolean isEmail = Mms.isEmailAddress(address); 476e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor boolean isPhoneNumber = Mms.isPhoneNumber(address); 477e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor 478e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor // We lowercase all email addresses, but not addresses that aren't numbers, because 479e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor // that would incorrectly turn an address such as "My Vodafone" into "my vodafone" 480e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor // and the thread title would be incorrect when displayed in the UI. 4817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String refinedAddress = isEmail ? address.toLowerCase() : address; 482e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor 483c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang String selection = "address=?"; 484c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang String[] selectionArgs; 48514595cbe9045755a5aa2bd28989c147c4709268cWei Huang long retVal = -1L; 486c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang 487e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor if (!isPhoneNumber) { 488c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang selectionArgs = new String[] { refinedAddress }; 489c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang } else { 49001c75ba95b875674a83128defc6b267e522db346Chen Mike selection += " OR PHONE_NUMBERS_EQUAL(address, ?, " + 49101c75ba95b875674a83128defc6b267e522db346Chen Mike (mUseStrictPhoneNumberComparation ? 1 : 0) + ")"; 492c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang selectionArgs = new String[] { refinedAddress, refinedAddress }; 493c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang } 494c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang 4957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Cursor cursor = null; 4967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 4977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project try { 4987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 4997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = db.query( 5007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "canonical_addresses", ID_PROJECTION, 5017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, selectionArgs, null, null, null); 5027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (cursor.getCount() == 0) { 5047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ContentValues contentValues = new ContentValues(1); 5057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project contentValues.put(CanonicalAddressesColumns.ADDRESS, refinedAddress); 5067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project db = mOpenHelper.getWritableDatabase(); 50814595cbe9045755a5aa2bd28989c147c4709268cWei Huang retVal = db.insert("canonical_addresses", 5097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project CanonicalAddressesColumns.ADDRESS, contentValues); 51014595cbe9045755a5aa2bd28989c147c4709268cWei Huang 511ea59f86662471e682f880b4916ce7588803f5605Wink Saville Log.d(LOG_TAG, "getSingleAddressId: insert new canonical_address for " + 512ea59f86662471e682f880b4916ce7588803f5605Wink Saville /*address*/ "xxxxxx" + ", _id=" + retVal); 51314595cbe9045755a5aa2bd28989c147c4709268cWei Huang 51414595cbe9045755a5aa2bd28989c147c4709268cWei Huang return retVal; 5157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (cursor.moveToFirst()) { 51814595cbe9045755a5aa2bd28989c147c4709268cWei Huang retVal = cursor.getLong(cursor.getColumnIndexOrThrow(BaseColumns._ID)); 5197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } finally { 5217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (cursor != null) { 5227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor.close(); 5237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 52614595cbe9045755a5aa2bd28989c147c4709268cWei Huang return retVal; 5277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 5307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the canonical address IDs for these addresses. 5317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 5327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Set<Long> getAddressIds(List<String> addresses) { 5337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Set<Long> result = new HashSet<Long>(addresses.size()); 5347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (String address : addresses) { 5367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (!address.equals(PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR)) { 5377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project long id = getSingleAddressId(address); 5387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (id != -1L) { 5397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project result.add(id); 5407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } else { 54114595cbe9045755a5aa2bd28989c147c4709268cWei Huang Log.e(LOG_TAG, "getAddressIds: address ID not found for " + address); 5427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return result; 5467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 5497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return a sorted array of the given Set of Longs. 5507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 5517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private long[] getSortedSet(Set<Long> numbers) { 5527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int size = numbers.size(); 5537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project long[] result = new long[size]; 5547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int i = 0; 5557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (Long number : numbers) { 5577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project result[i++] = number; 5587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 55914595cbe9045755a5aa2bd28989c147c4709268cWei Huang 56014595cbe9045755a5aa2bd28989c147c4709268cWei Huang if (size > 1) { 56114595cbe9045755a5aa2bd28989c147c4709268cWei Huang Arrays.sort(result); 56214595cbe9045755a5aa2bd28989c147c4709268cWei Huang } 56314595cbe9045755a5aa2bd28989c147c4709268cWei Huang 5647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return result; 5657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 5687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return a String of the numbers in the given array, in order, 5697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * separated by spaces. 5707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 5717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private String getSpaceSeparatedNumbers(long[] numbers) { 5727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int size = numbers.length; 5737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project StringBuilder buffer = new StringBuilder(); 5747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (int i = 0; i < size; i++) { 5767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (i != 0) { 5777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project buffer.append(' '); 5787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project buffer.append(numbers[i]); 5807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return buffer.toString(); 5827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 5857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Insert a record for a new thread. 5867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 5877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private void insertThread(String recipientIds, int numberOfRecipients) { 5887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ContentValues values = new ContentValues(4); 5897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project long date = System.currentTimeMillis(); 5917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project values.put(ThreadsColumns.DATE, date - date % 1000); 5927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project values.put(ThreadsColumns.RECIPIENT_IDS, recipientIds); 5937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (numberOfRecipients > 1) { 5947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project values.put(Threads.TYPE, Threads.BROADCAST_THREAD); 5957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project values.put(ThreadsColumns.MESSAGE_COUNT, 0); 5977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 59814595cbe9045755a5aa2bd28989c147c4709268cWei Huang long result = mOpenHelper.getWritableDatabase().insert("threads", null, values); 59914595cbe9045755a5aa2bd28989c147c4709268cWei Huang Log.d(LOG_TAG, "insertThread: created new thread_id " + result + 600ea59f86662471e682f880b4916ce7588803f5605Wink Saville " for recipientIds " + /*recipientIds*/ "xxxxxxx"); 60114595cbe9045755a5aa2bd28989c147c4709268cWei Huang 6027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project getContext().getContentResolver().notifyChange(MmsSms.CONTENT_URI, null); 6037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 6047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 60514595cbe9045755a5aa2bd28989c147c4709268cWei Huang private static final String THREAD_QUERY = 60614595cbe9045755a5aa2bd28989c147c4709268cWei Huang "SELECT _id FROM threads " + "WHERE recipient_ids=?"; 60714595cbe9045755a5aa2bd28989c147c4709268cWei Huang 6087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 6097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the thread ID for this list of 6107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * recipients IDs. If no thread exists with this ID, create 6117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * one and return it. Callers should always use 6127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Threads.getThreadId to access this information. 6137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 6147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private synchronized Cursor getThreadId(List<String> recipients) { 61514595cbe9045755a5aa2bd28989c147c4709268cWei Huang Set<Long> addressIds = getAddressIds(recipients); 61614595cbe9045755a5aa2bd28989c147c4709268cWei Huang String recipientIds = ""; 617c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang 6185926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor if (addressIds.size() == 0) { 6195926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor Log.e(LOG_TAG, "getThreadId: NO receipients specified -- NOT creating thread", 6205926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor new Exception()); 6215926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor return null; 6225926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor } else if (addressIds.size() == 1) { 6235926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor // optimize for size==1, which should be most of the cases 62414595cbe9045755a5aa2bd28989c147c4709268cWei Huang for (Long addressId : addressIds) { 62514595cbe9045755a5aa2bd28989c147c4709268cWei Huang recipientIds = Long.toString(addressId); 62614595cbe9045755a5aa2bd28989c147c4709268cWei Huang } 62714595cbe9045755a5aa2bd28989c147c4709268cWei Huang } else { 62814595cbe9045755a5aa2bd28989c147c4709268cWei Huang recipientIds = getSpaceSeparatedNumbers(getSortedSet(addressIds)); 62914595cbe9045755a5aa2bd28989c147c4709268cWei Huang } 6307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 63114595cbe9045755a5aa2bd28989c147c4709268cWei Huang if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) { 632ea59f86662471e682f880b4916ce7588803f5605Wink Saville Log.d(LOG_TAG, "getThreadId: recipientIds (selectionArgs) =" + 633ea59f86662471e682f880b4916ce7588803f5605Wink Saville /*recipientIds*/ "xxxxxxx"); 634b4ac04f7bd9d4f16ec181f368c42f89c96f83f55Tom Taylor } 63514595cbe9045755a5aa2bd28989c147c4709268cWei Huang 63614595cbe9045755a5aa2bd28989c147c4709268cWei Huang String[] selectionArgs = new String[] { recipientIds }; 6377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 63814595cbe9045755a5aa2bd28989c147c4709268cWei Huang Cursor cursor = db.rawQuery(THREAD_QUERY, selectionArgs); 6397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 6407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (cursor.getCount() == 0) { 6417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor.close(); 64214595cbe9045755a5aa2bd28989c147c4709268cWei Huang 643ea59f86662471e682f880b4916ce7588803f5605Wink Saville Log.d(LOG_TAG, "getThreadId: create new thread_id for recipients " + 644ea59f86662471e682f880b4916ce7588803f5605Wink Saville /*recipients*/ "xxxxxxxx"); 6457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project insertThread(recipientIds, recipients.size()); 64614595cbe9045755a5aa2bd28989c147c4709268cWei Huang 6477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project db = mOpenHelper.getReadableDatabase(); // In case insertThread closed it 64814595cbe9045755a5aa2bd28989c147c4709268cWei Huang cursor = db.rawQuery(THREAD_QUERY, selectionArgs); 6497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 6506a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner 65114595cbe9045755a5aa2bd28989c147c4709268cWei Huang if (cursor.getCount() > 1) { 65214595cbe9045755a5aa2bd28989c147c4709268cWei Huang Log.w(LOG_TAG, "getThreadId: why is cursorCount=" + cursor.getCount()); 65369e6ffada415d44c72d908ad9e152da51b190642Tom Taylor } 6547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 6557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return cursor; 6567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 6577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 6587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String concatSelections(String selection1, String selection2) { 6597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (TextUtils.isEmpty(selection1)) { 6607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return selection2; 6617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } else if (TextUtils.isEmpty(selection2)) { 6627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return selection1; 6637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } else { 6647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return selection1 + " AND " + selection2; 6657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 6667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 6677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 6687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 6697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * If a null projection is given, return the union of all columns 6707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * in both the MMS and SMS messages tables. Otherwise, return the 6717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * given projection. 6727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 6737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String[] handleNullMessageProjection( 6747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] projection) { 6757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return projection == null ? UNION_COLUMNS : projection; 6767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 6777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 6787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 6797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * If a null projection is given, return the set of all columns in 6807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * the threads table. Otherwise, return the given projection. 6817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 6827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String[] handleNullThreadsProjection( 6837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] projection) { 6847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return projection == null ? THREADS_COLUMNS : projection; 6857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 6867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 6877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 6887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * If a null sort order is given, return "normalized_date ASC". 6897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Otherwise, return the given sort order. 6907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 6917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String handleNullSortOrder (String sortOrder) { 6927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return sortOrder == null ? "normalized_date ASC" : sortOrder; 6937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 6947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 6957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 6967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return existing threads in the database. 6977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 6987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getSimpleConversations(String[] projection, String selection, 6997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] selectionArgs, String sortOrder) { 7007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return mOpenHelper.getReadableDatabase().query("threads", projection, 7017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, selectionArgs, null, null, " date DESC"); 7027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 7037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 7057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the thread which has draft in both MMS and SMS. 7067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 7077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Use this query: 7087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 7097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * SELECT ... 7107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM (SELECT _id, thread_id, ... 7117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM pdu 7127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * WHERE msg_box = 3 AND ... 7137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * UNION 7147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * SELECT _id, thread_id, ... 7157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM sms 7167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * WHERE type = 3 AND ... 7177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * ) 7187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * ; 7197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 7207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getDraftThread(String[] projection, String selection, 721f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String sortOrder) { 7227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] innerProjection = new String[] {BaseColumns._ID, Conversations.THREAD_ID}; 7237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder(); 7247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder(); 7257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsQueryBuilder.setTables(MmsProvider.TABLE_PDU); 7277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsQueryBuilder.setTables(SmsProvider.TABLE_SMS); 7287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery( 7307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerProjection, 7317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MMS_COLUMNS, 1, "mms", 7327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project concatSelections(selection, Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_DRAFTS), 733f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor null, null); 7347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String smsSubQuery = smsQueryBuilder.buildUnionSubQuery( 7357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerProjection, 7367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SMS_COLUMNS, 1, "sms", 7377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project concatSelections(selection, Sms.TYPE + "=" + Sms.MESSAGE_TYPE_DRAFT), 738f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor null, null); 7397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder(); 7407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionQueryBuilder.setDistinct(true); 7427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String unionQuery = unionQueryBuilder.buildUnionQuery( 7447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project new String[] { mmsSubQuery, smsSubQuery }, null, null); 7457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder outerQueryBuilder = new SQLiteQueryBuilder(); 7477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project outerQueryBuilder.setTables("(" + unionQuery + ")"); 7497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String outerQuery = outerQueryBuilder.buildQuery( 751f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor projection, null, null, null, sortOrder, null); 7527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return mOpenHelper.getReadableDatabase().rawQuery(outerQuery, EMPTY_STRING_ARRAY); 7547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 7557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 7577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the most recent message in each conversation in both MMS 7587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * and SMS. 7597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 7607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Use this query: 7617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 7627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * SELECT ... 7637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM (SELECT thread_id AS tid, date * 1000 AS normalized_date, ... 7647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM pdu 7657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * WHERE msg_box != 3 AND ... 7667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * GROUP BY thread_id 7677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * HAVING date = MAX(date) 7687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * UNION 7697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * SELECT thread_id AS tid, date AS normalized_date, ... 7707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM sms 7717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * WHERE ... 7727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * GROUP BY thread_id 7737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * HAVING date = MAX(date)) 7747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * GROUP BY tid 7757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * HAVING normalized_date = MAX(normalized_date); 7767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 7777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * The msg_box != 3 comparisons ensure that we don't include draft 7787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * messages. 7797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 7807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getConversations(String[] projection, String selection, 781f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String sortOrder) { 7827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder(); 7837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder(); 7847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsQueryBuilder.setTables(MmsProvider.TABLE_PDU); 7867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsQueryBuilder.setTables(SmsProvider.TABLE_SMS); 7877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] columns = handleNullMessageProjection(projection); 7897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] innerMmsProjection = makeProjectionWithDateAndThreadId( 7907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project UNION_COLUMNS, 1000); 7917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] innerSmsProjection = makeProjectionWithDateAndThreadId( 7927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project UNION_COLUMNS, 1); 7937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery( 7947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerMmsProjection, 7957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MMS_COLUMNS, 1, "mms", 796f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor concatSelections(selection, MMS_CONVERSATION_CONSTRAINT), 7977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "thread_id", "date = MAX(date)"); 7987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String smsSubQuery = smsQueryBuilder.buildUnionSubQuery( 7997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerSmsProjection, 8007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SMS_COLUMNS, 1, "sms", 801f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor concatSelections(selection, SMS_CONVERSATION_CONSTRAINT), 8027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "thread_id", "date = MAX(date)"); 8037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder(); 8047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionQueryBuilder.setDistinct(true); 8067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String unionQuery = unionQueryBuilder.buildUnionQuery( 8087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project new String[] { mmsSubQuery, smsSubQuery }, null, null); 8097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder outerQueryBuilder = new SQLiteQueryBuilder(); 8117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project outerQueryBuilder.setTables("(" + unionQuery + ")"); 8137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String outerQuery = outerQueryBuilder.buildQuery( 815f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor columns, null, "tid", 8167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "normalized_date = MAX(normalized_date)", sortOrder, null); 8177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return mOpenHelper.getReadableDatabase().rawQuery(outerQuery, EMPTY_STRING_ARRAY); 8197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 8207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 822f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor * Return the first locked message found in the union of MMS 823f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor * and SMS messages. 824f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor * 825f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor * Use this query: 826f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor * 827816e934a43bf705835bdb24503a85a14c4861991Tom Taylor * SELECT _id FROM pdu GROUP BY _id HAVING locked=1 UNION SELECT _id FROM sms GROUP 828816e934a43bf705835bdb24503a85a14c4861991Tom Taylor * BY _id HAVING locked=1 LIMIT 1 829f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor * 830816e934a43bf705835bdb24503a85a14c4861991Tom Taylor * We limit by 1 because we're only interested in knowing if 831f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor * there is *any* locked message, not the actual messages themselves. 832f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor */ 833f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private Cursor getFirstLockedMessage(String[] projection, String selection, 834f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String sortOrder) { 835f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder(); 836f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder(); 837f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 838f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor mmsQueryBuilder.setTables(MmsProvider.TABLE_PDU); 839f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor smsQueryBuilder.setTables(SmsProvider.TABLE_SMS); 840f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 841816e934a43bf705835bdb24503a85a14c4861991Tom Taylor String[] idColumn = new String[] { BaseColumns._ID }; 842816e934a43bf705835bdb24503a85a14c4861991Tom Taylor 843f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor // NOTE: buildUnionSubQuery *ignores* selectionArgs 844f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery( 845816e934a43bf705835bdb24503a85a14c4861991Tom Taylor MmsSms.TYPE_DISCRIMINATOR_COLUMN, idColumn, 846816e934a43bf705835bdb24503a85a14c4861991Tom Taylor null, 1, "mms", 847f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor selection, 848816e934a43bf705835bdb24503a85a14c4861991Tom Taylor BaseColumns._ID, "locked=1"); 849816e934a43bf705835bdb24503a85a14c4861991Tom Taylor 850f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor String smsSubQuery = smsQueryBuilder.buildUnionSubQuery( 851816e934a43bf705835bdb24503a85a14c4861991Tom Taylor MmsSms.TYPE_DISCRIMINATOR_COLUMN, idColumn, 852816e934a43bf705835bdb24503a85a14c4861991Tom Taylor null, 1, "sms", 853f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor selection, 854816e934a43bf705835bdb24503a85a14c4861991Tom Taylor BaseColumns._ID, "locked=1"); 855816e934a43bf705835bdb24503a85a14c4861991Tom Taylor 856f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder(); 857f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 858f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor unionQueryBuilder.setDistinct(true); 859f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 860f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor String unionQuery = unionQueryBuilder.buildUnionQuery( 861816e934a43bf705835bdb24503a85a14c4861991Tom Taylor new String[] { mmsSubQuery, smsSubQuery }, null, "1"); 862f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 863816e934a43bf705835bdb24503a85a14c4861991Tom Taylor Cursor cursor = mOpenHelper.getReadableDatabase().rawQuery(unionQuery, EMPTY_STRING_ARRAY); 864f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 865f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor if (DEBUG) { 866816e934a43bf705835bdb24503a85a14c4861991Tom Taylor Log.v("MmsSmsProvider", "getFirstLockedMessage query: " + unionQuery); 867816e934a43bf705835bdb24503a85a14c4861991Tom Taylor Log.v("MmsSmsProvider", "cursor count: " + cursor.getCount()); 868f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor } 869816e934a43bf705835bdb24503a85a14c4861991Tom Taylor return cursor; 870f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor } 871f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 872f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor /** 8737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return every message in each conversation in both MMS 8747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * and SMS. 8757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 8767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getCompleteConversations(String[] projection, 877f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String selection, String sortOrder) { 878f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String unionQuery = buildConversationQuery(projection, selection, sortOrder); 8797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return mOpenHelper.getReadableDatabase().rawQuery(unionQuery, EMPTY_STRING_ARRAY); 8817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 8827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 8847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Add normalized date and thread_id to the list of columns for an 8857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * inner projection. This is necessary so that the outer query 8867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * can have access to these columns even if the caller hasn't 8877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * requested them in the result. 8887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 8897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private String[] makeProjectionWithDateAndThreadId( 8907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] projection, int dateMultiple) { 8917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int projectionSize = projection.length; 8927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] result = new String[projectionSize + 2]; 8937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project result[0] = "thread_id AS tid"; 8957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project result[1] = "date * " + dateMultiple + " AS normalized_date"; 8967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (int i = 0; i < projectionSize; i++) { 8977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project result[i + 2] = projection[i]; 8987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 8997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return result; 9007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 9017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 9037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the union of MMS and SMS messages for this thread ID. 9047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 9057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getConversationMessages( 9067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String threadIdString, String[] projection, String selection, 907f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String sortOrder) { 9087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project try { 9097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Long.parseLong(threadIdString); 9107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } catch (NumberFormatException exception) { 9117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Log.e(LOG_TAG, "Thread ID must be a Long."); 9127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return null; 9137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 9147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSelection = concatSelections( 9167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, "thread_id = " + threadIdString); 917f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String unionQuery = buildConversationQuery(projection, finalSelection, sortOrder); 9187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return mOpenHelper.getReadableDatabase().rawQuery(unionQuery, EMPTY_STRING_ARRAY); 9207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 9217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 9237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the union of MMS and SMS messages whose recipients 9247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * included this phone number. 9257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 9267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Use this query: 9277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 9287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * SELECT ... 9297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM pdu, (SELECT _id AS address_id 9307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM addr 931c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang * WHERE (address='<phoneNumber>' OR 932c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang * PHONE_NUMBERS_EQUAL(addr.address, '<phoneNumber>', 1/0))) 9337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * AS matching_addresses 9347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * WHERE pdu._id = matching_addresses.address_id 9357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * UNION 9367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * SELECT ... 9377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM sms 938c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang * WHERE (address='<phoneNumber>' OR PHONE_NUMBERS_EQUAL(sms.address, '<phoneNumber>', 1/0)); 9397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 9407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getMessagesByPhoneNumber( 9417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String phoneNumber, String[] projection, String selection, 942f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String sortOrder) { 9437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String escapedPhoneNumber = DatabaseUtils.sqlEscapeString(phoneNumber); 9447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalMmsSelection = 9457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project concatSelections( 9467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, 9477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "pdu._id = matching_addresses.address_id"); 9487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSmsSelection = 9497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project concatSelections( 9507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, 951c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang "(address=" + escapedPhoneNumber + " OR PHONE_NUMBERS_EQUAL(address, " + 952845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa escapedPhoneNumber + 953c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang (mUseStrictPhoneNumberComparation ? ", 1))" : ", 0))")); 9547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder(); 9557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder(); 9567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsQueryBuilder.setDistinct(true); 9587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsQueryBuilder.setDistinct(true); 9597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsQueryBuilder.setTables( 9607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsProvider.TABLE_PDU + 9617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ", (SELECT _id AS address_id " + 962c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang "FROM addr WHERE (address=" + escapedPhoneNumber + 963c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang " OR PHONE_NUMBERS_EQUAL(addr.address, " + 964845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa escapedPhoneNumber + 965c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang (mUseStrictPhoneNumberComparation ? ", 1))) " : ", 0))) ") + 9667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "AS matching_addresses"); 9677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsQueryBuilder.setTables(SmsProvider.TABLE_SMS); 9687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] columns = handleNullMessageProjection(projection); 9707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery( 9717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, columns, MMS_COLUMNS, 972f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor 0, "mms", finalMmsSelection, null, null); 9737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String smsSubQuery = smsQueryBuilder.buildUnionSubQuery( 9747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, columns, SMS_COLUMNS, 975f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor 0, "sms", finalSmsSelection, null, null); 9767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder(); 9777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionQueryBuilder.setDistinct(true); 9797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String unionQuery = unionQueryBuilder.buildUnionQuery( 9817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project new String[] { mmsSubQuery, smsSubQuery }, sortOrder, null); 9827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return mOpenHelper.getReadableDatabase().rawQuery(unionQuery, EMPTY_STRING_ARRAY); 9847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 9857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 9877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the conversation of certain thread ID. 9887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 9897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getConversationById( 9907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String threadIdString, String[] projection, String selection, 9917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] selectionArgs, String sortOrder) { 9927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project try { 9937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Long.parseLong(threadIdString); 9947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } catch (NumberFormatException exception) { 9957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Log.e(LOG_TAG, "Thread ID must be a Long."); 9967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return null; 9977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 9987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String extraSelection = "_id=" + threadIdString; 10007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSelection = concatSelections(selection, extraSelection); 10017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); 10027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] columns = handleNullThreadsProjection(projection); 10037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project queryBuilder.setDistinct(true); 10057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project queryBuilder.setTables("threads"); 10067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return queryBuilder.query( 10077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mOpenHelper.getReadableDatabase(), columns, finalSelection, 10087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selectionArgs, sortOrder, null, null); 10097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 10107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String joinPduAndPendingMsgTables() { 10127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return MmsProvider.TABLE_PDU + " LEFT JOIN " + TABLE_PENDING_MSG 10137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + " ON pdu._id = pending_msgs.msg_id"; 10147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 10157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String[] createMmsProjection(String[] old) { 10177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] newProjection = new String[old.length]; 10187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (int i = 0; i < old.length; i++) { 10197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (old[i].equals(BaseColumns._ID)) { 10207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project newProjection[i] = "pdu._id"; 10217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } else { 10227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project newProjection[i] = old[i]; 10237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 10247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 10257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return newProjection; 10267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 10277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getUndeliveredMessages( 10297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] projection, String selection, String[] selectionArgs, 10307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String sortOrder) { 10317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] mmsProjection = createMmsProjection(projection); 10327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder(); 10347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder(); 10357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsQueryBuilder.setTables(joinPduAndPendingMsgTables()); 10377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsQueryBuilder.setTables(SmsProvider.TABLE_SMS); 10387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalMmsSelection = concatSelections( 10407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, Mms.MESSAGE_BOX + " = " + Mms.MESSAGE_BOX_OUTBOX); 10417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSmsSelection = concatSelections( 10427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, "(" + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_OUTBOX 10437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + " OR " + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_FAILED 10447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + " OR " + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_QUEUED + ")"); 10457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] smsColumns = handleNullMessageProjection(projection); 10477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] mmsColumns = handleNullMessageProjection(mmsProjection); 10487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] innerMmsProjection = makeProjectionWithDateAndThreadId( 10497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsColumns, 1000); 10507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] innerSmsProjection = makeProjectionWithDateAndThreadId( 10517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsColumns, 1); 10527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Set<String> columnsPresentInTable = new HashSet<String>(MMS_COLUMNS); 10547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project columnsPresentInTable.add("pdu._id"); 10557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project columnsPresentInTable.add(PendingMessages.ERROR_TYPE); 10567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery( 10577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerMmsProjection, 1058f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor columnsPresentInTable, 1, "mms", finalMmsSelection, 10597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project null, null); 10607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String smsSubQuery = smsQueryBuilder.buildUnionSubQuery( 10617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerSmsProjection, 1062f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor SMS_COLUMNS, 1, "sms", finalSmsSelection, 10637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project null, null); 10647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder(); 10657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionQueryBuilder.setDistinct(true); 10677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String unionQuery = unionQueryBuilder.buildUnionQuery( 10697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project new String[] { smsSubQuery, mmsSubQuery }, null, null); 10707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder outerQueryBuilder = new SQLiteQueryBuilder(); 10727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project outerQueryBuilder.setTables("(" + unionQuery + ")"); 10747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String outerQuery = outerQueryBuilder.buildQuery( 1076f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor smsColumns, null, null, null, sortOrder, null); 10777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return mOpenHelper.getReadableDatabase().rawQuery(outerQuery, EMPTY_STRING_ARRAY); 10797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 10807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 10827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Add normalized date to the list of columns for an inner 10837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * projection. 10847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 10857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String[] makeProjectionWithNormalizedDate( 10867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] projection, int dateMultiple) { 10877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int projectionSize = projection.length; 10887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] result = new String[projectionSize + 1]; 10897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project result[0] = "date * " + dateMultiple + " AS normalized_date"; 10917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project System.arraycopy(projection, 0, result, 1, projectionSize); 10927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return result; 10937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 10947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String buildConversationQuery(String[] projection, 1096f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String selection, String sortOrder) { 10977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] mmsProjection = createMmsProjection(projection); 10987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder(); 11007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder(); 11017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsQueryBuilder.setDistinct(true); 11037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsQueryBuilder.setDistinct(true); 11047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsQueryBuilder.setTables(joinPduAndPendingMsgTables()); 11057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsQueryBuilder.setTables(SmsProvider.TABLE_SMS); 11067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] smsColumns = handleNullMessageProjection(projection); 11087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] mmsColumns = handleNullMessageProjection(mmsProjection); 11097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] innerMmsProjection = makeProjectionWithNormalizedDate(mmsColumns, 1000); 11107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] innerSmsProjection = makeProjectionWithNormalizedDate(smsColumns, 1); 11117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Set<String> columnsPresentInTable = new HashSet<String>(MMS_COLUMNS); 11137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project columnsPresentInTable.add("pdu._id"); 11147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project columnsPresentInTable.add(PendingMessages.ERROR_TYPE); 11157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String mmsSelection = concatSelections(selection, 11177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.MESSAGE_BOX + " != " + Mms.MESSAGE_BOX_DRAFTS); 11187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery( 11197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerMmsProjection, 11207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project columnsPresentInTable, 0, "mms", 11217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project concatSelections(mmsSelection, MMS_CONVERSATION_CONSTRAINT), 1122f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor null, null); 11237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String smsSubQuery = smsQueryBuilder.buildUnionSubQuery( 11247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerSmsProjection, SMS_COLUMNS, 11257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 0, "sms", concatSelections(selection, SMS_CONVERSATION_CONSTRAINT), 1126f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor null, null); 11277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder(); 11287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionQueryBuilder.setDistinct(true); 11307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String unionQuery = unionQueryBuilder.buildUnionQuery( 11327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project new String[] { smsSubQuery, mmsSubQuery }, 11337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project handleNullSortOrder(sortOrder), null); 11347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder outerQueryBuilder = new SQLiteQueryBuilder(); 11367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project outerQueryBuilder.setTables("(" + unionQuery + ")"); 11387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return outerQueryBuilder.buildQuery( 1140f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor smsColumns, null, null, null, sortOrder, null); 11417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 11427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project @Override 11447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project public String getType(Uri uri) { 11457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return VND_ANDROID_DIR_MMS_SMS; 11467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 11477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project @Override 11497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project public int delete(Uri uri, String selection, 11507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] selectionArgs) { 11517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 11527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Context context = getContext(); 11537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int affectedRows = 0; 1154f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner 11557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project switch(URI_MATCHER.match(uri)) { 11567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CONVERSATIONS_MESSAGES: 11577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project long threadId; 11587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project try { 11597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project threadId = Long.parseLong(uri.getLastPathSegment()); 11607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } catch (NumberFormatException e) { 11617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Log.e(LOG_TAG, "Thread ID must be a long."); 11627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 11637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 11647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project affectedRows = deleteConversation(uri, selection, selectionArgs); 11657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSmsDatabaseHelper.updateThread(db, threadId); 11667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 11677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CONVERSATIONS: 11687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project affectedRows = MmsProvider.deleteMessages(context, db, 11697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, selectionArgs, uri) 11707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + db.delete("sms", selection, selectionArgs); 117187bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor // Intentionally don't pass the selection variable to updateAllThreads. 117287bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor // When we pass in "locked=0" there, the thread will get excluded from 117387bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor // the selection and not get updated. 117487bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor MmsSmsDatabaseHelper.updateAllThreads(db, null, null); 11757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 11767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_OBSOLETE_THREADS: 11777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project affectedRows = db.delete("threads", 11787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "_id NOT IN (SELECT DISTINCT thread_id FROM sms " + 11797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "UNION SELECT DISTINCT thread_id FROM pdu)", null); 11807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 11817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project default: 1182b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor throw new UnsupportedOperationException(NO_DELETES_INSERTS_OR_UPDATES + uri); 11837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 11847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (affectedRows > 0) { 11867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project context.getContentResolver().notifyChange(MmsSms.CONTENT_URI, null); 11877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 11887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return affectedRows; 11897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 11907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 11927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Delete the conversation with the given thread ID. 11937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 11947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private int deleteConversation(Uri uri, String selection, String[] selectionArgs) { 11957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String threadId = uri.getLastPathSegment(); 11967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 11987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSelection = concatSelections(selection, "thread_id = " + threadId); 11997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return MmsProvider.deleteMessages(getContext(), db, finalSelection, 12007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selectionArgs, uri) 12017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + db.delete("sms", finalSelection, selectionArgs); 12027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project @Override 12057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project public Uri insert(Uri uri, ContentValues values) { 1206b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor if (URI_MATCHER.match(uri) == URI_PENDING_MSG) { 1207b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 1208b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor long rowId = db.insert(TABLE_PENDING_MSG, null, values); 1209b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor return Uri.parse(uri + "/" + rowId); 1210b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor } 1211b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor throw new UnsupportedOperationException(NO_DELETES_INSERTS_OR_UPDATES + uri); 12127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project @Override 12157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project public int update(Uri uri, ContentValues values, 12167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String selection, String[] selectionArgs) { 12177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 12187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int affectedRows = 0; 12197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project switch(URI_MATCHER.match(uri)) { 12207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CONVERSATIONS_MESSAGES: 12217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String threadIdString = uri.getPathSegments().get(1); 12227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project affectedRows = updateConversation(threadIdString, values, 12237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, selectionArgs); 12247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 12251ecf192c60625c5227336430ee36705c13ae06e2Wei Huang 12267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_PENDING_MSG: 12277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project affectedRows = db.update(TABLE_PENDING_MSG, values, selection, null); 12287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 12291ecf192c60625c5227336430ee36705c13ae06e2Wei Huang 12301ecf192c60625c5227336430ee36705c13ae06e2Wei Huang case URI_CANONICAL_ADDRESS: { 12311ecf192c60625c5227336430ee36705c13ae06e2Wei Huang String extraSelection = "_id=" + uri.getPathSegments().get(1); 12321ecf192c60625c5227336430ee36705c13ae06e2Wei Huang String finalSelection = TextUtils.isEmpty(selection) 12331ecf192c60625c5227336430ee36705c13ae06e2Wei Huang ? extraSelection : extraSelection + " AND " + selection; 12341ecf192c60625c5227336430ee36705c13ae06e2Wei Huang 12351ecf192c60625c5227336430ee36705c13ae06e2Wei Huang affectedRows = db.update(TABLE_CANONICAL_ADDRESSES, values, finalSelection, null); 12361ecf192c60625c5227336430ee36705c13ae06e2Wei Huang break; 12371ecf192c60625c5227336430ee36705c13ae06e2Wei Huang } 12381ecf192c60625c5227336430ee36705c13ae06e2Wei Huang 12397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project default: 12407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project throw new UnsupportedOperationException( 1241b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor NO_DELETES_INSERTS_OR_UPDATES + uri); 12427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (affectedRows > 0) { 12457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project getContext().getContentResolver().notifyChange( 12467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.CONTENT_URI, null); 12477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return affectedRows; 12497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private int updateConversation( 12527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String threadIdString, ContentValues values, String selection, 12537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] selectionArgs) { 12547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project try { 12557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Long.parseLong(threadIdString); 12567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } catch (NumberFormatException exception) { 12577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Log.e(LOG_TAG, "Thread ID must be a Long."); 12587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return 0; 12597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 12627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSelection = concatSelections(selection, "thread_id=" + threadIdString); 12637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return db.update(MmsProvider.TABLE_PDU, values, finalSelection, selectionArgs) 12647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + db.update("sms", values, finalSelection, selectionArgs); 12657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 12687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Construct Sets of Strings containing exactly the columns 12697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * present in each table. We will use this when constructing 12707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * UNION queries across the MMS and SMS tables. 12717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 12727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static void initializeColumnSets() { 12737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int commonColumnCount = MMS_SMS_COLUMNS.length; 12747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int mmsOnlyColumnCount = MMS_ONLY_COLUMNS.length; 12757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int smsOnlyColumnCount = SMS_ONLY_COLUMNS.length; 12767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Set<String> unionColumns = new HashSet<String>(); 12777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (int i = 0; i < commonColumnCount; i++) { 12797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MMS_COLUMNS.add(MMS_SMS_COLUMNS[i]); 12807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SMS_COLUMNS.add(MMS_SMS_COLUMNS[i]); 12817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionColumns.add(MMS_SMS_COLUMNS[i]); 12827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (int i = 0; i < mmsOnlyColumnCount; i++) { 12847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MMS_COLUMNS.add(MMS_ONLY_COLUMNS[i]); 12857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionColumns.add(MMS_ONLY_COLUMNS[i]); 12867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (int i = 0; i < smsOnlyColumnCount; i++) { 12887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SMS_COLUMNS.add(SMS_ONLY_COLUMNS[i]); 12897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionColumns.add(SMS_ONLY_COLUMNS[i]); 12907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int i = 0; 12937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (String columnName : unionColumns) { 12947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project UNION_COLUMNS[i++] = columnName; 12957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project} 1298