Harden AttachmentDownloadService; fix storage calculation
Bug: 3292720 Bug: 3286634 Change-Id: I378aac369ee8317c0c41b1f021a3731b81bcb380
This commit is contained in:
parent
fdfd466fe6
commit
edb05ca5ee
|
@ -320,24 +320,30 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
||||||
int backgroundDownloads = MAX_SIMULTANEOUS_DOWNLOADS - mDownloadsInProgress.size();
|
int backgroundDownloads = MAX_SIMULTANEOUS_DOWNLOADS - mDownloadsInProgress.size();
|
||||||
// Always leave one slot for user requested download
|
// Always leave one slot for user requested download
|
||||||
if (backgroundDownloads > (MAX_SIMULTANEOUS_DOWNLOADS - 1)) {
|
if (backgroundDownloads > (MAX_SIMULTANEOUS_DOWNLOADS - 1)) {
|
||||||
// We'll take the most recent unloaded attachment
|
boolean repeat = true;
|
||||||
// TODO It would be more correct to look at other attachments if we are prevented
|
while (repeat) {
|
||||||
// from preloading due to per-account storage constraints, but this would be a
|
// We'll take the most recent unloaded attachment
|
||||||
// very unusual case.
|
Long prefetchId = Utility.getFirstRowLong(mContext, SINGLE_ATTACHMENT_URI,
|
||||||
Long prefetchId = Utility.getFirstRowLong(mContext,
|
Attachment.ID_PROJECTION, AttachmentColumns.CONTENT_URI
|
||||||
SINGLE_ATTACHMENT_URI,
|
+ " isnull AND " + Attachment.FLAGS + "=0", null,
|
||||||
Attachment.ID_PROJECTION,
|
Attachment.RECORD_ID + " DESC", Attachment.ID_PROJECTION_COLUMN);
|
||||||
AttachmentColumns.CONTENT_URI + " isnull AND " + Attachment.FLAGS + "=0",
|
if (prefetchId == null) break;
|
||||||
null,
|
|
||||||
Attachment.RECORD_ID + " DESC",
|
|
||||||
Attachment.ID_PROJECTION_COLUMN);
|
|
||||||
if (prefetchId != null) {
|
|
||||||
if (Email.DEBUG) {
|
if (Email.DEBUG) {
|
||||||
Log.d(TAG, ">> Prefetch attachment " + prefetchId);
|
Log.d(TAG, ">> Prefetch attachment " + prefetchId);
|
||||||
}
|
}
|
||||||
Attachment att = Attachment.restoreAttachmentWithId(mContext, prefetchId);
|
Attachment att = Attachment.restoreAttachmentWithId(mContext, prefetchId);
|
||||||
if (att != null && canPrefetchForAccount(att.mAccountKey,
|
// If att is null, the attachment must have been deleted out from under us
|
||||||
AttachmentProvider.getAttachmentDirectory(mContext, att.mAccountKey))) {
|
if (att == null) continue;
|
||||||
|
if (getServiceClassForAccount(att.mAccountKey) == null) {
|
||||||
|
// Clean up this orphaned attachment; there's no point in keeping it
|
||||||
|
// around; then try to find another one
|
||||||
|
EmailContent.delete(mContext, Attachment.CONTENT_URI, prefetchId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
repeat = false;
|
||||||
|
// TODO It's possible that we're just over limit for this particular account
|
||||||
|
// Handle this so that attachments from other accounts (if any) can be tried
|
||||||
|
if (canPrefetchForAccount(att.mAccountKey, mContext.getCacheDir())) {
|
||||||
DownloadRequest req = new DownloadRequest(mContext, att);
|
DownloadRequest req = new DownloadRequest(mContext, att);
|
||||||
mDownloadSet.tryStartDownload(req);
|
mDownloadSet.tryStartDownload(req);
|
||||||
}
|
}
|
||||||
|
@ -615,7 +621,7 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
||||||
* Return the class of the service used by the account type of the provided account id. We
|
* Return the class of the service used by the account type of the provided account id. We
|
||||||
* cache the results to avoid repeated database access
|
* cache the results to avoid repeated database access
|
||||||
* @param accountId the id of the account
|
* @param accountId the id of the account
|
||||||
* @return the service class for the account
|
* @return the service class for the account or null (if the account no longer exists)
|
||||||
*/
|
*/
|
||||||
private synchronized Class<? extends Service> getServiceClassForAccount(long accountId) {
|
private synchronized Class<? extends Service> getServiceClassForAccount(long accountId) {
|
||||||
// TODO: We should have some more data-driven way of determining the service class. I'd
|
// TODO: We should have some more data-driven way of determining the service class. I'd
|
||||||
|
@ -623,6 +629,7 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
||||||
Class<? extends Service> serviceClass = mAccountServiceMap.get(accountId);
|
Class<? extends Service> serviceClass = mAccountServiceMap.get(accountId);
|
||||||
if (serviceClass == null) {
|
if (serviceClass == null) {
|
||||||
String protocol = Account.getProtocol(mContext, accountId);
|
String protocol = Account.getProtocol(mContext, accountId);
|
||||||
|
if (protocol == null) return null;
|
||||||
if (protocol.equals("eas")) {
|
if (protocol.equals("eas")) {
|
||||||
serviceClass = ExchangeService.class;
|
serviceClass = ExchangeService.class;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -225,15 +225,15 @@ public class AttachmentDownloadServiceTests extends AccountTestCase {
|
||||||
// Now, test per-account storage
|
// Now, test per-account storage
|
||||||
// Mock storage @ 100 total and 50 available
|
// Mock storage @ 100 total and 50 available
|
||||||
mMockDirectory.setTotalAndUsableSpace(100L, 50L);
|
mMockDirectory.setTotalAndUsableSpace(100L, 50L);
|
||||||
// Mock a file of length 24, but need to uncache previous amount first
|
// Mock a file of length 12, but need to uncache previous amount first
|
||||||
mService.mAttachmentStorageMap.remove(1L);
|
mService.mAttachmentStorageMap.remove(1L);
|
||||||
mMockDirectory.setFileLength(24);
|
mMockDirectory.setFileLength(11);
|
||||||
// We can prefetch since 24 < half of 50
|
// We can prefetch since 11 < 50/4
|
||||||
assertTrue(mService.canPrefetchForAccount(1, mMockDirectory));
|
assertTrue(mService.canPrefetchForAccount(1, mMockDirectory));
|
||||||
// Mock a file of length 26, but need to uncache previous amount first
|
// Mock a file of length 13, but need to uncache previous amount first
|
||||||
mService.mAttachmentStorageMap.remove(1L);
|
mService.mAttachmentStorageMap.remove(1L);
|
||||||
mMockDirectory.setFileLength(26);
|
mMockDirectory.setFileLength(13);
|
||||||
// We can't prefetch since 26 > half of 50
|
// We can't prefetch since 13 > 50/4
|
||||||
assertFalse(mService.canPrefetchForAccount(1, mMockDirectory));
|
assertFalse(mService.canPrefetchForAccount(1, mMockDirectory));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue