/** Copyright 2015 Tim Engler, Rareventure LLC This file is part of Tiny Travel Tracker. Tiny Travel Tracker is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Tiny Travel Tracker is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Tiny Travel Tracker. If not, see <http://www.gnu.org/licenses/>. */ package com.rareventure.android; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; import java.util.Date; import com.rareventure.gps2.GTG; import com.rareventure.gps2.R; import android.annotation.TargetApi; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.SystemClock; import android.util.Log; /** * A timer that will continue to work even if the phone sleeps * It has two modes, one will allow the phone to sleep, and the other will keep it awake * (but leave the screen off) */ public class IntentTimer { private PendingIntent sender; private AlarmManager alarmManager; private WakeLock wakeLock; private BufferedWriter debugOut; /** * * @param componentClass class type can either be a BroadcastReceiver, a Service, or an Activity */ public IntentTimer(Context context, Class<?> componentClass) { Intent intent = new Intent(context, componentClass); sender = PendingIntent.getBroadcast(context, 0, intent, 0); alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK , "rareventure intent timer"); if(GTG.prefs.writeGpsWakeLockDebug) { try { debugOut = new BufferedWriter(new FileWriter(context.getString(R.string.gps_wake_lock_filename), true)); writeDebug("IntentTimer constructor"); } catch (IOException e) { Log.e(GTG.TAG, "Couldn't out wake lock debug file", e); } } } /** * This will turn off the wake lock and allow the phone to sleep (if it wants) * It will send an alert to the component class and it is then up to the component * class to decide what to do. The wakeLock will still be released when we wake * up. * * @param timeToWakeFromPhoneBoot time to wake, *this is in millis since the phone was started* */ public synchronized void sleepUntil(long timeToWakeFromPhoneBoot) { writeDebug("sleep until "+new Date(System.currentTimeMillis() + timeToWakeFromPhoneBoot - SystemClock.elapsedRealtime())); if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) SetAlarmMarshmallow.setAlarm(alarmManager,AlarmManager.ELAPSED_REALTIME_WAKEUP, timeToWakeFromPhoneBoot, sender); else alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, timeToWakeFromPhoneBoot, sender); if(wakeLock.isHeld()) { writeDebug("releasing wake lock for sleep"); wakeLock.release(); } } @TargetApi(Build.VERSION_CODES.M) private static class SetAlarmMarshmallow { public static void setAlarm(AlarmManager alarmManager, int elapsedRealtimeWakeup, long timeToWakeFromPhoneBoot, PendingIntent sender) { alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, timeToWakeFromPhoneBoot, sender); } } public synchronized void cancel() { writeDebug("cancel"); alarmManager.cancel(sender); } /** * Acquire a lock on the cpu to stay awake */ public synchronized void acquireWakeLock() { if(!wakeLock.isHeld()) { writeDebug("acquiring wake lock"); wakeLock.acquire(); writeDebug("acquired wake lock"); } // else // writeDebug("acquireWakeLock() wake lock already held"); } public synchronized void releaseWakeLock() { if(wakeLock.isHeld()) { writeDebug("releasing wake lock"); wakeLock.release(); writeDebug("released wake lock"); } // else // writeDebug("releaseWakeLock(), wake lock already released"); } public synchronized void writeDebug(String string) { if(GTG.prefs.writeGpsWakeLockDebug && debugOut != null) try { /* ttt_installer:remove_line */Log.i("IntentTimer", string); debugOut.write(new Date().toString()+" "); debugOut.write(string); debugOut.write("\n"); debugOut.flush(); } catch (IOException e) { Log.e(GTG.TAG, "Couldn't write to wake lock debug file",e); } Log.d(GTG.TAG,string); } }