Commit 544705c3 authored by Matt Reynolds's avatar Matt Reynolds Committed by Commit Bot

geolocation: Use high accuracy in sensors-only mode

The FusedLocationProvider API determines which location providers to use
based on a priority mode specified in the API call. In
PRIORITY_BALANCED_POWER_ACCURACY mode, the request will never cause
power-intensive providers like GPS to be used unless another app
requests it. Instead, the network provider is preferred.

If Android is configured to disable network location providers but to
enable sensors (like GPS), then elevate the priority of the request to
improve the likelihood that GPS sensors will be used to acquire a
location.

BUG=620003

Change-Id: Ia11b7d367b0bdf89631a3e0ccfc696daf1d238a3
Reviewed-on: https://chromium-review.googlesource.com/1182289
Commit-Queue: Matt Reynolds <mattreynolds@chromium.org>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Reviewed-by: default avatarMiguel Casas <mcasas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#590496}
parent c3ddb307
......@@ -5,9 +5,11 @@
package org.chromium.components.location;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Build;
import android.os.Process;
import android.provider.Settings;
......@@ -70,10 +72,15 @@ public class LocationUtils {
* Returns whether location services are enabled system-wide, i.e. whether any application is
* able to access location.
*/
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public boolean isSystemLocationSettingEnabled() {
Context context = ContextUtils.getApplicationContext();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
LocationManager locationManager =
(LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
return locationManager != null && locationManager.isLocationEnabled();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
return Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF)
!= Settings.Secure.LOCATION_MODE_OFF;
......@@ -83,6 +90,35 @@ public class LocationUtils {
}
}
/**
* Returns whether location services are enabled in sensors-only mode, i.e. when network
* location services are disabled but GPS and other sensors are enabled.
*/
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public boolean isSystemLocationSettingSensorsOnly() {
Context context = ContextUtils.getApplicationContext();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
LocationManager locationManager =
(LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
return locationManager != null && locationManager.isLocationEnabled()
&& locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
&& !locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
return Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF)
== Settings.Secure.LOCATION_MODE_SENSORS_ONLY;
} else {
// Before Android K, location provider settings were stored as a comma-delimited list
// containing the names of enabled providers. In sensors-only mode, the GPS provider is
// present and the network provider is absent.
String locationProviders = Settings.Secure.getString(
context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
return locationProviders.contains(LocationManager.GPS_PROVIDER)
&& !locationProviders.contains(LocationManager.NETWORK_PROVIDER);
}
}
/**
* Returns true iff a prompt can be triggered to ask the user to turn on the system location
* setting on their device.
......
......@@ -141,6 +141,7 @@ if (is_android) {
"$google_play_services_package:google_play_services_basement_java",
"$google_play_services_package:google_play_services_location_java",
"//base:base_java",
"//components/location/android:location_java",
"//services/device/public/java:geolocation_java",
]
}
......
include_rules = [
"+chromeos",
"+components/location",
"+dbus",
"+jni",
"+net/base",
......
......@@ -20,6 +20,7 @@ import com.google.android.gms.location.LocationServices;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.components.location.LocationUtils;
/**
* This is a LocationProvider using Google Play Services.
......@@ -67,11 +68,23 @@ public class LocationProviderGmsCore implements ConnectionCallbacks, OnConnectio
mLocationRequest = LocationRequest.create();
if (mEnablehighAccuracy) {
// With enableHighAccuracy, request a faster update interval and configure the provider
// for high accuracy mode.
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(UPDATE_INTERVAL_FAST_MS);
} else {
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY)
.setInterval(UPDATE_INTERVAL_MS);
// Use balanced mode by default. In this mode, the API will prefer the network provider
// but may use sensor data (for instance, GPS) if high accuracy is requested by another
// app.
//
// If location is configured for sensors-only then elevate the priority to ensure GPS
// and other sensors are used.
if (LocationUtils.getInstance().isSystemLocationSettingSensorsOnly()) {
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
} else {
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
}
mLocationRequest.setInterval(UPDATE_INTERVAL_MS);
}
final Location location = mLocationProviderApi.getLastLocation(mGoogleApiClient);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment