MmsSmsProvider.java revision 5a3194d943854ec3c2ec5df18a95a5b04ab5efa1
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;
3386b8a2cfb7558ec500b4de46bac3d873eaf6028fYe Wenimport android.provider.Telephony;
347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.CanonicalAddressesColumns;
357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Mms;
367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.MmsSms;
37e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wenimport android.provider.Telephony.MmsSms.PendingMessages;
387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Sms;
39e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wenimport android.provider.Telephony.Sms.Conversations;
407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Threads;
417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.ThreadsColumns;
427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.text.TextUtils;
437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.util.Log;
447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
45b1bae65bf18dc22762cf7b8210fdad836b3e4ee5Tom Taylorimport com.google.android.mms.pdu.PduHeaders;
467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
4786b8a2cfb7558ec500b4de46bac3d873eaf6028fYe Wenimport java.io.FileDescriptor;
4886b8a2cfb7558ec500b4de46bac3d873eaf6028fYe Wenimport java.io.PrintWriter;
49e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wenimport java.util.Arrays;
50e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wenimport java.util.HashSet;
51e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wenimport java.util.List;
52e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wenimport java.util.Set;
53e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen
547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project/**
557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * This class provides the ability to query the MMS and SMS databases
567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * at the same time, mixing messages from both in a single thread
577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * (A.K.A. conversation).
587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project *
597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * A virtual column, MmsSms.TYPE_DISCRIMINATOR_COLUMN, may be
607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * requested in the projection for a query.  Its value is either "mms"
617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * or "sms", depending on whether the message represented by the row
627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * is an MMS message or an SMS message, respectively.
637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project *
647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * This class also provides the ability to find out what addresses
657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * participated in a particular thread.  It doesn't support updates
667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * for either of these.
677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project *
687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * This class provides a way to allocate and retrieve thread IDs.
697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * This is done atomically through a query.  There is no insert URI
707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * for this.
717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project *
727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Finally, this class provides a way to delete or update all messages
737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * in a thread.
747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */
757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectpublic class MmsSmsProvider extends ContentProvider {
767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final UriMatcher URI_MATCHER =
777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            new UriMatcher(UriMatcher.NO_MATCH);
787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String LOG_TAG = "MmsSmsProvider";
79816e934a43bf705835bdb24503a85a14c4861991Tom Taylor    private static final boolean DEBUG = false;
807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String NO_DELETES_INSERTS_OR_UPDATES =
827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            "MmsSmsProvider does not support deletes, inserts, or updates for this URI.";
83f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_CONVERSATIONS                     = 0;
84f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_CONVERSATIONS_MESSAGES            = 1;
85f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_CONVERSATIONS_RECIPIENTS          = 2;
86f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_MESSAGES_BY_PHONE                 = 3;
87f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_THREAD_ID                         = 4;
88f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_CANONICAL_ADDRESS                 = 5;
89f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_PENDING_MSG                       = 6;
90f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_COMPLETE_CONVERSATIONS            = 7;
91f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_UNDELIVERED_MSG                   = 8;
92f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_CONVERSATIONS_SUBJECT             = 9;
93f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_NOTIFICATIONS                     = 10;
94f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_OBSOLETE_THREADS                  = 11;
95f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_DRAFT                             = 12;
96f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_CANONICAL_ADDRESSES               = 13;
97f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private static final int URI_SEARCH                            = 14;
988e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    private static final int URI_SEARCH_SUGGEST                    = 15;
998e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    private static final int URI_FIRST_LOCKED_MESSAGE_ALL          = 16;
1008e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    private static final int URI_FIRST_LOCKED_MESSAGE_BY_THREAD_ID = 17;
1016a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner    private static final int URI_MESSAGE_ID_TO_THREAD              = 18;
1027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
1047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * the name of the table that is used to store the queue of
1057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * messages(both MMS and SMS) to be sent/downloaded.
1067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
1077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public static final String TABLE_PENDING_MSG = "pending_msgs";
1087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1091ecf192c60625c5227336430ee36705c13ae06e2Wei Huang    /**
1101ecf192c60625c5227336430ee36705c13ae06e2Wei Huang     * the name of the table that is used to store the canonical addresses for both SMS and MMS.
1111ecf192c60625c5227336430ee36705c13ae06e2Wei Huang     */
1121ecf192c60625c5227336430ee36705c13ae06e2Wei Huang    private static final String TABLE_CANONICAL_ADDRESSES = "canonical_addresses";
1131ecf192c60625c5227336430ee36705c13ae06e2Wei Huang
11415156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor    /**
11515156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor     * the name of the table that is used to store the conversation threads.
11615156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor     */
11715156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor    static final String TABLE_THREADS = "threads";
11815156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor
1197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // These constants are used to construct union queries across the
1207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // MMS and SMS base tables.
1217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // These are the columns that appear in both the MMS ("pdu") and
1237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // SMS ("sms") message tables.
1247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String[] MMS_SMS_COLUMNS =
125cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen            { BaseColumns._ID, Mms.DATE, Mms.DATE_SENT, Mms.READ, Mms.THREAD_ID, Mms.LOCKED,
12672b147363200ff3f0bc467f23579042bd800ff13Wink Saville                    Mms.SUBSCRIPTION_ID };
1277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // These are the columns that appear only in the MMS message
1297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // table.
1307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String[] MMS_ONLY_COLUMNS = {
1317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Mms.CONTENT_CLASS, Mms.CONTENT_LOCATION, Mms.CONTENT_TYPE,
1327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Mms.DELIVERY_REPORT, Mms.EXPIRY, Mms.MESSAGE_CLASS, Mms.MESSAGE_ID,
1337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Mms.MESSAGE_SIZE, Mms.MESSAGE_TYPE, Mms.MESSAGE_BOX, Mms.PRIORITY,
1347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Mms.READ_STATUS, Mms.RESPONSE_STATUS, Mms.RESPONSE_TEXT,
1357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Mms.RETRIEVE_STATUS, Mms.RETRIEVE_TEXT_CHARSET, Mms.REPORT_ALLOWED,
1367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Mms.READ_REPORT, Mms.STATUS, Mms.SUBJECT, Mms.SUBJECT_CHARSET,
137f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor        Mms.TRANSACTION_ID, Mms.MMS_VERSION, Mms.TEXT_ONLY };
1387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // These are the columns that appear only in the SMS message
1407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // table.
1417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String[] SMS_ONLY_COLUMNS =
1427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            { "address", "body", "person", "reply_path_present",
143ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor              "service_center", "status", "subject", "type", "error_code" };
1447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // These are all the columns that appear in the "threads" table.
1467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String[] THREADS_COLUMNS = {
1477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        BaseColumns._ID,
1487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        ThreadsColumns.DATE,
1497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        ThreadsColumns.RECIPIENT_IDS,
1507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        ThreadsColumns.MESSAGE_COUNT
1517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    };
1527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1531ecf192c60625c5227336430ee36705c13ae06e2Wei Huang    private static final String[] CANONICAL_ADDRESSES_COLUMNS_1 =
1541ecf192c60625c5227336430ee36705c13ae06e2Wei Huang            new String[] { CanonicalAddressesColumns.ADDRESS };
1551ecf192c60625c5227336430ee36705c13ae06e2Wei Huang
1561ecf192c60625c5227336430ee36705c13ae06e2Wei Huang    private static final String[] CANONICAL_ADDRESSES_COLUMNS_2 =
1571ecf192c60625c5227336430ee36705c13ae06e2Wei Huang            new String[] { CanonicalAddressesColumns._ID,
1581ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                    CanonicalAddressesColumns.ADDRESS };
1591ecf192c60625c5227336430ee36705c13ae06e2Wei Huang
1607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // These are all the columns that appear in the MMS and SMS
1617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // message tables.
1627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String[] UNION_COLUMNS =
1637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            new String[MMS_SMS_COLUMNS.length
1647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                       + MMS_ONLY_COLUMNS.length
1657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                       + SMS_ONLY_COLUMNS.length];
1667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // These are all the columns that appear in the MMS table.
1687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final Set<String> MMS_COLUMNS = new HashSet<String>();
1697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // These are all the columns that appear in the SMS table.
1717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final Set<String> SMS_COLUMNS = new HashSet<String>();
1727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String VND_ANDROID_DIR_MMS_SMS =
1747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            "vnd.android-dir/mms-sms";
1757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String[] ID_PROJECTION = { BaseColumns._ID };
1777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String[] EMPTY_STRING_ARRAY = new String[0];
1797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1803e1cba826743423642635cc7b03abe292470f4c4Tom Taylor    private static final String[] SEARCH_STRING = new String[1];
1813e1cba826743423642635cc7b03abe292470f4c4Tom Taylor    private static final String SEARCH_QUERY = "SELECT snippet(words, '', ' ', '', 1, 1) as " +
1823e1cba826743423642635cc7b03abe292470f4c4Tom Taylor            "snippet FROM words WHERE index_text MATCH ? ORDER BY snippet LIMIT 50;";
1833e1cba826743423642635cc7b03abe292470f4c4Tom Taylor
1847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String SMS_CONVERSATION_CONSTRAINT = "(" +
1857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            Sms.TYPE + " != " + Sms.MESSAGE_TYPE_DRAFT + ")";
1867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String MMS_CONVERSATION_CONSTRAINT = "(" +
1887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            Mms.MESSAGE_BOX + " != " + Mms.MESSAGE_BOX_DRAFTS + " AND (" +
1897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            Mms.MESSAGE_TYPE + " = " + PduHeaders.MESSAGE_TYPE_SEND_REQ + " OR " +
1907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            Mms.MESSAGE_TYPE + " = " + PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF + " OR " +
1917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            Mms.MESSAGE_TYPE + " = " + PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND + "))";
1927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
19372f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen    private static String getTextSearchQuery(String smsTable, String pduTable) {
19472f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        // Search on the words table but return the rows from the corresponding sms table
19572f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        final String smsQuery = "SELECT "
19672f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + smsTable + "._id AS _id,"
19772f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "thread_id,"
19872f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "address,"
19972f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "body,"
20072f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "date,"
20172f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "date_sent,"
20272f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "index_text,"
20372f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "words._id "
20472f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "FROM " + smsTable + ",words "
20572f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "WHERE (index_text MATCH ? "
20672f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "AND " + smsTable + "._id=words.source_id "
20772f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "AND words.table_to_use=1)";
20872f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen
20972f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        // Search on the words table but return the rows from the corresponding parts table
21072f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        final String mmsQuery = "SELECT "
21172f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + pduTable + "._id,"
21272f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "thread_id,"
21372f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "addr.address,"
21472f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "part.text AS body,"
21572f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + pduTable + ".date,"
21672f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + pduTable + ".date_sent,"
21772f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "index_text,"
21872f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "words._id "
21972f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "FROM " + pduTable + ",part,addr,words "
22072f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "WHERE ((part.mid=" + pduTable + "._id) "
22172f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "AND (addr.msg_id=" + pduTable + "._id) "
22272f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "AND (addr.type=" + PduHeaders.TO + ") "
22372f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "AND (part.ct='text/plain') "
22472f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "AND (index_text MATCH ?) "
22572f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "AND (part._id = words.source_id) "
22672f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "AND (words.table_to_use=2))";
22772f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen
22872f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        // This code queries the sms and mms tables and returns a unified result set
22972f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        // of text matches.  We query the sms table which is pretty simple.  We also
23072f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        // query the pdu, part and addr table to get the mms result.  Note we're
23172f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        // using a UNION so we have to have the same number of result columns from
23272f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        // both queries.
23372f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        return smsQuery + " UNION " + mmsQuery + " "
23472f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "GROUP BY thread_id "
23572f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + "ORDER BY thread_id ASC, date DESC";
23672f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen    }
23701c75ba95b875674a83128defc6b267e522db346Chen Mike
2387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String AUTHORITY = "mms-sms";
2397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    static {
2417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        URI_MATCHER.addURI(AUTHORITY, "conversations", URI_CONVERSATIONS);
2427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        URI_MATCHER.addURI(AUTHORITY, "complete-conversations", URI_COMPLETE_CONVERSATIONS);
2437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // In these patterns, "#" is the thread ID.
2457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        URI_MATCHER.addURI(
2467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                AUTHORITY, "conversations/#", URI_CONVERSATIONS_MESSAGES);
2477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        URI_MATCHER.addURI(
2487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                AUTHORITY, "conversations/#/recipients",
2497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                URI_CONVERSATIONS_RECIPIENTS);
2507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        URI_MATCHER.addURI(
2527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                AUTHORITY, "conversations/#/subject",
2537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                URI_CONVERSATIONS_SUBJECT);
2547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // URI for deleting obsolete threads.
2567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        URI_MATCHER.addURI(AUTHORITY, "conversations/obsolete", URI_OBSOLETE_THREADS);
2577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        URI_MATCHER.addURI(
2597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                AUTHORITY, "messages/byphone/*",
2607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                URI_MESSAGES_BY_PHONE);
2617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // In this pattern, two query parameter names are expected:
2637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // "subject" and "recipient."  Multiple "recipient" parameters
2647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // may be present.
2657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        URI_MATCHER.addURI(AUTHORITY, "threadID", URI_THREAD_ID);
2667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Use this pattern to query the canonical address by given ID.
2687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        URI_MATCHER.addURI(AUTHORITY, "canonical-address/#", URI_CANONICAL_ADDRESS);
2697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
27037e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick        // Use this pattern to query all canonical addresses.
27137e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick        URI_MATCHER.addURI(AUTHORITY, "canonical-addresses", URI_CANONICAL_ADDRESSES);
272f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
27366d373c4797c53207e8f1ea97f3dc5541f390152Mark Wagner        URI_MATCHER.addURI(AUTHORITY, "search", URI_SEARCH);
2748e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        URI_MATCHER.addURI(AUTHORITY, "searchSuggest", URI_SEARCH_SUGGEST);
27537e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick
2767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // In this pattern, two query parameters may be supplied:
2777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // "protocol" and "message." For example:
2787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        //   content://mms-sms/pending?
2797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        //       -> Return all pending messages;
2807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        //   content://mms-sms/pending?protocol=sms
2817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        //       -> Only return pending SMs;
2827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        //   content://mms-sms/pending?protocol=mms&message=1
2837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        //       -> Return the the pending MM which ID equals '1'.
2847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        //
2857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        URI_MATCHER.addURI(AUTHORITY, "pending", URI_PENDING_MSG);
2867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Use this pattern to get a list of undelivered messages.
2887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        URI_MATCHER.addURI(AUTHORITY, "undelivered", URI_UNDELIVERED_MSG);
2897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Use this pattern to see what delivery status reports (for
2917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // both MMS and SMS) have not been delivered to the user.
2927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        URI_MATCHER.addURI(AUTHORITY, "notifications", URI_NOTIFICATIONS);
2937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        URI_MATCHER.addURI(AUTHORITY, "draft", URI_DRAFT);
295f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor
296f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor        URI_MATCHER.addURI(AUTHORITY, "locked", URI_FIRST_LOCKED_MESSAGE_ALL);
297f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor
298f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor        URI_MATCHER.addURI(AUTHORITY, "locked/#", URI_FIRST_LOCKED_MESSAGE_BY_THREAD_ID);
299f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor
3006a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner        URI_MATCHER.addURI(AUTHORITY, "messageIdToThread", URI_MESSAGE_ID_TO_THREAD);
3017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        initializeColumnSets();
3027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
3037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
3047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private SQLiteOpenHelper mOpenHelper;
3057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
306845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa    private boolean mUseStrictPhoneNumberComparation;
307845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa
3087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    @Override
3097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public boolean onCreate() {
310b2ce2d37bc6efc0c37d8cee925d3ad65a01ea4bfYe Wen        setAppOps(AppOpsManager.OP_READ_SMS, AppOpsManager.OP_WRITE_SMS);
3115a3194d943854ec3c2ec5df18a95a5b04ab5efa1Ji Yang        mOpenHelper = MmsSmsDatabaseHelper.getInstanceForCe(getContext());
312845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa        mUseStrictPhoneNumberComparation =
313845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa            getContext().getResources().getBoolean(
314845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa                    com.android.internal.R.bool.config_use_strict_phone_number_comparation);
3157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return true;
3167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
3177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
3187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    @Override
3197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public Cursor query(Uri uri, String[] projection,
3207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            String selection, String[] selectionArgs, String sortOrder) {
32172f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        // First check if restricted views of the "sms" and "pdu" tables should be used based on the
32272f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        // caller's identity. Only system, phone or the default sms app can have full access
32372f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        // of sms/mms data. For other apps, we present a restricted view which only contains sent
32472f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        // or received messages, without wap pushes.
32572f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        final boolean accessRestricted = ProviderUtil.isAccessRestricted(
32672f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                getContext(), getCallingPackage(), Binder.getCallingUid());
32772f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        final String pduTable = MmsProvider.getPduTable(accessRestricted);
32872f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        final String smsTable = SmsProvider.getSmsTable(accessRestricted);
32972f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen
3307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
3317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Cursor cursor = null;
33272f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        final int match = URI_MATCHER.match(uri);
33372f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        switch (match) {
3347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_COMPLETE_CONVERSATIONS:
33572f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                cursor = getCompleteConversations(projection, selection, sortOrder, smsTable,
33672f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                        pduTable);
3377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
3387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_CONVERSATIONS:
3397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                String simple = uri.getQueryParameter("simple");
3407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                if ((simple != null) && simple.equals("true")) {
3417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                    String threadType = uri.getQueryParameter("thread_type");
3427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                    if (!TextUtils.isEmpty(threadType)) {
3437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        selection = concatSelections(
3447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                                selection, Threads.TYPE + "=" + threadType);
3457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                    }
3467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                    cursor = getSimpleConversations(
3477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                            projection, selection, selectionArgs, sortOrder);
3487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                } else {
3497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                    cursor = getConversations(
35072f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                            projection, selection, sortOrder, smsTable, pduTable);
3517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                }
3527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
3537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_CONVERSATIONS_MESSAGES:
354f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                cursor = getConversationMessages(uri.getPathSegments().get(1), projection,
35572f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                        selection, sortOrder, smsTable, pduTable);
3567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
3577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_CONVERSATIONS_RECIPIENTS:
3587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                cursor = getConversationById(
3597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        uri.getPathSegments().get(1), projection, selection,
3607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        selectionArgs, sortOrder);
3617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
3627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_CONVERSATIONS_SUBJECT:
3637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                cursor = getConversationById(
3647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        uri.getPathSegments().get(1), projection, selection,
3657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        selectionArgs, sortOrder);
3667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
3677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_MESSAGES_BY_PHONE:
3687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                cursor = getMessagesByPhoneNumber(
36972f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                        uri.getPathSegments().get(2), projection, selection, sortOrder, smsTable,
37072f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                        pduTable);
3717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
3727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_THREAD_ID:
3737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                List<String> recipients = uri.getQueryParameters("recipient");
3747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
3757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                cursor = getThreadId(recipients);
3767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
3777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_CANONICAL_ADDRESS: {
3787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                String extraSelection = "_id=" + uri.getPathSegments().get(1);
3797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                String finalSelection = TextUtils.isEmpty(selection)
3807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        ? extraSelection : extraSelection + " AND " + selection;
3811ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                cursor = db.query(TABLE_CANONICAL_ADDRESSES,
3821ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                        CANONICAL_ADDRESSES_COLUMNS_1,
3831ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                        finalSelection,
3841ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                        selectionArgs,
3851ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                        null, null,
3861ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                        sortOrder);
3877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
3887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            }
38937e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick            case URI_CANONICAL_ADDRESSES:
3901ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                cursor = db.query(TABLE_CANONICAL_ADDRESSES,
3911ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                        CANONICAL_ADDRESSES_COLUMNS_2,
3921ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                        selection,
3931ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                        selectionArgs,
3941ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                        null, null,
3951ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                        sortOrder);
39637e4424493bb364eac8ae07c3d5fce52bebf735dFicus Kirkpatrick                break;
3978e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            case URI_SEARCH_SUGGEST: {
3983e1cba826743423642635cc7b03abe292470f4c4Tom Taylor                SEARCH_STRING[0] = uri.getQueryParameter("pattern") + '*' ;
3999e1fd44679b2de6df6af2c1e8b6bf191e799f4a9Mark Wagner
4009e1fd44679b2de6df6af2c1e8b6bf191e799f4a9Mark Wagner                // find the words which match the pattern using the snippet function.  The
4019e1fd44679b2de6df6af2c1e8b6bf191e799f4a9Mark Wagner                // snippet function parameters mainly describe how to format the result.
4029e1fd44679b2de6df6af2c1e8b6bf191e799f4a9Mark Wagner                // See http://www.sqlite.org/fts3.html#section_4_2 for details.
4038e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                if (       sortOrder != null
4048e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        || selection != null
4058e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        || selectionArgs != null
4068e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        || projection != null) {
4078e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    throw new IllegalArgumentException(
4088e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                            "do not specify sortOrder, selection, selectionArgs, or projection" +
4098e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                            "with this query");
4108e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                }
4118e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4123e1cba826743423642635cc7b03abe292470f4c4Tom Taylor                cursor = db.rawQuery(SEARCH_QUERY, SEARCH_STRING);
4138e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                break;
4148e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            }
4156a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner            case URI_MESSAGE_ID_TO_THREAD: {
4166a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                // Given a message ID and an indicator for SMS vs. MMS return
4176a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                // the thread id of the corresponding thread.
4186a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                try {
4196a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                    long id = Long.parseLong(uri.getQueryParameter("row_id"));
4206a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                    switch (Integer.parseInt(uri.getQueryParameter("table_to_use"))) {
4216a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                        case 1:  // sms
4226a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                            cursor = db.query(
42372f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                                smsTable,
4246a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                                new String[] { "thread_id" },
4256a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                                "_id=?",
4266a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                                new String[] { String.valueOf(id) },
4276a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                                null,
4286a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                                null,
4296a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                                null);
4306a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                            break;
4316a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                        case 2:  // mms
43272f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                            String mmsQuery = "SELECT thread_id "
43372f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                                    + "FROM " + pduTable + ",part "
43472f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                                    + "WHERE ((part.mid=" + pduTable + "._id) "
43572f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                                    + "AND " + "(part._id=?))";
4366a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                            cursor = db.rawQuery(mmsQuery, new String[] { String.valueOf(id) });
4376a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                            break;
4386a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                    }
4396a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                } catch (NumberFormatException ex) {
4406a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                    // ignore... return empty cursor
4416a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                }
4426a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner                break;
4436a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner            }
4448e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            case URI_SEARCH: {
44587bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor                if (       sortOrder != null
44687bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor                        || selection != null
44787bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor                        || selectionArgs != null
448f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                        || projection != null) {
449f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                    throw new IllegalArgumentException(
450f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            "do not specify sortOrder, selection, selectionArgs, or projection" +
451f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            "with this query");
45266d373c4797c53207e8f1ea97f3dc5541f390152Mark Wagner                }
45387bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor
4548e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                String searchString = uri.getQueryParameter("pattern") + "*";
4558e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4568e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                try {
45772f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                    cursor = db.rawQuery(getTextSearchQuery(smsTable, pduTable),
45872f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                            new String[] { searchString, searchString });
4598e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                } catch (Exception ex) {
4608e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    Log.e(LOG_TAG, "got exception: " + ex.toString());
4618e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                }
46266d373c4797c53207e8f1ea97f3dc5541f390152Mark Wagner                break;
4638e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            }
4647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_PENDING_MSG: {
4657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                String protoName = uri.getQueryParameter("protocol");
4667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                String msgId = uri.getQueryParameter("message");
4677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                int proto = TextUtils.isEmpty(protoName) ? -1
4687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        : (protoName.equals("sms") ? MmsSms.SMS_PROTO : MmsSms.MMS_PROTO);
4697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
4707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                String extraSelection = (proto != -1) ?
4717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        (PendingMessages.PROTO_TYPE + "=" + proto) : " 0=0 ";
4727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                if (!TextUtils.isEmpty(msgId)) {
4737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                    extraSelection += " AND " + PendingMessages.MSG_ID + "=" + msgId;
4747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                }
4757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
4767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                String finalSelection = TextUtils.isEmpty(selection)
4777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        ? extraSelection : ("(" + extraSelection + ") AND " + selection);
4787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                String finalOrder = TextUtils.isEmpty(sortOrder)
4797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        ? PendingMessages.DUE_TIME : sortOrder;
4807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                cursor = db.query(TABLE_PENDING_MSG, null,
4817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        finalSelection, selectionArgs, null, null, finalOrder);
4827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
4837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            }
4847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_UNDELIVERED_MSG: {
4857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                cursor = getUndeliveredMessages(projection, selection,
48672f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                        selectionArgs, sortOrder, smsTable, pduTable);
4877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
4887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            }
4897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_DRAFT: {
49072f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                cursor = getDraftThread(projection, selection, sortOrder, smsTable, pduTable);
4917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
4927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            }
493f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor            case URI_FIRST_LOCKED_MESSAGE_BY_THREAD_ID: {
494f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor                long threadId;
495f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor                try {
496f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor                    threadId = Long.parseLong(uri.getLastPathSegment());
497f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor                } catch (NumberFormatException e) {
498f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor                    Log.e(LOG_TAG, "Thread ID must be a long.");
499f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor                    break;
500f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor                }
501f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor                cursor = getFirstLockedMessage(projection, "thread_id=" + Long.toString(threadId),
50272f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                        sortOrder, smsTable, pduTable);
503f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor                break;
504f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor            }
505f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor            case URI_FIRST_LOCKED_MESSAGE_ALL: {
50672f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                cursor = getFirstLockedMessage(
50772f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                        projection, selection, sortOrder, smsTable, pduTable);
508f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor                break;
509f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor            }
5107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            default:
5117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                throw new IllegalStateException("Unrecognized URI:" + uri);
5127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
5137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5145926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor        if (cursor != null) {
5155926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor            cursor.setNotificationUri(getContext().getContentResolver(), MmsSms.CONTENT_URI);
5165926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor        }
5177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return cursor;
5187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
5197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
5217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Return the canonical address ID for this address.
5227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
5237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private long getSingleAddressId(String address) {
5247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        boolean isEmail = Mms.isEmailAddress(address);
525e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor        boolean isPhoneNumber = Mms.isPhoneNumber(address);
526e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor
527e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor        // We lowercase all email addresses, but not addresses that aren't numbers, because
528e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor        // that would incorrectly turn an address such as "My Vodafone" into "my vodafone"
529e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor        // and the thread title would be incorrect when displayed in the UI.
5307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String refinedAddress = isEmail ? address.toLowerCase() : address;
531e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor
532c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang        String selection = "address=?";
533c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang        String[] selectionArgs;
53414595cbe9045755a5aa2bd28989c147c4709268cWei Huang        long retVal = -1L;
535c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang
536e8a24ddaa58295f173fbf37fe3c0acb0d8569118Tom Taylor        if (!isPhoneNumber) {
537c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang            selectionArgs = new String[] { refinedAddress };
538c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang        } else {
53901c75ba95b875674a83128defc6b267e522db346Chen Mike            selection += " OR PHONE_NUMBERS_EQUAL(address, ?, " +
54001c75ba95b875674a83128defc6b267e522db346Chen Mike                        (mUseStrictPhoneNumberComparation ? 1 : 0) + ")";
541c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang            selectionArgs = new String[] { refinedAddress, refinedAddress };
542c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang        }
543c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang
5447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Cursor cursor = null;
5457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        try {
5477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            SQLiteDatabase db = mOpenHelper.getReadableDatabase();
5487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            cursor = db.query(
5497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                    "canonical_addresses", ID_PROJECTION,
5507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                    selection, selectionArgs, null, null, null);
5517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            if (cursor.getCount() == 0) {
5537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                ContentValues contentValues = new ContentValues(1);
5547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                contentValues.put(CanonicalAddressesColumns.ADDRESS, refinedAddress);
5557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                db = mOpenHelper.getWritableDatabase();
55714595cbe9045755a5aa2bd28989c147c4709268cWei Huang                retVal = db.insert("canonical_addresses",
5587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        CanonicalAddressesColumns.ADDRESS, contentValues);
55914595cbe9045755a5aa2bd28989c147c4709268cWei Huang
560ea59f86662471e682f880b4916ce7588803f5605Wink Saville                Log.d(LOG_TAG, "getSingleAddressId: insert new canonical_address for " +
561ea59f86662471e682f880b4916ce7588803f5605Wink Saville                        /*address*/ "xxxxxx" + ", _id=" + retVal);
56214595cbe9045755a5aa2bd28989c147c4709268cWei Huang
56314595cbe9045755a5aa2bd28989c147c4709268cWei Huang                return retVal;
5647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            }
5657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            if (cursor.moveToFirst()) {
56714595cbe9045755a5aa2bd28989c147c4709268cWei Huang                retVal = cursor.getLong(cursor.getColumnIndexOrThrow(BaseColumns._ID));
5687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            }
5697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        } finally {
5707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            if (cursor != null) {
5717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                cursor.close();
5727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            }
5737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
5747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
57514595cbe9045755a5aa2bd28989c147c4709268cWei Huang        return retVal;
5767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
5777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
5797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Return the canonical address IDs for these addresses.
5807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
5817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private Set<Long> getAddressIds(List<String> addresses) {
5827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Set<Long> result = new HashSet<Long>(addresses.size());
5837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        for (String address : addresses) {
5857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            if (!address.equals(PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR)) {
5867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                long id = getSingleAddressId(address);
5877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                if (id != -1L) {
5887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                    result.add(id);
5897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                } else {
59014595cbe9045755a5aa2bd28989c147c4709268cWei Huang                    Log.e(LOG_TAG, "getAddressIds: address ID not found for " + address);
5917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                }
5927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            }
5937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
5947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return result;
5957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
5967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
5977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
5987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Return a sorted array of the given Set of Longs.
5997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
6007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private long[] getSortedSet(Set<Long> numbers) {
6017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int size = numbers.size();
6027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        long[] result = new long[size];
6037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int i = 0;
6047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        for (Long number : numbers) {
6067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            result[i++] = number;
6077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
60814595cbe9045755a5aa2bd28989c147c4709268cWei Huang
60914595cbe9045755a5aa2bd28989c147c4709268cWei Huang        if (size > 1) {
61014595cbe9045755a5aa2bd28989c147c4709268cWei Huang            Arrays.sort(result);
61114595cbe9045755a5aa2bd28989c147c4709268cWei Huang        }
61214595cbe9045755a5aa2bd28989c147c4709268cWei Huang
6137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return result;
6147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
6157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
6177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Return a String of the numbers in the given array, in order,
6187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * separated by spaces.
6197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
6207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private String getSpaceSeparatedNumbers(long[] numbers) {
6217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int size = numbers.length;
6227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        StringBuilder buffer = new StringBuilder();
6237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        for (int i = 0; i < size; i++) {
6257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            if (i != 0) {
6267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                buffer.append(' ');
6277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            }
6287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            buffer.append(numbers[i]);
6297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
6307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return buffer.toString();
6317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
6327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
6347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Insert a record for a new thread.
6357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
6367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void insertThread(String recipientIds, int numberOfRecipients) {
6377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        ContentValues values = new ContentValues(4);
6387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        long date = System.currentTimeMillis();
6407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        values.put(ThreadsColumns.DATE, date - date % 1000);
6417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        values.put(ThreadsColumns.RECIPIENT_IDS, recipientIds);
6427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        if (numberOfRecipients > 1) {
6437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            values.put(Threads.TYPE, Threads.BROADCAST_THREAD);
6447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
6457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        values.put(ThreadsColumns.MESSAGE_COUNT, 0);
6467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
64715156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor        long result = mOpenHelper.getWritableDatabase().insert(TABLE_THREADS, null, values);
64814595cbe9045755a5aa2bd28989c147c4709268cWei Huang        Log.d(LOG_TAG, "insertThread: created new thread_id " + result +
649ea59f86662471e682f880b4916ce7588803f5605Wink Saville                " for recipientIds " + /*recipientIds*/ "xxxxxxx");
65014595cbe9045755a5aa2bd28989c147c4709268cWei Huang
65143f9fb234aabe569b342af78bdaf85effbd85f10Amith Yamasani        getContext().getContentResolver().notifyChange(MmsSms.CONTENT_URI, null, true,
65243f9fb234aabe569b342af78bdaf85effbd85f10Amith Yamasani                UserHandle.USER_ALL);
6537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
6547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
65514595cbe9045755a5aa2bd28989c147c4709268cWei Huang    private static final String THREAD_QUERY =
65614595cbe9045755a5aa2bd28989c147c4709268cWei Huang            "SELECT _id FROM threads " + "WHERE recipient_ids=?";
65714595cbe9045755a5aa2bd28989c147c4709268cWei Huang
6587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
6597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Return the thread ID for this list of
6607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * recipients IDs.  If no thread exists with this ID, create
6617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * one and return it.  Callers should always use
6627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Threads.getThreadId to access this information.
6637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
6647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private synchronized Cursor getThreadId(List<String> recipients) {
66514595cbe9045755a5aa2bd28989c147c4709268cWei Huang        Set<Long> addressIds = getAddressIds(recipients);
66614595cbe9045755a5aa2bd28989c147c4709268cWei Huang        String recipientIds = "";
667c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang
6685926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor        if (addressIds.size() == 0) {
6695926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor            Log.e(LOG_TAG, "getThreadId: NO receipients specified -- NOT creating thread",
6705926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor                    new Exception());
6715926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor            return null;
6725926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor        } else if (addressIds.size() == 1) {
6735926996da70fff9275e948d1cf8a0f17b52a5e14Tom Taylor            // optimize for size==1, which should be most of the cases
67414595cbe9045755a5aa2bd28989c147c4709268cWei Huang            for (Long addressId : addressIds) {
67514595cbe9045755a5aa2bd28989c147c4709268cWei Huang                recipientIds = Long.toString(addressId);
67614595cbe9045755a5aa2bd28989c147c4709268cWei Huang            }
67714595cbe9045755a5aa2bd28989c147c4709268cWei Huang        } else {
67814595cbe9045755a5aa2bd28989c147c4709268cWei Huang            recipientIds = getSpaceSeparatedNumbers(getSortedSet(addressIds));
67914595cbe9045755a5aa2bd28989c147c4709268cWei Huang        }
6807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
68114595cbe9045755a5aa2bd28989c147c4709268cWei Huang        if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
682ea59f86662471e682f880b4916ce7588803f5605Wink Saville            Log.d(LOG_TAG, "getThreadId: recipientIds (selectionArgs) =" +
683ea59f86662471e682f880b4916ce7588803f5605Wink Saville                    /*recipientIds*/ "xxxxxxx");
684b4ac04f7bd9d4f16ec181f368c42f89c96f83f55Tom Taylor        }
68514595cbe9045755a5aa2bd28989c147c4709268cWei Huang
68614595cbe9045755a5aa2bd28989c147c4709268cWei Huang        String[] selectionArgs = new String[] { recipientIds };
68715156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor
6887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
68915156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor        db.beginTransaction();
69015156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor        Cursor cursor = null;
69115156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor        try {
69215156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor            // Find the thread with the given recipients
69315156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor            cursor = db.rawQuery(THREAD_QUERY, selectionArgs);
6947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
69515156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor            if (cursor.getCount() == 0) {
69615156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor                // No thread with those recipients exists, so create the thread.
69715156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor                cursor.close();
69814595cbe9045755a5aa2bd28989c147c4709268cWei Huang
69915156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor                Log.d(LOG_TAG, "getThreadId: create new thread_id for recipients " +
70015156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor                        /*recipients*/ "xxxxxxxx");
70115156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor                insertThread(recipientIds, recipients.size());
70214595cbe9045755a5aa2bd28989c147c4709268cWei Huang
70315156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor                // The thread was just created, now find it and return it.
70415156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor                cursor = db.rawQuery(THREAD_QUERY, selectionArgs);
70515156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor            }
70615156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor            db.setTransactionSuccessful();
70715156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor        } catch (Throwable ex) {
70815156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor            Log.e(LOG_TAG, ex.getMessage(), ex);
70915156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor        } finally {
71015156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor            db.endTransaction();
7117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
7126a917909c55d1535f8d5a213a4dadf19bc79b1b8Mark Wagner
71315156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor        if (cursor != null && cursor.getCount() > 1) {
71414595cbe9045755a5aa2bd28989c147c4709268cWei Huang            Log.w(LOG_TAG, "getThreadId: why is cursorCount=" + cursor.getCount());
71569e6ffada415d44c72d908ad9e152da51b190642Tom Taylor        }
7167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return cursor;
7177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
7187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static String concatSelections(String selection1, String selection2) {
7207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        if (TextUtils.isEmpty(selection1)) {
7217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            return selection2;
7227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        } else if (TextUtils.isEmpty(selection2)) {
7237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            return selection1;
7247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        } else {
7257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            return selection1 + " AND " + selection2;
7267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
7277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
7287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
7307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * If a null projection is given, return the union of all columns
7317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * in both the MMS and SMS messages tables.  Otherwise, return the
7327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * given projection.
7337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
7347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static String[] handleNullMessageProjection(
7357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            String[] projection) {
7367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return projection == null ? UNION_COLUMNS : projection;
7377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
7387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
7407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * If a null projection is given, return the set of all columns in
7417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * the threads table.  Otherwise, return the given projection.
7427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
7437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static String[] handleNullThreadsProjection(
7447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            String[] projection) {
7457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return projection == null ? THREADS_COLUMNS : projection;
7467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
7477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
7497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * If a null sort order is given, return "normalized_date ASC".
7507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Otherwise, return the given sort order.
7517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
7527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static String handleNullSortOrder (String sortOrder) {
7537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return sortOrder == null ? "normalized_date ASC" : sortOrder;
7547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
7557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
7577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Return existing threads in the database.
7587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
7597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private Cursor getSimpleConversations(String[] projection, String selection,
7607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            String[] selectionArgs, String sortOrder) {
76115156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor        return mOpenHelper.getReadableDatabase().query(TABLE_THREADS, projection,
7627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                selection, selectionArgs, null, null, " date DESC");
7637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
7647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
7667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Return the thread which has draft in both MMS and SMS.
7677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *
7687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Use this query:
7697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *
7707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *   SELECT ...
7717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *     FROM (SELECT _id, thread_id, ...
7727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *             FROM pdu
7737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *             WHERE msg_box = 3 AND ...
7747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *           UNION
7757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *           SELECT _id, thread_id, ...
7767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *             FROM sms
7777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *             WHERE type = 3 AND ...
7787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *          )
7797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *   ;
7807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
7817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private Cursor getDraftThread(String[] projection, String selection,
78272f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen            String sortOrder, String smsTable, String pduTable) {
7837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] innerProjection = new String[] {BaseColumns._ID, Conversations.THREAD_ID};
7847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder();
7857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder();
7867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
78772f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        mmsQueryBuilder.setTables(pduTable);
78872f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        smsQueryBuilder.setTables(smsTable);
7897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
7907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery(
7917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerProjection,
7927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                MMS_COLUMNS, 1, "mms",
7937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                concatSelections(selection, Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_DRAFTS),
794f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                null, null);
7957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String smsSubQuery = smsQueryBuilder.buildUnionSubQuery(
7967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerProjection,
7977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                SMS_COLUMNS, 1, "sms",
7987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                concatSelections(selection, Sms.TYPE + "=" + Sms.MESSAGE_TYPE_DRAFT),
799f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                null, null);
8007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder();
8017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        unionQueryBuilder.setDistinct(true);
8037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String unionQuery = unionQueryBuilder.buildUnionQuery(
8057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                new String[] { mmsSubQuery, smsSubQuery }, null, null);
8067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder outerQueryBuilder = new SQLiteQueryBuilder();
8087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        outerQueryBuilder.setTables("(" + unionQuery + ")");
8107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String outerQuery = outerQueryBuilder.buildQuery(
812f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                projection, null, null, null, sortOrder, null);
8137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return mOpenHelper.getReadableDatabase().rawQuery(outerQuery, EMPTY_STRING_ARRAY);
8157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
8167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
8187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Return the most recent message in each conversation in both MMS
8197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * and SMS.
8207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *
8217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Use this query:
8227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *
8237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *   SELECT ...
8247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *     FROM (SELECT thread_id AS tid, date * 1000 AS normalized_date, ...
8257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *             FROM pdu
8267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *             WHERE msg_box != 3 AND ...
8277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *             GROUP BY thread_id
8287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *             HAVING date = MAX(date)
8297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *           UNION
8307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *           SELECT thread_id AS tid, date AS normalized_date, ...
8317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *             FROM sms
8327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *             WHERE ...
8337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *             GROUP BY thread_id
8347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *             HAVING date = MAX(date))
8357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *     GROUP BY tid
8367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *     HAVING normalized_date = MAX(normalized_date);
8377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *
8387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * The msg_box != 3 comparisons ensure that we don't include draft
8397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * messages.
8407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
8417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private Cursor getConversations(String[] projection, String selection,
84272f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen            String sortOrder, String smsTable, String pduTable) {
8437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder();
8447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder();
8457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
84672f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        mmsQueryBuilder.setTables(pduTable);
84772f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        smsQueryBuilder.setTables(smsTable);
8487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] columns = handleNullMessageProjection(projection);
8507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] innerMmsProjection = makeProjectionWithDateAndThreadId(
8517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                UNION_COLUMNS, 1000);
8527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] innerSmsProjection = makeProjectionWithDateAndThreadId(
8537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                UNION_COLUMNS, 1);
8547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery(
8557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerMmsProjection,
8567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                MMS_COLUMNS, 1, "mms",
857f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                concatSelections(selection, MMS_CONVERSATION_CONSTRAINT),
8587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                "thread_id", "date = MAX(date)");
8597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String smsSubQuery = smsQueryBuilder.buildUnionSubQuery(
8607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerSmsProjection,
8617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                SMS_COLUMNS, 1, "sms",
862f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                concatSelections(selection, SMS_CONVERSATION_CONSTRAINT),
8637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                "thread_id", "date = MAX(date)");
8647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder();
8657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        unionQueryBuilder.setDistinct(true);
8677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String unionQuery = unionQueryBuilder.buildUnionQuery(
8697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                new String[] { mmsSubQuery, smsSubQuery }, null, null);
8707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder outerQueryBuilder = new SQLiteQueryBuilder();
8727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        outerQueryBuilder.setTables("(" + unionQuery + ")");
8747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String outerQuery = outerQueryBuilder.buildQuery(
876f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                columns, null, "tid",
8777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                "normalized_date = MAX(normalized_date)", sortOrder, null);
8787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return mOpenHelper.getReadableDatabase().rawQuery(outerQuery, EMPTY_STRING_ARRAY);
8807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
8817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
883f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor     * Return the first locked message found in the union of MMS
884f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor     * and SMS messages.
885f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor     *
886f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor     * Use this query:
887f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor     *
888816e934a43bf705835bdb24503a85a14c4861991Tom Taylor     *  SELECT _id FROM pdu GROUP BY _id HAVING locked=1 UNION SELECT _id FROM sms GROUP
889816e934a43bf705835bdb24503a85a14c4861991Tom Taylor     *      BY _id HAVING locked=1 LIMIT 1
890f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor     *
891816e934a43bf705835bdb24503a85a14c4861991Tom Taylor     * We limit by 1 because we're only interested in knowing if
892f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor     * there is *any* locked message, not the actual messages themselves.
893f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor     */
894f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    private Cursor getFirstLockedMessage(String[] projection, String selection,
89572f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen            String sortOrder, String smsTable, String pduTable) {
896f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor        SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder();
897f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor        SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder();
898f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor
89972f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        mmsQueryBuilder.setTables(pduTable);
90072f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        smsQueryBuilder.setTables(smsTable);
901f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor
902816e934a43bf705835bdb24503a85a14c4861991Tom Taylor        String[] idColumn = new String[] { BaseColumns._ID };
903816e934a43bf705835bdb24503a85a14c4861991Tom Taylor
904f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor        // NOTE: buildUnionSubQuery *ignores* selectionArgs
905f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor        String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery(
906816e934a43bf705835bdb24503a85a14c4861991Tom Taylor                MmsSms.TYPE_DISCRIMINATOR_COLUMN, idColumn,
907816e934a43bf705835bdb24503a85a14c4861991Tom Taylor                null, 1, "mms",
908f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                selection,
909816e934a43bf705835bdb24503a85a14c4861991Tom Taylor                BaseColumns._ID, "locked=1");
910816e934a43bf705835bdb24503a85a14c4861991Tom Taylor
911f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor        String smsSubQuery = smsQueryBuilder.buildUnionSubQuery(
912816e934a43bf705835bdb24503a85a14c4861991Tom Taylor                MmsSms.TYPE_DISCRIMINATOR_COLUMN, idColumn,
913816e934a43bf705835bdb24503a85a14c4861991Tom Taylor                null, 1, "sms",
914f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                selection,
915816e934a43bf705835bdb24503a85a14c4861991Tom Taylor                BaseColumns._ID, "locked=1");
916816e934a43bf705835bdb24503a85a14c4861991Tom Taylor
917f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor        SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder();
918f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor
919f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor        unionQueryBuilder.setDistinct(true);
920f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor
921f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor        String unionQuery = unionQueryBuilder.buildUnionQuery(
922816e934a43bf705835bdb24503a85a14c4861991Tom Taylor                new String[] { mmsSubQuery, smsSubQuery }, null, "1");
923f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor
924816e934a43bf705835bdb24503a85a14c4861991Tom Taylor        Cursor cursor = mOpenHelper.getReadableDatabase().rawQuery(unionQuery, EMPTY_STRING_ARRAY);
925f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor
926f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor        if (DEBUG) {
927816e934a43bf705835bdb24503a85a14c4861991Tom Taylor            Log.v("MmsSmsProvider", "getFirstLockedMessage query: " + unionQuery);
928816e934a43bf705835bdb24503a85a14c4861991Tom Taylor            Log.v("MmsSmsProvider", "cursor count: " + cursor.getCount());
929f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor        }
930816e934a43bf705835bdb24503a85a14c4861991Tom Taylor        return cursor;
931f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    }
932f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor
933f0a7f15a4e5ef5a1d9cb5bb509cbbaac80b1297dTom Taylor    /**
9347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Return every message in each conversation in both MMS
9357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * and SMS.
9367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
9377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private Cursor getCompleteConversations(String[] projection,
93872f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen            String selection, String sortOrder, String smsTable, String pduTable) {
93972f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        String unionQuery = buildConversationQuery(projection, selection, sortOrder, smsTable,
94072f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                pduTable);
9417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return mOpenHelper.getReadableDatabase().rawQuery(unionQuery, EMPTY_STRING_ARRAY);
9437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
9447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
9467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Add normalized date and thread_id to the list of columns for an
9477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * inner projection.  This is necessary so that the outer query
9487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * can have access to these columns even if the caller hasn't
9497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * requested them in the result.
9507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
9517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private String[] makeProjectionWithDateAndThreadId(
9527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            String[] projection, int dateMultiple) {
9537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int projectionSize = projection.length;
9547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] result = new String[projectionSize + 2];
9557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        result[0] = "thread_id AS tid";
9577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        result[1] = "date * " + dateMultiple + " AS normalized_date";
9587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        for (int i = 0; i < projectionSize; i++) {
9597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            result[i + 2] = projection[i];
9607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
9617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return result;
9627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
9637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
9657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Return the union of MMS and SMS messages for this thread ID.
9667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
9677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private Cursor getConversationMessages(
9687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            String threadIdString, String[] projection, String selection,
96972f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen            String sortOrder, String smsTable, String pduTable) {
9707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        try {
9717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            Long.parseLong(threadIdString);
9727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        } catch (NumberFormatException exception) {
9737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            Log.e(LOG_TAG, "Thread ID must be a Long.");
9747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            return null;
9757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
9767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String finalSelection = concatSelections(
9787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                selection, "thread_id = " + threadIdString);
97972f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        String unionQuery = buildConversationQuery(projection, finalSelection, sortOrder, smsTable,
98072f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                pduTable);
9817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return mOpenHelper.getReadableDatabase().rawQuery(unionQuery, EMPTY_STRING_ARRAY);
9837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
9847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
9867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Return the union of MMS and SMS messages whose recipients
9877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * included this phone number.
9887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *
9897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Use this query:
9907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *
9917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * SELECT ...
992670c495b6e0489569f60a38a79770dd4ac44500awhliang     *   FROM pdu, (SELECT msg_id AS address_msg_id
9937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *              FROM addr
994c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang     *              WHERE (address='<phoneNumber>' OR
995c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang     *              PHONE_NUMBERS_EQUAL(addr.address, '<phoneNumber>', 1/0)))
9967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *             AS matching_addresses
997670c495b6e0489569f60a38a79770dd4ac44500awhliang     *   WHERE pdu._id = matching_addresses.address_msg_id
9987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * UNION
9997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * SELECT ...
10007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     *   FROM sms
1001c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang     *   WHERE (address='<phoneNumber>' OR PHONE_NUMBERS_EQUAL(sms.address, '<phoneNumber>', 1/0));
10027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
10037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private Cursor getMessagesByPhoneNumber(
10047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            String phoneNumber, String[] projection, String selection,
100572f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen            String sortOrder, String smsTable, String pduTable) {
10067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String escapedPhoneNumber = DatabaseUtils.sqlEscapeString(phoneNumber);
10077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String finalMmsSelection =
10087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                concatSelections(
10097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        selection,
101072f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                        pduTable + "._id = matching_addresses.address_msg_id");
10117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String finalSmsSelection =
10127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                concatSelections(
10137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        selection,
1014c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang                        "(address=" + escapedPhoneNumber + " OR PHONE_NUMBERS_EQUAL(address, " +
1015845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa                        escapedPhoneNumber +
1016c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang                        (mUseStrictPhoneNumberComparation ? ", 1))" : ", 0))"));
10177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder();
10187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder();
10197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
10207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        mmsQueryBuilder.setDistinct(true);
10217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        smsQueryBuilder.setDistinct(true);
10227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        mmsQueryBuilder.setTables(
102372f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                pduTable +
1024670c495b6e0489569f60a38a79770dd4ac44500awhliang                ", (SELECT msg_id AS address_msg_id " +
1025c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang                "FROM addr WHERE (address=" + escapedPhoneNumber +
1026c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang                " OR PHONE_NUMBERS_EQUAL(addr.address, " +
1027845a9163dffcbd1073930b8b334df27728418201Daisuke Miyakawa                escapedPhoneNumber +
1028c818d636af8c4f3d8a0d332634d1e73a5215d06bWei Huang                (mUseStrictPhoneNumberComparation ? ", 1))) " : ", 0))) ") +
10297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                "AS matching_addresses");
103072f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        smsQueryBuilder.setTables(smsTable);
10317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
10327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] columns = handleNullMessageProjection(projection);
10337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery(
10347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                MmsSms.TYPE_DISCRIMINATOR_COLUMN, columns, MMS_COLUMNS,
1035f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                0, "mms", finalMmsSelection, null, null);
10367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String smsSubQuery = smsQueryBuilder.buildUnionSubQuery(
10377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                MmsSms.TYPE_DISCRIMINATOR_COLUMN, columns, SMS_COLUMNS,
1038f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                0, "sms", finalSmsSelection, null, null);
10397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder();
10407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
10417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        unionQueryBuilder.setDistinct(true);
10427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
10437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String unionQuery = unionQueryBuilder.buildUnionQuery(
10447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                new String[] { mmsSubQuery, smsSubQuery }, sortOrder, null);
10457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
10467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return mOpenHelper.getReadableDatabase().rawQuery(unionQuery, EMPTY_STRING_ARRAY);
10477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
10487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
10497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
10507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Return the conversation of certain thread ID.
10517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
10527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private Cursor getConversationById(
10537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            String threadIdString, String[] projection, String selection,
10547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            String[] selectionArgs, String sortOrder) {
10557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        try {
10567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            Long.parseLong(threadIdString);
10577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        } catch (NumberFormatException exception) {
10587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            Log.e(LOG_TAG, "Thread ID must be a Long.");
10597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            return null;
10607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
10617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
10627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String extraSelection = "_id=" + threadIdString;
10637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String finalSelection = concatSelections(selection, extraSelection);
10647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
10657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] columns = handleNullThreadsProjection(projection);
10667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
10677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        queryBuilder.setDistinct(true);
106815156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor        queryBuilder.setTables(TABLE_THREADS);
10697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return queryBuilder.query(
10707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                mOpenHelper.getReadableDatabase(), columns, finalSelection,
10717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                selectionArgs, sortOrder, null, null);
10727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
10737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
107472f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen    private static String joinPduAndPendingMsgTables(String pduTable) {
107572f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        return pduTable + " LEFT JOIN " + TABLE_PENDING_MSG
107672f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                + " ON " + pduTable + "._id = pending_msgs.msg_id";
10777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
10787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
107972f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen    private static String[] createMmsProjection(String[] old, String pduTable) {
10807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] newProjection = new String[old.length];
10817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        for (int i = 0; i < old.length; i++) {
10827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            if (old[i].equals(BaseColumns._ID)) {
108372f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                newProjection[i] = pduTable + "._id";
10847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            } else {
10857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                newProjection[i] = old[i];
10867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            }
10877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
10887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return newProjection;
10897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
10907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
10917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private Cursor getUndeliveredMessages(
10927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            String[] projection, String selection, String[] selectionArgs,
109372f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen            String sortOrder, String smsTable, String pduTable) {
109472f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        String[] mmsProjection = createMmsProjection(projection, pduTable);
10957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
10967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder();
10977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder();
10987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
109972f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        mmsQueryBuilder.setTables(joinPduAndPendingMsgTables(pduTable));
110072f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        smsQueryBuilder.setTables(smsTable);
11017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String finalMmsSelection = concatSelections(
11037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                selection, Mms.MESSAGE_BOX + " = " + Mms.MESSAGE_BOX_OUTBOX);
11047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String finalSmsSelection = concatSelections(
11057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                selection, "(" + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_OUTBOX
11067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                + " OR " + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_FAILED
11077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                + " OR " + Sms.TYPE + " = " + Sms.MESSAGE_TYPE_QUEUED + ")");
11087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] smsColumns = handleNullMessageProjection(projection);
11107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] mmsColumns = handleNullMessageProjection(mmsProjection);
11117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] innerMmsProjection = makeProjectionWithDateAndThreadId(
11127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                mmsColumns, 1000);
11137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] innerSmsProjection = makeProjectionWithDateAndThreadId(
11147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                smsColumns, 1);
11157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Set<String> columnsPresentInTable = new HashSet<String>(MMS_COLUMNS);
111772f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        columnsPresentInTable.add(pduTable + "._id");
11187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        columnsPresentInTable.add(PendingMessages.ERROR_TYPE);
11197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery(
11207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerMmsProjection,
1121f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                columnsPresentInTable, 1, "mms", finalMmsSelection,
11227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                null, null);
11237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String smsSubQuery = smsQueryBuilder.buildUnionSubQuery(
11247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerSmsProjection,
1125f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                SMS_COLUMNS, 1, "sms", finalSmsSelection,
11267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                null, null);
11277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder();
11287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        unionQueryBuilder.setDistinct(true);
11307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String unionQuery = unionQueryBuilder.buildUnionQuery(
11327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                new String[] { smsSubQuery, mmsSubQuery }, null, null);
11337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder outerQueryBuilder = new SQLiteQueryBuilder();
11357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        outerQueryBuilder.setTables("(" + unionQuery + ")");
11377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String outerQuery = outerQueryBuilder.buildQuery(
1139f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                smsColumns, null, null, null, sortOrder, null);
11407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return mOpenHelper.getReadableDatabase().rawQuery(outerQuery, EMPTY_STRING_ARRAY);
11427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
11437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
11457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Add normalized date to the list of columns for an inner
11467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * projection.
11477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
11487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static String[] makeProjectionWithNormalizedDate(
11497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            String[] projection, int dateMultiple) {
11507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int projectionSize = projection.length;
11517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] result = new String[projectionSize + 1];
11527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        result[0] = "date * " + dateMultiple + " AS normalized_date";
11547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        System.arraycopy(projection, 0, result, 1, projectionSize);
11557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return result;
11567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
11577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static String buildConversationQuery(String[] projection,
115972f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen            String selection, String sortOrder, String smsTable, String pduTable) {
116072f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        String[] mmsProjection = createMmsProjection(projection, pduTable);
11617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder();
11637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder();
11647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        mmsQueryBuilder.setDistinct(true);
11667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        smsQueryBuilder.setDistinct(true);
116772f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        mmsQueryBuilder.setTables(joinPduAndPendingMsgTables(pduTable));
116872f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        smsQueryBuilder.setTables(smsTable);
11697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] smsColumns = handleNullMessageProjection(projection);
11717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] mmsColumns = handleNullMessageProjection(mmsProjection);
11727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] innerMmsProjection = makeProjectionWithNormalizedDate(mmsColumns, 1000);
11737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String[] innerSmsProjection = makeProjectionWithNormalizedDate(smsColumns, 1);
11747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Set<String> columnsPresentInTable = new HashSet<String>(MMS_COLUMNS);
117672f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        columnsPresentInTable.add(pduTable + "._id");
11777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        columnsPresentInTable.add(PendingMessages.ERROR_TYPE);
11787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String mmsSelection = concatSelections(selection,
11807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                                Mms.MESSAGE_BOX + " != " + Mms.MESSAGE_BOX_DRAFTS);
11817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery(
11827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerMmsProjection,
11837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                columnsPresentInTable, 0, "mms",
11847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                concatSelections(mmsSelection, MMS_CONVERSATION_CONSTRAINT),
1185f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                null, null);
11867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String smsSubQuery = smsQueryBuilder.buildUnionSubQuery(
11877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerSmsProjection, SMS_COLUMNS,
11887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                0, "sms", concatSelections(selection, SMS_CONVERSATION_CONSTRAINT),
1189f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                null, null);
11907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder();
11917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        unionQueryBuilder.setDistinct(true);
11937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String unionQuery = unionQueryBuilder.buildUnionQuery(
11957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                new String[] { smsSubQuery, mmsSubQuery },
11967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                handleNullSortOrder(sortOrder), null);
11977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
11987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteQueryBuilder outerQueryBuilder = new SQLiteQueryBuilder();
11997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
12007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        outerQueryBuilder.setTables("(" + unionQuery + ")");
12017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
12027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return outerQueryBuilder.buildQuery(
1203f008a619299d15bab78b989aef301d97a3930ca3Tom Taylor                smsColumns, null, null, null, sortOrder, null);
12047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
12057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
12067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    @Override
12077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public String getType(Uri uri) {
12087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return VND_ANDROID_DIR_MMS_SMS;
12097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
12107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
12117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    @Override
12127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public int delete(Uri uri, String selection,
12137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            String[] selectionArgs) {
12147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
12157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Context context = getContext();
12167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int affectedRows = 0;
1217f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
12187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        switch(URI_MATCHER.match(uri)) {
12197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_CONVERSATIONS_MESSAGES:
12207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                long threadId;
12217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                try {
12227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                    threadId = Long.parseLong(uri.getLastPathSegment());
12237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                } catch (NumberFormatException e) {
12247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                    Log.e(LOG_TAG, "Thread ID must be a long.");
12257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                    break;
12267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                }
12277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                affectedRows = deleteConversation(uri, selection, selectionArgs);
12287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                MmsSmsDatabaseHelper.updateThread(db, threadId);
12297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
12307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_CONVERSATIONS:
12317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                affectedRows = MmsProvider.deleteMessages(context, db,
12327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                                        selection, selectionArgs, uri)
12337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        + db.delete("sms", selection, selectionArgs);
123487bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor                // Intentionally don't pass the selection variable to updateAllThreads.
123587bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor                // When we pass in "locked=0" there, the thread will get excluded from
123687bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor                // the selection and not get updated.
123787bfe142b5c163e19fb9e60d558bbeb513ca150cTom Taylor                MmsSmsDatabaseHelper.updateAllThreads(db, null, null);
12387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
12397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_OBSOLETE_THREADS:
124015156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor                affectedRows = db.delete(TABLE_THREADS,
12414b14c35e9e44d5df2b5340141f2b24bab351c603Tom Taylor                        "_id NOT IN (SELECT DISTINCT thread_id FROM sms where thread_id NOT NULL " +
12424b14c35e9e44d5df2b5340141f2b24bab351c603Tom Taylor                        "UNION SELECT DISTINCT thread_id FROM pdu where thread_id NOT NULL)", null);
12437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
12447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            default:
1245b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor                throw new UnsupportedOperationException(NO_DELETES_INSERTS_OR_UPDATES + uri);
12467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
12477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
12487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        if (affectedRows > 0) {
124943f9fb234aabe569b342af78bdaf85effbd85f10Amith Yamasani            context.getContentResolver().notifyChange(MmsSms.CONTENT_URI, null, true,
125043f9fb234aabe569b342af78bdaf85effbd85f10Amith Yamasani                    UserHandle.USER_ALL);
12517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
12527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return affectedRows;
12537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
12547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
12557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
12567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Delete the conversation with the given thread ID.
12577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
12587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private int deleteConversation(Uri uri, String selection, String[] selectionArgs) {
12597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String threadId = uri.getLastPathSegment();
12607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
12617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
12627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String finalSelection = concatSelections(selection, "thread_id = " + threadId);
12637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return MmsProvider.deleteMessages(getContext(), db, finalSelection,
12647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                                          selectionArgs, uri)
12657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                + db.delete("sms", finalSelection, selectionArgs);
12667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
12677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
12687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    @Override
12697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public Uri insert(Uri uri, ContentValues values) {
1270b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor        if (URI_MATCHER.match(uri) == URI_PENDING_MSG) {
1271b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor            SQLiteDatabase db = mOpenHelper.getWritableDatabase();
1272b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor            long rowId = db.insert(TABLE_PENDING_MSG, null, values);
1273b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor            return Uri.parse(uri + "/" + rowId);
1274b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor        }
1275b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor        throw new UnsupportedOperationException(NO_DELETES_INSERTS_OR_UPDATES + uri);
12767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
12777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
12787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    @Override
12797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public int update(Uri uri, ContentValues values,
12807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            String selection, String[] selectionArgs) {
1281e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen        final int callerUid = Binder.getCallingUid();
128272f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen        final String callerPkg = getCallingPackage();
12837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
12847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int affectedRows = 0;
12857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        switch(URI_MATCHER.match(uri)) {
12867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_CONVERSATIONS_MESSAGES:
12877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                String threadIdString = uri.getPathSegments().get(1);
12887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                affectedRows = updateConversation(threadIdString, values,
128972f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen                        selection, selectionArgs, callerUid, callerPkg);
12907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
12911ecf192c60625c5227336430ee36705c13ae06e2Wei Huang
12927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            case URI_PENDING_MSG:
12937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                affectedRows = db.update(TABLE_PENDING_MSG, values, selection, null);
12947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                break;
12951ecf192c60625c5227336430ee36705c13ae06e2Wei Huang
12961ecf192c60625c5227336430ee36705c13ae06e2Wei Huang            case URI_CANONICAL_ADDRESS: {
12971ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                String extraSelection = "_id=" + uri.getPathSegments().get(1);
12981ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                String finalSelection = TextUtils.isEmpty(selection)
12991ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                        ? extraSelection : extraSelection + " AND " + selection;
13001ecf192c60625c5227336430ee36705c13ae06e2Wei Huang
13011ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                affectedRows = db.update(TABLE_CANONICAL_ADDRESSES, values, finalSelection, null);
13021ecf192c60625c5227336430ee36705c13ae06e2Wei Huang                break;
13031ecf192c60625c5227336430ee36705c13ae06e2Wei Huang            }
13041ecf192c60625c5227336430ee36705c13ae06e2Wei Huang
130582fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen            case URI_CONVERSATIONS: {
130682fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                final ContentValues finalValues = new ContentValues(1);
130782fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                if (values.containsKey(Threads.ARCHIVED)) {
130882fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                    // Only allow update archived
130982fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                    finalValues.put(Threads.ARCHIVED, values.getAsBoolean(Threads.ARCHIVED));
131082fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                }
131182fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                affectedRows = db.update(TABLE_THREADS, finalValues, selection, selectionArgs);
131282fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                break;
131382fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen            }
131482fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen
13157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            default:
13167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                throw new UnsupportedOperationException(
1317b91bcae9fa009787f165591fd7fc4c8f2f2dfd99Tom Taylor                        NO_DELETES_INSERTS_OR_UPDATES + uri);
13187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
13197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
13207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        if (affectedRows > 0) {
13217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            getContext().getContentResolver().notifyChange(
132243f9fb234aabe569b342af78bdaf85effbd85f10Amith Yamasani                    MmsSms.CONTENT_URI, null, true, UserHandle.USER_ALL);
13237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
13247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return affectedRows;
13257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
13267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
132772f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen    private int updateConversation(String threadIdString, ContentValues values, String selection,
132872f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen            String[] selectionArgs, int callerUid, String callerPkg) {
13297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        try {
13307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            Long.parseLong(threadIdString);
13317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        } catch (NumberFormatException exception) {
13327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            Log.e(LOG_TAG, "Thread ID must be a Long.");
13337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            return 0;
1334e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen
1335e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen        }
1336e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen        if (ProviderUtil.shouldRemoveCreator(values, callerUid)) {
1337e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen            // CREATOR should not be changed by non-SYSTEM/PHONE apps
133872f135589e5d705bcac4a3db3019e4d9d2d04d36Ye Wen            Log.w(LOG_TAG, callerPkg + " tries to update CREATOR");
1339e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen            // Sms.CREATOR and Mms.CREATOR are same. But let's do this
1340e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen            // twice in case the names may differ in the future
1341e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen            values.remove(Sms.CREATOR);
1342e07acb9f6a77d9753900224a4caefd5a8aec97eeYe Wen            values.remove(Mms.CREATOR);
13437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
13447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
13457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
13467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        String finalSelection = concatSelections(selection, "thread_id=" + threadIdString);
13477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return db.update(MmsProvider.TABLE_PDU, values, finalSelection, selectionArgs)
13487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                + db.update("sms", values, finalSelection, selectionArgs);
13497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
13507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
13517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
13527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Construct Sets of Strings containing exactly the columns
13537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * present in each table.  We will use this when constructing
13547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * UNION queries across the MMS and SMS tables.
13557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
13567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static void initializeColumnSets() {
13577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int commonColumnCount = MMS_SMS_COLUMNS.length;
13587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int mmsOnlyColumnCount = MMS_ONLY_COLUMNS.length;
13597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int smsOnlyColumnCount = SMS_ONLY_COLUMNS.length;
13607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Set<String> unionColumns = new HashSet<String>();
13617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
13627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        for (int i = 0; i < commonColumnCount; i++) {
13637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            MMS_COLUMNS.add(MMS_SMS_COLUMNS[i]);
13647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            SMS_COLUMNS.add(MMS_SMS_COLUMNS[i]);
13657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            unionColumns.add(MMS_SMS_COLUMNS[i]);
13667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
13677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        for (int i = 0; i < mmsOnlyColumnCount; i++) {
13687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            MMS_COLUMNS.add(MMS_ONLY_COLUMNS[i]);
13697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            unionColumns.add(MMS_ONLY_COLUMNS[i]);
13707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
13717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        for (int i = 0; i < smsOnlyColumnCount; i++) {
13727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            SMS_COLUMNS.add(SMS_ONLY_COLUMNS[i]);
13737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            unionColumns.add(SMS_ONLY_COLUMNS[i]);
13747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
13757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
13767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int i = 0;
13777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        for (String columnName : unionColumns) {
13787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            UNION_COLUMNS[i++] = columnName;
13797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
13807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
138186b8a2cfb7558ec500b4de46bac3d873eaf6028fYe Wen
138286b8a2cfb7558ec500b4de46bac3d873eaf6028fYe Wen    @Override
138386b8a2cfb7558ec500b4de46bac3d873eaf6028fYe Wen    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
138486b8a2cfb7558ec500b4de46bac3d873eaf6028fYe Wen        // Dump default SMS app
138586b8a2cfb7558ec500b4de46bac3d873eaf6028fYe Wen        String defaultSmsApp = Telephony.Sms.getDefaultSmsPackage(getContext());
138686b8a2cfb7558ec500b4de46bac3d873eaf6028fYe Wen        if (TextUtils.isEmpty(defaultSmsApp)) {
138786b8a2cfb7558ec500b4de46bac3d873eaf6028fYe Wen            defaultSmsApp = "None";
138886b8a2cfb7558ec500b4de46bac3d873eaf6028fYe Wen        }
138986b8a2cfb7558ec500b4de46bac3d873eaf6028fYe Wen        writer.println("Default SMS app: " + defaultSmsApp);
139086b8a2cfb7558ec500b4de46bac3d873eaf6028fYe Wen    }
13917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project}
1392