UnifiedNlp/src/org/microg/nlp/location/BackendHelper.java

128 lines
4 KiB
Java

package org.microg.nlp.location;
import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.*;
import android.util.Log;
import com.android.location.provider.LocationProviderBase;
import org.microg.nlp.AbstractBackendHelper;
import org.microg.nlp.api.LocationBackend;
import org.microg.nlp.api.LocationCallback;
import static org.microg.nlp.api.NlpApiConstants.LOCATION_EXTRA_BACKEND_COMPONENT;
import static org.microg.nlp.api.NlpApiConstants.LOCATION_EXTRA_BACKEND_PROVIDER;
class BackendHelper extends AbstractBackendHelper {
private static final String TAG = BackendHelper.class.getName();
private final BackendFuser backendFuser;
private final Callback callback = new Callback();
private LocationBackend backend;
private boolean updateWaiting;
private Location lastLocation;
public BackendHelper(Context context, BackendFuser backendFuser, Intent serviceIntent) {
super(TAG, context, serviceIntent);
this.backendFuser = backendFuser;
}
public Location getLastLocation() {
return lastLocation;
}
public Location update() {
if (backend == null) {
Log.d(TAG, "Not (yet) bound.");
updateWaiting = true;
} else {
updateWaiting = false;
try {
setLastLocation(backend.update());
backendFuser.reportLocation();
} catch (Exception e) {
Log.w(TAG, e);
unbind();
}
}
return lastLocation;
}
private Location setLastLocation(Location location) {
if (location == null) {
return lastLocation;
}
if (!location.hasAccuracy()) {
return lastLocation;
}
if (location.getExtras() == null) {
location.setExtras(new Bundle());
}
location.getExtras().putString(LOCATION_EXTRA_BACKEND_PROVIDER, location.getProvider());
location.getExtras().putString(LOCATION_EXTRA_BACKEND_COMPONENT,
serviceIntent.getComponent().flattenToShortString());
if (!location.hasAccuracy()) {
location.setAccuracy(50000);
}
if (location.getTime() <= 0) {
location.setTime(System.currentTimeMillis());
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
updateElapsedRealtimeNanos(location);
}
location.getExtras()
.putParcelable(LocationProviderBase.EXTRA_NO_GPS_LOCATION, new Location(location));
lastLocation = location;
return lastLocation;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private void updateElapsedRealtimeNanos(Location location) {
if (location.getElapsedRealtimeNanos() <= 0) {
location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
}
@Override
public void close() throws RemoteException {
backend.close();
}
@Override
public boolean hasBackend() {
return backend != null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
super.onServiceConnected(name, service);
backend = LocationBackend.Stub.asInterface(service);
if (backend != null) {
try {
backend.open(callback);
if (updateWaiting) {
update();
}
} catch (Exception e) {
Log.w(TAG, e);
unbind();
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
super.onServiceDisconnected(name);
backend = null;
}
private class Callback extends LocationCallback.Stub {
@Override
public void report(Location location) throws RemoteException {
setLastLocation(location);
backendFuser.reportLocation();
}
}
}