blob: 6d08c3642988198eb1a813825164ef086b2554ae [file] [log] [blame]
destradaa1af4b022013-07-12 15:43:36 -07001/*
2 * Copyright (C) 2013 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
17package com.android.server.location;
18
destradaab9026982015-08-27 17:34:54 -070019import android.content.Context;
destradaa0682809a2013-08-12 18:50:30 -070020import android.hardware.location.GeofenceHardware;
destradaa1af4b022013-07-12 15:43:36 -070021import android.hardware.location.GeofenceHardwareImpl;
destradaa0682809a2013-08-12 18:50:30 -070022import android.hardware.location.GeofenceHardwareRequestParcelable;
destradaa1af4b022013-07-12 15:43:36 -070023import android.hardware.location.IFusedLocationHardware;
24import android.hardware.location.IFusedLocationHardwareSink;
destradaa1af4b022013-07-12 15:43:36 -070025import android.location.FusedBatchOptions;
destradaab9026982015-08-27 17:34:54 -070026import android.location.IFusedGeofenceHardware;
destradaa1af4b022013-07-12 15:43:36 -070027import android.location.Location;
28import android.location.LocationListener;
29import android.location.LocationManager;
David Christie9e9ce922013-09-12 13:04:32 -070030import android.location.LocationRequest;
destradaa1af4b022013-07-12 15:43:36 -070031import android.os.Bundle;
destradaa64be0c62013-08-09 15:01:49 -070032import android.os.Looper;
destradaa1af4b022013-07-12 15:43:36 -070033import android.os.RemoteException;
34import android.os.SystemClock;
35import android.util.Log;
destradaa1af4b022013-07-12 15:43:36 -070036
37/**
38 * This class is an interop layer for JVM types and the JNI code that interacts
39 * with the FLP HAL implementation.
40 *
41 * {@hide}
42 */
43public class FlpHardwareProvider {
David Christiecfc9b6d2015-04-14 12:14:03 -070044 private static final int FIRST_VERSION_WITH_FLUSH_LOCATIONS = 2;
destradaa1af4b022013-07-12 15:43:36 -070045 private GeofenceHardwareImpl mGeofenceHardwareSink = null;
46 private IFusedLocationHardwareSink mLocationSink = null;
David Christieffca45a2015-04-11 23:15:08 -070047 // Capabilities provided by FlpCallbacks
48 private boolean mHaveBatchingCapabilities;
49 private int mBatchingCapabilities;
David Christie38feb6f2015-05-15 13:23:08 -070050 private int mVersion = 1;
destradaa1af4b022013-07-12 15:43:36 -070051
52 private static FlpHardwareProvider sSingletonInstance = null;
53
54 private final static String TAG = "FlpHardwareProvider";
55 private final Context mContext;
destradaa64be0c62013-08-09 15:01:49 -070056 private final Object mLocationSinkLock = new Object();
destradaa1af4b022013-07-12 15:43:36 -070057
destradaa0682809a2013-08-12 18:50:30 -070058 // FlpHal result codes, they must be equal to the ones in fused_location.h
59 private static final int FLP_RESULT_SUCCESS = 0;
60 private static final int FLP_RESULT_ERROR = -1;
61 private static final int FLP_RESULT_INSUFFICIENT_MEMORY = -2;
62 private static final int FLP_RESULT_TOO_MANY_GEOFENCES = -3;
63 private static final int FLP_RESULT_ID_EXISTS = -4;
64 private static final int FLP_RESULT_ID_UNKNOWN = -5;
65 private static final int FLP_RESULT_INVALID_GEOFENCE_TRANSITION = -6;
66
destradaacc972722014-04-25 11:37:52 -070067 // FlpHal monitor status codes, they must be equal to the ones in fused_location.h
68 private static final int FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE = 1<<0;
69 private static final int FLP_GEOFENCE_MONITOR_STATUS_AVAILABLE = 1<<1;
70
destradaa1af4b022013-07-12 15:43:36 -070071 public static FlpHardwareProvider getInstance(Context context) {
72 if (sSingletonInstance == null) {
73 sSingletonInstance = new FlpHardwareProvider(context);
Zhentao Suna4dfc2c2014-05-12 16:14:47 -070074 sSingletonInstance.nativeInit();
destradaa1af4b022013-07-12 15:43:36 -070075 }
76
77 return sSingletonInstance;
78 }
79
80 private FlpHardwareProvider(Context context) {
81 mContext = context;
82
83 // register for listening for passive provider data
destradaa1af4b022013-07-12 15:43:36 -070084 LocationManager manager = (LocationManager) mContext.getSystemService(
85 Context.LOCATION_SERVICE);
David Christie9e9ce922013-09-12 13:04:32 -070086 final long minTime = 0;
87 final float minDistance = 0;
88 final boolean oneShot = false;
89 LocationRequest request = LocationRequest.createFromDeprecatedProvider(
destradaa1af4b022013-07-12 15:43:36 -070090 LocationManager.PASSIVE_PROVIDER,
David Christie9e9ce922013-09-12 13:04:32 -070091 minTime,
92 minDistance,
93 oneShot);
94 // Don't keep track of this request since it's done on behalf of other clients
95 // (which are kept track of separately).
96 request.setHideFromAppOps(true);
97 manager.requestLocationUpdates(
98 request,
destradaa1af4b022013-07-12 15:43:36 -070099 new NetworkLocationListener(),
destradaa64be0c62013-08-09 15:01:49 -0700100 Looper.myLooper());
destradaa1af4b022013-07-12 15:43:36 -0700101 }
102
destradaa5ce66d82014-05-28 18:24:08 -0700103 public static boolean isSupported() {
destradaa1af4b022013-07-12 15:43:36 -0700104 return nativeIsSupported();
105 }
106
107 /**
108 * Private callback functions used by FLP HAL.
109 */
110 // FlpCallbacks members
111 private void onLocationReport(Location[] locations) {
112 for (Location location : locations) {
113 location.setProvider(LocationManager.FUSED_PROVIDER);
114 // set the elapsed time-stamp just as GPS provider does
115 location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
116 }
117
destradaa64be0c62013-08-09 15:01:49 -0700118 IFusedLocationHardwareSink sink;
119 synchronized (mLocationSinkLock) {
120 sink = mLocationSink;
121 }
destradaa1af4b022013-07-12 15:43:36 -0700122 try {
destradaa64be0c62013-08-09 15:01:49 -0700123 if (sink != null) {
124 sink.onLocationAvailable(locations);
destradaa1af4b022013-07-12 15:43:36 -0700125 }
126 } catch (RemoteException e) {
127 Log.e(TAG, "RemoteException calling onLocationAvailable");
128 }
129 }
130
David Christieffca45a2015-04-11 23:15:08 -0700131 private void onBatchingCapabilities(int capabilities) {
132 synchronized (mLocationSinkLock) {
133 mHaveBatchingCapabilities = true;
134 mBatchingCapabilities = capabilities;
135 }
136
137 maybeSendCapabilities();
David Christiea1a8e7f2015-06-19 16:18:53 -0700138
139 if (mGeofenceHardwareSink != null) {
140 mGeofenceHardwareSink.setVersion(getVersion());
141 }
David Christieffca45a2015-04-11 23:15:08 -0700142 }
143
David Christie15003f12015-04-12 20:57:57 -0700144 private void onBatchingStatus(int status) {
145 IFusedLocationHardwareSink sink;
146 synchronized (mLocationSinkLock) {
147 sink = mLocationSink;
148 }
149 try {
150 if (sink != null) {
151 sink.onStatusChanged(status);
152 }
153 } catch (RemoteException e) {
154 Log.e(TAG, "RemoteException calling onBatchingStatus");
155 }
156 }
157
David Christiea1a8e7f2015-06-19 16:18:53 -0700158 // Returns the current version of the FLP HAL. This depends both on the version of the
159 // structure returned by the hardware layer, and whether or not we've received the
160 // capabilities callback on initialization. Assume original version until we get
161 // the new initialization callback.
162 private int getVersion() {
163 synchronized (mLocationSinkLock) {
164 if (mHaveBatchingCapabilities) {
165 return mVersion;
166 }
167 }
168 return 1;
169 }
170
David Christiecfc9b6d2015-04-14 12:14:03 -0700171 private void setVersion(int version) {
172 mVersion = version;
David Christie38feb6f2015-05-15 13:23:08 -0700173 if (mGeofenceHardwareSink != null) {
David Christiea1a8e7f2015-06-19 16:18:53 -0700174 mGeofenceHardwareSink.setVersion(getVersion());
David Christie38feb6f2015-05-15 13:23:08 -0700175 }
David Christiecfc9b6d2015-04-14 12:14:03 -0700176 }
177
David Christieffca45a2015-04-11 23:15:08 -0700178 private void maybeSendCapabilities() {
179 IFusedLocationHardwareSink sink;
180 boolean haveBatchingCapabilities;
181 int batchingCapabilities;
182 synchronized (mLocationSinkLock) {
183 sink = mLocationSink;
184 haveBatchingCapabilities = mHaveBatchingCapabilities;
185 batchingCapabilities = mBatchingCapabilities;
186 }
187 try {
188 if (sink != null && haveBatchingCapabilities) {
189 sink.onCapabilities(batchingCapabilities);
190 }
191 } catch (RemoteException e) {
192 Log.e(TAG, "RemoteException calling onLocationAvailable");
193 }
194 }
195
destradaa1af4b022013-07-12 15:43:36 -0700196 // FlpDiagnosticCallbacks members
197 private void onDataReport(String data) {
destradaa64be0c62013-08-09 15:01:49 -0700198 IFusedLocationHardwareSink sink;
199 synchronized (mLocationSinkLock) {
200 sink = mLocationSink;
201 }
destradaa1af4b022013-07-12 15:43:36 -0700202 try {
203 if (mLocationSink != null) {
destradaa64be0c62013-08-09 15:01:49 -0700204 sink.onDiagnosticDataAvailable(data);
destradaa1af4b022013-07-12 15:43:36 -0700205 }
206 } catch (RemoteException e) {
207 Log.e(TAG, "RemoteException calling onDiagnosticDataAvailable");
208 }
209 }
210
211 // FlpGeofenceCallbacks members
212 private void onGeofenceTransition(
213 int geofenceId,
214 Location location,
215 int transition,
216 long timestamp,
destradaa0682809a2013-08-12 18:50:30 -0700217 int sourcesUsed) {
destradaacc972722014-04-25 11:37:52 -0700218 // the transition Id does not require translation because the values in fused_location.h
219 // and GeofenceHardware are in sync
destradaa0682809a2013-08-12 18:50:30 -0700220 getGeofenceHardwareSink().reportGeofenceTransition(
221 geofenceId,
222 updateLocationInformation(location),
223 transition,
224 timestamp,
225 GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE,
226 sourcesUsed);
destradaa1af4b022013-07-12 15:43:36 -0700227 }
228
229 private void onGeofenceMonitorStatus(int status, int source, Location location) {
destradaa839904e2013-09-11 12:42:51 -0700230 // allow the location to be optional in this event
231 Location updatedLocation = null;
232 if(location != null) {
233 updatedLocation = updateLocationInformation(location);
234 }
235
destradaacc972722014-04-25 11:37:52 -0700236 int monitorStatus;
237 switch (status) {
238 case FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE:
239 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
240 break;
241 case FLP_GEOFENCE_MONITOR_STATUS_AVAILABLE:
242 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
243 break;
244 default:
245 Log.e(TAG, "Invalid FlpHal Geofence monitor status: " + status);
246 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
247 break;
248 }
249
destradaa0682809a2013-08-12 18:50:30 -0700250 getGeofenceHardwareSink().reportGeofenceMonitorStatus(
251 GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE,
destradaacc972722014-04-25 11:37:52 -0700252 monitorStatus,
destradaa839904e2013-09-11 12:42:51 -0700253 updatedLocation,
destradaa0682809a2013-08-12 18:50:30 -0700254 source);
destradaa1af4b022013-07-12 15:43:36 -0700255 }
256
257 private void onGeofenceAdd(int geofenceId, int result) {
destradaa0682809a2013-08-12 18:50:30 -0700258 getGeofenceHardwareSink().reportGeofenceAddStatus(
259 geofenceId,
260 translateToGeofenceHardwareStatus(result));
destradaa1af4b022013-07-12 15:43:36 -0700261 }
262
263 private void onGeofenceRemove(int geofenceId, int result) {
destradaa0682809a2013-08-12 18:50:30 -0700264 getGeofenceHardwareSink().reportGeofenceRemoveStatus(
265 geofenceId,
266 translateToGeofenceHardwareStatus(result));
destradaa1af4b022013-07-12 15:43:36 -0700267 }
268
269 private void onGeofencePause(int geofenceId, int result) {
destradaa0682809a2013-08-12 18:50:30 -0700270 getGeofenceHardwareSink().reportGeofencePauseStatus(
271 geofenceId,
272 translateToGeofenceHardwareStatus(result));
destradaa1af4b022013-07-12 15:43:36 -0700273 }
274
275 private void onGeofenceResume(int geofenceId, int result) {
destradaa0682809a2013-08-12 18:50:30 -0700276 getGeofenceHardwareSink().reportGeofenceResumeStatus(
277 geofenceId,
278 translateToGeofenceHardwareStatus(result));
destradaa1af4b022013-07-12 15:43:36 -0700279 }
280
David Christieffca45a2015-04-11 23:15:08 -0700281 private void onGeofencingCapabilities(int capabilities) {
282 getGeofenceHardwareSink().onCapabilities(capabilities);
283 }
284
destradaa1af4b022013-07-12 15:43:36 -0700285 /**
286 * Private native methods accessing FLP HAL.
287 */
288 static { nativeClassInit(); }
289
290 // Core members
291 private static native void nativeClassInit();
292 private static native boolean nativeIsSupported();
293
294 // FlpLocationInterface members
Zhentao Suna4dfc2c2014-05-12 16:14:47 -0700295 private native void nativeInit();
destradaa1af4b022013-07-12 15:43:36 -0700296 private native int nativeGetBatchSize();
297 private native void nativeStartBatching(int requestId, FusedBatchOptions options);
298 private native void nativeUpdateBatchingOptions(int requestId, FusedBatchOptions optionsObject);
299 private native void nativeStopBatching(int id);
300 private native void nativeRequestBatchedLocation(int lastNLocations);
David Christiefff30432015-04-12 21:26:02 -0700301 private native void nativeFlushBatchedLocations();
destradaa1af4b022013-07-12 15:43:36 -0700302 private native void nativeInjectLocation(Location location);
destradaa1af4b022013-07-12 15:43:36 -0700303 private native void nativeCleanup();
304
305 // FlpDiagnosticsInterface members
306 private native boolean nativeIsDiagnosticSupported();
307 private native void nativeInjectDiagnosticData(String data);
308
309 // FlpDeviceContextInterface members
310 private native boolean nativeIsDeviceContextSupported();
311 private native void nativeInjectDeviceContext(int deviceEnabledContext);
312
313 // FlpGeofencingInterface members
314 private native boolean nativeIsGeofencingSupported();
destradaa0682809a2013-08-12 18:50:30 -0700315 private native void nativeAddGeofences(
316 GeofenceHardwareRequestParcelable[] geofenceRequestsArray);
destradaa1af4b022013-07-12 15:43:36 -0700317 private native void nativePauseGeofence(int geofenceId);
318 private native void nativeResumeGeofence(int geofenceId, int monitorTransitions);
319 private native void nativeModifyGeofenceOption(
320 int geofenceId,
321 int lastTransition,
322 int monitorTransitions,
323 int notificationResponsiveness,
324 int unknownTimer,
325 int sourcesToUse);
326 private native void nativeRemoveGeofences(int[] geofenceIdsArray);
327
328 /**
329 * Interface implementations for services built on top of this functionality.
330 */
331 public static final String LOCATION = "Location";
332 public static final String GEOFENCING = "Geofencing";
333
334 public IFusedLocationHardware getLocationHardware() {
destradaa1af4b022013-07-12 15:43:36 -0700335 return mLocationHardware;
336 }
337
338 public IFusedGeofenceHardware getGeofenceHardware() {
destradaa1af4b022013-07-12 15:43:36 -0700339 return mGeofenceHardwareService;
340 }
341
destradaab9026982015-08-27 17:34:54 -0700342 public void cleanup() {
343 Log.i(TAG, "Calling nativeCleanup()");
344 nativeCleanup();
345 }
346
destradaa1af4b022013-07-12 15:43:36 -0700347 private final IFusedLocationHardware mLocationHardware = new IFusedLocationHardware.Stub() {
348 @Override
349 public void registerSink(IFusedLocationHardwareSink eventSink) {
destradaa64be0c62013-08-09 15:01:49 -0700350 synchronized (mLocationSinkLock) {
351 // only one sink is allowed at the moment
352 if (mLocationSink != null) {
David Christiedaf35c32014-08-05 14:42:37 -0700353 Log.e(TAG, "Replacing an existing IFusedLocationHardware sink");
destradaa64be0c62013-08-09 15:01:49 -0700354 }
destradaa1af4b022013-07-12 15:43:36 -0700355
destradaa64be0c62013-08-09 15:01:49 -0700356 mLocationSink = eventSink;
357 }
David Christieffca45a2015-04-11 23:15:08 -0700358 maybeSendCapabilities();
destradaa1af4b022013-07-12 15:43:36 -0700359 }
360
361 @Override
362 public void unregisterSink(IFusedLocationHardwareSink eventSink) {
destradaa64be0c62013-08-09 15:01:49 -0700363 synchronized (mLocationSinkLock) {
364 // don't throw if the sink is not registered, simply make it a no-op
365 if (mLocationSink == eventSink) {
366 mLocationSink = null;
367 }
destradaa1af4b022013-07-12 15:43:36 -0700368 }
369 }
370
371 @Override
372 public int getSupportedBatchSize() {
373 return nativeGetBatchSize();
374 }
375
376 @Override
377 public void startBatching(int requestId, FusedBatchOptions options) {
378 nativeStartBatching(requestId, options);
379 }
380
381 @Override
382 public void stopBatching(int requestId) {
383 nativeStopBatching(requestId);
384 }
385
386 @Override
387 public void updateBatchingOptions(int requestId, FusedBatchOptions options) {
388 nativeUpdateBatchingOptions(requestId, options);
389 }
390
391 @Override
392 public void requestBatchOfLocations(int batchSizeRequested) {
393 nativeRequestBatchedLocation(batchSizeRequested);
394 }
395
396 @Override
David Christiefff30432015-04-12 21:26:02 -0700397 public void flushBatchedLocations() {
David Christiea1a8e7f2015-06-19 16:18:53 -0700398 if (getVersion() >= FIRST_VERSION_WITH_FLUSH_LOCATIONS) {
David Christiecfc9b6d2015-04-14 12:14:03 -0700399 nativeFlushBatchedLocations();
400 } else {
401 Log.wtf(TAG,
402 "Tried to call flushBatchedLocations on an unsupported implementation");
403 }
David Christiefff30432015-04-12 21:26:02 -0700404 }
405
406 @Override
destradaa1af4b022013-07-12 15:43:36 -0700407 public boolean supportsDiagnosticDataInjection() {
408 return nativeIsDiagnosticSupported();
409 }
410
411 @Override
412 public void injectDiagnosticData(String data) {
413 nativeInjectDiagnosticData(data);
414 }
415
416 @Override
417 public boolean supportsDeviceContextInjection() {
418 return nativeIsDeviceContextSupported();
419 }
420
421 @Override
422 public void injectDeviceContext(int deviceEnabledContext) {
423 nativeInjectDeviceContext(deviceEnabledContext);
424 }
David Christiecfc9b6d2015-04-14 12:14:03 -0700425
426 @Override
427 public int getVersion() {
David Christiea1a8e7f2015-06-19 16:18:53 -0700428 return FlpHardwareProvider.this.getVersion();
David Christiecfc9b6d2015-04-14 12:14:03 -0700429 }
destradaa1af4b022013-07-12 15:43:36 -0700430 };
431
432 private final IFusedGeofenceHardware mGeofenceHardwareService =
433 new IFusedGeofenceHardware.Stub() {
434 @Override
435 public boolean isSupported() {
436 return nativeIsGeofencingSupported();
437 }
438
439 @Override
destradaa0682809a2013-08-12 18:50:30 -0700440 public void addGeofences(GeofenceHardwareRequestParcelable[] geofenceRequestsArray) {
441 nativeAddGeofences(geofenceRequestsArray);
destradaa1af4b022013-07-12 15:43:36 -0700442 }
443
444 @Override
445 public void removeGeofences(int[] geofenceIds) {
446 nativeRemoveGeofences(geofenceIds);
447 }
448
449 @Override
450 public void pauseMonitoringGeofence(int geofenceId) {
451 nativePauseGeofence(geofenceId);
452 }
453
454 @Override
455 public void resumeMonitoringGeofence(int geofenceId, int monitorTransitions) {
456 nativeResumeGeofence(geofenceId, monitorTransitions);
457 }
458
459 @Override
460 public void modifyGeofenceOptions(int geofenceId,
461 int lastTransition,
462 int monitorTransitions,
463 int notificationResponsiveness,
destradaa0682809a2013-08-12 18:50:30 -0700464 int unknownTimer,
465 int sourcesToUse) {
destradaa1af4b022013-07-12 15:43:36 -0700466 nativeModifyGeofenceOption(
467 geofenceId,
468 lastTransition,
469 monitorTransitions,
470 notificationResponsiveness,
471 unknownTimer,
destradaa0682809a2013-08-12 18:50:30 -0700472 sourcesToUse);
destradaa1af4b022013-07-12 15:43:36 -0700473 }
474 };
475
476 /**
477 * Internal classes and functions used by the provider.
478 */
479 private final class NetworkLocationListener implements LocationListener {
480 @Override
481 public void onLocationChanged(Location location) {
482 if (
483 !LocationManager.NETWORK_PROVIDER.equals(location.getProvider()) ||
484 !location.hasAccuracy()
485 ) {
486 return;
487 }
488
489 nativeInjectLocation(location);
490 }
491
492 @Override
493 public void onStatusChanged(String provider, int status, Bundle extras) { }
494
495 @Override
496 public void onProviderEnabled(String provider) { }
497
498 @Override
499 public void onProviderDisabled(String provider) { }
500 }
501
502 private GeofenceHardwareImpl getGeofenceHardwareSink() {
503 if (mGeofenceHardwareSink == null) {
destradaa1af4b022013-07-12 15:43:36 -0700504 mGeofenceHardwareSink = GeofenceHardwareImpl.getInstance(mContext);
David Christiea1a8e7f2015-06-19 16:18:53 -0700505 mGeofenceHardwareSink.setVersion(getVersion());
destradaa1af4b022013-07-12 15:43:36 -0700506 }
507
508 return mGeofenceHardwareSink;
509 }
destradaa0682809a2013-08-12 18:50:30 -0700510
511 private static int translateToGeofenceHardwareStatus(int flpHalResult) {
512 switch(flpHalResult) {
513 case FLP_RESULT_SUCCESS:
514 return GeofenceHardware.GEOFENCE_SUCCESS;
515 case FLP_RESULT_ERROR:
516 return GeofenceHardware.GEOFENCE_FAILURE;
destradaa17ff2b22014-07-10 12:41:11 -0700517 case FLP_RESULT_INSUFFICIENT_MEMORY:
518 return GeofenceHardware.GEOFENCE_ERROR_INSUFFICIENT_MEMORY;
destradaa0682809a2013-08-12 18:50:30 -0700519 case FLP_RESULT_TOO_MANY_GEOFENCES:
520 return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
521 case FLP_RESULT_ID_EXISTS:
522 return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
523 case FLP_RESULT_ID_UNKNOWN:
524 return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
525 case FLP_RESULT_INVALID_GEOFENCE_TRANSITION:
526 return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
527 default:
528 Log.e(TAG, String.format("Invalid FlpHal result code: %d", flpHalResult));
529 return GeofenceHardware.GEOFENCE_FAILURE;
530 }
531 }
532
533 private Location updateLocationInformation(Location location) {
534 location.setProvider(LocationManager.FUSED_PROVIDER);
535 // set the elapsed time-stamp just as GPS provider does
536 location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
537 return location;
538 }
539}