diff options
author | Danny Baumann <dannybaumann@web.de> | 2016-01-15 12:21:47 +0100 |
---|---|---|
committer | Danny Baumann <dannybaumann@web.de> | 2016-01-20 23:32:40 -0800 |
commit | a29e6b2215fcab6024345e156d30ea1a931120d3 (patch) | |
tree | 3d197087f0fd4d853fb53f2e8f8121f9356cb0a7 | |
parent | 34fb128e4325f764267c54629c4ee563e08aa6c7 (diff) | |
download | android_packages_apps_Email-a29e6b2215fcab6024345e156d30ea1a931120d3.tar.gz android_packages_apps_Email-a29e6b2215fcab6024345e156d30ea1a931120d3.tar.bz2 android_packages_apps_Email-a29e6b2215fcab6024345e156d30ea1a931120d3.zip |
Improve notification coalescence algorithm.
Instead of coalescing for 15 seconds after the first change
notification, coalesce until change notifications have been idle for at
least 2 seconds. This avoids long update delays, which is especially
jarring when using notifications on a wearable and the initial
notification didn't yet include the message body.
Also skip coalescence entirely for deletions; update immediately in that
case.
Change-Id: I67bed9a1af7b023020b0fd5429495eb45000e858
-rw-r--r-- | src/com/android/email/EmailNotificationController.java | 101 |
1 files changed, 55 insertions, 46 deletions
diff --git a/src/com/android/email/EmailNotificationController.java b/src/com/android/email/EmailNotificationController.java index e57b41833..2d22776d8 100644 --- a/src/com/android/email/EmailNotificationController.java +++ b/src/com/android/email/EmailNotificationController.java @@ -56,6 +56,7 @@ import com.android.mail.utils.NotificationUtils; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -213,9 +214,7 @@ public class EmailNotificationController implements NotificationController { */ private static final int NOTIFICATION_DELAYED_MESSAGE = 0; - private static final long NOTIFICATION_DELAY = 15 * DateUtils.SECOND_IN_MILLIS; - // True if we're coalescing notification updates - private static boolean sNotificationDelayedMessagePending; + private static final long NOTIFICATION_DELAY = 2 * DateUtils.SECOND_IN_MILLIS; // True if accounts have changed and we need to refresh everything private static boolean sRefreshAllNeeded; // Set of accounts we need to regenerate notifications for @@ -228,28 +227,30 @@ public class EmailNotificationController implements NotificationController { sNotificationThread = new NotificationThread(); sNotificationHandler = new Handler(sNotificationThread.getLooper(), new Handler.Callback() { - @Override - public boolean handleMessage(final android.os.Message message) { - /** - * To reduce spamming the notifications, we quiesce updates for a few - * seconds to batch them up, then handle them here. - */ - LogUtils.d(LOG_TAG, "Delayed notification processing"); - synchronized (sNotificationDelayedMessageLock) { - sNotificationDelayedMessagePending = false; - final Context context = (Context)message.obj; - if (sRefreshAllNeeded) { - sRefreshAllNeeded = false; - refreshAllNotificationsInternal(context); - } + @Override + public boolean handleMessage(final android.os.Message message) { + /** + * To reduce spamming the notifications, we quiesce updates for a few + * seconds to batch them up, then handle them here. + */ + if (message.arg1 != 0) { + LogUtils.d(LOG_TAG, "Delayed notification processing"); + synchronized (sNotificationDelayedMessageLock) { + final Context context = (Context)message.obj; + if (sRefreshAllNeeded) { + sRefreshAllNeeded = false; + refreshAllNotificationsInternal(context); + } else { for (final Long accountId : sRefreshAccountSet) { refreshNotificationsForAccountInternal(context, accountId); } - sRefreshAccountSet.clear(); } - return true; + sRefreshAccountSet.clear(); } - }); + } + return true; + } + }); } } @@ -590,19 +591,32 @@ public class EmailNotificationController implements NotificationController { notificationManager.cancel((int) (NOTIFICATION_ID_BASE_SECURITY_CHANGED + account.mId)); } + private static void scheduleNotificationUpdateLocked(final Context context, + boolean immediate) { + ensureHandlerExists(); + android.os.Message msg = android.os.Message.obtain(sNotificationHandler, + NOTIFICATION_DELAYED_MESSAGE, 1, 0, context); + boolean isInDelayWindow = sNotificationHandler.hasMessages(NOTIFICATION_DELAYED_MESSAGE); + + sNotificationHandler.removeMessages(NOTIFICATION_DELAYED_MESSAGE); + if (!immediate && isInDelayWindow) { + // we're in the delay window, restart timer + sNotificationHandler.sendMessageDelayed(msg, NOTIFICATION_DELAY); + } else { + // no refreshes happened in the last delay window; refresh immediately + // and send a dummy message to ensure the delay window is respected + // when the next update comes in + sNotificationHandler.sendMessage(msg); + sNotificationHandler.sendEmptyMessageDelayed(NOTIFICATION_DELAYED_MESSAGE, + NOTIFICATION_DELAY); + } + } + private static void refreshNotificationsForAccount(final Context context, - final long accountId) { + final long accountId, boolean immediate) { synchronized (sNotificationDelayedMessageLock) { - if (sNotificationDelayedMessagePending) { - sRefreshAccountSet.add(accountId); - } else { - ensureHandlerExists(); - sNotificationHandler.sendMessageDelayed( - android.os.Message.obtain(sNotificationHandler, - NOTIFICATION_DELAYED_MESSAGE, context), NOTIFICATION_DELAY); - sNotificationDelayedMessagePending = true; - refreshNotificationsForAccountInternal(context, accountId); - } + sRefreshAccountSet.add(accountId); + scheduleNotificationUpdateLocked(context, immediate); } } @@ -722,18 +736,10 @@ public class EmailNotificationController implements NotificationController { account, folder, true /* getAttention */); } - private static void refreshAllNotifications(final Context context) { + private static void refreshAllNotifications(final Context context, boolean immediate) { synchronized (sNotificationDelayedMessageLock) { - if (sNotificationDelayedMessagePending) { - sRefreshAllNeeded = true; - } else { - ensureHandlerExists(); - sNotificationHandler.sendMessageDelayed( - android.os.Message.obtain(sNotificationHandler, - NOTIFICATION_DELAYED_MESSAGE, context), NOTIFICATION_DELAY); - sNotificationDelayedMessagePending = true; - refreshAllNotificationsInternal(context); - } + sRefreshAllNeeded = true; + scheduleNotificationUpdateLocked(context, immediate); } } @@ -757,8 +763,11 @@ public class EmailNotificationController implements NotificationController { } @Override - public void onChange(final boolean selfChange) { - refreshNotificationsForAccount(mContext, mAccountId); + public void onChange(final boolean selfChange, Uri uri) { + List<String> segments = uri != null ? uri.getPathSegments() : null; + boolean isDelete = segments != null && segments.size() >= 2 + ? EmailProvider.NOTIFICATION_OP_DELETE.equals(segments.get(1)) : false; + refreshNotificationsForAccount(mContext, mAccountId, isDelete); } } @@ -774,7 +783,7 @@ public class EmailNotificationController implements NotificationController { } @Override - public void onChange(final boolean selfChange) { + public void onChange(final boolean selfChange, Uri uri) { final ContentResolver resolver = mContext.getContentResolver(); final Cursor c = resolver.query(Account.CONTENT_URI, EmailContent.ID_PROJECTION, null, null, null); @@ -811,7 +820,7 @@ public class EmailNotificationController implements NotificationController { sInstance.unregisterMessageNotification(accountId); } - refreshAllNotifications(mContext); + refreshAllNotifications(mContext, !removedAccountList.isEmpty()); } } |