diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index e5b324a49..38bbabcc3 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -214,14 +214,18 @@
-
-
-
+
+
+
+
+
wakeLocks = new ConcurrentHashMap();
- private static AtomicInteger wakeLockSeq = new AtomicInteger(0);
-
- private Integer getWakeLock(Context context)
+ public Integer receive(Context context, Intent intent, Integer tmpWakeLockId)
{
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "K9");
- wakeLock.setReferenceCounted(false);
- wakeLock.acquire(K9.BOOT_RECEIVER_WAKE_LOCK_TIMEOUT);
- Integer tmpWakeLockId = wakeLockSeq.getAndIncrement();
- wakeLocks.put(tmpWakeLockId, wakeLock);
- return tmpWakeLockId;
- }
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "BootReceiver.onReceive" + intent);
- private void releaseWakeLock(Integer wakeLockId)
- {
- if (wakeLockId != null)
+ if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()))
{
- WakeLock wl = wakeLocks.remove(wakeLockId);
- if (wl != null)
- {
- wl.release();
- }
- else
- {
- if (K9.DEBUG)
- Log.w(K9.LOG_TAG, "BootReceiver WakeLock " + wakeLockId + " doesn't exist");
- }
+ //K9.setServicesEnabled(context, tmpWakeLockId);
+ //tmpWakeLockId = null;
}
- }
-
- public void onReceive(Context context, Intent intent)
- {
- Integer tmpWakeLockId = getWakeLock(context);
- try
+ else if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(intent.getAction()))
{
+ MailService.actionCancel(context, tmpWakeLockId);
+ tmpWakeLockId = null;
+ }
+ else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(intent.getAction()))
+ {
+ MailService.actionReschedule(context, tmpWakeLockId);
+ tmpWakeLockId = null;
+ }
+ else if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction()))
+ {
+ boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
+ MailService.connectivityChange(context, !noConnectivity, tmpWakeLockId);
+ tmpWakeLockId = null;
+ }
+ else if (ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED.equals(intent.getAction()))
+ {
+ MailService.backgroundDataChanged(context, tmpWakeLockId);
+ tmpWakeLockId = null;
+ }
+ else if (FIRE_INTENT.equals(intent.getAction()))
+ {
+ Intent alarmedIntent = intent.getParcelableExtra(ALARMED_INTENT);
+ String alarmedAction = alarmedIntent.getAction();
if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "BootReceiver.onReceive" + intent);
-
- if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()))
+ Log.i(K9.LOG_TAG, "BootReceiver Got alarm to fire alarmedIntent " + alarmedAction);
+ alarmedIntent.putExtra(WAKE_LOCK_ID, tmpWakeLockId);
+ tmpWakeLockId = null;
+ if (alarmedIntent != null)
{
- //K9.setServicesEnabled(context, tmpWakeLockId);
- //tmpWakeLockId = null;
- }
- else if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(intent.getAction()))
- {
- MailService.actionCancel(context, tmpWakeLockId);
- tmpWakeLockId = null;
- }
- else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(intent.getAction()))
- {
- MailService.actionReschedule(context, tmpWakeLockId);
- tmpWakeLockId = null;
- }
- else if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction()))
- {
- boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
- MailService.connectivityChange(context, !noConnectivity, tmpWakeLockId);
- tmpWakeLockId = null;
- }
- else if (ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED.equals(intent.getAction()))
- {
- MailService.backgroundDataChanged(context, tmpWakeLockId);
- tmpWakeLockId = null;
- }
- else if (FIRE_INTENT.equals(intent.getAction()))
- {
- Intent alarmedIntent = intent.getParcelableExtra(ALARMED_INTENT);
- String alarmedAction = alarmedIntent.getAction();
-
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "BootReceiver Got alarm to fire alarmedIntent " + alarmedAction);
- alarmedIntent.putExtra(WAKE_LOCK_ID, tmpWakeLockId);
- tmpWakeLockId = null;
- if (alarmedIntent != null)
- {
- context.startService(alarmedIntent);
- }
- }
- else if (SCHEDULE_INTENT.equals(intent.getAction()))
- {
- long atTime = intent.getLongExtra(AT_TIME, -1);
- Intent alarmedIntent = intent.getParcelableExtra(ALARMED_INTENT);
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG,"BootReceiver Scheduling intent " + alarmedIntent + " for " + new Date(atTime));
-
- PendingIntent pi = buildPendingIntent(context, intent);
- AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
-
- alarmMgr.set(AlarmManager.RTC_WAKEUP, atTime, pi);
- }
- else if (CANCEL_INTENT.equals(intent.getAction()))
- {
- Intent alarmedIntent = intent.getParcelableExtra(ALARMED_INTENT);
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "BootReceiver Canceling alarmedIntent " + alarmedIntent);
-
- PendingIntent pi = buildPendingIntent(context, intent);
-
- AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
- alarmMgr.cancel(pi);
- }
- else if (BootReceiver.WAKE_LOCK_RELEASE.equals(intent.getAction()))
- {
- Integer wakeLockId = intent.getIntExtra(WAKE_LOCK_ID, -1);
- if (wakeLockId != -1)
- {
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "BootReceiver Release wakeLock " + wakeLockId);
- releaseWakeLock(wakeLockId);
- }
+ context.startService(alarmedIntent);
}
}
- finally
+ else if (SCHEDULE_INTENT.equals(intent.getAction()))
{
- releaseWakeLock(tmpWakeLockId);
+ long atTime = intent.getLongExtra(AT_TIME, -1);
+ Intent alarmedIntent = intent.getParcelableExtra(ALARMED_INTENT);
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG,"BootReceiver Scheduling intent " + alarmedIntent + " for " + new Date(atTime));
+
+ PendingIntent pi = buildPendingIntent(context, intent);
+ AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
+
+ alarmMgr.set(AlarmManager.RTC_WAKEUP, atTime, pi);
}
+ else if (CANCEL_INTENT.equals(intent.getAction()))
+ {
+ Intent alarmedIntent = intent.getParcelableExtra(ALARMED_INTENT);
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "BootReceiver Canceling alarmedIntent " + alarmedIntent);
+
+ PendingIntent pi = buildPendingIntent(context, intent);
+
+ AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
+ alarmMgr.cancel(pi);
+ }
+
+
+ return tmpWakeLockId;
}
private PendingIntent buildPendingIntent(Context context, Intent intent)
@@ -184,15 +131,5 @@ public class BootReceiver extends BroadcastReceiver
i.putExtra(ALARMED_INTENT, alarmedIntent);
context.sendBroadcast(i);
}
-
- public static void releaseWakeLock(Context context, int wakeLockId)
- {
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "BootReceiver Got request to release wakeLock " + wakeLockId);
- Intent i = new Intent();
- i.setClass(context, BootReceiver.class);
- i.setAction(WAKE_LOCK_RELEASE);
- i.putExtra(WAKE_LOCK_ID, wakeLockId);
- context.sendBroadcast(i);
- }
+
}
diff --git a/src/com/fsck/k9/service/CoreReceiver.java b/src/com/fsck/k9/service/CoreReceiver.java
new file mode 100644
index 000000000..50a560c18
--- /dev/null
+++ b/src/com/fsck/k9/service/CoreReceiver.java
@@ -0,0 +1,100 @@
+
+package com.fsck.k9.service;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.util.Log;
+
+import com.fsck.k9.K9;
+
+public class CoreReceiver extends BroadcastReceiver
+{
+
+ public static String WAKE_LOCK_RELEASE = "com.fsck.k9.service.CoreReceiver.wakeLockRelease";
+
+ public static String WAKE_LOCK_ID = "com.fsck.k9.service.CoreReceiver.wakeLockId";
+
+ private static ConcurrentHashMap wakeLocks = new ConcurrentHashMap();
+ private static AtomicInteger wakeLockSeq = new AtomicInteger(0);
+
+ private static Integer getWakeLock(Context context)
+ {
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "K9");
+ wakeLock.setReferenceCounted(false);
+ wakeLock.acquire(K9.BOOT_RECEIVER_WAKE_LOCK_TIMEOUT);
+ Integer tmpWakeLockId = wakeLockSeq.getAndIncrement();
+ wakeLocks.put(tmpWakeLockId, wakeLock);
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "CoreReceiver Created wakeLock " + tmpWakeLockId);
+ return tmpWakeLockId;
+ }
+
+ private static void releaseWakeLock(Integer wakeLockId)
+ {
+ if (wakeLockId != null)
+ {
+ WakeLock wl = wakeLocks.remove(wakeLockId);
+ if (wl != null)
+ {
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "CoreReceiver Releasing wakeLock " + wakeLockId);
+ wl.release();
+ }
+ else
+ {
+ Log.w(K9.LOG_TAG, "BootReceiver WakeLock " + wakeLockId + " doesn't exist");
+ }
+ }
+ }
+
+ public void onReceive(Context context, Intent intent)
+ {
+ Integer tmpWakeLockId = CoreReceiver.getWakeLock(context);
+ try
+ {
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "CoreReceiver.onReceive" + intent);
+ if (CoreReceiver.WAKE_LOCK_RELEASE.equals(intent.getAction()))
+ {
+ Integer wakeLockId = intent.getIntExtra(WAKE_LOCK_ID, -1);
+ if (wakeLockId != -1)
+ {
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "CoreReceiver Release wakeLock " + wakeLockId);
+ CoreReceiver.releaseWakeLock(wakeLockId);
+ }
+ }
+ else
+ {
+ tmpWakeLockId = receive(context, intent, tmpWakeLockId);
+ }
+ }
+ finally
+ {
+ CoreReceiver.releaseWakeLock(tmpWakeLockId);
+ }
+ }
+
+ public Integer receive(Context context, Intent intent, Integer wakeLockId)
+ {
+ return wakeLockId;
+ }
+
+ public static void releaseWakeLock(Context context, int wakeLockId)
+ {
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "CoreReceiver Got request to release wakeLock " + wakeLockId);
+ Intent i = new Intent();
+ i.setClass(context, CoreReceiver.class);
+ i.setAction(WAKE_LOCK_RELEASE);
+ i.putExtra(WAKE_LOCK_ID, wakeLockId);
+ context.sendBroadcast(i);
+ }
+}
diff --git a/src/com/fsck/k9/service/MailService.java b/src/com/fsck/k9/service/MailService.java
index a488697a9..4f3f4429c 100644
--- a/src/com/fsck/k9/service/MailService.java
+++ b/src/com/fsck/k9/service/MailService.java
@@ -1,478 +1,473 @@
-
-package com.fsck.k9.service;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.NetworkInfo.State;
-import android.os.IBinder;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.util.Config;
-import android.util.Log;
-import com.fsck.k9.*;
-import com.fsck.k9.mail.Pusher;
-
-import java.util.Collection;
-import java.util.Date;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- */
-public class MailService extends CoreService
-{
- private static final String ACTION_CHECK_MAIL = "com.fsck.k9.intent.action.MAIL_SERVICE_WAKEUP";
- private static final String ACTION_RESCHEDULE = "com.fsck.k9.intent.action.MAIL_SERVICE_RESCHEDULE";
- private static final String ACTION_RESCHEDULE_CHECK = "com.fsck.k9.intent.action.MAIL_SERVICE_RESCHEDULE_CHECK";
- private static final String ACTION_CANCEL = "com.fsck.k9.intent.action.MAIL_SERVICE_CANCEL";
- private static final String ACTION_REFRESH_PUSHERS = "com.fsck.k9.intent.action.MAIL_SERVICE_REFRESH_PUSHERS";
- private static final String CONNECTIVITY_CHANGE = "com.fsck.k9.intent.action.MAIL_SERVICE_CONNECTIVITY_CHANGE";
- private static final String BACKGROUND_DATA_CHANGED = "com.fsck.k9.intent.action.MAIL_SERVICE_BACKGROUND_DATA_CHANGED";
- private static final String CANCEL_CONNECTIVITY_NOTICE = "com.fsck.k9.intent.action.MAIL_SERVICE_CANCEL_CONNECTIVITY_NOTICE";
-
- private static final String HAS_CONNECTIVITY = "com.fsck.k9.intent.action.MAIL_SERVICE_HAS_CONNECTIVITY";
-
- private final ExecutorService threadPool = Executors.newFixedThreadPool(1); // Must be single threaded
-
-
- public static void actionReschedule(Context context, Integer wakeLockId)
- {
- Intent i = new Intent();
- i.setClass(context, MailService.class);
- i.setAction(MailService.ACTION_RESCHEDULE);
- addWakeLockId(i, wakeLockId);
- context.startService(i);
- }
-
- public static void rescheduleCheck(Context context, Integer wakeLockId)
- {
- Intent i = new Intent();
- i.setClass(context, MailService.class);
- i.setAction(MailService.ACTION_RESCHEDULE_CHECK);
- addWakeLockId(i, wakeLockId);
- context.startService(i);
- }
-
- public static void actionCancel(Context context, Integer wakeLockId)
- {
- Intent i = new Intent();
- i.setClass(context, MailService.class);
- i.setAction(MailService.ACTION_CANCEL);
- addWakeLockId(i, wakeLockId);
- context.startService(i);
- }
-
- public static void connectivityChange(Context context, boolean hasConnectivity, Integer wakeLockId)
- {
- Intent i = new Intent();
- i.setClass(context, MailService.class);
- i.setAction(MailService.CONNECTIVITY_CHANGE);
- i.putExtra(HAS_CONNECTIVITY, hasConnectivity);
- addWakeLockId(i, wakeLockId);
- context.startService(i);
- }
-
- public static void backgroundDataChanged(Context context, Integer wakeLockId)
- {
- Intent i = new Intent();
- i.setClass(context, MailService.class);
- i.setAction(MailService.BACKGROUND_DATA_CHANGED);
- addWakeLockId(i, wakeLockId);
- context.startService(i);
- }
-
- @Override
- public void onCreate()
- {
- super.onCreate();
- if (K9.DEBUG)
- Log.v(K9.LOG_TAG, "***** MailService *****: onCreate");
- }
-
- @Override
- public void startService(Intent intent, int startId)
- {
- Integer startIdObj = startId;
- long startTime = System.currentTimeMillis();
- try
- {
- ConnectivityManager connectivityManager = (ConnectivityManager)getApplication().getSystemService(Context.CONNECTIVITY_SERVICE);
- boolean doBackground = true;
- boolean hasConnectivity = false;
-
- if (connectivityManager != null)
- {
- NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
- if (netInfo != null)
- {
- State state = netInfo.getState();
- hasConnectivity = state == State.CONNECTED;
- }
- boolean backgroundData = connectivityManager.getBackgroundDataSetting();
-
- K9.BACKGROUND_OPS bOps = K9.getBackgroundOps();
- doBackground = (backgroundData == true && bOps != K9.BACKGROUND_OPS.NEVER)
- | (backgroundData == false && bOps == K9.BACKGROUND_OPS.ALWAYS);
-
- }
-
- setForeground(true); // if it gets killed once, it'll never restart
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "MailService.onStart(" + intent + ", " + startId
- + "), hasConnectivity = " + hasConnectivity + ", doBackground = " + doBackground);
-
- // MessagingController.getInstance(getApplication()).addListener(mListener);
- if (ACTION_CHECK_MAIL.equals(intent.getAction()))
- {
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "***** MailService *****: checking mail");
-
- if (hasConnectivity && doBackground)
- {
- PollService.startService(this);
- }
-
- reschedule(startIdObj);
- startIdObj = null;
- }
- else if (ACTION_CANCEL.equals(intent.getAction()))
- {
- if (Config.LOGV)
- {
- Log.v(K9.LOG_TAG, "***** MailService *****: cancel");
- }
-
- cancel();
- }
- else if (ACTION_RESCHEDULE.equals(intent.getAction()))
- {
- if (Config.LOGV)
- {
- Log.v(K9.LOG_TAG, "***** MailService *****: reschedule");
- }
- rescheduleAll(hasConnectivity, doBackground, startIdObj);
- startIdObj = null;
-
- }
- else if (ACTION_RESCHEDULE_CHECK.equals(intent.getAction()))
- {
- if (Config.LOGV)
- {
- Log.v(K9.LOG_TAG, "***** MailService *****: reschedule check");
- }
- reschedule(startIdObj);
- startIdObj = null;
-
- }
- else if (ACTION_REFRESH_PUSHERS.equals(intent.getAction()))
- {
- if (hasConnectivity && doBackground)
- {
- schedulePushers(null);
- refreshPushers(startIdObj);
- startIdObj = null;
- }
- }
- else if (CONNECTIVITY_CHANGE.equals(intent.getAction()) ||
- BACKGROUND_DATA_CHANGED.equals(intent.getAction()))
- {
- notifyConnectionStatus(hasConnectivity);
- rescheduleAll(hasConnectivity, doBackground, startIdObj);
- startIdObj = null;
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "Got connectivity action with hasConnectivity = " + hasConnectivity + ", doBackground = " + doBackground);
- }
- else if (CANCEL_CONNECTIVITY_NOTICE.equals(intent.getAction()))
- {
- notifyConnectionStatus(true);
- }
- }
- finally
- {
- if (startIdObj != null)
- {
- stopSelf(startId);
- }
- }
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "MailService.onStart took " + (System.currentTimeMillis() - startTime) + "ms");
- }
-
- private void rescheduleAll(final boolean hasConnectivity, final boolean doBackground, final Integer startId)
- {
- if (hasConnectivity && doBackground)
- {
- reschedule(null);
- reschedulePushers(startId);
- }
- else
- {
- stopPushers(startId);
- }
- }
-
- private void notifyConnectionStatus(boolean hasConnectivity)
- {
- if (true) return;
- NotificationManager notifMgr =
- (NotificationManager)getApplication().getSystemService(Context.NOTIFICATION_SERVICE);
- if (hasConnectivity == false)
- {
- String notice = getApplication().getString(R.string.no_connection_alert);
- String header = getApplication().getString(R.string.alert_header);
-
-
- Notification notif = new Notification(R.drawable.stat_notify_email_generic,
- header, System.currentTimeMillis());
-
- Intent i = new Intent();
- i.setClassName(getApplication().getPackageName(), "com.fsck.k9.service.MailService");
- i.setAction(MailService.CANCEL_CONNECTIVITY_NOTICE);
-
- PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
-
- notif.setLatestEventInfo(getApplication(), header, notice, pi);
- notif.flags = Notification.FLAG_ONGOING_EVENT;
-
- notifMgr.notify(K9.CONNECTIVITY_ID, notif);
- }
- else
- {
- notifMgr.cancel(K9.CONNECTIVITY_ID);
- }
- }
-
- @Override
- public void onDestroy()
- {
- if (K9.DEBUG)
- Log.v(K9.LOG_TAG, "***** MailService *****: onDestroy()");
- super.onDestroy();
- // MessagingController.getInstance(getApplication()).removeListener(mListener);
- }
-
- private void cancel()
- {
- Intent i = new Intent();
- i.setClassName(getApplication().getPackageName(), "com.fsck.k9.service.MailService");
- i.setAction(ACTION_CHECK_MAIL);
- BootReceiver.cancelIntent(this, i);
- }
-
- private void reschedule(Integer startId)
- {
- execute(getApplication(), new Runnable()
- {
- public void run()
- {
- int shortestInterval = -1;
-
- for (Account account : Preferences.getPreferences(MailService.this).getAccounts())
- {
- if (account.getAutomaticCheckIntervalMinutes() != -1
- && (account.getAutomaticCheckIntervalMinutes() < shortestInterval || shortestInterval == -1))
- {
- shortestInterval = account.getAutomaticCheckIntervalMinutes();
- }
- }
-
- if (shortestInterval == -1)
- {
- if (K9.DEBUG)
- Log.v(K9.LOG_TAG, "No next check scheduled for package " + getApplication().getPackageName());
- cancel();
- }
- else
- {
- long delay = (shortestInterval * (60 * 1000));
-
- long nextTime = System.currentTimeMillis() + delay;
- if (K9.DEBUG)
- {
- try
- {
- Log.i(K9.LOG_TAG,
- "Next check for package " + getApplication().getPackageName() + " scheduled for " + new Date(nextTime));
- }
- catch (Exception e)
- {
- // I once got a NullPointerException deep in new Date();
- Log.e(K9.LOG_TAG, "Exception while logging", e);
- }
- }
-
- Intent i = new Intent();
- i.setClassName(getApplication().getPackageName(), "com.fsck.k9.service.MailService");
- i.setAction(ACTION_CHECK_MAIL);
- BootReceiver.scheduleIntent(MailService.this, nextTime, i);
-
- }
- }
- }
- , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
- }
-
- private void stopPushers(final Integer startId)
- {
- execute(getApplication(), new Runnable()
- {
- public void run()
- {
- MessagingController.getInstance(getApplication()).stopAllPushing();
- PushService.stopService(MailService.this);
- }
- }
- , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
- }
-
- private void reschedulePushers(final Integer startId)
- {
- execute(getApplication(), new Runnable()
- {
- public void run()
- {
-
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "Rescheduling pushers");
- stopPushers(null);
- setupPushers(null);
- schedulePushers(startId);
-
- }
- }
- , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, null);
- }
-
- private void setupPushers(final Integer startId)
- {
- execute(getApplication(), new Runnable()
- {
- public void run()
- {
- boolean pushing = false;
- for (Account account : Preferences.getPreferences(MailService.this).getAccounts())
- {
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "Setting up pushers for account " + account.getDescription());
- pushing |= MessagingController.getInstance(getApplication()).setupPushing(account);
- }
- if (pushing)
- {
- PushService.startService(MailService.this);
- }
- }
- }
- , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
- }
-
- private void refreshPushers(final Integer startId)
- {
- execute(getApplication(), new Runnable()
- {
- public void run()
- {
- try
- {
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "Refreshing pushers");
- Collection pushers = MessagingController.getInstance(getApplication()).getPushers();
- for (Pusher pusher : pushers)
- {
- pusher.refresh();
- }
- }
- catch (Exception e)
- {
- Log.e(K9.LOG_TAG, "Exception while refreshing pushers", e);
- }
- }
- }
- , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
- }
-
- private void schedulePushers(final Integer startId)
- {
- execute(getApplication(), new Runnable()
- {
- public void run()
- {
- int minInterval = -1;
-
- Collection pushers = MessagingController.getInstance(getApplication()).getPushers();
- for (Pusher pusher : pushers)
- {
- int interval = pusher.getRefreshInterval();
- if (interval != -1 && (interval < minInterval || minInterval == -1))
- {
- minInterval = interval;
- }
- }
- if (K9.DEBUG)
- Log.v(K9.LOG_TAG, "Pusher refresh interval = " + minInterval);
-
- if (minInterval != -1)
- {
- long nextTime = System.currentTimeMillis() + minInterval;
-
- if (K9.DEBUG)
- Log.d(K9.LOG_TAG, "Next pusher refresh scheduled for " + new Date(nextTime));
-
- Intent i = new Intent();
- i.setClassName(getApplication().getPackageName(), "com.fsck.k9.service.MailService");
- i.setAction(ACTION_REFRESH_PUSHERS);
- BootReceiver.scheduleIntent(MailService.this, nextTime, i);
- }
- }
- }
- , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
- }
-
- public void execute(Context context, final Runnable runner, int wakeLockTime, final Integer startId)
- {
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- final WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "K9");
- wakeLock.setReferenceCounted(false);
- wakeLock.acquire(wakeLockTime);
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "MailService queueing Runnable " + runner.hashCode() + " with startId " + startId);
-
- Runnable myRunner = new Runnable()
- {
- public void run()
- {
- try
- {
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "MailService running Runnable " + runner.hashCode() + " with startId " + startId);
- runner.run();
- }
- finally
- {
- if (K9.DEBUG)
- Log.i(K9.LOG_TAG, "MailService completed Runnable " + runner.hashCode() + " with startId " + startId);
- wakeLock.release();
-
- if (startId != null)
- {
- stopSelf(startId);
- }
- }
- }
-
- };
-
- threadPool.execute(myRunner);
- }
-
- public IBinder onBind(Intent intent)
- {
- return null;
- }
-
-
-}
+
+package com.fsck.k9.service;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.State;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.util.Config;
+import android.util.Log;
+import com.fsck.k9.*;
+import com.fsck.k9.mail.Pusher;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ */
+public class MailService extends CoreService
+{
+ private static final String ACTION_CHECK_MAIL = "com.fsck.k9.intent.action.MAIL_SERVICE_WAKEUP";
+ private static final String ACTION_RESCHEDULE = "com.fsck.k9.intent.action.MAIL_SERVICE_RESCHEDULE";
+ private static final String ACTION_RESCHEDULE_CHECK = "com.fsck.k9.intent.action.MAIL_SERVICE_RESCHEDULE_CHECK";
+ private static final String ACTION_CANCEL = "com.fsck.k9.intent.action.MAIL_SERVICE_CANCEL";
+ private static final String ACTION_REFRESH_PUSHERS = "com.fsck.k9.intent.action.MAIL_SERVICE_REFRESH_PUSHERS";
+ private static final String CONNECTIVITY_CHANGE = "com.fsck.k9.intent.action.MAIL_SERVICE_CONNECTIVITY_CHANGE";
+ private static final String BACKGROUND_DATA_CHANGED = "com.fsck.k9.intent.action.MAIL_SERVICE_BACKGROUND_DATA_CHANGED";
+ private static final String CANCEL_CONNECTIVITY_NOTICE = "com.fsck.k9.intent.action.MAIL_SERVICE_CANCEL_CONNECTIVITY_NOTICE";
+
+ private static final String HAS_CONNECTIVITY = "com.fsck.k9.intent.action.MAIL_SERVICE_HAS_CONNECTIVITY";
+
+ private final ExecutorService threadPool = Executors.newFixedThreadPool(1); // Must be single threaded
+
+
+ public static void actionReschedule(Context context, Integer wakeLockId)
+ {
+ Intent i = new Intent();
+ i.setClass(context, MailService.class);
+ i.setAction(MailService.ACTION_RESCHEDULE);
+ addWakeLockId(i, wakeLockId);
+ if (wakeLockId == null)
+ {
+ addWakeLock(context, i);
+ }
+ context.startService(i);
+ }
+
+ public static void rescheduleCheck(Context context, Integer wakeLockId)
+ {
+ Intent i = new Intent();
+ i.setClass(context, MailService.class);
+ i.setAction(MailService.ACTION_RESCHEDULE_CHECK);
+ addWakeLockId(i, wakeLockId);
+ context.startService(i);
+ }
+
+ public static void actionCancel(Context context, Integer wakeLockId)
+ {
+ Intent i = new Intent();
+ i.setClass(context, MailService.class);
+ i.setAction(MailService.ACTION_CANCEL);
+ addWakeLockId(i, wakeLockId);
+ context.startService(i);
+ }
+
+ public static void connectivityChange(Context context, boolean hasConnectivity, Integer wakeLockId)
+ {
+ Intent i = new Intent();
+ i.setClass(context, MailService.class);
+ i.setAction(MailService.CONNECTIVITY_CHANGE);
+ i.putExtra(HAS_CONNECTIVITY, hasConnectivity);
+ addWakeLockId(i, wakeLockId);
+ context.startService(i);
+ }
+
+ public static void backgroundDataChanged(Context context, Integer wakeLockId)
+ {
+ Intent i = new Intent();
+ i.setClass(context, MailService.class);
+ i.setAction(MailService.BACKGROUND_DATA_CHANGED);
+ addWakeLockId(i, wakeLockId);
+ context.startService(i);
+ }
+
+ @Override
+ public void onCreate()
+ {
+ super.onCreate();
+ if (K9.DEBUG)
+ Log.v(K9.LOG_TAG, "***** MailService *****: onCreate");
+ }
+
+ @Override
+ public void startService(Intent intent, int startId)
+ {
+ Integer startIdObj = startId;
+ long startTime = System.currentTimeMillis();
+ try
+ {
+ ConnectivityManager connectivityManager = (ConnectivityManager)getApplication().getSystemService(Context.CONNECTIVITY_SERVICE);
+ boolean doBackground = true;
+ boolean hasConnectivity = false;
+
+ if (connectivityManager != null)
+ {
+ NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
+ if (netInfo != null)
+ {
+ State state = netInfo.getState();
+ hasConnectivity = state == State.CONNECTED;
+ }
+ boolean backgroundData = connectivityManager.getBackgroundDataSetting();
+
+ K9.BACKGROUND_OPS bOps = K9.getBackgroundOps();
+ doBackground = (backgroundData == true && bOps != K9.BACKGROUND_OPS.NEVER)
+ | (backgroundData == false && bOps == K9.BACKGROUND_OPS.ALWAYS);
+
+ }
+
+ setForeground(true); // if it gets killed once, it'll never restart
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "MailService.onStart(" + intent + ", " + startId
+ + "), hasConnectivity = " + hasConnectivity + ", doBackground = " + doBackground);
+
+ // MessagingController.getInstance(getApplication()).addListener(mListener);
+ if (ACTION_CHECK_MAIL.equals(intent.getAction()))
+ {
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "***** MailService *****: checking mail");
+
+ if (hasConnectivity && doBackground)
+ {
+ PollService.startService(this);
+ }
+
+ reschedule(startIdObj);
+ startIdObj = null;
+ }
+ else if (ACTION_CANCEL.equals(intent.getAction()))
+ {
+ if (K9.DEBUG)
+ Log.v(K9.LOG_TAG, "***** MailService *****: cancel");
+
+ cancel();
+ }
+ else if (ACTION_RESCHEDULE.equals(intent.getAction()))
+ {
+ if (K9.DEBUG)
+ Log.v(K9.LOG_TAG, "***** MailService *****: reschedule");
+
+ rescheduleAll(hasConnectivity, doBackground, startIdObj);
+ startIdObj = null;
+
+ }
+ else if (ACTION_RESCHEDULE_CHECK.equals(intent.getAction()))
+ {
+ if (K9.DEBUG)
+ Log.v(K9.LOG_TAG, "***** MailService *****: reschedule check");
+
+ reschedule(startIdObj);
+ startIdObj = null;
+
+ }
+ else if (ACTION_REFRESH_PUSHERS.equals(intent.getAction()))
+ {
+ if (hasConnectivity && doBackground)
+ {
+ schedulePushers(null);
+ refreshPushers(startIdObj);
+ startIdObj = null;
+ }
+ }
+ else if (CONNECTIVITY_CHANGE.equals(intent.getAction()) ||
+ BACKGROUND_DATA_CHANGED.equals(intent.getAction()))
+ {
+ notifyConnectionStatus(hasConnectivity);
+ rescheduleAll(hasConnectivity, doBackground, startIdObj);
+ startIdObj = null;
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "Got connectivity action with hasConnectivity = " + hasConnectivity + ", doBackground = " + doBackground);
+ }
+ else if (CANCEL_CONNECTIVITY_NOTICE.equals(intent.getAction()))
+ {
+ notifyConnectionStatus(true);
+ }
+ }
+ finally
+ {
+ if (startIdObj != null)
+ {
+ stopSelf(startId);
+ }
+ }
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "MailService.onStart took " + (System.currentTimeMillis() - startTime) + "ms");
+ }
+
+ private void rescheduleAll(final boolean hasConnectivity, final boolean doBackground, final Integer startId)
+ {
+ if (hasConnectivity && doBackground)
+ {
+ reschedule(null);
+ reschedulePushers(startId);
+ }
+ else
+ {
+ stopPushers(startId);
+ }
+ }
+
+ private void notifyConnectionStatus(boolean hasConnectivity)
+ {
+ if (true) return;
+ NotificationManager notifMgr =
+ (NotificationManager)getApplication().getSystemService(Context.NOTIFICATION_SERVICE);
+ if (hasConnectivity == false)
+ {
+ String notice = getApplication().getString(R.string.no_connection_alert);
+ String header = getApplication().getString(R.string.alert_header);
+
+
+ Notification notif = new Notification(R.drawable.stat_notify_email_generic,
+ header, System.currentTimeMillis());
+
+ Intent i = new Intent();
+ i.setClassName(getApplication().getPackageName(), "com.fsck.k9.service.MailService");
+ i.setAction(MailService.CANCEL_CONNECTIVITY_NOTICE);
+
+ PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
+
+ notif.setLatestEventInfo(getApplication(), header, notice, pi);
+ notif.flags = Notification.FLAG_ONGOING_EVENT;
+
+ notifMgr.notify(K9.CONNECTIVITY_ID, notif);
+ }
+ else
+ {
+ notifMgr.cancel(K9.CONNECTIVITY_ID);
+ }
+ }
+
+ @Override
+ public void onDestroy()
+ {
+ if (K9.DEBUG)
+ Log.v(K9.LOG_TAG, "***** MailService *****: onDestroy()");
+ super.onDestroy();
+ // MessagingController.getInstance(getApplication()).removeListener(mListener);
+ }
+
+ private void cancel()
+ {
+ Intent i = new Intent();
+ i.setClassName(getApplication().getPackageName(), "com.fsck.k9.service.MailService");
+ i.setAction(ACTION_CHECK_MAIL);
+ BootReceiver.cancelIntent(this, i);
+ }
+
+ private void reschedule(Integer startId)
+ {
+ execute(getApplication(), new Runnable()
+ {
+ public void run()
+ {
+ int shortestInterval = -1;
+
+ for (Account account : Preferences.getPreferences(MailService.this).getAccounts())
+ {
+ if (account.getAutomaticCheckIntervalMinutes() != -1
+ && (account.getAutomaticCheckIntervalMinutes() < shortestInterval || shortestInterval == -1))
+ {
+ shortestInterval = account.getAutomaticCheckIntervalMinutes();
+ }
+ }
+
+ if (shortestInterval == -1)
+ {
+ if (K9.DEBUG)
+ Log.v(K9.LOG_TAG, "No next check scheduled for package " + getApplication().getPackageName());
+ cancel();
+ }
+ else
+ {
+ long delay = (shortestInterval * (60 * 1000));
+
+ long nextTime = System.currentTimeMillis() + delay;
+ try
+ {
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "Next check for package " + getApplication().getPackageName() + " scheduled for " + new Date(nextTime));
+ }
+ catch (Exception e)
+ {
+ // I once got a NullPointerException deep in new Date();
+ Log.e(K9.LOG_TAG, "Exception while logging", e);
+ }
+
+ Intent i = new Intent();
+ i.setClassName(getApplication().getPackageName(), "com.fsck.k9.service.MailService");
+ i.setAction(ACTION_CHECK_MAIL);
+ BootReceiver.scheduleIntent(MailService.this, nextTime, i);
+
+ }
+ }
+ }
+ , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
+ }
+
+ private void stopPushers(final Integer startId)
+ {
+ execute(getApplication(), new Runnable()
+ {
+ public void run()
+ {
+ MessagingController.getInstance(getApplication()).stopAllPushing();
+ PushService.stopService(MailService.this);
+ }
+ }
+ , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
+ }
+
+ private void reschedulePushers(final Integer startId)
+ {
+ execute(getApplication(), new Runnable()
+ {
+ public void run()
+ {
+
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "Rescheduling pushers");
+ stopPushers(null);
+ setupPushers(null);
+ schedulePushers(startId);
+
+ }
+ }
+ , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, null);
+ }
+
+ private void setupPushers(final Integer startId)
+ {
+ execute(getApplication(), new Runnable()
+ {
+ public void run()
+ {
+ boolean pushing = false;
+ for (Account account : Preferences.getPreferences(MailService.this).getAccounts())
+ {
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "Setting up pushers for account " + account.getDescription());
+ pushing |= MessagingController.getInstance(getApplication()).setupPushing(account);
+ }
+ if (pushing)
+ {
+ PushService.startService(MailService.this);
+ }
+ }
+ }
+ , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
+ }
+
+ private void refreshPushers(final Integer startId)
+ {
+ execute(getApplication(), new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "Refreshing pushers");
+ Collection pushers = MessagingController.getInstance(getApplication()).getPushers();
+ for (Pusher pusher : pushers)
+ {
+ pusher.refresh();
+ }
+ }
+ catch (Exception e)
+ {
+ Log.e(K9.LOG_TAG, "Exception while refreshing pushers", e);
+ }
+ }
+ }
+ , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
+ }
+
+ private void schedulePushers(final Integer startId)
+ {
+ execute(getApplication(), new Runnable()
+ {
+ public void run()
+ {
+ int minInterval = -1;
+
+ Collection pushers = MessagingController.getInstance(getApplication()).getPushers();
+ for (Pusher pusher : pushers)
+ {
+ int interval = pusher.getRefreshInterval();
+ if (interval != -1 && (interval < minInterval || minInterval == -1))
+ {
+ minInterval = interval;
+ }
+ }
+ if (K9.DEBUG)
+ {
+ Log.v(K9.LOG_TAG, "Pusher refresh interval = " + minInterval);
+ }
+ if (minInterval != -1)
+ {
+ long nextTime = System.currentTimeMillis() + minInterval;
+ if (K9.DEBUG)
+ Log.d(K9.LOG_TAG, "Next pusher refresh scheduled for " + new Date(nextTime));
+ Intent i = new Intent();
+ i.setClassName(getApplication().getPackageName(), "com.fsck.k9.service.MailService");
+ i.setAction(ACTION_REFRESH_PUSHERS);
+ BootReceiver.scheduleIntent(MailService.this, nextTime, i);
+ }
+ }
+ }
+ , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
+ }
+
+ public void execute(Context context, final Runnable runner, int wakeLockTime, final Integer startId)
+ {
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ final WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "K9");
+ wakeLock.setReferenceCounted(false);
+ wakeLock.acquire(wakeLockTime);
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "MailService queueing Runnable " + runner.hashCode() + " with startId " + startId);
+ Runnable myRunner = new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "MailService running Runnable " + runner.hashCode() + " with startId " + startId);
+ runner.run();
+ }
+ finally
+ {
+ if (K9.DEBUG)
+ Log.i(K9.LOG_TAG, "MailService completed Runnable " + runner.hashCode() + " with startId " + startId);
+ wakeLock.release();
+ if (startId != null)
+ {
+ stopSelf(startId);
+ }
+ }
+ }
+
+ };
+
+ threadPool.execute(myRunner);
+ }
+
+ public IBinder onBind(Intent intent)
+ {
+ return null;
+ }
+
+
+}