2009-12-14 21:50:53 -05:00
|
|
|
package com.fsck.k9.service;
|
2009-11-22 12:01:04 -05:00
|
|
|
|
2009-12-20 20:48:15 -05:00
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
2010-01-12 09:09:30 -05:00
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
|
import java.util.concurrent.Executors;
|
2010-10-29 15:55:04 -04:00
|
|
|
import java.util.concurrent.RejectedExecutionException;
|
2009-12-20 20:48:15 -05:00
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
2009-11-22 12:01:04 -05:00
|
|
|
import android.app.Service;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.os.IBinder;
|
|
|
|
import android.os.PowerManager;
|
|
|
|
import android.util.Log;
|
2009-12-14 21:50:53 -05:00
|
|
|
import com.fsck.k9.K9;
|
2011-02-04 18:18:08 -05:00
|
|
|
import com.fsck.k9.controller.MessagingController;
|
2010-05-16 20:30:32 -04:00
|
|
|
import com.fsck.k9.helper.power.TracingPowerManager;
|
|
|
|
import com.fsck.k9.helper.power.TracingPowerManager.TracingWakeLock;
|
2009-11-22 12:01:04 -05:00
|
|
|
|
2011-09-04 16:00:02 -04:00
|
|
|
/**
|
2011-10-28 23:00:37 -04:00
|
|
|
* {@code CoreService} is the base class for all K-9 Services.
|
2011-10-28 15:29:39 -04:00
|
|
|
*
|
2011-10-28 23:00:37 -04:00
|
|
|
* <p>
|
|
|
|
* An Android service is a way to model a part of an application that needs to accomplish certain
|
|
|
|
* tasks without the UI part of the application being necessarily active (of course an application
|
|
|
|
* could also be a pure service, without any UI; this is not the case of K-9). By declaring a
|
|
|
|
* service and starting it, the OS knows that the application has work to do and should avoid
|
|
|
|
* killing the process.
|
|
|
|
* </p><p>
|
|
|
|
* A service's main purpose is to do some task (usually in the background) which requires one or
|
|
|
|
* more threads. The thread that starts the service is the same as the UI thread of the process. It
|
|
|
|
* should thus not be used to run the tasks.
|
|
|
|
* </p><p>
|
|
|
|
* CoreService is providing the execution plumbing for background tasks including the required
|
|
|
|
* thread and task queuing for all K9 services to use.
|
|
|
|
* </p><p>
|
|
|
|
* A service is supposed to run only as long as it has some work to do whether that work is active
|
|
|
|
* processing or some just some monitoring, like listening on a network port for incoming connections
|
|
|
|
* or listing on an open network connection for incoming data (push mechanism).
|
|
|
|
* </p><p>
|
|
|
|
* To make sure the service is running only when required, is must be shutdown after tasks are
|
|
|
|
* done. As the execution of tasks is abstracted away in this class, it also handles proper
|
|
|
|
* shutdown. If a Service doesn't want this, it needs to call {@code enableAutoShutdown(true)} in
|
|
|
|
* its {@link Service#onCreate()} method.
|
|
|
|
* </p><p>
|
|
|
|
* While a service is running its tasks, it is usually not a good idea to let the device go to
|
|
|
|
* sleep mode. Wake locks are used to avoid this. CoreService provides a central registry
|
|
|
|
* (singleton) that can be used application-wide to store wake locks.
|
|
|
|
* </p><p>
|
|
|
|
* In short, CoreService provides the following features to K-9 Services:
|
|
|
|
* <ul>
|
|
|
|
* <li>task execution and queuing</li>
|
|
|
|
* <li>Service life cycle management (ensures the service is stopped when not needed anymore);
|
|
|
|
* enabled by default</li>
|
|
|
|
* <li>wake lock registry and management</li>
|
|
|
|
* </ul>
|
2011-09-04 16:00:02 -04:00
|
|
|
*/
|
2011-02-06 17:09:48 -05:00
|
|
|
public abstract class CoreService extends Service {
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2011-10-28 23:00:37 -04:00
|
|
|
public static String WAKE_LOCK_ID = "com.fsck.k9.service.CoreService.wakeLockId";
|
|
|
|
|
|
|
|
private static ConcurrentHashMap<Integer, TracingWakeLock> sWakeLocks =
|
|
|
|
new ConcurrentHashMap<Integer, TracingWakeLock>();
|
|
|
|
private static AtomicInteger sWakeLockSeq = new AtomicInteger(0);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Threadpool that is used to execute and queue background actions inside the service.
|
|
|
|
*/
|
|
|
|
private ExecutorService mThreadPool = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* String of the class name used in debug messages.
|
|
|
|
*/
|
2010-04-19 23:22:43 -04:00
|
|
|
private final String className = getClass().getName();
|
2010-04-29 00:59:14 -04:00
|
|
|
|
2011-09-04 16:00:02 -04:00
|
|
|
/**
|
2011-10-28 23:00:37 -04:00
|
|
|
* {@code true} if the {@code Service}'s {@link #onDestroy()} method was called. {@code false}
|
|
|
|
* otherwise.
|
|
|
|
*
|
|
|
|
* <p>
|
|
|
|
* <strong>Note:</strong>
|
|
|
|
* This is used to ignore (expected) {@link RejectedExecutionException}s thrown by
|
|
|
|
* {@link ExecutorService#execute(Runnable)} after the service (and with that, the thread pool)
|
|
|
|
* was shut down.
|
|
|
|
* </p>
|
2011-09-04 16:00:02 -04:00
|
|
|
*/
|
2011-10-28 23:00:37 -04:00
|
|
|
private volatile boolean mShutdown = false;
|
2011-10-28 15:29:39 -04:00
|
|
|
|
2011-09-04 16:00:02 -04:00
|
|
|
/**
|
2011-10-28 23:00:37 -04:00
|
|
|
* Controls the auto shutdown mechanism of the service.
|
|
|
|
*
|
|
|
|
* <p>
|
|
|
|
* The default service life-cycle model is that the service should run only as long as a task
|
|
|
|
* is running. If a service should behave differently, disable auto shutdown using
|
|
|
|
* {@link #setAutoShutdown(boolean)}.
|
|
|
|
* </p>
|
2011-09-04 16:00:02 -04:00
|
|
|
*/
|
2011-10-28 23:00:37 -04:00
|
|
|
private boolean mAutoShutdown = true;
|
2011-10-28 15:29:39 -04:00
|
|
|
|
2011-10-28 23:00:37 -04:00
|
|
|
/**
|
|
|
|
* This variable is part of the auto shutdown feature and determines whether the service has to
|
|
|
|
* be shutdown at the end of the {@link #onStart(Intent, int)} method or not.
|
|
|
|
*/
|
|
|
|
protected boolean mImmediateShutdown = true;
|
2010-04-29 00:59:14 -04:00
|
|
|
|
|
|
|
|
2011-09-04 16:00:02 -04:00
|
|
|
/**
|
2011-10-28 23:00:37 -04:00
|
|
|
* Adds an existing wake lock identified by its registry ID to the specified intent.
|
|
|
|
*
|
|
|
|
* @param context
|
|
|
|
* A {@link Context} instance. Never {@code null}.
|
|
|
|
* @param intent
|
|
|
|
* The {@link Intent} to add the wake lock registy ID as extra to. Never {@code null}.
|
2011-09-04 16:00:02 -04:00
|
|
|
* @param wakeLockId
|
2011-10-28 23:00:37 -04:00
|
|
|
* The wake lock registry ID of an existing wake lock or {@code null}.
|
|
|
|
* @param createIfNotExists
|
|
|
|
* If {@code wakeLockId} is {@code null} and this parameter is {@code true} a new wake
|
|
|
|
* lock is created, registered, and added to {@code intent}.
|
2011-09-04 16:00:02 -04:00
|
|
|
*/
|
2011-10-28 23:00:37 -04:00
|
|
|
protected static void addWakeLockId(Context context, Intent intent, Integer wakeLockId,
|
|
|
|
boolean createIfNotExists) {
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
if (wakeLockId != null) {
|
2011-10-28 23:00:37 -04:00
|
|
|
intent.putExtra(BootReceiver.WAKE_LOCK_ID, wakeLockId);
|
2011-09-04 16:00:02 -04:00
|
|
|
return;
|
2009-11-22 12:01:04 -05:00
|
|
|
}
|
2011-10-28 23:00:37 -04:00
|
|
|
|
|
|
|
if (createIfNotExists) {
|
|
|
|
addWakeLock(context,intent);
|
|
|
|
}
|
2009-11-22 12:01:04 -05:00
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2011-09-04 16:00:02 -04:00
|
|
|
/**
|
2011-10-28 23:00:37 -04:00
|
|
|
* Adds a new wake lock to the specified intent.
|
|
|
|
*
|
|
|
|
* <p>
|
|
|
|
* This will add the wake lock to the central wake lock registry managed by this class.
|
|
|
|
* </p>
|
|
|
|
*
|
|
|
|
* @param context
|
|
|
|
* A {@link Context} instance. Never {@code null}.
|
|
|
|
* @param intent
|
|
|
|
* The {@link Intent} to add the wake lock registy ID as extra to. Never {@code null}.
|
2011-09-04 16:00:02 -04:00
|
|
|
*/
|
2011-10-28 23:00:37 -04:00
|
|
|
protected static void addWakeLock(Context context, Intent intent) {
|
|
|
|
TracingWakeLock wakeLock = acquireWakeLock(context, "CoreService addWakeLock",
|
|
|
|
K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT);
|
2011-09-04 16:00:02 -04:00
|
|
|
Integer tmpWakeLockId = registerWakeLock(wakeLock);
|
2011-10-28 23:00:37 -04:00
|
|
|
intent.putExtra(WAKE_LOCK_ID, tmpWakeLockId);
|
2011-09-04 16:00:02 -04:00
|
|
|
}
|
2010-01-02 20:50:51 -05:00
|
|
|
|
2011-09-04 16:00:02 -04:00
|
|
|
/**
|
2011-10-28 23:00:37 -04:00
|
|
|
* Registers a wake lock with the wake lock registry.
|
|
|
|
*
|
2011-09-04 16:00:02 -04:00
|
|
|
* @param wakeLock
|
2011-10-28 23:00:37 -04:00
|
|
|
* The {@link TracingWakeLock} instance that should be registered with the wake lock
|
|
|
|
* registry. Never {@code null}.
|
|
|
|
*
|
|
|
|
* @return The ID that identifies this wake lock in the registry.
|
2011-09-04 16:00:02 -04:00
|
|
|
*/
|
|
|
|
protected static Integer registerWakeLock(TracingWakeLock wakeLock) {
|
2011-10-28 23:00:37 -04:00
|
|
|
// Get a new wake lock ID
|
|
|
|
Integer tmpWakeLockId = sWakeLockSeq.getAndIncrement();
|
|
|
|
|
|
|
|
// Store the wake lock in the registry
|
|
|
|
sWakeLocks.put(tmpWakeLockId, wakeLock);
|
|
|
|
|
2011-09-04 16:00:02 -04:00
|
|
|
return tmpWakeLockId;
|
2009-12-20 20:48:15 -05:00
|
|
|
}
|
2010-04-29 00:59:14 -04:00
|
|
|
|
2011-09-04 16:00:02 -04:00
|
|
|
/**
|
2011-10-28 23:00:37 -04:00
|
|
|
* Acquires a wake lock.
|
|
|
|
*
|
2011-09-04 16:00:02 -04:00
|
|
|
* @param context
|
2011-10-28 23:00:37 -04:00
|
|
|
* A {@link Context} instance. Never {@code null}.
|
|
|
|
* @param tag
|
|
|
|
* The tag to supply to {@link TracingPowerManager}.
|
|
|
|
* @param timeout
|
|
|
|
* The wake lock timeout.
|
|
|
|
*
|
|
|
|
* @return A new {@link TracingWakeLock} instance.
|
2011-09-04 16:00:02 -04:00
|
|
|
*/
|
|
|
|
protected static TracingWakeLock acquireWakeLock(Context context, String tag, long timeout) {
|
|
|
|
TracingPowerManager pm = TracingPowerManager.getPowerManager(context);
|
|
|
|
TracingWakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, tag);
|
|
|
|
wakeLock.setReferenceCounted(false);
|
|
|
|
wakeLock.acquire(timeout);
|
|
|
|
return wakeLock;
|
|
|
|
}
|
2010-01-02 20:50:51 -05:00
|
|
|
|
2009-11-22 12:01:04 -05:00
|
|
|
@Override
|
2011-10-28 23:00:37 -04:00
|
|
|
public void onCreate() {
|
|
|
|
if (K9.DEBUG) {
|
|
|
|
Log.i(K9.LOG_TAG, "CoreService: " + className + ".onCreate()");
|
|
|
|
}
|
|
|
|
|
|
|
|
mThreadPool = Executors.newFixedThreadPool(1); // Must be single threaded
|
|
|
|
super.onCreate();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public final void onStart(Intent intent, int startId) {
|
2011-09-04 16:05:13 -04:00
|
|
|
// deprecated method but still used for backwards compatibility with Android version <2.0
|
2011-10-28 15:29:39 -04:00
|
|
|
|
2011-10-28 23:00:37 -04:00
|
|
|
// Acquire new wake lock
|
|
|
|
TracingWakeLock wakeLock = acquireWakeLock(this, "CoreService onStart",
|
|
|
|
K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT);
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2011-10-28 23:00:37 -04:00
|
|
|
if (K9.DEBUG) {
|
2010-04-19 23:22:43 -04:00
|
|
|
Log.i(K9.LOG_TAG, "CoreService: " + className + ".onStart(" + intent + ", " + startId);
|
2011-10-28 23:00:37 -04:00
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2011-10-28 23:00:37 -04:00
|
|
|
// If we were started by BootReceiver, release the wake lock acquired there.
|
2009-11-22 12:01:04 -05:00
|
|
|
int wakeLockId = intent.getIntExtra(BootReceiver.WAKE_LOCK_ID, -1);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (wakeLockId != -1) {
|
2009-11-22 12:01:04 -05:00
|
|
|
BootReceiver.releaseWakeLock(this, wakeLockId);
|
|
|
|
}
|
2011-10-28 23:00:37 -04:00
|
|
|
|
|
|
|
// If we were passed an ID from our own wake lock registry, retrieve that wake lock and
|
|
|
|
// release it.
|
|
|
|
int coreWakeLockId = intent.getIntExtra(WAKE_LOCK_ID, -1);
|
|
|
|
if (coreWakeLockId != -1) {
|
|
|
|
if (K9.DEBUG) {
|
2009-12-20 20:48:15 -05:00
|
|
|
Log.d(K9.LOG_TAG, "Got core wake lock id " + coreWakeLockId);
|
2011-10-28 23:00:37 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Remove wake lock from the registry
|
|
|
|
TracingWakeLock coreWakeLock = sWakeLocks.remove(coreWakeLockId);
|
|
|
|
|
|
|
|
// Release wake lock
|
2011-02-06 17:09:48 -05:00
|
|
|
if (coreWakeLock != null) {
|
2011-10-28 23:00:37 -04:00
|
|
|
if (K9.DEBUG) {
|
|
|
|
Log.d(K9.LOG_TAG, "Found core wake lock with id " + coreWakeLockId +
|
|
|
|
", releasing");
|
|
|
|
}
|
2009-12-20 20:48:15 -05:00
|
|
|
coreWakeLock.release();
|
|
|
|
}
|
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2011-09-04 16:05:13 -04:00
|
|
|
// Run the actual start-code of the service
|
2011-09-04 16:00:02 -04:00
|
|
|
mImmediateShutdown = true;
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
2009-11-22 12:01:04 -05:00
|
|
|
super.onStart(intent, startId);
|
|
|
|
startService(intent, startId);
|
2011-02-06 17:09:48 -05:00
|
|
|
} finally {
|
2011-10-28 23:00:37 -04:00
|
|
|
try {
|
|
|
|
// Release the wake lock acquired at the start of this method
|
|
|
|
wakeLock.release();
|
|
|
|
} catch (Exception e) { /* ignore */ }
|
|
|
|
|
|
|
|
try {
|
|
|
|
// If there is no outstanding work to be done in a background thread we can stop
|
|
|
|
// this service.
|
|
|
|
if (mAutoShutdown && mImmediateShutdown && startId != -1) {
|
|
|
|
stopSelf(startId);
|
|
|
|
}
|
|
|
|
} catch (Exception e) { /* ignore */ }
|
2009-11-22 12:01:04 -05:00
|
|
|
}
|
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2011-09-04 16:00:02 -04:00
|
|
|
/**
|
2011-10-28 23:00:37 -04:00
|
|
|
* Execute a task in the background thread.
|
2011-10-28 15:29:39 -04:00
|
|
|
*
|
2011-09-04 16:00:02 -04:00
|
|
|
* @param context
|
2011-10-28 23:00:37 -04:00
|
|
|
* A {@link Context} instance. Never {@code null}.
|
2011-09-04 16:00:02 -04:00
|
|
|
* @param runner
|
2011-10-28 23:00:37 -04:00
|
|
|
* The code to be executed in the background thread.
|
2011-09-04 16:00:02 -04:00
|
|
|
* @param wakeLockTime
|
2011-10-28 23:00:37 -04:00
|
|
|
* The timeout for the wake lock that will be acquired by this method.
|
2011-09-04 16:00:02 -04:00
|
|
|
* @param startId
|
2011-10-28 23:00:37 -04:00
|
|
|
* The {@code startId} value received in {@link #onStart(Intent, int)} or {@code null}
|
|
|
|
* if you don't want the service to be shut down after {@code runner} has been executed
|
|
|
|
* (e.g. because you need to run another background task).<br>
|
|
|
|
* If this parameter is {@code null} you need to call {@code setAutoShutdown(false)}
|
|
|
|
* otherwise the auto shutdown code will stop the service.
|
2011-09-04 16:00:02 -04:00
|
|
|
*/
|
2011-10-28 23:00:37 -04:00
|
|
|
public void execute(Context context, final Runnable runner, int wakeLockTime,
|
|
|
|
final Integer startId) {
|
2010-04-29 00:59:14 -04:00
|
|
|
|
2011-09-04 16:05:13 -04:00
|
|
|
boolean serviceShutdownScheduled = false;
|
2011-09-04 16:00:02 -04:00
|
|
|
final boolean autoShutdown = mAutoShutdown;
|
2010-04-29 00:59:14 -04:00
|
|
|
|
2011-10-28 23:00:37 -04:00
|
|
|
// Acquire a new wakelock
|
|
|
|
final TracingWakeLock wakeLock = acquireWakeLock(context, "CoreService execute",
|
|
|
|
wakeLockTime);
|
|
|
|
|
|
|
|
// Wrap the supplied runner with code to release the wake lock and stop the service if
|
|
|
|
// appropriate.
|
2011-02-06 17:09:48 -05:00
|
|
|
Runnable myRunner = new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
try {
|
2011-10-28 23:00:37 -04:00
|
|
|
// Get the sync status
|
2011-02-04 18:18:08 -05:00
|
|
|
boolean oldIsSyncDisabled = MailService.isSyncDisabled();
|
2011-10-28 23:00:37 -04:00
|
|
|
|
|
|
|
if (K9.DEBUG) {
|
|
|
|
Log.d(K9.LOG_TAG, "CoreService (" + className + ") running Runnable " +
|
|
|
|
runner.hashCode() + " with startId " + startId);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run the supplied code
|
2010-01-12 09:09:30 -05:00
|
|
|
runner.run();
|
2011-10-28 23:00:37 -04:00
|
|
|
|
|
|
|
// If the sync status changed while runner was executing, notify
|
|
|
|
// MessagingController
|
2011-02-06 17:09:48 -05:00
|
|
|
if (MailService.isSyncDisabled() != oldIsSyncDisabled) {
|
2011-02-04 18:18:08 -05:00
|
|
|
MessagingController.getInstance(getApplication()).systemStatusChanged();
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
} finally {
|
2011-10-28 23:00:37 -04:00
|
|
|
// Making absolutely sure stopSelf() will be called
|
|
|
|
try {
|
|
|
|
if (K9.DEBUG) {
|
|
|
|
Log.d(K9.LOG_TAG, "CoreService (" + className + ") completed " +
|
|
|
|
"Runnable " + runner.hashCode() + " with startId " + startId);
|
|
|
|
}
|
2011-09-04 16:00:02 -04:00
|
|
|
wakeLock.release();
|
|
|
|
} finally {
|
|
|
|
if (autoShutdown && startId != null) {
|
2011-10-28 23:00:37 -04:00
|
|
|
stopSelf(startId);
|
2011-09-04 16:00:02 -04:00
|
|
|
}
|
2010-01-12 09:09:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2011-10-28 23:00:37 -04:00
|
|
|
|
|
|
|
// TODO: remove this. we never set mThreadPool to null
|
|
|
|
if (mThreadPool == null) {
|
|
|
|
Log.e(K9.LOG_TAG, "CoreService.execute (" + className + ") called with no thread " +
|
|
|
|
"pool available; running Runnable " + runner.hashCode() +
|
|
|
|
" in calling thread");
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
synchronized (this) {
|
2010-04-19 23:22:43 -04:00
|
|
|
myRunner.run();
|
2011-10-28 23:00:37 -04:00
|
|
|
serviceShutdownScheduled = startId != null;
|
2010-04-19 23:22:43 -04:00
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
} else {
|
2011-10-28 23:00:37 -04:00
|
|
|
if (K9.DEBUG) {
|
|
|
|
Log.d(K9.LOG_TAG, "CoreService (" + className + ") queueing Runnable " +
|
|
|
|
runner.hashCode() + " with startId " + startId);
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
2011-10-28 23:00:37 -04:00
|
|
|
mThreadPool.execute(myRunner);
|
2011-09-04 16:05:13 -04:00
|
|
|
serviceShutdownScheduled = startId != null;
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (RejectedExecutionException e) {
|
2011-10-28 23:00:37 -04:00
|
|
|
// Ignore RejectedExecutionException after we shut down the thread pool in
|
|
|
|
// onDestroy(). Still, this should not happen!
|
2011-02-06 17:09:48 -05:00
|
|
|
if (!mShutdown) {
|
2010-10-29 15:55:04 -04:00
|
|
|
throw e;
|
|
|
|
}
|
2011-10-28 23:00:37 -04:00
|
|
|
|
|
|
|
Log.i(K9.LOG_TAG, "CoreService: " + className + " is shutting down, ignoring " +
|
|
|
|
"rejected execution exception: " + e.getMessage());
|
2010-10-29 15:55:04 -04:00
|
|
|
}
|
2010-04-19 23:22:43 -04:00
|
|
|
}
|
2011-10-28 23:00:37 -04:00
|
|
|
|
2011-10-28 15:29:39 -04:00
|
|
|
mImmediateShutdown = !serviceShutdownScheduled;
|
2010-01-12 09:09:30 -05:00
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2011-09-04 16:00:02 -04:00
|
|
|
/**
|
2011-10-28 23:00:37 -04:00
|
|
|
* Subclasses need to implement this instead of overriding {@link #onStart(Intent, int)}.
|
|
|
|
*
|
|
|
|
* <p>
|
|
|
|
* This allows {@link CoreService} to manage the service lifecycle, incl. wake lock management.
|
|
|
|
* </p>
|
|
|
|
|
2011-09-04 16:00:02 -04:00
|
|
|
* @param intent
|
2011-10-28 23:00:37 -04:00
|
|
|
* The Intent supplied to {@link Context#startService(Intent)}.
|
2011-09-04 16:00:02 -04:00
|
|
|
* @param startId
|
2011-10-28 23:00:37 -04:00
|
|
|
* A unique integer representing this specific request to start. Use with
|
|
|
|
* {@link #stopSelfResult(int)}.
|
2011-09-04 16:00:02 -04:00
|
|
|
*/
|
2009-11-22 12:01:04 -05:00
|
|
|
public abstract void startService(Intent intent, int startId);
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2010-10-29 15:55:04 -04:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public void onLowMemory() {
|
2010-10-29 15:55:04 -04:00
|
|
|
Log.w(K9.LOG_TAG, "CoreService: " + className + ".onLowMemory() - Running low on memory");
|
|
|
|
}
|
|
|
|
|
2011-10-28 23:00:37 -04:00
|
|
|
/**
|
|
|
|
* Clean up when the service is stopped.
|
|
|
|
*/
|
2009-11-22 12:01:04 -05:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public void onDestroy() {
|
2011-10-28 23:00:37 -04:00
|
|
|
if (K9.DEBUG) {
|
2010-04-19 23:22:43 -04:00
|
|
|
Log.i(K9.LOG_TAG, "CoreService: " + className + ".onDestroy()");
|
2011-10-28 23:00:37 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Shut down thread pool
|
2010-10-29 15:55:04 -04:00
|
|
|
mShutdown = true;
|
2011-10-28 23:00:37 -04:00
|
|
|
mThreadPool.shutdown();
|
|
|
|
|
2009-11-22 12:01:04 -05:00
|
|
|
super.onDestroy();
|
|
|
|
}
|
2011-09-04 16:00:02 -04:00
|
|
|
|
|
|
|
/**
|
2011-10-28 23:00:37 -04:00
|
|
|
* Return whether or not auto shutdown is enabled.
|
|
|
|
*
|
|
|
|
* @return {@code true} iff auto shutdown is enabled.
|
2011-09-04 16:00:02 -04:00
|
|
|
*/
|
|
|
|
protected boolean isAutoShutdown() {
|
|
|
|
return mAutoShutdown;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2011-10-28 23:00:37 -04:00
|
|
|
* Enable or disable auto shutdown (enabled by default).
|
|
|
|
*
|
2011-09-04 16:00:02 -04:00
|
|
|
* @param autoShutdown
|
2011-10-28 23:00:37 -04:00
|
|
|
* {@code true} to enable auto shutdown. {@code false} to disable.
|
|
|
|
*
|
|
|
|
* @see #mAutoShutdown
|
2011-09-04 16:00:02 -04:00
|
|
|
*/
|
|
|
|
protected void setAutoShutdown(boolean autoShutdown) {
|
|
|
|
mAutoShutdown = autoShutdown;
|
|
|
|
}
|
2011-10-28 23:00:37 -04:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public IBinder onBind(Intent intent) {
|
|
|
|
// Unused
|
|
|
|
return null;
|
|
|
|
}
|
2009-11-22 12:01:04 -05:00
|
|
|
}
|