Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6fa9ad4a authored by Nick Pelly's avatar Nick Pelly
Browse files

Location overhaul, major commit.

Themes: Fused Location, Geofencing, LocationRequest.

API changes
o Fused location is always returned when asking for location by Criteria.
o Fused location is never returned as a LocationProvider object, nor returned
  as a provider String. This wouldn't make sense because the current API
  design assumes that LocationProvider's have fixed properties (accuracy, power
  etc).
o The fused location engine will tune itself based on the criteria passed
  by applications.
o Deprecate LocationProvider. Apps should use fused location (via Criteria
  class), instead of enumerating through LocationProvider objects. It is
  also over-engineered: designed for a world with a plethora of location
  providers that never materialized.
o The Criteria class is also over-engineered, with many methods that aren't
  currently used, but for now we won't deprecate them since they may have
  value in the future. It is now used to tune the fused location engine.
o Deprecate getBestProvider() and getProvider().
o Add getLastKnownLocation(Criteria), so we can return last known
  fused locations.
o Apps with only ACCESS_COARSE_LOCATION _can_ now use the GPS, but the location
  they receive will be fudged to a 1km radius. They can also use NETWORK
  and fused locatoins, which are fudged in the same way if necessary.
o Totally deprecate Criteria, in favor of LocationRequest.
  Criteria was designed to map QOS to a location provider. What we
  really need is to map QOS to _locations_.
  The death knell was the conflicting ACCURACY_ constants on
  Criteria, with values 1, 2, 3, 1, 2. Yes not a typo.
o Totally deprecate LocationProvider.
o Deprecate test/mock provider support. They require a named provider,
  which is a concept we are moving away from. We do not yet have a
  replacement, but I think its ok to deprecate since you also
  need to have 'allow mock locations' checked in developer settings.
  They will continue to work.
o Deprecate event codes associated with provider status. The fused
  provider is _always_ available.
o Introduce Geofence data object to provide an easier path fowards
  for polygons etc.

Implementation changes
o Fused implementation: incoming (GPS and NLP) location fixes are given
  a weight, that exponentially decays with respect to age and accuracy.
  The half-life of age is ~60 seconds, and the half-life of accuracy is
  ~20 meters. The fixes are weighted and combined to output a fused
  location.
o Move Fused Location impl into
  frameworks/base/packages/FusedLocation
o Refactor Fused Location behind the IProvider AIDL interface. This allow us
  to distribute newer versions of Fused Location in a new APK, at run-time.
o Introduce ServiceWatcher.java, to refactor code used for run-time upgrades of
  Fused Location, and the NLP.
o Fused Location is by default run in the system server (but can be moved to
  any process or pacakge, even at run-time).
o Plumb the Criteria requirements through to the Fused Location provider via
  ILocation.sendExtraCommand(). I re-used this interface to avoid modifying the
  ILocation interface, which would have broken run-time upgradability of the
  NLP.
o Switch the geofence manager to using fused location.
o Clean up 'adb shell dumpsys location' output.
o Introduce config_locationProviderPackageNames and
  config_overlay_locationProviderPackageNames to configure the default
  and overlay package names for Geocoder, NLP and FLP.
o Lots of misc cleanup.
o Improve location fudging. Apply random vector then quantize.
o Hide internal POJO's from clients of com.android.location.provider.jar
  (NLP and FLP). Introduce wrappers ProviderRequestUnbundled and
  ProviderPropertiesUnbundled.
o Introduce ProviderProperties to collapse all the provider accuracy/
  bearing/altitude/power plumbing (that is deprecated anyway).
o DELETE lots of code: DummyLocationProvider,
o Rename the (internal) LocationProvider to LocationProviderBase.
o Plumb pid, uid and packageName throughout
  LocationManagerService#Receiver to support future features.

TODO: The FLP and Geofencer have a lot of room to be more intelligent
TODO: Documentation
TODO: test test test

Change-Id: Iacefd2f176ed40ce1e23b090a164792aa8819c55
parent c47f80f1
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -197,8 +197,8 @@ LOCAL_SRC_FILES += \
	location/java/android/location/IGpsStatusProvider.aidl \
	location/java/android/location/ILocationListener.aidl \
	location/java/android/location/ILocationManager.aidl \
	location/java/android/location/ILocationProvider.aidl \
	location/java/android/location/INetInitiatedListener.aidl \
	location/java/com/android/internal/location/ILocationProvider.aidl \
	media/java/android/media/IAudioService.aidl \
	media/java/android/media/IAudioFocusDispatcher.aidl \
	media/java/android/media/IAudioRoutesObserver.aidl \
@@ -306,7 +306,11 @@ aidl_files := \
	frameworks/base/graphics/java/android/graphics/Rect.aidl \
	frameworks/base/graphics/java/android/graphics/Region.aidl \
	frameworks/base/location/java/android/location/Criteria.aidl \
	frameworks/base/location/java/android/location/Geofence.aidl \
	frameworks/base/location/java/android/location/Location.aidl \
	frameworks/base/location/java/android/location/LocationRequest.aidl \
	frameworks/base/location/java/com/android/internal/location/ProviderProperties.aidl \
	frameworks/base/location/java/com/android/internal/location/ProviderRequest.aidl \
	frameworks/base/telephony/java/android/telephony/ServiceState.aidl \
	frameworks/base/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
	frameworks/base/telephony/java/com/android/internal/telephony/ITelephony.aidl \
+83 −45
Original line number Diff line number Diff line
@@ -10451,7 +10451,7 @@ package android.location {
    field public static final android.os.Parcelable.Creator CREATOR;
  }
  public class Criteria implements android.os.Parcelable {
  public deprecated class Criteria implements android.os.Parcelable {
    ctor public Criteria();
    ctor public Criteria(android.location.Criteria);
    method public int describeContents();
@@ -10497,6 +10497,13 @@ package android.location {
    method public static boolean isPresent();
  }
  public final class Geofence implements android.os.Parcelable {
    method public static android.location.Geofence createCircle(double, double, float);
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator CREATOR;
  }
  public final class GpsSatellite {
    method public float getAzimuth();
    method public float getElevation();
@@ -10534,7 +10541,7 @@ package android.location {
    method public int describeContents();
    method public static void distanceBetween(double, double, double, double, float[]);
    method public float distanceTo(android.location.Location);
    method public void dump(android.util.Printer, java.lang.String);
    method public deprecated void dump(android.util.Printer, java.lang.String);
    method public float getAccuracy();
    method public double getAltitude();
    method public float getBearing();
@@ -10582,65 +10589,96 @@ package android.location {
  public class LocationManager {
    method public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
    method public boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
    method public void addProximityAlert(double, double, float, long, android.app.PendingIntent);
    method public void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
    method public void clearTestProviderEnabled(java.lang.String);
    method public void clearTestProviderLocation(java.lang.String);
    method public void clearTestProviderStatus(java.lang.String);
    method public java.util.List<java.lang.String> getAllProviders();
    method public java.lang.String getBestProvider(android.location.Criteria, boolean);
    method public deprecated void addProximityAlert(double, double, float, long, android.app.PendingIntent);
    method public deprecated void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
    method public deprecated void clearTestProviderEnabled(java.lang.String);
    method public deprecated void clearTestProviderLocation(java.lang.String);
    method public deprecated void clearTestProviderStatus(java.lang.String);
    method public deprecated java.util.List<java.lang.String> getAllProviders();
    method public deprecated java.lang.String getBestProvider(android.location.Criteria, boolean);
    method public android.location.GpsStatus getGpsStatus(android.location.GpsStatus);
    method public android.location.Location getLastKnownLocation(java.lang.String);
    method public android.location.LocationProvider getProvider(java.lang.String);
    method public java.util.List<java.lang.String> getProviders(boolean);
    method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
    method public boolean isProviderEnabled(java.lang.String);
    method public deprecated android.location.Location getLastKnownLocation(java.lang.String);
    method public deprecated android.location.Location getLastKnownLocation(android.location.Criteria);
    method public android.location.Location getLastLocation(android.location.LocationRequest);
    method public deprecated android.location.LocationProvider getProvider(java.lang.String);
    method public deprecated java.util.List<java.lang.String> getProviders(boolean);
    method public deprecated java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
    method public deprecated boolean isProviderEnabled(java.lang.String);
    method public void removeAllGeofences(android.app.PendingIntent);
    method public void removeGeofence(android.location.Geofence, android.app.PendingIntent);
    method public void removeGpsStatusListener(android.location.GpsStatus.Listener);
    method public void removeNmeaListener(android.location.GpsStatus.NmeaListener);
    method public void removeProximityAlert(android.app.PendingIntent);
    method public void removeTestProvider(java.lang.String);
    method public deprecated void removeProximityAlert(android.app.PendingIntent);
    method public deprecated void removeTestProvider(java.lang.String);
    method public void removeUpdates(android.location.LocationListener);
    method public void removeUpdates(android.app.PendingIntent);
    method public void requestLocationUpdates(java.lang.String, long, float, android.location.LocationListener);
    method public void requestLocationUpdates(java.lang.String, long, float, android.location.LocationListener, android.os.Looper);
    method public void requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper);
    method public void requestLocationUpdates(java.lang.String, long, float, android.app.PendingIntent);
    method public void requestLocationUpdates(long, float, android.location.Criteria, android.app.PendingIntent);
    method public void requestSingleUpdate(java.lang.String, android.location.LocationListener, android.os.Looper);
    method public void requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper);
    method public void requestSingleUpdate(java.lang.String, android.app.PendingIntent);
    method public void requestSingleUpdate(android.location.Criteria, android.app.PendingIntent);
    method public boolean sendExtraCommand(java.lang.String, java.lang.String, android.os.Bundle);
    method public void setTestProviderEnabled(java.lang.String, boolean);
    method public void setTestProviderLocation(java.lang.String, android.location.Location);
    method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
    field public static final java.lang.String GPS_PROVIDER = "gps";
    method public void requestGeofence(android.location.LocationRequest, android.location.Geofence, android.app.PendingIntent);
    method public deprecated void requestLocationUpdates(java.lang.String, long, float, android.location.LocationListener);
    method public deprecated void requestLocationUpdates(java.lang.String, long, float, android.location.LocationListener, android.os.Looper);
    method public deprecated void requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper);
    method public deprecated void requestLocationUpdates(java.lang.String, long, float, android.app.PendingIntent);
    method public deprecated void requestLocationUpdates(long, float, android.location.Criteria, android.app.PendingIntent);
    method public void requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper);
    method public void requestLocationUpdates(android.location.LocationRequest, android.app.PendingIntent);
    method public deprecated void requestSingleUpdate(java.lang.String, android.location.LocationListener, android.os.Looper);
    method public deprecated void requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper);
    method public deprecated void requestSingleUpdate(java.lang.String, android.app.PendingIntent);
    method public deprecated void requestSingleUpdate(android.location.Criteria, android.app.PendingIntent);
    method public deprecated boolean sendExtraCommand(java.lang.String, java.lang.String, android.os.Bundle);
    method public deprecated void setTestProviderEnabled(java.lang.String, boolean);
    method public deprecated void setTestProviderLocation(java.lang.String, android.location.Location);
    method public deprecated void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
    field public static final deprecated java.lang.String GPS_PROVIDER = "gps";
    field public static final java.lang.String KEY_LOCATION_CHANGED = "location";
    field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled";
    field public static final deprecated java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled";
    field public static final java.lang.String KEY_PROXIMITY_ENTERING = "entering";
    field public static final java.lang.String KEY_STATUS_CHANGED = "status";
    field public static final java.lang.String NETWORK_PROVIDER = "network";
    field public static final java.lang.String PASSIVE_PROVIDER = "passive";
    field public static final java.lang.String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
    field public static final deprecated java.lang.String KEY_STATUS_CHANGED = "status";
    field public static final deprecated java.lang.String NETWORK_PROVIDER = "network";
    field public static final deprecated java.lang.String PASSIVE_PROVIDER = "passive";
    field public static final deprecated java.lang.String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
  }
  public abstract class LocationProvider {
    method public abstract int getAccuracy();
  public deprecated class LocationProvider {
    method public int getAccuracy();
    method public java.lang.String getName();
    method public abstract int getPowerRequirement();
    method public abstract boolean hasMonetaryCost();
    method public int getPowerRequirement();
    method public boolean hasMonetaryCost();
    method public boolean meetsCriteria(android.location.Criteria);
    method public abstract boolean requiresCell();
    method public abstract boolean requiresNetwork();
    method public abstract boolean requiresSatellite();
    method public abstract boolean supportsAltitude();
    method public abstract boolean supportsBearing();
    method public abstract boolean supportsSpeed();
    method public boolean requiresCell();
    method public boolean requiresNetwork();
    method public boolean requiresSatellite();
    method public boolean supportsAltitude();
    method public boolean supportsBearing();
    method public boolean supportsSpeed();
    field public static final int AVAILABLE = 2; // 0x2
    field public static final int OUT_OF_SERVICE = 0; // 0x0
    field public static final int TEMPORARILY_UNAVAILABLE = 1; // 0x1
  }
  public final class LocationRequest implements android.os.Parcelable {
    method public static android.location.LocationRequest create();
    method public int describeContents();
    method public long getExpireAt();
    method public long getFastestInterval();
    method public long getInterval();
    method public int getNumUpdates();
    method public int getQuality();
    method public android.location.LocationRequest setExpireAt(long);
    method public android.location.LocationRequest setExpireIn(long);
    method public android.location.LocationRequest setFastestInterval(long);
    method public android.location.LocationRequest setInterval(long);
    method public android.location.LocationRequest setNumUpdates(int);
    method public android.location.LocationRequest setQuality(int);
    method public void writeToParcel(android.os.Parcel, int);
    field public static final int ACCURACY_BLOCK = 102; // 0x66
    field public static final int ACCURACY_CITY = 104; // 0x68
    field public static final int ACCURACY_FINE = 100; // 0x64
    field public static final android.os.Parcelable.Creator CREATOR;
    field public static final int POWER_HIGH = 203; // 0xcb
    field public static final int POWER_LOW = 201; // 0xc9
    field public static final int POWER_NONE = 200; // 0xc8
  }
}
package android.media {
+23 −4
Original line number Diff line number Diff line
@@ -592,11 +592,30 @@
    <!-- True if WallpaperService is enabled -->
    <bool name="config_enableWallpaperService">true</bool>

    <!-- Package name providing network location support. -->
    <string name="config_networkLocationProviderPackageName" translatable="false">@null</string>
    <!-- Package name(s) containing location provider support.
         These packages can contain services implementing location providers,
         such as the Geocode Provider, Network Location Provider, and
         Fused Location Provider. They will each be searched for
         service components implementing these providers.
         It is strongly recommended that the packages explicitly named
         below are on the system image, so that they will not map to
         a 3rd party application.
         The location framework also has support for installation
         of new location providers at run-time. The new package does not
         have to be explicitly listed here, however it must have a signature
         that matches the signature of at least one package on this list.
         Platforms should overlay additional packages in
         config_overlay_locationProviderPackageNames, instead of overlaying
         this config, if they only want to append packages and not replace
         the entire array.
         -->
    <string-array name="config_locationProviderPackageNames" translatable="false">
        <item>com.android.location.fused</item>
    </string-array>

    <!-- Package name providing geocoder API support. -->
    <string name="config_geocodeProviderPackageName" translatable="false">@null</string>
    <!-- Pacakge name(s) supplied by overlay, and appended to
         config_locationProviderPackageNames. -->
    <string-array name="config_overlay_locationProviderPackageNames" translatable="false" />

    <!-- Boolean indicating if current platform supports bluetooth SCO for off call
    use cases -->
+2 −2
Original line number Diff line number Diff line
@@ -1415,6 +1415,8 @@
  <java-symbol type="array" name="config_serialPorts" />
  <java-symbol type="array" name="radioAttributes" />
  <java-symbol type="array" name="config_oemUsbModeOverride" />
  <java-symbol type="array" name="config_locationProviderPackageNames" />
  <java-symbol type="array" name="config_overlay_locationProviderPackageNames" />
  <java-symbol type="bool" name="config_animateScreenLights" />
  <java-symbol type="bool" name="config_automatic_brightness_available" />
  <java-symbol type="bool" name="config_sf_limitedAlpha" />
@@ -1493,8 +1495,6 @@
  <java-symbol type="string" name="car_mode_disable_notification_title" />
  <java-symbol type="string" name="chooser_wallpaper" />
  <java-symbol type="string" name="config_datause_iface" />
  <java-symbol type="string" name="config_geocodeProviderPackageName" />
  <java-symbol type="string" name="config_networkLocationProviderPackageName" />
  <java-symbol type="string" name="config_wimaxManagerClassname" />
  <java-symbol type="string" name="config_wimaxNativeLibLocation" />
  <java-symbol type="string" name="config_wimaxServiceClassname" />
+45 −0
Original line number Diff line number Diff line
@@ -24,7 +24,9 @@ import android.os.Parcelable;
 * location provider.  Providers maybe ordered according to accuracy,
 * power usage, ability to report altitude, speed,
 * and bearing, and monetary cost.
 * @deprecated {@link LocationRequest} instead
 */
@Deprecated
public class Criteria implements Parcelable {
    /**
     * A constant indicating that the application does not choose to
@@ -326,6 +328,7 @@ public class Criteria implements Parcelable {

    public static final Parcelable.Creator<Criteria> CREATOR =
        new Parcelable.Creator<Criteria>() {
        @Override
        public Criteria createFromParcel(Parcel in) {
            Criteria c = new Criteria();
            c.mHorizontalAccuracy = in.readInt();
@@ -340,15 +343,18 @@ public class Criteria implements Parcelable {
            return c;
        }

        @Override
        public Criteria[] newArray(int size) {
            return new Criteria[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeInt(mHorizontalAccuracy);
        parcel.writeInt(mVerticalAccuracy);
@@ -360,4 +366,43 @@ public class Criteria implements Parcelable {
        parcel.writeInt(mSpeedRequired ? 1 : 0);
        parcel.writeInt(mCostAllowed ? 1 : 0);
    }

    private static String powerToString(int power) {
        switch (power) {
            case NO_REQUIREMENT:
                return "NO_REQ";
            case POWER_LOW:
                return "LOW";
            case POWER_MEDIUM:
                return "MEDIUM";
            case POWER_HIGH:
                return "HIGH";
            default:
                return "???";
        }
    }

    private static String accuracyToString(int accuracy) {
        switch (accuracy) {
            case NO_REQUIREMENT:
                return "---";
            case ACCURACY_HIGH:
                return "HIGH";
            case ACCURACY_MEDIUM:
                return "MEDIUM";
            case ACCURACY_LOW:
                return "LOW";
            default:
                return "???";
        }
    }

    @Override
    public String toString() {
        StringBuilder s = new StringBuilder();
        s.append("Criteria[power=").append(powerToString(mPowerRequirement));
        s.append(" acc=").append(accuracyToString(mHorizontalAccuracy));
        s.append(']');
        return s.toString();
    }
}
Loading