1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/*
2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project
3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License");
5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License.
6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at
7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *      http://www.apache.org/licenses/LICENSE-2.0
9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software
11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS,
12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and
14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License.
15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */
16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.ui.conversation;
18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.app.AlertDialog;
20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Context;
21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.res.Resources;
22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.net.Uri;
23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.text.TextUtils;
24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.text.format.Formatter;
25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.Factory;
27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.R;
28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.BugleDatabaseOperations;
29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DataModel;
30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ConversationMessageData;
31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ConversationParticipantsData;
32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ParticipantData;
33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.mmslib.pdu.PduHeaders;
34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.sms.DatabaseMessages.MmsMessage;
35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.sms.MmsUtils;
36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.Assert;
37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.Assert.DoesNotRunOnMainThread;
38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.Dates;
39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.DebugUtils;
40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.OsUtil;
41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.PhoneUtils;
42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.SafeAsyncTask;
43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.List;
45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class MessageDetailsDialog {
47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String RECIPIENT_SEPARATOR = ", ";
48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    // All methods are static, no creating this class
50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private MessageDetailsDialog() {
51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static void show(final Context context, final ConversationMessageData data,
54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final ConversationParticipantsData participants, final ParticipantData self) {
55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (DebugUtils.isDebugEnabled()) {
56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            new SafeAsyncTask<Void, Void, String>() {
57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                @Override
58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                protected String doInBackgroundTimed(Void... params) {
59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    return getMessageDetails(context, data, participants, self);
60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                @Override
63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                protected void onPostExecute(String messageDetails) {
64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    showDialog(context, messageDetails);
65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }.executeOnThreadPool(null, null, null);
67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } else {
68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            String messageDetails = getMessageDetails(context, data, participants, self);
69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            showDialog(context, messageDetails);
70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static String getMessageDetails(final Context context,
74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final ConversationMessageData data,
75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final ConversationParticipantsData participants, final ParticipantData self) {
76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        String messageDetails = null;
77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (data.getIsSms()) {
78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            messageDetails = getSmsMessageDetails(data, participants, self);
79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } else {
80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // TODO: Handle SMS_TYPE_MMS_PUSH_NOTIFICATION type differently?
81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            messageDetails = getMmsMessageDetails(context, data, participants, self);
82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return messageDetails;
85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static void showDialog(final Context context, String messageDetails) {
88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (!TextUtils.isEmpty(messageDetails)) {
89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            new AlertDialog.Builder(context)
90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    .setTitle(R.string.message_details_title)
91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    .setMessage(messageDetails)
92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    .setCancelable(true)
93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    .show();
94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Return a string, separated by newlines, that contains a number of labels and values
99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * for this sms message. The string will be displayed in a modal dialog.
100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @return string list of various message properties
101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static String getSmsMessageDetails(final ConversationMessageData data,
103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final ConversationParticipantsData participants, final ParticipantData self) {
104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Resources res = Factory.get().getApplicationContext().getResources();
105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final StringBuilder details = new StringBuilder();
106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Type: Text message
108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append(res.getString(R.string.message_type_label));
109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append(res.getString(R.string.text_message));
110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // From: +1425xxxxxxx
112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // or To: +1425xxxxxxx
113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String rawSender = data.getSenderNormalizedDestination();
114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (!TextUtils.isEmpty(rawSender)) {
115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append('\n');
116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(res.getString(R.string.from_label));
117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(rawSender);
118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String rawRecipients = getRecipientParticipantString(participants,
120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                data.getParticipantId(), data.getIsIncoming(), data.getSelfParticipantId());
121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (!TextUtils.isEmpty(rawRecipients)) {
122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append('\n');
123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(res.getString(R.string.to_address_label));
124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(rawRecipients);
125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Sent: Mon 11:42AM
128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (data.getIsIncoming()) {
129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (data.getSentTimeStamp() != MmsUtils.INVALID_TIMESTAMP) {
130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                details.append('\n');
131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                details.append(res.getString(R.string.sent_label));
132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                details.append(
133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        Dates.getMessageDetailsTimeString(data.getSentTimeStamp()).toString());
134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Sent: Mon 11:43AM
138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // or Received: Mon 11:43AM
139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        appendSentOrReceivedTimestamp(res, details, data);
140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        appendSimInfo(res, self, details);
142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (DebugUtils.isDebugEnabled()) {
144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            appendDebugInfo(details, data);
145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return details.toString();
148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Return a string, separated by newlines, that contains a number of labels and values
152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * for this mms message. The string will be displayed in a modal dialog.
153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @return string list of various message properties
154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static String getMmsMessageDetails(Context context, final ConversationMessageData data,
156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final ConversationParticipantsData participants, final ParticipantData self) {
157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Resources res = Factory.get().getApplicationContext().getResources();
158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // TODO: when we support non-auto-download of mms messages, we'll have to handle
159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // the case when the message is a PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND and display
160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // something different. See the Messaging app's MessageUtils.getNotificationIndDetails()
161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final StringBuilder details = new StringBuilder();
163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Type: Multimedia message.
165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append(res.getString(R.string.message_type_label));
166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append(res.getString(R.string.multimedia_message));
167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // From: +1425xxxxxxx
169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String rawSender = data.getSenderNormalizedDestination();
170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append('\n');
171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append(res.getString(R.string.from_label));
172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append(!TextUtils.isEmpty(rawSender) ? rawSender :
173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                res.getString(R.string.hidden_sender_address));
174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // To: +1425xxxxxxx
176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String rawRecipients = getRecipientParticipantString(participants,
177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                data.getParticipantId(), data.getIsIncoming(), data.getSelfParticipantId());
178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (!TextUtils.isEmpty(rawRecipients)) {
179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append('\n');
180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(res.getString(R.string.to_address_label));
181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(rawRecipients);
182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Sent: Tue 3:05PM
185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // or Received: Tue 3:05PM
186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        appendSentOrReceivedTimestamp(res, details, data);
187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Subject: You're awesome
189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append('\n');
190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append(res.getString(R.string.subject_label));
191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (!TextUtils.isEmpty(MmsUtils.cleanseMmsSubject(res, data.getMmsSubject()))) {
192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(data.getMmsSubject());
193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Priority: High/Normal/Low
196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append('\n');
197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append(res.getString(R.string.priority_label));
198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append(getPriorityDescription(res, data.getSmsPriority()));
199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Message size: 30 KB
201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (data.getSmsMessageSize() > 0) {
202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append('\n');
203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(res.getString(R.string.message_size_label));
204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(Formatter.formatFileSize(context, data.getSmsMessageSize()));
205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
207d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        appendSimInfo(res, self, details);
208d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
209d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (DebugUtils.isDebugEnabled()) {
210d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            appendDebugInfo(details, data);
211d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
212d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
213d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return details.toString();
214d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
215d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
216d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static void appendSentOrReceivedTimestamp(Resources res, StringBuilder details,
217d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            ConversationMessageData data) {
218d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        int labelId = -1;
219d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (data.getIsIncoming()) {
220d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            labelId = R.string.received_label;
221d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } else if (data.getIsSendComplete()) {
222d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            labelId = R.string.sent_label;
223d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
224d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (labelId >= 0) {
225d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append('\n');
226d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(res.getString(labelId));
227d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(
228d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    Dates.getMessageDetailsTimeString(data.getReceivedTimeStamp()).toString());
229d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
230d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
231d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
232d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @DoesNotRunOnMainThread
233d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static void appendDebugInfo(StringBuilder details, ConversationMessageData data) {
234d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // We grab the thread id from the database, so this needs to run in the background
235d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        Assert.isNotMainThread();
236d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append("\n\n");
237d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append("DEBUG");
238d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
239d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append('\n');
240d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append("Message id: ");
241d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append(data.getMessageId());
242d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
243d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String telephonyUri = data.getSmsMessageUri();
244d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append('\n');
245d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append("Telephony uri: ");
246d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append(telephonyUri);
247d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
248d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String conversationId = data.getConversationId();
249d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
250d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (conversationId == null) {
251d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            return;
252d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
253d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
254d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append('\n');
255d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append("Conversation id: ");
256d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append(conversationId);
257d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
258d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final long threadId = BugleDatabaseOperations.getThreadId(DataModel.get().getDatabase(),
259d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                conversationId);
260d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
261d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append('\n');
262d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append("Conversation telephony thread id: ");
263d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        details.append(threadId);
264d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
265d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        MmsMessage mms = null;
266d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
267d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (data.getIsMms()) {
268d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (telephonyUri == null) {
269d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return;
270d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
271d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mms = MmsUtils.loadMms(Uri.parse(telephonyUri));
272d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (mms == null) {
273d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return;
274d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
275d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
276d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // We log the thread id again to check that they are internally consistent
277d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final long mmsThreadId = mms.mThreadId;
278d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append('\n');
279d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append("Telephony thread id: ");
280d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(mmsThreadId);
281d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
282d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // Log the MMS content location
283d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final String mmsContentLocation = mms.mContentLocation;
284d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append('\n');
285d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append("Content location URL: ");
286d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(mmsContentLocation);
287d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
288d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
289d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String recipientsString = MmsUtils.getRawRecipientIdsForThread(threadId);
290d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (recipientsString != null) {
291d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append('\n');
292d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append("Thread recipient ids: ");
293d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(recipientsString);
294d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
295d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
296d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final List<String> recipients = MmsUtils.getRecipientsByThread(threadId);
297d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (recipients != null) {
298d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append('\n');
299d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append("Thread recipients: ");
300d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            details.append(recipients.toString());
301d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
302d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (mms != null) {
303d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                final String from = MmsUtils.getMmsSender(recipients, mms.getUri());
304d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                details.append('\n');
305d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                details.append("Sender: ");
306d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                details.append(from);
307d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
308d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
309d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
310d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
311d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static String getRecipientParticipantString(
312d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final ConversationParticipantsData participants, final String senderId,
313d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final boolean addSelf, final String selfId) {
314d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final StringBuilder recipients = new StringBuilder();
315d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        for (final ParticipantData participant : participants) {
316d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (TextUtils.equals(participant.getId(), senderId)) {
317d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // Don't add sender
318d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                continue;
319d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
320d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (participant.isSelf() &&
321d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    (!participant.getId().equals(selfId) || !addSelf)) {
322d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // For self participants, don't add the one that's not relevant to this message
323d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // or if we are asked not to add self
324d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                continue;
325d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
326d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final String phoneNumber = participant.getNormalizedDestination();
327d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // Don't add empty number. This should not happen. But if that happens
328d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // we should not add it.
329d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (!TextUtils.isEmpty(phoneNumber)) {
330d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                if (recipients.length() > 0) {
331d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    recipients.append(RECIPIENT_SEPARATOR);
332d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
333d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                recipients.append(phoneNumber);
334d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
335d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
336d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return recipients.toString();
337d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
338d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
339d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
340d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Convert the numeric mms priority into a human-readable string
341d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @param res
342d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @param priorityValue coded PduHeader priority
343d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @return string representation of the priority
344d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
345d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static String getPriorityDescription(final Resources res, final int priorityValue) {
346d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        switch(priorityValue) {
347d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            case PduHeaders.PRIORITY_HIGH:
348d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return res.getString(R.string.priority_high);
349d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            case PduHeaders.PRIORITY_LOW:
350d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return res.getString(R.string.priority_low);
351d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            case PduHeaders.PRIORITY_NORMAL:
352d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            default:
353d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return res.getString(R.string.priority_normal);
354d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
355d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
356d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
357d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static void appendSimInfo(final Resources res,
358d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final ParticipantData self, final StringBuilder outString) {
359d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (!OsUtil.isAtLeastL_MR1()
360d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                || self == null
361d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                || PhoneUtils.getDefault().getActiveSubscriptionCount() < 2) {
362d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            return;
363d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
364d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // The appended SIM info would look like:
365d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // SIM: SUB 01
366d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // or SIM: SIM 1
367d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // or SIM: Unknown
368d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        Assert.isTrue(self.isSelf());
369d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        outString.append('\n');
370d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        outString.append(res.getString(R.string.sim_label));
371d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (self.isActiveSubscription() && !self.isDefaultSelf()) {
372d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final String subscriptionName = self.getSubscriptionName();
373d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (TextUtils.isEmpty(subscriptionName)) {
374d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                outString.append(res.getString(R.string.sim_slot_identifier,
375d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        self.getDisplaySlotId()));
376d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            } else {
377d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                outString.append(subscriptionName);
378d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
379d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
380d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
381d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd}
382