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.content.Intent; 22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.Cursor; 23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.net.ConnectivityManager; 24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.os.Parcel; 25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.os.Parcelable; 26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.telephony.ServiceState; 27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.Factory; 29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.BugleDatabaseOperations; 30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DataModel; 31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DatabaseHelper; 32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DatabaseHelper.MessageColumns; 33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DatabaseWrapper; 34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.MessagingContentProvider; 35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.MessageData; 36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ParticipantData; 37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.sms.MmsUtils; 38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.BugleGservices; 39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.BugleGservicesKeys; 40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.BuglePrefs; 41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.BuglePrefsKeys; 42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.ConnectivityUtil.ConnectivityListener; 43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.LogUtil; 44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.OsUtil; 45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.PhoneUtils; 46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.HashSet; 48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.Set; 49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/** 51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Action used to lookup any messages in the pending send/download state and either fail them or 52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * retry their action. This action only initiates one retry at a time - further retries should be 53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * triggered by successful sending of a message, network status change or exponential backoff timer. 54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class ProcessPendingMessagesAction extends Action implements Parcelable { 56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG; 57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final int PENDING_INTENT_REQUEST_CODE = 101; 58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static void processFirstPendingMessage() { 60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Clear any pending alarms or connectivity events 61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd unregister(); 62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Clear retry count 63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setRetry(0); 64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Start action 66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ProcessPendingMessagesAction action = new ProcessPendingMessagesAction(); 67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd action.start(); 68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static void scheduleProcessPendingMessagesAction(final boolean failed, 71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Action processingAction) { 72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.i(TAG, "ProcessPendingMessagesAction: Scheduling pending messages" 73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + (failed ? "(message failed)" : "")); 74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Can safely clear any pending alarms or connectivity events as either an action 75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // is currently running or we will run now or register if pending actions possible. 76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd unregister(); 77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean isDefaultSmsApp = PhoneUtils.getDefault().isDefaultSmsApp(); 79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean scheduleAlarm = false; 80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If message succeeded and if Bugle is default SMS app just carry on with next message 81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!failed && isDefaultSmsApp) { 82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Clear retry attempt count as something just succeeded 83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setRetry(0); 84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Lookup and queue next message for immediate processing by background worker 86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // iff there are no pending messages this will do nothing and return true. 87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ProcessPendingMessagesAction action = new ProcessPendingMessagesAction(); 88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (action.queueActions(processingAction)) { 89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (processingAction.hasBackgroundActions()) { 91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "ProcessPendingMessagesAction: Action queued"); 92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "ProcessPendingMessagesAction: No actions to queue"); 94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Have queued next action if needed, nothing more to do 97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return; 98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // In case of error queuing schedule a retry 100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd scheduleAlarm = true; 101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.w(TAG, "ProcessPendingMessagesAction: Action failed to queue; retrying"); 102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (getHavePendingMessages() || scheduleAlarm) { 104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Still have a pending message that needs to be queued for processing 105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ConnectivityListener listener = new ConnectivityListener() { 106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void onConnectivityStateChanged(final Context context, final Intent intent) { 108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int networkType = 109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MmsUtils.getConnectivityEventNetworkType(context, intent); 110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (networkType != ConnectivityManager.TYPE_MOBILE) { 111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return; 112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean isConnected = !intent.getBooleanExtra( 114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); 115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // TODO: Should we check in more detail? 116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isConnected) { 117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd onConnected(); 118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void onPhoneStateChanged(final Context context, final int serviceState) { 123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (serviceState == ServiceState.STATE_IN_SERVICE) { 124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd onConnected(); 125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void onConnected() { 129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.i(TAG, "ProcessPendingMessagesAction: Now connected; starting action"); 130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Clear any pending alarms or connectivity events but leave attempt count alone 132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd unregister(); 133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Start action 135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ProcessPendingMessagesAction action = new ProcessPendingMessagesAction(); 136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd action.start(); 137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Read and increment attempt number from shared prefs 140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int retryAttempt = getNextRetry(); 141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd register(listener, retryAttempt); 142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // No more pending messages (presumably the message that failed has expired) or it 144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // may be possible that a send and a download are already in process. 145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Clear retry attempt count. 146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // TODO Might be premature if send and download in process... 147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // but worst case means we try to send a bit more often. 148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setRetry(0); 149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "ProcessPendingMessagesAction: No more pending messages"); 152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static void register(final ConnectivityListener listener, final int retryAttempt) { 157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int retryNumber = retryAttempt; 158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Register to be notified about connectivity changes 160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DataModel.get().getConnectivityUtil().register(listener); 161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ProcessPendingMessagesAction action = new ProcessPendingMessagesAction(); 163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long initialBackoffMs = BugleGservices.get().getLong( 164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleGservicesKeys.INITIAL_MESSAGE_RESEND_DELAY_MS, 165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleGservicesKeys.INITIAL_MESSAGE_RESEND_DELAY_MS_DEFAULT); 166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long maxDelayMs = BugleGservices.get().getLong( 167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleGservicesKeys.MAX_MESSAGE_RESEND_DELAY_MS, 168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleGservicesKeys.MAX_MESSAGE_RESEND_DELAY_MS_DEFAULT); 169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd long delayMs; 170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd long nextDelayMs = initialBackoffMs; 171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd do { 172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd delayMs = nextDelayMs; 173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd retryNumber--; 174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd nextDelayMs = delayMs * 2; 175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd while (retryNumber > 0 && nextDelayMs < maxDelayMs); 177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.i(TAG, "ProcessPendingMessagesAction: Registering for retry #" + retryAttempt 179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + " in " + delayMs + " ms"); 180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd action.schedule(PENDING_INTENT_REQUEST_CODE, delayMs); 182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static void unregister() { 185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Clear any pending alarms or connectivity events 186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DataModel.get().getConnectivityUtil().unregister(); 187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ProcessPendingMessagesAction action = new ProcessPendingMessagesAction(); 189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd action.schedule(PENDING_INTENT_REQUEST_CODE, Long.MAX_VALUE); 190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "ProcessPendingMessagesAction: Unregistering for connectivity changed " 193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + "events and clearing scheduled alarm"); 194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static void setRetry(final int retryAttempt) { 198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final BuglePrefs prefs = Factory.get().getApplicationPrefs(); 199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd prefs.putInt(BuglePrefsKeys.PROCESS_PENDING_MESSAGES_RETRY_COUNT, retryAttempt); 200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static int getNextRetry() { 203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final BuglePrefs prefs = Factory.get().getApplicationPrefs(); 204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int retryAttempt = 205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd prefs.getInt(BuglePrefsKeys.PROCESS_PENDING_MESSAGES_RETRY_COUNT, 0) + 1; 206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd prefs.putInt(BuglePrefsKeys.PROCESS_PENDING_MESSAGES_RETRY_COUNT, retryAttempt); 207d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return retryAttempt; 208d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 209d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 210d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private ProcessPendingMessagesAction() { 211d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 212d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 213d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 214d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Read from the DB and determine if there are any messages we should process 215d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return true if we have pending messages 216d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 217d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static boolean getHavePendingMessages() { 218d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final DatabaseWrapper db = DataModel.get().getDatabase(); 219d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long now = System.currentTimeMillis(); 220d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 221d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String toSendMessageId = findNextMessageToSend(db, now); 222d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (toSendMessageId != null) { 223d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return true; 224d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 225d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String toDownloadMessageId = findNextMessageToDownload(db, now); 226d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (toDownloadMessageId != null) { 227d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return true; 228d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 229d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 230d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Messages may be in the process of sending/downloading even when there are no pending 231d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // messages... 232d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 233d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 234d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 235d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 236d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Queue any pending actions 237d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param actionState 238d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return true if action queued (or no actions to queue) else false 239d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 240d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private boolean queueActions(final Action processingAction) { 241d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final DatabaseWrapper db = DataModel.get().getDatabase(); 242d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long now = System.currentTimeMillis(); 243d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean succeeded = true; 244d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 245d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Will queue no more than one message to send plus one message to download 246d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // This keeps outgoing messages "in order" but allow downloads to happen even if sending 247d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // gets blocked until messages time out. Manual resend bumps messages to head of queue. 248d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String toSendMessageId = findNextMessageToSend(db, now); 249d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String toDownloadMessageId = findNextMessageToDownload(db, now); 250d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (toSendMessageId != null) { 251d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.i(TAG, "ProcessPendingMessagesAction: Queueing message " + toSendMessageId 252d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + " for sending"); 253d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // This could queue nothing 254d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!SendMessageAction.queueForSendInBackground(toSendMessageId, processingAction)) { 255d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.w(TAG, "ProcessPendingMessagesAction: Failed to queue message " 256d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + toSendMessageId + " for sending"); 257d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd succeeded = false; 258d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 259d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 260d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (toDownloadMessageId != null) { 261d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.i(TAG, "ProcessPendingMessagesAction: Queueing message " + toDownloadMessageId 262d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + " for download"); 263d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // This could queue nothing 264d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!DownloadMmsAction.queueMmsForDownloadInBackground(toDownloadMessageId, 265d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd processingAction)) { 266d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.w(TAG, "ProcessPendingMessagesAction: Failed to queue message " 267d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + toDownloadMessageId + " for download"); 268d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd succeeded = false; 269d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 270d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 271d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (toSendMessageId == null && toDownloadMessageId == null) { 272d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) { 273d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.d(TAG, "ProcessPendingMessagesAction: No messages to send or download"); 274d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 275d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 276d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return succeeded; 277d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 278d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 279d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 280d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected Object executeAction() { 281d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If triggered by alarm will not have unregistered yet 282d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd unregister(); 283d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 284d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (PhoneUtils.getDefault().isDefaultSmsApp()) { 285d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd queueActions(this); 286d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 287d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 288d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "ProcessPendingMessagesAction: Not default SMS app; rescheduling"); 289d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 290d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd scheduleProcessPendingMessagesAction(true, this); 291d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 292d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 293d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 294d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 295d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 296d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static String findNextMessageToSend(final DatabaseWrapper db, final long now) { 297d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String toSendMessageId = null; 298d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.beginTransaction(); 299d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Cursor sending = null; 300d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Cursor cursor = null; 301d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int sendingCnt = 0; 302d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int pendingCnt = 0; 303d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int failedCnt = 0; 304d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 305d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // First check to see if we have any messages already sending 306d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd sending = db.query(DatabaseHelper.MESSAGES_TABLE, 307d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessageData.getProjection(), 308d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DatabaseHelper.MessageColumns.STATUS + " IN (?, ?)", 309d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new String[]{Integer.toString(MessageData.BUGLE_STATUS_OUTGOING_SENDING), 310d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Integer.toString(MessageData.BUGLE_STATUS_OUTGOING_RESENDING)}, 311d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd null, 312d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd null, 313d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DatabaseHelper.MessageColumns.RECEIVED_TIMESTAMP + " ASC"); 314d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean messageCurrentlySending = sending.moveToNext(); 315d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd sendingCnt = sending.getCount(); 316d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Look for messages we could send 317d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ContentValues values = new ContentValues(); 318d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(DatabaseHelper.MessageColumns.STATUS, 319d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessageData.BUGLE_STATUS_OUTGOING_FAILED); 320d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor = db.query(DatabaseHelper.MESSAGES_TABLE, 321d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessageData.getProjection(), 322d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DatabaseHelper.MessageColumns.STATUS + " IN (" 323d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + MessageData.BUGLE_STATUS_OUTGOING_YET_TO_SEND + "," 324d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + MessageData.BUGLE_STATUS_OUTGOING_AWAITING_RETRY + ")", 325d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd null, 326d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd null, 327d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd null, 328d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DatabaseHelper.MessageColumns.RECEIVED_TIMESTAMP + " ASC"); 329d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd pendingCnt = cursor.getCount(); 330d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 331d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd while (cursor.moveToNext()) { 332d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final MessageData message = new MessageData(); 333d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd message.bind(cursor); 334d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (message.getInResendWindow(now)) { 335d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If no messages currently sending 336d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!messageCurrentlySending) { 337d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Resend this message 338d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd toSendMessageId = message.getMessageId(); 339d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Before queuing the message for resending, check if the message's self is 340d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // active. If not, switch back to the system's default subscription. 341d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (OsUtil.isAtLeastL_MR1()) { 342d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ParticipantData messageSelf = BugleDatabaseOperations 343d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .getExistingParticipant(db, message.getSelfId()); 344d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (messageSelf == null || !messageSelf.isActiveSubscription()) { 345d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ParticipantData defaultSelf = BugleDatabaseOperations 346d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .getOrCreateSelf(db, PhoneUtils.getDefault() 347d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .getDefaultSmsSubscriptionId()); 348d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (defaultSelf != null) { 349d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd message.bindSelfId(defaultSelf.getId()); 350d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ContentValues selfValues = new ContentValues(); 351d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selfValues.put(MessageColumns.SELF_PARTICIPANT_ID, 352d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd defaultSelf.getId()); 353d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleDatabaseOperations.updateMessageRow(db, 354d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd message.getMessageId(), selfValues); 355d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessagingContentProvider.notifyMessagesChanged( 356d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd message.getConversationId()); 357d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 358d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 359d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 360d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 361d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 362d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 363d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd failedCnt++; 364d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 365d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Mark message as failed 366d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleDatabaseOperations.updateMessageRow(db, message.getMessageId(), values); 367d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessagingContentProvider.notifyMessagesChanged(message.getConversationId()); 368d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 369d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 370d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.setTransactionSuccessful(); 371d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 372d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.endTransaction(); 373d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (cursor != null) { 374d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor.close(); 375d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 376d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (sending != null) { 377d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd sending.close(); 378d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 379d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 380d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 381d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) { 382d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.d(TAG, "ProcessPendingMessagesAction: " 383d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + sendingCnt + " messages already sending, " 384d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + pendingCnt + " messages to send, " 385d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + failedCnt + " failed messages"); 386d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 387d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 388d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return toSendMessageId; 389d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 390d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 391d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static String findNextMessageToDownload(final DatabaseWrapper db, final long now) { 392d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String toDownloadMessageId = null; 393d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.beginTransaction(); 394d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Cursor cursor = null; 395d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int downloadingCnt = 0; 396d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int pendingCnt = 0; 397d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 398d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // First check if we have any messages already downloading 399d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd downloadingCnt = (int) db.queryNumEntries(DatabaseHelper.MESSAGES_TABLE, 400d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DatabaseHelper.MessageColumns.STATUS + " IN (?, ?)", 401d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new String[] { 402d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Integer.toString(MessageData.BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING), 403d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Integer.toString(MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING) 404d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }); 405d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 406d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // TODO: This query is not actually needed if downloadingCnt == 0. 407d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor = db.query(DatabaseHelper.MESSAGES_TABLE, 408d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessageData.getProjection(), 409d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DatabaseHelper.MessageColumns.STATUS + " =? OR " 410d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + DatabaseHelper.MessageColumns.STATUS + " =?", 411d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new String[]{ 412d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Integer.toString( 413d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD), 414d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Integer.toString( 415d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD) 416d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }, 417d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd null, 418d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd null, 419d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DatabaseHelper.MessageColumns.RECEIVED_TIMESTAMP + " ASC"); 420d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 421d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd pendingCnt = cursor.getCount(); 422d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 423d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If no messages are currently downloading and there is a download pending, 424d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // queue the download of the oldest pending message. 425d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (downloadingCnt == 0 && cursor.moveToNext()) { 426d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Always start the next pending message. We will check if a download has 427d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // expired in DownloadMmsAction and mark message failed there. 428d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final MessageData message = new MessageData(); 429d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd message.bind(cursor); 430d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd toDownloadMessageId = message.getMessageId(); 431d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 432d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.setTransactionSuccessful(); 433d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 434d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.endTransaction(); 435d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (cursor != null) { 436d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor.close(); 437d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 438d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 439d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 440d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) { 441d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.d(TAG, "ProcessPendingMessagesAction: " 442d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + downloadingCnt + " messages already downloading, " 443d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + pendingCnt + " messages to download"); 444d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 445d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 446d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return toDownloadMessageId; 447d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 448d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 449d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private ProcessPendingMessagesAction(final Parcel in) { 450d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd super(in); 451d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 452d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 453d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final Parcelable.Creator<ProcessPendingMessagesAction> CREATOR 454d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd = new Parcelable.Creator<ProcessPendingMessagesAction>() { 455d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 456d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public ProcessPendingMessagesAction createFromParcel(final Parcel in) { 457d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new ProcessPendingMessagesAction(in); 458d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 459d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 460d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 461d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public ProcessPendingMessagesAction[] newArray(final int size) { 462d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new ProcessPendingMessagesAction[size]; 463d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 464d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 465d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 466d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 467d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void writeToParcel(final Parcel parcel, final int flags) { 468d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd writeActionToParcel(parcel, flags); 469d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 470d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd} 471