From 190b2fb8a1be1d72475e2a60d0f00422712ee094 Mon Sep 17 00:00:00 2001 From: Marc Blank Date: Thu, 7 Jul 2011 14:27:59 -0700 Subject: [PATCH] Add support for TrafficStats; use with IMAP/POP3 * All IMAP/POP3 functionality uses TrafficStats except for attachment loading (subsequenc CL) Bug: 4988322 Change-Id: I91d826e0f7151a2101b642c868ab8c37e9660332 --- .../com/android/emailcommon/TrafficFlags.java | 113 ++++++++++++++++++ .../android/emailcommon/utility/Utility.java | 37 +++--- .../android/email/MessagingController.java | 9 ++ 3 files changed, 143 insertions(+), 16 deletions(-) create mode 100644 emailcommon/src/com/android/emailcommon/TrafficFlags.java diff --git a/emailcommon/src/com/android/emailcommon/TrafficFlags.java b/emailcommon/src/com/android/emailcommon/TrafficFlags.java new file mode 100644 index 000000000..c8c4e034c --- /dev/null +++ b/emailcommon/src/com/android/emailcommon/TrafficFlags.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2011 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.emailcommon; + +import android.content.Context; + +import com.android.emailcommon.provider.Account; +import com.android.emailcommon.provider.HostAuth; +import com.android.emailcommon.utility.Utility; + +/** + * Constants for tagging threads for traffic stats, and associated utilities + * + * Example usage: + * TrafficStats.setThreadStatsTag(accountId | PROTOCOL_IMAP | DATA_EMAIL | REASON_SYNC); + */ +public class TrafficFlags { + // Bits 0->15, account id + private static final int ACCOUNT_MASK = 0x0000FFFF; + + // Bits 16&17, protocol (0 = POP3) + private static final int PROTOCOL_SHIFT = 16; + private static final int PROTOCOL_MASK = 3 << PROTOCOL_SHIFT; + public static final int PROTOCOL_POP3 = 0 << PROTOCOL_SHIFT; + public static final int PROTOCOL_IMAP = 1 << PROTOCOL_SHIFT; + public static final int PROTOCOL_EAS = 2 << PROTOCOL_SHIFT; + public static final int PROTOCOL_SMTP = 3 << PROTOCOL_SHIFT; + private static final String[] PROTOCOLS = new String[] {HostAuth.SCHEME_POP3, + HostAuth.SCHEME_IMAP, HostAuth.SCHEME_EAS, HostAuth.SCHEME_SMTP}; + + // Bits 18&19, type (0 = EMAIL) + private static final int DATA_SHIFT = 18; + private static final int DATA_MASK = 3 << DATA_SHIFT; + public static final int DATA_EMAIL = 0 << DATA_SHIFT; + public static final int DATA_CONTACTS = 1 << DATA_SHIFT; + public static final int DATA_CALENDAR = 2 << DATA_SHIFT; + + // Bits 20&21, reason (if protocol != SMTP) + private static final int REASON_SHIFT = 20; + private static final int REASON_MASK = 3 << REASON_SHIFT; + public static final int REASON_SYNC = 0 << REASON_SHIFT; + public static final int REASON_ATTACHMENT_USER = 1 << REASON_SHIFT; + // Note: We don't yet use the PRECACHE reason (it's complicated...) + public static final int REASON_ATTACHMENT_PRECACHE = 2 << REASON_SHIFT; + private static final String[] REASONS = new String[] {"sync", "attachment", "precache"}; + + /** + * Get flags indicating sync of the passed-in account; note that, by default, these flags + * indicate an email sync; to change the type of sync, simply "or" in DATA_CONTACTS or + * DATA_CALENDAR (since DATA_EMAIL = 0) + * + * @param context the caller's context + * @param account the account being used + * @return flags for syncing this account + */ + public static int getSyncFlags(Context context, Account account) { + int protocolIndex = Utility.arrayIndex(PROTOCOLS, account.getProtocol(context)); + return (int)account.mId | REASON_SYNC | (protocolIndex << PROTOCOL_SHIFT); + } + + /** + * Get flags indicating attachment loading from the passed-in account + * + * @param context the caller's context + * @param account the account being used + * @return flags for loading an attachment in this account + */ + public static int getAttachmentFlags(Context context, Account account) { + int protocolIndex = Utility.arrayIndex(PROTOCOLS, account.getProtocol(context)); + return (int)account.mId | REASON_ATTACHMENT_USER | (protocolIndex << PROTOCOL_SHIFT); + } + + /** + * Get flags indicating sending SMTP email from the passed-in account + * + * @param context the caller's context + * @param account the account being used + * @return flags for sending SMTP email from this account + */ + public static int getSmtpFlags(Context context, Account account) { + return (int)account.mId | REASON_SYNC | PROTOCOL_SMTP; + } + + public static String toString(int flags) { + StringBuilder sb = new StringBuilder(); + sb.append("account "); + sb.append(flags & ACCOUNT_MASK); + sb.append(','); + sb.append(REASONS[(flags & REASON_MASK) >> REASON_SHIFT]); + sb.append(','); + sb.append(PROTOCOLS[(flags & PROTOCOL_MASK) >> PROTOCOL_SHIFT]); + int maskedData = flags & DATA_MASK; + if (maskedData != 0) { + sb.append(','); + sb.append(maskedData == DATA_CALENDAR ? "calendar" : "contacts"); + } + return sb.toString(); + } +} diff --git a/emailcommon/src/com/android/emailcommon/utility/Utility.java b/emailcommon/src/com/android/emailcommon/utility/Utility.java index f1c3906ef..87883727b 100644 --- a/emailcommon/src/com/android/emailcommon/utility/Utility.java +++ b/emailcommon/src/com/android/emailcommon/utility/Utility.java @@ -16,20 +16,6 @@ package com.android.emailcommon.utility; -import com.android.emailcommon.Logging; -import com.android.emailcommon.provider.Account; -import com.android.emailcommon.provider.EmailContent; -import com.android.emailcommon.provider.EmailContent.AccountColumns; -import com.android.emailcommon.provider.EmailContent.Attachment; -import com.android.emailcommon.provider.EmailContent.AttachmentColumns; -import com.android.emailcommon.provider.EmailContent.HostAuthColumns; -import com.android.emailcommon.provider.EmailContent.MailboxColumns; -import com.android.emailcommon.provider.EmailContent.Message; -import com.android.emailcommon.provider.EmailContent.MessageColumns; -import com.android.emailcommon.provider.HostAuth; -import com.android.emailcommon.provider.Mailbox; -import com.android.emailcommon.provider.ProviderUnavailableException; - import android.app.Activity; import android.app.Fragment; import android.content.ContentResolver; @@ -57,6 +43,20 @@ import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; +import com.android.emailcommon.Logging; +import com.android.emailcommon.provider.Account; +import com.android.emailcommon.provider.EmailContent; +import com.android.emailcommon.provider.EmailContent.AccountColumns; +import com.android.emailcommon.provider.EmailContent.Attachment; +import com.android.emailcommon.provider.EmailContent.AttachmentColumns; +import com.android.emailcommon.provider.EmailContent.HostAuthColumns; +import com.android.emailcommon.provider.EmailContent.MailboxColumns; +import com.android.emailcommon.provider.EmailContent.Message; +import com.android.emailcommon.provider.EmailContent.MessageColumns; +import com.android.emailcommon.provider.HostAuth; +import com.android.emailcommon.provider.Mailbox; +import com.android.emailcommon.provider.ProviderUnavailableException; + import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileDescriptor; @@ -119,12 +119,17 @@ public class Utility { } public final static boolean arrayContains(Object[] a, Object o) { + int index = arrayIndex(a, o); + return (index >= 0); + } + + public final static int arrayIndex(Object[] a, Object o) { for (int i = 0, count = a.length; i < count; i++) { if (a[i].equals(o)) { - return true; + return i; } } - return false; + return -1; } /** diff --git a/src/com/android/email/MessagingController.java b/src/com/android/email/MessagingController.java index ccff9e695..be1aa8d72 100644 --- a/src/com/android/email/MessagingController.java +++ b/src/com/android/email/MessagingController.java @@ -21,6 +21,7 @@ import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; +import android.net.TrafficStats; import android.net.Uri; import android.os.Process; import android.text.TextUtils; @@ -29,6 +30,7 @@ import android.util.Log; import com.android.email.mail.Sender; import com.android.email.mail.Store; import com.android.emailcommon.Logging; +import com.android.emailcommon.TrafficFlags; import com.android.emailcommon.internet.MimeBodyPart; import com.android.emailcommon.internet.MimeHeader; import com.android.emailcommon.internet.MimeMultipart; @@ -256,6 +258,7 @@ public class MessagingController implements Runnable { // content synchronization (addition AND removal) since each store will likely need // to implement it's own, unique synchronization methodology. public void run() { + TrafficStats.setThreadStatsTag(TrafficFlags.getSyncFlags(mContext, account)); Cursor localFolderCursor = null; try { // Step 1: Get remote mailboxes @@ -348,6 +351,7 @@ public class MessagingController implements Runnable { */ private void synchronizeMailboxSynchronous(final Account account, final Mailbox folder) { + TrafficStats.setThreadStatsTag(TrafficFlags.getSyncFlags(mContext, account)); mListeners.synchronizeMailboxStarted(account.mId, folder.mId); if ((folder.mFlags & Mailbox.FLAG_HOLDS_MAIL) == 0) { // We don't hold messages, so, nothing to synchronize @@ -1078,6 +1082,7 @@ public class MessagingController implements Runnable { */ private void processPendingActionsSynchronous(Account account) throws MessagingException { + TrafficStats.setThreadStatsTag(TrafficFlags.getSyncFlags(mContext, account)); ContentResolver resolver = mContext.getContentResolver(); String[] accountIdArgs = new String[] { Long.toString(account.mId) }; @@ -1859,6 +1864,7 @@ public class MessagingController implements Runnable { mListeners.loadMessageForViewFailed(messageId, "null account or mailbox"); return; } + TrafficStats.setThreadStatsTag(TrafficFlags.getSyncFlags(mContext, account)); Store remoteStore = Store.getInstance(account, mContext); String remoteServerId = mailbox.mServerId; @@ -1931,6 +1937,8 @@ public class MessagingController implements Runnable { background); return; } + TrafficStats.setThreadStatsTag( + TrafficFlags.getAttachmentFlags(mContext, account)); Store remoteStore = Store.getInstance(account, mContext); Folder remoteFolder = remoteStore.getFolder(mailbox.mServerId); @@ -2008,6 +2016,7 @@ public class MessagingController implements Runnable { */ public void sendPendingMessagesSynchronous(final Account account, long sentFolderId) { + TrafficStats.setThreadStatsTag(TrafficFlags.getSmtpFlags(mContext, account)); NotificationController nc = NotificationController.getInstance(mContext); // 1. Loop through all messages in the account's outbox long outboxId = Mailbox.findMailboxOfType(mContext, account.mId, Mailbox.TYPE_OUTBOX);