1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.location.gnss; 18 19 import android.Manifest; 20 import android.annotation.Nullable; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.hardware.location.GeofenceHardware; 24 import android.hardware.location.GeofenceHardwareImpl; 25 import android.location.FusedBatchOptions; 26 import android.location.GnssAntennaInfo; 27 import android.location.GnssCapabilities; 28 import android.location.GnssMeasurementCorrections; 29 import android.location.GnssMeasurementRequest; 30 import android.location.IGnssAntennaInfoListener; 31 import android.location.IGnssMeasurementsListener; 32 import android.location.IGnssNavigationMessageListener; 33 import android.location.IGnssNmeaListener; 34 import android.location.IGnssStatusListener; 35 import android.location.IGpsGeofenceHardware; 36 import android.location.Location; 37 import android.location.LocationManager; 38 import android.location.util.identity.CallerIdentity; 39 import android.os.BatteryStats; 40 import android.os.Binder; 41 import android.os.RemoteException; 42 import android.os.ServiceManager; 43 import android.os.UserHandle; 44 import android.util.IndentingPrintWriter; 45 import android.util.Log; 46 47 import com.android.internal.app.IBatteryStats; 48 import com.android.server.FgThread; 49 import com.android.server.location.gnss.hal.GnssNative; 50 import com.android.server.location.injector.Injector; 51 52 import java.io.FileDescriptor; 53 import java.util.List; 54 55 /** Manages Gnss providers and related Gnss functions for LocationManagerService. */ 56 public class GnssManagerService { 57 58 public static final String TAG = "GnssManager"; 59 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG); 60 61 private static final String ATTRIBUTION_ID = "GnssService"; 62 63 final Context mContext; 64 private final GnssNative mGnssNative; 65 66 private final GnssLocationProvider mGnssLocationProvider; 67 private final GnssStatusProvider mGnssStatusProvider; 68 private final GnssNmeaProvider mGnssNmeaProvider; 69 private final GnssMeasurementsProvider mGnssMeasurementsProvider; 70 private final GnssNavigationMessageProvider mGnssNavigationMessageProvider; 71 private final GnssAntennaInfoProvider mGnssAntennaInfoProvider; 72 private final IGpsGeofenceHardware mGnssGeofenceProxy; 73 74 private final GnssGeofenceHalModule mGeofenceHalModule; 75 private final GnssCapabilitiesHalModule mCapabilitiesHalModule; 76 77 private final GnssMetrics mGnssMetrics; 78 GnssManagerService(Context context, Injector injector, GnssNative gnssNative)79 public GnssManagerService(Context context, Injector injector, GnssNative gnssNative) { 80 mContext = context.createAttributionContext(ATTRIBUTION_ID); 81 mGnssNative = gnssNative; 82 83 mGnssMetrics = new GnssMetrics(mContext, IBatteryStats.Stub.asInterface( 84 ServiceManager.getService(BatteryStats.SERVICE_NAME)), mGnssNative); 85 86 mGnssLocationProvider = new GnssLocationProvider(mContext, injector, mGnssNative, 87 mGnssMetrics); 88 mGnssStatusProvider = new GnssStatusProvider(injector, mGnssNative); 89 mGnssNmeaProvider = new GnssNmeaProvider(injector, mGnssNative); 90 mGnssMeasurementsProvider = new GnssMeasurementsProvider(injector, mGnssNative); 91 mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(injector, mGnssNative); 92 mGnssAntennaInfoProvider = new GnssAntennaInfoProvider(mGnssNative); 93 mGnssGeofenceProxy = new GnssGeofenceProxy(mGnssNative); 94 95 mGeofenceHalModule = new GnssGeofenceHalModule(mGnssNative); 96 mCapabilitiesHalModule = new GnssCapabilitiesHalModule(mGnssNative); 97 98 // allow gnss access to begin - we must assume that callbacks can start immediately 99 mGnssNative.register(); 100 } 101 102 /** Called when system is ready. */ onSystemReady()103 public void onSystemReady() { 104 mGnssLocationProvider.onSystemReady(); 105 } 106 107 /** Retrieve the GnssLocationProvider. */ getGnssLocationProvider()108 public GnssLocationProvider getGnssLocationProvider() { 109 return mGnssLocationProvider; 110 } 111 112 /** 113 * Set whether the GnssLocationProvider is suspended on the device. This method was added to 114 * help support power management use cases on automotive devices. 115 */ setAutomotiveGnssSuspended(boolean suspended)116 public void setAutomotiveGnssSuspended(boolean suspended) { 117 mGnssLocationProvider.setAutomotiveGnssSuspended(suspended); 118 } 119 120 /** 121 * Return whether the GnssLocationProvider is suspended or not. This method was added to 122 * help support power management use cases on automotive devices. 123 */ isAutomotiveGnssSuspended()124 public boolean isAutomotiveGnssSuspended() { 125 return mGnssLocationProvider.isAutomotiveGnssSuspended(); 126 } 127 128 /** Retrieve the IGpsGeofenceHardware. */ getGnssGeofenceProxy()129 public IGpsGeofenceHardware getGnssGeofenceProxy() { 130 return mGnssGeofenceProxy; 131 } 132 133 /** 134 * Get year of GNSS hardware. 135 */ getGnssYearOfHardware()136 public int getGnssYearOfHardware() { 137 return mGnssNative.getHardwareYear(); 138 } 139 140 /** 141 * Get model name of GNSS hardware. 142 */ 143 @Nullable getGnssHardwareModelName()144 public String getGnssHardwareModelName() { 145 return mGnssNative.getHardwareModelName(); 146 } 147 148 /** 149 * Get GNSS hardware capabilities. 150 */ getGnssCapabilities()151 public GnssCapabilities getGnssCapabilities() { 152 return mGnssNative.getCapabilities(); 153 } 154 155 /** 156 * Get GNSS antenna information. 157 */ getGnssAntennaInfos()158 public @Nullable List<GnssAntennaInfo> getGnssAntennaInfos() { 159 return mGnssAntennaInfoProvider.getAntennaInfos(); 160 } 161 162 /** 163 * Get size of GNSS batch (GNSS location results are batched together for power savings). 164 */ getGnssBatchSize()165 public int getGnssBatchSize() { 166 return mGnssLocationProvider.getBatchSize(); 167 } 168 169 /** 170 * Registers listener for GNSS status changes. 171 */ registerGnssStatusCallback(IGnssStatusListener listener, String packageName, @Nullable String attributionTag, String listenerId)172 public void registerGnssStatusCallback(IGnssStatusListener listener, String packageName, 173 @Nullable String attributionTag, String listenerId) { 174 mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); 175 176 CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag, 177 listenerId); 178 mGnssStatusProvider.addListener(identity, listener); 179 } 180 181 /** 182 * Unregisters listener for GNSS status changes. 183 */ unregisterGnssStatusCallback(IGnssStatusListener listener)184 public void unregisterGnssStatusCallback(IGnssStatusListener listener) { 185 mGnssStatusProvider.removeListener(listener); 186 } 187 188 /** 189 * Registers listener for GNSS NMEA messages. 190 */ registerGnssNmeaCallback(IGnssNmeaListener listener, String packageName, @Nullable String attributionTag, String listenerId)191 public void registerGnssNmeaCallback(IGnssNmeaListener listener, String packageName, 192 @Nullable String attributionTag, String listenerId) { 193 mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); 194 195 CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag, 196 listenerId); 197 mGnssNmeaProvider.addListener(identity, listener); 198 } 199 200 /** 201 * Unregisters listener for GNSS NMEA messages. 202 */ unregisterGnssNmeaCallback(IGnssNmeaListener listener)203 public void unregisterGnssNmeaCallback(IGnssNmeaListener listener) { 204 mGnssNmeaProvider.removeListener(listener); 205 } 206 207 /** 208 * Adds a GNSS measurements listener. 209 */ addGnssMeasurementsListener(GnssMeasurementRequest request, IGnssMeasurementsListener listener, String packageName, @Nullable String attributionTag, String listenerId)210 public void addGnssMeasurementsListener(GnssMeasurementRequest request, 211 IGnssMeasurementsListener listener, String packageName, 212 @Nullable String attributionTag, String listenerId) { 213 mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); 214 if (request.isCorrelationVectorOutputsEnabled()) { 215 mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null); 216 } 217 CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag, 218 listenerId); 219 mGnssMeasurementsProvider.addListener(request, identity, listener); 220 } 221 222 /** 223 * Injects GNSS measurement corrections. 224 */ injectGnssMeasurementCorrections(GnssMeasurementCorrections corrections)225 public void injectGnssMeasurementCorrections(GnssMeasurementCorrections corrections) { 226 mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null); 227 mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); 228 229 if (!mGnssNative.injectMeasurementCorrections(corrections)) { 230 Log.w(TAG, "failed to inject GNSS measurement corrections"); 231 } 232 } 233 234 /** 235 * Removes a GNSS measurements listener. 236 */ removeGnssMeasurementsListener(IGnssMeasurementsListener listener)237 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) { 238 mGnssMeasurementsProvider.removeListener(listener); 239 } 240 241 /** 242 * Adds a GNSS navigation message listener. 243 */ addGnssNavigationMessageListener(IGnssNavigationMessageListener listener, String packageName, @Nullable String attributionTag, String listenerId)244 public void addGnssNavigationMessageListener(IGnssNavigationMessageListener listener, 245 String packageName, @Nullable String attributionTag, String listenerId) { 246 mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); 247 248 CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag, 249 listenerId); 250 mGnssNavigationMessageProvider.addListener(identity, listener); 251 } 252 253 /** 254 * Removes a GNSS navigation message listener. 255 */ removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener)256 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) { 257 mGnssNavigationMessageProvider.removeListener(listener); 258 } 259 260 /** 261 * Adds a GNSS antenna info listener. 262 */ addGnssAntennaInfoListener(IGnssAntennaInfoListener listener, String packageName, @Nullable String attributionTag, String listenerId)263 public void addGnssAntennaInfoListener(IGnssAntennaInfoListener listener, String packageName, 264 @Nullable String attributionTag, String listenerId) { 265 266 CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag, 267 listenerId); 268 mGnssAntennaInfoProvider.addListener(identity, listener); 269 } 270 271 /** 272 * Removes a GNSS antenna info listener. 273 */ removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener)274 public void removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener) { 275 mGnssAntennaInfoProvider.removeListener(listener); 276 } 277 278 /** 279 * Send Ni Response, indicating a location request initiated by a network carrier. 280 */ sendNiResponse(int notifId, int userResponse)281 public void sendNiResponse(int notifId, int userResponse) { 282 try { 283 mGnssLocationProvider.getNetInitiatedListener().sendNiResponse(notifId, userResponse); 284 } catch (RemoteException e) { 285 throw e.rethrowFromSystemServer(); 286 } 287 } 288 289 /** 290 * Dump info for debugging. 291 */ dump(FileDescriptor fd, IndentingPrintWriter ipw, String[] args)292 public void dump(FileDescriptor fd, IndentingPrintWriter ipw, String[] args) { 293 if (args.length > 0 && args[0].equals("--gnssmetrics")) { 294 ipw.append(mGnssMetrics.dumpGnssMetricsAsProtoString()); 295 return; 296 } 297 298 ipw.println("Capabilities: " + mGnssNative.getCapabilities()); 299 300 if (mGnssStatusProvider.isSupported()) { 301 ipw.println("Status Provider:"); 302 ipw.increaseIndent(); 303 mGnssStatusProvider.dump(fd, ipw, args); 304 ipw.decreaseIndent(); 305 } 306 307 if (mGnssMeasurementsProvider.isSupported()) { 308 ipw.println("Measurements Provider:"); 309 ipw.increaseIndent(); 310 mGnssMeasurementsProvider.dump(fd, ipw, args); 311 ipw.decreaseIndent(); 312 } 313 314 if (mGnssNavigationMessageProvider.isSupported()) { 315 ipw.println("Navigation Message Provider:"); 316 ipw.increaseIndent(); 317 mGnssNavigationMessageProvider.dump(fd, ipw, args); 318 ipw.decreaseIndent(); 319 } 320 321 if (mGnssAntennaInfoProvider.isSupported()) { 322 ipw.println("Antenna Info Provider:"); 323 ipw.increaseIndent(); 324 ipw.println("Antenna Infos: " + mGnssAntennaInfoProvider.getAntennaInfos()); 325 mGnssAntennaInfoProvider.dump(fd, ipw, args); 326 ipw.decreaseIndent(); 327 } 328 329 GnssPowerStats powerStats = mGnssNative.getPowerStats(); 330 if (powerStats != null) { 331 ipw.println("Last Power Stats:"); 332 ipw.increaseIndent(); 333 powerStats.dump(fd, ipw, args, mGnssNative.getCapabilities()); 334 ipw.decreaseIndent(); 335 } 336 } 337 338 private class GnssCapabilitiesHalModule implements GnssNative.BaseCallbacks { 339 GnssCapabilitiesHalModule(GnssNative gnssNative)340 GnssCapabilitiesHalModule(GnssNative gnssNative) { 341 gnssNative.addBaseCallbacks(this); 342 } 343 344 @Override onHalRestarted()345 public void onHalRestarted() {} 346 347 @Override onCapabilitiesChanged(GnssCapabilities oldCapabilities, GnssCapabilities newCapabilities)348 public void onCapabilitiesChanged(GnssCapabilities oldCapabilities, 349 GnssCapabilities newCapabilities) { 350 final long ident = Binder.clearCallingIdentity(); 351 try { 352 Intent intent = new Intent(LocationManager.ACTION_GNSS_CAPABILITIES_CHANGED) 353 .putExtra(LocationManager.EXTRA_GNSS_CAPABILITIES, newCapabilities) 354 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) 355 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 356 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 357 } finally { 358 Binder.restoreCallingIdentity(ident); 359 } 360 } 361 } 362 363 private class GnssGeofenceHalModule implements GnssNative.GeofenceCallbacks { 364 365 private GeofenceHardwareImpl mGeofenceHardwareImpl; 366 GnssGeofenceHalModule(GnssNative gnssNative)367 GnssGeofenceHalModule(GnssNative gnssNative) { 368 gnssNative.setGeofenceCallbacks(this); 369 } 370 getGeofenceHardware()371 private synchronized GeofenceHardwareImpl getGeofenceHardware() { 372 if (mGeofenceHardwareImpl == null) { 373 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 374 } 375 return mGeofenceHardwareImpl; 376 } 377 378 @Override onReportGeofenceTransition(int geofenceId, Location location, @GeofenceTransition int transition, long timestamp)379 public void onReportGeofenceTransition(int geofenceId, Location location, 380 @GeofenceTransition int transition, long timestamp) { 381 FgThread.getHandler().post(() -> getGeofenceHardware().reportGeofenceTransition( 382 geofenceId, location, transition, timestamp, 383 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE, 384 FusedBatchOptions.SourceTechnologies.GNSS)); 385 } 386 387 @Override onReportGeofenceStatus(@eofenceAvailability int status, Location location)388 public void onReportGeofenceStatus(@GeofenceAvailability int status, Location location) { 389 FgThread.getHandler().post(() -> { 390 int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE; 391 if (status == GEOFENCE_AVAILABILITY_AVAILABLE) { 392 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE; 393 } 394 getGeofenceHardware().reportGeofenceMonitorStatus( 395 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE, 396 monitorStatus, 397 location, 398 FusedBatchOptions.SourceTechnologies.GNSS); 399 }); 400 } 401 402 @Override onReportGeofenceAddStatus(int geofenceId, @GeofenceStatus int status)403 public void onReportGeofenceAddStatus(int geofenceId, @GeofenceStatus int status) { 404 FgThread.getHandler().post(() -> getGeofenceHardware().reportGeofenceAddStatus( 405 geofenceId, translateGeofenceStatus(status))); 406 } 407 408 @Override onReportGeofenceRemoveStatus(int geofenceId, @GeofenceStatus int status)409 public void onReportGeofenceRemoveStatus(int geofenceId, @GeofenceStatus int status) { 410 FgThread.getHandler().post(() -> getGeofenceHardware().reportGeofenceRemoveStatus( 411 geofenceId, translateGeofenceStatus(status))); 412 } 413 414 @Override onReportGeofencePauseStatus(int geofenceId, @GeofenceStatus int status)415 public void onReportGeofencePauseStatus(int geofenceId, @GeofenceStatus int status) { 416 FgThread.getHandler().post(() -> getGeofenceHardware().reportGeofencePauseStatus( 417 geofenceId, translateGeofenceStatus(status))); 418 } 419 420 @Override onReportGeofenceResumeStatus(int geofenceId, @GeofenceStatus int status)421 public void onReportGeofenceResumeStatus(int geofenceId, @GeofenceStatus int status) { 422 FgThread.getHandler().post(() -> getGeofenceHardware().reportGeofenceResumeStatus( 423 geofenceId, translateGeofenceStatus(status))); 424 } 425 translateGeofenceStatus(@eofenceStatus int status)426 private int translateGeofenceStatus(@GeofenceStatus int status) { 427 switch (status) { 428 case GEOFENCE_STATUS_OPERATION_SUCCESS: 429 return GeofenceHardware.GEOFENCE_SUCCESS; 430 case GEOFENCE_STATUS_ERROR_GENERIC: 431 return GeofenceHardware.GEOFENCE_FAILURE; 432 case GEOFENCE_STATUS_ERROR_ID_EXISTS: 433 return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS; 434 case GEOFENCE_STATUS_ERROR_INVALID_TRANSITION: 435 return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION; 436 case GEOFENCE_STATUS_ERROR_TOO_MANY_GEOFENCES: 437 return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES; 438 case GEOFENCE_STATUS_ERROR_ID_UNKNOWN: 439 return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN; 440 default: 441 return -1; 442 } 443 } 444 } 445 } 446