diff options
author | Mike Dodd <mdodd@google.com> | 2015-08-12 18:48:39 +0000 |
---|---|---|
committer | Mike Dodd <mdodd@google.com> | 2015-08-12 18:48:39 +0000 |
commit | ef8c7abbcfc9c770385d6609a4b4bc70240ebdc4 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /src/com/android/messaging/datamodel/action/SyncMessagesAction.java | |
parent | 461a34b466cb4b13dbbc2ec6330b31e217b2ac4e (diff) | |
download | android_packages_apps_Messaging-ef8c7abbcfc9c770385d6609a4b4bc70240ebdc4.tar.gz android_packages_apps_Messaging-ef8c7abbcfc9c770385d6609a4b4bc70240ebdc4.tar.bz2 android_packages_apps_Messaging-ef8c7abbcfc9c770385d6609a4b4bc70240ebdc4.zip |
Revert "Initial checkin of AOSP Messaging app."
This reverts commit 461a34b466cb4b13dbbc2ec6330b31e217b2ac4e.
Change-Id: Iac4ca77eeaa94989e91dead49a7959c905bd3078
Diffstat (limited to 'src/com/android/messaging/datamodel/action/SyncMessagesAction.java')
-rw-r--r-- | src/com/android/messaging/datamodel/action/SyncMessagesAction.java | 637 |
1 files changed, 0 insertions, 637 deletions
diff --git a/src/com/android/messaging/datamodel/action/SyncMessagesAction.java b/src/com/android/messaging/datamodel/action/SyncMessagesAction.java deleted file mode 100644 index f4a3e1f..0000000 --- a/src/com/android/messaging/datamodel/action/SyncMessagesAction.java +++ /dev/null @@ -1,637 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.messaging.datamodel.action; - -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteException; -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.SystemClock; -import android.provider.Telephony.Mms; -import android.support.v4.util.LongSparseArray; - -import com.android.messaging.Factory; -import com.android.messaging.datamodel.DataModel; -import com.android.messaging.datamodel.DatabaseWrapper; -import com.android.messaging.datamodel.MessagingContentProvider; -import com.android.messaging.datamodel.SyncManager; -import com.android.messaging.datamodel.SyncManager.ThreadInfoCache; -import com.android.messaging.datamodel.data.ParticipantData; -import com.android.messaging.mmslib.SqliteWrapper; -import com.android.messaging.sms.DatabaseMessages; -import com.android.messaging.sms.DatabaseMessages.LocalDatabaseMessage; -import com.android.messaging.sms.DatabaseMessages.MmsMessage; -import com.android.messaging.sms.DatabaseMessages.SmsMessage; -import com.android.messaging.sms.MmsUtils; -import com.android.messaging.util.Assert; -import com.android.messaging.util.BugleGservices; -import com.android.messaging.util.BugleGservicesKeys; -import com.android.messaging.util.BuglePrefs; -import com.android.messaging.util.BuglePrefsKeys; -import com.android.messaging.util.ContentType; -import com.android.messaging.util.LogUtil; -import com.android.messaging.util.OsUtil; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -/** - * Action used to sync messages from smsmms db to local database - */ -public class SyncMessagesAction extends Action implements Parcelable { - static final long SYNC_FAILED = Long.MIN_VALUE; - - private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG; - - private static final String KEY_START_TIMESTAMP = "start_timestamp"; - private static final String KEY_MAX_UPDATE = "max_update"; - private static final String KEY_LOWER_BOUND = "lower_bound"; - private static final String KEY_UPPER_BOUND = "upper_bound"; - private static final String BUNDLE_KEY_LAST_TIMESTAMP = "last_timestamp"; - private static final String BUNDLE_KEY_SMS_MESSAGES = "sms_to_add"; - private static final String BUNDLE_KEY_MMS_MESSAGES = "mms_to_add"; - private static final String BUNDLE_KEY_MESSAGES_TO_DELETE = "messages_to_delete"; - - /** - * Start a full sync (backed off a few seconds to avoid pulling sending/receiving messages). - */ - public static void fullSync() { - final BugleGservices bugleGservices = BugleGservices.get(); - final long smsSyncBackoffTimeMillis = bugleGservices.getLong( - BugleGservicesKeys.SMS_SYNC_BACKOFF_TIME_MILLIS, - BugleGservicesKeys.SMS_SYNC_BACKOFF_TIME_MILLIS_DEFAULT); - - final long now = System.currentTimeMillis(); - // TODO: Could base this off most recent message in db but now should be okay... - final long startTimestamp = now - smsSyncBackoffTimeMillis; - - final SyncMessagesAction action = new SyncMessagesAction(-1L, startTimestamp, - 0, startTimestamp); - action.start(); - } - - /** - * Start an incremental sync to pull messages since last sync (backed off a few seconds).. - */ - public static void sync() { - final BugleGservices bugleGservices = BugleGservices.get(); - final long smsSyncBackoffTimeMillis = bugleGservices.getLong( - BugleGservicesKeys.SMS_SYNC_BACKOFF_TIME_MILLIS, - BugleGservicesKeys.SMS_SYNC_BACKOFF_TIME_MILLIS_DEFAULT); - - final long now = System.currentTimeMillis(); - // TODO: Could base this off most recent message in db but now should be okay... - final long startTimestamp = now - smsSyncBackoffTimeMillis; - - sync(startTimestamp); - } - - /** - * Start an incremental sync when the application starts up (no back off as not yet - * sending/receiving). - */ - public static void immediateSync() { - final long now = System.currentTimeMillis(); - // TODO: Could base this off most recent message in db but now should be okay... - final long startTimestamp = now; - - sync(startTimestamp); - } - - private static void sync(final long startTimestamp) { - if (!OsUtil.hasSmsPermission()) { - // Sync requires READ_SMS permission - return; - } - - final BuglePrefs prefs = BuglePrefs.getApplicationPrefs(); - // Lower bound is end of previous sync - final long syncLowerBoundTimeMillis = prefs.getLong(BuglePrefsKeys.LAST_SYNC_TIME, - BuglePrefsKeys.LAST_SYNC_TIME_DEFAULT); - - final SyncMessagesAction action = new SyncMessagesAction(syncLowerBoundTimeMillis, - startTimestamp, 0, startTimestamp); - action.start(); - } - - private SyncMessagesAction(final long lowerBound, final long upperBound, - final int maxMessagesToUpdate, final long startTimestamp) { - actionParameters.putLong(KEY_LOWER_BOUND, lowerBound); - actionParameters.putLong(KEY_UPPER_BOUND, upperBound); - actionParameters.putInt(KEY_MAX_UPDATE, maxMessagesToUpdate); - actionParameters.putLong(KEY_START_TIMESTAMP, startTimestamp); - } - - @Override - protected Object executeAction() { - final DatabaseWrapper db = DataModel.get().getDatabase(); - - long lowerBoundTimeMillis = actionParameters.getLong(KEY_LOWER_BOUND); - final long upperBoundTimeMillis = actionParameters.getLong(KEY_UPPER_BOUND); - final int initialMaxMessagesToUpdate = actionParameters.getInt(KEY_MAX_UPDATE); - final long startTimestamp = actionParameters.getLong(KEY_START_TIMESTAMP); - - if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) { - LogUtil.d(TAG, "SyncMessagesAction: Request to sync messages from " - + lowerBoundTimeMillis + " to " + upperBoundTimeMillis + " (start timestamp = " - + startTimestamp + ", message update limit = " + initialMaxMessagesToUpdate - + ")"); - } - - final SyncManager syncManager = DataModel.get().getSyncManager(); - if (lowerBoundTimeMillis >= 0) { - // Cursors - final SyncCursorPair cursors = new SyncCursorPair(-1L, lowerBoundTimeMillis); - final boolean inSync = cursors.isSynchronized(db); - if (!inSync) { - if (syncManager.delayUntilFullSync(startTimestamp) == 0) { - lowerBoundTimeMillis = -1; - actionParameters.putLong(KEY_LOWER_BOUND, lowerBoundTimeMillis); - - if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) { - LogUtil.d(TAG, "SyncMessagesAction: Messages before " - + lowerBoundTimeMillis + " not in sync; promoting to full sync"); - } - } else if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) { - LogUtil.d(TAG, "SyncMessagesAction: Messages before " - + lowerBoundTimeMillis + " not in sync; will do incremental sync"); - } - } else { - if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) { - LogUtil.d(TAG, "SyncMessagesAction: Messages before " + lowerBoundTimeMillis - + " are in sync"); - } - } - } - - // Check if sync allowed (can be too soon after last or one is already running) - if (syncManager.shouldSync(lowerBoundTimeMillis < 0, startTimestamp)) { - syncManager.startSyncBatch(upperBoundTimeMillis); - requestBackgroundWork(); - } - - return null; - } - - @Override - protected Bundle doBackgroundWork() { - final BugleGservices bugleGservices = BugleGservices.get(); - final DatabaseWrapper db = DataModel.get().getDatabase(); - - final int maxMessagesToScan = bugleGservices.getInt( - BugleGservicesKeys.SMS_SYNC_BATCH_MAX_MESSAGES_TO_SCAN, - BugleGservicesKeys.SMS_SYNC_BATCH_MAX_MESSAGES_TO_SCAN_DEFAULT); - - final int initialMaxMessagesToUpdate = actionParameters.getInt(KEY_MAX_UPDATE); - final int smsSyncSubsequentBatchSizeMin = bugleGservices.getInt( - BugleGservicesKeys.SMS_SYNC_BATCH_SIZE_MIN, - BugleGservicesKeys.SMS_SYNC_BATCH_SIZE_MIN_DEFAULT); - final int smsSyncSubsequentBatchSizeMax = bugleGservices.getInt( - BugleGservicesKeys.SMS_SYNC_BATCH_SIZE_MAX, - BugleGservicesKeys.SMS_SYNC_BATCH_SIZE_MAX_DEFAULT); - - // Cap sync size to GServices limits - final int maxMessagesToUpdate = Math.max(smsSyncSubsequentBatchSizeMin, - Math.min(initialMaxMessagesToUpdate, smsSyncSubsequentBatchSizeMax)); - - final long lowerBoundTimeMillis = actionParameters.getLong(KEY_LOWER_BOUND); - final long upperBoundTimeMillis = actionParameters.getLong(KEY_UPPER_BOUND); - - LogUtil.i(TAG, "SyncMessagesAction: Starting batch for messages from " - + lowerBoundTimeMillis + " to " + upperBoundTimeMillis - + " (message update limit = " + maxMessagesToUpdate + ", message scan limit = " - + maxMessagesToScan + ")"); - - // Clear last change time so that we can work out if this batch is dirty when it completes - final SyncManager syncManager = DataModel.get().getSyncManager(); - - // Clear the singleton cache that maps threads to recipients and to conversations. - final SyncManager.ThreadInfoCache cache = syncManager.getThreadInfoCache(); - cache.clear(); - - // Sms messages to store - final ArrayList<SmsMessage> smsToAdd = new ArrayList<SmsMessage>(); - // Mms messages to store - final LongSparseArray<MmsMessage> mmsToAdd = new LongSparseArray<MmsMessage>(); - // List of local SMS/MMS to remove - final ArrayList<LocalDatabaseMessage> messagesToDelete = - new ArrayList<LocalDatabaseMessage>(); - - long lastTimestampMillis = SYNC_FAILED; - if (syncManager.isSyncing(upperBoundTimeMillis)) { - // Cursors - final SyncCursorPair cursors = new SyncCursorPair(lowerBoundTimeMillis, - upperBoundTimeMillis); - - // Actually compare the messages using cursor pair - lastTimestampMillis = syncCursorPair(db, cursors, smsToAdd, mmsToAdd, - messagesToDelete, maxMessagesToScan, maxMessagesToUpdate, cache); - } - final Bundle response = new Bundle(); - - // If comparison succeeds bundle up the changes for processing in ActionService - if (lastTimestampMillis > SYNC_FAILED) { - final ArrayList<MmsMessage> mmsToAddList = new ArrayList<MmsMessage>(); - for (int i = 0; i < mmsToAdd.size(); i++) { - final MmsMessage mms = mmsToAdd.valueAt(i); - mmsToAddList.add(mms); - } - - response.putParcelableArrayList(BUNDLE_KEY_SMS_MESSAGES, smsToAdd); - response.putParcelableArrayList(BUNDLE_KEY_MMS_MESSAGES, mmsToAddList); - response.putParcelableArrayList(BUNDLE_KEY_MESSAGES_TO_DELETE, messagesToDelete); - } - response.putLong(BUNDLE_KEY_LAST_TIMESTAMP, lastTimestampMillis); - - return response; - } - - /** - * Compare messages based on timestamp and uri - * @param db local database wrapper - * @param cursors cursor pair holding references to local and remote messages - * @param smsToAdd newly found sms messages to add - * @param mmsToAdd newly found mms messages to add - * @param messagesToDelete messages not found needing deletion - * @param maxMessagesToScan max messages to scan for changes - * @param maxMessagesToUpdate max messages to return for updates - * @param cache cache for conversation id / thread id / recipient set mapping - * @return timestamp of the oldest message seen during the sync scan - */ - private long syncCursorPair(final DatabaseWrapper db, final SyncCursorPair cursors, - final ArrayList<SmsMessage> smsToAdd, final LongSparseArray<MmsMessage> mmsToAdd, - final ArrayList<LocalDatabaseMessage> messagesToDelete, final int maxMessagesToScan, - final int maxMessagesToUpdate, final ThreadInfoCache cache) { - long lastTimestampMillis; - final long startTimeMillis = SystemClock.elapsedRealtime(); - - // Number of messages scanned local and remote - int localPos = 0; - int remotePos = 0; - int localTotal = 0; - int remoteTotal = 0; - // Scan through the messages on both sides and prepare messages for local message table - // changes (including adding and deleting) - try { - cursors.query(db); - - localTotal = cursors.getLocalCount(); - remoteTotal = cursors.getRemoteCount(); - - if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) { - LogUtil.d(TAG, "SyncMessagesAction: Scanning cursors (local count = " + localTotal - + ", remote count = " + remoteTotal + ", message update limit = " - + maxMessagesToUpdate + ", message scan limit = " + maxMessagesToScan - + ")"); - } - - lastTimestampMillis = cursors.scan(maxMessagesToScan, maxMessagesToUpdate, - smsToAdd, mmsToAdd, messagesToDelete, cache); - - localPos = cursors.getLocalPosition(); - remotePos = cursors.getRemotePosition(); - - if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) { - LogUtil.d(TAG, "SyncMessagesAction: Scanned cursors (local position = " + localPos - + " of " + localTotal + ", remote position = " + remotePos + " of " - + remoteTotal + ")"); - } - - // Batch loading the parts of the MMS messages in this batch - loadMmsParts(mmsToAdd); - // Lookup senders for incoming mms messages - setMmsSenders(mmsToAdd, cache); - } catch (final SQLiteException e) { - LogUtil.e(TAG, "SyncMessagesAction: Database exception", e); - // Let's abort - lastTimestampMillis = SYNC_FAILED; - } catch (final Exception e) { - // We want to catch anything unexpected since this is running in a separate thread - // and any unexpected exception will just fail this thread silently. - // Let's crash for dogfooders! - LogUtil.wtf(TAG, "SyncMessagesAction: unexpected failure in scan", e); - lastTimestampMillis = SYNC_FAILED; - } finally { - if (cursors != null) { - cursors.close(); - } - } - - final long endTimeMillis = SystemClock.elapsedRealtime(); - - if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) { - LogUtil.d(TAG, "SyncMessagesAction: Scan complete (took " - + (endTimeMillis - startTimeMillis) + " ms). " + smsToAdd.size() - + " remote SMS to add, " + mmsToAdd.size() + " MMS to add, " - + messagesToDelete.size() + " local messages to delete. " - + "Oldest timestamp seen = " + lastTimestampMillis); - } - - return lastTimestampMillis; - } - - /** - * Perform local database updates and schedule follow on sync actions - */ - @Override - protected Object processBackgroundResponse(final Bundle response) { - final long lastTimestampMillis = response.getLong(BUNDLE_KEY_LAST_TIMESTAMP); - final long lowerBoundTimeMillis = actionParameters.getLong(KEY_LOWER_BOUND); - final long upperBoundTimeMillis = actionParameters.getLong(KEY_UPPER_BOUND); - final int maxMessagesToUpdate = actionParameters.getInt(KEY_MAX_UPDATE); - final long startTimestamp = actionParameters.getLong(KEY_START_TIMESTAMP); - - // Check with the sync manager if any conflicting updates have been made to databases - final SyncManager syncManager = DataModel.get().getSyncManager(); - final boolean orphan = !syncManager.isSyncing(upperBoundTimeMillis); - - // lastTimestampMillis used to indicate failure - if (orphan) { - // This batch does not match current in progress timestamp. - LogUtil.w(TAG, "SyncMessagesAction: Ignoring orphan sync batch for messages from " - + lowerBoundTimeMillis + " to " + upperBoundTimeMillis); - } else { - final boolean dirty = syncManager.isBatchDirty(lastTimestampMillis); - if (lastTimestampMillis == SYNC_FAILED) { - LogUtil.e(TAG, "SyncMessagesAction: Sync failed - terminating"); - - // Failed - update last sync times to throttle our failure rate - final BuglePrefs prefs = BuglePrefs.getApplicationPrefs(); - // Save sync completion time so next sync will start from here - prefs.putLong(BuglePrefsKeys.LAST_SYNC_TIME, startTimestamp); - // Remember last full sync so that don't start background full sync right away - prefs.putLong(BuglePrefsKeys.LAST_FULL_SYNC_TIME, startTimestamp); - - syncManager.complete(); - } else if (dirty) { - LogUtil.w(TAG, "SyncMessagesAction: Redoing dirty sync batch of messages from " - + lowerBoundTimeMillis + " to " + upperBoundTimeMillis); - - // Redo this batch - final SyncMessagesAction nextBatch = - new SyncMessagesAction(lowerBoundTimeMillis, upperBoundTimeMillis, - maxMessagesToUpdate, startTimestamp); - - syncManager.startSyncBatch(upperBoundTimeMillis); - requestBackgroundWork(nextBatch); - } else { - // Succeeded - final ArrayList<SmsMessage> smsToAdd = - response.getParcelableArrayList(BUNDLE_KEY_SMS_MESSAGES); - final ArrayList<MmsMessage> mmsToAdd = - response.getParcelableArrayList(BUNDLE_KEY_MMS_MESSAGES); - final ArrayList<LocalDatabaseMessage> messagesToDelete = - response.getParcelableArrayList(BUNDLE_KEY_MESSAGES_TO_DELETE); - - final int messagesUpdated = smsToAdd.size() + mmsToAdd.size() - + messagesToDelete.size(); - - // Perform local database changes in one transaction - long txnTimeMillis = 0; - if (messagesUpdated > 0) { - final long startTimeMillis = SystemClock.elapsedRealtime(); - final SyncMessageBatch batch = new SyncMessageBatch(smsToAdd, mmsToAdd, - messagesToDelete, syncManager.getThreadInfoCache()); - batch.updateLocalDatabase(); - final long endTimeMillis = SystemClock.elapsedRealtime(); - txnTimeMillis = endTimeMillis - startTimeMillis; - - LogUtil.i(TAG, "SyncMessagesAction: Updated local database " - + "(took " + txnTimeMillis + " ms). Added " - + smsToAdd.size() + " SMS, added " + mmsToAdd.size() + " MMS, deleted " - + messagesToDelete.size() + " messages."); - - // TODO: Investigate whether we can make this more fine-grained. - MessagingContentProvider.notifyEverythingChanged(); - } else { - if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) { - LogUtil.d(TAG, "SyncMessagesAction: No local database updates to make"); - } - - if (!syncManager.getHasFirstSyncCompleted()) { - // If we have never completed a sync before (fresh install) and there are - // no messages, still inform the UI of a change so it can update syncing - // messages shown to the user - MessagingContentProvider.notifyConversationListChanged(); - MessagingContentProvider.notifyPartsChanged(); - } - } - // Determine if there are more messages that need to be scanned - if (lastTimestampMillis >= 0 && lastTimestampMillis >= lowerBoundTimeMillis) { - if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) { - LogUtil.d(TAG, "SyncMessagesAction: More messages to sync; scheduling next " - + "sync batch now."); - } - - // Include final millisecond of last sync in next sync - final long newUpperBoundTimeMillis = lastTimestampMillis + 1; - final int newMaxMessagesToUpdate = nextBatchSize(messagesUpdated, - txnTimeMillis); - - final SyncMessagesAction nextBatch = - new SyncMessagesAction(lowerBoundTimeMillis, newUpperBoundTimeMillis, - newMaxMessagesToUpdate, startTimestamp); - - // Proceed with next batch - syncManager.startSyncBatch(newUpperBoundTimeMillis); - requestBackgroundWork(nextBatch); - } else { - final BuglePrefs prefs = BuglePrefs.getApplicationPrefs(); - // Save sync completion time so next sync will start from here - prefs.putLong(BuglePrefsKeys.LAST_SYNC_TIME, startTimestamp); - if (lowerBoundTimeMillis < 0) { - // Remember last full sync so that don't start another full sync right away - prefs.putLong(BuglePrefsKeys.LAST_FULL_SYNC_TIME, startTimestamp); - } - - final long now = System.currentTimeMillis(); - - // After any sync check if new messages have arrived - final SyncCursorPair recents = new SyncCursorPair(startTimestamp, now); - final SyncCursorPair olders = new SyncCursorPair(-1L, startTimestamp); - final DatabaseWrapper db = DataModel.get().getDatabase(); - if (!recents.isSynchronized(db)) { - LogUtil.i(TAG, "SyncMessagesAction: Changed messages after sync; " - + "scheduling an incremental sync now."); - - // Just add a new batch for recent messages - final SyncMessagesAction nextBatch = - new SyncMessagesAction(startTimestamp, now, 0, startTimestamp); - syncManager.startSyncBatch(now); - requestBackgroundWork(nextBatch); - // After partial sync verify sync state - } else if (lowerBoundTimeMillis >= 0 && !olders.isSynchronized(db)) { - // Add a batch going back to start of time - LogUtil.w(TAG, "SyncMessagesAction: Changed messages before sync batch; " - + "scheduling a full sync now."); - - final SyncMessagesAction nextBatch = - new SyncMessagesAction(-1L, startTimestamp, 0, startTimestamp); - - syncManager.startSyncBatch(startTimestamp); - requestBackgroundWork(nextBatch); - } else { - LogUtil.i(TAG, "SyncMessagesAction: All messages now in sync"); - - // All done, in sync - syncManager.complete(); - } - } - // Either sync should be complete or we should have a follow up request - Assert.isTrue(hasBackgroundActions() || !syncManager.isSyncing()); - } - } - - return null; - } - - /** - * Decide the next batch size based on the stats we collected with past batch - * @param messagesUpdated number of messages updated in this batch - * @param txnTimeMillis time the transaction took in ms - * @return Target number of messages to sync for next batch - */ - private static int nextBatchSize(final int messagesUpdated, final long txnTimeMillis) { - final BugleGservices bugleGservices = BugleGservices.get(); - final long smsSyncSubsequentBatchTimeLimitMillis = bugleGservices.getLong( - BugleGservicesKeys.SMS_SYNC_BATCH_TIME_LIMIT_MILLIS, - BugleGservicesKeys.SMS_SYNC_BATCH_TIME_LIMIT_MILLIS_DEFAULT); - - if (txnTimeMillis <= 0) { - return 0; - } - // Number of messages we can sync within the batch time limit using - // the average sync time calculated based on the stats we collected - // in previous batch - return (int) ((double) (messagesUpdated) / (double) txnTimeMillis - * smsSyncSubsequentBatchTimeLimitMillis); - } - - /** - * Batch loading MMS parts for the messages in current batch - */ - private void loadMmsParts(final LongSparseArray<MmsMessage> mmses) { - final Context context = Factory.get().getApplicationContext(); - final int totalIds = mmses.size(); - for (int start = 0; start < totalIds; start += MmsUtils.MAX_IDS_PER_QUERY) { - final int end = Math.min(start + MmsUtils.MAX_IDS_PER_QUERY, totalIds); //excluding - final int count = end - start; - final String batchSelection = String.format( - Locale.US, - "%s != '%s' AND %s IN %s", - Mms.Part.CONTENT_TYPE, - ContentType.APP_SMIL, - Mms.Part.MSG_ID, - MmsUtils.getSqlInOperand(count)); - final String[] batchSelectionArgs = new String[count]; - for (int i = 0; i < count; i++) { - batchSelectionArgs[i] = Long.toString(mmses.valueAt(start + i).getId()); - } - final Cursor cursor = SqliteWrapper.query( - context, - context.getContentResolver(), - MmsUtils.MMS_PART_CONTENT_URI, - DatabaseMessages.MmsPart.PROJECTION, - batchSelection, - batchSelectionArgs, - null/*sortOrder*/); - if (cursor != null) { - try { - while (cursor.moveToNext()) { - // Delay loading the media content for parsing for efficiency - // TODO: load the media and fill in the dimensions when - // we actually display it - final DatabaseMessages.MmsPart part = - DatabaseMessages.MmsPart.get(cursor, false/*loadMedia*/); - final DatabaseMessages.MmsMessage mms = mmses.get(part.mMessageId); - if (mms != null) { - mms.addPart(part); - } - } - } finally { - cursor.close(); - } - } - } - } - - /** - * Batch loading MMS sender for the messages in current batch - */ - private void setMmsSenders(final LongSparseArray<MmsMessage> mmses, - final ThreadInfoCache cache) { - // Store all the MMS messages - for (int i = 0; i < mmses.size(); i++) { - final MmsMessage mms = mmses.valueAt(i); - - final boolean isOutgoing = mms.mType != Mms.MESSAGE_BOX_INBOX; - String senderId = null; - if (!isOutgoing) { - // We only need to find out sender phone number for received message - senderId = getMmsSender(mms, cache); - if (senderId == null) { - LogUtil.w(TAG, "SyncMessagesAction: Could not find sender of incoming MMS " - + "message " + mms.getUri() + "; using 'unknown sender' instead"); - senderId = ParticipantData.getUnknownSenderDestination(); - } - } - mms.setSender(senderId); - } - } - - /** - * Find out the sender of an MMS message - */ - private String getMmsSender(final MmsMessage mms, final ThreadInfoCache cache) { - final List<String> recipients = cache.getThreadRecipients(mms.mThreadId); - Assert.notNull(recipients); - Assert.isTrue(recipients.size() > 0); - - if (recipients.size() == 1 - && recipients.get(0).equals(ParticipantData.getUnknownSenderDestination())) { - LogUtil.w(TAG, "SyncMessagesAction: MMS message " + mms.mUri + " has unknown sender " - + "(thread id = " + mms.mThreadId + ")"); - } - - return MmsUtils.getMmsSender(recipients, mms.mUri); - } - - private SyncMessagesAction(final Parcel in) { - super(in); - } - - public static final Parcelable.Creator<SyncMessagesAction> CREATOR - = new Parcelable.Creator<SyncMessagesAction>() { - @Override - public SyncMessagesAction createFromParcel(final Parcel in) { - return new SyncMessagesAction(in); - } - - @Override - public SyncMessagesAction[] newArray(final int size) { - return new SyncMessagesAction[size]; - } - }; - - @Override - public void writeToParcel(final Parcel parcel, final int flags) { - writeActionToParcel(parcel, flags); - } -} |