Merge "GNSS Batching - Default Implementation"
This commit is contained in:
@@ -388,6 +388,7 @@ LOCAL_SRC_FILES += \
|
||||
core/java/com/android/internal/widget/IRemoteViewsAdapterConnection.aidl \
|
||||
keystore/java/android/security/IKeyChainAliasCallback.aidl \
|
||||
keystore/java/android/security/IKeyChainService.aidl \
|
||||
location/java/android/location/IBatchedLocationCallback.aidl \
|
||||
location/java/android/location/ICountryDetector.aidl \
|
||||
location/java/android/location/ICountryListener.aidl \
|
||||
location/java/android/location/IFusedProvider.aidl \
|
||||
|
||||
@@ -21413,6 +21413,11 @@ package android.location {
|
||||
field public static final android.os.Parcelable.Creator<android.location.Address> CREATOR;
|
||||
}
|
||||
|
||||
public abstract class BatchedLocationCallback {
|
||||
ctor public BatchedLocationCallback();
|
||||
method public void onLocationBatch(java.util.List<android.location.Location>);
|
||||
}
|
||||
|
||||
public class Criteria implements android.os.Parcelable {
|
||||
ctor public Criteria();
|
||||
ctor public Criteria(android.location.Criteria);
|
||||
@@ -21951,14 +21956,17 @@ package android.location {
|
||||
method public void clearTestProviderEnabled(java.lang.String);
|
||||
method public void clearTestProviderLocation(java.lang.String);
|
||||
method public void clearTestProviderStatus(java.lang.String);
|
||||
method public void flushGnssBatch();
|
||||
method public java.util.List<java.lang.String> getAllProviders();
|
||||
method public java.lang.String getBestProvider(android.location.Criteria, boolean);
|
||||
method public int getGnssBatchSize();
|
||||
method public deprecated android.location.GpsStatus getGpsStatus(android.location.GpsStatus);
|
||||
method public android.location.Location getLastKnownLocation(java.lang.String);
|
||||
method public android.location.LocationProvider getProvider(java.lang.String);
|
||||
method public java.util.List<java.lang.String> getProviders(boolean);
|
||||
method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
|
||||
method public boolean isProviderEnabled(java.lang.String);
|
||||
method public boolean registerGnssBatchedLocationCallback(long, boolean, android.location.BatchedLocationCallback, android.os.Handler);
|
||||
method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
|
||||
method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
|
||||
method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
|
||||
@@ -21989,6 +21997,7 @@ package android.location {
|
||||
method public void setTestProviderEnabled(java.lang.String, boolean);
|
||||
method public void setTestProviderLocation(java.lang.String, android.location.Location);
|
||||
method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
|
||||
method public boolean unregisterGnssBatchedLocationCallback(android.location.BatchedLocationCallback);
|
||||
method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
|
||||
method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
|
||||
method public void unregisterGnssStatusCallback(android.location.GnssStatus.Callback);
|
||||
|
||||
44
location/java/android/location/BatchedLocationCallback.java
Normal file
44
location/java/android/location/BatchedLocationCallback.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.location;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.SystemApi;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Used for receiving notifications from the LocationManager when
|
||||
* the a batch of location is ready. These methods are called if the
|
||||
* BatchedLocationCallback has been registered with the location manager service
|
||||
* using the
|
||||
* {@link LocationManager#registerGnssBatchedLocationCallback#startGnssBatch(long,
|
||||
* boolean, BatchedLocationCallback, android.os.Handler)} method.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public abstract class BatchedLocationCallback {
|
||||
|
||||
/**
|
||||
* Called when a new batch of locations is ready
|
||||
*
|
||||
* @param locations A list of all new locations (possibly zero of them.)
|
||||
*/
|
||||
public void onLocationBatch(List<Location> locations) {}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package android.location;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A handler class to manage transport callbacks for {@link BatchedLocationCallback}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
class BatchedLocationCallbackTransport
|
||||
extends LocalListenerHelper<BatchedLocationCallback> {
|
||||
private final ILocationManager mLocationManager;
|
||||
|
||||
private final IBatchedLocationCallback mCallbackTransport = new CallbackTransport();
|
||||
|
||||
public BatchedLocationCallbackTransport(Context context, ILocationManager locationManager) {
|
||||
super(context, "BatchedLocationCallbackTransport");
|
||||
mLocationManager = locationManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean registerWithServer() throws RemoteException {
|
||||
return mLocationManager.addGnssBatchingCallback(
|
||||
mCallbackTransport,
|
||||
getContext().getPackageName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void unregisterFromServer() throws RemoteException {
|
||||
mLocationManager.removeGnssBatchingCallback();
|
||||
}
|
||||
|
||||
private class CallbackTransport extends IBatchedLocationCallback.Stub {
|
||||
@Override
|
||||
public void onLocationBatch(final List<Location> locations) {
|
||||
ListenerOperation<BatchedLocationCallback> operation =
|
||||
new ListenerOperation<BatchedLocationCallback>() {
|
||||
@Override
|
||||
public void execute(BatchedLocationCallback callback)
|
||||
throws RemoteException {
|
||||
callback.onLocationBatch(locations);
|
||||
}
|
||||
};
|
||||
foreach(operation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ public final class GnssNavigationMessage implements Parcelable {
|
||||
*/
|
||||
public static abstract class Callback {
|
||||
/**
|
||||
* The status of GNSS measurements event.
|
||||
* The status of GNSS Navigation Message event.
|
||||
* @hide
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
|
||||
29
location/java/android/location/IBatchedLocationCallback.aidl
Normal file
29
location/java/android/location/IBatchedLocationCallback.aidl
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2017, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.location;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
oneway interface IBatchedLocationCallback
|
||||
{
|
||||
void onLocationBatch(in List<Location> locations);
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import android.location.Address;
|
||||
import android.location.Criteria;
|
||||
import android.location.GeocoderParams;
|
||||
import android.location.Geofence;
|
||||
import android.location.IBatchedLocationCallback;
|
||||
import android.location.IGnssMeasurementsListener;
|
||||
import android.location.IGnssStatusListener;
|
||||
import android.location.IGnssNavigationMessageListener;
|
||||
@@ -71,6 +72,13 @@ interface ILocationManager
|
||||
|
||||
int getGnssYearOfHardware();
|
||||
|
||||
int getGnssBatchSize(String packageName);
|
||||
boolean addGnssBatchingCallback(in IBatchedLocationCallback callback, String packageName);
|
||||
void removeGnssBatchingCallback();
|
||||
boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName);
|
||||
void flushGnssBatch(String packageName);
|
||||
boolean stopGnssBatch();
|
||||
|
||||
// --- deprecated ---
|
||||
List<String> getAllProviders();
|
||||
List<String> getProviders(in Criteria criteria, boolean enabledOnly);
|
||||
@@ -99,6 +107,9 @@ interface ILocationManager
|
||||
// it need not be shared with other providers.
|
||||
void reportLocation(in Location location, boolean passive);
|
||||
|
||||
// Used when a (initially Gnss) Location batch arrives
|
||||
void reportLocationBatch(in List<Location> locations);
|
||||
|
||||
// for reporting callback completion
|
||||
void locationCallbackFinished(ILocationListener listener);
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.location;
|
||||
|
||||
import com.android.internal.location.ProviderProperties;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SystemApi;
|
||||
import android.annotation.TestApi;
|
||||
@@ -59,13 +60,15 @@ import static android.Manifest.permission.ACCESS_FINE_LOCATION;
|
||||
* return location results, but the update rate will be throttled and the exact
|
||||
* location will be obfuscated to a coarse level of accuracy.
|
||||
*/
|
||||
public class LocationManager {
|
||||
public class LocationManager
|
||||
{
|
||||
private static final String TAG = "LocationManager";
|
||||
|
||||
private final Context mContext;
|
||||
private final ILocationManager mService;
|
||||
private final GnssMeasurementCallbackTransport mGnssMeasurementCallbackTransport;
|
||||
private final GnssNavigationMessageCallbackTransport mGnssNavigationMessageCallbackTransport;
|
||||
private final BatchedLocationCallbackTransport mBatchedLocationCallbackTransport;
|
||||
private final HashMap<GpsStatus.Listener, GnssStatusListenerTransport> mGpsStatusListeners =
|
||||
new HashMap<>();
|
||||
private final HashMap<GpsStatus.NmeaListener, GnssStatusListenerTransport> mGpsNmeaListeners =
|
||||
@@ -321,9 +324,13 @@ public class LocationManager {
|
||||
public LocationManager(Context context, ILocationManager service) {
|
||||
mService = service;
|
||||
mContext = context;
|
||||
mGnssMeasurementCallbackTransport = new GnssMeasurementCallbackTransport(mContext, mService);
|
||||
mGnssMeasurementCallbackTransport =
|
||||
new GnssMeasurementCallbackTransport(mContext, mService);
|
||||
mGnssNavigationMessageCallbackTransport =
|
||||
new GnssNavigationMessageCallbackTransport(mContext, mService);
|
||||
mBatchedLocationCallbackTransport =
|
||||
new BatchedLocationCallbackTransport(mContext, mService);
|
||||
|
||||
}
|
||||
|
||||
private LocationProvider createProvider(String name, ProviderProperties properties) {
|
||||
@@ -1878,7 +1885,8 @@ public class LocationManager {
|
||||
* No-op method to keep backward-compatibility.
|
||||
* Don't use it. Use {@link #unregisterGnssNavigationMessageCallback} instead.
|
||||
* @hide
|
||||
* @deprecated use {@link #unregisterGnssNavigationMessageCallback(GnssMeasurements.Callback)}
|
||||
* @deprecated use
|
||||
* {@link #unregisterGnssNavigationMessageCallback(GnssNavigationMessage.Callback)}
|
||||
* instead
|
||||
*/
|
||||
@Deprecated
|
||||
@@ -1959,6 +1967,96 @@ public class LocationManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the batch size (in number of Location objects) that are supported by the batching
|
||||
* interface.
|
||||
*
|
||||
* @return Maximum number of location objects that can be returned
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
|
||||
public int getGnssBatchSize() {
|
||||
try {
|
||||
return mService.getGnssBatchSize(mContext.getPackageName());
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start hardware-batching of GNSS locations. This API is primarily used when the AP is
|
||||
* asleep and the device can batch GNSS locations in the hardware.
|
||||
*
|
||||
* Note this is designed (as was the fused location interface before it) for a single user
|
||||
* SystemApi - requests are not consolidated. Care should be taken when the System switches
|
||||
* users that may have different batching requests, to stop hardware batching for one user, and
|
||||
* restart it for the next.
|
||||
*
|
||||
* @param periodNanos Time interval, in nanoseconds, that the GNSS locations are requested
|
||||
* within the batch
|
||||
* @param wakeOnFifoFull True if the hardware batching should flush the locations in a
|
||||
* a callback to the listener, when it's internal buffer is full. If
|
||||
* set to false, the oldest location information is, instead,
|
||||
* dropped when the buffer is full.
|
||||
* @param callback The listener on which to return the batched locations
|
||||
* @param handler The handler on which to process the callback
|
||||
*
|
||||
* @return True if batching was successfully started
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
|
||||
public boolean registerGnssBatchedLocationCallback(long periodNanos, boolean wakeOnFifoFull,
|
||||
BatchedLocationCallback callback, Handler handler) {
|
||||
mBatchedLocationCallbackTransport.add(callback, handler);
|
||||
|
||||
try {
|
||||
return mService.startGnssBatch(periodNanos, wakeOnFifoFull, mContext.getPackageName());
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the batched GNSS locations.
|
||||
* All GNSS locations currently ready in the batch are returned via the callback sent in
|
||||
* startGnssBatch(), and the buffer containing the batched locations is cleared.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
|
||||
public void flushGnssBatch() {
|
||||
try {
|
||||
mService.flushGnssBatch(mContext.getPackageName());
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop batching locations. This API is primarily used when the AP is
|
||||
* asleep and the device can batch locations in the hardware.
|
||||
*
|
||||
* @param callback the specific callback class to remove from the transport layer
|
||||
*
|
||||
* @return True if batching was successfully started
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
|
||||
public boolean unregisterGnssBatchedLocationCallback(BatchedLocationCallback callback) {
|
||||
|
||||
mBatchedLocationCallbackTransport.remove(callback);
|
||||
|
||||
try {
|
||||
return mService.stopGnssBatch();
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends additional commands to a location provider.
|
||||
* Can be used to support provider specific extensions to the Location Manager API
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.annotation.NonNull;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.location.ProviderProperties;
|
||||
@@ -62,6 +63,7 @@ import android.location.Address;
|
||||
import android.location.Criteria;
|
||||
import android.location.GeocoderParams;
|
||||
import android.location.Geofence;
|
||||
import android.location.IBatchedLocationCallback;
|
||||
import android.location.IGnssMeasurementsListener;
|
||||
import android.location.IGnssStatusListener;
|
||||
import android.location.IGnssStatusProvider;
|
||||
@@ -101,6 +103,7 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -229,6 +232,11 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
|
||||
|
||||
private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
|
||||
private IBatchedLocationCallback mGnssBatchingCallback;
|
||||
private LinkedCallback mGnssBatchingDeathCallback;
|
||||
private boolean mGnssBatchingInProgress = false;
|
||||
|
||||
public LocationManagerService(Context context) {
|
||||
super();
|
||||
mContext = context;
|
||||
@@ -545,6 +553,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
|
||||
mLocationHandler.getLooper());
|
||||
mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
|
||||
mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
|
||||
mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
|
||||
mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
|
||||
addProviderLocked(gnssProvider);
|
||||
@@ -1073,13 +1082,197 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
*/
|
||||
@Override
|
||||
public int getGnssYearOfHardware() {
|
||||
if (mGnssNavigationMessageProvider != null) {
|
||||
if (mGnssSystemInfoProvider != null) {
|
||||
return mGnssSystemInfoProvider.getGnssYearOfHardware();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs some checks for GNSS (FINE) level permissions, used by several methods which directly
|
||||
* (try to) access GNSS information at this layer.
|
||||
*/
|
||||
private boolean hasGnssPermissions(String packageName) {
|
||||
int allowedResolutionLevel = getCallerAllowedResolutionLevel();
|
||||
checkResolutionLevelIsSufficientForProviderUse(
|
||||
allowedResolutionLevel,
|
||||
LocationManager.GPS_PROVIDER);
|
||||
|
||||
int pid = Binder.getCallingPid();
|
||||
int uid = Binder.getCallingUid();
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
boolean hasLocationAccess;
|
||||
try {
|
||||
hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
|
||||
return hasLocationAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GNSS batching size, if available.
|
||||
*/
|
||||
@Override
|
||||
public int getGnssBatchSize(String packageName) {
|
||||
mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
|
||||
"Location Hardware permission not granted to access hardware batching");
|
||||
|
||||
if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
|
||||
return mGnssBatchingProvider.getSize();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a callback for GNSS Batching events, if permissions allow, which are transported
|
||||
* to potentially multiple listeners by the BatchedLocationCallbackTransport above this.
|
||||
*/
|
||||
@Override
|
||||
public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
|
||||
mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
|
||||
"Location Hardware permission not granted to access hardware batching");
|
||||
|
||||
if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mGnssBatchingCallback = callback;
|
||||
mGnssBatchingDeathCallback = new LinkedCallback(callback);
|
||||
try {
|
||||
callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
|
||||
} catch (RemoteException e) {
|
||||
// if the remote process registering the listener is already dead, just swallow the
|
||||
// exception and return
|
||||
Log.e(TAG, "Remote listener already died.", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private class LinkedCallback implements IBinder.DeathRecipient {
|
||||
private final IBatchedLocationCallback mCallback;
|
||||
|
||||
public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public IBatchedLocationCallback getUnderlyingListener() {
|
||||
return mCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void binderDied() {
|
||||
Log.d(TAG, "Remote Batching Callback died: " + mCallback);
|
||||
stopGnssBatch();
|
||||
removeGnssBatchingCallback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes callback for GNSS batching
|
||||
*/
|
||||
@Override
|
||||
public void removeGnssBatchingCallback() {
|
||||
try {
|
||||
mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
|
||||
0 /* flags */);
|
||||
} catch (NoSuchElementException e) {
|
||||
// if the death callback isn't connected (it should be...), log error, swallow the
|
||||
// exception and return
|
||||
Log.e(TAG, "Couldn't unlink death callback.", e);
|
||||
}
|
||||
mGnssBatchingCallback = null;
|
||||
mGnssBatchingDeathCallback = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Starts GNSS batching, if available.
|
||||
*/
|
||||
@Override
|
||||
public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
|
||||
mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
|
||||
"Location Hardware permission not granted to access hardware batching");
|
||||
|
||||
if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mGnssBatchingInProgress) {
|
||||
// Current design does not expect multiple starts to be called repeatedly
|
||||
Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
|
||||
// Try to clean up anyway, and continue
|
||||
stopGnssBatch();
|
||||
}
|
||||
|
||||
mGnssBatchingInProgress = true;
|
||||
return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes a GNSS batch in progress
|
||||
*/
|
||||
@Override
|
||||
public void flushGnssBatch(String packageName) {
|
||||
mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
|
||||
"Location Hardware permission not granted to access hardware batching");
|
||||
|
||||
if (!hasGnssPermissions(packageName)) {
|
||||
Log.e(TAG, "flushGnssBatch called without GNSS permissions");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mGnssBatchingInProgress) {
|
||||
Log.w(TAG, "flushGnssBatch called with no batch in progress");
|
||||
}
|
||||
|
||||
if (mGnssBatchingProvider != null) {
|
||||
mGnssBatchingProvider.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops GNSS batching
|
||||
*/
|
||||
@Override
|
||||
public boolean stopGnssBatch() {
|
||||
mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
|
||||
"Location Hardware permission not granted to access hardware batching");
|
||||
|
||||
if (mGnssBatchingProvider != null) {
|
||||
mGnssBatchingInProgress = false;
|
||||
return mGnssBatchingProvider.stop();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportLocationBatch(List<Location> locations) {
|
||||
checkCallerIsProvider();
|
||||
|
||||
// Currently used only for GNSS locations - update permissions check if changed
|
||||
if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
|
||||
if (mGnssBatchingCallback == null) {
|
||||
Slog.e(TAG, "reportLocationBatch() called without active Callback");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mGnssBatchingCallback.onLocationBatch(locations);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
|
||||
}
|
||||
} else {
|
||||
Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked");
|
||||
}
|
||||
}
|
||||
|
||||
private void addProviderLocked(LocationProviderInterface provider) {
|
||||
mProviders.add(provider);
|
||||
mProvidersByName.put(provider.getName(), provider);
|
||||
@@ -2000,22 +2193,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
@Override
|
||||
public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
|
||||
int allowedResolutionLevel = getCallerAllowedResolutionLevel();
|
||||
checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
|
||||
LocationManager.GPS_PROVIDER);
|
||||
|
||||
final int pid = Binder.getCallingPid();
|
||||
final int uid = Binder.getCallingUid();
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (!checkLocationAccess(pid, uid, packageName, allowedResolutionLevel)) {
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
|
||||
if (mGnssStatusProvider == null) {
|
||||
if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2043,22 +2221,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
public boolean addGnssMeasurementsListener(
|
||||
IGnssMeasurementsListener listener,
|
||||
String packageName) {
|
||||
int allowedResolutionLevel = getCallerAllowedResolutionLevel();
|
||||
checkResolutionLevelIsSufficientForProviderUse(
|
||||
allowedResolutionLevel,
|
||||
LocationManager.GPS_PROVIDER);
|
||||
|
||||
int pid = Binder.getCallingPid();
|
||||
int uid = Binder.getCallingUid();
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
boolean hasLocationAccess;
|
||||
try {
|
||||
hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
|
||||
if (!hasLocationAccess || mGnssMeasurementsProvider == null) {
|
||||
if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
|
||||
return false;
|
||||
}
|
||||
return mGnssMeasurementsProvider.addListener(listener);
|
||||
@@ -2075,22 +2238,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
public boolean addGnssNavigationMessageListener(
|
||||
IGnssNavigationMessageListener listener,
|
||||
String packageName) {
|
||||
int allowedResolutionLevel = getCallerAllowedResolutionLevel();
|
||||
checkResolutionLevelIsSufficientForProviderUse(
|
||||
allowedResolutionLevel,
|
||||
LocationManager.GPS_PROVIDER);
|
||||
|
||||
int pid = Binder.getCallingPid();
|
||||
int uid = Binder.getCallingUid();
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
boolean hasLocationAccess;
|
||||
try {
|
||||
hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
|
||||
if (!hasLocationAccess || mGnssNavigationMessageProvider == null) {
|
||||
if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
|
||||
return false;
|
||||
}
|
||||
return mGnssNavigationMessageProvider.addListener(listener);
|
||||
@@ -2866,6 +3014,9 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
pw.println(":");
|
||||
provider.dump(fd, pw, args);
|
||||
}
|
||||
if (mGnssBatchingInProgress) {
|
||||
pw.println(" GNSS batching in progress");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,6 @@ import android.os.WorkSource;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Telephony.Carriers;
|
||||
import android.provider.Telephony.Sms.Intents;
|
||||
import android.telephony.SmsMessage;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
|
||||
import android.telephony.TelephonyManager;
|
||||
@@ -82,17 +81,17 @@ import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.NtpTrustedTime;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
import java.util.Map;
|
||||
@@ -411,7 +410,6 @@ public class GnssLocationProvider implements LocationProviderInterface {
|
||||
private WorkSource mClientSource = new WorkSource();
|
||||
|
||||
private GeofenceHardwareImpl mGeofenceHardwareImpl;
|
||||
|
||||
private int mYearOfHardware = 0;
|
||||
|
||||
// Set lower than the current ITAR limit of 600m/s to allow this to trigger even if GPS HAL
|
||||
@@ -1125,6 +1123,7 @@ public class GnssLocationProvider implements LocationProviderInterface {
|
||||
|
||||
mGnssMeasurementsProvider.onGpsEnabledChanged();
|
||||
mGnssNavigationMessageProvider.onGpsEnabledChanged();
|
||||
enableBatching();
|
||||
} else {
|
||||
synchronized (mLock) {
|
||||
mEnabled = false;
|
||||
@@ -1156,6 +1155,7 @@ public class GnssLocationProvider implements LocationProviderInterface {
|
||||
mAlarmManager.cancel(mWakeupIntent);
|
||||
mAlarmManager.cancel(mTimeoutIntent);
|
||||
|
||||
disableBatching();
|
||||
// do this before releasing wakelock
|
||||
native_cleanup();
|
||||
|
||||
@@ -1791,6 +1791,84 @@ public class GnssLocationProvider implements LocationProviderInterface {
|
||||
};
|
||||
}
|
||||
|
||||
public interface GnssBatchingProvider {
|
||||
/**
|
||||
* Returns the GNSS batching size
|
||||
*/
|
||||
int getSize();
|
||||
/**
|
||||
* Starts the hardware batching operation
|
||||
*/
|
||||
boolean start(long periodNanos, boolean wakeOnFifoFull);
|
||||
/**
|
||||
* Forces a flush of existing locations from the hardware batching
|
||||
*/
|
||||
void flush();
|
||||
/**
|
||||
* Stops the batching operation
|
||||
*/
|
||||
boolean stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public GnssBatchingProvider getGnssBatchingProvider() {
|
||||
return new GnssBatchingProvider() {
|
||||
@Override
|
||||
public int getSize() {
|
||||
return native_get_batch_size();
|
||||
}
|
||||
@Override
|
||||
public boolean start(long periodNanos, boolean wakeOnFifoFull) {
|
||||
if (periodNanos <= 0) {
|
||||
Log.e(TAG, "Invalid periodNanos " + periodNanos +
|
||||
"in batching request, not started");
|
||||
return false;
|
||||
}
|
||||
return native_start_batch(periodNanos, wakeOnFifoFull);
|
||||
}
|
||||
@Override
|
||||
public void flush() {
|
||||
native_flush_batch();
|
||||
}
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return native_stop_batch();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Batching if enabled
|
||||
*/
|
||||
private void enableBatching() {
|
||||
if (!native_init_batching()) {
|
||||
Log.e(TAG, "Failed to initialize GNSS batching");
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable batching
|
||||
*/
|
||||
private void disableBatching() {
|
||||
native_stop_batch();
|
||||
native_cleanup_batching();
|
||||
}
|
||||
|
||||
/**
|
||||
* called from native code - GNSS location batch callback
|
||||
*/
|
||||
private void reportLocationBatch(Location[] locationArray) {
|
||||
List<Location> locations = new ArrayList<>(Arrays.asList(locationArray));
|
||||
if(DEBUG) { Log.d(TAG, "Location batch of size " + locationArray.length + "reported"); }
|
||||
try {
|
||||
mILocationManager.reportLocationBatch(locations);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "RemoteException calling reportLocationBatch");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* called from native code to request XTRA data
|
||||
*/
|
||||
@@ -2117,7 +2195,10 @@ public class GnssLocationProvider implements LocationProviderInterface {
|
||||
// note that this assumes the message will not be removed from the queue before
|
||||
// it is handled (otherwise the wake lock would be leaked).
|
||||
mWakeLock.acquire();
|
||||
Log.i(TAG, "WakeLock acquired by sendMessage(" + message + ", " + arg + ", " + obj + ")");
|
||||
if (Log.isLoggable(TAG, Log.INFO)) {
|
||||
Log.i(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg
|
||||
+ ", " + obj + ")");
|
||||
}
|
||||
mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
|
||||
}
|
||||
|
||||
@@ -2175,8 +2256,10 @@ public class GnssLocationProvider implements LocationProviderInterface {
|
||||
if (msg.arg2 == 1) {
|
||||
// wakelock was taken for this message, release it
|
||||
mWakeLock.release();
|
||||
Log.i(TAG, "WakeLock released by handleMessage(" + message + ", " + msg.arg1 + ", "
|
||||
+ msg.obj + ")");
|
||||
if (Log.isLoggable(TAG, Log.INFO)) {
|
||||
Log.i(TAG, "WakeLock released by handleMessage(" + messageIdAsString(message)
|
||||
+ ", " + msg.arg1 + ", " + msg.obj + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2424,6 +2507,40 @@ public class GnssLocationProvider implements LocationProviderInterface {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A string representing the given message ID.
|
||||
*/
|
||||
private String messageIdAsString(int message) {
|
||||
switch (message) {
|
||||
case ENABLE:
|
||||
return "ENABLE";
|
||||
case SET_REQUEST:
|
||||
return "SET_REQUEST";
|
||||
case UPDATE_NETWORK_STATE:
|
||||
return "UPDATE_NETWORK_STATE";
|
||||
case REQUEST_SUPL_CONNECTION:
|
||||
return "REQUEST_SUPL_CONNECTION";
|
||||
case RELEASE_SUPL_CONNECTION:
|
||||
return "RELEASE_SUPL_CONNECTION";
|
||||
case INJECT_NTP_TIME:
|
||||
return "INJECT_NTP_TIME";
|
||||
case DOWNLOAD_XTRA_DATA:
|
||||
return "DOWNLOAD_XTRA_DATA";
|
||||
case INJECT_NTP_TIME_FINISHED:
|
||||
return "INJECT_NTP_TIME_FINISHED";
|
||||
case DOWNLOAD_XTRA_DATA_FINISHED:
|
||||
return "DOWNLOAD_XTRA_DATA_FINISHED";
|
||||
case UPDATE_LOCATION:
|
||||
return "UPDATE_LOCATION";
|
||||
case SUBSCRIPTION_OR_SIM_CHANGED:
|
||||
return "SUBSCRIPTION_OR_SIM_CHANGED";
|
||||
case INITIALIZE_HANDLER:
|
||||
return "INITIALIZE_HANDLER";
|
||||
default:
|
||||
return "<Unknown>";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
StringBuilder s = new StringBuilder();
|
||||
@@ -2441,7 +2558,9 @@ public class GnssLocationProvider implements LocationProviderInterface {
|
||||
if (hasCapability(GPS_CAPABILITY_NAV_MESSAGES)) s.append("NAV_MESSAGES ");
|
||||
s.append(")\n");
|
||||
|
||||
s.append(native_get_internal_state());
|
||||
s.append(" internal state: ").append(native_get_internal_state());
|
||||
s.append("\n");
|
||||
|
||||
pw.append(s);
|
||||
}
|
||||
|
||||
@@ -2562,4 +2681,12 @@ public class GnssLocationProvider implements LocationProviderInterface {
|
||||
private static native boolean native_set_gps_lock(int gpsLock);
|
||||
private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn);
|
||||
|
||||
// GNSS Batching
|
||||
private static native int native_get_batch_size();
|
||||
private static native boolean native_start_batch(long periodNanos, boolean wakeOnFifoFull);
|
||||
private static native void native_flush_batch();
|
||||
private static native boolean native_stop_batch();
|
||||
private static native boolean native_init_batching();
|
||||
private static native void native_cleanup_batching();
|
||||
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ static jmethodID method_reportGeofencePauseStatus;
|
||||
static jmethodID method_reportGeofenceResumeStatus;
|
||||
static jmethodID method_reportMeasurementData;
|
||||
static jmethodID method_reportNavigationMessages;
|
||||
static jmethodID method_reportLocationBatch;
|
||||
|
||||
/*
|
||||
* Save a pointer to JavaVm to attach/detach threads executing
|
||||
@@ -80,6 +81,8 @@ using android::hardware::gnss::V1_0::IAGnssCallback;
|
||||
using android::hardware::gnss::V1_0::IAGnssRil;
|
||||
using android::hardware::gnss::V1_0::IAGnssRilCallback;
|
||||
using android::hardware::gnss::V1_0::IGnss;
|
||||
using android::hardware::gnss::V1_0::IGnssBatching;
|
||||
using android::hardware::gnss::V1_0::IGnssBatchingCallback;
|
||||
using android::hardware::gnss::V1_0::IGnssCallback;
|
||||
using android::hardware::gnss::V1_0::IGnssConfiguration;
|
||||
using android::hardware::gnss::V1_0::IGnssDebug;
|
||||
@@ -100,6 +103,7 @@ sp<IGnssXtra> gnssXtraIface = nullptr;
|
||||
sp<IAGnssRil> agnssRilIface = nullptr;
|
||||
sp<IGnssGeofencing> gnssGeofencingIface = nullptr;
|
||||
sp<IAGnss> agnssIface = nullptr;
|
||||
sp<IGnssBatching> gnssBatchingIface = nullptr;
|
||||
sp<IGnssDebug> gnssDebugIface = nullptr;
|
||||
sp<IGnssConfiguration> gnssConfigurationIface = nullptr;
|
||||
sp<IGnssNi> gnssNiIface = nullptr;
|
||||
@@ -139,6 +143,7 @@ void JavaMethodHelper<T>::callJavaMethod(
|
||||
class JavaObject {
|
||||
public:
|
||||
JavaObject(JNIEnv* env, const char* class_name);
|
||||
JavaObject(JNIEnv* env, const char* class_name, const char * sz_arg_1);
|
||||
virtual ~JavaObject();
|
||||
|
||||
template<class T>
|
||||
@@ -159,6 +164,12 @@ JavaObject::JavaObject(JNIEnv* env, const char* class_name) : env_(env) {
|
||||
object_ = env_->NewObject(clazz_, ctor);
|
||||
}
|
||||
|
||||
JavaObject::JavaObject(JNIEnv* env, const char* class_name, const char * sz_arg_1) : env_(env) {
|
||||
clazz_ = env_->FindClass(class_name);
|
||||
jmethodID ctor = env->GetMethodID(clazz_, "<init>", "(Ljava/lang/String;)V");
|
||||
object_ = env_->NewObject(clazz_, ctor, env->NewStringUTF(sz_arg_1));
|
||||
}
|
||||
|
||||
JavaObject::~JavaObject() {
|
||||
env_->DeleteLocalRef(clazz_);
|
||||
}
|
||||
@@ -591,6 +602,7 @@ Return<void> GnssNavigationMessageCallback::gnssNavigationMessageCb(
|
||||
env->CallVoidMethod(mCallbacksObj,
|
||||
method_reportNavigationMessages,
|
||||
navigationMessage);
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
env->DeleteLocalRef(navigationMessage);
|
||||
return Void();
|
||||
}
|
||||
@@ -925,6 +937,81 @@ Return<void> AGnssRilCallback::requestRefLocCb() {
|
||||
return Void();
|
||||
}
|
||||
|
||||
/*
|
||||
* GnssBatchingCallback interface implements the callback methods
|
||||
* required by the IGnssBatching interface.
|
||||
*/
|
||||
struct GnssBatchingCallback : public IGnssBatchingCallback {
|
||||
/*
|
||||
* Methods from ::android::hardware::gps::V1_0::IGnssBatchingCallback
|
||||
* follow.
|
||||
*/
|
||||
Return<void> gnssLocationBatchCb(
|
||||
const ::android::hardware::hidl_vec<hardware::gnss::V1_0::GnssLocation> & locations)
|
||||
override;
|
||||
private:
|
||||
jobject translateLocation(
|
||||
JNIEnv* env, const hardware::gnss::V1_0::GnssLocation* location);
|
||||
};
|
||||
|
||||
Return<void> GnssBatchingCallback::gnssLocationBatchCb(
|
||||
const ::android::hardware::hidl_vec<hardware::gnss::V1_0::GnssLocation> & locations) {
|
||||
JNIEnv* env = getJniEnv();
|
||||
|
||||
jobjectArray jLocations = env->NewObjectArray(locations.size(),
|
||||
env->FindClass("android/location/Location"), nullptr);
|
||||
|
||||
for (uint16_t i = 0; i < locations.size(); ++i) {
|
||||
jobject jLocation = translateLocation(env, &locations[i]);
|
||||
env->SetObjectArrayElement(jLocations, i, jLocation);
|
||||
env->DeleteLocalRef(jLocation);
|
||||
}
|
||||
|
||||
env->CallVoidMethod(mCallbacksObj, method_reportLocationBatch, jLocations);
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
|
||||
env->DeleteLocalRef(jLocations);
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
// TODO: Use this common code to translate location for Geofencing and regular Location
|
||||
jobject GnssBatchingCallback::translateLocation(
|
||||
JNIEnv* env, const hardware::gnss::V1_0::GnssLocation* location) {
|
||||
JavaObject object(env, "android/location/Location", "gps");
|
||||
|
||||
uint16_t flags = static_cast<uint32_t>(location->gnssLocationFlags);
|
||||
if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_LAT_LONG) {
|
||||
SET(Latitude, location->latitudeDegrees);
|
||||
SET(Longitude, location->longitudeDegrees);
|
||||
}
|
||||
if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_ALTITUDE) {
|
||||
SET(Altitude, location->altitudeMeters);
|
||||
}
|
||||
if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_SPEED) {
|
||||
SET(Speed, location->speedMetersPerSec);
|
||||
}
|
||||
if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_BEARING) {
|
||||
SET(Bearing, location->bearingDegrees);
|
||||
}
|
||||
if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
|
||||
SET(Accuracy, location->horizontalAccuracyMeters);
|
||||
}
|
||||
if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
|
||||
SET(VerticalAccuracyMeters, location->verticalAccuracyMeters);
|
||||
}
|
||||
if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_SPEED_ACCURACY) {
|
||||
SET(SpeedAccuracyMetersPerSecond, location->speedAccuracyMetersPerSecond);
|
||||
}
|
||||
if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_BEARING_ACCURACY) {
|
||||
SET(BearingAccuracyDegrees, location->bearingAccuracyDegrees);
|
||||
}
|
||||
SET(Time, location->timestamp);
|
||||
|
||||
return object.get();
|
||||
}
|
||||
|
||||
|
||||
static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
|
||||
method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFFFFJ)V");
|
||||
method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
|
||||
@@ -959,6 +1046,10 @@ static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env,
|
||||
clazz,
|
||||
"reportNavigationMessage",
|
||||
"(Landroid/location/GnssNavigationMessage;)V");
|
||||
method_reportLocationBatch = env->GetMethodID(
|
||||
clazz,
|
||||
"reportLocationBatch",
|
||||
"([Landroid/location/Location;)V");
|
||||
|
||||
/*
|
||||
* Save a pointer to JVM.
|
||||
@@ -1033,6 +1124,13 @@ static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env,
|
||||
} else {
|
||||
gnssGeofencingIface = gnssGeofencing;
|
||||
}
|
||||
|
||||
auto gnssBatching = gnssHal->getExtensionGnssBatching();
|
||||
if (!gnssBatching.isOk()) {
|
||||
ALOGD("Unable to get a handle to gnssBatching");
|
||||
} else {
|
||||
gnssBatchingIface = gnssBatching;
|
||||
}
|
||||
} else {
|
||||
ALOGE("Unable to get GPS service\n");
|
||||
}
|
||||
@@ -1704,6 +1802,67 @@ static jboolean android_location_GnssLocationProvider_set_gnss_pos_protocol_sele
|
||||
}
|
||||
}
|
||||
|
||||
static jint android_location_GnssLocationProvider_get_batch_size(JNIEnv*, jclass) {
|
||||
if (gnssBatchingIface == nullptr) {
|
||||
return 0; // batching not supported, size = 0
|
||||
}
|
||||
auto result = gnssBatchingIface->getBatchSize();
|
||||
if (result.isOk()) {
|
||||
return static_cast<jint>(result);
|
||||
} else {
|
||||
return 0; // failure in binder, don't support batching
|
||||
}
|
||||
}
|
||||
|
||||
static jboolean android_location_GnssLocationProvider_init_batching(JNIEnv*, jclass) {
|
||||
if (gnssBatchingIface == nullptr) {
|
||||
return JNI_FALSE; // batching not supported
|
||||
}
|
||||
sp<IGnssBatchingCallback> gnssBatchingCbIface = new GnssBatchingCallback();
|
||||
|
||||
return static_cast<jboolean>(gnssBatchingIface->init(gnssBatchingCbIface));
|
||||
}
|
||||
|
||||
static void android_location_GnssLocationProvider_cleanup_batching(JNIEnv*, jclass) {
|
||||
if (gnssBatchingIface == nullptr) {
|
||||
return; // batching not supported
|
||||
}
|
||||
gnssBatchingIface->cleanup();
|
||||
}
|
||||
|
||||
static jboolean android_location_GnssLocationProvider_start_batch(JNIEnv*, jclass,
|
||||
jlong periodNanos, jboolean wakeOnFifoFull) {
|
||||
if (gnssBatchingIface == nullptr) {
|
||||
return JNI_FALSE; // batching not supported
|
||||
}
|
||||
|
||||
IGnssBatching::Options options;
|
||||
options.periodNanos = periodNanos;
|
||||
if (wakeOnFifoFull) {
|
||||
options.flags = static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL);
|
||||
} else {
|
||||
options.flags = 0;
|
||||
}
|
||||
|
||||
return static_cast<jboolean>(gnssBatchingIface->start(options));
|
||||
}
|
||||
|
||||
static void android_location_GnssLocationProvider_flush_batch(JNIEnv*, jclass) {
|
||||
if (gnssBatchingIface == nullptr) {
|
||||
return; // batching not supported
|
||||
}
|
||||
|
||||
gnssBatchingIface->flush();
|
||||
}
|
||||
|
||||
static jboolean android_location_GnssLocationProvider_stop_batch(JNIEnv*, jclass) {
|
||||
if (gnssBatchingIface == nullptr) {
|
||||
return JNI_FALSE; // batching not supported
|
||||
}
|
||||
|
||||
return gnssBatchingIface->stop();
|
||||
}
|
||||
|
||||
static const JNINativeMethod sMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{"class_init_native", "()V", reinterpret_cast<void *>(
|
||||
@@ -1829,6 +1988,27 @@ static const JNINativeMethod sMethods[] = {
|
||||
{"native_set_emergency_supl_pdn",
|
||||
"(I)Z",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_set_emergency_supl_pdn)},
|
||||
{"native_get_batch_size",
|
||||
"()I",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_get_batch_size)},
|
||||
{"native_init_batching",
|
||||
"()Z",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_init_batching)},
|
||||
{"native_start_batch",
|
||||
"(JZ)Z",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_start_batch)},
|
||||
{"native_flush_batch",
|
||||
"()V",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_flush_batch)},
|
||||
{"native_stop_batch",
|
||||
"()Z",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_stop_batch)},
|
||||
{"native_init_batching",
|
||||
"()Z",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_init_batching)},
|
||||
{"native_cleanup_batching",
|
||||
"()V",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_cleanup_batching)},
|
||||
};
|
||||
|
||||
int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
|
||||
|
||||
Reference in New Issue
Block a user