Skip to content

Commit

Permalink
Drop waking navigation service on alarm
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-osm committed Dec 8, 2020
1 parent 4acb398 commit 950a9cc
Show file tree
Hide file tree
Showing 8 changed files with 22 additions and 237 deletions.
1 change: 0 additions & 1 deletion OsmAnd/AndroidManifest.xml
Expand Up @@ -1053,7 +1053,6 @@
android:label="@string/process_downloading_service"
android:stopWithTask="false" />

<receiver android:name="net.osmand.plus.OnNavigationServiceAlarmReceiver" />
<receiver android:name="net.osmand.plus.notifications.NotificationDismissReceiver" />

<activity android:name="net.osmand.plus.activities.PrintDialogActivity" />
Expand Down
3 changes: 1 addition & 2 deletions OsmAnd/src/net/osmand/plus/AppInitializer.java
Expand Up @@ -760,8 +760,7 @@ private void saveGPXTracks() {
}
}
if(app.getSettings().SAVE_GLOBAL_TRACK_TO_GPX.get() && OsmandPlugin.getEnabledPlugin(OsmandMonitoringPlugin.class) != null){
int interval = app.getSettings().SAVE_GLOBAL_TRACK_INTERVAL.get();
app.startNavigationService(NavigationService.USED_BY_GPX, app.navigationServiceGpsInterval(interval));
app.startNavigationService(NavigationService.USED_BY_GPX);
}
}

Expand Down
163 changes: 12 additions & 151 deletions OsmAnd/src/net/osmand/plus/NavigationService.java
@@ -1,23 +1,15 @@
package net.osmand.plus;

import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;

Expand All @@ -28,26 +20,17 @@
public class NavigationService extends Service implements LocationListener {

public static class NavigationServiceBinder extends Binder {

}

// global id don't conflict with others
public static int USED_BY_NAVIGATION = 1;
public static int USED_BY_GPX = 2;
public final static String USAGE_INTENT = "SERVICE_USED_BY";
public final static String USAGE_OFF_INTERVAL = "SERVICE_OFF_INTERVAL";

private final NavigationServiceBinder binder = new NavigationServiceBinder();

private int serviceOffInterval;
private String serviceOffProvider;
private int serviceErrorTimeout;
private long nextManualWakeup;
private OsmandSettings settings;
private Handler handler;

private static WakeLock lockStatic;
private PendingIntent pendingIntent;

protected int usedBy = 0;
private OsmAndLocationProvider locationProvider;
Expand All @@ -57,26 +40,6 @@ public IBinder onBind(Intent intent) {
return binder;
}

protected synchronized static PowerManager.WakeLock getLock(Context context) {
if (lockStatic == null) {
PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "OsmAnd:NavigationServiceLock");
}
return lockStatic;
}

public long getNextManualWakeup() {
return nextManualWakeup;
}

public void setNextManualWakeup(long value) {
nextManualWakeup = value;
}

public int getServiceOffInterval() {
return serviceOffInterval;
}

public int getUsedBy() {
return usedBy;
}
Expand All @@ -97,71 +60,33 @@ public void stopIfNeeded(Context ctx, int usageIntent) {
final Intent serviceIntent = new Intent(ctx, NavigationService.class);
ctx.stopService(serviceIntent);
} else {
// Issue #3604
final OsmandApplication app = (OsmandApplication) getApplication();
if ((usedBy == USED_BY_GPX) && (app.navigationServiceGpsInterval(app.getSettings().SAVE_GLOBAL_TRACK_INTERVAL.get()) != 0) && (serviceOffInterval == 0)) {
serviceOffInterval = app.getSettings().SAVE_GLOBAL_TRACK_INTERVAL.get();
setupServiceErrorTimeout();
app.setNavigationService(this);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, OnNavigationServiceAlarmReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT);
nextManualWakeup = SystemClock.elapsedRealtime() + serviceOffInterval;
if (Build.VERSION.SDK_INT >= 23) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, pendingIntent);
} else if (Build.VERSION.SDK_INT >= 19) {
// setRepeating() became inexact starting with SDK 19
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, pendingIntent);
} else {
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, serviceOffInterval, pendingIntent);
}
}
app.getNotificationHelper().updateTopNotification();
app.getNotificationHelper().refreshNotifications();
}
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
handler = new Handler();
final OsmandApplication app = (OsmandApplication) getApplication();
settings = app.getSettings();
usedBy = intent.getIntExtra(USAGE_INTENT, 0);
serviceOffInterval = intent.getIntExtra(USAGE_OFF_INTERVAL, 0);
if ((usedBy & USED_BY_NAVIGATION) != 0) {
serviceOffInterval = 0;
}

// use only gps provider
serviceOffProvider = LocationManager.GPS_PROVIDER;
setupServiceErrorTimeout();

locationProvider = app.getLocationProvider();
app.setNavigationService(this);

// requesting
if (isContinuous()) {
// request location updates
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
try {
locationManager.requestLocationUpdates(serviceOffProvider, 0, 0, NavigationService.this);
} catch (SecurityException e) {
Toast.makeText(this, R.string.no_location_permission, Toast.LENGTH_LONG).show();
Log.d(PlatformUtil.TAG, "Location service permission not granted"); //$NON-NLS-1$
} catch (IllegalArgumentException e) {
Toast.makeText(this, R.string.gps_not_available, Toast.LENGTH_LONG).show();
Log.d(PlatformUtil.TAG, "GPS location provider not available"); //$NON-NLS-1$
}
} else {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, OnNavigationServiceAlarmReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT);
nextManualWakeup = SystemClock.elapsedRealtime() + serviceOffInterval;
if (Build.VERSION.SDK_INT >= 23) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, pendingIntent);
} else if (Build.VERSION.SDK_INT >= 19) {
// setRepeating() became inexact starting with SDK 19
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, pendingIntent);
} else {
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, serviceOffInterval, pendingIntent);
}
// request location updates
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
try {
locationManager.requestLocationUpdates(serviceOffProvider, 0, 0, NavigationService.this);
} catch (SecurityException e) {
Toast.makeText(this, R.string.no_location_permission, Toast.LENGTH_LONG).show();
Log.d(PlatformUtil.TAG, "Location service permission not granted"); //$NON-NLS-1$
} catch (IllegalArgumentException e) {
Toast.makeText(this, R.string.gps_not_available, Toast.LENGTH_LONG).show();
Log.d(PlatformUtil.TAG, "GPS location provider not available"); //$NON-NLS-1$
}

// registering icon at top level
Expand All @@ -185,20 +110,6 @@ public void onCreate() {
// initializing variables
}

private boolean isContinuous() {
return serviceOffInterval == 0;
}

private void setupServiceErrorTimeout() {
serviceErrorTimeout = serviceOffInterval / 5;
// 1. not more than 12 mins
serviceErrorTimeout = Math.min(serviceErrorTimeout, 12 * 60 * 1000);
// 2. not less than 30 seconds
serviceErrorTimeout = Math.max(serviceErrorTimeout, 30 * 1000);
// 3. not more than serviceOffInterval
serviceErrorTimeout = Math.min(serviceErrorTimeout, serviceOffInterval);
}

@Override
public void onDestroy() {
super.onDestroy();
Expand All @@ -212,20 +123,6 @@ public void onDestroy() {
} catch (SecurityException e) {
Log.d(PlatformUtil.TAG, "Location service permission not granted"); //$NON-NLS-1$
}

if (!isContinuous()) {
WakeLock lock = getLock(this);
if (lock.isHeld()) {
lock.release();
}
}

if (pendingIntent != null) {
// remove alarm
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
}

// remove notification
stopForeground(Boolean.TRUE);
app.getNotificationHelper().updateTopNotification();
Expand All @@ -237,47 +134,11 @@ public void run() {
}, 500);
}

@SuppressLint("MissingPermission")
public void onWakeUp() {
// request location updates
final LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
try {
locationManager.requestLocationUpdates(serviceOffProvider, 0, 0, this);
if (serviceOffInterval > serviceErrorTimeout) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
WakeLock lock = getLock(NavigationService.this);
if (lock.isHeld()) {
lock.release();
locationManager.removeUpdates(NavigationService.this);
}
}
}, serviceErrorTimeout);
}
} catch (RuntimeException e) {
// ignore
}
}

@Override
public void onLocationChanged(Location l) {
if (l != null && !settings.MAP_ACTIVITY_ENABLED.get()) {
net.osmand.Location location = OsmAndLocationProvider.convertLocation(l, (OsmandApplication) getApplication());
if (!isContinuous()) {
// unregister listener and wait next time
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
try {
locationManager.removeUpdates(this);
} catch (SecurityException e) {
Log.d(PlatformUtil.TAG, "Location service permission not granted"); //$NON-NLS-1$
}
WakeLock lock = getLock(this);
if (lock.isHeld()) {
lock.release();
}
}
locationProvider.setLocationFromService(location, isContinuous());
locationProvider.setLocationFromService(location);
}
}

Expand Down
51 changes: 0 additions & 51 deletions OsmAnd/src/net/osmand/plus/OnNavigationServiceAlarmReceiver.java

This file was deleted.

12 changes: 5 additions & 7 deletions OsmAnd/src/net/osmand/plus/OsmAndLocationProvider.java
Expand Up @@ -791,19 +791,17 @@ private void simulatePositionImpl() {
}
}
}


public void setLocationFromService(net.osmand.Location location, boolean continuous) {

public void setLocationFromService(net.osmand.Location location) {
if (locationSimulation.isRouteAnimating()) {
return;
}
if (location != null) {
notifyGpsLocationRecovered();
}
// if continuous notify about lost location
if (continuous) {
scheduleCheckIfGpsLost(location);
}
// notify about lost location
scheduleCheckIfGpsLost(location);

app.getSavingTrackHelper().updateLocation(location, heading);
OsmandPlugin.updateLocationPlugins(location);
app.getRoutingHelper().updateLocation(location);
Expand Down
22 changes: 1 addition & 21 deletions OsmAnd/src/net/osmand/plus/OsmandApplication.java
Expand Up @@ -945,34 +945,14 @@ public int getVersionCode() {
}
}


public int navigationServiceGpsInterval(int interval) {
// Issue 5632 Workaround: Keep GPS always on instead of using AlarmManager, as API>=19 restricts repeated AlarmManager reception
// Maybe do not apply to API=19 devices, many still behave acceptably (often restriction not worse than 1/min)
if ((Build.VERSION.SDK_INT > 19) && (getSettings().SAVE_GLOBAL_TRACK_INTERVAL.get() < 5 * 60000)) {
return 0;
}
// Default: Save battery power by turning off GPS between measurements
if (interval >= 30000) {
return interval;
// GPS continuous
} else {
return 0;
}
}


public void startNavigationService(int intent, int interval) {
public void startNavigationService(int intent) {
final Intent serviceIntent = new Intent(this, NavigationService.class);

if (getNavigationService() != null) {
intent |= getNavigationService().getUsedBy();
interval = Math.min(getNavigationService().getServiceOffInterval(), interval);
getNavigationService().stopSelf();

}
serviceIntent.putExtra(NavigationService.USAGE_INTENT, intent);
serviceIntent.putExtra(NavigationService.USAGE_OFF_INTERVAL, interval);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent);
} else {
Expand Down
Expand Up @@ -500,8 +500,7 @@ public void run() {
settings.SAVE_GLOBAL_TRACK_INTERVAL.set(vs.value);
settings.SAVE_GLOBAL_TRACK_TO_GPX.set(true);
settings.SAVE_GLOBAL_TRACK_REMEMBER.set(choice.value);
int interval = settings.SAVE_GLOBAL_TRACK_INTERVAL.get();
app.startNavigationService(NavigationService.USED_BY_GPX, app.navigationServiceGpsInterval(interval));
app.startNavigationService(NavigationService.USED_BY_GPX);
}
};
if (choice.value || map == null) {
Expand Down

0 comments on commit 950a9cc

Please sign in to comment.