From 7e788f2473d2cb276ebb495081b53ea5d87370a0 Mon Sep 17 00:00:00 2001 From: weitan Date: Fri, 17 Jun 2016 15:59:49 +0800 Subject: Email: Support configure the sync size for each mail content Users could configure the sync size after setuping the account. After Setting the Sync size. Change-Id: I4270cedf5275c6228946580008dc077cb71a4957 CRs-Fixed: 1016744 --- .../com/android/emailcommon/provider/Account.java | 53 +++++++++++++++++++++- .../android/emailcommon/provider/EmailContent.java | 16 +++++-- .../emailcommon/service/EmailServiceProxy.java | 16 +++++++ .../android/emailcommon/service/IEmailService.aidl | 3 ++ .../com/android/emailcommon/service/SyncSize.java | 49 ++++++++++++++++++++ .../emailcommon/utility/AttachmentUtilities.java | 47 ++++++++++++------- 6 files changed, 163 insertions(+), 21 deletions(-) create mode 100644 emailcommon/src/com/android/emailcommon/service/SyncSize.java (limited to 'emailcommon') diff --git a/emailcommon/src/com/android/emailcommon/provider/Account.java b/emailcommon/src/com/android/emailcommon/provider/Account.java index 5a3ab7f3a..b13c60246 100755 --- a/emailcommon/src/com/android/emailcommon/provider/Account.java +++ b/emailcommon/src/com/android/emailcommon/provider/Account.java @@ -31,6 +31,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; +import com.android.emailcommon.service.SyncSize; import com.android.emailcommon.utility.Utility; import com.android.mail.utils.LogUtils; import com.google.common.annotations.VisibleForTesting; @@ -150,6 +151,10 @@ public final class Account extends EmailContent implements Parcelable { public transient HostAuth mHostAuthSend; public transient Policy mPolicy; + // To save the sync size of this account. + public int mSetSyncSizeEnabled; + public int mSyncSize; + // Marks this account as being a temporary entry, so we know to use it directly and not go // through the database or any caches private transient boolean mTemporary; @@ -171,6 +176,8 @@ public final class Account extends EmailContent implements Parcelable { public static final int CONTENT_POLICY_KEY_COLUMN = 14; public static final int CONTENT_PING_DURATION_COLUMN = 15; public static final int CONTENT_MAX_ATTACHMENT_SIZE_COLUMN = 16; + public static final int CONTENT_SET_SYNC_SIZE_ENABLED_COLUMN = 17; + public static final int CONTENT_SYNC_SIZE_COLUMN = 18; public static final String[] CONTENT_PROJECTION = { AttachmentColumns._ID, AccountColumns.DISPLAY_NAME, @@ -181,7 +188,8 @@ public final class Account extends EmailContent implements Parcelable { AccountColumns.RINGTONE_URI, AccountColumns.PROTOCOL_VERSION, AccountColumns.SECURITY_SYNC_KEY, AccountColumns.SIGNATURE, AccountColumns.POLICY_KEY, AccountColumns.PING_DURATION, - AccountColumns.MAX_ATTACHMENT_SIZE + AccountColumns.MAX_ATTACHMENT_SIZE, AccountColumns.SET_SYNC_SIZE_ENABLED, + AccountColumns.SYNC_SIZE }; public static final int ACCOUNT_FLAGS_COLUMN_ID = 0; @@ -204,6 +212,8 @@ public final class Account extends EmailContent implements Parcelable { mSyncInterval = -1; mSyncLookback = -1; mFlags = 0; + mSetSyncSizeEnabled = SyncSize.ENABLED_DEFAULT_VALUE; + mSyncSize = SyncSize.SYNC_SIZE_ENTIRE_MAIL; } public static Account restoreAccountWithId(Context context, long id) { @@ -279,6 +289,8 @@ public final class Account extends EmailContent implements Parcelable { mSignature = cursor.getString(CONTENT_SIGNATURE_COLUMN); mPolicyKey = cursor.getLong(CONTENT_POLICY_KEY_COLUMN); mPingDuration = cursor.getLong(CONTENT_PING_DURATION_COLUMN); + mSetSyncSizeEnabled = cursor.getInt(CONTENT_SET_SYNC_SIZE_ENABLED_COLUMN); + mSyncSize = cursor.getInt(CONTENT_SYNC_SIZE_COLUMN); } public boolean isTemporary() { @@ -402,6 +414,39 @@ public final class Account extends EmailContent implements Parcelable { mPingDuration = value; } + /** + * @return If this account enabled the sync size function, return true. + */ + public boolean isSetSyncSizeEnabled() { + return mSetSyncSizeEnabled == SyncSize.ENABLED ? true : false; + } + + /** + * Set the sync size function if enabled for this account. + * @param enabled the state of sync size function for this account. + */ + public void setSyncSizeEnabled(boolean enabled) { + mSetSyncSizeEnabled = enabled ? SyncSize.ENABLED : SyncSize.DISABLED; + } + + /** + * @return The max size per mail will be sync from service + * TODO define the values for "all", "20KB", "100KB", etc. See arrays.xml + */ + public int getSyncSize() { + return mSyncSize; + } + + /** + * Set the max size per mail will be sync from service. Be sure to call save() to + * commit to database. + * TODO define the values for "all", "20KB", "100KB", etc. See arrays.xml + * @param size the max size per mail would be sync from service. + */ + public void setSyncSize(int size) { + mSyncSize = size; + } + /** * @return the flags for this account */ @@ -749,6 +794,8 @@ public final class Account extends EmailContent implements Parcelable { values.put(AccountColumns.SIGNATURE, mSignature); values.put(AccountColumns.POLICY_KEY, mPolicyKey); values.put(AccountColumns.PING_DURATION, mPingDuration); + values.put(AccountColumns.SET_SYNC_SIZE_ENABLED, mSetSyncSizeEnabled); + values.put(AccountColumns.SYNC_SIZE, mSyncSize); return values; } @@ -889,6 +936,8 @@ public final class Account extends EmailContent implements Parcelable { dest.writeString(mSecuritySyncKey); dest.writeString(mSignature); dest.writeLong(mPolicyKey); + dest.writeInt(mSetSyncSizeEnabled); + dest.writeInt(mSyncSize); if (mHostAuthRecv != null) { dest.writeByte((byte)1); @@ -927,6 +976,8 @@ public final class Account extends EmailContent implements Parcelable { mSecuritySyncKey = in.readString(); mSignature = in.readString(); mPolicyKey = in.readLong(); + mSetSyncSizeEnabled = in.readInt(); + mSyncSize = in.readInt(); mHostAuthRecv = null; if (in.readByte() == 1) { diff --git a/emailcommon/src/com/android/emailcommon/provider/EmailContent.java b/emailcommon/src/com/android/emailcommon/provider/EmailContent.java index 28826fd85..ebe61cab7 100755 --- a/emailcommon/src/com/android/emailcommon/provider/EmailContent.java +++ b/emailcommon/src/com/android/emailcommon/provider/EmailContent.java @@ -34,6 +34,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.provider.BaseColumns; +import android.text.TextUtils; import com.android.emailcommon.Logging; import com.android.emailcommon.R; @@ -827,8 +828,9 @@ public abstract class EmailContent { */ public static final String FLAG_LOADED_SELECTION = MessageColumns.FLAG_LOADED + " IN (" - + Message.FLAG_LOADED_PARTIAL + "," + Message.FLAG_LOADED_COMPLETE - + ")"; + + Message.FLAG_LOADED_PARTIAL + "," + Message.FLAG_LOADED_COMPLETE + "," + + Message.FLAG_LOADED_PARTIAL_COMPLETE + "," + + Message.FLAG_LOADED_PARTIAL_FETCHING +")"; public static final String ALL_FAVORITE_SELECTION = MessageColumns.FLAG_FAVORITE + "=1 AND " @@ -939,8 +941,10 @@ public abstract class EmailContent { public static final int FLAG_LOADED_UNLOADED = 0; public static final int FLAG_LOADED_COMPLETE = 1; public static final int FLAG_LOADED_PARTIAL = 2; - public static final int FLAG_LOADED_DELETED = 3; - public static final int FLAG_LOADED_UNKNOWN = 4; + public static final int FLAG_LOADED_PARTIAL_COMPLETE = 3; + public static final int FLAG_LOADED_PARTIAL_FETCHING = 4; + public static final int FLAG_LOADED_DELETED = 5; + public static final int FLAG_LOADED_UNKNOWN = 6; // Bits used in mFlags // The following three states are mutually exclusive, and indicate whether the message is an @@ -1721,6 +1725,10 @@ public abstract class EmailContent { public static final String MAX_ATTACHMENT_SIZE = "maxAttachmentSize"; // Current duration of the Exchange ping public static final String PING_DURATION = "pingDuration"; + // If the user could set the sync size for this account. + public static final String SET_SYNC_SIZE_ENABLED = "setSyncSizeEnabled"; + // The sync size for each message of this account. + public static final String SYNC_SIZE = "syncSize"; } public interface QuickResponseColumns extends BaseColumns { diff --git a/emailcommon/src/com/android/emailcommon/service/EmailServiceProxy.java b/emailcommon/src/com/android/emailcommon/service/EmailServiceProxy.java index 36a0d336e..2ba5ec1cb 100644 --- a/emailcommon/src/com/android/emailcommon/service/EmailServiceProxy.java +++ b/emailcommon/src/com/android/emailcommon/service/EmailServiceProxy.java @@ -247,6 +247,22 @@ public class EmailServiceProxy extends ServiceProxy implements IEmailService { }, "sendMeetingResponse"); } + /** + * Request the sync adapter to load a complete message; the service MUST give higher priority + * to non-background loading. + * + * @param messageId the id of the message to be loaded + */ + @Override + public void loadMore(final long messageId) throws RemoteException { + setTask(new ProxyTask() { + @Override + public void run() throws RemoteException { + mService.loadMore(messageId); + } + }, "loadMore"); + } + /** * Request the service to delete the account's PIM (personal information management) data. This * data includes any data that is 1) associated with the account and 2) created/stored by the diff --git a/emailcommon/src/com/android/emailcommon/service/IEmailService.aidl b/emailcommon/src/com/android/emailcommon/service/IEmailService.aidl index a6f49dc6c..cd0cf758f 100644 --- a/emailcommon/src/com/android/emailcommon/service/IEmailService.aidl +++ b/emailcommon/src/com/android/emailcommon/service/IEmailService.aidl @@ -30,6 +30,9 @@ interface IEmailService { oneway void loadAttachment(IEmailServiceCallback cb, long accountId, long attachmentId, boolean background); + // Used to load uncompleted message. + oneway void loadMore(long messageId); + void updateFolderList(long accountId); // TODO: For Eas, sync() will also sync the outbox. We should make IMAP and POP work the same diff --git a/emailcommon/src/com/android/emailcommon/service/SyncSize.java b/emailcommon/src/com/android/emailcommon/service/SyncSize.java new file mode 100644 index 000000000..36aea9f15 --- /dev/null +++ b/emailcommon/src/com/android/emailcommon/service/SyncSize.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.emailcommon.service; + +public class SyncSize { + /** + * 1 means the sync size function is enabled, others means the sync size + * function is disabled. + */ + public static final int ENABLED = 1; + public static final int DISABLED = 0; + + public static final int SYNC_SIZE_ENTIRE_MAIL = Integer.MAX_VALUE; + public static final int SYNC_SIZE_20_K = 20480; + public static final int SYNC_SIZE_100_K = 102400; + public static final int SYNC_SIZE_200_K = 204800; + public static final int SYNC_SIZE_500_K = 512000; + public static final int SYNC_SIZE_1_M = 1024000; + + public static final int ENABLED_DEFAULT_VALUE = ENABLED; + public static final int SYNC_SIZE_DEFAULT_VALUE = SYNC_SIZE_200_K; +} diff --git a/emailcommon/src/com/android/emailcommon/utility/AttachmentUtilities.java b/emailcommon/src/com/android/emailcommon/utility/AttachmentUtilities.java index 407a9034b..5c3df3eb1 100644 --- a/emailcommon/src/com/android/emailcommon/utility/AttachmentUtilities.java +++ b/emailcommon/src/com/android/emailcommon/utility/AttachmentUtilities.java @@ -398,16 +398,38 @@ public class AttachmentUtilities { final ContentValues cv = new ContentValues(); final long attachmentId = attachment.mId; final long accountId = attachment.mAccountKey; - final String contentUri; - final long size; + String contentUri = null; + long size = attachment.mSize; try { ContentResolver resolver = context.getContentResolver(); - if (attachment.mUiDestination == UIProvider.AttachmentDestination.CACHE) { + // As we changed the save attachment process to use the cached content first, + // if the cached do not exist, we will try to download it. Then under this case + // we need save the content to cache and external both. + if (attachment.mUiDestination == UIProvider.AttachmentDestination.CACHE + || !Utility.attachmentExists(context, attachment)) { Uri attUri = getAttachmentUri(accountId, attachmentId); size = copyFile(in, resolver.openOutputStream(attUri)); contentUri = attUri.toString(); - } else if (Utility.isExternalStorageMounted()) { + + // Update the attachment + cv.put(AttachmentColumns.SIZE, size); + cv.put(AttachmentColumns.CONTENT_URI, contentUri); + cv.put(AttachmentColumns.UI_STATE, UIProvider.AttachmentState.SAVED); + context.getContentResolver().update(uri, cv, null, null); + } else { + // Do not use the input stream, close it. + in.close(); + } + + // If the destination is external, try to save the content to external. + if (attachment.mUiDestination == UIProvider.AttachmentDestination.EXTERNAL) { + if (!Utility.isExternalStorageMounted()) { + LogUtils.w(Logging.LOG_TAG, + "Trying to save an attachment without external storage?"); + throw new IOException(); + } + if (TextUtils.isEmpty(attachment.mFileName)) { // TODO: This will prevent a crash but does not surface the underlying problem // to the user correctly. @@ -419,7 +441,8 @@ public class AttachmentUtilities { Environment.DIRECTORY_DOWNLOADS); downloads.mkdirs(); File file = Utility.createUniqueFile(downloads, attachment.mFileName); - size = copyFile(in, new FileOutputStream(file)); + Uri attUri = getAttachmentUri(accountId, attachmentId); + size = copyFile(resolver.openInputStream(attUri), new FileOutputStream(file)); String absolutePath = file.getAbsolutePath(); // Although the download manager can scan media files, scanning only happens @@ -440,25 +463,17 @@ public class AttachmentUtilities { false /* do not use media scanner */, mimeType, absolutePath, size, true /* show notification */); - contentUri = dm.getUriForDownloadedFile(id).toString(); + LogUtils.d(Logging.LOG_TAG, "Save the att to download manager, id = %d", id); } catch (final IllegalArgumentException e) { LogUtils.d(LogUtils.TAG, e, "IAE from DownloadManager while saving attachment"); throw new IOException(e); } - } else { - LogUtils.w(Logging.LOG_TAG, - "Trying to save an attachment without external storage?"); - throw new IOException(); } - - // Update the attachment - cv.put(AttachmentColumns.SIZE, size); - cv.put(AttachmentColumns.CONTENT_URI, contentUri); - cv.put(AttachmentColumns.UI_STATE, UIProvider.AttachmentState.SAVED); } catch (IOException e) { // Handle failures here... + cv.clear(); cv.put(AttachmentColumns.UI_STATE, UIProvider.AttachmentState.FAILED); + context.getContentResolver().update(uri, cv, null, null); } - context.getContentResolver().update(uri, cv, null, null); } } -- cgit v1.2.3