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