Fix longstanding EAS battery burner
* This happens when the plain text of an Exchange 2003 message
is more than about 500k characters; what's happening is that
a TransactionTooLarge exception is being thrown in the binder
* The reason we never figured it out previously is that the
exception isn't listed in emaillog.txt (which users can easily
send); bugreports/logcat output is harder...
* The fix is to progressively truncate the text
Bug: 5789201
Change-Id: I7524070721e7c25b490200293cb8efb8dfd99d05
diff --git a/src/com/android/exchange/adapter/EmailSyncAdapter.java b/src/com/android/exchange/adapter/EmailSyncAdapter.java
index 4181723..33c517f 100644
--- a/src/com/android/exchange/adapter/EmailSyncAdapter.java
+++ b/src/com/android/exchange/adapter/EmailSyncAdapter.java
@@ -25,6 +25,7 @@
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
+import android.os.TransactionTooLargeException;
import android.provider.CalendarContract.Events;
import android.text.Html;
import android.text.SpannedString;
@@ -1111,9 +1112,23 @@
@Override
public void commit() {
+ commitImpl(0);
+ }
+
+ public void commitImpl(int tryCount) {
// Use a batch operation to handle the changes
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+ // Maximum size of message text per fetch
+ int numFetched = fetchedEmails.size();
+ int maxPerFetch = 0;
+ if (numFetched > 0 && tryCount > 0) {
+ // Educated guess that 450000 chars (900k) is ok; 600k is a killer
+ // Remember that when fetching, we're not getting any other data
+ // We'll keep trying, reducing the maximum each time
+ // Realistically, this will rarely exceed 1, and probably never 2
+ maxPerFetch = 450000 / numFetched / tryCount;
+ }
for (Message msg: fetchedEmails) {
// Find the original message's id (by serverId and mailbox)
Cursor c = getServerIdCursor(msg.mServerId, EmailContent.ID_PROJECTION);
@@ -1138,6 +1153,10 @@
if (id != null) {
userLog("Fetched body successfully for ", id);
mBindArgument[0] = id;
+ if ((maxPerFetch > 0) && (msg.mText.length() > maxPerFetch)) {
+ userLog("Truncating message to " + maxPerFetch);
+ msg.mText = msg.mText.substring(0, maxPerFetch) + "...";
+ }
ops.add(ContentProviderOperation.newUpdate(Body.CONTENT_URI)
.withSelection(Body.MESSAGE_KEY + "=?", mBindArgument)
.withValue(Body.TEXT_CONTENT, msg.mText)
@@ -1192,7 +1211,10 @@
try {
mContentResolver.applyBatch(EmailContent.AUTHORITY, ops);
userLog(mMailbox.mDisplayName, " SyncKey saved as: ", mMailbox.mSyncKey);
- } catch (RemoteException e) {
+ } catch (TransactionTooLargeException e) {
+ Log.w(TAG, "Transaction failed on fetched message; retrying...");
+ commitImpl(++tryCount);
+ } catch (RemoteException e) {
// There is nothing to be done here; fail by returning null
} catch (OperationApplicationException e) {
// There is nothing to be done here; fail by returning null