Fields Summary |
---|
private static final String | TAG |
private static final String | NETWORK |
private static final String | GPS |
private static final String | FUSED |
public static final long | SWITCH_ON_FRESHNESS_CLIFF_NS |
private final android.content.Context | mContext |
private final android.location.LocationManager | mLocationManager |
private final android.os.Looper | mLooper |
private Callback | mCallback |
private android.location.Location | mFusedLocation |
private android.location.Location | mGpsLocation |
private android.location.Location | mNetworkLocation |
private boolean | mEnabled |
private com.android.location.provider.ProviderRequestUnbundled | mRequest |
private final HashMap | mStats |
Methods Summary |
---|
public void | deinit()Called to stop doing any work, and release all resources
This can happen when a better fusion engine is installed
in a different package, and this one is no longer needed.
Called on mLooper thread
mRequest = null;
disable();
Log.i(TAG, "engine stopped (" + mContext.getPackageName() + ")");
|
public void | disable()Called on mLooper thread
mEnabled = false;
updateRequirements();
|
private void | disableProvider(java.lang.String name)
ProviderStats stats = mStats.get(name);
if (stats.requested) {
stats.requested = false;
mLocationManager.removeUpdates(this); //TODO GLOBAL
}
|
public void | dump(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.lang.String[] args)
StringBuilder s = new StringBuilder();
s.append("mEnabled=" + mEnabled).append(' ").append(mRequest).append('\n");
s.append("fused=").append(mFusedLocation).append('\n");
s.append(String.format("gps %s\n", mGpsLocation));
s.append(" ").append(mStats.get(GPS)).append('\n");
s.append(String.format("net %s\n", mNetworkLocation));
s.append(" ").append(mStats.get(NETWORK)).append('\n");
pw.append(s);
|
public void | enable()Called on mLooper thread
mEnabled = true;
updateRequirements();
|
private void | enableProvider(java.lang.String name, long minTime)
ProviderStats stats = mStats.get(name);
if (stats.available) {
if (!stats.requested) {
stats.requestTime = SystemClock.elapsedRealtime();
stats.requested = true;
stats.minTime = minTime;
mLocationManager.requestLocationUpdates(name, minTime, 0, this, mLooper);
} else if (stats.minTime != minTime) {
stats.minTime = minTime;
mLocationManager.requestLocationUpdates(name, minTime, 0, this, mLooper);
}
}
|
public void | init(com.android.location.fused.FusionEngine$Callback callback)
Log.i(TAG, "engine started (" + mContext.getPackageName() + ")");
mCallback = callback;
|
private static boolean | isBetterThan(android.location.Location locationA, android.location.Location locationB)Test whether one location (a) is better to use than another (b).
if (locationA == null) {
return false;
}
if (locationB == null) {
return true;
}
// A provider is better if the reading is sufficiently newer. Heading
// underground can cause GPS to stop reporting fixes. In this case it's
// appropriate to revert to cell, even when its accuracy is less.
if (locationA.getElapsedRealtimeNanos() > locationB.getElapsedRealtimeNanos() + SWITCH_ON_FRESHNESS_CLIFF_NS) {
return true;
}
// A provider is better if it has better accuracy. Assuming both readings
// are fresh (and by that accurate), choose the one with the smaller
// accuracy circle.
if (!locationA.hasAccuracy()) {
return false;
}
if (!locationB.hasAccuracy()) {
return true;
}
return locationA.getAccuracy() < locationB.getAccuracy();
|
public void | onLocationChanged(android.location.Location location)Called on mLooper thread
if (GPS.equals(location.getProvider())) {
mGpsLocation = location;
updateFusedLocation();
} else if (NETWORK.equals(location.getProvider())) {
mNetworkLocation = location;
updateFusedLocation();
}
|
public void | onProviderDisabled(java.lang.String provider)Called on mLooper thread
ProviderStats stats = mStats.get(provider);
if (stats == null) return;
stats.available = false;
|
public void | onProviderEnabled(java.lang.String provider)Called on mLooper thread
ProviderStats stats = mStats.get(provider);
if (stats == null) return;
stats.available = true;
|
public void | onStatusChanged(java.lang.String provider, int status, android.os.Bundle extras)Called on mLooper thread
|
public void | setRequest(com.android.location.provider.ProviderRequestUnbundled request, android.os.WorkSource source)Called on mLooper thread
mRequest = request;
mEnabled = request.getReportLocation();
updateRequirements();
|
public void | switchUser()Called on mLooper thread
// reset state to prevent location data leakage
mFusedLocation = null;
mGpsLocation = null;
mNetworkLocation = null;
|
private void | updateFusedLocation()
// may the best location win!
if (isBetterThan(mGpsLocation, mNetworkLocation)) {
mFusedLocation = new Location(mGpsLocation);
} else {
mFusedLocation = new Location(mNetworkLocation);
}
mFusedLocation.setProvider(FUSED);
if (mNetworkLocation != null) {
// copy NO_GPS_LOCATION extra from mNetworkLocation into mFusedLocation
Bundle srcExtras = mNetworkLocation.getExtras();
if (srcExtras != null) {
Parcelable srcParcelable =
srcExtras.getParcelable(LocationProviderBase.EXTRA_NO_GPS_LOCATION);
if (srcParcelable instanceof Location) {
Bundle dstExtras = mFusedLocation.getExtras();
if (dstExtras == null) {
dstExtras = new Bundle();
mFusedLocation.setExtras(dstExtras);
}
dstExtras.putParcelable(LocationProviderBase.EXTRA_NO_GPS_LOCATION,
(Location) srcParcelable);
}
}
}
if (mCallback != null) {
mCallback.reportLocation(mFusedLocation);
} else {
Log.w(TAG, "Location updates received while fusion engine not started");
}
|
private void | updateRequirements()
if (mEnabled == false || mRequest == null) {
mRequest = null;
disableProvider(NETWORK);
disableProvider(GPS);
return;
}
long networkInterval = Long.MAX_VALUE;
long gpsInterval = Long.MAX_VALUE;
for (LocationRequestUnbundled request : mRequest.getLocationRequests()) {
switch (request.getQuality()) {
case LocationRequestUnbundled.ACCURACY_FINE:
case LocationRequestUnbundled.POWER_HIGH:
if (request.getInterval() < gpsInterval) {
gpsInterval = request.getInterval();
}
if (request.getInterval() < networkInterval) {
networkInterval = request.getInterval();
}
break;
case LocationRequestUnbundled.ACCURACY_BLOCK:
case LocationRequestUnbundled.ACCURACY_CITY:
case LocationRequestUnbundled.POWER_LOW:
if (request.getInterval() < networkInterval) {
networkInterval = request.getInterval();
}
break;
}
}
if (gpsInterval < Long.MAX_VALUE) {
enableProvider(GPS, gpsInterval);
} else {
disableProvider(GPS);
}
if (networkInterval < Long.MAX_VALUE) {
enableProvider(NETWORK, networkInterval);
} else {
disableProvider(NETWORK);
}
|