diff options
Diffstat (limited to 'src/com/android/messaging/datamodel/data/ConversationMessageData.java')
-rw-r--r-- | src/com/android/messaging/datamodel/data/ConversationMessageData.java | 917 |
1 files changed, 0 insertions, 917 deletions
diff --git a/src/com/android/messaging/datamodel/data/ConversationMessageData.java b/src/com/android/messaging/datamodel/data/ConversationMessageData.java deleted file mode 100644 index 19e1b97..0000000 --- a/src/com/android/messaging/datamodel/data/ConversationMessageData.java +++ /dev/null @@ -1,917 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.messaging.datamodel.data; - -import android.database.Cursor; -import android.net.Uri; -import android.provider.BaseColumns; -import android.provider.ContactsContract; -import android.text.TextUtils; -import android.text.format.DateUtils; - -import com.android.messaging.datamodel.DatabaseHelper; -import com.android.messaging.datamodel.DatabaseHelper.MessageColumns; -import com.android.messaging.datamodel.DatabaseHelper.PartColumns; -import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns; -import com.android.messaging.util.Assert; -import com.android.messaging.util.BugleGservices; -import com.android.messaging.util.BugleGservicesKeys; -import com.android.messaging.util.ContentType; -import com.android.messaging.util.Dates; -import com.android.messaging.util.LogUtil; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Predicate; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -/** - * Class representing a message within a conversation sequence. The message parts - * are available via the getParts() method. - * - * TODO: See if we can delegate to MessageData for the logic that this class duplicates - * (e.g. getIsMms). - */ -public class ConversationMessageData { - private static final String TAG = LogUtil.BUGLE_TAG; - - private String mMessageId; - private String mConversationId; - private String mParticipantId; - private int mPartsCount; - private List<MessagePartData> mParts; - private long mSentTimestamp; - private long mReceivedTimestamp; - private boolean mSeen; - private boolean mRead; - private int mProtocol; - private int mStatus; - private String mSmsMessageUri; - private int mSmsPriority; - private int mSmsMessageSize; - private String mMmsSubject; - private long mMmsExpiry; - private int mRawTelephonyStatus; - private String mSenderFullName; - private String mSenderFirstName; - private String mSenderDisplayDestination; - private String mSenderNormalizedDestination; - private String mSenderProfilePhotoUri; - private long mSenderContactId; - private String mSenderContactLookupKey; - private String mSelfParticipantId; - - /** Are we similar enough to the previous/next messages that we can cluster them? */ - private boolean mCanClusterWithPreviousMessage; - private boolean mCanClusterWithNextMessage; - - public ConversationMessageData() { - } - - public void bind(final Cursor cursor) { - mMessageId = cursor.getString(INDEX_MESSAGE_ID); - mConversationId = cursor.getString(INDEX_CONVERSATION_ID); - mParticipantId = cursor.getString(INDEX_PARTICIPANT_ID); - mPartsCount = cursor.getInt(INDEX_PARTS_COUNT); - - mParts = makeParts( - cursor.getString(INDEX_PARTS_IDS), - cursor.getString(INDEX_PARTS_CONTENT_TYPES), - cursor.getString(INDEX_PARTS_CONTENT_URIS), - cursor.getString(INDEX_PARTS_WIDTHS), - cursor.getString(INDEX_PARTS_HEIGHTS), - cursor.getString(INDEX_PARTS_TEXTS), - mPartsCount, - mMessageId); - - mSentTimestamp = cursor.getLong(INDEX_SENT_TIMESTAMP); - mReceivedTimestamp = cursor.getLong(INDEX_RECEIVED_TIMESTAMP); - mSeen = (cursor.getInt(INDEX_SEEN) != 0); - mRead = (cursor.getInt(INDEX_READ) != 0); - mProtocol = cursor.getInt(INDEX_PROTOCOL); - mStatus = cursor.getInt(INDEX_STATUS); - mSmsMessageUri = cursor.getString(INDEX_SMS_MESSAGE_URI); - mSmsPriority = cursor.getInt(INDEX_SMS_PRIORITY); - mSmsMessageSize = cursor.getInt(INDEX_SMS_MESSAGE_SIZE); - mMmsSubject = cursor.getString(INDEX_MMS_SUBJECT); - mMmsExpiry = cursor.getLong(INDEX_MMS_EXPIRY); - mRawTelephonyStatus = cursor.getInt(INDEX_RAW_TELEPHONY_STATUS); - mSenderFullName = cursor.getString(INDEX_SENDER_FULL_NAME); - mSenderFirstName = cursor.getString(INDEX_SENDER_FIRST_NAME); - mSenderDisplayDestination = cursor.getString(INDEX_SENDER_DISPLAY_DESTINATION); - mSenderNormalizedDestination = cursor.getString(INDEX_SENDER_NORMALIZED_DESTINATION); - mSenderProfilePhotoUri = cursor.getString(INDEX_SENDER_PROFILE_PHOTO_URI); - mSenderContactId = cursor.getLong(INDEX_SENDER_CONTACT_ID); - mSenderContactLookupKey = cursor.getString(INDEX_SENDER_CONTACT_LOOKUP_KEY); - mSelfParticipantId = cursor.getString(INDEX_SELF_PARTICIPIANT_ID); - - if (!cursor.isFirst() && cursor.moveToPrevious()) { - mCanClusterWithPreviousMessage = canClusterWithMessage(cursor); - cursor.moveToNext(); - } else { - mCanClusterWithPreviousMessage = false; - } - if (!cursor.isLast() && cursor.moveToNext()) { - mCanClusterWithNextMessage = canClusterWithMessage(cursor); - cursor.moveToPrevious(); - } else { - mCanClusterWithNextMessage = false; - } - } - - private boolean canClusterWithMessage(final Cursor cursor) { - final String otherParticipantId = cursor.getString(INDEX_PARTICIPANT_ID); - if (!TextUtils.equals(getParticipantId(), otherParticipantId)) { - return false; - } - final int otherStatus = cursor.getInt(INDEX_STATUS); - final boolean otherIsIncoming = (otherStatus >= MessageData.BUGLE_STATUS_FIRST_INCOMING); - if (getIsIncoming() != otherIsIncoming) { - return false; - } - final long otherReceivedTimestamp = cursor.getLong(INDEX_RECEIVED_TIMESTAMP); - final long timestampDeltaMillis = Math.abs(mReceivedTimestamp - otherReceivedTimestamp); - if (timestampDeltaMillis > DateUtils.MINUTE_IN_MILLIS) { - return false; - } - final String otherSelfId = cursor.getString(INDEX_SELF_PARTICIPIANT_ID); - if (!TextUtils.equals(getSelfParticipantId(), otherSelfId)) { - return false; - } - return true; - } - - private static final Character QUOTE_CHAR = '\''; - private static final char DIVIDER = '|'; - - // statics to avoid unnecessary object allocation - private static final StringBuilder sUnquoteStringBuilder = new StringBuilder(); - private static final ArrayList<String> sUnquoteResults = new ArrayList<String>(); - - // this lock is used to guard access to the above statics - private static final Object sUnquoteLock = new Object(); - - private static void addResult(final ArrayList<String> results, final StringBuilder value) { - if (value.length() > 0) { - results.add(value.toString()); - } else { - results.add(EMPTY_STRING); - } - } - - @VisibleForTesting - static String[] splitUnquotedString(final String inputString) { - if (TextUtils.isEmpty(inputString)) { - return new String[0]; - } - - return inputString.split("\\" + DIVIDER); - } - - /** - * Takes a group-concated and quoted string and decomposes it into its constituent - * parts. A quoted string starts and ends with a single quote. Actual single quotes - * within the string are escaped using a second single quote. So, for example, an - * input string with 3 constituent parts might look like this: - * - * 'now is the time'|'I can''t do it'|'foo' - * - * This would be returned as an array of 3 strings as follows: - * now is the time - * I can't do it - * foo - * - * This is achieved by walking through the inputString, character by character, - * ignoring the outer quotes and the divider and replacing any pair of consecutive - * single quotes with a single single quote. - * - * @param inputString - * @return array of constituent strings - */ - @VisibleForTesting - static String[] splitQuotedString(final String inputString) { - if (TextUtils.isEmpty(inputString)) { - return new String[0]; - } - - // this method can be called from multiple threads but it uses a static - // string builder - synchronized (sUnquoteLock) { - final int length = inputString.length(); - final ArrayList<String> results = sUnquoteResults; - results.clear(); - - int characterPos = -1; - while (++characterPos < length) { - final char mustBeQuote = inputString.charAt(characterPos); - Assert.isTrue(QUOTE_CHAR == mustBeQuote); - while (++characterPos < length) { - final char currentChar = inputString.charAt(characterPos); - if (currentChar == QUOTE_CHAR) { - final char peekAhead = characterPos < length - 1 - ? inputString.charAt(characterPos + 1) : 0; - - if (peekAhead == QUOTE_CHAR) { - characterPos += 1; // skip the second quote - } else { - addResult(results, sUnquoteStringBuilder); - sUnquoteStringBuilder.setLength(0); - - Assert.isTrue((peekAhead == DIVIDER) || (peekAhead == (char) 0)); - characterPos += 1; // skip the divider - break; - } - } - sUnquoteStringBuilder.append(currentChar); - } - } - return results.toArray(new String[results.size()]); - } - } - - static MessagePartData makePartData( - final String partId, - final String contentType, - final String contentUriString, - final String contentWidth, - final String contentHeight, - final String text, - final String messageId) { - if (ContentType.isTextType(contentType)) { - final MessagePartData textPart = MessagePartData.createTextMessagePart(text); - textPart.updatePartId(partId); - textPart.updateMessageId(messageId); - return textPart; - } else { - final Uri contentUri = Uri.parse(contentUriString); - final int width = Integer.parseInt(contentWidth); - final int height = Integer.parseInt(contentHeight); - final MessagePartData attachmentPart = MessagePartData.createMediaMessagePart( - contentType, contentUri, width, height); - attachmentPart.updatePartId(partId); - attachmentPart.updateMessageId(messageId); - return attachmentPart; - } - } - - @VisibleForTesting - static List<MessagePartData> makeParts( - final String rawIds, - final String rawContentTypes, - final String rawContentUris, - final String rawWidths, - final String rawHeights, - final String rawTexts, - final int partsCount, - final String messageId) { - final List<MessagePartData> parts = new LinkedList<MessagePartData>(); - if (partsCount == 1) { - parts.add(makePartData( - rawIds, - rawContentTypes, - rawContentUris, - rawWidths, - rawHeights, - rawTexts, - messageId)); - } else { - unpackMessageParts( - parts, - splitUnquotedString(rawIds), - splitQuotedString(rawContentTypes), - splitQuotedString(rawContentUris), - splitUnquotedString(rawWidths), - splitUnquotedString(rawHeights), - splitQuotedString(rawTexts), - partsCount, - messageId); - } - return parts; - } - - @VisibleForTesting - static void unpackMessageParts( - final List<MessagePartData> parts, - final String[] ids, - final String[] contentTypes, - final String[] contentUris, - final String[] contentWidths, - final String[] contentHeights, - final String[] texts, - final int partsCount, - final String messageId) { - - Assert.equals(partsCount, ids.length); - Assert.equals(partsCount, contentTypes.length); - Assert.equals(partsCount, contentUris.length); - Assert.equals(partsCount, contentWidths.length); - Assert.equals(partsCount, contentHeights.length); - Assert.equals(partsCount, texts.length); - - for (int i = 0; i < partsCount; i++) { - parts.add(makePartData( - ids[i], - contentTypes[i], - contentUris[i], - contentWidths[i], - contentHeights[i], - texts[i], - messageId)); - } - - if (parts.size() != partsCount) { - LogUtil.wtf(TAG, "Only unpacked " + parts.size() + " parts from message (id=" - + messageId + "), expected " + partsCount + " parts"); - } - } - - public final String getMessageId() { - return mMessageId; - } - - public final String getConversationId() { - return mConversationId; - } - - public final String getParticipantId() { - return mParticipantId; - } - - public List<MessagePartData> getParts() { - return mParts; - } - - public boolean hasText() { - for (final MessagePartData part : mParts) { - if (part.isText()) { - return true; - } - } - return false; - } - - /** - * Get a concatenation of all text parts - * - * @return the text that is a concatenation of all text parts - */ - public String getText() { - // This is optimized for single text part case, which is the majority - - // For single text part, we just return the part without creating the StringBuilder - String firstTextPart = null; - boolean foundText = false; - // For multiple text parts, we need the StringBuilder and the separator for concatenation - StringBuilder sb = null; - String separator = null; - for (final MessagePartData part : mParts) { - if (part.isText()) { - if (!foundText) { - // First text part - firstTextPart = part.getText(); - foundText = true; - } else { - // Second and beyond - if (sb == null) { - // Need the StringBuilder and the separator starting from 2nd text part - sb = new StringBuilder(); - if (!TextUtils.isEmpty(firstTextPart)) { - sb.append(firstTextPart); - } - separator = BugleGservices.get().getString( - BugleGservicesKeys.MMS_TEXT_CONCAT_SEPARATOR, - BugleGservicesKeys.MMS_TEXT_CONCAT_SEPARATOR_DEFAULT); - } - final String partText = part.getText(); - if (!TextUtils.isEmpty(partText)) { - if (!TextUtils.isEmpty(separator) && sb.length() > 0) { - sb.append(separator); - } - sb.append(partText); - } - } - } - } - if (sb == null) { - // Only one text part - return firstTextPart; - } else { - // More than one - return sb.toString(); - } - } - - public boolean hasAttachments() { - for (final MessagePartData part : mParts) { - if (part.isAttachment()) { - return true; - } - } - return false; - } - - public List<MessagePartData> getAttachments() { - return getAttachments(null); - } - - public List<MessagePartData> getAttachments(final Predicate<MessagePartData> filter) { - if (mParts.isEmpty()) { - return Collections.emptyList(); - } - final List<MessagePartData> attachmentParts = new LinkedList<>(); - for (final MessagePartData part : mParts) { - if (part.isAttachment()) { - if (filter == null || filter.apply(part)) { - attachmentParts.add(part); - } - } - } - return attachmentParts; - } - - public final long getSentTimeStamp() { - return mSentTimestamp; - } - - public final long getReceivedTimeStamp() { - return mReceivedTimestamp; - } - - public final String getFormattedReceivedTimeStamp() { - return Dates.getMessageTimeString(mReceivedTimestamp).toString(); - } - - public final boolean getIsSeen() { - return mSeen; - } - - public final boolean getIsRead() { - return mRead; - } - - public final boolean getIsMms() { - return (mProtocol == MessageData.PROTOCOL_MMS || - mProtocol == MessageData.PROTOCOL_MMS_PUSH_NOTIFICATION); - } - - public final boolean getIsMmsNotification() { - return (mProtocol == MessageData.PROTOCOL_MMS_PUSH_NOTIFICATION); - } - - public final boolean getIsSms() { - return mProtocol == (MessageData.PROTOCOL_SMS); - } - - final int getProtocol() { - return mProtocol; - } - - public final int getStatus() { - return mStatus; - } - - public final String getSmsMessageUri() { - return mSmsMessageUri; - } - - public final int getSmsPriority() { - return mSmsPriority; - } - - public final int getSmsMessageSize() { - return mSmsMessageSize; - } - - public final String getMmsSubject() { - return mMmsSubject; - } - - public final long getMmsExpiry() { - return mMmsExpiry; - } - - public final int getRawTelephonyStatus() { - return mRawTelephonyStatus; - } - - public final String getSelfParticipantId() { - return mSelfParticipantId; - } - - public boolean getIsIncoming() { - return (mStatus >= MessageData.BUGLE_STATUS_FIRST_INCOMING); - } - - public boolean hasIncomingErrorStatus() { - return (mStatus == MessageData.BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE || - mStatus == MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED); - } - - public boolean getIsSendComplete() { - return mStatus == MessageData.BUGLE_STATUS_OUTGOING_COMPLETE; - } - - public String getSenderFullName() { - return mSenderFullName; - } - - public String getSenderFirstName() { - return mSenderFirstName; - } - - public String getSenderDisplayDestination() { - return mSenderDisplayDestination; - } - - public String getSenderNormalizedDestination() { - return mSenderNormalizedDestination; - } - - public Uri getSenderProfilePhotoUri() { - return mSenderProfilePhotoUri == null ? null : Uri.parse(mSenderProfilePhotoUri); - } - - public long getSenderContactId() { - return mSenderContactId; - } - - public String getSenderDisplayName() { - if (!TextUtils.isEmpty(mSenderFullName)) { - return mSenderFullName; - } - if (!TextUtils.isEmpty(mSenderFirstName)) { - return mSenderFirstName; - } - return mSenderDisplayDestination; - } - - public String getSenderContactLookupKey() { - return mSenderContactLookupKey; - } - - public boolean getShowDownloadMessage() { - return MessageData.getShowDownloadMessage(mStatus); - } - - public boolean getShowResendMessage() { - return MessageData.getShowResendMessage(mStatus); - } - - public boolean getCanForwardMessage() { - // Even for outgoing messages, we only allow forwarding if the message has finished sending - // as media often has issues when send isn't complete - return (mStatus == MessageData.BUGLE_STATUS_OUTGOING_COMPLETE || - mStatus == MessageData.BUGLE_STATUS_INCOMING_COMPLETE); - } - - public boolean getCanCopyMessageToClipboard() { - return (hasText() && - (!getIsIncoming() || mStatus == MessageData.BUGLE_STATUS_INCOMING_COMPLETE)); - } - - public boolean getOneClickResendMessage() { - return MessageData.getOneClickResendMessage(mStatus, mRawTelephonyStatus); - } - - /** - * Get sender's lookup uri. - * This method doesn't support corp contacts. - * - * @return Lookup uri of sender's contact - */ - public Uri getSenderContactLookupUri() { - if (mSenderContactId > ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED - && !TextUtils.isEmpty(mSenderContactLookupKey)) { - return ContactsContract.Contacts.getLookupUri(mSenderContactId, - mSenderContactLookupKey); - } - return null; - } - - public boolean getCanClusterWithPreviousMessage() { - return mCanClusterWithPreviousMessage; - } - - public boolean getCanClusterWithNextMessage() { - return mCanClusterWithNextMessage; - } - - @Override - public String toString() { - return MessageData.toString(mMessageId, mParts); - } - - // Data definitions - - public static final String getConversationMessagesQuerySql() { - return CONVERSATION_MESSAGES_QUERY_SQL - + " AND " - // Inject the conversation id - + DatabaseHelper.MESSAGES_TABLE + "." + MessageColumns.CONVERSATION_ID + "=?)" - + CONVERSATION_MESSAGES_QUERY_SQL_GROUP_BY; - } - - static final String getConversationMessageIdsQuerySql() { - return CONVERSATION_MESSAGES_IDS_QUERY_SQL - + " AND " - // Inject the conversation id - + DatabaseHelper.MESSAGES_TABLE + "." + MessageColumns.CONVERSATION_ID + "=?)" - + CONVERSATION_MESSAGES_QUERY_SQL_GROUP_BY; - } - - public static final String getNotificationQuerySql() { - return CONVERSATION_MESSAGES_QUERY_SQL - + " AND " - + "(" + DatabaseHelper.MessageColumns.STATUS + " in (" - + MessageData.BUGLE_STATUS_INCOMING_COMPLETE + ", " - + MessageData.BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD + ")" - + " AND " - + DatabaseHelper.MessageColumns.SEEN + " = 0)" - + ")" - + NOTIFICATION_QUERY_SQL_GROUP_BY; - } - - public static final String getWearableQuerySql() { - return CONVERSATION_MESSAGES_QUERY_SQL - + " AND " - + DatabaseHelper.MESSAGES_TABLE + "." + MessageColumns.CONVERSATION_ID + "=?" - + " AND " - + DatabaseHelper.MessageColumns.STATUS + " IN (" - + MessageData.BUGLE_STATUS_OUTGOING_DELIVERED + ", " - + MessageData.BUGLE_STATUS_OUTGOING_COMPLETE + ", " - + MessageData.BUGLE_STATUS_OUTGOING_YET_TO_SEND + ", " - + MessageData.BUGLE_STATUS_OUTGOING_SENDING + ", " - + MessageData.BUGLE_STATUS_OUTGOING_RESENDING + ", " - + MessageData.BUGLE_STATUS_OUTGOING_AWAITING_RETRY + ", " - + MessageData.BUGLE_STATUS_INCOMING_COMPLETE + ", " - + MessageData.BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD + ")" - + ")" - + NOTIFICATION_QUERY_SQL_GROUP_BY; - } - - /* - * Generate a sqlite snippet to call the quote function on the columnName argument. - * The columnName doesn't strictly have to be a column name (e.g. it could be an - * expression). - */ - private static String quote(final String columnName) { - return "quote(" + columnName + ")"; - } - - private static String makeGroupConcatString(final String column) { - return "group_concat(" + column + ", '" + DIVIDER + "')"; - } - - private static String makeIfNullString(final String column) { - return "ifnull(" + column + "," + "''" + ")"; - } - - private static String makePartsTableColumnString(final String column) { - return DatabaseHelper.PARTS_TABLE + '.' + column; - } - - private static String makeCaseWhenString(final String column, - final boolean quote, - final String asColumn) { - final String fullColumn = makeIfNullString(makePartsTableColumnString(column)); - final String groupConcatTerm = quote - ? makeGroupConcatString(quote(fullColumn)) - : makeGroupConcatString(fullColumn); - return "CASE WHEN (" + CONVERSATION_MESSAGE_VIEW_PARTS_COUNT + ">1) THEN " + groupConcatTerm - + " ELSE " + makePartsTableColumnString(column) + " END AS " + asColumn; - } - - private static final String CONVERSATION_MESSAGE_VIEW_PARTS_COUNT = - "count(" + DatabaseHelper.PARTS_TABLE + '.' + PartColumns._ID + ")"; - - private static final String EMPTY_STRING = ""; - - private static final String CONVERSATION_MESSAGES_QUERY_PROJECTION_SQL = - DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns._ID - + " as " + ConversationMessageViewColumns._ID + ", " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.CONVERSATION_ID - + " as " + ConversationMessageViewColumns.CONVERSATION_ID + ", " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SENDER_PARTICIPANT_ID - + " as " + ConversationMessageViewColumns.PARTICIPANT_ID + ", " - - + makeCaseWhenString(PartColumns._ID, false, - ConversationMessageViewColumns.PARTS_IDS) + ", " - + makeCaseWhenString(PartColumns.CONTENT_TYPE, true, - ConversationMessageViewColumns.PARTS_CONTENT_TYPES) + ", " - + makeCaseWhenString(PartColumns.CONTENT_URI, true, - ConversationMessageViewColumns.PARTS_CONTENT_URIS) + ", " - + makeCaseWhenString(PartColumns.WIDTH, false, - ConversationMessageViewColumns.PARTS_WIDTHS) + ", " - + makeCaseWhenString(PartColumns.HEIGHT, false, - ConversationMessageViewColumns.PARTS_HEIGHTS) + ", " - + makeCaseWhenString(PartColumns.TEXT, true, - ConversationMessageViewColumns.PARTS_TEXTS) + ", " - - + CONVERSATION_MESSAGE_VIEW_PARTS_COUNT - + " as " + ConversationMessageViewColumns.PARTS_COUNT + ", " - - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SENT_TIMESTAMP - + " as " + ConversationMessageViewColumns.SENT_TIMESTAMP + ", " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.RECEIVED_TIMESTAMP - + " as " + ConversationMessageViewColumns.RECEIVED_TIMESTAMP + ", " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SEEN - + " as " + ConversationMessageViewColumns.SEEN + ", " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.READ - + " as " + ConversationMessageViewColumns.READ + ", " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.PROTOCOL - + " as " + ConversationMessageViewColumns.PROTOCOL + ", " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.STATUS - + " as " + ConversationMessageViewColumns.STATUS + ", " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SMS_MESSAGE_URI - + " as " + ConversationMessageViewColumns.SMS_MESSAGE_URI + ", " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SMS_PRIORITY - + " as " + ConversationMessageViewColumns.SMS_PRIORITY + ", " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SMS_MESSAGE_SIZE - + " as " + ConversationMessageViewColumns.SMS_MESSAGE_SIZE + ", " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.MMS_SUBJECT - + " as " + ConversationMessageViewColumns.MMS_SUBJECT + ", " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.MMS_EXPIRY - + " as " + ConversationMessageViewColumns.MMS_EXPIRY + ", " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.RAW_TELEPHONY_STATUS - + " as " + ConversationMessageViewColumns.RAW_TELEPHONY_STATUS + ", " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SELF_PARTICIPANT_ID - + " as " + ConversationMessageViewColumns.SELF_PARTICIPANT_ID + ", " - + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.FULL_NAME - + " as " + ConversationMessageViewColumns.SENDER_FULL_NAME + ", " - + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.FIRST_NAME - + " as " + ConversationMessageViewColumns.SENDER_FIRST_NAME + ", " - + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.DISPLAY_DESTINATION - + " as " + ConversationMessageViewColumns.SENDER_DISPLAY_DESTINATION + ", " - + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.NORMALIZED_DESTINATION - + " as " + ConversationMessageViewColumns.SENDER_NORMALIZED_DESTINATION + ", " - + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.PROFILE_PHOTO_URI - + " as " + ConversationMessageViewColumns.SENDER_PROFILE_PHOTO_URI + ", " - + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.CONTACT_ID - + " as " + ConversationMessageViewColumns.SENDER_CONTACT_ID + ", " - + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.LOOKUP_KEY - + " as " + ConversationMessageViewColumns.SENDER_CONTACT_LOOKUP_KEY + " "; - - private static final String CONVERSATION_MESSAGES_QUERY_FROM_WHERE_SQL = - " FROM " + DatabaseHelper.MESSAGES_TABLE - + " LEFT JOIN " + DatabaseHelper.PARTS_TABLE - + " ON (" + DatabaseHelper.MESSAGES_TABLE + "." + MessageColumns._ID - + "=" + DatabaseHelper.PARTS_TABLE + "." + PartColumns.MESSAGE_ID + ") " - + " LEFT JOIN " + DatabaseHelper.PARTICIPANTS_TABLE - + " ON (" + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SENDER_PARTICIPANT_ID - + '=' + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns._ID + ")" - // Exclude draft messages from main view - + " WHERE (" + DatabaseHelper.MESSAGES_TABLE + "." + MessageColumns.STATUS - + " <> " + MessageData.BUGLE_STATUS_OUTGOING_DRAFT; - - // This query is mostly static, except for the injection of conversation id. This is for - // performance reasons, to ensure that the query uses indices and does not trigger full scans - // of the messages table. See b/17160946 for more details. - private static final String CONVERSATION_MESSAGES_QUERY_SQL = "SELECT " - + CONVERSATION_MESSAGES_QUERY_PROJECTION_SQL - + CONVERSATION_MESSAGES_QUERY_FROM_WHERE_SQL; - - private static final String CONVERSATION_MESSAGE_IDS_PROJECTION_SQL = - DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns._ID - + " as " + ConversationMessageViewColumns._ID + " "; - - private static final String CONVERSATION_MESSAGES_IDS_QUERY_SQL = "SELECT " - + CONVERSATION_MESSAGE_IDS_PROJECTION_SQL - + CONVERSATION_MESSAGES_QUERY_FROM_WHERE_SQL; - - // Note that we sort DESC and ConversationData reverses the cursor. This is a performance - // issue (improvement) for large cursors. - private static final String CONVERSATION_MESSAGES_QUERY_SQL_GROUP_BY = - " GROUP BY " + DatabaseHelper.PARTS_TABLE + '.' + PartColumns.MESSAGE_ID - + " ORDER BY " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.RECEIVED_TIMESTAMP + " DESC"; - - private static final String NOTIFICATION_QUERY_SQL_GROUP_BY = - " GROUP BY " + DatabaseHelper.PARTS_TABLE + '.' + PartColumns.MESSAGE_ID - + " ORDER BY " - + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.RECEIVED_TIMESTAMP + " DESC"; - - interface ConversationMessageViewColumns extends BaseColumns { - static final String _ID = MessageColumns._ID; - static final String CONVERSATION_ID = MessageColumns.CONVERSATION_ID; - static final String PARTICIPANT_ID = MessageColumns.SENDER_PARTICIPANT_ID; - static final String PARTS_COUNT = "parts_count"; - static final String SENT_TIMESTAMP = MessageColumns.SENT_TIMESTAMP; - static final String RECEIVED_TIMESTAMP = MessageColumns.RECEIVED_TIMESTAMP; - static final String SEEN = MessageColumns.SEEN; - static final String READ = MessageColumns.READ; - static final String PROTOCOL = MessageColumns.PROTOCOL; - static final String STATUS = MessageColumns.STATUS; - static final String SMS_MESSAGE_URI = MessageColumns.SMS_MESSAGE_URI; - static final String SMS_PRIORITY = MessageColumns.SMS_PRIORITY; - static final String SMS_MESSAGE_SIZE = MessageColumns.SMS_MESSAGE_SIZE; - static final String MMS_SUBJECT = MessageColumns.MMS_SUBJECT; - static final String MMS_EXPIRY = MessageColumns.MMS_EXPIRY; - static final String RAW_TELEPHONY_STATUS = MessageColumns.RAW_TELEPHONY_STATUS; - static final String SELF_PARTICIPANT_ID = MessageColumns.SELF_PARTICIPANT_ID; - static final String SENDER_FULL_NAME = ParticipantColumns.FULL_NAME; - static final String SENDER_FIRST_NAME = ParticipantColumns.FIRST_NAME; - static final String SENDER_DISPLAY_DESTINATION = ParticipantColumns.DISPLAY_DESTINATION; - static final String SENDER_NORMALIZED_DESTINATION = - ParticipantColumns.NORMALIZED_DESTINATION; - static final String SENDER_PROFILE_PHOTO_URI = ParticipantColumns.PROFILE_PHOTO_URI; - static final String SENDER_CONTACT_ID = ParticipantColumns.CONTACT_ID; - static final String SENDER_CONTACT_LOOKUP_KEY = ParticipantColumns.LOOKUP_KEY; - static final String PARTS_IDS = "parts_ids"; - static final String PARTS_CONTENT_TYPES = "parts_content_types"; - static final String PARTS_CONTENT_URIS = "parts_content_uris"; - static final String PARTS_WIDTHS = "parts_widths"; - static final String PARTS_HEIGHTS = "parts_heights"; - static final String PARTS_TEXTS = "parts_texts"; - } - - private static int sIndexIncrementer = 0; - - private static final int INDEX_MESSAGE_ID = sIndexIncrementer++; - private static final int INDEX_CONVERSATION_ID = sIndexIncrementer++; - private static final int INDEX_PARTICIPANT_ID = sIndexIncrementer++; - - private static final int INDEX_PARTS_IDS = sIndexIncrementer++; - private static final int INDEX_PARTS_CONTENT_TYPES = sIndexIncrementer++; - private static final int INDEX_PARTS_CONTENT_URIS = sIndexIncrementer++; - private static final int INDEX_PARTS_WIDTHS = sIndexIncrementer++; - private static final int INDEX_PARTS_HEIGHTS = sIndexIncrementer++; - private static final int INDEX_PARTS_TEXTS = sIndexIncrementer++; - - private static final int INDEX_PARTS_COUNT = sIndexIncrementer++; - - private static final int INDEX_SENT_TIMESTAMP = sIndexIncrementer++; - private static final int INDEX_RECEIVED_TIMESTAMP = sIndexIncrementer++; - private static final int INDEX_SEEN = sIndexIncrementer++; - private static final int INDEX_READ = sIndexIncrementer++; - private static final int INDEX_PROTOCOL = sIndexIncrementer++; - private static final int INDEX_STATUS = sIndexIncrementer++; - private static final int INDEX_SMS_MESSAGE_URI = sIndexIncrementer++; - private static final int INDEX_SMS_PRIORITY = sIndexIncrementer++; - private static final int INDEX_SMS_MESSAGE_SIZE = sIndexIncrementer++; - private static final int INDEX_MMS_SUBJECT = sIndexIncrementer++; - private static final int INDEX_MMS_EXPIRY = sIndexIncrementer++; - private static final int INDEX_RAW_TELEPHONY_STATUS = sIndexIncrementer++; - private static final int INDEX_SELF_PARTICIPIANT_ID = sIndexIncrementer++; - private static final int INDEX_SENDER_FULL_NAME = sIndexIncrementer++; - private static final int INDEX_SENDER_FIRST_NAME = sIndexIncrementer++; - private static final int INDEX_SENDER_DISPLAY_DESTINATION = sIndexIncrementer++; - private static final int INDEX_SENDER_NORMALIZED_DESTINATION = sIndexIncrementer++; - private static final int INDEX_SENDER_PROFILE_PHOTO_URI = sIndexIncrementer++; - private static final int INDEX_SENDER_CONTACT_ID = sIndexIncrementer++; - private static final int INDEX_SENDER_CONTACT_LOOKUP_KEY = sIndexIncrementer++; - - - private static String[] sProjection = { - ConversationMessageViewColumns._ID, - ConversationMessageViewColumns.CONVERSATION_ID, - ConversationMessageViewColumns.PARTICIPANT_ID, - - ConversationMessageViewColumns.PARTS_IDS, - ConversationMessageViewColumns.PARTS_CONTENT_TYPES, - ConversationMessageViewColumns.PARTS_CONTENT_URIS, - ConversationMessageViewColumns.PARTS_WIDTHS, - ConversationMessageViewColumns.PARTS_HEIGHTS, - ConversationMessageViewColumns.PARTS_TEXTS, - - ConversationMessageViewColumns.PARTS_COUNT, - ConversationMessageViewColumns.SENT_TIMESTAMP, - ConversationMessageViewColumns.RECEIVED_TIMESTAMP, - ConversationMessageViewColumns.SEEN, - ConversationMessageViewColumns.READ, - ConversationMessageViewColumns.PROTOCOL, - ConversationMessageViewColumns.STATUS, - ConversationMessageViewColumns.SMS_MESSAGE_URI, - ConversationMessageViewColumns.SMS_PRIORITY, - ConversationMessageViewColumns.SMS_MESSAGE_SIZE, - ConversationMessageViewColumns.MMS_SUBJECT, - ConversationMessageViewColumns.MMS_EXPIRY, - ConversationMessageViewColumns.RAW_TELEPHONY_STATUS, - ConversationMessageViewColumns.SELF_PARTICIPANT_ID, - ConversationMessageViewColumns.SENDER_FULL_NAME, - ConversationMessageViewColumns.SENDER_FIRST_NAME, - ConversationMessageViewColumns.SENDER_DISPLAY_DESTINATION, - ConversationMessageViewColumns.SENDER_NORMALIZED_DESTINATION, - ConversationMessageViewColumns.SENDER_PROFILE_PHOTO_URI, - ConversationMessageViewColumns.SENDER_CONTACT_ID, - ConversationMessageViewColumns.SENDER_CONTACT_LOOKUP_KEY, - }; - - public static String[] getProjection() { - return sProjection; - } -} |