package org.microg.nlp.location; import android.annotation.SuppressLint; 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(); } } }