/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.services.tasks;
import com.google.android.apps.mytracks.services.TrackRecordingService;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
import android.util.Log;
/**
* Execute a periodic task on a time or distance schedule.
*
* @author Sandor Dornbush
*/
public class PeriodicTaskExecutor {
private static final String TAG = PeriodicTaskExecutor.class.getSimpleName();
private static final long MINUTE_TO_MILLISECONDS = 60000L;
private final TrackRecordingService trackRecordingService;
private final PeriodicTaskFactory periodicTaskFactory;
/**
* The task frequency. A positive value is a time frequency (minutes). A
* negative value is a distance frequency (km or mi). A zero value is to turn
* off periodic task.
*/
private int taskFrequency = PreferencesUtils.FREQUENCY_OFF;
private PeriodicTask periodicTask;
// Time periodic task executor
private TimerTaskExecutor timerTaskExecutor = null;
private boolean metricUnits;
// The next distance for the distance periodic task
private double nextTaskDistance = Double.MAX_VALUE;
public PeriodicTaskExecutor(
TrackRecordingService trackRecordingService, PeriodicTaskFactory periodicTaskFactory) {
this.trackRecordingService = trackRecordingService;
this.periodicTaskFactory = periodicTaskFactory;
}
/**
* Restores the executor.
*/
public void restore() {
if (!trackRecordingService.isRecording() || trackRecordingService.isPaused()) {
Log.d(TAG, "Not recording or paused.");
return;
}
if (!isTimeFrequency()) {
if (timerTaskExecutor != null) {
timerTaskExecutor.shutdown();
timerTaskExecutor = null;
}
}
if (taskFrequency == PreferencesUtils.FREQUENCY_OFF) {
Log.d(TAG, "Task frequency is off.");
return;
}
periodicTask = periodicTaskFactory.create(trackRecordingService);
// Returning null is ok
if (periodicTask == null) {
Log.d(TAG, "Peridoic task is null.");
return;
}
periodicTask.start();
if (isTimeFrequency()) {
if (timerTaskExecutor == null) {
timerTaskExecutor = new TimerTaskExecutor(periodicTask, trackRecordingService);
}
timerTaskExecutor.scheduleTask(taskFrequency * MINUTE_TO_MILLISECONDS);
} else {
// For distance periodic task
calculateNextTaskDistance();
}
}
/**
* Shuts down the executor.
*/
public void shutdown() {
if (periodicTask != null) {
periodicTask.shutdown();
periodicTask = null;
}
if (timerTaskExecutor != null) {
timerTaskExecutor.shutdown();
timerTaskExecutor = null;
}
}
/**
* Updates the executor.
*/
public void update() {
if (!isDistanceFrequency() || periodicTask == null) {
return;
}
TripStatistics tripStatistics = trackRecordingService.getTripStatistics();
if (tripStatistics == null) {
return;
}
double distance = tripStatistics.getTotalDistance()
* UnitConversions.M_TO_KM;
if (!metricUnits) {
distance *= UnitConversions.KM_TO_MI;
}
if (distance > nextTaskDistance) {
periodicTask.run(trackRecordingService);
calculateNextTaskDistance();
}
}
/**
* Sets task frequency.
*
* @param taskFrequency the task frequency
*/
public void setTaskFrequency(int taskFrequency) {
this.taskFrequency = taskFrequency;
restore();
}
/**
* Sets metricUnits.
*
* @param metricUnits true to use metric units
*/
public void setMetricUnits(boolean metricUnits) {
this.metricUnits = metricUnits;
calculateNextTaskDistance();
}
/**
* Calculates the next distance for the distance periodic task.
*/
private void calculateNextTaskDistance() {
if (!trackRecordingService.isRecording() || trackRecordingService.isPaused()
|| periodicTask == null) {
return;
}
TripStatistics tripStatistics = trackRecordingService.getTripStatistics();
if (tripStatistics == null) {
return;
}
if (!isDistanceFrequency()) {
nextTaskDistance = Double.MAX_VALUE;
Log.d(TAG, "SplitManager: Distance splits disabled.");
return;
}
double distance = tripStatistics.getTotalDistance()
* UnitConversions.M_TO_KM;
if (!metricUnits) {
distance *= UnitConversions.KM_TO_MI;
}
// The index will be negative since the frequency is negative.
int index = (int) (distance / taskFrequency);
index -= 1;
nextTaskDistance = taskFrequency * index;
}
/**
* True if time frequency.
*/
private boolean isTimeFrequency() {
return taskFrequency > 0;
}
/**
* True if distance frequency.
*/
private boolean isDistanceFrequency() {
return taskFrequency < 0;
}
}