16fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly/* 26fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * Copyright (C) 2012 The Android Open Source Project 36fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * 46fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License"); 56fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * you may not use this file except in compliance with the License. 66fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * You may obtain a copy of the License at 76fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * 86fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * http://www.apache.org/licenses/LICENSE-2.0 96fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * 106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * Unless required by applicable law or agreed to in writing, software 116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS, 126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * See the License for the specific language governing permissions and 146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * limitations under the License. 156fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly */ 166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 176fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellypackage com.android.location.fused; 186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport java.io.FileDescriptor; 206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport java.io.PrintWriter; 216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport java.util.HashMap; 226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 23779b77455fc51382ecafa210b8a805d2a616da55Victoria Leaseimport com.android.location.provider.LocationProviderBase; 247ab7f538924371a9dd4be7a27a6ae3b4c04b301cLaurent Tuimport com.android.location.provider.LocationRequestUnbundled; 256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport com.android.location.provider.ProviderRequestUnbundled; 266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.content.Context; 286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.location.Location; 296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.location.LocationListener; 306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.location.LocationManager; 316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.os.Bundle; 326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.os.Looper; 33779b77455fc51382ecafa210b8a805d2a616da55Victoria Leaseimport android.os.Parcelable; 346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.os.SystemClock; 356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.os.WorkSource; 366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.util.Log; 376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellypublic class FusionEngine implements LocationListener { 396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public interface Callback { 406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public void reportLocation(Location location); 416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private static final String TAG = "FusedLocation"; 446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private static final String NETWORK = LocationManager.NETWORK_PROVIDER; 456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private static final String GPS = LocationManager.GPS_PROVIDER; 46779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease private static final String FUSED = LocationProviderBase.FUSED_PROVIDER; 476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 480fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease public static final long SWITCH_ON_FRESHNESS_CLIFF_NS = 11 * 1000000000; // 11 seconds 496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private final Context mContext; 516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private final LocationManager mLocationManager; 526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private final Looper mLooper; 536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly // all fields are only used on mLooper thread. except for in dump() which is not thread-safe 556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private Callback mCallback; 566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private Location mFusedLocation; 576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private Location mGpsLocation; 586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private Location mNetworkLocation; 596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private boolean mEnabled; 616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private ProviderRequestUnbundled mRequest; 626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private final HashMap<String, ProviderStats> mStats = new HashMap<String, ProviderStats>(); 646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public FusionEngine(Context context, Looper looper) { 666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mContext = context; 676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); 686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mNetworkLocation = new Location(""); 696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mNetworkLocation.setAccuracy(Float.MAX_VALUE); 706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mGpsLocation = new Location(""); 716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mGpsLocation.setAccuracy(Float.MAX_VALUE); 726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mLooper = looper; 736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mStats.put(GPS, new ProviderStats()); 756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mStats.get(GPS).available = mLocationManager.isProviderEnabled(GPS); 766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mStats.put(NETWORK, new ProviderStats()); 776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mStats.get(NETWORK).available = mLocationManager.isProviderEnabled(NETWORK); 78779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease 796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public void init(Callback callback) { 826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly Log.i(TAG, "engine started (" + mContext.getPackageName() + ")"); 836fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mCallback = callback; 846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly /** 876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * Called to stop doing any work, and release all resources 886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * This can happen when a better fusion engine is installed 896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * in a different package, and this one is no longer needed. 906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * Called on mLooper thread 916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly */ 926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public void deinit() { 936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mRequest = null; 946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly disable(); 956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly Log.i(TAG, "engine stopped (" + mContext.getPackageName() + ")"); 966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly /** Called on mLooper thread */ 996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public void enable() { 1006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mEnabled = true; 1016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly updateRequirements(); 1026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly /** Called on mLooper thread */ 1056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public void disable() { 1066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mEnabled = false; 1076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly updateRequirements(); 1086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly /** Called on mLooper thread */ 11108ca1046fe4f1890f91241f8d082a024ef6cfd93Nick Pelly public void setRequest(ProviderRequestUnbundled request, WorkSource source) { 1126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mRequest = request; 11308ca1046fe4f1890f91241f8d082a024ef6cfd93Nick Pelly mEnabled = request.getReportLocation(); 1146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly updateRequirements(); 1156fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1176fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private static class ProviderStats { 1186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public boolean available; 1196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public boolean requested; 1206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public long requestTime; 1216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public long minTime; 1226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly @Override 1236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public String toString() { 1246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly StringBuilder s = new StringBuilder(); 1256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly s.append(available ? "AVAILABLE" : "UNAVAILABLE"); 1266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly s.append(requested ? " REQUESTED" : " ---"); 1276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return s.toString(); 1286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private void enableProvider(String name, long minTime) { 1326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly ProviderStats stats = mStats.get(name); 1336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 134b30f38383e4691bf23311f62649aa504832731dbVictoria Lease if (stats.available) { 135b30f38383e4691bf23311f62649aa504832731dbVictoria Lease if (!stats.requested) { 136b30f38383e4691bf23311f62649aa504832731dbVictoria Lease stats.requestTime = SystemClock.elapsedRealtime(); 137b30f38383e4691bf23311f62649aa504832731dbVictoria Lease stats.requested = true; 138b30f38383e4691bf23311f62649aa504832731dbVictoria Lease stats.minTime = minTime; 139b30f38383e4691bf23311f62649aa504832731dbVictoria Lease mLocationManager.requestLocationUpdates(name, minTime, 0, this, mLooper); 140b30f38383e4691bf23311f62649aa504832731dbVictoria Lease } else if (stats.minTime != minTime) { 141b30f38383e4691bf23311f62649aa504832731dbVictoria Lease stats.minTime = minTime; 142b30f38383e4691bf23311f62649aa504832731dbVictoria Lease mLocationManager.requestLocationUpdates(name, minTime, 0, this, mLooper); 143b30f38383e4691bf23311f62649aa504832731dbVictoria Lease } 1446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private void disableProvider(String name) { 1486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly ProviderStats stats = mStats.get(name); 1496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (stats.requested) { 1516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly stats.requested = false; 1526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mLocationManager.removeUpdates(this); //TODO GLOBAL 1536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private void updateRequirements() { 1576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (mEnabled == false || mRequest == null) { 1586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mRequest = null; 1596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly disableProvider(NETWORK); 1606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly disableProvider(GPS); 1616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return; 1626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly long networkInterval = Long.MAX_VALUE; 1656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly long gpsInterval = Long.MAX_VALUE; 1667ab7f538924371a9dd4be7a27a6ae3b4c04b301cLaurent Tu for (LocationRequestUnbundled request : mRequest.getLocationRequests()) { 1676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly switch (request.getQuality()) { 1687ab7f538924371a9dd4be7a27a6ae3b4c04b301cLaurent Tu case LocationRequestUnbundled.ACCURACY_FINE: 1697ab7f538924371a9dd4be7a27a6ae3b4c04b301cLaurent Tu case LocationRequestUnbundled.POWER_HIGH: 1706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (request.getInterval() < gpsInterval) { 1716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly gpsInterval = request.getInterval(); 1726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (request.getInterval() < networkInterval) { 1746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly networkInterval = request.getInterval(); 1756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly break; 1777ab7f538924371a9dd4be7a27a6ae3b4c04b301cLaurent Tu case LocationRequestUnbundled.ACCURACY_BLOCK: 1787ab7f538924371a9dd4be7a27a6ae3b4c04b301cLaurent Tu case LocationRequestUnbundled.ACCURACY_CITY: 1797ab7f538924371a9dd4be7a27a6ae3b4c04b301cLaurent Tu case LocationRequestUnbundled.POWER_LOW: 1806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (request.getInterval() < networkInterval) { 1816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly networkInterval = request.getInterval(); 1826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1836fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly break; 1846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (gpsInterval < Long.MAX_VALUE) { 1886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly enableProvider(GPS, gpsInterval); 1896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } else { 1906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly disableProvider(GPS); 1916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (networkInterval < Long.MAX_VALUE) { 1936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly enableProvider(NETWORK, networkInterval); 1946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } else { 1956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly disableProvider(NETWORK); 1966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1990fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease /** 2000fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease * Test whether one location (a) is better to use than another (b). 2010fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease */ 2020fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease private static boolean isBetterThan(Location locationA, Location locationB) { 2030fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease if (locationA == null) { 2040fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease return false; 2050fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease } 2060fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease if (locationB == null) { 2070fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease return true; 2080fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease } 2090fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease // A provider is better if the reading is sufficiently newer. Heading 2100fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease // underground can cause GPS to stop reporting fixes. In this case it's 2110fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease // appropriate to revert to cell, even when its accuracy is less. 2120fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease if (locationA.getElapsedRealtimeNanos() > locationB.getElapsedRealtimeNanos() + SWITCH_ON_FRESHNESS_CLIFF_NS) { 2130fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease return true; 2140fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease } 2150fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease 2160fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease // A provider is better if it has better accuracy. Assuming both readings 2170fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease // are fresh (and by that accurate), choose the one with the smaller 2180fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease // accuracy circle. 2190fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease if (!locationA.hasAccuracy()) { 2200fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease return false; 2210fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease } 2220fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease if (!locationB.hasAccuracy()) { 2230fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease return true; 2240fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease } 2250fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease return locationA.getAccuracy() < locationB.getAccuracy(); 2266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 2276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 2286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private void updateFusedLocation() { 2290fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease // may the best location win! 2300fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease if (isBetterThan(mGpsLocation, mNetworkLocation)) { 2310fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease mFusedLocation = new Location(mGpsLocation); 2320fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease } else { 2330fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease mFusedLocation = new Location(mNetworkLocation); 2346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 235779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease mFusedLocation.setProvider(FUSED); 23609016ab4dd056a16809419d612cb865a14980880Victoria Lease if (mNetworkLocation != null) { 237779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease // copy NO_GPS_LOCATION extra from mNetworkLocation into mFusedLocation 238779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease Bundle srcExtras = mNetworkLocation.getExtras(); 239779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease if (srcExtras != null) { 240779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease Parcelable srcParcelable = 241779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease srcExtras.getParcelable(LocationProviderBase.EXTRA_NO_GPS_LOCATION); 242779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease if (srcParcelable instanceof Location) { 243779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease Bundle dstExtras = mFusedLocation.getExtras(); 244779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease if (dstExtras == null) { 245779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease dstExtras = new Bundle(); 246779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease mFusedLocation.setExtras(dstExtras); 247779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease } 248779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease dstExtras.putParcelable(LocationProviderBase.EXTRA_NO_GPS_LOCATION, 249779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease (Location) srcParcelable); 250779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease } 251779b77455fc51382ecafa210b8a805d2a616da55Victoria Lease } 25209016ab4dd056a16809419d612cb865a14980880Victoria Lease } 2536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 254161f42619b82995f88f6e299b6c74cb8382c4135Laurent Tu if (mCallback != null) { 255161f42619b82995f88f6e299b6c74cb8382c4135Laurent Tu mCallback.reportLocation(mFusedLocation); 256161f42619b82995f88f6e299b6c74cb8382c4135Laurent Tu } else { 257161f42619b82995f88f6e299b6c74cb8382c4135Laurent Tu Log.w(TAG, "Location updates received while fusion engine not started"); 258161f42619b82995f88f6e299b6c74cb8382c4135Laurent Tu } 2596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 2606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 2616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly /** Called on mLooper thread */ 2626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly @Override 2636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public void onLocationChanged(Location location) { 2646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (GPS.equals(location.getProvider())) { 2656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mGpsLocation = location; 2666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly updateFusedLocation(); 2676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } else if (NETWORK.equals(location.getProvider())) { 2686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mNetworkLocation = location; 2696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly updateFusedLocation(); 2706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 2716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 2726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 2736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly /** Called on mLooper thread */ 2746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly @Override 2756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public void onStatusChanged(String provider, int status, Bundle extras) { } 2766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 2776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly /** Called on mLooper thread */ 2786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly @Override 2796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public void onProviderEnabled(String provider) { 2806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly ProviderStats stats = mStats.get(provider); 2816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (stats == null) return; 2826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 2836fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly stats.available = true; 2846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 2856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 2866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly /** Called on mLooper thread */ 2876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly @Override 2886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public void onProviderDisabled(String provider) { 2896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly ProviderStats stats = mStats.get(provider); 2906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (stats == null) return; 2916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 2926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly stats.available = false; 2936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 2946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 2956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly StringBuilder s = new StringBuilder(); 2976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly s.append("mEnabled=" + mEnabled).append(' ').append(mRequest).append('\n'); 2986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly s.append("fused=").append(mFusedLocation).append('\n'); 2990fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease s.append(String.format("gps %s\n", mGpsLocation)); 3006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly s.append(" ").append(mStats.get(GPS)).append('\n'); 3010fdfa6b49e7642a90a1b98881e4e2801cbcd3c77Victoria Lease s.append(String.format("net %s\n", mNetworkLocation)); 3026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly s.append(" ").append(mStats.get(NETWORK)).append('\n'); 3036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly pw.append(s); 3046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 30503cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease 30603cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease /** Called on mLooper thread */ 30703cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease public void switchUser() { 30803cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease // reset state to prevent location data leakage 30903cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease mFusedLocation = null; 31003cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease mGpsLocation = null; 31103cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease mNetworkLocation = null; 31203cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease } 3136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly} 314