MmsSmsProvider.java revision e07acb9f6a77d9753900224a4caefd5a8aec97ee
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 19f27792fb80c6f533a250ec75867c9f2351ff9f04Dianne Hackbornimport android.app.AppOpsManager; 207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.content.ContentProvider; 217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.content.ContentValues; 227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.content.Context; 237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.content.UriMatcher; 247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.Cursor; 257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.DatabaseUtils; 267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase; 277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.sqlite.SQLiteOpenHelper; 287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.sqlite.SQLiteQueryBuilder; 297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.net.Uri; 30e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wenimport android.os.Binder; 3143f9fb234aabe569b342af78bdaf85effbd85f10Amith Yamasaniimport android.os.UserHandle; 327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.BaseColumns; 337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.CanonicalAddressesColumns; 347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Mms; 357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.MmsSms; 36e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wenimport android.provider.Telephony.MmsSms.PendingMessages; 377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Sms; 38e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wenimport android.provider.Telephony.Sms.Conversations; 397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Threads; 407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.ThreadsColumns; 417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.text.TextUtils; 427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.util.Log; 437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 44b1bae65bf18dc22762cf7b8210fdad836b3e4ee5Tom Taylorimport com.google.android.mms.pdu.PduHeaders; 457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 46e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wenimport java.util.Arrays; 47e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wenimport java.util.HashSet; 48e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wenimport java.util.List; 49e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wenimport java.util.Set; 50e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen 517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project/** 527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * This class provides the ability to query the MMS and SMS databases 537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * at the same time, mixing messages from both in a single thread 547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * (A.K.A. conversation). 557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * A virtual column, MmsSms.TYPE_DISCRIMINATOR_COLUMN, may be 577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * requested in the projection for a query. Its value is either "mms" 587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * or "sms", depending on whether the message represented by the row 597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * is an MMS message or an SMS message, respectively. 607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * This class also provides the ability to find out what addresses 627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * participated in a particular thread. It doesn't support updates 637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * for either of these. 647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * This class provides a way to allocate and retrieve thread IDs. 667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * This is done atomically through a query. There is no insert URI 677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * for this. 687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Finally, this class provides a way to delete or update all messages 707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * in a thread. 717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectpublic class MmsSmsProvider extends ContentProvider { 737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final UriMatcher URI_MATCHER = 747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project new UriMatcher(UriMatcher.NO_MATCH); 757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String LOG_TAG = "MmsSmsProvider"; 76816e934a43bf705835bdb24503a85a14c4861991Tom Taylor private static final boolean DEBUG = false; 777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String NO_DELETES_INSERTS_OR_UPDATES = 797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "MmsSmsProvider does not support deletes, inserts, or updates for this URI."; 80f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_CONVERSATIONS = 0; 81f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_CONVERSATIONS_MESSAGES = 1; 82f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_CONVERSATIONS_RECIPIENTS = 2; 83f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_MESSAGES_BY_PHONE = 3; 84f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_THREAD_ID = 4; 85f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_CANONICAL_ADDRESS = 5; 86f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_PENDING_MSG = 6; 87f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_COMPLETE_CONVERSATIONS = 7; 88f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_UNDELIVERED_MSG = 8; 89f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_CONVERSATIONS_SUBJECT = 9; 90f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_NOTIFICATIONS = 10; 91f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_OBSOLETE_THREADS = 11; 92f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_DRAFT = 12; 93f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_CANONICAL_ADDRESSES = 13; 94f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private static final int URI_SEARCH = 14; 958e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner private static final int URI_SEARCH_SUGGEST = 15; 968e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner private static final int URI_FIRST_LOCKED_MESSAGE_ALL = 16; 978e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner private static final int URI_FIRST_LOCKED_MESSAGE_BY_THREAD_ID = 17; 986a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner private static final int URI_MESSAGE_ID_TO_THREAD = 18; 997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 1017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * the name of the table that is used to store the queue of 1027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * messages(both MMS and SMS) to be sent/downloaded. 1037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 1047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project public static final String TABLE_PENDING_MSG = "pending_msgs"; 1057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1061ecf192c60625c5227336430ee36705c13ae06e2Wei Huang /** 1071ecf192c60625c5227336430ee36705c13ae06e2Wei Huang * the name of the table that is used to store the canonical addresses for both SMS and MMS. 1081ecf192c60625c5227336430ee36705c13ae06e2Wei Huang */ 1091ecf192c60625c5227336430ee36705c13ae06e2Wei Huang private static final String TABLE_CANONICAL_ADDRESSES = "canonical_addresses"; 1101ecf192c60625c5227336430ee36705c13ae06e2Wei Huang 11115156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor /** 11215156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor * the name of the table that is used to store the conversation threads. 11315156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor */ 11415156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor static final String TABLE_THREADS = "threads"; 11515156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor 1167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These constants are used to construct union queries across the 1177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // MMS and SMS base tables. 1187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These are the columns that appear in both the MMS ("pdu") and 1207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // SMS ("sms") message tables. 1217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String[] MMS_SMS_COLUMNS = 122cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen { BaseColumns._ID, Mms.DATE, Mms.DATE_SENT, Mms.READ, Mms.THREAD_ID, Mms.LOCKED, 123cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen Mms.SUB_ID }; 1247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These are the columns that appear only in the MMS message 1267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // table. 1277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String[] MMS_ONLY_COLUMNS = { 1287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.CONTENT_CLASS, Mms.CONTENT_LOCATION, Mms.CONTENT_TYPE, 1297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.DELIVERY_REPORT, Mms.EXPIRY, Mms.MESSAGE_CLASS, Mms.MESSAGE_ID, 1307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.MESSAGE_SIZE, Mms.MESSAGE_TYPE, Mms.MESSAGE_BOX, Mms.PRIORITY, 1317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.READ_STATUS, Mms.RESPONSE_STATUS, Mms.RESPONSE_TEXT, 1327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.RETRIEVE_STATUS, Mms.RETRIEVE_TEXT_CHARSET, Mms.REPORT_ALLOWED, 1337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.READ_REPORT, Mms.STATUS, Mms.SUBJECT, Mms.SUBJECT_CHARSET, 134f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor Mms.TRANSACTION_ID, Mms.MMS_VERSION, Mms.TEXT_ONLY }; 1357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These are the columns that appear only in the SMS message 1377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // table. 1387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String[] SMS_ONLY_COLUMNS = 1397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project { "address", "body", "person", "reply_path_present", 140ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor "service_center", "status", "subject", "type", "error_code" }; 1417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These are all the columns that appear in the "threads" table. 1437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String[] THREADS_COLUMNS = { 1447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project BaseColumns._ID, 1457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ThreadsColumns.DATE, 1467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ThreadsColumns.RECIPIENT_IDS, 1477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ThreadsColumns.MESSAGE_COUNT 1487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project }; 1497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1501ecf192c60625c5227336430ee36705c13ae06e2Wei Huang private static final String[] CANONICAL_ADDRESSES_COLUMNS_1 = 1511ecf192c60625c5227336430ee36705c13ae06e2Wei Huang new String[] { CanonicalAddressesColumns.ADDRESS }; 1521ecf192c60625c5227336430ee36705c13ae06e2Wei Huang 1531ecf192c60625c5227336430ee36705c13ae06e2Wei Huang private static final String[] CANONICAL_ADDRESSES_COLUMNS_2 = 1541ecf192c60625c5227336430ee36705c13ae06e2Wei Huang new String[] { CanonicalAddressesColumns._ID, 1551ecf192c60625c5227336430ee36705c13ae06e2Wei Huang CanonicalAddressesColumns.ADDRESS }; 1561ecf192c60625c5227336430ee36705c13ae06e2Wei Huang 1577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These are all the columns that appear in the MMS and SMS 1587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // message tables. 1597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String[] UNION_COLUMNS = 1607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project new String[MMS_SMS_COLUMNS.length 1617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + MMS_ONLY_COLUMNS.length 1627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + SMS_ONLY_COLUMNS.length]; 1637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These are all the columns that appear in the MMS table. 1657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final Set<String> MMS_COLUMNS = new HashSet<String>(); 1667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // These are all the columns that appear in the SMS table. 1687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final Set<String> SMS_COLUMNS = new HashSet<String>(); 1697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String VND_ANDROID_DIR_MMS_SMS = 1717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "vnd.android-dir/mms-sms"; 1727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String[] ID_PROJECTION = { BaseColumns._ID }; 1747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String[] EMPTY_STRING_ARRAY = new String[0]; 1767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1773e1cba826743423642635cc7b03abe292470f4c4Tom Taylor private static final String[] SEARCH_STRING = new String[1]; 1783e1cba826743423642635cc7b03abe292470f4c4Tom Taylor private static final String SEARCH_QUERY = "SELECT snippet(words, '', ' ', '', 1, 1) as " + 1793e1cba826743423642635cc7b03abe292470f4c4Tom Taylor "snippet FROM words WHERE index_text MATCH ? ORDER BY snippet LIMIT 50;"; 1803e1cba826743423642635cc7b03abe292470f4c4Tom Taylor 1817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String SMS_CONVERSATION_CONSTRAINT = "(" + 1827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Sms.TYPE + " != " + Sms.MESSAGE_TYPE_DRAFT + ")"; 1837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 1847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String MMS_CONVERSATION_CONSTRAINT = "(" + 1857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.MESSAGE_BOX + " != " + Mms.MESSAGE_BOX_DRAFTS + " AND (" + 1867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.MESSAGE_TYPE + " = " + PduHeaders.MESSAGE_TYPE_SEND_REQ + " OR " + 1877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.MESSAGE_TYPE + " = " + PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF + " OR " + 1887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.MESSAGE_TYPE + " = " + PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND + "))"; 1897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 19001c75ba95b875674a83128defc6b267e522db346Chen Mike // Search on the words table but return the rows from the corresponding sms table 19101c75ba95b875674a83128defc6b267e522db346Chen Mike private static final String SMS_QUERY = 192ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert "SELECT sms._id AS _id,thread_id,address,body,date,date_sent,index_text,words._id " + 19376e665b3042222aa6d65eccb0f84618f387837aaMark Wagner "FROM sms,words WHERE (index_text MATCH ? " + 19401c75ba95b875674a83128defc6b267e522db346Chen Mike "AND sms._id=words.source_id AND words.table_to_use=1)"; 19501c75ba95b875674a83128defc6b267e522db346Chen Mike 19601c75ba95b875674a83128defc6b267e522db346Chen Mike // Search on the words table but return the rows from the corresponding parts table 19701c75ba95b875674a83128defc6b267e522db346Chen Mike private static final String MMS_QUERY = 19801c75ba95b875674a83128defc6b267e522db346Chen Mike "SELECT pdu._id,thread_id,addr.address,part.text " + 199ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert "AS body,pdu.date,pdu.date_sent,index_text,words._id " + 20001c75ba95b875674a83128defc6b267e522db346Chen Mike "FROM pdu,part,addr,words WHERE ((part.mid=pdu._id) AND " + 20101c75ba95b875674a83128defc6b267e522db346Chen Mike "(addr.msg_id=pdu._id) AND " + 20201c75ba95b875674a83128defc6b267e522db346Chen Mike "(addr.type=" + PduHeaders.TO + ") AND " + 20301c75ba95b875674a83128defc6b267e522db346Chen Mike "(part.ct='text/plain') AND " + 20476e665b3042222aa6d65eccb0f84618f387837aaMark Wagner "(index_text MATCH ?) AND " + 20501c75ba95b875674a83128defc6b267e522db346Chen Mike "(part._id = words.source_id) AND " + 20601c75ba95b875674a83128defc6b267e522db346Chen Mike "(words.table_to_use=2))"; 20701c75ba95b875674a83128defc6b267e522db346Chen Mike 20801c75ba95b875674a83128defc6b267e522db346Chen Mike // This code queries the sms and mms tables and returns a unified result set 20901c75ba95b875674a83128defc6b267e522db346Chen Mike // of text matches. We query the sms table which is pretty simple. We also 2109081ab6bd08fa66bac28d65f0ce4fca14b6954a6Jean-Baptiste Queru // query the pdu, part and addr table to get the mms result. Notet we're 21101c75ba95b875674a83128defc6b267e522db346Chen Mike // using a UNION so we have to have the same number of result columns from 21201c75ba95b875674a83128defc6b267e522db346Chen Mike // both queries. 21301c75ba95b875674a83128defc6b267e522db346Chen Mike private static final String SMS_MMS_QUERY = 21401c75ba95b875674a83128defc6b267e522db346Chen Mike SMS_QUERY + " UNION " + MMS_QUERY + 21501c75ba95b875674a83128defc6b267e522db346Chen Mike " GROUP BY thread_id ORDER BY thread_id ASC, date DESC"; 21601c75ba95b875674a83128defc6b267e522db346Chen Mike 2177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static final String AUTHORITY = "mms-sms"; 2187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project static { 2207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "conversations", URI_CONVERSATIONS); 2217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "complete-conversations", URI_COMPLETE_CONVERSATIONS); 2227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // In these patterns, "#" is the thread ID. 2247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI( 2257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project AUTHORITY, "conversations/#", URI_CONVERSATIONS_MESSAGES); 2267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI( 2277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project AUTHORITY, "conversations/#/recipients", 2287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_CONVERSATIONS_RECIPIENTS); 2297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI( 2317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project AUTHORITY, "conversations/#/subject", 2327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_CONVERSATIONS_SUBJECT); 2337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // URI for deleting obsolete threads. 2357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "conversations/obsolete", URI_OBSOLETE_THREADS); 2367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI( 2387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project AUTHORITY, "messages/byphone/*", 2397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MESSAGES_BY_PHONE); 2407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // In this pattern, two query parameter names are expected: 2427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // "subject" and "recipient." Multiple "recipient" parameters 2437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // may be present. 2447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "threadID", URI_THREAD_ID); 2457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // Use this pattern to query the canonical address by given ID. 2477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "canonical-address/#", URI_CANONICAL_ADDRESS); 2487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 24937e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick // Use this pattern to query all canonical addresses. 25037e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick URI_MATCHER.addURI(AUTHORITY, "canonical-addresses", URI_CANONICAL_ADDRESSES); 251f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner 25266d373c4797c53207e8f1ea97f3dc5541f390152Mark Wagner URI_MATCHER.addURI(AUTHORITY, "search", URI_SEARCH); 2538e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner URI_MATCHER.addURI(AUTHORITY, "searchSuggest", URI_SEARCH_SUGGEST); 25437e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick 2557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // In this pattern, two query parameters may be supplied: 2567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // "protocol" and "message." For example: 2577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // content://mms-sms/pending? 2587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // -> Return all pending messages; 2597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // content://mms-sms/pending?protocol=sms 2607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // -> Only return pending SMs; 2617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // content://mms-sms/pending?protocol=mms&message=1 2627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // -> Return the the pending MM which ID equals '1'. 2637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // 2647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "pending", URI_PENDING_MSG); 2657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // Use this pattern to get a list of undelivered messages. 2677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "undelivered", URI_UNDELIVERED_MSG); 2687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // Use this pattern to see what delivery status reports (for 2707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project // both MMS and SMS) have not been delivered to the user. 2717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "notifications", URI_NOTIFICATIONS); 2727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project URI_MATCHER.addURI(AUTHORITY, "draft", URI_DRAFT); 274f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 275f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor URI_MATCHER.addURI(AUTHORITY, "locked", URI_FIRST_LOCKED_MESSAGE_ALL); 276f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 277f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor URI_MATCHER.addURI(AUTHORITY, "locked/#", URI_FIRST_LOCKED_MESSAGE_BY_THREAD_ID); 278f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 2796a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner URI_MATCHER.addURI(AUTHORITY, "messageIdToThread", URI_MESSAGE_ID_TO_THREAD); 2807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project initializeColumnSets(); 2817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 2827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private SQLiteOpenHelper mOpenHelper; 2847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 285845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa private boolean mUseStrictPhoneNumberComparation; 286845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa 2877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project @Override 2887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project public boolean onCreate() { 289b2ce2d37bc6efc0c37d8cee925d3ad65a01ea4bfYe Wen setAppOps(AppOpsManager.OP_READ_SMS, AppOpsManager.OP_WRITE_SMS); 290b2ce2d37bc6efc0c37d8cee925d3ad65a01ea4bfYe Wen mOpenHelper = MmsSmsDatabaseHelper.getInstance(getContext()); 291845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa mUseStrictPhoneNumberComparation = 292845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa getContext().getResources().getBoolean( 293845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa com.android.internal.R.bool.config_use_strict_phone_number_comparation); 2947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return true; 2957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 2967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 2977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project @Override 2987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project public Cursor query(Uri uri, String[] projection, 2997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String selection, String[] selectionArgs, String sortOrder) { 3007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 3017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Cursor cursor = null; 3027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project switch(URI_MATCHER.match(uri)) { 3037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_COMPLETE_CONVERSATIONS: 304f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor cursor = getCompleteConversations(projection, selection, sortOrder); 3057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CONVERSATIONS: 3077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String simple = uri.getQueryParameter("simple"); 3087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if ((simple != null) && simple.equals("true")) { 3097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String threadType = uri.getQueryParameter("thread_type"); 3107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (!TextUtils.isEmpty(threadType)) { 3117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection = concatSelections( 3127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, Threads.TYPE + "=" + threadType); 3137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 3147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = getSimpleConversations( 3157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project projection, selection, selectionArgs, sortOrder); 3167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } else { 3177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = getConversations( 318f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor projection, selection, sortOrder); 3197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 3207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CONVERSATIONS_MESSAGES: 322f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor cursor = getConversationMessages(uri.getPathSegments().get(1), projection, 323f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor selection, sortOrder); 3247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CONVERSATIONS_RECIPIENTS: 3267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = getConversationById( 3277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project uri.getPathSegments().get(1), projection, selection, 3287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selectionArgs, sortOrder); 3297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CONVERSATIONS_SUBJECT: 3317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = getConversationById( 3327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project uri.getPathSegments().get(1), projection, selection, 3337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selectionArgs, sortOrder); 3347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_MESSAGES_BY_PHONE: 3367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = getMessagesByPhoneNumber( 337f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor uri.getPathSegments().get(2), projection, selection, sortOrder); 3387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_THREAD_ID: 3407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project List<String> recipients = uri.getQueryParameters("recipient"); 3417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 3427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = getThreadId(recipients); 3437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CANONICAL_ADDRESS: { 3457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String extraSelection = "_id=" + uri.getPathSegments().get(1); 3467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSelection = TextUtils.isEmpty(selection) 3477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ? extraSelection : extraSelection + " AND " + selection; 3481ecf192c60625c5227336430ee36705c13ae06e2Wei Huang cursor = db.query(TABLE_CANONICAL_ADDRESSES, 3491ecf192c60625c5227336430ee36705c13ae06e2Wei Huang CANONICAL_ADDRESSES_COLUMNS_1, 3501ecf192c60625c5227336430ee36705c13ae06e2Wei Huang finalSelection, 3511ecf192c60625c5227336430ee36705c13ae06e2Wei Huang selectionArgs, 3521ecf192c60625c5227336430ee36705c13ae06e2Wei Huang null, null, 3531ecf192c60625c5227336430ee36705c13ae06e2Wei Huang sortOrder); 3547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 3557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 35637e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick case URI_CANONICAL_ADDRESSES: 3571ecf192c60625c5227336430ee36705c13ae06e2Wei Huang cursor = db.query(TABLE_CANONICAL_ADDRESSES, 3581ecf192c60625c5227336430ee36705c13ae06e2Wei Huang CANONICAL_ADDRESSES_COLUMNS_2, 3591ecf192c60625c5227336430ee36705c13ae06e2Wei Huang selection, 3601ecf192c60625c5227336430ee36705c13ae06e2Wei Huang selectionArgs, 3611ecf192c60625c5227336430ee36705c13ae06e2Wei Huang null, null, 3621ecf192c60625c5227336430ee36705c13ae06e2Wei Huang sortOrder); 36337e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick break; 3648e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner case URI_SEARCH_SUGGEST: { 3653e1cba826743423642635cc7b03abe292470f4c4Tom Taylor SEARCH_STRING[0] = uri.getQueryParameter("pattern") + '*' ; 3669e1fd44679b2de6df6af2c1e8b6bf191e799f4a9Mark Wagner 3679e1fd44679b2de6df6af2c1e8b6bf191e799f4a9Mark Wagner // find the words which match the pattern using the snippet function. The 3689e1fd44679b2de6df6af2c1e8b6bf191e799f4a9Mark Wagner // snippet function parameters mainly describe how to format the result. 3699e1fd44679b2de6df6af2c1e8b6bf191e799f4a9Mark Wagner // See http://www.sqlite.org/fts3.html#section_4_2 for details. 3708e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner if ( sortOrder != null 3718e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner || selection != null 3728e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner || selectionArgs != null 3738e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner || projection != null) { 3748e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner throw new IllegalArgumentException( 3758e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner "do not specify sortOrder, selection, selectionArgs, or projection" + 3768e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner "with this query"); 3778e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner } 3788e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner 3793e1cba826743423642635cc7b03abe292470f4c4Tom Taylor cursor = db.rawQuery(SEARCH_QUERY, SEARCH_STRING); 3808e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner break; 3818e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner } 3826a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner case URI_MESSAGE_ID_TO_THREAD: { 3836a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner // Given a message ID and an indicator for SMS vs. MMS return 3846a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner // the thread id of the corresponding thread. 3856a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner try { 3866a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner long id = Long.parseLong(uri.getQueryParameter("row_id")); 3876a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner switch (Integer.parseInt(uri.getQueryParameter("table_to_use"))) { 3886a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner case 1: // sms 3896a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner cursor = db.query( 3906a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner "sms", 3916a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner new String[] { "thread_id" }, 3926a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner "_id=?", 3936a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner new String[] { String.valueOf(id) }, 3946a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner null, 3956a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner null, 3966a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner null); 3976a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner break; 3986a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner case 2: // mms 3996a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner String mmsQuery = 4006a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner "SELECT thread_id FROM pdu,part WHERE ((part.mid=pdu._id) AND " + 4016a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner "(part._id=?))"; 4026a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner cursor = db.rawQuery(mmsQuery, new String[] { String.valueOf(id) }); 4036a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner break; 4046a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner } 4056a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner } catch (NumberFormatException ex) { 4066a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner // ignore... return empty cursor 4076a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner } 4086a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner break; 4096a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner } 4108e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner case URI_SEARCH: { 41187bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor if ( sortOrder != null 41287bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor || selection != null 41387bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor || selectionArgs != null 414f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner || projection != null) { 415f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner throw new IllegalArgumentException( 416f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner "do not specify sortOrder, selection, selectionArgs, or projection" + 417f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner "with this query"); 41866d373c4797c53207e8f1ea97f3dc5541f390152Mark Wagner } 41987bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor 4208e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner String searchString = uri.getQueryParameter("pattern") + "*"; 4218e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner 4228e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner try { 42301c75ba95b875674a83128defc6b267e522db346Chen Mike cursor = db.rawQuery(SMS_MMS_QUERY, new String[] { searchString, searchString }); 4248e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner } catch (Exception ex) { 4258e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner Log.e(LOG_TAG, "got exception: " + ex.toString()); 4268e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner } 42766d373c4797c53207e8f1ea97f3dc5541f390152Mark Wagner break; 4288e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner } 4297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_PENDING_MSG: { 4307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String protoName = uri.getQueryParameter("protocol"); 4317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String msgId = uri.getQueryParameter("message"); 4327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int proto = TextUtils.isEmpty(protoName) ? -1 4337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project : (protoName.equals("sms") ? MmsSms.SMS_PROTO : MmsSms.MMS_PROTO); 4347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 4357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String extraSelection = (proto != -1) ? 4367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project (PendingMessages.PROTO_TYPE + "=" + proto) : " 0=0 "; 4377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (!TextUtils.isEmpty(msgId)) { 4387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project extraSelection += " AND " + PendingMessages.MSG_ID + "=" + msgId; 4397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 4407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 4417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSelection = TextUtils.isEmpty(selection) 4427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ? extraSelection : ("(" + extraSelection + ") AND " + selection); 4437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalOrder = TextUtils.isEmpty(sortOrder) 4447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ? PendingMessages.DUE_TIME : sortOrder; 4457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = db.query(TABLE_PENDING_MSG, null, 4467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project finalSelection, selectionArgs, null, null, finalOrder); 4477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 4487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 4497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_UNDELIVERED_MSG: { 4507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = getUndeliveredMessages(projection, selection, 4517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selectionArgs, sortOrder); 4527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 4537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 4547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_DRAFT: { 455f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor cursor = getDraftThread(projection, selection, sortOrder); 4567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 4577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 458f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor case URI_FIRST_LOCKED_MESSAGE_BY_THREAD_ID: { 459f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor long threadId; 460f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor try { 461f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor threadId = Long.parseLong(uri.getLastPathSegment()); 462f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor } catch (NumberFormatException e) { 463f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor Log.e(LOG_TAG, "Thread ID must be a long."); 464f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor break; 465f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor } 466f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor cursor = getFirstLockedMessage(projection, "thread_id=" + Long.toString(threadId), 467f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor sortOrder); 468f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor break; 469f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor } 470f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor case URI_FIRST_LOCKED_MESSAGE_ALL: { 471f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor cursor = getFirstLockedMessage(projection, selection, sortOrder); 472f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor break; 473f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor } 4747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project default: 4757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project throw new IllegalStateException("Unrecognized URI:" + uri); 4767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 4777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 4785926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor if (cursor != null) { 4795926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor cursor.setNotificationUri(getContext().getContentResolver(), MmsSms.CONTENT_URI); 4805926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor } 4817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return cursor; 4827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 4837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 4847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 4857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the canonical address ID for this address. 4867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 4877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private long getSingleAddressId(String address) { 4887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project boolean isEmail = Mms.isEmailAddress(address); 489e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor boolean isPhoneNumber = Mms.isPhoneNumber(address); 490e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor 491e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor // We lowercase all email addresses, but not addresses that aren't numbers, because 492e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor // that would incorrectly turn an address such as "My Vodafone" into "my vodafone" 493e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor // and the thread title would be incorrect when displayed in the UI. 4947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String refinedAddress = isEmail ? address.toLowerCase() : address; 495e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor 496c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang String selection = "address=?"; 497c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang String[] selectionArgs; 49814595cbe9045755a5aa2bd28989c147c4709268cWei Huang long retVal = -1L; 499c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang 500e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor if (!isPhoneNumber) { 501c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang selectionArgs = new String[] { refinedAddress }; 502c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang } else { 50301c75ba95b875674a83128defc6b267e522db346Chen Mike selection += " OR PHONE_NUMBERS_EQUAL(address, ?, " + 50401c75ba95b875674a83128defc6b267e522db346Chen Mike (mUseStrictPhoneNumberComparation ? 1 : 0) + ")"; 505c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang selectionArgs = new String[] { refinedAddress, refinedAddress }; 506c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang } 507c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang 5087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Cursor cursor = null; 5097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project try { 5117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 5127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor = db.query( 5137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "canonical_addresses", ID_PROJECTION, 5147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, selectionArgs, null, null, null); 5157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (cursor.getCount() == 0) { 5177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ContentValues contentValues = new ContentValues(1); 5187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project contentValues.put(CanonicalAddressesColumns.ADDRESS, refinedAddress); 5197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project db = mOpenHelper.getWritableDatabase(); 52114595cbe9045755a5aa2bd28989c147c4709268cWei Huang retVal = db.insert("canonical_addresses", 5227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project CanonicalAddressesColumns.ADDRESS, contentValues); 52314595cbe9045755a5aa2bd28989c147c4709268cWei Huang 524ea59f86662471e682f880b4916ce7588803f5605Wink Saville Log.d(LOG_TAG, "getSingleAddressId: insert new canonical_address for " + 525ea59f86662471e682f880b4916ce7588803f5605Wink Saville /*address*/ "xxxxxx" + ", _id=" + retVal); 52614595cbe9045755a5aa2bd28989c147c4709268cWei Huang 52714595cbe9045755a5aa2bd28989c147c4709268cWei Huang return retVal; 5287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (cursor.moveToFirst()) { 53114595cbe9045755a5aa2bd28989c147c4709268cWei Huang retVal = cursor.getLong(cursor.getColumnIndexOrThrow(BaseColumns._ID)); 5327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } finally { 5347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (cursor != null) { 5357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project cursor.close(); 5367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 53914595cbe9045755a5aa2bd28989c147c4709268cWei Huang return retVal; 5407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 5437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the canonical address IDs for these addresses. 5447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 5457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Set<Long> getAddressIds(List<String> addresses) { 5467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Set<Long> result = new HashSet<Long>(addresses.size()); 5477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (String address : addresses) { 5497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (!address.equals(PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR)) { 5507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project long id = getSingleAddressId(address); 5517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (id != -1L) { 5527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project result.add(id); 5537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } else { 55414595cbe9045755a5aa2bd28989c147c4709268cWei Huang Log.e(LOG_TAG, "getAddressIds: address ID not found for " + address); 5557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return result; 5597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 5627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return a sorted array of the given Set of Longs. 5637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 5647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private long[] getSortedSet(Set<Long> numbers) { 5657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int size = numbers.size(); 5667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project long[] result = new long[size]; 5677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int i = 0; 5687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (Long number : numbers) { 5707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project result[i++] = number; 5717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 57214595cbe9045755a5aa2bd28989c147c4709268cWei Huang 57314595cbe9045755a5aa2bd28989c147c4709268cWei Huang if (size > 1) { 57414595cbe9045755a5aa2bd28989c147c4709268cWei Huang Arrays.sort(result); 57514595cbe9045755a5aa2bd28989c147c4709268cWei Huang } 57614595cbe9045755a5aa2bd28989c147c4709268cWei Huang 5777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return result; 5787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 5817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return a String of the numbers in the given array, in order, 5827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * separated by spaces. 5837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 5847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private String getSpaceSeparatedNumbers(long[] numbers) { 5857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int size = numbers.length; 5867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project StringBuilder buffer = new StringBuilder(); 5877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (int i = 0; i < size; i++) { 5897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (i != 0) { 5907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project buffer.append(' '); 5917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project buffer.append(numbers[i]); 5937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return buffer.toString(); 5957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 5967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 5977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 5987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Insert a record for a new thread. 5997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 6007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private void insertThread(String recipientIds, int numberOfRecipients) { 6017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project ContentValues values = new ContentValues(4); 6027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 6037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project long date = System.currentTimeMillis(); 6047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project values.put(ThreadsColumns.DATE, date - date % 1000); 6057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project values.put(ThreadsColumns.RECIPIENT_IDS, recipientIds); 6067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (numberOfRecipients > 1) { 6077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project values.put(Threads.TYPE, Threads.BROADCAST_THREAD); 6087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 6097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project values.put(ThreadsColumns.MESSAGE_COUNT, 0); 6107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 61115156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor long result = mOpenHelper.getWritableDatabase().insert(TABLE_THREADS, null, values); 61214595cbe9045755a5aa2bd28989c147c4709268cWei Huang Log.d(LOG_TAG, "insertThread: created new thread_id " + result + 613ea59f86662471e682f880b4916ce7588803f5605Wink Saville " for recipientIds " + /*recipientIds*/ "xxxxxxx"); 61414595cbe9045755a5aa2bd28989c147c4709268cWei Huang 61543f9fb234aabe569b342af78bdaf85effbd85f10Amith Yamasani getContext().getContentResolver().notifyChange(MmsSms.CONTENT_URI, null, true, 61643f9fb234aabe569b342af78bdaf85effbd85f10Amith Yamasani UserHandle.USER_ALL); 6177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 6187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 61914595cbe9045755a5aa2bd28989c147c4709268cWei Huang private static final String THREAD_QUERY = 62014595cbe9045755a5aa2bd28989c147c4709268cWei Huang "SELECT _id FROM threads " + "WHERE recipient_ids=?"; 62114595cbe9045755a5aa2bd28989c147c4709268cWei Huang 6227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 6237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the thread ID for this list of 6247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * recipients IDs. If no thread exists with this ID, create 6257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * one and return it. Callers should always use 6267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Threads.getThreadId to access this information. 6277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 6287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private synchronized Cursor getThreadId(List<String> recipients) { 62914595cbe9045755a5aa2bd28989c147c4709268cWei Huang Set<Long> addressIds = getAddressIds(recipients); 63014595cbe9045755a5aa2bd28989c147c4709268cWei Huang String recipientIds = ""; 631c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang 6325926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor if (addressIds.size() == 0) { 6335926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor Log.e(LOG_TAG, "getThreadId: NO receipients specified -- NOT creating thread", 6345926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor new Exception()); 6355926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor return null; 6365926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor } else if (addressIds.size() == 1) { 6375926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor // optimize for size==1, which should be most of the cases 63814595cbe9045755a5aa2bd28989c147c4709268cWei Huang for (Long addressId : addressIds) { 63914595cbe9045755a5aa2bd28989c147c4709268cWei Huang recipientIds = Long.toString(addressId); 64014595cbe9045755a5aa2bd28989c147c4709268cWei Huang } 64114595cbe9045755a5aa2bd28989c147c4709268cWei Huang } else { 64214595cbe9045755a5aa2bd28989c147c4709268cWei Huang recipientIds = getSpaceSeparatedNumbers(getSortedSet(addressIds)); 64314595cbe9045755a5aa2bd28989c147c4709268cWei Huang } 6447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 64514595cbe9045755a5aa2bd28989c147c4709268cWei Huang if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) { 646ea59f86662471e682f880b4916ce7588803f5605Wink Saville Log.d(LOG_TAG, "getThreadId: recipientIds (selectionArgs) =" + 647ea59f86662471e682f880b4916ce7588803f5605Wink Saville /*recipientIds*/ "xxxxxxx"); 648b4ac04f7bd9d4f16ec181f368c42f89c96f83f55Tom Taylor } 64914595cbe9045755a5aa2bd28989c147c4709268cWei Huang 65014595cbe9045755a5aa2bd28989c147c4709268cWei Huang String[] selectionArgs = new String[] { recipientIds }; 65115156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor 6527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 65315156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor db.beginTransaction(); 65415156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor Cursor cursor = null; 65515156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor try { 65615156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor // Find the thread with the given recipients 65715156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor cursor = db.rawQuery(THREAD_QUERY, selectionArgs); 6587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 65915156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor if (cursor.getCount() == 0) { 66015156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor // No thread with those recipients exists, so create the thread. 66115156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor cursor.close(); 66214595cbe9045755a5aa2bd28989c147c4709268cWei Huang 66315156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor Log.d(LOG_TAG, "getThreadId: create new thread_id for recipients " + 66415156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor /*recipients*/ "xxxxxxxx"); 66515156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor insertThread(recipientIds, recipients.size()); 66614595cbe9045755a5aa2bd28989c147c4709268cWei Huang 66715156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor // The thread was just created, now find it and return it. 66815156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor cursor = db.rawQuery(THREAD_QUERY, selectionArgs); 66915156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor } 67015156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor db.setTransactionSuccessful(); 67115156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor } catch (Throwable ex) { 67215156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor Log.e(LOG_TAG, ex.getMessage(), ex); 67315156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor } finally { 67415156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor db.endTransaction(); 6757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 6766a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner 67715156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor if (cursor != null && cursor.getCount() > 1) { 67814595cbe9045755a5aa2bd28989c147c4709268cWei Huang Log.w(LOG_TAG, "getThreadId: why is cursorCount=" + cursor.getCount()); 67969e6ffada415d44c72d908ad9e152da51b190642Tom Taylor } 6807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return cursor; 6817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 6827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 6837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String concatSelections(String selection1, String selection2) { 6847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (TextUtils.isEmpty(selection1)) { 6857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return selection2; 6867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } else if (TextUtils.isEmpty(selection2)) { 6877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return selection1; 6887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } else { 6897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return selection1 + " AND " + selection2; 6907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 6917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 6927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 6937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 6947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * If a null projection is given, return the union of all columns 6957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * in both the MMS and SMS messages tables. Otherwise, return the 6967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * given projection. 6977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 6987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String[] handleNullMessageProjection( 6997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] projection) { 7007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return projection == null ? UNION_COLUMNS : projection; 7017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 7027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 7047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * If a null projection is given, return the set of all columns in 7057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * the threads table. Otherwise, return the given projection. 7067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 7077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String[] handleNullThreadsProjection( 7087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] projection) { 7097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return projection == null ? THREADS_COLUMNS : projection; 7107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 7117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 7137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * If a null sort order is given, return "normalized_date ASC". 7147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Otherwise, return the given sort order. 7157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 7167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String handleNullSortOrder (String sortOrder) { 7177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return sortOrder == null ? "normalized_date ASC" : sortOrder; 7187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 7197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 7217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return existing threads in the database. 7227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 7237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getSimpleConversations(String[] projection, String selection, 7247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] selectionArgs, String sortOrder) { 72515156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor return mOpenHelper.getReadableDatabase().query(TABLE_THREADS, projection, 7267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, selectionArgs, null, null, " date DESC"); 7277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 7287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 7307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the thread which has draft in both MMS and SMS. 7317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 7327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Use this query: 7337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 7347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * SELECT ... 7357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM (SELECT _id, thread_id, ... 7367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM pdu 7377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * WHERE msg_box = 3 AND ... 7387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * UNION 7397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * SELECT _id, thread_id, ... 7407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM sms 7417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * WHERE type = 3 AND ... 7427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * ) 7437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * ; 7447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 7457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getDraftThread(String[] projection, String selection, 746f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String sortOrder) { 7477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] innerProjection = new String[] {BaseColumns._ID, Conversations.THREAD_ID}; 7487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder(); 7497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder(); 7507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsQueryBuilder.setTables(MmsProvider.TABLE_PDU); 7527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsQueryBuilder.setTables(SmsProvider.TABLE_SMS); 7537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery( 7557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerProjection, 7567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MMS_COLUMNS, 1, "mms", 7577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project concatSelections(selection, Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_DRAFTS), 758f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor null, null); 7597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String smsSubQuery = smsQueryBuilder.buildUnionSubQuery( 7607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerProjection, 7617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SMS_COLUMNS, 1, "sms", 7627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project concatSelections(selection, Sms.TYPE + "=" + Sms.MESSAGE_TYPE_DRAFT), 763f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor null, null); 7647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder(); 7657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionQueryBuilder.setDistinct(true); 7677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String unionQuery = unionQueryBuilder.buildUnionQuery( 7697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project new String[] { mmsSubQuery, smsSubQuery }, null, null); 7707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder outerQueryBuilder = new SQLiteQueryBuilder(); 7727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project outerQueryBuilder.setTables("(" + unionQuery + ")"); 7747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String outerQuery = outerQueryBuilder.buildQuery( 776f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor projection, null, null, null, sortOrder, null); 7777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return mOpenHelper.getReadableDatabase().rawQuery(outerQuery, EMPTY_STRING_ARRAY); 7797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 7807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 7817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 7827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the most recent message in each conversation in both MMS 7837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * and SMS. 7847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 7857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Use this query: 7867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 7877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * SELECT ... 7887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM (SELECT thread_id AS tid, date * 1000 AS normalized_date, ... 7897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM pdu 7907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * WHERE msg_box != 3 AND ... 7917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * GROUP BY thread_id 7927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * HAVING date = MAX(date) 7937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * UNION 7947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * SELECT thread_id AS tid, date AS normalized_date, ... 7957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM sms 7967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * WHERE ... 7977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * GROUP BY thread_id 7987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * HAVING date = MAX(date)) 7997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * GROUP BY tid 8007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * HAVING normalized_date = MAX(normalized_date); 8017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 8027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * The msg_box != 3 comparisons ensure that we don't include draft 8037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * messages. 8047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 8057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getConversations(String[] projection, String selection, 806f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String sortOrder) { 8077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder(); 8087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder(); 8097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsQueryBuilder.setTables(MmsProvider.TABLE_PDU); 8117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsQueryBuilder.setTables(SmsProvider.TABLE_SMS); 8127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] columns = handleNullMessageProjection(projection); 8147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] innerMmsProjection = makeProjectionWithDateAndThreadId( 8157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project UNION_COLUMNS, 1000); 8167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] innerSmsProjection = makeProjectionWithDateAndThreadId( 8177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project UNION_COLUMNS, 1); 8187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery( 8197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerMmsProjection, 8207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MMS_COLUMNS, 1, "mms", 821f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor concatSelections(selection, MMS_CONVERSATION_CONSTRAINT), 8227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "thread_id", "date = MAX(date)"); 8237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String smsSubQuery = smsQueryBuilder.buildUnionSubQuery( 8247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerSmsProjection, 8257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SMS_COLUMNS, 1, "sms", 826f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor concatSelections(selection, SMS_CONVERSATION_CONSTRAINT), 8277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "thread_id", "date = MAX(date)"); 8287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder(); 8297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionQueryBuilder.setDistinct(true); 8317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String unionQuery = unionQueryBuilder.buildUnionQuery( 8337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project new String[] { mmsSubQuery, smsSubQuery }, null, null); 8347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder outerQueryBuilder = new SQLiteQueryBuilder(); 8367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project outerQueryBuilder.setTables("(" + unionQuery + ")"); 8387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String outerQuery = outerQueryBuilder.buildQuery( 840f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor columns, null, "tid", 8417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "normalized_date = MAX(normalized_date)", sortOrder, null); 8427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return mOpenHelper.getReadableDatabase().rawQuery(outerQuery, EMPTY_STRING_ARRAY); 8447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 8457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 8467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 847f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor * Return the first locked message found in the union of MMS 848f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor * and SMS messages. 849f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor * 850f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor * Use this query: 851f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor * 852816e934a43bf705835bdb24503a85a14c4861991Tom Taylor * SELECT _id FROM pdu GROUP BY _id HAVING locked=1 UNION SELECT _id FROM sms GROUP 853816e934a43bf705835bdb24503a85a14c4861991Tom Taylor * BY _id HAVING locked=1 LIMIT 1 854f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor * 855816e934a43bf705835bdb24503a85a14c4861991Tom Taylor * We limit by 1 because we're only interested in knowing if 856f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor * there is *any* locked message, not the actual messages themselves. 857f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor */ 858f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor private Cursor getFirstLockedMessage(String[] projection, String selection, 859f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String sortOrder) { 860f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder(); 861f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder(); 862f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 863f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor mmsQueryBuilder.setTables(MmsProvider.TABLE_PDU); 864f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor smsQueryBuilder.setTables(SmsProvider.TABLE_SMS); 865f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 866816e934a43bf705835bdb24503a85a14c4861991Tom Taylor String[] idColumn = new String[] { BaseColumns._ID }; 867816e934a43bf705835bdb24503a85a14c4861991Tom Taylor 868f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor // NOTE: buildUnionSubQuery *ignores* selectionArgs 869f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery( 870816e934a43bf705835bdb24503a85a14c4861991Tom Taylor MmsSms.TYPE_DISCRIMINATOR_COLUMN, idColumn, 871816e934a43bf705835bdb24503a85a14c4861991Tom Taylor null, 1, "mms", 872f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor selection, 873816e934a43bf705835bdb24503a85a14c4861991Tom Taylor BaseColumns._ID, "locked=1"); 874816e934a43bf705835bdb24503a85a14c4861991Tom Taylor 875f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor String smsSubQuery = smsQueryBuilder.buildUnionSubQuery( 876816e934a43bf705835bdb24503a85a14c4861991Tom Taylor MmsSms.TYPE_DISCRIMINATOR_COLUMN, idColumn, 877816e934a43bf705835bdb24503a85a14c4861991Tom Taylor null, 1, "sms", 878f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor selection, 879816e934a43bf705835bdb24503a85a14c4861991Tom Taylor BaseColumns._ID, "locked=1"); 880816e934a43bf705835bdb24503a85a14c4861991Tom Taylor 881f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder(); 882f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 883f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor unionQueryBuilder.setDistinct(true); 884f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 885f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor String unionQuery = unionQueryBuilder.buildUnionQuery( 886816e934a43bf705835bdb24503a85a14c4861991Tom Taylor new String[] { mmsSubQuery, smsSubQuery }, null, "1"); 887f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 888816e934a43bf705835bdb24503a85a14c4861991Tom Taylor Cursor cursor = mOpenHelper.getReadableDatabase().rawQuery(unionQuery, EMPTY_STRING_ARRAY); 889f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 890f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor if (DEBUG) { 891816e934a43bf705835bdb24503a85a14c4861991Tom Taylor Log.v("MmsSmsProvider", "getFirstLockedMessage query: " + unionQuery); 892816e934a43bf705835bdb24503a85a14c4861991Tom Taylor Log.v("MmsSmsProvider", "cursor count: " + cursor.getCount()); 893f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor } 894816e934a43bf705835bdb24503a85a14c4861991Tom Taylor return cursor; 895f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor } 896f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor 897f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor /** 8987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return every message in each conversation in both MMS 8997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * and SMS. 9007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 9017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getCompleteConversations(String[] projection, 902f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String selection, String sortOrder) { 903f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String unionQuery = buildConversationQuery(projection, selection, sortOrder); 9047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return mOpenHelper.getReadableDatabase().rawQuery(unionQuery, EMPTY_STRING_ARRAY); 9067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 9077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 9097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Add normalized date and thread_id to the list of columns for an 9107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * inner projection. This is necessary so that the outer query 9117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * can have access to these columns even if the caller hasn't 9127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * requested them in the result. 9137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 9147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private String[] makeProjectionWithDateAndThreadId( 9157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] projection, int dateMultiple) { 9167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int projectionSize = projection.length; 9177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] result = new String[projectionSize + 2]; 9187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project result[0] = "thread_id AS tid"; 9207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project result[1] = "date * " + dateMultiple + " AS normalized_date"; 9217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (int i = 0; i < projectionSize; i++) { 9227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project result[i + 2] = projection[i]; 9237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 9247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return result; 9257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 9267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 9287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the union of MMS and SMS messages for this thread ID. 9297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 9307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getConversationMessages( 9317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String threadIdString, String[] projection, String selection, 932f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String sortOrder) { 9337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project try { 9347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Long.parseLong(threadIdString); 9357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } catch (NumberFormatException exception) { 9367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Log.e(LOG_TAG, "Thread ID must be a Long."); 9377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return null; 9387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 9397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSelection = concatSelections( 9417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, "thread_id = " + threadIdString); 942f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String unionQuery = buildConversationQuery(projection, finalSelection, sortOrder); 9437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return mOpenHelper.getReadableDatabase().rawQuery(unionQuery, EMPTY_STRING_ARRAY); 9457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 9467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 9487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the union of MMS and SMS messages whose recipients 9497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * included this phone number. 9507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 9517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Use this query: 9527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * 9537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * SELECT ... 954670c495b6e0489569f60a38a79770dd4ac44500awhliang * FROM pdu, (SELECT msg_id AS address_msg_id 9557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM addr 956c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang * WHERE (address='<phoneNumber>' OR 957c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang * PHONE_NUMBERS_EQUAL(addr.address, '<phoneNumber>', 1/0))) 9587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * AS matching_addresses 959670c495b6e0489569f60a38a79770dd4ac44500awhliang * WHERE pdu._id = matching_addresses.address_msg_id 9607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * UNION 9617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * SELECT ... 9627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * FROM sms 963c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang * WHERE (address='<phoneNumber>' OR PHONE_NUMBERS_EQUAL(sms.address, '<phoneNumber>', 1/0)); 9647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 9657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getMessagesByPhoneNumber( 9667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String phoneNumber, String[] projection, String selection, 967f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String sortOrder) { 9687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String escapedPhoneNumber = DatabaseUtils.sqlEscapeString(phoneNumber); 9697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalMmsSelection = 9707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project concatSelections( 9717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, 972670c495b6e0489569f60a38a79770dd4ac44500awhliang "pdu._id = matching_addresses.address_msg_id"); 9737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSmsSelection = 9747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project concatSelections( 9757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, 976c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang "(address=" + escapedPhoneNumber + " OR PHONE_NUMBERS_EQUAL(address, " + 977845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa escapedPhoneNumber + 978c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang (mUseStrictPhoneNumberComparation ? ", 1))" : ", 0))")); 9797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder(); 9807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder(); 9817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsQueryBuilder.setDistinct(true); 9837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsQueryBuilder.setDistinct(true); 9847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsQueryBuilder.setTables( 9857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsProvider.TABLE_PDU + 986670c495b6e0489569f60a38a79770dd4ac44500awhliang ", (SELECT msg_id AS address_msg_id " + 987c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang "FROM addr WHERE (address=" + escapedPhoneNumber + 988c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang " OR PHONE_NUMBERS_EQUAL(addr.address, " + 989845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa escapedPhoneNumber + 990c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang (mUseStrictPhoneNumberComparation ? ", 1))) " : ", 0))) ") + 9917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project "AS matching_addresses"); 9927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsQueryBuilder.setTables(SmsProvider.TABLE_SMS); 9937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 9947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] columns = handleNullMessageProjection(projection); 9957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery( 9967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, columns, MMS_COLUMNS, 997f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor 0, "mms", finalMmsSelection, null, null); 9987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String smsSubQuery = smsQueryBuilder.buildUnionSubQuery( 9997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, columns, SMS_COLUMNS, 1000f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor 0, "sms", finalSmsSelection, null, null); 10017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder(); 10027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionQueryBuilder.setDistinct(true); 10047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String unionQuery = unionQueryBuilder.buildUnionQuery( 10067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project new String[] { mmsSubQuery, smsSubQuery }, sortOrder, null); 10077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return mOpenHelper.getReadableDatabase().rawQuery(unionQuery, EMPTY_STRING_ARRAY); 10097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 10107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 10127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Return the conversation of certain thread ID. 10137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 10147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getConversationById( 10157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String threadIdString, String[] projection, String selection, 10167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] selectionArgs, String sortOrder) { 10177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project try { 10187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Long.parseLong(threadIdString); 10197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } catch (NumberFormatException exception) { 10207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Log.e(LOG_TAG, "Thread ID must be a Long."); 10217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return null; 10227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 10237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String extraSelection = "_id=" + threadIdString; 10257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSelection = concatSelections(selection, extraSelection); 10267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); 10277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] columns = handleNullThreadsProjection(projection); 10287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project queryBuilder.setDistinct(true); 103015156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor queryBuilder.setTables(TABLE_THREADS); 10317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return queryBuilder.query( 10327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mOpenHelper.getReadableDatabase(), columns, finalSelection, 10337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selectionArgs, sortOrder, null, null); 10347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 10357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String joinPduAndPendingMsgTables() { 10377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return MmsProvider.TABLE_PDU + " LEFT JOIN " + TABLE_PENDING_MSG 10387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + " ON pdu._id = pending_msgs.msg_id"; 10397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 10407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String[] createMmsProjection(String[] old) { 10427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] newProjection = new String[old.length]; 10437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (int i = 0; i < old.length; i++) { 10447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (old[i].equals(BaseColumns._ID)) { 10457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project newProjection[i] = "pdu._id"; 10467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } else { 10477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project newProjection[i] = old[i]; 10487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 10497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 10507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return newProjection; 10517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 10527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private Cursor getUndeliveredMessages( 10547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] projection, String selection, String[] selectionArgs, 10557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String sortOrder) { 10567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] mmsProjection = createMmsProjection(projection); 10577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder(); 10597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder(); 10607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsQueryBuilder.setTables(joinPduAndPendingMsgTables()); 10627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsQueryBuilder.setTables(SmsProvider.TABLE_SMS); 10637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalMmsSelection = concatSelections( 10657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, Mms.MESSAGE_BOX + " = " + Mms.MESSAGE_BOX_OUTBOX); 10667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSmsSelection = concatSelections( 10677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, "(" + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_OUTBOX 10687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + " OR " + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_FAILED 10697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + " OR " + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_QUEUED + ")"); 10707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] smsColumns = handleNullMessageProjection(projection); 10727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] mmsColumns = handleNullMessageProjection(mmsProjection); 10737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] innerMmsProjection = makeProjectionWithDateAndThreadId( 10747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsColumns, 1000); 10757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] innerSmsProjection = makeProjectionWithDateAndThreadId( 10767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsColumns, 1); 10777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Set<String> columnsPresentInTable = new HashSet<String>(MMS_COLUMNS); 10797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project columnsPresentInTable.add("pdu._id"); 10807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project columnsPresentInTable.add(PendingMessages.ERROR_TYPE); 10817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery( 10827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerMmsProjection, 1083f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor columnsPresentInTable, 1, "mms", finalMmsSelection, 10847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project null, null); 10857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String smsSubQuery = smsQueryBuilder.buildUnionSubQuery( 10867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerSmsProjection, 1087f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor SMS_COLUMNS, 1, "sms", finalSmsSelection, 10887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project null, null); 10897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder(); 10907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionQueryBuilder.setDistinct(true); 10927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String unionQuery = unionQueryBuilder.buildUnionQuery( 10947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project new String[] { smsSubQuery, mmsSubQuery }, null, null); 10957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder outerQueryBuilder = new SQLiteQueryBuilder(); 10977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 10987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project outerQueryBuilder.setTables("(" + unionQuery + ")"); 10997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String outerQuery = outerQueryBuilder.buildQuery( 1101f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor smsColumns, null, null, null, sortOrder, null); 11027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return mOpenHelper.getReadableDatabase().rawQuery(outerQuery, EMPTY_STRING_ARRAY); 11047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 11057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 11077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Add normalized date to the list of columns for an inner 11087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * projection. 11097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 11107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String[] makeProjectionWithNormalizedDate( 11117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] projection, int dateMultiple) { 11127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int projectionSize = projection.length; 11137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] result = new String[projectionSize + 1]; 11147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project result[0] = "date * " + dateMultiple + " AS normalized_date"; 11167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project System.arraycopy(projection, 0, result, 1, projectionSize); 11177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return result; 11187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 11197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static String buildConversationQuery(String[] projection, 1121f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor String selection, String sortOrder) { 11227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] mmsProjection = createMmsProjection(projection); 11237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder(); 11257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder(); 11267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsQueryBuilder.setDistinct(true); 11287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsQueryBuilder.setDistinct(true); 11297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project mmsQueryBuilder.setTables(joinPduAndPendingMsgTables()); 11307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project smsQueryBuilder.setTables(SmsProvider.TABLE_SMS); 11317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] smsColumns = handleNullMessageProjection(projection); 11337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] mmsColumns = handleNullMessageProjection(mmsProjection); 11347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] innerMmsProjection = makeProjectionWithNormalizedDate(mmsColumns, 1000); 11357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] innerSmsProjection = makeProjectionWithNormalizedDate(smsColumns, 1); 11367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Set<String> columnsPresentInTable = new HashSet<String>(MMS_COLUMNS); 11387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project columnsPresentInTable.add("pdu._id"); 11397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project columnsPresentInTable.add(PendingMessages.ERROR_TYPE); 11407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String mmsSelection = concatSelections(selection, 11427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Mms.MESSAGE_BOX + " != " + Mms.MESSAGE_BOX_DRAFTS); 11437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery( 11447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerMmsProjection, 11457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project columnsPresentInTable, 0, "mms", 11467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project concatSelections(mmsSelection, MMS_CONVERSATION_CONSTRAINT), 1147f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor null, null); 11487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String smsSubQuery = smsQueryBuilder.buildUnionSubQuery( 11497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerSmsProjection, SMS_COLUMNS, 11507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 0, "sms", concatSelections(selection, SMS_CONVERSATION_CONSTRAINT), 1151f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor null, null); 11527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder(); 11537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionQueryBuilder.setDistinct(true); 11557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String unionQuery = unionQueryBuilder.buildUnionQuery( 11577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project new String[] { smsSubQuery, mmsSubQuery }, 11587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project handleNullSortOrder(sortOrder), null); 11597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteQueryBuilder outerQueryBuilder = new SQLiteQueryBuilder(); 11617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project outerQueryBuilder.setTables("(" + unionQuery + ")"); 11637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return outerQueryBuilder.buildQuery( 1165f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor smsColumns, null, null, null, sortOrder, null); 11667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 11677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project @Override 11697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project public String getType(Uri uri) { 11707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return VND_ANDROID_DIR_MMS_SMS; 11717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 11727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 11737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project @Override 11747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project public int delete(Uri uri, String selection, 11757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String[] selectionArgs) { 11767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 11777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Context context = getContext(); 11787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int affectedRows = 0; 1179f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner 11807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project switch(URI_MATCHER.match(uri)) { 11817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CONVERSATIONS_MESSAGES: 11827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project long threadId; 11837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project try { 11847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project threadId = Long.parseLong(uri.getLastPathSegment()); 11857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } catch (NumberFormatException e) { 11867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Log.e(LOG_TAG, "Thread ID must be a long."); 11877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 11887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 11897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project affectedRows = deleteConversation(uri, selection, selectionArgs); 11907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MmsSmsDatabaseHelper.updateThread(db, threadId); 11917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 11927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CONVERSATIONS: 11937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project affectedRows = MmsProvider.deleteMessages(context, db, 11947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selection, selectionArgs, uri) 11957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + db.delete("sms", selection, selectionArgs); 119687bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor // Intentionally don't pass the selection variable to updateAllThreads. 119787bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor // When we pass in "locked=0" there, the thread will get excluded from 119887bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor // the selection and not get updated. 119987bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor MmsSmsDatabaseHelper.updateAllThreads(db, null, null); 12007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 12017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_OBSOLETE_THREADS: 120215156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor affectedRows = db.delete(TABLE_THREADS, 12034b14c35e9e44d5df2b5340141f2b24bab351c603Tom Taylor "_id NOT IN (SELECT DISTINCT thread_id FROM sms where thread_id NOT NULL " + 12044b14c35e9e44d5df2b5340141f2b24bab351c603Tom Taylor "UNION SELECT DISTINCT thread_id FROM pdu where thread_id NOT NULL)", null); 12057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 12067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project default: 1207b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor throw new UnsupportedOperationException(NO_DELETES_INSERTS_OR_UPDATES + uri); 12087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (affectedRows > 0) { 121143f9fb234aabe569b342af78bdaf85effbd85f10Amith Yamasani context.getContentResolver().notifyChange(MmsSms.CONTENT_URI, null, true, 121243f9fb234aabe569b342af78bdaf85effbd85f10Amith Yamasani UserHandle.USER_ALL); 12137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return affectedRows; 12157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 12187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Delete the conversation with the given thread ID. 12197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 12207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private int deleteConversation(Uri uri, String selection, String[] selectionArgs) { 12217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String threadId = uri.getLastPathSegment(); 12227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 12247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSelection = concatSelections(selection, "thread_id = " + threadId); 12257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return MmsProvider.deleteMessages(getContext(), db, finalSelection, 12267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project selectionArgs, uri) 12277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + db.delete("sms", finalSelection, selectionArgs); 12287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project @Override 12317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project public Uri insert(Uri uri, ContentValues values) { 1232b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor if (URI_MATCHER.match(uri) == URI_PENDING_MSG) { 1233b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 1234b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor long rowId = db.insert(TABLE_PENDING_MSG, null, values); 1235b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor return Uri.parse(uri + "/" + rowId); 1236b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor } 1237b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor throw new UnsupportedOperationException(NO_DELETES_INSERTS_OR_UPDATES + uri); 12387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project @Override 12417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project public int update(Uri uri, ContentValues values, 12427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String selection, String[] selectionArgs) { 1243e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen final int callerUid = Binder.getCallingUid(); 12447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 12457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int affectedRows = 0; 12467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project switch(URI_MATCHER.match(uri)) { 12477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_CONVERSATIONS_MESSAGES: 12487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String threadIdString = uri.getPathSegments().get(1); 12497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project affectedRows = updateConversation(threadIdString, values, 1250e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen selection, selectionArgs, callerUid); 12517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 12521ecf192c60625c5227336430ee36705c13ae06e2Wei Huang 12537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project case URI_PENDING_MSG: 12547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project affectedRows = db.update(TABLE_PENDING_MSG, values, selection, null); 12557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project break; 12561ecf192c60625c5227336430ee36705c13ae06e2Wei Huang 12571ecf192c60625c5227336430ee36705c13ae06e2Wei Huang case URI_CANONICAL_ADDRESS: { 12581ecf192c60625c5227336430ee36705c13ae06e2Wei Huang String extraSelection = "_id=" + uri.getPathSegments().get(1); 12591ecf192c60625c5227336430ee36705c13ae06e2Wei Huang String finalSelection = TextUtils.isEmpty(selection) 12601ecf192c60625c5227336430ee36705c13ae06e2Wei Huang ? extraSelection : extraSelection + " AND " + selection; 12611ecf192c60625c5227336430ee36705c13ae06e2Wei Huang 12621ecf192c60625c5227336430ee36705c13ae06e2Wei Huang affectedRows = db.update(TABLE_CANONICAL_ADDRESSES, values, finalSelection, null); 12631ecf192c60625c5227336430ee36705c13ae06e2Wei Huang break; 12641ecf192c60625c5227336430ee36705c13ae06e2Wei Huang } 12651ecf192c60625c5227336430ee36705c13ae06e2Wei Huang 126682fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen case URI_CONVERSATIONS: { 126782fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen final ContentValues finalValues = new ContentValues(1); 126882fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen if (values.containsKey(Threads.ARCHIVED)) { 126982fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen // Only allow update archived 127082fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen finalValues.put(Threads.ARCHIVED, values.getAsBoolean(Threads.ARCHIVED)); 127182fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen } 127282fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen affectedRows = db.update(TABLE_THREADS, finalValues, selection, selectionArgs); 127382fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen break; 127482fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen } 127582fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen 12767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project default: 12777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project throw new UnsupportedOperationException( 1278b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor NO_DELETES_INSERTS_OR_UPDATES + uri); 12797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project if (affectedRows > 0) { 12827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project getContext().getContentResolver().notifyChange( 128343f9fb234aabe569b342af78bdaf85effbd85f10Amith Yamasani MmsSms.CONTENT_URI, null, true, UserHandle.USER_ALL); 12847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return affectedRows; 12867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 12877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 12887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private int updateConversation( 12897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String threadIdString, ContentValues values, String selection, 1290e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen String[] selectionArgs, int callerUid) { 12917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project try { 12927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Long.parseLong(threadIdString); 12937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } catch (NumberFormatException exception) { 12947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Log.e(LOG_TAG, "Thread ID must be a Long."); 12957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return 0; 1296e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen 1297e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen } 1298e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen if (ProviderUtil.shouldRemoveCreator(values, callerUid)) { 1299e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen // CREATOR should not be changed by non-SYSTEM/PHONE apps 1300e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen Log.w(LOG_TAG, ProviderUtil.getPackageNamesByUid(getContext(), callerUid) + 1301e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen " tries to update CREATOR"); 1302e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen // Sms.CREATOR and Mms.CREATOR are same. But let's do this 1303e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen // twice in case the names may differ in the future 1304e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen values.remove(Sms.CREATOR); 1305e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen values.remove(Mms.CREATOR); 13067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 13077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 13087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 13097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project String finalSelection = concatSelections(selection, "thread_id=" + threadIdString); 13107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project return db.update(MmsProvider.TABLE_PDU, values, finalSelection, selectionArgs) 13117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project + db.update("sms", values, finalSelection, selectionArgs); 13127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 13137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 13147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project /** 13157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Construct Sets of Strings containing exactly the columns 13167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * present in each table. We will use this when constructing 13177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * UNION queries across the MMS and SMS tables. 13187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */ 13197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project private static void initializeColumnSets() { 13207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int commonColumnCount = MMS_SMS_COLUMNS.length; 13217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int mmsOnlyColumnCount = MMS_ONLY_COLUMNS.length; 13227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int smsOnlyColumnCount = SMS_ONLY_COLUMNS.length; 13237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project Set<String> unionColumns = new HashSet<String>(); 13247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 13257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (int i = 0; i < commonColumnCount; i++) { 13267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MMS_COLUMNS.add(MMS_SMS_COLUMNS[i]); 13277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SMS_COLUMNS.add(MMS_SMS_COLUMNS[i]); 13287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionColumns.add(MMS_SMS_COLUMNS[i]); 13297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 13307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (int i = 0; i < mmsOnlyColumnCount; i++) { 13317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project MMS_COLUMNS.add(MMS_ONLY_COLUMNS[i]); 13327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionColumns.add(MMS_ONLY_COLUMNS[i]); 13337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 13347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (int i = 0; i < smsOnlyColumnCount; i++) { 13357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project SMS_COLUMNS.add(SMS_ONLY_COLUMNS[i]); 13367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project unionColumns.add(SMS_ONLY_COLUMNS[i]); 13377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 13387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project 13397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project int i = 0; 13407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project for (String columnName : unionColumns) { 13417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project UNION_COLUMNS[i++] = columnName; 13427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 13437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project } 13447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project} 1345