Various GNSS cleanups

-Remove GNSS disable on idle behavior. This breaks the contract of
location providers and seems likely to increase power usage by forcing
more network location usage in some circumstances. Power save modes
are already handled at a higher level, the GNSS location provider
should not need to care about them.
-Remove some unnecessary thread trampolining.
-Reorganize vars to better conform to standard ordering practices
(statics first, etc).
-Prevent double reporting of network locations to GNSS HAL.
-Prevent mock locations from being reported to the HAL.
-Switch to listener alarms instead of pending intent alarms.

Test: presubmits
Change-Id: I8c526f32b1dbcdac419d1d7644fc2e511b0f9b5c
This commit is contained in:
Soonil Nagarkar
2020-11-05 14:04:02 -08:00
parent bf126a7af3
commit 623cf937ba
4 changed files with 161 additions and 290 deletions

View File

@@ -310,6 +310,7 @@ public abstract class AbstractLocationProvider {
* Sets a new request and worksource for the provider.
*/
public final void setRequest(ProviderRequest request) {
// TODO: do we want to hold a wakelock until onSetRequest is run?
// all calls into the provider must be moved onto the provider thread to prevent deadlock
mExecutor.execute(() -> onSetRequest(request));
}

View File

@@ -324,6 +324,8 @@ public class LocationManagerService extends ILocationManager.Stub {
}
void onSystemThirdPartyAppsCanStart() {
// network provider should always be initialized before the gps provider since the gps
// provider has unfortunate hard dependencies on the network provider
ProxyLocationProvider networkProvider = ProxyLocationProvider.createAndRegister(
mContext,
NETWORK_LOCATION_SERVICE_ACTION,

View File

@@ -16,11 +16,12 @@
package com.android.server.location.gnss;
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -45,10 +46,8 @@ import android.location.LocationResult;
import android.location.util.identity.CallerIdentity;
import android.os.AsyncTask;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
@@ -77,9 +76,7 @@ import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
import com.android.internal.location.gnssmetrics.GnssMetrics;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.DeviceIdleInternal;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.location.AbstractLocationProvider;
import com.android.server.location.gnss.GnssSatelliteBlocklistHelper.GnssSatelliteBlocklistCallback;
import com.android.server.location.gnss.NtpTimeHelper.InjectNtpTimeCallback;
@@ -91,6 +88,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
@@ -182,12 +180,9 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
private static final int AGPS_SUPL_MODE_MSA = 0x02;
private static final int AGPS_SUPL_MODE_MSB = 0x01;
private static final int UPDATE_LOW_POWER_MODE = 1;
private static final int SET_REQUEST = 3;
private static final int INJECT_NTP_TIME = 5;
// PSDS stands for Predicted Satellite Data Service
private static final int DOWNLOAD_PSDS_DATA = 6;
private static final int INITIALIZE_HANDLER = 13;
private static final int REQUEST_LOCATION = 16;
private static final int REPORT_LOCATION = 17; // HAL reports location
private static final int REPORT_SV_STATUS = 18; // HAL reports SV status
@@ -270,8 +265,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}
}
private final Object mLock = new Object();
// stop trying if we do not receive a fix within 60 seconds
private static final int NO_FIX_TIMEOUT = 60 * 1000;
@@ -293,6 +286,23 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
private static final long DOWNLOAD_PSDS_DATA_TIMEOUT_MS = 60 * 1000;
private static final long WAKELOCK_TIMEOUT_MILLIS = 30 * 1000;
// threshold for delay in GNSS engine turning off before warning & error
private static final long LOCATION_OFF_DELAY_THRESHOLD_WARN_MILLIS = 2 * 1000;
private static final long LOCATION_OFF_DELAY_THRESHOLD_ERROR_MILLIS = 15 * 1000;
private static final String DOWNLOAD_EXTRA_WAKELOCK_KEY = "GnssLocationProviderPsdsDownload";
// Set lower than the current ITAR limit of 600m/s to allow this to trigger even if GPS HAL
// stops output right at 600m/s, depriving this of the information of a device that reaches
// greater than 600m/s, and higher than the speed of sound to avoid impacting most use cases.
private static final float ITAR_SPEED_LIMIT_METERS_PER_SECOND = 400.0F;
private final Object mLock = new Object();
private final Context mContext;
private final Handler mHandler;
@GuardedBy("mLock")
private final ExponentialBackOff mPsdsBackOff = new ExponentialBackOff(RETRY_INTERVAL,
MAX_RETRY_INTERVAL);
@@ -305,37 +315,16 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
private boolean mBatchingEnabled;
private boolean mShutdown;
@GuardedBy("mLock")
private Set<Integer> mPendingDownloadPsdsTypes = new HashSet<>();
// true if GPS is navigating
private boolean mNavigating;
// requested frequency of fixes, in milliseconds
private boolean mStarted;
private boolean mBatchingStarted;
private long mStartedChangedElapsedRealtime;
private int mFixInterval = 1000;
// true if low power mode for the GNSS chipset is part of the latest request.
private boolean mLowPowerMode = false;
private ProviderRequest mProviderRequest;
// true if we started navigation in the HAL, only change value of this in setStarted
private boolean mStarted;
// true if batching is being used
private boolean mBatchingStarted;
// for logging of latest change, and warning of ongoing location after a stop
private long mStartedChangedElapsedRealtime;
// threshold for delay in GNSS engine turning off before warning & error
private static final long LOCATION_OFF_DELAY_THRESHOLD_WARN_MILLIS = 2 * 1000;
private static final long LOCATION_OFF_DELAY_THRESHOLD_ERROR_MILLIS = 15 * 1000;
// capabilities reported through the top level IGnssCallback.hal
private volatile int mTopHalCapabilities;
// true if PSDS is supported
private boolean mSupportsPsds;
private int mPositionMode;
private GnssPositionMode mLastPositionMode;
// for calculating time to first fix
private long mFixRequestTime = 0;
@@ -344,25 +333,23 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
// time we received our last fix
private long mLastFixTime;
private int mPositionMode;
private GnssPositionMode mLastPositionMode;
private final WorkSource mClientSource = new WorkSource();
// Current request from underlying location clients.
private ProviderRequest mProviderRequest;
// True if gps should be disabled because of PowerManager controls
private boolean mDisableGpsForPowerManager = false;
// capabilities reported through the top level IGnssCallback.hal
private volatile int mTopHalCapabilities;
/**
* True if the device idle controller has determined that the device is stationary. This is only
* updated when the device enters idle mode.
*/
private volatile boolean mIsDeviceStationary = false;
// true if PSDS is supported
private boolean mSupportsPsds;
@GuardedBy("mLock")
private final PowerManager.WakeLock mDownloadPsdsWakeLock;
@GuardedBy("mLock")
private final Set<Integer> mPendingDownloadPsdsTypes = new HashSet<>();
/**
* Properties loaded from PROPERTIES_FILE.
* It must be accessed only inside {@link #mHandler}.
*/
private GnssConfiguration mGnssConfiguration;
private final GnssConfiguration mGnssConfiguration;
private String mSuplServerHost;
private int mSuplServerPort = TCP_MIN_PORT;
@@ -370,15 +357,12 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
private int mC2KServerPort;
private boolean mSuplEsEnabled = false;
private final Looper mLooper;
private final LocationExtras mLocationExtras = new LocationExtras();
private final GnssStatusProvider mGnssStatusListenerHelper;
private final GnssMeasurementsProvider mGnssMeasurementsProvider;
private final GnssMeasurementCorrectionsProvider mGnssMeasurementCorrectionsProvider;
private final GnssAntennaInfoProvider mGnssAntennaInfoProvider;
private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
private final LocationChangeListener mNetworkLocationListener = new NetworkLocationListener();
private final LocationChangeListener mFusedLocationListener = new FusedLocationListener();
private final NtpTimeHelper mNtpTimeHelper;
private final GnssGeofenceProvider mGnssGeofenceProvider;
private final GnssCapabilitiesProvider mGnssCapabilitiesProvider;
@@ -387,53 +371,32 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
// Available only on GNSS HAL 2.0 implementations and later.
private GnssVisibilityControl mGnssVisibilityControl;
private final Context mContext;
private Handler mHandler;
private final GnssNetworkConnectivityHandler mNetworkConnectivityHandler;
private final GpsNetInitiatedHandler mNIHandler;
// Wakelocks
private static final String WAKELOCK_KEY = "GnssLocationProvider";
private final PowerManager.WakeLock mWakeLock;
private static final String DOWNLOAD_EXTRA_WAKELOCK_KEY = "GnssLocationProviderPsdsDownload";
@GuardedBy("mLock")
private final PowerManager.WakeLock mDownloadPsdsWakeLock;
// Alarms
private static final String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
private static final String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
private final PowerManager mPowerManager;
private final AlarmManager mAlarmManager;
private final PendingIntent mWakeupIntent;
private final PendingIntent mTimeoutIntent;
private final AlarmManager.OnAlarmListener mWakeupListener = this::startNavigating;
private final AlarmManager.OnAlarmListener mTimeoutListener = this::hibernate;
private final AppOpsManager mAppOps;
private final IBatteryStats mBatteryStats;
// Current list of underlying location clients.
// only modified on handler thread
private WorkSource mClientSource = new WorkSource();
private GeofenceHardwareImpl mGeofenceHardwareImpl;
// Volatile for simple inter-thread sync on these values.
private volatile int mHardwareYear = 0;
private volatile String mHardwareModelName;
// Set lower than the current ITAR limit of 600m/s to allow this to trigger even if GPS HAL
// stops output right at 600m/s, depriving this of the information of a device that reaches
// greater than 600m/s, and higher than the speed of sound to avoid impacting most use cases.
private static final float ITAR_SPEED_LIMIT_METERS_PER_SECOND = 400.0F;
private volatile boolean mItarSpeedLimitExceeded = false;
@GuardedBy("mLock")
private final ArrayList<Runnable> mFlushListeners = new ArrayList<>(0);
// GNSS Metrics
private GnssMetrics mGnssMetrics;
private final GnssMetrics mGnssMetrics;
public GnssStatusProvider getGnssStatusProvider() {
return mGnssStatusListenerHelper;
@@ -459,51 +422,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
return mGnssNavigationMessageProvider;
}
private final DeviceIdleInternal.StationaryListener mDeviceIdleStationaryListener =
isStationary -> {
mIsDeviceStationary = isStationary;
// Call updateLowPowerMode on handler thread so it's always called from the same
// thread.
mHandler.sendEmptyMessage(UPDATE_LOW_POWER_MODE);
};
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
if (action == null) {
return;
}
switch (action) {
case ALARM_WAKEUP:
startNavigating();
break;
case ALARM_TIMEOUT:
hibernate();
break;
case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED:
DeviceIdleInternal deviceIdleService = LocalServices.getService(
DeviceIdleInternal.class);
if (mPowerManager.isDeviceIdleMode()) {
deviceIdleService.registerStationaryListener(mDeviceIdleStationaryListener);
} else {
deviceIdleService.unregisterStationaryListener(
mDeviceIdleStationaryListener);
}
// Call updateLowPowerMode on handler thread so it's always called from the
// same thread.
mHandler.sendEmptyMessage(UPDATE_LOW_POWER_MODE);
break;
case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
case TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
subscriptionOrCarrierConfigChanged();
break;
}
}
};
/**
* Implements {@link GnssSatelliteBlocklistCallback#onUpdateSatelliteBlocklist}.
*/
@@ -553,16 +471,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}
}
private void updateLowPowerMode() {
// Disable GPS if we are in device idle mode and the device is stationary.
boolean disableGpsForPowerManager = mPowerManager.isDeviceIdleMode() && mIsDeviceStationary;
if (disableGpsForPowerManager != mDisableGpsForPowerManager) {
mDisableGpsForPowerManager = disableGpsForPowerManager;
updateEnabled();
updateRequirements();
}
}
private void reloadGpsProperties() {
mGnssConfiguration.reloadGpsProperties();
setSuplHostPort();
@@ -581,23 +489,19 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
super(FgThread.getExecutor(), CallerIdentity.fromContext(context));
mContext = context;
mLooper = FgThread.getHandler().getLooper();
// Create a wake lock
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
PowerManager powerManager = Objects.requireNonNull(
mContext.getSystemService(PowerManager.class));
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mWakeLock.setReferenceCounted(true);
// Create a separate wake lock for psds downloader as it may be released due to timeout.
mDownloadPsdsWakeLock = mPowerManager.newWakeLock(
mDownloadPsdsWakeLock = powerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, DOWNLOAD_EXTRA_WAKELOCK_KEY);
mDownloadPsdsWakeLock.setReferenceCounted(true);
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP),
PendingIntent.FLAG_IMMUTABLE);
mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT),
PendingIntent.FLAG_IMMUTABLE);
// App ops service to keep track of who is accessing the GPS
mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -607,7 +511,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
BatteryStats.SERVICE_NAME));
// Construct internal handler
mHandler = new ProviderHandler(mLooper);
mHandler = new ProviderHandler(FgThread.getHandler().getLooper());
// Load GPS configuration and register listeners in the background:
// some operations, such as opening files and registering broadcast receivers, can take a
@@ -623,7 +527,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
// Trigger PSDS data download when the network comes up after booting.
mPendingDownloadPsdsTypes.add(GnssPsdsDownloader.LONG_TERM_PSDS_SERVER_INDEX);
mNetworkConnectivityHandler = new GnssNetworkConnectivityHandler(context,
GnssLocationProvider.this::onNetworkAvailable, mLooper, mNIHandler);
GnssLocationProvider.this::onNetworkAvailable, mHandler.getLooper(), mNIHandler);
mGnssStatusListenerHelper = new GnssStatusProvider(injector);
mGnssMeasurementsProvider = new GnssMeasurementsProvider(injector);
@@ -632,10 +536,10 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(injector);
mGnssMetrics = new GnssMetrics(mContext, mBatteryStats);
mNtpTimeHelper = new NtpTimeHelper(mContext, mLooper, this);
mNtpTimeHelper = new NtpTimeHelper(mContext, mHandler.getLooper(), this);
mGnssSatelliteBlocklistHelper =
new GnssSatelliteBlocklistHelper(mContext,
mLooper, this);
mHandler.getLooper(), this);
mGnssGeofenceProvider = new GnssGeofenceProvider();
setProperties(PROPERTIES);
@@ -664,10 +568,66 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}
}, UserHandle.USER_ALL);
sendMessage(INITIALIZE_HANDLER, 0, null);
mHandler.post(this::handleInitialize);
mHandler.post(mGnssSatelliteBlocklistHelper::updateSatelliteBlocklist);
}
private void handleInitialize() {
// it *appears* that native_init() needs to be called at least once before invoking any
// other gnss methods, so we cycle once on initialization.
native_init();
native_cleanup();
if (native_is_gnss_visibility_control_supported()) {
mGnssVisibilityControl = new GnssVisibilityControl(mContext, mHandler.getLooper(),
mNIHandler);
}
// load default GPS configuration
// (this configuration might change in the future based on SIM changes)
reloadGpsProperties();
// listen for events
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
intentFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
if (action == null) {
return;
}
switch (action) {
case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
case TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
subscriptionOrCarrierConfigChanged();
break;
}
}
}, intentFilter, null, mHandler);
mNetworkConnectivityHandler.registerNetworkCallbacks();
// permanently passively listen to all network locations
LocationManager locationManager = Objects.requireNonNull(
mContext.getSystemService(LocationManager.class));
if (locationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
new LocationRequest.Builder(LocationRequest.PASSIVE_INTERVAL)
.setMinUpdateIntervalMillis(0)
.setHiddenFromAppOps(true)
.build(),
DIRECT_EXECUTOR,
this::injectLocation);
}
updateEnabled();
}
/**
* Implements {@link InjectNtpTimeCallback#injectTime}
*/
@@ -712,19 +672,20 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
LocationManager locationManager = (LocationManager) mContext.getSystemService(
Context.LOCATION_SERVICE);
String provider;
LocationChangeListener locationListener;
LocationListener locationListener;
LocationRequest.Builder locationRequest = new LocationRequest.Builder(
LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS);
LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS).setMaxUpdates(1);
if (independentFromGnss) {
// For fast GNSS TTFF
// For fast GNSS TTFF - we use an empty listener because we will rely on the passive
// network listener to actually inject the location. this prevents double injection
provider = LocationManager.NETWORK_PROVIDER;
locationListener = mNetworkLocationListener;
locationListener = location -> { };
locationRequest.setQuality(LocationRequest.QUALITY_LOW_POWER);
} else {
// For Device-Based Hybrid (E911)
provider = LocationManager.FUSED_PROVIDER;
locationListener = mFusedLocationListener;
locationListener = this::injectBestLocation;
locationRequest.setQuality(LocationRequest.QUALITY_HIGH_ACCURACY);
}
@@ -739,31 +700,26 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}
}
locationRequest.setDurationMillis(durationMillis);
Log.i(TAG,
String.format(
"GNSS HAL Requesting location updates from %s provider for %d millis.",
provider, durationMillis));
try {
locationManager.requestLocationUpdates(provider, locationRequest.build(),
new HandlerExecutor(mHandler), locationListener);
locationListener.mNumLocationUpdateRequest++;
mHandler.postDelayed(() -> {
if (--locationListener.mNumLocationUpdateRequest == 0) {
Log.i(TAG,
String.format("Removing location updates from %s provider.", provider));
locationManager.removeUpdates(locationListener);
}
}, durationMillis);
} catch (IllegalArgumentException e) {
Log.w(TAG, "Unable to request location.", e);
}
locationManager.requestLocationUpdates(provider, locationRequest.build(),
DIRECT_EXECUTOR, locationListener);
}
private void injectBestLocation(Location location) {
if (DEBUG) {
Log.d(TAG, "injectBestLocation: " + location);
}
if (location.isFromMockProvider()) {
return;
}
int gnssLocationFlags = LOCATION_HAS_LAT_LONG
| (location.hasAltitude() ? LOCATION_HAS_ALTITUDE : 0)
| (location.hasSpeed() ? LOCATION_HAS_SPEED : 0)
@@ -864,10 +820,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}
private void injectLocation(Location location) {
if (location.hasAccuracy()) {
if (DEBUG) {
Log.d(TAG, "injectLocation: " + location);
}
if (location.hasAccuracy() && !location.isFromMockProvider()) {
native_inject_location(location.getLatitude(), location.getLongitude(),
location.getAccuracy());
}
@@ -954,6 +907,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
mGnssVisibilityControl.onGpsEnabledChanged(/* isEnabled= */ false);
}
// do this before releasing wakelock
native_cleanup_batching();
native_cleanup();
}
@@ -962,10 +916,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
boolean enabled = mContext.getSystemService(LocationManager.class)
.isLocationEnabledForUser(UserHandle.CURRENT);
// ... but disable if PowerManager overrides
enabled &= !mDisableGpsForPowerManager;
// .. but enable anyway, if there's an active settings-ignored request
// .. but enable anyway, if there's an active settings-ignored request (e.g. ELS)
enabled |= (mProviderRequest != null
&& mProviderRequest.isActive()
&& mProviderRequest.isLocationSettingsIgnored());
@@ -1016,10 +967,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
@Override
public void onSetRequest(ProviderRequest request) {
sendMessage(SET_REQUEST, 0, request);
}
private void handleSetRequest(ProviderRequest request) {
mProviderRequest = request;
updateEnabled();
updateRequirements();
@@ -1037,7 +984,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
updateClientUids(mProviderRequest.getWorkSource());
mFixInterval = (int) mProviderRequest.getIntervalMillis();
mLowPowerMode = mProviderRequest.isLowPower();
// check for overflow
if (mFixInterval != mProviderRequest.getIntervalMillis()) {
Log.w(TAG, "interval overflow: " + mProviderRequest.getIntervalMillis());
@@ -1066,7 +1012,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
// change period and/or lowPowerMode
if (!setPositionMode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
mFixInterval, mLowPowerMode)) {
mFixInterval, mProviderRequest.isLowPower())) {
Log.e(TAG, "set_position_mode failed in updateRequirements");
}
} else if (!mStarted) {
@@ -1074,18 +1020,18 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
startNavigating();
} else {
// GNSS Engine is already ON, but no GPS_CAPABILITY_SCHEDULING
mAlarmManager.cancel(mTimeoutIntent);
mAlarmManager.cancel(mTimeoutListener);
if (mFixInterval >= NO_FIX_TIMEOUT) {
// set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
// and our fix interval is not short
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, TAG,
mTimeoutListener, mHandler);
}
}
}
} else {
updateClientUids(new WorkSource());
stopNavigating();
stopBatching();
}
@@ -1123,6 +1069,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
// (2) Inform AppOps service about the list of changes to UIDs.
// TODO: this doesn't seem correct, work chain attribution tag != package?
List<WorkChain>[] diffs = WorkSource.diffChains(mClientSource, source);
if (diffs != null) {
List<WorkChain> newChains = diffs[0];
@@ -1146,6 +1093,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}
// Update the flat UIDs and names list and inform app-ops of all changes.
// TODO: why is GnssLocationProvider the only component using these deprecated APIs?
WorkSource[] changes = mClientSource.setReturningDiffs(source);
if (changes != null) {
WorkSource newWork = changes[0];
@@ -1171,23 +1119,17 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
@Override
public void onExtraCommand(int uid, int pid, String command, Bundle extras) {
final long identity = Binder.clearCallingIdentity();
try {
if ("delete_aiding_data".equals(command)) {
deleteAidingData(extras);
} else if ("force_time_injection".equals(command)) {
requestUtcTime();
} else if ("force_psds_injection".equals(command)) {
if (mSupportsPsds) {
downloadPsdsData(/* psdsType= */
GnssPsdsDownloader.LONG_TERM_PSDS_SERVER_INDEX);
}
} else {
Log.w(TAG, "sendExtraCommand: unknown command " + command);
if ("delete_aiding_data".equals(command)) {
deleteAidingData(extras);
} else if ("force_time_injection".equals(command)) {
requestUtcTime();
} else if ("force_psds_injection".equals(command)) {
if (mSupportsPsds) {
downloadPsdsData(/* psdsType= */
GnssPsdsDownloader.LONG_TERM_PSDS_SERVER_INDEX);
}
} finally {
Binder.restoreCallingIdentity(identity);
} else {
Log.w(TAG, "sendExtraCommand: unknown command " + command);
}
}
@@ -1258,9 +1200,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}
int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
mLowPowerMode = mProviderRequest.isLowPower();
if (!setPositionMode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
interval, mLowPowerMode)) {
interval, mProviderRequest.isLowPower())) {
setStarted(false);
Log.e(TAG, "set_position_mode failed in startNavigating()");
return;
@@ -1279,7 +1220,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
// and our fix interval is not short
if (mFixInterval >= NO_FIX_TIMEOUT) {
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, TAG, mTimeoutListener,
mHandler);
}
}
}
@@ -1297,8 +1239,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
// reset SV count to zero
mLocationExtras.reset();
}
mAlarmManager.cancel(mTimeoutIntent);
mAlarmManager.cancel(mWakeupIntent);
mAlarmManager.cancel(mTimeoutListener);
mAlarmManager.cancel(mWakeupListener);
}
private void startBatching() {
@@ -1331,7 +1273,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
// stop GPS until our next fix interval arrives
stopNavigating();
long now = SystemClock.elapsedRealtime();
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent);
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, TAG,
mWakeupListener, mHandler);
}
private boolean hasCapability(int capability) {
@@ -1409,7 +1352,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
// slow.
// As we just recievied a location, we'll cancel that timer.
if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
mAlarmManager.cancel(mTimeoutIntent);
mAlarmManager.cancel(mTimeoutListener);
}
}
@@ -1428,11 +1371,10 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
case GPS_STATUS_SESSION_BEGIN:
mNavigating = true;
break;
case GPS_STATUS_SESSION_END:
mNavigating = false;
break;
case GPS_STATUS_ENGINE_ON:
break;
case GPS_STATUS_SESSION_END:
// fall through
case GPS_STATUS_ENGINE_OFF:
mNavigating = false;
break;
@@ -1626,7 +1568,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
* @hide
*/
public GnssMetricsProvider getGnssMetricsProvider() {
return () -> mGnssMetrics.dumpGnssMetricsAsProtoString();
return mGnssMetrics::dumpGnssMetricsAsProtoString;
}
/**
@@ -1959,9 +1901,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
public void handleMessage(Message msg) {
int message = msg.what;
switch (message) {
case SET_REQUEST:
handleSetRequest((ProviderRequest) msg.obj);
break;
case INJECT_NTP_TIME:
mNtpTimeHelper.retrieveAndInjectNtpTime();
break;
@@ -1971,18 +1910,12 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
case DOWNLOAD_PSDS_DATA:
handleDownloadPsdsData(msg.arg1);
break;
case INITIALIZE_HANDLER:
handleInitialize();
break;
case REPORT_LOCATION:
handleReportLocation(msg.arg1 == 1, (Location) msg.obj);
break;
case REPORT_SV_STATUS:
handleReportSvStatus((GnssStatus) msg.obj);
break;
case UPDATE_LOW_POWER_MODE:
updateLowPowerMode();
break;
}
if (msg.arg2 == 1) {
// wakelock was taken for this message, release it
@@ -1993,70 +1926,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}
}
}
/**
* This method is bound to the constructor. It is in charge of loading properties and
* registering for events that will be posted to this handler.
*/
private void handleInitialize() {
// it *appears* that native_init() needs to be called at least once before invoking any
// other gnss methods, so we cycle once on initialization.
native_init();
native_cleanup();
if (native_is_gnss_visibility_control_supported()) {
mGnssVisibilityControl = new GnssVisibilityControl(mContext, mLooper, mNIHandler);
}
// load default GPS configuration
// (this configuration might change in the future based on SIM changes)
reloadGpsProperties();
// listen for events
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ALARM_WAKEUP);
intentFilter.addAction(ALARM_TIMEOUT);
intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
intentFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
mNetworkConnectivityHandler.registerNetworkCallbacks();
// listen for PASSIVE_PROVIDER updates
LocationManager locManager =
(LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
locManager.requestLocationUpdates(
LocationManager.PASSIVE_PROVIDER,
new LocationRequest.Builder(0)
.setHiddenFromAppOps(true)
.build(),
new HandlerExecutor(this),
new NetworkLocationListener());
updateEnabled();
}
}
private abstract static class LocationChangeListener implements LocationListener {
private int mNumLocationUpdateRequest;
}
private final class NetworkLocationListener extends LocationChangeListener {
@Override
public void onLocationChanged(Location location) {
// this callback happens on mHandler looper
if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
injectLocation(location);
}
}
}
private final class FusedLocationListener extends LocationChangeListener {
@Override
public void onLocationChanged(Location location) {
injectBestLocation(location);
}
}
/**
@@ -2064,16 +1933,12 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
*/
private String messageIdAsString(int message) {
switch (message) {
case SET_REQUEST:
return "SET_REQUEST";
case INJECT_NTP_TIME:
return "INJECT_NTP_TIME";
case REQUEST_LOCATION:
return "REQUEST_LOCATION";
case DOWNLOAD_PSDS_DATA:
return "DOWNLOAD_PSDS_DATA";
case INITIALIZE_HANDLER:
return "INITIALIZE_HANDLER";
case REPORT_LOCATION:
return "REPORT_LOCATION";
case REPORT_SV_STATUS:
@@ -2109,8 +1974,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
s.append("mBatchingStarted=").append(mBatchingStarted).append('\n');
s.append("mBatchSize=").append(getBatchSize()).append('\n');
s.append("mFixInterval=").append(mFixInterval).append('\n');
s.append("mLowPowerMode=").append(mLowPowerMode).append('\n');
s.append("mDisableGpsForPowerManager=").append(mDisableGpsForPowerManager).append('\n');
s.append("mTopHalCapabilities=0x").append(Integer.toHexString(mTopHalCapabilities));
s.append(" ( ");
if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHEDULING ");

View File

@@ -22,6 +22,8 @@ import static android.os.PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF
import static android.os.PowerManager.LOCATION_MODE_NO_CHANGE;
import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
import static com.android.server.location.LocationManagerService.D;
import android.annotation.Nullable;
import android.location.LocationRequest;
import android.location.util.identity.CallerIdentity;
@@ -29,14 +31,13 @@ import android.os.Build;
import android.os.PowerManager.LocationPowerSaveMode;
import com.android.internal.location.ProviderRequest;
import com.android.server.location.LocationManagerService;
import com.android.server.utils.eventlog.LocalEventLog;
/** In memory event log for location events. */
public class LocationEventLog extends LocalEventLog {
private static int getLogSize() {
if (Build.IS_DEBUGGABLE || LocationManagerService.D) {
if (Build.IS_DEBUGGABLE || D) {
return 500;
} else {
return 200;
@@ -91,13 +92,17 @@ public class LocationEventLog extends LocalEventLog {
/** Logs a new incoming location for a location provider. */
public synchronized void logProviderReceivedLocations(String provider, int numLocations) {
addLogEvent(EVENT_PROVIDER_RECEIVE_LOCATION, provider, numLocations);
if (Build.IS_DEBUGGABLE || D) {
addLogEvent(EVENT_PROVIDER_RECEIVE_LOCATION, provider, numLocations);
}
}
/** Logs a location deliver for a client of a location provider. */
public synchronized void logProviderDeliveredLocations(String provider, int numLocations,
CallerIdentity identity) {
addLogEvent(EVENT_PROVIDER_DELIVER_LOCATION, provider, numLocations, identity);
if (Build.IS_DEBUGGABLE || D) {
addLogEvent(EVENT_PROVIDER_DELIVER_LOCATION, provider, numLocations, identity);
}
}
/** Logs that the location power save mode has changed. */