Merge "Various GNSS cleanups"

This commit is contained in:
Soonil Nagarkar
2020-11-11 05:08:41 +00:00
committed by Android (Google) Code Review
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. */