2009-12-14 21:50:53 -05:00
|
|
|
package com.fsck.k9.service;
|
2009-11-22 12:01:04 -05:00
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.util.Log;
|
2009-12-14 21:50:53 -05:00
|
|
|
import com.fsck.k9.K9;
|
2010-05-16 20:30:32 -04:00
|
|
|
import com.fsck.k9.helper.power.TracingPowerManager.TracingWakeLock;
|
2009-11-22 12:01:04 -05:00
|
|
|
|
2009-12-09 22:16:42 -05:00
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
import java.util.concurrent.CountDownLatch;
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
2009-11-22 12:01:04 -05:00
|
|
|
public class SleepService extends CoreService
|
|
|
|
{
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2009-12-14 21:50:53 -05:00
|
|
|
private static String ALARM_FIRED = "com.fsck.k9.service.SleepService.ALARM_FIRED";
|
|
|
|
private static String LATCH_ID = "com.fsck.k9.service.SleepService.LATCH_ID_EXTRA";
|
2009-11-24 19:40:29 -05:00
|
|
|
|
|
|
|
|
2009-11-22 12:01:04 -05:00
|
|
|
private static ConcurrentHashMap<Integer, SleepDatum> sleepData = new ConcurrentHashMap<Integer, SleepDatum>();
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2009-11-22 12:01:04 -05:00
|
|
|
private static AtomicInteger latchId = new AtomicInteger();
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2010-05-16 20:30:32 -04:00
|
|
|
public static void sleep(Context context, long sleepTime, TracingWakeLock wakeLock, long wakeLockTimeout)
|
2009-11-22 12:01:04 -05:00
|
|
|
{
|
|
|
|
Integer id = latchId.getAndIncrement();
|
2009-12-14 21:50:53 -05:00
|
|
|
if (K9.DEBUG)
|
|
|
|
Log.d(K9.LOG_TAG, "SleepService Preparing CountDownLatch with id = " + id + ", thread " + Thread.currentThread().getName());
|
2009-11-22 12:01:04 -05:00
|
|
|
SleepDatum sleepDatum = new SleepDatum();
|
|
|
|
CountDownLatch latch = new CountDownLatch(1);
|
|
|
|
sleepDatum.latch = latch;
|
2010-05-22 13:35:05 -04:00
|
|
|
sleepDatum.reacquireLatch = new CountDownLatch(1);
|
2009-11-22 12:01:04 -05:00
|
|
|
sleepData.put(id, sleepDatum);
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2009-11-22 12:01:04 -05:00
|
|
|
Intent i = new Intent();
|
2009-12-14 21:50:53 -05:00
|
|
|
i.setClassName(context.getPackageName(), "com.fsck.k9.service.SleepService");
|
2009-11-22 12:01:04 -05:00
|
|
|
i.putExtra(LATCH_ID, id);
|
|
|
|
i.setAction(ALARM_FIRED + "." + id);
|
|
|
|
long startTime = System.currentTimeMillis();
|
|
|
|
long nextTime = startTime + sleepTime;
|
|
|
|
BootReceiver.scheduleIntent(context, nextTime, i);
|
|
|
|
if (wakeLock != null)
|
|
|
|
{
|
|
|
|
sleepDatum.wakeLock = wakeLock;
|
|
|
|
sleepDatum.timeout = wakeLockTimeout;
|
|
|
|
wakeLock.release();
|
|
|
|
}
|
|
|
|
try
|
|
|
|
{
|
2010-05-16 20:30:32 -04:00
|
|
|
boolean countedDown = latch.await(sleepTime, TimeUnit.MILLISECONDS);
|
2010-08-29 19:39:26 -04:00
|
|
|
if (!countedDown)
|
2009-11-22 12:01:04 -05:00
|
|
|
{
|
2009-12-14 21:50:53 -05:00
|
|
|
if (K9.DEBUG)
|
|
|
|
Log.d(K9.LOG_TAG, "SleepService latch timed out for id = " + id + ", thread " + Thread.currentThread().getName());
|
2010-05-22 13:35:05 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (InterruptedException ie)
|
|
|
|
{
|
|
|
|
Log.e(K9.LOG_TAG, "SleepService Interrupted while awaiting latch", ie);
|
|
|
|
}
|
|
|
|
SleepDatum releaseDatum = sleepData.remove(id);
|
|
|
|
if (releaseDatum == null)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (K9.DEBUG)
|
|
|
|
Log.d(K9.LOG_TAG, "SleepService waiting for reacquireLatch for id = " + id + ", thread " + Thread.currentThread().getName());
|
2010-08-29 19:39:26 -04:00
|
|
|
if (!sleepDatum.reacquireLatch.await(5000, TimeUnit.MILLISECONDS))
|
2009-11-22 12:01:04 -05:00
|
|
|
{
|
2010-05-22 13:35:05 -04:00
|
|
|
Log.w(K9.LOG_TAG, "SleepService reacquireLatch timed out for id = " + id + ", thread " + Thread.currentThread().getName());
|
2009-11-22 12:01:04 -05:00
|
|
|
}
|
2010-05-22 13:35:05 -04:00
|
|
|
else if (K9.DEBUG)
|
|
|
|
Log.d(K9.LOG_TAG, "SleepService reacquireLatch finished for id = " + id + ", thread " + Thread.currentThread().getName());
|
|
|
|
}
|
|
|
|
catch (InterruptedException ie)
|
|
|
|
{
|
|
|
|
Log.e(K9.LOG_TAG, "SleepService Interrupted while awaiting reacquireLatch", ie);
|
2009-11-22 12:01:04 -05:00
|
|
|
}
|
|
|
|
}
|
2010-05-22 13:35:05 -04:00
|
|
|
else
|
2009-11-22 12:01:04 -05:00
|
|
|
{
|
2010-05-22 13:35:05 -04:00
|
|
|
reacquireWakeLock(releaseDatum);
|
2009-11-22 12:01:04 -05:00
|
|
|
}
|
2010-05-30 00:17:00 -04:00
|
|
|
|
2009-11-22 12:01:04 -05:00
|
|
|
long endTime = System.currentTimeMillis();
|
|
|
|
long actualSleep = endTime - startTime;
|
2010-05-30 00:17:00 -04:00
|
|
|
|
2009-11-22 12:01:04 -05:00
|
|
|
if (actualSleep < sleepTime)
|
|
|
|
{
|
2009-12-14 21:50:53 -05:00
|
|
|
Log.w(K9.LOG_TAG, "SleepService sleep time too short: requested was " + sleepTime + ", actual was " + actualSleep);
|
2009-11-22 12:01:04 -05:00
|
|
|
}
|
2010-05-22 13:35:05 -04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (K9.DEBUG)
|
2010-05-30 00:17:00 -04:00
|
|
|
Log.d(K9.LOG_TAG, "SleepService requested sleep time was " + sleepTime + ", actual was " + actualSleep);
|
2010-05-22 13:35:05 -04:00
|
|
|
}
|
2009-11-22 12:01:04 -05:00
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2009-11-22 12:01:04 -05:00
|
|
|
private static void endSleep(Integer id)
|
|
|
|
{
|
|
|
|
if (id != -1)
|
|
|
|
{
|
|
|
|
SleepDatum sleepDatum = sleepData.remove(id);
|
|
|
|
if (sleepDatum != null)
|
|
|
|
{
|
|
|
|
CountDownLatch latch = sleepDatum.latch;
|
|
|
|
if (latch == null)
|
|
|
|
{
|
2009-12-14 21:50:53 -05:00
|
|
|
Log.e(K9.LOG_TAG, "SleepService No CountDownLatch available with id = " + id);
|
2009-11-22 12:01:04 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-12-14 21:50:53 -05:00
|
|
|
if (K9.DEBUG)
|
|
|
|
Log.d(K9.LOG_TAG, "SleepService Counting down CountDownLatch with id = " + id);
|
2009-11-22 12:01:04 -05:00
|
|
|
latch.countDown();
|
|
|
|
}
|
|
|
|
reacquireWakeLock(sleepDatum);
|
2010-05-22 13:35:05 -04:00
|
|
|
sleepDatum.reacquireLatch.countDown();
|
2009-11-22 12:01:04 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-12-14 21:50:53 -05:00
|
|
|
if (K9.DEBUG)
|
|
|
|
Log.d(K9.LOG_TAG, "SleepService Sleep for id " + id + " already finished");
|
2009-11-22 12:01:04 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2009-11-22 12:01:04 -05:00
|
|
|
private static void reacquireWakeLock(SleepDatum sleepDatum)
|
|
|
|
{
|
2010-05-16 20:30:32 -04:00
|
|
|
TracingWakeLock wakeLock = sleepDatum.wakeLock;
|
2009-11-22 12:01:04 -05:00
|
|
|
if (wakeLock != null)
|
|
|
|
{
|
2009-11-24 19:40:29 -05:00
|
|
|
synchronized (wakeLock)
|
2009-11-22 12:01:04 -05:00
|
|
|
{
|
|
|
|
long timeout = sleepDatum.timeout;
|
2009-12-14 21:50:53 -05:00
|
|
|
if (K9.DEBUG)
|
2010-04-14 23:17:25 -04:00
|
|
|
Log.d(K9.LOG_TAG, "SleepService Acquiring wakeLock for " + timeout + "ms");
|
2009-11-22 12:01:04 -05:00
|
|
|
wakeLock.acquire(timeout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void startService(Intent intent, int startId)
|
|
|
|
{
|
2009-11-24 19:40:29 -05:00
|
|
|
if (intent.getAction().startsWith(ALARM_FIRED))
|
|
|
|
{
|
2009-11-22 12:01:04 -05:00
|
|
|
Integer id = intent.getIntExtra(LATCH_ID, -1);
|
|
|
|
endSleep(id);
|
|
|
|
}
|
|
|
|
stopSelf(startId);
|
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2009-11-22 12:01:04 -05:00
|
|
|
private static class SleepDatum
|
|
|
|
{
|
|
|
|
CountDownLatch latch;
|
2010-05-16 20:30:32 -04:00
|
|
|
TracingWakeLock wakeLock;
|
2009-11-22 12:01:04 -05:00
|
|
|
long timeout;
|
2010-05-22 13:35:05 -04:00
|
|
|
CountDownLatch reacquireLatch;
|
2009-11-22 12:01:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|