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.datamodel.action;
18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.app.Activity;
20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Context;
21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.net.Uri;
22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.os.Bundle;
23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.os.Parcel;
24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.os.Parcelable;
25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.telephony.PhoneNumberUtils;
26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.telephony.SmsManager;
27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.Factory;
29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.BugleDatabaseOperations;
30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.BugleNotifications;
31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DataModel;
32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DatabaseWrapper;
33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.MmsFileProvider;
34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.MessageData;
35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.MessagePartData;
36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ParticipantData;
37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.mmslib.pdu.SendConf;
38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.sms.MmsConfig;
39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.sms.MmsSender;
40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.sms.MmsUtils;
41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.Assert;
42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.LogUtil;
43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.io.File;
45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.ArrayList;
46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/**
48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd* Update message status to reflect success or failure
49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd* Can also update the message itself if a "final" message is now available from telephony db
50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd*/
51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class ProcessSentMessageAction extends Action {
52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    // These are always set
55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_SMS = "is_sms";
56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_SENT_BY_PLATFORM = "sent_by_platform";
57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    // These are set when we're processing a message sent by the user. They are null for messages
59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    // sent automatically (e.g. a NotifyRespInd/AcknowledgeInd sent in response to a download).
60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_MESSAGE_ID = "message_id";
61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_MESSAGE_URI = "message_uri";
62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_UPDATED_MESSAGE_URI = "updated_message_uri";
63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_SUB_ID = "sub_id";
64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    // These are set for messages sent by the platform (L+)
66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final String KEY_RESULT_CODE = "result_code";
67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final String KEY_HTTP_STATUS_CODE = "http_status_code";
68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_CONTENT_URI = "content_uri";
69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_RESPONSE = "response";
70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_RESPONSE_IMPORTANT = "response_important";
71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    // These are set for messages we sent ourself (legacy), or which we fast-failed before sending.
73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_STATUS = "status";
74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_RAW_STATUS = "raw_status";
75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    // This is called when MMS lib API returns via PendingIntent
77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static void processMmsSent(final int resultCode, final Uri messageUri,
78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final Bundle extras) {
79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final ProcessSentMessageAction action = new ProcessSentMessageAction();
80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Bundle params = action.actionParameters;
81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putBoolean(KEY_SMS, false);
82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putBoolean(KEY_SENT_BY_PLATFORM, true);
83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putString(KEY_MESSAGE_ID, extras.getString(SendMessageAction.EXTRA_MESSAGE_ID));
84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putParcelable(KEY_MESSAGE_URI, messageUri);
85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putParcelable(KEY_UPDATED_MESSAGE_URI,
86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                extras.getParcelable(SendMessageAction.EXTRA_UPDATED_MESSAGE_URI));
87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putInt(KEY_SUB_ID,
88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                extras.getInt(SendMessageAction.KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID));
89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putInt(KEY_RESULT_CODE, resultCode);
90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putInt(KEY_HTTP_STATUS_CODE, extras.getInt(SmsManager.EXTRA_MMS_HTTP_STATUS, 0));
91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putParcelable(KEY_CONTENT_URI,
92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                extras.getParcelable(SendMessageAction.EXTRA_CONTENT_URI));
93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putByteArray(KEY_RESPONSE, extras.getByteArray(SmsManager.EXTRA_MMS_DATA));
94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putBoolean(KEY_RESPONSE_IMPORTANT,
95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                extras.getBoolean(SendMessageAction.EXTRA_RESPONSE_IMPORTANT));
96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        action.start();
97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static void processMessageSentFastFailed(final String messageId,
100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final Uri messageUri, final Uri updatedMessageUri, final int subId, final boolean isSms,
101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final int status, final int rawStatus, final int resultCode) {
102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final ProcessSentMessageAction action = new ProcessSentMessageAction();
103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Bundle params = action.actionParameters;
104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putBoolean(KEY_SMS, isSms);
105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putBoolean(KEY_SENT_BY_PLATFORM, false);
106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putString(KEY_MESSAGE_ID, messageId);
107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putParcelable(KEY_MESSAGE_URI, messageUri);
108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putParcelable(KEY_UPDATED_MESSAGE_URI, updatedMessageUri);
109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putInt(KEY_SUB_ID, subId);
110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putInt(KEY_STATUS, status);
111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putInt(KEY_RAW_STATUS, rawStatus);
112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        params.putInt(KEY_RESULT_CODE, resultCode);
113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        action.start();
114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private ProcessSentMessageAction() {
117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Callers must use one of the static methods above
118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    * Update message status to reflect success or failure
122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    * Can also update the message itself if a "final" message is now available from telephony db
123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    */
124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    protected Object executeAction() {
126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Context context = Factory.get().getApplicationContext();
127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String messageId = actionParameters.getString(KEY_MESSAGE_ID);
128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Uri messageUri = actionParameters.getParcelable(KEY_MESSAGE_URI);
129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Uri updatedMessageUri = actionParameters.getParcelable(KEY_UPDATED_MESSAGE_URI);
130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final boolean isSms = actionParameters.getBoolean(KEY_SMS);
131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final boolean sentByPlatform = actionParameters.getBoolean(KEY_SENT_BY_PLATFORM);
132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        int status = actionParameters.getInt(KEY_STATUS, MmsUtils.MMS_REQUEST_MANUAL_RETRY);
134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        int rawStatus = actionParameters.getInt(KEY_RAW_STATUS,
135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                MmsUtils.PDU_HEADER_VALUE_UNDEFINED);
136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final int subId = actionParameters.getInt(KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (sentByPlatform) {
139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // Delete temporary file backing the contentUri passed to MMS service
140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final Uri contentUri = actionParameters.getParcelable(KEY_CONTENT_URI);
141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            Assert.isTrue(contentUri != null);
142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final File tempFile = MmsFileProvider.getFile(contentUri);
143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            long messageSize = 0;
144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (tempFile.exists()) {
145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                messageSize = tempFile.length();
146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                tempFile.delete();
147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    LogUtil.v(TAG, "ProcessSentMessageAction: Deleted temp file with outgoing "
149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                            + "MMS pdu: " + contentUri);
150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final int resultCode = actionParameters.getInt(KEY_RESULT_CODE);
154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final boolean responseImportant = actionParameters.getBoolean(KEY_RESPONSE_IMPORTANT);
155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (resultCode == Activity.RESULT_OK) {
156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                if (responseImportant) {
157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    // Get the status from the response PDU and update telephony
158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    final byte[] response = actionParameters.getByteArray(KEY_RESPONSE);
159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    final SendConf sendConf = MmsSender.parseSendConf(response, subId);
160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    if (sendConf != null) {
161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        final MmsUtils.StatusPlusUri result =
162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                                MmsUtils.updateSentMmsMessageStatus(context, messageUri, sendConf);
163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        status = result.status;
164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        rawStatus = result.rawStatus;
165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    }
166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            } else {
168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                String errorMsg = "ProcessSentMessageAction: Platform returned error resultCode: "
169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        + resultCode;
170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                final int httpStatusCode = actionParameters.getInt(KEY_HTTP_STATUS_CODE);
171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                if (httpStatusCode != 0) {
172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    errorMsg += (", HTTP status code: " + httpStatusCode);
173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                LogUtil.w(TAG, errorMsg);
175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                status = MmsSender.getErrorResultStatus(resultCode, httpStatusCode);
176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // Check for MMS messages that failed because they exceeded the maximum size,
178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // indicated by an I/O error from the platform.
179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                if (resultCode == SmsManager.MMS_ERROR_IO_ERROR) {
180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    if (messageSize > MmsConfig.get(subId).getMaxMessageSize()) {
181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        rawStatus = MessageData.RAW_TELEPHONY_STATUS_MESSAGE_TOO_BIG;
182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    }
183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (messageId != null) {
187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final int resultCode = actionParameters.getInt(KEY_RESULT_CODE);
188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final int httpStatusCode = actionParameters.getInt(KEY_HTTP_STATUS_CODE);
189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            processResult(
190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    messageId, updatedMessageUri, status, rawStatus, isSms, this, subId,
191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    resultCode, httpStatusCode);
192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } else {
193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                LogUtil.v(TAG, "ProcessSentMessageAction: No sent message to process (it was "
195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        + "probably a notify response for an MMS download)");
196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return null;
199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    static void processResult(final String messageId, Uri updatedMessageUri, int status,
202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final int rawStatus, final boolean isSms, final Action processingAction,
203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final int subId, final int resultCode, final int httpStatusCode) {
204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final DatabaseWrapper db = DataModel.get().getDatabase();
205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        MessageData message = BugleDatabaseOperations.readMessage(db, messageId);
206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final MessageData originalMessage = message;
207d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (message == null) {
208d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            LogUtil.w(TAG, "ProcessSentMessageAction: Sent message " + messageId
209d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    + " missing from local database");
210d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            return;
211d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
212d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String conversationId = message.getConversationId();
213d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (updatedMessageUri != null) {
214d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // Update message if we have newly written final message in the telephony db
215d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final MessageData update = MmsUtils.readSendingMmsMessage(updatedMessageUri,
216d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    conversationId, message.getParticipantId(), message.getSelfId());
217d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (update != null) {
218d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // Set message Id of final message to that of the existing place holder.
219d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                update.updateMessageId(message.getMessageId());
220d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // Update image sizes.
221d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                update.updateSizesForImageParts();
222d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // Temp attachments are no longer needed
223d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                for (final MessagePartData part : message.getParts()) {
224d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    part.destroySync();
225d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
226d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                message = update;
227d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // processResult will rewrite the complete message as part of update
228d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            } else {
229d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                updatedMessageUri = null;
230d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                status = MmsUtils.MMS_REQUEST_MANUAL_RETRY;
231d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                LogUtil.e(TAG, "ProcessSentMessageAction: Unable to read sending message");
232d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
233d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
234d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
235d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final long timestamp = System.currentTimeMillis();
236d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        boolean failed;
237d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (status == MmsUtils.MMS_REQUEST_SUCCEEDED) {
238d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            message.markMessageSent(timestamp);
239d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            failed = false;
240d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } else if (status == MmsUtils.MMS_REQUEST_AUTO_RETRY
241d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                && message.getInResendWindow(timestamp)) {
242d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            message.markMessageNotSent(timestamp);
243d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            message.setRawTelephonyStatus(rawStatus);
244d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            failed = false;
245d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } else {
246d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            message.markMessageFailed(timestamp);
247d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            message.setRawTelephonyStatus(rawStatus);
248d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            message.setMessageSeen(false);
249d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            failed = true;
250d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
251d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
252d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // We have special handling for when a message to an emergency number fails. In this case,
253d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // we notify immediately of any failure (even if we auto-retry), and instruct the user to
254d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // try calling the emergency number instead.
255d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (status != MmsUtils.MMS_REQUEST_SUCCEEDED) {
256d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final ArrayList<String> recipients =
257d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    BugleDatabaseOperations.getRecipientsForConversation(db, conversationId);
258d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            for (final String recipient : recipients) {
259d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                if (PhoneNumberUtils.isEmergencyNumber(recipient)) {
260d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    BugleNotifications.notifyEmergencySmsFailed(recipient, conversationId);
261d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    message.markMessageFailedEmergencyNumber(timestamp);
262d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    failed = true;
263d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    break;
264d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
265d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
266d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
267d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
268d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Update the message status and optionally refresh the message with final parts/values.
269d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (SendMessageAction.updateMessageAndStatus(isSms, message, updatedMessageUri, failed)) {
270d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // We shouldn't show any notifications if we're not allowed to modify Telephony for
271d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // this message.
272d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (failed) {
273d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                BugleNotifications.update(false, BugleNotifications.UPDATE_ERRORS);
274d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
275d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            BugleActionToasts.onSendMessageOrManualDownloadActionCompleted(
276d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    conversationId, !failed, status, isSms, subId, true/*isSend*/);
277d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
278d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
279d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        LogUtil.i(TAG, "ProcessSentMessageAction: Done sending " + (isSms ? "SMS" : "MMS")
280d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                + " message " + message.getMessageId()
281d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                + " in conversation " + conversationId
282d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                + "; status is " + MmsUtils.getRequestStatusDescription(status));
283d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
284d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Whether we succeeded or failed we will check and maybe schedule some more work
285d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        ProcessPendingMessagesAction.scheduleProcessPendingMessagesAction(
286d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                status != MmsUtils.MMS_REQUEST_SUCCEEDED, processingAction);
287d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
288d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
289d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private ProcessSentMessageAction(final Parcel in) {
290d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        super(in);
291d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
292d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
293d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final Parcelable.Creator<ProcessSentMessageAction> CREATOR
294d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            = new Parcelable.Creator<ProcessSentMessageAction>() {
295d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        @Override
296d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        public ProcessSentMessageAction createFromParcel(final Parcel in) {
297d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            return new ProcessSentMessageAction(in);
298d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
299d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
300d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        @Override
301d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        public ProcessSentMessageAction[] newArray(final int size) {
302d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            return new ProcessSentMessageAction[size];
303d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
304d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    };
305d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
306d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
307d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void writeToParcel(final Parcel parcel, final int flags) {
308d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        writeActionToParcel(parcel, flags);
309d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
310d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd}
311