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.content.ContentValues;
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 Dodd
26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.Factory;
27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.BugleDatabaseOperations;
28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DataModel;
29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DatabaseWrapper;
31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.MessagingContentProvider;
32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.SyncManager;
33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.MessageData;
34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ParticipantData;
35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.sms.MmsUtils;
36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.Assert;
37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.Assert.RunsOnMainThread;
38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.LogUtil;
39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/**
41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Downloads an MMS message.
42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * <p>
43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * This class is public (not package-private) because the SMS/MMS (e.g. MmsUtils) classes need to
44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * access the EXTRA_* fields for setting up the 'downloaded' pending intent.
45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */
46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class DownloadMmsAction extends Action implements Parcelable {
47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Interface for DownloadMmsAction listeners
51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public interface DownloadMmsActionListener {
53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        @RunsOnMainThread
54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        abstract void onDownloadMessageStarting(final ActionMonitor monitor,
55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                final Object data, final MessageData message);
56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        @RunsOnMainThread
57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        abstract void onDownloadMessageSucceeded(final ActionMonitor monitor,
58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                final Object data, final MessageData message);
59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        @RunsOnMainThread
60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        abstract void onDownloadMessageFailed(final ActionMonitor monitor,
61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                final Object data, final MessageData message);
62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Queue download of an mms notification message (can only be called during execute of action)
66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    static boolean queueMmsForDownloadInBackground(final String messageId,
68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final Action processingAction) {
69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // When this method is being called, it is always from auto download
70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final DownloadMmsAction action = new DownloadMmsAction();
71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // This could queue nothing
72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return action.queueAction(messageId, processingAction);
73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_MESSAGE_ID = "message_id";
76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_CONVERSATION_ID = "conversation_id";
77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_PARTICIPANT_ID = "participant_id";
78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_CONTENT_LOCATION = "content_location";
79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_TRANSACTION_ID = "transaction_id";
80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_NOTIFICATION_URI = "notification_uri";
81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_SUB_ID = "sub_id";
82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_SUB_PHONE_NUMBER = "sub_phone_number";
83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_AUTO_DOWNLOAD = "auto_download";
84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String KEY_FAILURE_STATUS = "failure_status";
85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    // Values we attach to the pending intent that's fired when the message is downloaded.
87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    // Only applicable when downloading via the platform APIs on L+.
88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final String EXTRA_MESSAGE_ID = "message_id";
89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final String EXTRA_CONTENT_URI = "content_uri";
90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final String EXTRA_NOTIFICATION_URI = "notification_uri";
91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final String EXTRA_SUB_ID = "sub_id";
92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final String EXTRA_SUB_PHONE_NUMBER = "sub_phone_number";
93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final String EXTRA_TRANSACTION_ID = "transaction_id";
94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final String EXTRA_CONTENT_LOCATION = "content_location";
95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final String EXTRA_AUTO_DOWNLOAD = "auto_download";
96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final String EXTRA_RECEIVED_TIMESTAMP = "received_timestamp";
97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final String EXTRA_CONVERSATION_ID = "conversation_id";
98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final String EXTRA_PARTICIPANT_ID = "participant_id";
99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final String EXTRA_STATUS_IF_FAILED = "status_if_failed";
100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private DownloadMmsAction() {
102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        super();
103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    protected Object executeAction() {
107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        Assert.fail("DownloadMmsAction must be queued rather than started");
108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return null;
109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    protected boolean queueAction(final String messageId, final Action processingAction) {
112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        actionParameters.putString(KEY_MESSAGE_ID, messageId);
113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final DatabaseWrapper db = DataModel.get().getDatabase();
115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Read the message from local db
116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final MessageData message = BugleDatabaseOperations.readMessage(db, messageId);
117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (message != null && message.canDownloadMessage()) {
118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final Uri notificationUri = message.getSmsMessageUri();
119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final String conversationId = message.getConversationId();
120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final int status = message.getStatus();
121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final String selfId = message.getSelfId();
123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final ParticipantData self = BugleDatabaseOperations
124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    .getExistingParticipant(db, selfId);
125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final int subId = self.getSubId();
126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            actionParameters.putInt(KEY_SUB_ID, subId);
127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            actionParameters.putString(KEY_CONVERSATION_ID, conversationId);
128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            actionParameters.putString(KEY_PARTICIPANT_ID, message.getParticipantId());
129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            actionParameters.putString(KEY_CONTENT_LOCATION, message.getMmsContentLocation());
130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            actionParameters.putString(KEY_TRANSACTION_ID, message.getMmsTransactionId());
131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            actionParameters.putParcelable(KEY_NOTIFICATION_URI, notificationUri);
132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            actionParameters.putBoolean(KEY_AUTO_DOWNLOAD, isAutoDownload(status));
133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final long now = System.currentTimeMillis();
135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (message.getInDownloadWindow(now)) {
136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // We can still retry
137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                actionParameters.putString(KEY_SUB_PHONE_NUMBER, self.getNormalizedDestination());
138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                final int downloadingStatus = getDownloadingStatus(status);
140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // Update message status to indicate downloading.
141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                updateMessageStatus(notificationUri, messageId, conversationId,
142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        downloadingStatus, MessageData.RAW_TELEPHONY_STATUS_UNDEFINED);
143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // Pre-compute the next status when failed so we don't have to load from db again
144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                actionParameters.putInt(KEY_FAILURE_STATUS, getFailureStatus(downloadingStatus));
145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // Actual download happens in background
147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                processingAction.requestBackgroundWork(this);
148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    LogUtil.d(TAG,
151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                            "DownloadMmsAction: Queued download of MMS message " + messageId);
152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return true;
154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            } else {
155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                LogUtil.w(TAG, "DownloadMmsAction: Download of MMS message " + messageId
156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        + " failed (outside download window)");
157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // Retries depleted and we failed. Update the message status so we won't retry again
159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                updateMessageStatus(notificationUri, messageId, conversationId,
160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED,
161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        MessageData.RAW_TELEPHONY_STATUS_UNDEFINED);
162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                if (status == MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD) {
163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    // For auto download failure, we should send a DEFERRED NotifyRespInd
164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    // to carrier to indicate we will manual download later
165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    ProcessDownloadedMmsAction.sendDeferredRespStatus(
166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                            messageId, message.getMmsTransactionId(),
167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                            message.getMmsContentLocation(), subId);
168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    return true;
169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return false;
173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Find out the auto download state of this message based on its starting status
177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     *
178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @param status The starting status of the message.
179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @return True if this is a message doing auto downloading, false otherwise
180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static boolean isAutoDownload(final int status) {
182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        switch (status) {
183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            case MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD:
184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return false;
185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            case MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD:
186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return true;
187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            default:
188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                Assert.fail("isAutoDownload: invalid input status " + status);
189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return false;
190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Get the corresponding downloading status based on the starting status of the message
195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     *
196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @param status The starting status of the message.
197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @return The downloading status
198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static int getDownloadingStatus(final int status) {
200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        switch (status) {
201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            case MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD:
202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING;
203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            case MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD:
204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return MessageData.BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING;
205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            default:
206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                Assert.fail("isAutoDownload: invalid input status " + status);
207d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING;
208d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
209d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
210d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
211d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
212d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Get the corresponding failed status based on the current downloading status
213d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     *
214d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @param status The downloading status
215d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @return The status the message should have if downloading failed
216d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
217d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static int getFailureStatus(final int status) {
218d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        switch (status) {
219d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            case MessageData.BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING:
220d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD;
221d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            case MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING:
222d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD;
223d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            default:
224d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                Assert.fail("isAutoDownload: invalid input status " + status);
225d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD;
226d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
227d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
228d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
229d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
230d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    protected Bundle doBackgroundWork() {
231d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Context context = Factory.get().getApplicationContext();
232d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final int subId = actionParameters.getInt(KEY_SUB_ID);
233d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String messageId = actionParameters.getString(KEY_MESSAGE_ID);
234d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Uri notificationUri = actionParameters.getParcelable(KEY_NOTIFICATION_URI);
235d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String subPhoneNumber = actionParameters.getString(KEY_SUB_PHONE_NUMBER);
236d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String transactionId = actionParameters.getString(KEY_TRANSACTION_ID);
237d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String contentLocation = actionParameters.getString(KEY_CONTENT_LOCATION);
238d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final boolean autoDownload = actionParameters.getBoolean(KEY_AUTO_DOWNLOAD);
239d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
240d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String participantId = actionParameters.getString(KEY_PARTICIPANT_ID);
241d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final int statusIfFailed = actionParameters.getInt(KEY_FAILURE_STATUS);
242d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
243d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final long receivedTimestampRoundedToSecond =
244d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                1000 * ((System.currentTimeMillis() + 500) / 1000);
245d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
246d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        LogUtil.i(TAG, "DownloadMmsAction: Downloading MMS message " + messageId
247d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                + " (" + (autoDownload ? "auto" : "manual") + ")");
248d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
249d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Bundle some values we'll need after the message is downloaded (via platform APIs)
250d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Bundle extras = new Bundle();
251d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        extras.putString(EXTRA_MESSAGE_ID, messageId);
252d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        extras.putString(EXTRA_CONVERSATION_ID, conversationId);
253d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        extras.putString(EXTRA_PARTICIPANT_ID, participantId);
254d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        extras.putInt(EXTRA_STATUS_IF_FAILED, statusIfFailed);
255d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
256d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Start the download
257d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final MmsUtils.StatusPlusUri status = MmsUtils.downloadMmsMessage(context,
258d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                notificationUri, subId, subPhoneNumber, transactionId, contentLocation,
259d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                autoDownload, receivedTimestampRoundedToSecond / 1000L, extras);
260d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (status == MmsUtils.STATUS_PENDING) {
261d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // Async download; no status yet
262d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
263d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                LogUtil.d(TAG, "DownloadMmsAction: Downloading MMS message " + messageId
264d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        + " asynchronously; waiting for pending intent to signal completion");
265d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
266d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } else {
267d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // Inform sync that message has been added at local received timestamp
268d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final SyncManager syncManager = DataModel.get().getSyncManager();
269d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            syncManager.onNewMessageInserted(receivedTimestampRoundedToSecond);
270d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // Handle downloaded message
271d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            ProcessDownloadedMmsAction.processMessageDownloadFastFailed(messageId,
272d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    notificationUri, conversationId, participantId, contentLocation, subId,
273d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    subPhoneNumber, statusIfFailed, autoDownload, transactionId,
274d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    status.resultCode);
275d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
276d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return null;
277d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
278d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
279d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
280d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    protected Object processBackgroundResponse(final Bundle response) {
281d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Nothing to do here; post-download actions handled by ProcessDownloadedMmsAction
282d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return null;
283d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
284d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
285d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
286d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    protected Object processBackgroundFailure() {
287d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String messageId = actionParameters.getString(KEY_MESSAGE_ID);
288d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String transactionId = actionParameters.getString(KEY_TRANSACTION_ID);
289d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
290d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String participantId = actionParameters.getString(KEY_PARTICIPANT_ID);
291d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final int statusIfFailed = actionParameters.getInt(KEY_FAILURE_STATUS);
292d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final int subId = actionParameters.getInt(KEY_SUB_ID);
293d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
294d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        ProcessDownloadedMmsAction.processDownloadActionFailure(messageId,
295d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                MmsUtils.MMS_REQUEST_MANUAL_RETRY, MessageData.RAW_TELEPHONY_STATUS_UNDEFINED,
296d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                conversationId, participantId, statusIfFailed, subId, transactionId);
297d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
298d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return null;
299d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
300d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
301d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    static void updateMessageStatus(final Uri messageUri, final String messageId,
302d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final String conversationId, final int status, final int rawStatus) {
303d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Context context = Factory.get().getApplicationContext();
304d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Downloading status just kept in local DB but need to fix up telephony DB first
305d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (status == MessageData.BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING ||
306d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                status == MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING) {
307d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            MmsUtils.clearMmsStatus(context, messageUri);
308d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
309d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Then mark downloading status in our local DB
310d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final ContentValues values = new ContentValues();
311d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        values.put(MessageColumns.STATUS, status);
312d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        values.put(MessageColumns.RAW_TELEPHONY_STATUS, rawStatus);
313d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final DatabaseWrapper db = DataModel.get().getDatabase();
314d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        BugleDatabaseOperations.updateMessageRowIfExists(db, messageId, values);
315d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
316d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        MessagingContentProvider.notifyMessagesChanged(conversationId);
317d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
318d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
319d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private DownloadMmsAction(final Parcel in) {
320d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        super(in);
321d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
322d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
323d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final Parcelable.Creator<DownloadMmsAction> CREATOR
324d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            = new Parcelable.Creator<DownloadMmsAction>() {
325d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        @Override
326d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        public DownloadMmsAction createFromParcel(final Parcel in) {
327d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            return new DownloadMmsAction(in);
328d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
329d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
330d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        @Override
331d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        public DownloadMmsAction[] newArray(final int size) {
332d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            return new DownloadMmsAction[size];
333d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
334d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    };
335d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
336d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
337d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void writeToParcel(final Parcel parcel, final int flags) {
338d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        writeActionToParcel(parcel, flags);
339d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
340d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd}
341