Fix unbounded async task creation in ADS
Queue operations through a single ConcurrentLinkedQueue and service the updates on a single async task to avoid spamming the async thread task queue. b/11336926 Change-Id: I8e5c526d61f70fbad0ccef80afd08fc26bb5acf0
This commit is contained in:
parent
c165d9bd77
commit
426de73380
|
@ -27,6 +27,7 @@ import android.content.Intent;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
@ -35,7 +36,6 @@ import android.text.format.DateUtils;
|
||||||
import com.android.email.AttachmentInfo;
|
import com.android.email.AttachmentInfo;
|
||||||
import com.android.email.EmailConnectivityManager;
|
import com.android.email.EmailConnectivityManager;
|
||||||
import com.android.email.NotificationController;
|
import com.android.email.NotificationController;
|
||||||
import com.android.email2.ui.MailActivityEmail;
|
|
||||||
import com.android.emailcommon.provider.Account;
|
import com.android.emailcommon.provider.Account;
|
||||||
import com.android.emailcommon.provider.EmailContent;
|
import com.android.emailcommon.provider.EmailContent;
|
||||||
import com.android.emailcommon.provider.EmailContent.Attachment;
|
import com.android.emailcommon.provider.EmailContent.Attachment;
|
||||||
|
@ -55,8 +55,10 @@ import java.io.PrintWriter;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.Queue;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
public class AttachmentDownloadService extends Service implements Runnable {
|
public class AttachmentDownloadService extends Service implements Runnable {
|
||||||
public static final String TAG = LogUtils.TAG;
|
public static final String TAG = LogUtils.TAG;
|
||||||
|
@ -846,6 +848,12 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The queue entries here are entries of the form {id, flags}, with the values passed in to
|
||||||
|
// attachmentChanged()
|
||||||
|
private static final Queue<long[]> sAttachmentChangedQueue =
|
||||||
|
new ConcurrentLinkedQueue<long[]>();
|
||||||
|
private static AsyncTask<Void, Void, Void> sAttachmentChangedTask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called directly by EmailProvider whenever an attachment is inserted or changed
|
* Called directly by EmailProvider whenever an attachment is inserted or changed
|
||||||
* @param context the caller's context
|
* @param context the caller's context
|
||||||
|
@ -853,20 +861,39 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
||||||
* @param flags the new flags for the attachment
|
* @param flags the new flags for the attachment
|
||||||
*/
|
*/
|
||||||
public static void attachmentChanged(final Context context, final long id, final int flags) {
|
public static void attachmentChanged(final Context context, final long id, final int flags) {
|
||||||
Utility.runAsync(new Runnable() {
|
synchronized (sAttachmentChangedQueue) {
|
||||||
@Override
|
sAttachmentChangedQueue.add(new long[]{id, flags});
|
||||||
public void run() {
|
|
||||||
Attachment attachment = Attachment.restoreAttachmentWithId(context, id);
|
if (sAttachmentChangedTask == null) {
|
||||||
if (attachment != null) {
|
sAttachmentChangedTask = new AsyncTask<Void, Void, Void>() {
|
||||||
// Store the flags we got from EmailProvider; given that all of this
|
@Override
|
||||||
// activity is asynchronous, we need to use the newest data from
|
protected Void doInBackground(Void... params) {
|
||||||
// EmailProvider
|
while (true) {
|
||||||
attachment.mFlags = flags;
|
final long[] change;
|
||||||
Intent intent = new Intent(context, AttachmentDownloadService.class);
|
synchronized (sAttachmentChangedQueue) {
|
||||||
intent.putExtra(EXTRA_ATTACHMENT, attachment);
|
change = sAttachmentChangedQueue.poll();
|
||||||
context.startService(intent);
|
if (change == null) {
|
||||||
}
|
sAttachmentChangedTask = null;
|
||||||
}});
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final long id = change[0];
|
||||||
|
final long flags = change[1];
|
||||||
|
final Attachment attachment =
|
||||||
|
Attachment.restoreAttachmentWithId(context, id);
|
||||||
|
if (attachment == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
attachment.mFlags = (int) flags;
|
||||||
|
final Intent intent =
|
||||||
|
new Intent(context, AttachmentDownloadService.class);
|
||||||
|
intent.putExtra(EXTRA_ATTACHMENT, attachment);
|
||||||
|
context.startService(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue