1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-12-26 01:28:50 -05:00

Preparatory for more BroadcastReceivers

This commit is contained in:
Daniel Applebaum 2010-01-04 00:47:11 +00:00
parent 33495135ac
commit c86a46deb1
4 changed files with 644 additions and 608 deletions

View File

@ -214,14 +214,18 @@
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.net.conn.BACKGROUND_DATA_SETTING_CHANGED" /> <action android:name="android.net.conn.BACKGROUND_DATA_SETTING_CHANGED" />
</intent-filter>
<intent-filter>
<action android:name="com.fsck.k9.service.BroadcastReceiver.wakeLockRelease"/>
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="com.fsck.k9.service.BroadcastReceiver.scheduleIntent"/> <action android:name="com.fsck.k9.service.BroadcastReceiver.scheduleIntent"/>
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver android:name="com.fsck.k9.service.CoreReceiver"
android:enabled="true"
>
<intent-filter>
<action android:name="com.fsck.k9.service.CoreReceiver.wakeLockRelease"/>
</intent-filter>
</receiver>
<service <service
android:name="com.fsck.k9.service.MailService" android:name="com.fsck.k9.service.MailService"
android:enabled="true" android:enabled="true"

View File

@ -1,151 +1,98 @@
package com.fsck.k9.service; package com.fsck.k9.service;
import java.util.Date;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.Uri; import android.net.Uri;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log; import android.util.Log;
import com.fsck.k9.K9; import com.fsck.k9.K9;
import java.util.Date; public class BootReceiver extends CoreReceiver
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
public class BootReceiver extends BroadcastReceiver
{ {
public static String WAKE_LOCK_RELEASE = "com.fsck.k9.service.BroadcastReceiver.wakeLockRelease";
public static String FIRE_INTENT = "com.fsck.k9.service.BroadcastReceiver.fireIntent"; public static String FIRE_INTENT = "com.fsck.k9.service.BroadcastReceiver.fireIntent";
public static String SCHEDULE_INTENT = "com.fsck.k9.service.BroadcastReceiver.scheduleIntent"; public static String SCHEDULE_INTENT = "com.fsck.k9.service.BroadcastReceiver.scheduleIntent";
public static String CANCEL_INTENT = "com.fsck.k9.service.BroadcastReceiver.cancelIntent"; public static String CANCEL_INTENT = "com.fsck.k9.service.BroadcastReceiver.cancelIntent";
public static String WAKE_LOCK_ID = "com.fsck.k9.service.BroadcastReceiver.wakeLockId";
public static String ALARMED_INTENT = "com.fsck.k9.service.BroadcastReceiver.pendingIntent"; public static String ALARMED_INTENT = "com.fsck.k9.service.BroadcastReceiver.pendingIntent";
public static String AT_TIME = "com.fsck.k9.service.BroadcastReceiver.atTime"; public static String AT_TIME = "com.fsck.k9.service.BroadcastReceiver.atTime";
private static ConcurrentHashMap<Integer, WakeLock> wakeLocks = new ConcurrentHashMap<Integer, WakeLock>(); public Integer receive(Context context, Intent intent, Integer tmpWakeLockId)
private static AtomicInteger wakeLockSeq = new AtomicInteger(0);
private Integer getWakeLock(Context context)
{ {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); if (K9.DEBUG)
WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "K9"); Log.i(K9.LOG_TAG, "BootReceiver.onReceive" + intent);
wakeLock.setReferenceCounted(false);
wakeLock.acquire(K9.BOOT_RECEIVER_WAKE_LOCK_TIMEOUT);
Integer tmpWakeLockId = wakeLockSeq.getAndIncrement();
wakeLocks.put(tmpWakeLockId, wakeLock);
return tmpWakeLockId;
}
private void releaseWakeLock(Integer wakeLockId) if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()))
{
if (wakeLockId != null)
{ {
WakeLock wl = wakeLocks.remove(wakeLockId); //K9.setServicesEnabled(context, tmpWakeLockId);
if (wl != null) //tmpWakeLockId = null;
{
wl.release();
}
else
{
if (K9.DEBUG)
Log.w(K9.LOG_TAG, "BootReceiver WakeLock " + wakeLockId + " doesn't exist");
}
} }
} else if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(intent.getAction()))
public void onReceive(Context context, Intent intent)
{
Integer tmpWakeLockId = getWakeLock(context);
try
{ {
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) if (K9.DEBUG)
Log.i(K9.LOG_TAG, "BootReceiver.onReceive" + intent); Log.i(K9.LOG_TAG, "BootReceiver Got alarm to fire alarmedIntent " + alarmedAction);
alarmedIntent.putExtra(WAKE_LOCK_ID, tmpWakeLockId);
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) tmpWakeLockId = null;
if (alarmedIntent != null)
{ {
//K9.setServicesEnabled(context, tmpWakeLockId); context.startService(alarmedIntent);
//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);
}
} }
} }
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) private PendingIntent buildPendingIntent(Context context, Intent intent)
@ -184,15 +131,5 @@ public class BootReceiver extends BroadcastReceiver
i.putExtra(ALARMED_INTENT, alarmedIntent); i.putExtra(ALARMED_INTENT, alarmedIntent);
context.sendBroadcast(i); 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);
}
} }

View File

@ -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<Integer, WakeLock> wakeLocks = new ConcurrentHashMap<Integer, WakeLock>();
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);
}
}

View File

@ -1,478 +1,473 @@
package com.fsck.k9.service; package com.fsck.k9.service;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.NetworkInfo.State; import android.net.NetworkInfo.State;
import android.os.IBinder; import android.os.IBinder;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.PowerManager.WakeLock; import android.os.PowerManager.WakeLock;
import android.util.Config; import android.util.Config;
import android.util.Log; import android.util.Log;
import com.fsck.k9.*; import com.fsck.k9.*;
import com.fsck.k9.mail.Pusher; import com.fsck.k9.mail.Pusher;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
/** /**
*/ */
public class MailService extends CoreService 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_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 = "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_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_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 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 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 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 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 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 private final ExecutorService threadPool = Executors.newFixedThreadPool(1); // Must be single threaded
public static void actionReschedule(Context context, Integer wakeLockId) public static void actionReschedule(Context context, Integer wakeLockId)
{ {
Intent i = new Intent(); Intent i = new Intent();
i.setClass(context, MailService.class); i.setClass(context, MailService.class);
i.setAction(MailService.ACTION_RESCHEDULE); i.setAction(MailService.ACTION_RESCHEDULE);
addWakeLockId(i, wakeLockId); addWakeLockId(i, wakeLockId);
context.startService(i); if (wakeLockId == null)
} {
addWakeLock(context, i);
public static void rescheduleCheck(Context context, Integer wakeLockId) }
{ context.startService(i);
Intent i = new Intent(); }
i.setClass(context, MailService.class);
i.setAction(MailService.ACTION_RESCHEDULE_CHECK); public static void rescheduleCheck(Context context, Integer wakeLockId)
addWakeLockId(i, wakeLockId); {
context.startService(i); Intent i = new Intent();
} i.setClass(context, MailService.class);
i.setAction(MailService.ACTION_RESCHEDULE_CHECK);
public static void actionCancel(Context context, Integer wakeLockId) addWakeLockId(i, wakeLockId);
{ context.startService(i);
Intent i = new Intent(); }
i.setClass(context, MailService.class);
i.setAction(MailService.ACTION_CANCEL); public static void actionCancel(Context context, Integer wakeLockId)
addWakeLockId(i, wakeLockId); {
context.startService(i); Intent i = new Intent();
} i.setClass(context, MailService.class);
i.setAction(MailService.ACTION_CANCEL);
public static void connectivityChange(Context context, boolean hasConnectivity, Integer wakeLockId) addWakeLockId(i, wakeLockId);
{ context.startService(i);
Intent i = new Intent(); }
i.setClass(context, MailService.class);
i.setAction(MailService.CONNECTIVITY_CHANGE); public static void connectivityChange(Context context, boolean hasConnectivity, Integer wakeLockId)
i.putExtra(HAS_CONNECTIVITY, hasConnectivity); {
addWakeLockId(i, wakeLockId); Intent i = new Intent();
context.startService(i); i.setClass(context, MailService.class);
} i.setAction(MailService.CONNECTIVITY_CHANGE);
i.putExtra(HAS_CONNECTIVITY, hasConnectivity);
public static void backgroundDataChanged(Context context, Integer wakeLockId) addWakeLockId(i, wakeLockId);
{ context.startService(i);
Intent i = new Intent(); }
i.setClass(context, MailService.class);
i.setAction(MailService.BACKGROUND_DATA_CHANGED); public static void backgroundDataChanged(Context context, Integer wakeLockId)
addWakeLockId(i, wakeLockId); {
context.startService(i); Intent i = new Intent();
} i.setClass(context, MailService.class);
i.setAction(MailService.BACKGROUND_DATA_CHANGED);
@Override addWakeLockId(i, wakeLockId);
public void onCreate() context.startService(i);
{ }
super.onCreate();
if (K9.DEBUG) @Override
Log.v(K9.LOG_TAG, "***** MailService *****: onCreate"); public void onCreate()
} {
super.onCreate();
@Override if (K9.DEBUG)
public void startService(Intent intent, int startId) Log.v(K9.LOG_TAG, "***** MailService *****: onCreate");
{ }
Integer startIdObj = startId;
long startTime = System.currentTimeMillis(); @Override
try public void startService(Intent intent, int startId)
{ {
ConnectivityManager connectivityManager = (ConnectivityManager)getApplication().getSystemService(Context.CONNECTIVITY_SERVICE); Integer startIdObj = startId;
boolean doBackground = true; long startTime = System.currentTimeMillis();
boolean hasConnectivity = false; try
{
if (connectivityManager != null) ConnectivityManager connectivityManager = (ConnectivityManager)getApplication().getSystemService(Context.CONNECTIVITY_SERVICE);
{ boolean doBackground = true;
NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo(); boolean hasConnectivity = false;
if (netInfo != null)
{ if (connectivityManager != null)
State state = netInfo.getState(); {
hasConnectivity = state == State.CONNECTED; NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
} if (netInfo != null)
boolean backgroundData = connectivityManager.getBackgroundDataSetting(); {
State state = netInfo.getState();
K9.BACKGROUND_OPS bOps = K9.getBackgroundOps(); hasConnectivity = state == State.CONNECTED;
doBackground = (backgroundData == true && bOps != K9.BACKGROUND_OPS.NEVER) }
| (backgroundData == false && bOps == K9.BACKGROUND_OPS.ALWAYS); boolean backgroundData = connectivityManager.getBackgroundDataSetting();
} K9.BACKGROUND_OPS bOps = K9.getBackgroundOps();
doBackground = (backgroundData == true && bOps != K9.BACKGROUND_OPS.NEVER)
setForeground(true); // if it gets killed once, it'll never restart | (backgroundData == false && bOps == K9.BACKGROUND_OPS.ALWAYS);
if (K9.DEBUG)
Log.i(K9.LOG_TAG, "MailService.onStart(" + intent + ", " + startId }
+ "), hasConnectivity = " + hasConnectivity + ", doBackground = " + doBackground);
setForeground(true); // if it gets killed once, it'll never restart
// MessagingController.getInstance(getApplication()).addListener(mListener); if (K9.DEBUG)
if (ACTION_CHECK_MAIL.equals(intent.getAction())) Log.i(K9.LOG_TAG, "MailService.onStart(" + intent + ", " + startId
{ + "), hasConnectivity = " + hasConnectivity + ", doBackground = " + doBackground);
if (K9.DEBUG)
Log.i(K9.LOG_TAG, "***** MailService *****: checking mail"); // MessagingController.getInstance(getApplication()).addListener(mListener);
if (ACTION_CHECK_MAIL.equals(intent.getAction()))
if (hasConnectivity && doBackground) {
{ if (K9.DEBUG)
PollService.startService(this); Log.i(K9.LOG_TAG, "***** MailService *****: checking mail");
}
if (hasConnectivity && doBackground)
reschedule(startIdObj); {
startIdObj = null; PollService.startService(this);
} }
else if (ACTION_CANCEL.equals(intent.getAction()))
{ reschedule(startIdObj);
if (Config.LOGV) startIdObj = null;
{ }
Log.v(K9.LOG_TAG, "***** MailService *****: cancel"); else if (ACTION_CANCEL.equals(intent.getAction()))
} {
if (K9.DEBUG)
cancel(); Log.v(K9.LOG_TAG, "***** MailService *****: cancel");
}
else if (ACTION_RESCHEDULE.equals(intent.getAction())) cancel();
{ }
if (Config.LOGV) else if (ACTION_RESCHEDULE.equals(intent.getAction()))
{ {
Log.v(K9.LOG_TAG, "***** MailService *****: reschedule"); if (K9.DEBUG)
} Log.v(K9.LOG_TAG, "***** MailService *****: reschedule");
rescheduleAll(hasConnectivity, doBackground, startIdObj);
startIdObj = null; rescheduleAll(hasConnectivity, doBackground, startIdObj);
startIdObj = null;
}
else if (ACTION_RESCHEDULE_CHECK.equals(intent.getAction())) }
{ else if (ACTION_RESCHEDULE_CHECK.equals(intent.getAction()))
if (Config.LOGV) {
{ if (K9.DEBUG)
Log.v(K9.LOG_TAG, "***** MailService *****: reschedule check"); Log.v(K9.LOG_TAG, "***** MailService *****: reschedule check");
}
reschedule(startIdObj); reschedule(startIdObj);
startIdObj = null; startIdObj = null;
} }
else if (ACTION_REFRESH_PUSHERS.equals(intent.getAction())) else if (ACTION_REFRESH_PUSHERS.equals(intent.getAction()))
{ {
if (hasConnectivity && doBackground) if (hasConnectivity && doBackground)
{ {
schedulePushers(null); schedulePushers(null);
refreshPushers(startIdObj); refreshPushers(startIdObj);
startIdObj = null; startIdObj = null;
} }
} }
else if (CONNECTIVITY_CHANGE.equals(intent.getAction()) || else if (CONNECTIVITY_CHANGE.equals(intent.getAction()) ||
BACKGROUND_DATA_CHANGED.equals(intent.getAction())) BACKGROUND_DATA_CHANGED.equals(intent.getAction()))
{ {
notifyConnectionStatus(hasConnectivity); notifyConnectionStatus(hasConnectivity);
rescheduleAll(hasConnectivity, doBackground, startIdObj); rescheduleAll(hasConnectivity, doBackground, startIdObj);
startIdObj = null; startIdObj = null;
if (K9.DEBUG) if (K9.DEBUG)
Log.i(K9.LOG_TAG, "Got connectivity action with hasConnectivity = " + hasConnectivity + ", doBackground = " + doBackground); Log.i(K9.LOG_TAG, "Got connectivity action with hasConnectivity = " + hasConnectivity + ", doBackground = " + doBackground);
} }
else if (CANCEL_CONNECTIVITY_NOTICE.equals(intent.getAction())) else if (CANCEL_CONNECTIVITY_NOTICE.equals(intent.getAction()))
{ {
notifyConnectionStatus(true); notifyConnectionStatus(true);
} }
} }
finally finally
{ {
if (startIdObj != null) if (startIdObj != null)
{ {
stopSelf(startId); stopSelf(startId);
} }
} }
if (K9.DEBUG) if (K9.DEBUG)
Log.i(K9.LOG_TAG, "MailService.onStart took " + (System.currentTimeMillis() - startTime) + "ms"); Log.i(K9.LOG_TAG, "MailService.onStart took " + (System.currentTimeMillis() - startTime) + "ms");
} }
private void rescheduleAll(final boolean hasConnectivity, final boolean doBackground, final Integer startId) private void rescheduleAll(final boolean hasConnectivity, final boolean doBackground, final Integer startId)
{ {
if (hasConnectivity && doBackground) if (hasConnectivity && doBackground)
{ {
reschedule(null); reschedule(null);
reschedulePushers(startId); reschedulePushers(startId);
} }
else else
{ {
stopPushers(startId); stopPushers(startId);
} }
} }
private void notifyConnectionStatus(boolean hasConnectivity) private void notifyConnectionStatus(boolean hasConnectivity)
{ {
if (true) return; if (true) return;
NotificationManager notifMgr = NotificationManager notifMgr =
(NotificationManager)getApplication().getSystemService(Context.NOTIFICATION_SERVICE); (NotificationManager)getApplication().getSystemService(Context.NOTIFICATION_SERVICE);
if (hasConnectivity == false) if (hasConnectivity == false)
{ {
String notice = getApplication().getString(R.string.no_connection_alert); String notice = getApplication().getString(R.string.no_connection_alert);
String header = getApplication().getString(R.string.alert_header); String header = getApplication().getString(R.string.alert_header);
Notification notif = new Notification(R.drawable.stat_notify_email_generic, Notification notif = new Notification(R.drawable.stat_notify_email_generic,
header, System.currentTimeMillis()); header, System.currentTimeMillis());
Intent i = new Intent(); Intent i = new Intent();
i.setClassName(getApplication().getPackageName(), "com.fsck.k9.service.MailService"); i.setClassName(getApplication().getPackageName(), "com.fsck.k9.service.MailService");
i.setAction(MailService.CANCEL_CONNECTIVITY_NOTICE); i.setAction(MailService.CANCEL_CONNECTIVITY_NOTICE);
PendingIntent pi = PendingIntent.getService(this, 0, i, 0); PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
notif.setLatestEventInfo(getApplication(), header, notice, pi); notif.setLatestEventInfo(getApplication(), header, notice, pi);
notif.flags = Notification.FLAG_ONGOING_EVENT; notif.flags = Notification.FLAG_ONGOING_EVENT;
notifMgr.notify(K9.CONNECTIVITY_ID, notif); notifMgr.notify(K9.CONNECTIVITY_ID, notif);
} }
else else
{ {
notifMgr.cancel(K9.CONNECTIVITY_ID); notifMgr.cancel(K9.CONNECTIVITY_ID);
} }
} }
@Override @Override
public void onDestroy() public void onDestroy()
{ {
if (K9.DEBUG) if (K9.DEBUG)
Log.v(K9.LOG_TAG, "***** MailService *****: onDestroy()"); Log.v(K9.LOG_TAG, "***** MailService *****: onDestroy()");
super.onDestroy(); super.onDestroy();
// MessagingController.getInstance(getApplication()).removeListener(mListener); // MessagingController.getInstance(getApplication()).removeListener(mListener);
} }
private void cancel() private void cancel()
{ {
Intent i = new Intent(); Intent i = new Intent();
i.setClassName(getApplication().getPackageName(), "com.fsck.k9.service.MailService"); i.setClassName(getApplication().getPackageName(), "com.fsck.k9.service.MailService");
i.setAction(ACTION_CHECK_MAIL); i.setAction(ACTION_CHECK_MAIL);
BootReceiver.cancelIntent(this, i); BootReceiver.cancelIntent(this, i);
} }
private void reschedule(Integer startId) private void reschedule(Integer startId)
{ {
execute(getApplication(), new Runnable() execute(getApplication(), new Runnable()
{ {
public void run() public void run()
{ {
int shortestInterval = -1; int shortestInterval = -1;
for (Account account : Preferences.getPreferences(MailService.this).getAccounts()) for (Account account : Preferences.getPreferences(MailService.this).getAccounts())
{ {
if (account.getAutomaticCheckIntervalMinutes() != -1 if (account.getAutomaticCheckIntervalMinutes() != -1
&& (account.getAutomaticCheckIntervalMinutes() < shortestInterval || shortestInterval == -1)) && (account.getAutomaticCheckIntervalMinutes() < shortestInterval || shortestInterval == -1))
{ {
shortestInterval = account.getAutomaticCheckIntervalMinutes(); shortestInterval = account.getAutomaticCheckIntervalMinutes();
} }
} }
if (shortestInterval == -1) if (shortestInterval == -1)
{ {
if (K9.DEBUG) if (K9.DEBUG)
Log.v(K9.LOG_TAG, "No next check scheduled for package " + getApplication().getPackageName()); Log.v(K9.LOG_TAG, "No next check scheduled for package " + getApplication().getPackageName());
cancel(); cancel();
} }
else else
{ {
long delay = (shortestInterval * (60 * 1000)); long delay = (shortestInterval * (60 * 1000));
long nextTime = System.currentTimeMillis() + delay; long nextTime = System.currentTimeMillis() + delay;
if (K9.DEBUG) try
{ {
try if (K9.DEBUG)
{ Log.i(K9.LOG_TAG, "Next check for package " + getApplication().getPackageName() + " scheduled for " + new Date(nextTime));
Log.i(K9.LOG_TAG, }
"Next check for package " + getApplication().getPackageName() + " scheduled for " + new Date(nextTime)); catch (Exception e)
} {
catch (Exception e) // I once got a NullPointerException deep in new Date();
{ Log.e(K9.LOG_TAG, "Exception while logging", 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);
Intent i = new Intent(); BootReceiver.scheduleIntent(MailService.this, nextTime, i);
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);
} }
}
, K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId); private void stopPushers(final Integer startId)
} {
execute(getApplication(), new Runnable()
private void stopPushers(final Integer startId) {
{ public void run()
execute(getApplication(), new Runnable() {
{ MessagingController.getInstance(getApplication()).stopAllPushing();
public void run() PushService.stopService(MailService.this);
{ }
MessagingController.getInstance(getApplication()).stopAllPushing(); }
PushService.stopService(MailService.this); , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
} }
}
, K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId); private void reschedulePushers(final Integer startId)
} {
execute(getApplication(), new Runnable()
private void reschedulePushers(final Integer startId) {
{ public void run()
execute(getApplication(), new Runnable() {
{
public void run() if (K9.DEBUG)
{ Log.i(K9.LOG_TAG, "Rescheduling pushers");
stopPushers(null);
if (K9.DEBUG) setupPushers(null);
Log.i(K9.LOG_TAG, "Rescheduling pushers"); schedulePushers(startId);
stopPushers(null);
setupPushers(null); }
schedulePushers(startId); }
, K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, null);
} }
}
, K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, null); private void setupPushers(final Integer startId)
} {
execute(getApplication(), new Runnable()
private void setupPushers(final Integer startId) {
{ public void run()
execute(getApplication(), new Runnable() {
{ boolean pushing = false;
public void run() for (Account account : Preferences.getPreferences(MailService.this).getAccounts())
{ {
boolean pushing = false; if (K9.DEBUG)
for (Account account : Preferences.getPreferences(MailService.this).getAccounts()) Log.i(K9.LOG_TAG, "Setting up pushers for account " + account.getDescription());
{ pushing |= MessagingController.getInstance(getApplication()).setupPushing(account);
if (K9.DEBUG) }
Log.i(K9.LOG_TAG, "Setting up pushers for account " + account.getDescription()); if (pushing)
pushing |= MessagingController.getInstance(getApplication()).setupPushing(account); {
} PushService.startService(MailService.this);
if (pushing) }
{ }
PushService.startService(MailService.this); }
} , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
} }
}
, K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId); private void refreshPushers(final Integer startId)
} {
execute(getApplication(), new Runnable()
private void refreshPushers(final Integer startId) {
{ public void run()
execute(getApplication(), new Runnable() {
{ try
public void run() {
{ if (K9.DEBUG)
try Log.i(K9.LOG_TAG, "Refreshing pushers");
{ Collection<Pusher> pushers = MessagingController.getInstance(getApplication()).getPushers();
if (K9.DEBUG) for (Pusher pusher : pushers)
Log.i(K9.LOG_TAG, "Refreshing pushers"); {
Collection<Pusher> pushers = MessagingController.getInstance(getApplication()).getPushers(); pusher.refresh();
for (Pusher pusher : pushers) }
{ }
pusher.refresh(); catch (Exception e)
} {
} Log.e(K9.LOG_TAG, "Exception while refreshing pushers", e);
catch (Exception e) }
{ }
Log.e(K9.LOG_TAG, "Exception while refreshing pushers", e); }
} , K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
} }
}
, K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId); private void schedulePushers(final Integer startId)
} {
execute(getApplication(), new Runnable()
private void schedulePushers(final Integer startId) {
{ public void run()
execute(getApplication(), new Runnable() {
{ int minInterval = -1;
public void run()
{ Collection<Pusher> pushers = MessagingController.getInstance(getApplication()).getPushers();
int minInterval = -1; for (Pusher pusher : pushers)
{
Collection<Pusher> pushers = MessagingController.getInstance(getApplication()).getPushers(); int interval = pusher.getRefreshInterval();
for (Pusher pusher : pushers) if (interval != -1 && (interval < minInterval || minInterval == -1))
{ {
int interval = pusher.getRefreshInterval(); minInterval = interval;
if (interval != -1 && (interval < minInterval || minInterval == -1)) }
{ }
minInterval = interval; if (K9.DEBUG)
} {
} Log.v(K9.LOG_TAG, "Pusher refresh interval = " + minInterval);
if (K9.DEBUG) }
Log.v(K9.LOG_TAG, "Pusher refresh interval = " + minInterval); if (minInterval != -1)
{
if (minInterval != -1) long nextTime = System.currentTimeMillis() + minInterval;
{ if (K9.DEBUG)
long nextTime = System.currentTimeMillis() + minInterval; Log.d(K9.LOG_TAG, "Next pusher refresh scheduled for " + new Date(nextTime));
Intent i = new Intent();
if (K9.DEBUG) i.setClassName(getApplication().getPackageName(), "com.fsck.k9.service.MailService");
Log.d(K9.LOG_TAG, "Next pusher refresh scheduled for " + new Date(nextTime)); i.setAction(ACTION_REFRESH_PUSHERS);
BootReceiver.scheduleIntent(MailService.this, nextTime, i);
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)
, K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId); {
} PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
final WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "K9");
public void execute(Context context, final Runnable runner, int wakeLockTime, final Integer startId) wakeLock.setReferenceCounted(false);
{ wakeLock.acquire(wakeLockTime);
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); if (K9.DEBUG)
final WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "K9"); Log.i(K9.LOG_TAG, "MailService queueing Runnable " + runner.hashCode() + " with startId " + startId);
wakeLock.setReferenceCounted(false); Runnable myRunner = new Runnable()
wakeLock.acquire(wakeLockTime); {
if (K9.DEBUG) public void run()
Log.i(K9.LOG_TAG, "MailService queueing Runnable " + runner.hashCode() + " with startId " + startId); {
try
Runnable myRunner = new Runnable() {
{
public void run() if (K9.DEBUG)
{ Log.i(K9.LOG_TAG, "MailService running Runnable " + runner.hashCode() + " with startId " + startId);
try runner.run();
{ }
if (K9.DEBUG) finally
Log.i(K9.LOG_TAG, "MailService running Runnable " + runner.hashCode() + " with startId " + startId); {
runner.run(); if (K9.DEBUG)
} Log.i(K9.LOG_TAG, "MailService completed Runnable " + runner.hashCode() + " with startId " + startId);
finally wakeLock.release();
{ if (startId != null)
if (K9.DEBUG) {
Log.i(K9.LOG_TAG, "MailService completed Runnable " + runner.hashCode() + " with startId " + startId); stopSelf(startId);
wakeLock.release(); }
}
if (startId != null) }
{
stopSelf(startId); };
}
} threadPool.execute(myRunner);
} }
}; public IBinder onBind(Intent intent)
{
threadPool.execute(myRunner); return null;
} }
public IBinder onBind(Intent intent)
{ }
return null;
}
}