• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     /** Retrieve the IGpsGeofenceHardware. */
getGnssGeofenceProxy()113     public IGpsGeofenceHardware getGnssGeofenceProxy() {
114         return mGnssGeofenceProxy;
115     }
116 
117     /**
118      * Get year of GNSS hardware.
119      */
getGnssYearOfHardware()120     public int getGnssYearOfHardware() {
121         return mGnssNative.getHardwareYear();
122     }
123 
124     /**
125      * Get model name of GNSS hardware.
126      */
127     @Nullable
getGnssHardwareModelName()128     public String getGnssHardwareModelName() {
129         return mGnssNative.getHardwareModelName();
130     }
131 
132     /**
133      * Get GNSS hardware capabilities.
134      */
getGnssCapabilities()135     public GnssCapabilities getGnssCapabilities() {
136         return mGnssNative.getCapabilities();
137     }
138 
139     /**
140      * Get GNSS antenna information.
141      */
getGnssAntennaInfos()142     public @Nullable List<GnssAntennaInfo> getGnssAntennaInfos() {
143         return mGnssAntennaInfoProvider.getAntennaInfos();
144     }
145 
146     /**
147      * Get size of GNSS batch (GNSS location results are batched together for power savings).
148      */
getGnssBatchSize()149     public int getGnssBatchSize() {
150         return mGnssLocationProvider.getBatchSize();
151     }
152 
153     /**
154      * Registers listener for GNSS status changes.
155      */
registerGnssStatusCallback(IGnssStatusListener listener, String packageName, @Nullable String attributionTag, String listenerId)156     public void registerGnssStatusCallback(IGnssStatusListener listener, String packageName,
157             @Nullable String attributionTag, String listenerId) {
158         mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
159 
160         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
161                 listenerId);
162         mGnssStatusProvider.addListener(identity, listener);
163     }
164 
165     /**
166      * Unregisters listener for GNSS status changes.
167      */
unregisterGnssStatusCallback(IGnssStatusListener listener)168     public void unregisterGnssStatusCallback(IGnssStatusListener listener) {
169         mGnssStatusProvider.removeListener(listener);
170     }
171 
172     /**
173      * Registers listener for GNSS NMEA messages.
174      */
registerGnssNmeaCallback(IGnssNmeaListener listener, String packageName, @Nullable String attributionTag, String listenerId)175     public void registerGnssNmeaCallback(IGnssNmeaListener listener, String packageName,
176             @Nullable String attributionTag, String listenerId) {
177         mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
178 
179         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
180                 listenerId);
181         mGnssNmeaProvider.addListener(identity, listener);
182     }
183 
184     /**
185      * Unregisters listener for GNSS NMEA messages.
186      */
unregisterGnssNmeaCallback(IGnssNmeaListener listener)187     public void unregisterGnssNmeaCallback(IGnssNmeaListener listener) {
188         mGnssNmeaProvider.removeListener(listener);
189     }
190 
191     /**
192      * Adds a GNSS measurements listener.
193      */
addGnssMeasurementsListener(GnssMeasurementRequest request, IGnssMeasurementsListener listener, String packageName, @Nullable String attributionTag, String listenerId)194     public void addGnssMeasurementsListener(GnssMeasurementRequest request,
195             IGnssMeasurementsListener listener, String packageName,
196             @Nullable String attributionTag, String listenerId) {
197         mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
198         if (request.isCorrelationVectorOutputsEnabled()) {
199             mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
200         }
201         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
202                 listenerId);
203         mGnssMeasurementsProvider.addListener(request, identity, listener);
204     }
205 
206     /**
207      * Injects GNSS measurement corrections.
208      */
injectGnssMeasurementCorrections(GnssMeasurementCorrections corrections)209     public void injectGnssMeasurementCorrections(GnssMeasurementCorrections corrections) {
210         mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
211         mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
212 
213         if (!mGnssNative.injectMeasurementCorrections(corrections)) {
214             Log.w(TAG, "failed to inject GNSS measurement corrections");
215         }
216     }
217 
218     /**
219      * Removes a GNSS measurements listener.
220      */
removeGnssMeasurementsListener(IGnssMeasurementsListener listener)221     public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
222         mGnssMeasurementsProvider.removeListener(listener);
223     }
224 
225     /**
226      * Adds a GNSS navigation message listener.
227      */
addGnssNavigationMessageListener(IGnssNavigationMessageListener listener, String packageName, @Nullable String attributionTag, String listenerId)228     public void addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
229             String packageName, @Nullable String attributionTag, String listenerId) {
230         mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
231 
232         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
233                 listenerId);
234         mGnssNavigationMessageProvider.addListener(identity, listener);
235     }
236 
237     /**
238      * Removes a GNSS navigation message listener.
239      */
removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener)240     public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
241         mGnssNavigationMessageProvider.removeListener(listener);
242     }
243 
244     /**
245      * Adds a GNSS antenna info listener.
246      */
addGnssAntennaInfoListener(IGnssAntennaInfoListener listener, String packageName, @Nullable String attributionTag, String listenerId)247     public void addGnssAntennaInfoListener(IGnssAntennaInfoListener listener, String packageName,
248             @Nullable String attributionTag, String listenerId) {
249 
250         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
251                 listenerId);
252         mGnssAntennaInfoProvider.addListener(identity, listener);
253     }
254 
255     /**
256      * Removes a GNSS antenna info listener.
257      */
removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener)258     public void removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener) {
259         mGnssAntennaInfoProvider.removeListener(listener);
260     }
261 
262     /**
263      * Send Ni Response, indicating a location request initiated by a network carrier.
264      */
sendNiResponse(int notifId, int userResponse)265     public void sendNiResponse(int notifId, int userResponse) {
266         try {
267             mGnssLocationProvider.getNetInitiatedListener().sendNiResponse(notifId, userResponse);
268         } catch (RemoteException e) {
269             throw e.rethrowFromSystemServer();
270         }
271     }
272 
273     /**
274      * Dump info for debugging.
275      */
dump(FileDescriptor fd, IndentingPrintWriter ipw, String[] args)276     public void dump(FileDescriptor fd, IndentingPrintWriter ipw, String[] args) {
277         if (args.length > 0 && args[0].equals("--gnssmetrics")) {
278             ipw.append(mGnssMetrics.dumpGnssMetricsAsProtoString());
279             return;
280         }
281 
282         ipw.println("Capabilities: " + mGnssNative.getCapabilities());
283 
284         if (mGnssStatusProvider.isSupported()) {
285             ipw.println("Status Provider:");
286             ipw.increaseIndent();
287             mGnssStatusProvider.dump(fd, ipw, args);
288             ipw.decreaseIndent();
289         }
290 
291         if (mGnssMeasurementsProvider.isSupported()) {
292             ipw.println("Measurements Provider:");
293             ipw.increaseIndent();
294             mGnssMeasurementsProvider.dump(fd, ipw, args);
295             ipw.decreaseIndent();
296         }
297 
298         if (mGnssNavigationMessageProvider.isSupported()) {
299             ipw.println("Navigation Message Provider:");
300             ipw.increaseIndent();
301             mGnssNavigationMessageProvider.dump(fd, ipw, args);
302             ipw.decreaseIndent();
303         }
304 
305         if (mGnssAntennaInfoProvider.isSupported()) {
306             ipw.println("Navigation Message Provider:");
307             ipw.increaseIndent();
308             ipw.println("Antenna Infos: " + mGnssAntennaInfoProvider.getAntennaInfos());
309             mGnssAntennaInfoProvider.dump(fd, ipw, args);
310             ipw.decreaseIndent();
311         }
312 
313         GnssPowerStats powerStats = mGnssNative.getPowerStats();
314         if (powerStats != null) {
315             ipw.println("Last Power Stats:");
316             ipw.increaseIndent();
317             powerStats.dump(fd, ipw, args, mGnssNative.getCapabilities());
318             ipw.decreaseIndent();
319         }
320     }
321 
322     private class GnssCapabilitiesHalModule implements GnssNative.BaseCallbacks {
323 
GnssCapabilitiesHalModule(GnssNative gnssNative)324         GnssCapabilitiesHalModule(GnssNative gnssNative) {
325             gnssNative.addBaseCallbacks(this);
326         }
327 
328         @Override
onHalRestarted()329         public void onHalRestarted() {}
330 
331         @Override
onCapabilitiesChanged(GnssCapabilities oldCapabilities, GnssCapabilities newCapabilities)332         public void onCapabilitiesChanged(GnssCapabilities oldCapabilities,
333                 GnssCapabilities newCapabilities) {
334             long ident = Binder.clearCallingIdentity();
335             try {
336                 Intent intent = new Intent(LocationManager.ACTION_GNSS_CAPABILITIES_CHANGED)
337                         .putExtra(LocationManager.EXTRA_GNSS_CAPABILITIES, newCapabilities)
338                         .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
339                         .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
340                 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
341             } finally {
342                 Binder.restoreCallingIdentity(ident);
343             }
344         }
345     }
346 
347     private class GnssGeofenceHalModule implements GnssNative.GeofenceCallbacks {
348 
349         private GeofenceHardwareImpl mGeofenceHardwareImpl;
350 
GnssGeofenceHalModule(GnssNative gnssNative)351         GnssGeofenceHalModule(GnssNative gnssNative) {
352             gnssNative.setGeofenceCallbacks(this);
353         }
354 
getGeofenceHardware()355         private synchronized GeofenceHardwareImpl getGeofenceHardware() {
356             if (mGeofenceHardwareImpl == null) {
357                 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
358             }
359             return mGeofenceHardwareImpl;
360         }
361 
362         @Override
onReportGeofenceTransition(int geofenceId, Location location, @GeofenceTransition int transition, long timestamp)363         public void onReportGeofenceTransition(int geofenceId, Location location,
364                 @GeofenceTransition int transition, long timestamp) {
365             FgThread.getHandler().post(() -> getGeofenceHardware().reportGeofenceTransition(
366                     geofenceId, location, transition, timestamp,
367                     GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
368                     FusedBatchOptions.SourceTechnologies.GNSS));
369         }
370 
371         @Override
onReportGeofenceStatus(@eofenceAvailability int status, Location location)372         public void onReportGeofenceStatus(@GeofenceAvailability int status, Location location) {
373             FgThread.getHandler().post(() -> {
374                 int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
375                 if (status == GEOFENCE_AVAILABILITY_AVAILABLE) {
376                     monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
377                 }
378                 getGeofenceHardware().reportGeofenceMonitorStatus(
379                         GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
380                         monitorStatus,
381                         location,
382                         FusedBatchOptions.SourceTechnologies.GNSS);
383             });
384         }
385 
386         @Override
onReportGeofenceAddStatus(int geofenceId, @GeofenceStatus int status)387         public void onReportGeofenceAddStatus(int geofenceId, @GeofenceStatus int status) {
388             FgThread.getHandler().post(() -> getGeofenceHardware().reportGeofenceAddStatus(
389                     geofenceId, translateGeofenceStatus(status)));
390         }
391 
392         @Override
onReportGeofenceRemoveStatus(int geofenceId, @GeofenceStatus int status)393         public void onReportGeofenceRemoveStatus(int geofenceId, @GeofenceStatus int status) {
394             FgThread.getHandler().post(() -> getGeofenceHardware().reportGeofenceRemoveStatus(
395                     geofenceId, translateGeofenceStatus(status)));
396         }
397 
398         @Override
onReportGeofencePauseStatus(int geofenceId, @GeofenceStatus int status)399         public void onReportGeofencePauseStatus(int geofenceId, @GeofenceStatus int status) {
400             FgThread.getHandler().post(() -> getGeofenceHardware().reportGeofencePauseStatus(
401                     geofenceId, translateGeofenceStatus(status)));
402         }
403 
404         @Override
onReportGeofenceResumeStatus(int geofenceId, @GeofenceStatus int status)405         public void onReportGeofenceResumeStatus(int geofenceId, @GeofenceStatus int status) {
406             FgThread.getHandler().post(() -> getGeofenceHardware().reportGeofenceResumeStatus(
407                     geofenceId, translateGeofenceStatus(status)));
408         }
409 
translateGeofenceStatus(@eofenceStatus int status)410         private int translateGeofenceStatus(@GeofenceStatus int status) {
411             switch (status) {
412                 case GEOFENCE_STATUS_OPERATION_SUCCESS:
413                     return GeofenceHardware.GEOFENCE_SUCCESS;
414                 case GEOFENCE_STATUS_ERROR_GENERIC:
415                     return GeofenceHardware.GEOFENCE_FAILURE;
416                 case GEOFENCE_STATUS_ERROR_ID_EXISTS:
417                     return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
418                 case GEOFENCE_STATUS_ERROR_INVALID_TRANSITION:
419                     return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
420                 case GEOFENCE_STATUS_ERROR_TOO_MANY_GEOFENCES:
421                     return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
422                 case GEOFENCE_STATUS_ERROR_ID_UNKNOWN:
423                     return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
424                 default:
425                     return -1;
426             }
427         }
428     }
429 }
430