blob: f24ea38a0e7bb65a0fd7bb19ecf76e3263e98dfc [file] [log] [blame]
/*
* Copyright (C) 2008 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.
*/
// Define LOG_TAG and LOG_NDEBUG before <log/log.h> to overwrite the default values.
#define LOG_TAG "GnssLocationProviderJni"
#define LOG_NDEBUG 0
#include <android/hardware/gnss/1.0/IGnss.h>
#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
#include <android/hardware/gnss/1.1/IGnss.h>
#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
#include <android/hardware/gnss/2.0/IGnss.h>
#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
#include <android/hardware/gnss/2.1/IGnss.h>
#include <android/hardware/gnss/2.1/IGnssAntennaInfo.h>
#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
#include <android/hardware/gnss/BnGnss.h>
#include <android/hardware/gnss/BnGnssCallback.h>
#include <android/hardware/gnss/BnGnssDebug.h>
#include <android/hardware/gnss/BnGnssGeofence.h>
#include <android/hardware/gnss/BnGnssGeofenceCallback.h>
#include <android/hardware/gnss/BnGnssMeasurementCallback.h>
#include <android/hardware/gnss/BnGnssPowerIndicationCallback.h>
#include <android/hardware/gnss/BnGnssPsdsCallback.h>
#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
#include <binder/IServiceManager.h>
#include <nativehelper/JNIHelp.h>
#include <pthread.h>
#include <string.h>
#include <utils/SystemClock.h>
#include <cinttypes>
#include <iomanip>
#include <limits>
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/Log.h"
#include "gnss/AGnss.h"
#include "gnss/AGnssRil.h"
#include "gnss/GnssAntennaInfoCallback.h"
#include "gnss/GnssBatching.h"
#include "gnss/GnssConfiguration.h"
#include "gnss/GnssDebug.h"
#include "gnss/GnssGeofence.h"
#include "gnss/GnssMeasurement.h"
#include "gnss/GnssNavigationMessage.h"
#include "gnss/GnssVisibilityControl.h"
#include "gnss/Utils.h"
#include "hardware_legacy/power.h"
#include "jni.h"
#include "utils/Log.h"
#include "utils/misc.h"
static jclass class_gnssPowerStats;
static jmethodID method_reportLocation;
static jmethodID method_reportStatus;
static jmethodID method_reportSvStatus;
static jmethodID method_reportNmea;
static jmethodID method_setTopHalCapabilities;
static jmethodID method_setGnssYearOfHardware;
static jmethodID method_setGnssHardwareModelName;
static jmethodID method_psdsDownloadRequest;
static jmethodID method_reportNiNotification;
static jmethodID method_requestLocation;
static jmethodID method_requestUtcTime;
static jmethodID method_reportGnssServiceDied;
static jmethodID method_reportGnssPowerStats;
static jmethodID method_setSubHalMeasurementCorrectionsCapabilities;
static jmethodID method_correctionsGetLatitudeDegrees;
static jmethodID method_correctionsGetLongitudeDegrees;
static jmethodID method_correctionsGetAltitudeMeters;
static jmethodID method_correctionsGetHorPosUncMeters;
static jmethodID method_correctionsGetVerPosUncMeters;
static jmethodID method_correctionsGetToaGpsNanosecondsOfWeek;
static jmethodID method_correctionsGetSingleSatCorrectionList;
static jmethodID method_correctionsHasEnvironmentBearing;
static jmethodID method_correctionsGetEnvironmentBearingDegrees;
static jmethodID method_correctionsGetEnvironmentBearingUncertaintyDegrees;
static jmethodID method_listSize;
static jmethodID method_correctionListGet;
static jmethodID method_correctionSatFlags;
static jmethodID method_correctionSatConstType;
static jmethodID method_correctionSatId;
static jmethodID method_correctionSatCarrierFreq;
static jmethodID method_correctionSatIsLosProb;
static jmethodID method_correctionSatEpl;
static jmethodID method_correctionSatEplUnc;
static jmethodID method_correctionSatRefPlane;
static jmethodID method_correctionPlaneLatDeg;
static jmethodID method_correctionPlaneLngDeg;
static jmethodID method_correctionPlaneAltDeg;
static jmethodID method_correctionPlaneAzimDeg;
static jmethodID method_reportNfwNotification;
static jmethodID method_isInEmergencySession;
static jmethodID method_gnssPowerStatsCtor;
static jmethodID method_setSubHalPowerIndicationCapabilities;
using android::OK;
using android::sp;
using android::status_t;
using android::String16;
using android::wp;
using android::binder::Status;
using android::gnss::GnssConfigurationInterface;
using android::hardware::Return;
using android::hardware::Void;
using android::hardware::hidl_vec;
using android::hardware::hidl_string;
using android::hardware::hidl_death_recipient;
using android::hardware::gnss::V1_0::GnssLocationFlags;
using android::hardware::gnss::V1_0::IGnssNavigationMessage;
using android::hardware::gnss::V1_0::IGnssNavigationMessageCallback;
using android::hardware::gnss::V1_0::IGnssNi;
using android::hardware::gnss::V1_0::IGnssNiCallback;
using android::hardware::gnss::V1_0::IGnssXtra;
using android::hardware::gnss::V1_0::IGnssXtraCallback;
using android::hardware::gnss::V2_0::ElapsedRealtimeFlags;
using MeasurementCorrections_V1_0 = android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
using MeasurementCorrections_V1_1 = android::hardware::gnss::measurement_corrections::V1_1::MeasurementCorrections;
using SingleSatCorrection_V1_0 =
android::hardware::gnss::measurement_corrections::V1_0::SingleSatCorrection;
using SingleSatCorrection_V1_1 =
android::hardware::gnss::measurement_corrections::V1_1::SingleSatCorrection;
using android::hardware::gnss::measurement_corrections::V1_0::ReflectingPlane;
using android::hidl::base::V1_0::IBase;
using GnssConstellationType_V1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
using GnssConstellationType_V2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
using GnssLocation_V1_0 = android::hardware::gnss::V1_0::GnssLocation;
using GnssLocation_V2_0 = android::hardware::gnss::V2_0::GnssLocation;
using IGnss_V1_0 = android::hardware::gnss::V1_0::IGnss;
using IGnss_V1_1 = android::hardware::gnss::V1_1::IGnss;
using IGnss_V2_0 = android::hardware::gnss::V2_0::IGnss;
using IGnss_V2_1 = android::hardware::gnss::V2_1::IGnss;
using IGnssCallback_V1_0 = android::hardware::gnss::V1_0::IGnssCallback;
using IGnssCallback_V2_0 = android::hardware::gnss::V2_0::IGnssCallback;
using IGnssCallback_V2_1 = android::hardware::gnss::V2_1::IGnssCallback;
using IGnssAntennaInfo = android::hardware::gnss::V2_1::IGnssAntennaInfo;
using IMeasurementCorrections_V1_0 = android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
using IMeasurementCorrections_V1_1 = android::hardware::gnss::measurement_corrections::V1_1::IMeasurementCorrections;
using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
using android::hardware::gnss::measurement_corrections::V1_0::GnssSingleSatCorrectionFlags;
using android::hardware::gnss::BlocklistedSource;
using android::hardware::gnss::GnssConstellationType;
using android::hardware::gnss::GnssPowerStats;
using android::hardware::gnss::IGnssPowerIndication;
using android::hardware::gnss::IGnssPowerIndicationCallback;
using android::hardware::gnss::PsdsType;
using IAGnssAidl = android::hardware::gnss::IAGnss;
using IAGnssRilAidl = android::hardware::gnss::IAGnssRil;
using IGnssAidl = android::hardware::gnss::IGnss;
using IGnssCallbackAidl = android::hardware::gnss::IGnssCallback;
using IGnssBatchingAidl = android::hardware::gnss::IGnssBatching;
using IGnssDebugAidl = android::hardware::gnss::IGnssDebug;
using IGnssPsdsAidl = android::hardware::gnss::IGnssPsds;
using IGnssPsdsCallbackAidl = android::hardware::gnss::IGnssPsdsCallback;
using IGnssConfigurationAidl = android::hardware::gnss::IGnssConfiguration;
using GnssLocationAidl = android::hardware::gnss::GnssLocation;
struct GnssDeathRecipient : virtual public hidl_death_recipient
{
// hidl_death_recipient interface
virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override {
ALOGE("IGNSS hidl service failed, trying to recover...");
JNIEnv* env = android::AndroidRuntime::getJNIEnv();
env->CallVoidMethod(android::mCallbacksObj, method_reportGnssServiceDied);
}
};
// Must match the value from GnssMeasurement.java
static const uint32_t SVID_FLAGS_HAS_BASEBAND_CN0 = (1<<4);
sp<GnssDeathRecipient> gnssHalDeathRecipient = nullptr;
sp<IGnss_V1_0> gnssHal = nullptr;
sp<IGnss_V1_1> gnssHal_V1_1 = nullptr;
sp<IGnss_V2_0> gnssHal_V2_0 = nullptr;
sp<IGnss_V2_1> gnssHal_V2_1 = nullptr;
sp<IGnssAidl> gnssHalAidl = nullptr;
sp<IGnssBatchingAidl> gnssBatchingAidlIface = nullptr;
sp<IGnssPsdsAidl> gnssPsdsAidlIface = nullptr;
sp<IGnssXtra> gnssXtraIface = nullptr;
sp<IGnssNi> gnssNiIface = nullptr;
sp<IGnssPowerIndication> gnssPowerIndicationIface = nullptr;
sp<IMeasurementCorrections_V1_0> gnssCorrectionsIface_V1_0 = nullptr;
sp<IMeasurementCorrections_V1_1> gnssCorrectionsIface_V1_1 = nullptr;
sp<IGnssAntennaInfo> gnssAntennaInfoIface = nullptr;
std::unique_ptr<GnssConfigurationInterface> gnssConfigurationIface = nullptr;
std::unique_ptr<android::gnss::GnssMeasurementInterface> gnssMeasurementIface = nullptr;
std::unique_ptr<android::gnss::GnssNavigationMessageInterface> gnssNavigationMessageIface = nullptr;
std::unique_ptr<android::gnss::GnssBatchingInterface> gnssBatchingIface = nullptr;
std::unique_ptr<android::gnss::GnssGeofenceInterface> gnssGeofencingIface = nullptr;
std::unique_ptr<android::gnss::AGnssInterface> agnssIface = nullptr;
std::unique_ptr<android::gnss::GnssDebugInterface> gnssDebugIface = nullptr;
std::unique_ptr<android::gnss::AGnssRilInterface> agnssRilIface = nullptr;
std::unique_ptr<android::gnss::GnssVisibilityControlInterface> gnssVisibilityControlIface = nullptr;
#define WAKE_LOCK_NAME "GPS"
namespace android {
namespace {
// Returns true if location has lat/long information.
bool hasLatLong(const GnssLocationAidl& location) {
return (location.gnssLocationFlags & GnssLocationAidl::HAS_LAT_LONG) != 0;
}
// Returns true if location has lat/long information.
bool hasLatLong(const GnssLocation_V1_0& location) {
return (static_cast<uint32_t>(location.gnssLocationFlags) &
GnssLocationFlags::HAS_LAT_LONG) != 0;
}
// Returns true if location has lat/long information.
bool hasLatLong(const GnssLocation_V2_0& location) {
return hasLatLong(location.v1_0);
}
} // namespace
static inline jboolean boolToJbool(bool value) {
return value ? JNI_TRUE : JNI_FALSE;
}
static GnssLocationAidl createGnssLocation(jint gnssLocationFlags, jdouble latitudeDegrees,
jdouble longitudeDegrees, jdouble altitudeMeters,
jfloat speedMetersPerSec, jfloat bearingDegrees,
jfloat horizontalAccuracyMeters,
jfloat verticalAccuracyMeters,
jfloat speedAccuracyMetersPerSecond,
jfloat bearingAccuracyDegrees, jlong timestamp,
jint elapsedRealtimeFlags, jlong elapsedRealtimeNanos,
jdouble elapsedRealtimeUncertaintyNanos) {
GnssLocationAidl location;
location.gnssLocationFlags = static_cast<int>(gnssLocationFlags);
location.latitudeDegrees = static_cast<double>(latitudeDegrees);
location.longitudeDegrees = static_cast<double>(longitudeDegrees);
location.altitudeMeters = static_cast<double>(altitudeMeters);
location.speedMetersPerSec = static_cast<double>(speedMetersPerSec);
location.bearingDegrees = static_cast<double>(bearingDegrees);
location.horizontalAccuracyMeters = static_cast<double>(horizontalAccuracyMeters);
location.verticalAccuracyMeters = static_cast<double>(verticalAccuracyMeters);
location.speedAccuracyMetersPerSecond = static_cast<double>(speedAccuracyMetersPerSecond);
location.bearingAccuracyDegrees = static_cast<double>(bearingAccuracyDegrees);
location.timestampMillis = static_cast<uint64_t>(timestamp);
location.elapsedRealtime.flags = static_cast<int>(elapsedRealtimeFlags);
location.elapsedRealtime.timestampNs = static_cast<uint64_t>(elapsedRealtimeNanos);
location.elapsedRealtime.timeUncertaintyNs =
static_cast<double>(elapsedRealtimeUncertaintyNanos);
return location;
}
static GnssLocation_V1_0 createGnssLocation_V1_0(
jint gnssLocationFlags, jdouble latitudeDegrees, jdouble longitudeDegrees,
jdouble altitudeMeters, jfloat speedMetersPerSec, jfloat bearingDegrees,
jfloat horizontalAccuracyMeters, jfloat verticalAccuracyMeters,
jfloat speedAccuracyMetersPerSecond, jfloat bearingAccuracyDegrees,
jlong timestamp) {
GnssLocation_V1_0 location;
location.gnssLocationFlags = static_cast<uint16_t>(gnssLocationFlags);
location.latitudeDegrees = static_cast<double>(latitudeDegrees);
location.longitudeDegrees = static_cast<double>(longitudeDegrees);
location.altitudeMeters = static_cast<double>(altitudeMeters);
location.speedMetersPerSec = static_cast<float>(speedMetersPerSec);
location.bearingDegrees = static_cast<float>(bearingDegrees);
location.horizontalAccuracyMeters = static_cast<float>(horizontalAccuracyMeters);
location.verticalAccuracyMeters = static_cast<float>(verticalAccuracyMeters);
location.speedAccuracyMetersPerSecond = static_cast<float>(speedAccuracyMetersPerSecond);
location.bearingAccuracyDegrees = static_cast<float>(bearingAccuracyDegrees);
location.timestamp = static_cast<uint64_t>(timestamp);
return location;
}
static GnssLocation_V2_0 createGnssLocation_V2_0(
jint gnssLocationFlags, jdouble latitudeDegrees, jdouble longitudeDegrees,
jdouble altitudeMeters, jfloat speedMetersPerSec, jfloat bearingDegrees,
jfloat horizontalAccuracyMeters, jfloat verticalAccuracyMeters,
jfloat speedAccuracyMetersPerSecond, jfloat bearingAccuracyDegrees,
jlong timestamp, jint elapsedRealtimeFlags, jlong elapsedRealtimeNanos,
jdouble elapsedRealtimeUncertaintyNanos) {
GnssLocation_V2_0 location;
location.v1_0 = createGnssLocation_V1_0(
gnssLocationFlags, latitudeDegrees, longitudeDegrees, altitudeMeters,
speedMetersPerSec, bearingDegrees, horizontalAccuracyMeters,
verticalAccuracyMeters, speedAccuracyMetersPerSecond,
bearingAccuracyDegrees, timestamp);
location.elapsedRealtime.flags = static_cast<uint16_t>(elapsedRealtimeFlags);
location.elapsedRealtime.timestampNs = static_cast<uint64_t>(elapsedRealtimeNanos);
location.elapsedRealtime.timeUncertaintyNs = static_cast<uint64_t>(elapsedRealtimeUncertaintyNanos);
return location;
}
/*
* GnssCallback class implements the callback methods for IGnss interface.
*/
struct GnssCallback : public IGnssCallback_V2_1 {
Return<void> gnssLocationCb(const GnssLocation_V1_0& location) override;
Return<void> gnssStatusCb(const IGnssCallback_V1_0::GnssStatusValue status) override;
Return<void> gnssSvStatusCb(const IGnssCallback_V1_0::GnssSvStatus& svStatus) override {
return gnssSvStatusCbImpl<IGnssCallback_V1_0::GnssSvStatus, IGnssCallback_V1_0::GnssSvInfo>(
svStatus);
}
Return<void> gnssNmeaCb(int64_t timestamp, const android::hardware::hidl_string& nmea) override;
Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
Return<void> gnssAcquireWakelockCb() override;
Return<void> gnssReleaseWakelockCb() override;
Return<void> gnssRequestTimeCb() override;
Return<void> gnssRequestLocationCb(const bool independentFromGnss) override;
Return<void> gnssSetSystemInfoCb(const IGnssCallback_V1_0::GnssSystemInfo& info) override;
// New in 1.1
Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;
// New in 2.0
Return<void> gnssRequestLocationCb_2_0(const bool independentFromGnss, const bool isUserEmergency)
override;
Return<void> gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override;
Return<void> gnssLocationCb_2_0(const GnssLocation_V2_0& location) override;
Return<void> gnssSvStatusCb_2_0(const hidl_vec<IGnssCallback_V2_0::GnssSvInfo>& svInfoList) override {
return gnssSvStatusCbImpl<hidl_vec<IGnssCallback_V2_0::GnssSvInfo>,
IGnssCallback_V1_0::GnssSvInfo>(svInfoList);
}
// New in 2.1
Return<void> gnssSvStatusCb_2_1(const hidl_vec<IGnssCallback_V2_1::GnssSvInfo>& svInfoList) override {
return gnssSvStatusCbImpl<hidl_vec<IGnssCallback_V2_1::GnssSvInfo>,
IGnssCallback_V1_0::GnssSvInfo>(svInfoList);
}
Return<void> gnssSetCapabilitiesCb_2_1(uint32_t capabilities) override;
// TODO: Reconsider allocation cost vs threadsafety on these statics
static const char* sNmeaString;
static size_t sNmeaStringLength;
template <class T>
static Return<void> gnssLocationCbImpl(const T& location);
template <class T_list, class T_sv_info>
static Return<void> gnssSvStatusCbImpl(const T_list& svStatus);
private:
template <class T>
static uint32_t getHasBasebandCn0DbHzFlag(const T& svStatus) {
return 0;
}
template <class T>
static double getBasebandCn0DbHz(const T& svStatus, size_t i) {
return 0.0;
}
template <class T>
static uint32_t getGnssSvInfoListSize(const T& svInfoList) {
return svInfoList.size();
}
static const IGnssCallbackAidl::GnssSvInfo& getGnssSvInfoOfIndex(
const std::vector<IGnssCallbackAidl::GnssSvInfo>& svInfoList, size_t i) {
return svInfoList[i];
}
static const IGnssCallback_V1_0::GnssSvInfo& getGnssSvInfoOfIndex(
const IGnssCallback_V1_0::GnssSvStatus& svStatus, size_t i) {
return svStatus.gnssSvList.data()[i];
}
static const IGnssCallback_V1_0::GnssSvInfo& getGnssSvInfoOfIndex(
const hidl_vec<IGnssCallback_V2_0::GnssSvInfo>& svInfoList, size_t i) {
return svInfoList[i].v1_0;
}
static const IGnssCallback_V1_0::GnssSvInfo& getGnssSvInfoOfIndex(
const hidl_vec<IGnssCallback_V2_1::GnssSvInfo>& svInfoList, size_t i) {
return svInfoList[i].v2_0.v1_0;
}
template <class T>
static uint32_t getConstellationType(const T& svInfoList, size_t i) {
return static_cast<uint32_t>(svInfoList[i].constellation);
}
};
Return<void> GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) {
ALOGD("%s: name=%s\n", __func__, name.c_str());
JNIEnv* env = getJniEnv();
jstring jstringName = env->NewStringUTF(name.c_str());
env->CallVoidMethod(mCallbacksObj, method_setGnssHardwareModelName, jstringName);
if (jstringName) {
env->DeleteLocalRef(jstringName);
}
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Void();
}
const char* GnssCallback::sNmeaString = nullptr;
size_t GnssCallback::sNmeaStringLength = 0;
template<class T>
Return<void> GnssCallback::gnssLocationCbImpl(const T& location) {
JNIEnv* env = getJniEnv();
jobject jLocation = translateGnssLocation(env, location);
env->CallVoidMethod(mCallbacksObj,
method_reportLocation,
boolToJbool(hasLatLong(location)),
jLocation);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
env->DeleteLocalRef(jLocation);
return Void();
}
Return<void> GnssCallback::gnssLocationCb(const GnssLocation_V1_0& location) {
return gnssLocationCbImpl<GnssLocation_V1_0>(location);
}
Return<void>
GnssCallback::gnssLocationCb_2_0(const GnssLocation_V2_0& location) {
return gnssLocationCbImpl<GnssLocation_V2_0>(location);
}
Return<void> GnssCallback::gnssStatusCb(const IGnssCallback_V2_0::GnssStatusValue status) {
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_reportStatus, status);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Void();
}
template<>
uint32_t GnssCallback::getHasBasebandCn0DbHzFlag(const hidl_vec<IGnssCallback_V2_1::GnssSvInfo>&
svStatus) {
return SVID_FLAGS_HAS_BASEBAND_CN0;
}
template <>
uint32_t GnssCallback::getHasBasebandCn0DbHzFlag(
const std::vector<IGnssCallbackAidl::GnssSvInfo>& svStatus) {
return SVID_FLAGS_HAS_BASEBAND_CN0;
}
template <>
double GnssCallback::getBasebandCn0DbHz(
const std::vector<IGnssCallbackAidl::GnssSvInfo>& svInfoList, size_t i) {
return svInfoList[i].basebandCN0DbHz;
}
template<>
double GnssCallback::getBasebandCn0DbHz(const hidl_vec<IGnssCallback_V2_1::GnssSvInfo>& svInfoList,
size_t i) {
return svInfoList[i].basebandCN0DbHz;
}
template <>
uint32_t GnssCallback::getGnssSvInfoListSize(const IGnssCallback_V1_0::GnssSvStatus& svStatus) {
return svStatus.numSvs;
}
template <>
uint32_t GnssCallback::getConstellationType(const IGnssCallback_V1_0::GnssSvStatus& svStatus,
size_t i) {
return static_cast<uint32_t>(svStatus.gnssSvList.data()[i].constellation);
}
template <>
uint32_t GnssCallback::getConstellationType(
const hidl_vec<IGnssCallback_V2_1::GnssSvInfo>& svInfoList, size_t i) {
return static_cast<uint32_t>(svInfoList[i].v2_0.constellation);
}
template <class T_list, class T_sv_info>
Return<void> GnssCallback::gnssSvStatusCbImpl(const T_list& svStatus) {
JNIEnv* env = getJniEnv();
uint32_t listSize = getGnssSvInfoListSize(svStatus);
jintArray svidWithFlagArray = env->NewIntArray(listSize);
jfloatArray cn0Array = env->NewFloatArray(listSize);
jfloatArray elevArray = env->NewFloatArray(listSize);
jfloatArray azimArray = env->NewFloatArray(listSize);
jfloatArray carrierFreqArray = env->NewFloatArray(listSize);
jfloatArray basebandCn0Array = env->NewFloatArray(listSize);
jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
jfloat* azim = env->GetFloatArrayElements(azimArray, 0);
jfloat* carrierFreq = env->GetFloatArrayElements(carrierFreqArray, 0);
jfloat* basebandCn0s = env->GetFloatArrayElements(basebandCn0Array, 0);
/*
* Read GNSS SV info.
*/
for (size_t i = 0; i < listSize; ++i) {
enum ShiftWidth: uint8_t {
SVID_SHIFT_WIDTH = 12,
CONSTELLATION_TYPE_SHIFT_WIDTH = 8
};
const T_sv_info& info = getGnssSvInfoOfIndex(svStatus, i);
svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
(getConstellationType(svStatus, i) << CONSTELLATION_TYPE_SHIFT_WIDTH) |
static_cast<uint32_t>(info.svFlag);
cn0s[i] = info.cN0Dbhz;
elev[i] = info.elevationDegrees;
azim[i] = info.azimuthDegrees;
carrierFreq[i] = info.carrierFrequencyHz;
svidWithFlags[i] |= getHasBasebandCn0DbHzFlag(svStatus);
basebandCn0s[i] = getBasebandCn0DbHz(svStatus, i);
}
env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
env->ReleaseFloatArrayElements(elevArray, elev, 0);
env->ReleaseFloatArrayElements(azimArray, azim, 0);
env->ReleaseFloatArrayElements(carrierFreqArray, carrierFreq, 0);
env->ReleaseFloatArrayElements(basebandCn0Array, basebandCn0s, 0);
env->CallVoidMethod(mCallbacksObj, method_reportSvStatus,
static_cast<jint>(listSize), svidWithFlagArray, cn0Array, elevArray, azimArray,
carrierFreqArray, basebandCn0Array);
env->DeleteLocalRef(svidWithFlagArray);
env->DeleteLocalRef(cn0Array);
env->DeleteLocalRef(elevArray);
env->DeleteLocalRef(azimArray);
env->DeleteLocalRef(carrierFreqArray);
env->DeleteLocalRef(basebandCn0Array);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Void();
}
Return<void> GnssCallback::gnssNmeaCb(
int64_t timestamp, const ::android::hardware::hidl_string& nmea) {
JNIEnv* env = getJniEnv();
/*
* The Java code will call back to read these values.
* We do this to avoid creating unnecessary String objects.
*/
sNmeaString = nmea.c_str();
sNmeaStringLength = nmea.size();
env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Void();
}
Return<void> GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
ALOGD("%s: %du\n", __func__, capabilities);
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_setTopHalCapabilities, capabilities);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Void();
}
Return<void> GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) {
return GnssCallback::gnssSetCapabilitesCb(capabilities);
}
Return<void> GnssCallback::gnssSetCapabilitiesCb_2_1(uint32_t capabilities) {
return GnssCallback::gnssSetCapabilitesCb(capabilities);
}
Return<void> GnssCallback::gnssAcquireWakelockCb() {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
return Void();
}
Return<void> GnssCallback::gnssReleaseWakelockCb() {
release_wake_lock(WAKE_LOCK_NAME);
return Void();
}
Return<void> GnssCallback::gnssRequestTimeCb() {
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Void();
}
Return<void> GnssCallback::gnssRequestLocationCb(const bool independentFromGnss) {
return GnssCallback::gnssRequestLocationCb_2_0(independentFromGnss, /* isUserEmergency= */
false);
}
Return<void> GnssCallback::gnssRequestLocationCb_2_0(const bool independentFromGnss, const bool
isUserEmergency) {
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_requestLocation, boolToJbool(independentFromGnss),
boolToJbool(isUserEmergency));
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Void();
}
Return<void> GnssCallback::gnssSetSystemInfoCb(const IGnssCallback_V2_0::GnssSystemInfo& info) {
ALOGD("%s: yearOfHw=%d\n", __func__, info.yearOfHw);
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
info.yearOfHw);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Void();
}
class GnssCallbackAidl : public android::hardware::gnss::BnGnssCallback {
public:
Status gnssSetCapabilitiesCb(const int capabilities) override;
Status gnssStatusCb(const GnssStatusValue status) override;
Status gnssSvStatusCb(const std::vector<GnssSvInfo>& svInfoList) override;
Status gnssLocationCb(const GnssLocationAidl& location) override;
Status gnssNmeaCb(const int64_t timestamp, const std::string& nmea) override;
Status gnssAcquireWakelockCb() override;
Status gnssReleaseWakelockCb() override;
Status gnssSetSystemInfoCb(const GnssSystemInfo& info) override;
Status gnssRequestTimeCb() override;
Status gnssRequestLocationCb(const bool independentFromGnss,
const bool isUserEmergency) override;
};
Status GnssCallbackAidl::gnssSetCapabilitiesCb(const int capabilities) {
ALOGD("GnssCallbackAidl::%s: %du\n", __func__, capabilities);
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_setTopHalCapabilities, capabilities);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Status::ok();
}
Status GnssCallbackAidl::gnssStatusCb(const GnssStatusValue status) {
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_reportStatus, status);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Status::ok();
}
Status GnssCallbackAidl::gnssSvStatusCb(const std::vector<GnssSvInfo>& svInfoList) {
GnssCallback::gnssSvStatusCbImpl<std::vector<GnssSvInfo>, GnssSvInfo>(svInfoList);
return Status::ok();
}
Status GnssCallbackAidl::gnssLocationCb(const GnssLocationAidl& location) {
GnssCallback::gnssLocationCbImpl<GnssLocationAidl>(location);
return Status::ok();
}
Status GnssCallbackAidl::gnssNmeaCb(const int64_t timestamp, const std::string& nmea) {
JNIEnv* env = getJniEnv();
/*
* The Java code will call back to read these values.
* We do this to avoid creating unnecessary String objects.
*/
GnssCallback::sNmeaString = nmea.c_str();
GnssCallback::sNmeaStringLength = nmea.size();
env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Status::ok();
}
Status GnssCallbackAidl::gnssAcquireWakelockCb() {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
return Status::ok();
}
Status GnssCallbackAidl::gnssReleaseWakelockCb() {
release_wake_lock(WAKE_LOCK_NAME);
return Status::ok();
}
Status GnssCallbackAidl::gnssSetSystemInfoCb(const GnssSystemInfo& info) {
ALOGD("%s: yearOfHw=%d, name=%s\n", __func__, info.yearOfHw, info.name.c_str());
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware, info.yearOfHw);
jstring jstringName = env->NewStringUTF(info.name.c_str());
env->CallVoidMethod(mCallbacksObj, method_setGnssHardwareModelName, jstringName);
if (jstringName) {
env->DeleteLocalRef(jstringName);
}
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Status::ok();
}
Status GnssCallbackAidl::gnssRequestTimeCb() {
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Status::ok();
}
Status GnssCallbackAidl::gnssRequestLocationCb(const bool independentFromGnss,
const bool isUserEmergency) {
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_requestLocation, boolToJbool(independentFromGnss),
boolToJbool(isUserEmergency));
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Status::ok();
}
/*
* GnssPowerIndicationCallback class implements the callback methods for the IGnssPowerIndication
* interface.
*/
struct GnssPowerIndicationCallback : public android::hardware::gnss::BnGnssPowerIndicationCallback {
public:
Status setCapabilitiesCb(const int capabilities) override;
Status gnssPowerStatsCb(const GnssPowerStats& data) override;
};
Status GnssPowerIndicationCallback::setCapabilitiesCb(const int capabilities) {
ALOGD("GnssPowerIndicationCallback::%s: %du\n", __func__, capabilities);
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_setSubHalPowerIndicationCapabilities, capabilities);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Status::ok();
}
Status GnssPowerIndicationCallback::gnssPowerStatsCb(const GnssPowerStats& data) {
JNIEnv* env = getJniEnv();
int size = data.otherModesEnergyMilliJoule.size();
jdoubleArray otherModesEnergy = env->NewDoubleArray(size);
if (size > 0) {
env->SetDoubleArrayRegion(otherModesEnergy, (jsize)0, size,
&(data.otherModesEnergyMilliJoule[0]));
}
jobject gnssPowerStats =
env->NewObject(class_gnssPowerStats, method_gnssPowerStatsCtor,
data.elapsedRealtime.flags, data.elapsedRealtime.timestampNs,
data.elapsedRealtime.timeUncertaintyNs, data.totalEnergyMilliJoule,
data.singlebandTrackingModeEnergyMilliJoule,
data.multibandTrackingModeEnergyMilliJoule,
data.singlebandAcquisitionModeEnergyMilliJoule,
data.multibandAcquisitionModeEnergyMilliJoule, otherModesEnergy);
env->CallVoidMethod(mCallbacksObj, method_reportGnssPowerStats, gnssPowerStats);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
env->DeleteLocalRef(gnssPowerStats);
env->DeleteLocalRef(otherModesEnergy);
return Status::ok();
}
/*
* GnssPsdsCallback class implements the callback methods for the IGnssPsds
* interface.
*/
struct GnssPsdsCallbackAidl : public android::hardware::gnss::BnGnssPsdsCallback {
Status downloadRequestCb(PsdsType psdsType) override {
ALOGD("%s. psdsType: %d", __func__, static_cast<int32_t>(psdsType));
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_psdsDownloadRequest, psdsType);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Status::ok();
}
};
/**
* GnssXtraCallback class implements the callback methods for the IGnssXtra
* interface.
*/
class GnssXtraCallback : public IGnssXtraCallback {
Return<void> downloadRequestCb() override;
};
Return<void> GnssXtraCallback::downloadRequestCb() {
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_psdsDownloadRequest, /* psdsType= */ 1);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Void();
}
/*
* MeasurementCorrectionsCallback implements callback methods of interface
* IMeasurementCorrectionsCallback.hal.
*/
struct MeasurementCorrectionsCallback : public IMeasurementCorrectionsCallback {
Return<void> setCapabilitiesCb(uint32_t capabilities) override;
};
Return<void> MeasurementCorrectionsCallback::setCapabilitiesCb(uint32_t capabilities) {
ALOGD("%s: %du\n", __func__, capabilities);
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_setSubHalMeasurementCorrectionsCapabilities,
capabilities);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Void();
}
/*
* GnssNiCallback implements callback methods required by the IGnssNi interface.
*/
struct GnssNiCallback : public IGnssNiCallback {
Return<void> niNotifyCb(const IGnssNiCallback::GnssNiNotification& notification)
override;
};
Return<void> GnssNiCallback::niNotifyCb(
const IGnssNiCallback::GnssNiNotification& notification) {
JNIEnv* env = getJniEnv();
jstring requestorId = env->NewStringUTF(notification.requestorId.c_str());
jstring text = env->NewStringUTF(notification.notificationMessage.c_str());
if (requestorId && text) {
env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
notification.notificationId, notification.niType,
notification.notifyFlags, notification.timeoutSec,
notification.defaultResponse, requestorId, text,
notification.requestorIdEncoding,
notification.notificationIdEncoding);
} else {
ALOGE("%s: OOM Error\n", __func__);
}
if (requestorId) {
env->DeleteLocalRef(requestorId);
}
if (text) {
env->DeleteLocalRef(text);
}
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Void();
}
/* Initializes the GNSS service handle. */
static void android_location_gnss_hal_GnssNative_set_gps_service_handle() {
gnssHalAidl = waitForVintfService<IGnssAidl>();
if (gnssHalAidl != nullptr) {
ALOGD("Successfully got GNSS AIDL handle. Version=%d.", gnssHalAidl->getInterfaceVersion());
if (gnssHalAidl->getInterfaceVersion() >= 2) {
return;
}
}
ALOGD("Trying IGnss_V2_1::getService()");
gnssHal_V2_1 = IGnss_V2_1::getService();
if (gnssHal_V2_1 != nullptr) {
gnssHal = gnssHal_V2_1;
gnssHal_V2_0 = gnssHal_V2_1;
gnssHal_V1_1 = gnssHal_V2_1;
gnssHal = gnssHal_V2_1;
return;
}
ALOGD("gnssHal 2.1 was null, trying 2.0");
gnssHal_V2_0 = IGnss_V2_0::getService();
if (gnssHal_V2_0 != nullptr) {
gnssHal = gnssHal_V2_0;
gnssHal_V1_1 = gnssHal_V2_0;
return;
}
ALOGD("gnssHal 2.0 was null, trying 1.1");
gnssHal_V1_1 = IGnss_V1_1::getService();
if (gnssHal_V1_1 != nullptr) {
gnssHal = gnssHal_V1_1;
return;
}
ALOGD("gnssHal 1.1 was null, trying 1.0");
gnssHal = IGnss_V1_0::getService();
}
/* One time initialization at system boot */
static void android_location_gnss_hal_GnssNative_class_init_once(JNIEnv* env, jclass clazz) {
// Initialize the top level gnss HAL handle.
android_location_gnss_hal_GnssNative_set_gps_service_handle();
// Cache methodIDs and class IDs.
method_reportLocation = env->GetMethodID(clazz, "reportLocation",
"(ZLandroid/location/Location;)V");
method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "(I[I[F[F[F[F[F)V");
method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
method_setTopHalCapabilities = env->GetMethodID(clazz, "setTopHalCapabilities", "(I)V");
method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
method_setGnssHardwareModelName = env->GetMethodID(clazz, "setGnssHardwareModelName",
"(Ljava/lang/String;)V");
method_psdsDownloadRequest = env->GetMethodID(clazz, "psdsDownloadRequest", "(I)V");
method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
"(IIIIILjava/lang/String;Ljava/lang/String;II)V");
method_requestLocation = env->GetMethodID(clazz, "requestLocation", "(ZZ)V");
method_requestUtcTime = env->GetMethodID(clazz, "requestUtcTime", "()V");
method_reportGnssServiceDied = env->GetMethodID(clazz, "reportGnssServiceDied", "()V");
method_reportNfwNotification = env->GetMethodID(clazz, "reportNfwNotification",
"(Ljava/lang/String;BLjava/lang/String;BLjava/lang/String;BZZ)V");
method_reportGnssPowerStats =
env->GetMethodID(clazz, "reportGnssPowerStats",
"(Lcom/android/server/location/gnss/GnssPowerStats;)V");
method_isInEmergencySession = env->GetMethodID(clazz, "isInEmergencySession", "()Z");
method_setSubHalMeasurementCorrectionsCapabilities = env->GetMethodID(clazz,
"setSubHalMeasurementCorrectionsCapabilities", "(I)V");
method_setSubHalPowerIndicationCapabilities =
env->GetMethodID(clazz, "setSubHalPowerIndicationCapabilities", "(I)V");
jclass measCorrClass = env->FindClass("android/location/GnssMeasurementCorrections");
method_correctionsGetLatitudeDegrees = env->GetMethodID(
measCorrClass,"getLatitudeDegrees", "()D");
method_correctionsGetLongitudeDegrees = env->GetMethodID(
measCorrClass, "getLongitudeDegrees", "()D");
method_correctionsGetAltitudeMeters = env->GetMethodID(
measCorrClass, "getAltitudeMeters", "()D");
method_correctionsGetHorPosUncMeters = env->GetMethodID(
measCorrClass, "getHorizontalPositionUncertaintyMeters", "()D");
method_correctionsGetVerPosUncMeters = env->GetMethodID(
measCorrClass, "getVerticalPositionUncertaintyMeters", "()D");
method_correctionsGetToaGpsNanosecondsOfWeek = env->GetMethodID(
measCorrClass, "getToaGpsNanosecondsOfWeek", "()J");
method_correctionsGetSingleSatCorrectionList = env->GetMethodID(
measCorrClass, "getSingleSatelliteCorrectionList", "()Ljava/util/List;");
method_correctionsHasEnvironmentBearing = env->GetMethodID(
measCorrClass, "hasEnvironmentBearing", "()Z");
method_correctionsGetEnvironmentBearingDegrees = env->GetMethodID(
measCorrClass, "getEnvironmentBearingDegrees", "()F");
method_correctionsGetEnvironmentBearingUncertaintyDegrees = env->GetMethodID(
measCorrClass, "getEnvironmentBearingUncertaintyDegrees", "()F");
jclass corrListClass = env->FindClass("java/util/List");
method_listSize = env->GetMethodID(corrListClass, "size", "()I");
method_correctionListGet = env->GetMethodID(corrListClass, "get", "(I)Ljava/lang/Object;");
jclass singleSatCorrClass = env->FindClass("android/location/GnssSingleSatCorrection");
method_correctionSatFlags = env->GetMethodID(
singleSatCorrClass, "getSingleSatelliteCorrectionFlags", "()I");
method_correctionSatConstType = env->GetMethodID(
singleSatCorrClass, "getConstellationType", "()I");
method_correctionSatId= env->GetMethodID(
singleSatCorrClass, "getSatelliteId", "()I");
method_correctionSatCarrierFreq = env->GetMethodID(
singleSatCorrClass, "getCarrierFrequencyHz", "()F");
method_correctionSatIsLosProb = env->GetMethodID(
singleSatCorrClass,"getProbabilityLineOfSight", "()F");
method_correctionSatEpl = env->GetMethodID(
singleSatCorrClass, "getExcessPathLengthMeters", "()F");
method_correctionSatEplUnc = env->GetMethodID(
singleSatCorrClass, "getExcessPathLengthUncertaintyMeters", "()F");
method_correctionSatRefPlane = env->GetMethodID(
singleSatCorrClass, "getReflectingPlane", "()Landroid/location/GnssReflectingPlane;");
jclass refPlaneClass = env->FindClass("android/location/GnssReflectingPlane");
method_correctionPlaneLatDeg = env->GetMethodID(refPlaneClass, "getLatitudeDegrees", "()D");
method_correctionPlaneLngDeg = env->GetMethodID(refPlaneClass, "getLongitudeDegrees", "()D");
method_correctionPlaneAltDeg = env->GetMethodID(refPlaneClass, "getAltitudeMeters", "()D");
method_correctionPlaneAzimDeg = env->GetMethodID(refPlaneClass, "getAzimuthDegrees", "()D");
jclass gnssPowerStatsClass = env->FindClass("com/android/server/location/gnss/GnssPowerStats");
class_gnssPowerStats = (jclass)env->NewGlobalRef(gnssPowerStatsClass);
method_gnssPowerStatsCtor = env->GetMethodID(class_gnssPowerStats, "<init>", "(IJDDDDDD[D)V");
gnss::GnssAntennaInfo_class_init_once(env, clazz);
gnss::GnssBatching_class_init_once(env, clazz);
gnss::GnssConfiguration_class_init_once(env);
gnss::GnssGeofence_class_init_once(env, clazz);
gnss::GnssMeasurement_class_init_once(env, clazz);
gnss::GnssNavigationMessage_class_init_once(env, clazz);
gnss::AGnss_class_init_once(env, clazz);
gnss::AGnssRil_class_init_once(env, clazz);
gnss::Utils_class_init_once(env);
}
/* Initialization needed at system boot and whenever GNSS service dies. */
static void android_location_gnss_hal_GnssNative_init_once(JNIEnv* env, jobject obj,
jboolean reinitializeGnssServiceHandle) {
/*
* Save a pointer to JVM.
*/
jint jvmStatus = env->GetJavaVM(&android::ScopedJniThreadAttach::sJvm);
if (jvmStatus != JNI_OK) {
LOG_ALWAYS_FATAL("Unable to get Java VM. Error: %d", jvmStatus);
}
if (reinitializeGnssServiceHandle) {
android_location_gnss_hal_GnssNative_set_gps_service_handle();
}
if (gnssHal == nullptr && gnssHalAidl == nullptr) {
ALOGE("Unable to get GPS service\n");
return;
}
// TODO: linkToDeath for AIDL HAL
if (gnssHal != nullptr) {
gnssHalDeathRecipient = new GnssDeathRecipient();
hardware::Return<bool> linked = gnssHal->linkToDeath(gnssHalDeathRecipient, /*cookie*/ 0);
if (!linked.isOk()) {
ALOGE("Transaction error in linking to GnssHAL death: %s",
linked.description().c_str());
} else if (!linked) {
ALOGW("Unable to link to GnssHal death notifications");
} else {
ALOGD("Link to death notification successful");
}
}
if (gnssHalAidl != nullptr) {
sp<IGnssPsdsAidl> gnssPsdsAidl;
auto status = gnssHalAidl->getExtensionPsds(&gnssPsdsAidl);
if (status.isOk()) {
gnssPsdsAidlIface = gnssPsdsAidl;
} else {
ALOGD("Unable to get a handle to PSDS AIDL interface.");
}
} else if (gnssHal != nullptr) {
auto gnssXtra = gnssHal->getExtensionXtra();
if (!gnssXtra.isOk()) {
ALOGD("Unable to get a handle to Xtra");
} else {
gnssXtraIface = gnssXtra;
}
}
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
sp<IAGnssRilAidl> agnssRilAidl;
auto status = gnssHalAidl->getExtensionAGnssRil(&agnssRilAidl);
if (checkAidlStatus(status, "Unable to get a handle to AGnssRil interface.")) {
agnssRilIface = std::make_unique<gnss::AGnssRil>(agnssRilAidl);
}
} else if (gnssHal_V2_0 != nullptr) {
auto agnssRil_V2_0 = gnssHal_V2_0->getExtensionAGnssRil_2_0();
if (checkHidlReturn(agnssRil_V2_0, "Unable to get a handle to AGnssRil_V2_0")) {
agnssRilIface = std::make_unique<gnss::AGnssRil_V2_0>(agnssRil_V2_0);
}
} else if (gnssHal != nullptr) {
auto agnssRil_V1_0 = gnssHal->getExtensionAGnssRil();
if (checkHidlReturn(agnssRil_V1_0, "Unable to get a handle to AGnssRil_V1_0")) {
agnssRilIface = std::make_unique<gnss::AGnssRil_V1_0>(agnssRil_V1_0);
}
}
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
sp<IAGnssAidl> agnssAidl;
auto status = gnssHalAidl->getExtensionAGnss(&agnssAidl);
if (checkAidlStatus(status, "Unable to get a handle to AGnss interface.")) {
agnssIface = std::make_unique<gnss::AGnss>(agnssAidl);
}
} else if (gnssHal_V2_0 != nullptr) {
auto agnss_V2_0 = gnssHal_V2_0->getExtensionAGnss_2_0();
if (checkHidlReturn(agnss_V2_0, "Unable to get a handle to AGnss_V2_0")) {
agnssIface = std::make_unique<gnss::AGnss_V2_0>(agnss_V2_0);
}
} else if (gnssHal != nullptr) {
auto agnss_V1_0 = gnssHal->getExtensionAGnss();
if (checkHidlReturn(agnss_V1_0, "Unable to get a handle to AGnss_V1_0")) {
agnssIface = std::make_unique<gnss::AGnss_V1_0>(agnss_V1_0);
}
}
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
sp<hardware::gnss::IGnssNavigationMessageInterface> gnssNavigationMessage;
auto status = gnssHalAidl->getExtensionGnssNavigationMessage(&gnssNavigationMessage);
if (checkAidlStatus(status,
"Unable to get a handle to GnssNavigationMessage AIDL interface.")) {
gnssNavigationMessageIface =
std::make_unique<gnss::GnssNavigationMessageAidl>(gnssNavigationMessage);
}
} else if (gnssHal != nullptr) {
auto gnssNavigationMessage = gnssHal->getExtensionGnssNavigationMessage();
if (checkHidlReturn(gnssNavigationMessage,
"Unable to get a handle to GnssNavigationMessage interface.")) {
gnssNavigationMessageIface =
std::make_unique<gnss::GnssNavigationMessageHidl>(gnssNavigationMessage);
}
}
// Allow all causal combinations between IGnss.hal and IGnssMeasurement.hal. That means,
// 2.1@IGnss can be paired with {1.0, 1,1, 2.0, 2.1}@IGnssMeasurement
// 2.0@IGnss can be paired with {1.0, 1,1, 2.0}@IGnssMeasurement
// 1.1@IGnss can be paired {1.0, 1.1}@IGnssMeasurement
// 1.0@IGnss is paired with 1.0@IGnssMeasurement
gnssMeasurementIface = nullptr;
if (gnssHalAidl != nullptr) {
sp<hardware::gnss::IGnssMeasurementInterface> gnssMeasurement;
auto status = gnssHalAidl->getExtensionGnssMeasurement(&gnssMeasurement);
if (checkAidlStatus(status, "Unable to get a handle to GnssMeasurement AIDL interface.")) {
gnssMeasurementIface =
std::make_unique<android::gnss::GnssMeasurement>(gnssMeasurement);
}
}
if (gnssHal_V2_1 != nullptr && gnssMeasurementIface == nullptr) {
auto gnssMeasurement = gnssHal_V2_1->getExtensionGnssMeasurement_2_1();
if (checkHidlReturn(gnssMeasurement, "Unable to get a handle to GnssMeasurement_V2_1")) {
gnssMeasurementIface =
std::make_unique<android::gnss::GnssMeasurement_V2_1>(gnssMeasurement);
}
}
if (gnssHal_V2_0 != nullptr && gnssMeasurementIface == nullptr) {
auto gnssMeasurement = gnssHal_V2_0->getExtensionGnssMeasurement_2_0();
if (checkHidlReturn(gnssMeasurement, "Unable to get a handle to GnssMeasurement_V2_0")) {
gnssMeasurementIface =
std::make_unique<android::gnss::GnssMeasurement_V2_0>(gnssMeasurement);
}
}
if (gnssHal_V1_1 != nullptr && gnssMeasurementIface == nullptr) {
auto gnssMeasurement = gnssHal_V1_1->getExtensionGnssMeasurement_1_1();
if (checkHidlReturn(gnssMeasurement, "Unable to get a handle to GnssMeasurement_V1_1")) {
gnssMeasurementIface =
std::make_unique<android::gnss::GnssMeasurement_V1_1>(gnssMeasurement);
}
}
if (gnssHal != nullptr && gnssMeasurementIface == nullptr) {
auto gnssMeasurement = gnssHal->getExtensionGnssMeasurement();
if (checkHidlReturn(gnssMeasurement, "Unable to get a handle to GnssMeasurement_V1_0")) {
gnssMeasurementIface =
std::make_unique<android::gnss::GnssMeasurement_V1_0>(gnssMeasurement);
}
}
if (gnssHal_V2_1 != nullptr) {
auto gnssAntennaInfo = gnssHal_V2_1->getExtensionGnssAntennaInfo();
if (!gnssAntennaInfo.isOk()) {
ALOGD("Unable to get a handle to GnssAntennaInfo");
} else {
gnssAntennaInfoIface = gnssAntennaInfo;
}
}
if (gnssHal_V2_1 != nullptr) {
auto gnssCorrections = gnssHal_V2_1->getExtensionMeasurementCorrections_1_1();
if (!gnssCorrections.isOk()) {
ALOGD("Unable to get a handle to GnssMeasurementCorrections 1.1 interface");
} else {
gnssCorrectionsIface_V1_1 = gnssCorrections;
gnssCorrectionsIface_V1_0 = gnssCorrectionsIface_V1_1;
}
} else if (gnssHal_V2_0 != nullptr) {
auto gnssCorrections = gnssHal_V2_0->getExtensionMeasurementCorrections();
if (!gnssCorrections.isOk()) {
ALOGD("Unable to get a handle to GnssMeasurementCorrections interface");
} else {
gnssCorrectionsIface_V1_0 = gnssCorrections;
}
}
// Allow all causal combinations between IGnss.hal and IGnssDebug.hal. That means,
// 2.0@IGnss can be paired with {1.0, 2.0}@IGnssDebug
// 1.0@IGnss is paired with 1.0@IGnssDebug
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
sp<IGnssDebugAidl> gnssDebugAidl;
auto status = gnssHalAidl->getExtensionGnssDebug(&gnssDebugAidl);
if (checkAidlStatus(status, "Unable to get a handle to GnssDebug interface.")) {
gnssDebugIface = std::make_unique<gnss::GnssDebug>(gnssDebugAidl);
}
}
if (gnssHal_V2_0 != nullptr && gnssDebugIface == nullptr) {
auto gnssDebug_V2_0 = gnssHal_V2_0->getExtensionGnssDebug_2_0();
if (checkHidlReturn(gnssDebug_V2_0, "Unable to get a handle to GnssDebug_V2_0.")) {
gnssDebugIface = std::make_unique<gnss::GnssDebug_V2_0>(gnssDebug_V2_0);
}
}
if (gnssHal != nullptr && gnssDebugIface == nullptr) {
auto gnssDebug_V1_0 = gnssHal->getExtensionGnssDebug();
if (checkHidlReturn(gnssDebug_V1_0, "Unable to get a handle to GnssDebug_V1_0.")) {
gnssDebugIface = std::make_unique<gnss::GnssDebug_V1_0>(gnssDebug_V1_0);
}
}
if (gnssHal != nullptr) {
auto gnssNi = gnssHal->getExtensionGnssNi();
if (!gnssNi.isOk()) {
ALOGD("Unable to get a handle to GnssNi");
} else {
gnssNiIface = gnssNi;
}
}
if (gnssHalAidl != nullptr) {
sp<IGnssConfigurationAidl> gnssConfigurationAidl;
auto status = gnssHalAidl->getExtensionGnssConfiguration(&gnssConfigurationAidl);
if (checkAidlStatus(status,
"Unable to get a handle to GnssConfiguration AIDL interface.")) {
gnssConfigurationIface =
std::make_unique<android::gnss::GnssConfiguration>(gnssConfigurationAidl);
}
} else if (gnssHal_V2_1 != nullptr) {
auto gnssConfiguration = gnssHal_V2_1->getExtensionGnssConfiguration_2_1();
if (checkHidlReturn(gnssConfiguration,
"Unable to get a handle to GnssConfiguration_V2_1")) {
gnssConfigurationIface =
std::make_unique<android::gnss::GnssConfiguration_V2_1>(gnssConfiguration);
}
} else if (gnssHal_V2_0 != nullptr) {
auto gnssConfiguration = gnssHal_V2_0->getExtensionGnssConfiguration_2_0();
if (checkHidlReturn(gnssConfiguration,
"Unable to get a handle to GnssConfiguration_V2_0")) {
gnssConfigurationIface =
std::make_unique<android::gnss::GnssConfiguration_V2_0>(gnssConfiguration);
}
} else if (gnssHal_V1_1 != nullptr) {
auto gnssConfiguration = gnssHal_V1_1->getExtensionGnssConfiguration_1_1();
if (checkHidlReturn(gnssConfiguration,
"Unable to get a handle to GnssConfiguration_V1_1")) {
gnssConfigurationIface =
std::make_unique<gnss::GnssConfiguration_V1_1>(gnssConfiguration);
}
} else if (gnssHal != nullptr) {
auto gnssConfiguration = gnssHal->getExtensionGnssConfiguration();
if (checkHidlReturn(gnssConfiguration,
"Unable to get a handle to GnssConfiguration_V1_0")) {
gnssConfigurationIface =
std::make_unique<gnss::GnssConfiguration_V1_0>(gnssConfiguration);
}
}
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
sp<hardware::gnss::IGnssGeofence> gnssGeofence;
auto status = gnssHalAidl->getExtensionGnssGeofence(&gnssGeofence);
if (checkAidlStatus(status, "Unable to get a handle to GnssGeofence AIDL interface.")) {
gnssGeofencingIface = std::make_unique<gnss::GnssGeofenceAidl>(gnssGeofence);
}
} else if (gnssHal != nullptr) {
auto gnssGeofencing = gnssHal->getExtensionGnssGeofencing();
if (checkHidlReturn(gnssGeofencing, "Unable to get a handle to GnssGeofencing")) {
gnssGeofencingIface = std::make_unique<gnss::GnssGeofenceHidl>(gnssGeofencing);
}
}
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
sp<android::hardware::gnss::IGnssBatching> gnssBatchingAidl;
auto status = gnssHalAidl->getExtensionGnssBatching(&gnssBatchingAidl);
if (checkAidlStatus(status, "Unable to get a handle to GnssBatching interface.")) {
gnssBatchingIface = std::make_unique<gnss::GnssBatching>(gnssBatchingAidl);
}
} else if (gnssHal_V2_0 != nullptr) {
auto gnssBatching_V2_0 = gnssHal_V2_0->getExtensionGnssBatching_2_0();
if (checkHidlReturn(gnssBatching_V2_0, "Unable to get a handle to GnssBatching_V2_0")) {
gnssBatchingIface = std::make_unique<gnss::GnssBatching_V2_0>(gnssBatching_V2_0);
}
}
if (gnssHal != nullptr && gnssBatchingIface == nullptr) {
auto gnssBatching_V1_0 = gnssHal->getExtensionGnssBatching();
if (checkHidlReturn(gnssBatching_V1_0, "Unable to get a handle to GnssBatching")) {
gnssBatchingIface = std::make_unique<gnss::GnssBatching_V1_0>(gnssBatching_V1_0);
}
}
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
sp<android::hardware::gnss::visibility_control::IGnssVisibilityControl>
gnssVisibilityControlAidl;
auto status = gnssHalAidl->getExtensionGnssVisibilityControl(&gnssVisibilityControlAidl);
if (checkAidlStatus(status,
"Unable to get a handle to GnssVisibilityControl AIDL interface.")) {
gnssVisibilityControlIface =
std::make_unique<gnss::GnssVisibilityControlAidl>(gnssVisibilityControlAidl);
}
} else if (gnssHal_V2_0 != nullptr) {
auto gnssVisibilityControlHidl = gnssHal_V2_0->getExtensionVisibilityControl();
if (checkHidlReturn(gnssVisibilityControlHidl,
"Unable to get a handle to GnssVisibilityControl HIDL interface")) {
gnssVisibilityControlIface =
std::make_unique<gnss::GnssVisibilityControlHidl>(gnssVisibilityControlHidl);
}
}
if (gnssHalAidl != nullptr) {
sp<IGnssPowerIndication> gnssPowerIndication;
auto status = gnssHalAidl->getExtensionGnssPowerIndication(&gnssPowerIndication);
if (checkAidlStatus(status, "Unable to get a handle to GnssPowerIndication interface.")) {
gnssPowerIndicationIface = gnssPowerIndication;
}
}
if (mCallbacksObj) {
ALOGE("Callbacks already initialized");
} else {
mCallbacksObj = env->NewGlobalRef(obj);
}
}
static jboolean android_location_gnss_hal_GnssNative_is_supported(JNIEnv* /* env */, jclass) {
return (gnssHalAidl != nullptr || gnssHal != nullptr) ? JNI_TRUE : JNI_FALSE;
}
static jboolean android_location_GnssNetworkConnectivityHandler_is_agps_ril_supported(
JNIEnv* /* env */, jclass /* clazz */) {
return (agnssRilIface != nullptr) ? JNI_TRUE : JNI_FALSE;
}
static jobject android_location_GnssConfiguration_get_gnss_configuration_version(
JNIEnv* env, jclass /* jclazz */) {
if (gnssConfigurationIface == nullptr) {
return nullptr;
}
return gnssConfigurationIface->getVersion(env);
}
/* Initialization needed each time the GPS service is shutdown. */
static jboolean android_location_gnss_hal_GnssNative_init(JNIEnv* /* env */, jclass) {
/*
* This must be set before calling into the HAL library.
*/
if (!mCallbacksObj) {
ALOGE("No callbacks set during GNSS HAL initialization.");
return JNI_FALSE;
}
/*
* Fail if the main interface fails to initialize
*/
if (gnssHal == nullptr && gnssHalAidl == nullptr) {
ALOGE("Unable to initialize GNSS HAL.");
return JNI_FALSE;
}
// Set top level IGnss.hal callback.
if (gnssHal != nullptr) {
Return<bool> result = false;
sp<IGnssCallback_V2_1> gnssCbIface = new GnssCallback();
if (gnssHal_V2_1 != nullptr) {
result = gnssHal_V2_1->setCallback_2_1(gnssCbIface);
} else if (gnssHal_V2_0 != nullptr) {
result = gnssHal_V2_0->setCallback_2_0(gnssCbIface);
} else if (gnssHal_V1_1 != nullptr) {
result = gnssHal_V1_1->setCallback_1_1(gnssCbIface);
} else {
result = gnssHal->setCallback(gnssCbIface);
}
if (!checkHidlReturn(result, "IGnss setCallback() failed.")) {
return JNI_FALSE;
}
}
if (gnssHalAidl != nullptr) {
sp<IGnssCallbackAidl> gnssCbIfaceAidl = new GnssCallbackAidl();
auto status = gnssHalAidl->setCallback(gnssCbIfaceAidl);
if (!checkAidlStatus(status, "IGnssAidl setCallback() failed.")) {
return JNI_FALSE;
}
}
// Set IGnssPsds or IGnssXtra callback.
if (gnssPsdsAidlIface != nullptr) {
sp<IGnssPsdsCallbackAidl> gnssPsdsCallbackAidl = new GnssPsdsCallbackAidl();
auto status = gnssPsdsAidlIface->setCallback(gnssPsdsCallbackAidl);
if (!checkAidlStatus(status, "IGnssPsdsAidl setCallback() failed.")) {
gnssPsdsAidlIface = nullptr;
}
} else if (gnssXtraIface != nullptr) {
sp<IGnssXtraCallback> gnssXtraCbIface = new GnssXtraCallback();
auto result = gnssXtraIface->setCallback(gnssXtraCbIface);
if (!checkHidlReturn(result, "IGnssXtra setCallback() failed.")) {
gnssXtraIface = nullptr;
} else {
ALOGI("Unable to initialize IGnssXtra interface.");
}
}
// Set IAGnss callback.
if (agnssIface == nullptr ||
!agnssIface->setCallback(std::make_unique<gnss::AGnssCallback>())) {
ALOGI("Unable to initialize IAGnss interface.");
}
// Set GnssGeofence callback.
if (gnssGeofencingIface != nullptr) {
gnssGeofencingIface->setCallback(std::make_unique<gnss::GnssGeofenceCallback>());
} else {
ALOGI("Unable to initialize IGnssGeofencing interface.");
}
// Set IGnssNi.hal callback.
sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
if (gnssNiIface != nullptr) {
auto status = gnssNiIface->setCallback(gnssNiCbIface);
checkHidlReturn(status, "IGnssNi setCallback() failed.");
} else {
ALOGI("Unable to initialize IGnssNi interface.");
}
// Set IAGnssRil callback.
if (agnssRilIface == nullptr ||
!agnssRilIface->setCallback(std::make_unique<gnss::AGnssRilCallback>())) {
ALOGI("Unable to initialize IAGnssRil interface.");
}
// Set IGnssVisibilityControl callback.
if (gnssVisibilityControlIface != nullptr) {
gnssVisibilityControlIface->setCallback(
std::make_unique<gnss::GnssVisibilityControlCallback>());
} else {
ALOGI("Unable to initialize IGnssVisibilityControl interface.");
}
// Set IMeasurementCorrections.hal callback.
if (gnssCorrectionsIface_V1_1 != nullptr) {
sp<IMeasurementCorrectionsCallback> gnssCorrectionsIfaceCbIface =
new MeasurementCorrectionsCallback();
auto result = gnssCorrectionsIface_V1_1->setCallback(gnssCorrectionsIfaceCbIface);
checkHidlReturn(result, "IMeasurementCorrections 1.1 setCallback() failed.");
} else if (gnssCorrectionsIface_V1_0 != nullptr) {
sp<IMeasurementCorrectionsCallback> gnssCorrectionsIfaceCbIface =
new MeasurementCorrectionsCallback();
auto result = gnssCorrectionsIface_V1_0->setCallback(gnssCorrectionsIfaceCbIface);
checkHidlReturn(result, "IMeasurementCorrections 1.0 setCallback() failed.");
} else {
ALOGI("Unable to find IMeasurementCorrections.");
}
// Set IGnssPowerIndication.hal callback.
if (gnssPowerIndicationIface != nullptr) {
sp<IGnssPowerIndicationCallback> gnssPowerIndicationCallback =
new GnssPowerIndicationCallback();
auto status = gnssPowerIndicationIface->setCallback(gnssPowerIndicationCallback);
if (!checkAidlStatus(status, "IGnssPowerIndication setCallback() failed.")) {
gnssPowerIndicationIface = nullptr;
}
}
return JNI_TRUE;
}
static void android_location_gnss_hal_GnssNative_cleanup(JNIEnv* /* env */, jclass) {
if (gnssHalAidl != nullptr) {
auto status = gnssHalAidl->close();
checkAidlStatus(status, "IGnssAidl close() failed.");
}
if (gnssHal != nullptr) {
auto result = gnssHal->cleanup();
checkHidlReturn(result, "IGnss cleanup() failed.");
}
}
static jboolean android_location_gnss_hal_GnssNative_set_position_mode(
JNIEnv* /* env */, jclass, jint mode, jint recurrence, jint min_interval,
jint preferred_accuracy, jint preferred_time, jboolean low_power_mode) {
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
auto status = gnssHalAidl->setPositionMode(static_cast<IGnssAidl::GnssPositionMode>(mode),
static_cast<IGnssAidl::GnssPositionRecurrence>(
recurrence),
min_interval, preferred_accuracy, preferred_time,
low_power_mode);
return checkAidlStatus(status, "IGnssAidl setPositionMode() failed.");
}
Return<bool> result = false;
if (gnssHal_V1_1 != nullptr) {
result = gnssHal_V1_1->setPositionMode_1_1(static_cast<IGnss_V1_0::GnssPositionMode>(mode),
static_cast<IGnss_V1_0::GnssPositionRecurrence>(recurrence),
min_interval,
preferred_accuracy,
preferred_time,
low_power_mode);
} else if (gnssHal != nullptr) {
result = gnssHal->setPositionMode(static_cast<IGnss_V1_0::GnssPositionMode>(mode),
static_cast<IGnss_V1_0::GnssPositionRecurrence>(recurrence),
min_interval,
preferred_accuracy,
preferred_time);
}
return checkHidlReturn(result, "IGnss setPositionMode() failed.");
}
static jboolean android_location_gnss_hal_GnssNative_start(JNIEnv* /* env */, jclass) {
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
auto status = gnssHalAidl->start();
return checkAidlStatus(status, "IGnssAidl start() failed.");
}
if (gnssHal == nullptr) {
return JNI_FALSE;
}
auto result = gnssHal->start();
return checkHidlReturn(result, "IGnss start() failed.");
}
static jboolean android_location_gnss_hal_GnssNative_stop(JNIEnv* /* env */, jclass) {
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
auto status = gnssHalAidl->stop();
return checkAidlStatus(status, "IGnssAidl stop() failed.");
}
if (gnssHal == nullptr) {
return JNI_FALSE;
}
auto result = gnssHal->stop();
return checkHidlReturn(result, "IGnss stop() failed.");
}
static void android_location_gnss_hal_GnssNative_delete_aiding_data(JNIEnv* /* env */, jclass,
jint flags) {
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
auto status = gnssHalAidl->deleteAidingData(static_cast<IGnssAidl::GnssAidingData>(flags));
checkAidlStatus(status, "IGnssAidl deleteAidingData() failed.");
return;
}
if (gnssHal == nullptr) {
return;
}
auto result = gnssHal->deleteAidingData(static_cast<IGnss_V1_0::GnssAidingData>(flags));
checkHidlReturn(result, "IGnss deleteAidingData() failed.");
}
static void android_location_gnss_hal_GnssNative_agps_set_reference_location_cellid(
JNIEnv* /* env */, jclass, jint type, jint mcc, jint mnc, jint lac, jlong cid, jint tac,
jint pcid, jint arfcn) {
if (agnssRilIface == nullptr) {
ALOGE("%s: IAGnssRil interface not available.", __func__);
return;
}
agnssRilIface->setRefLocation(type, mcc, mnc, lac, cid, tac, pcid, arfcn);
}
static void android_location_gnss_hal_GnssNative_agps_set_id(JNIEnv* env, jclass, jint type,
jstring setid_string) {
if (agnssRilIface == nullptr) {
ALOGE("%s: IAGnssRil interface not available.", __func__);
return;
}
agnssRilIface->setSetId(type, setid_string);
}
static jint android_location_gnss_hal_GnssNative_read_nmea(JNIEnv* env, jclass,
jbyteArray nmeaArray, jint buffer_size) {
// this should only be called from within a call to reportNmea
jbyte* nmea = reinterpret_cast<jbyte *>(env->GetPrimitiveArrayCritical(nmeaArray, 0));
int length = GnssCallback::sNmeaStringLength;
if (length > buffer_size)
length = buffer_size;
memcpy(nmea, GnssCallback::sNmeaString, length);
env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
return (jint) length;
}
static void android_location_gnss_hal_GnssNative_inject_time(JNIEnv* /* env */, jclass, jlong time,
jlong timeReference,
jint uncertainty) {
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
auto status = gnssHalAidl->injectTime(time, timeReference, uncertainty);
checkAidlStatus(status, "IGnssAidl injectTime() failed.");
return;
}
if (gnssHal == nullptr) {
return;
}
auto result = gnssHal->injectTime(time, timeReference, uncertainty);
checkHidlReturn(result, "IGnss injectTime() failed.");
}
static void android_location_gnss_hal_GnssNative_inject_best_location(
JNIEnv* /* env */, jclass, jint gnssLocationFlags, jdouble latitudeDegrees,
jdouble longitudeDegrees, jdouble altitudeMeters, jfloat speedMetersPerSec,
jfloat bearingDegrees, jfloat horizontalAccuracyMeters, jfloat verticalAccuracyMeters,
jfloat speedAccuracyMetersPerSecond, jfloat bearingAccuracyDegrees, jlong timestamp,
jint elapsedRealtimeFlags, jlong elapsedRealtimeNanos,
jdouble elapsedRealtimeUncertaintyNanos) {
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
GnssLocationAidl location =
createGnssLocation(gnssLocationFlags, latitudeDegrees, longitudeDegrees,
altitudeMeters, speedMetersPerSec, bearingDegrees,
horizontalAccuracyMeters, verticalAccuracyMeters,
speedAccuracyMetersPerSecond, bearingAccuracyDegrees, timestamp,
elapsedRealtimeFlags, elapsedRealtimeNanos,
elapsedRealtimeUncertaintyNanos);
auto status = gnssHalAidl->injectBestLocation(location);
checkAidlStatus(status, "IGnssAidl injectBestLocation() failed.");
return;
}
if (gnssHal_V2_0 != nullptr) {
GnssLocation_V2_0 location = createGnssLocation_V2_0(
gnssLocationFlags,
latitudeDegrees,
longitudeDegrees,
altitudeMeters,
speedMetersPerSec,
bearingDegrees,
horizontalAccuracyMeters,
verticalAccuracyMeters,
speedAccuracyMetersPerSecond,
bearingAccuracyDegrees,
timestamp,
elapsedRealtimeFlags,
elapsedRealtimeNanos,
elapsedRealtimeUncertaintyNanos);
auto result = gnssHal_V2_0->injectBestLocation_2_0(location);
checkHidlReturn(result, "IGnss injectBestLocation_2_0() failed.");
return;
}
if (gnssHal_V1_1 != nullptr) {
GnssLocation_V1_0 location = createGnssLocation_V1_0(
gnssLocationFlags,
latitudeDegrees,
longitudeDegrees,
altitudeMeters,
speedMetersPerSec,
bearingDegrees,
horizontalAccuracyMeters,
verticalAccuracyMeters,
speedAccuracyMetersPerSecond,
bearingAccuracyDegrees,
timestamp);
auto result = gnssHal_V1_1->injectBestLocation(location);
checkHidlReturn(result, "IGnss injectBestLocation() failed.");
}
ALOGE("IGnss injectBestLocation() is called but gnssHal_V1_1 is not available.");
}
static void android_location_gnss_hal_GnssNative_inject_location(
JNIEnv* /* env */, jclass, jint gnssLocationFlags, jdouble latitudeDegrees,
jdouble longitudeDegrees, jdouble altitudeMeters, jfloat speedMetersPerSec,
jfloat bearingDegrees, jfloat horizontalAccuracyMeters, jfloat verticalAccuracyMeters,
jfloat speedAccuracyMetersPerSecond, jfloat bearingAccuracyDegrees, jlong timestamp,
jint elapsedRealtimeFlags, jlong elapsedRealtimeNanos,
jdouble elapsedRealtimeUncertaintyNanos) {
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
GnssLocationAidl location =
createGnssLocation(gnssLocationFlags, latitudeDegrees, longitudeDegrees,
altitudeMeters, speedMetersPerSec, bearingDegrees,
horizontalAccuracyMeters, verticalAccuracyMeters,
speedAccuracyMetersPerSecond, bearingAccuracyDegrees, timestamp,
elapsedRealtimeFlags, elapsedRealtimeNanos,
elapsedRealtimeUncertaintyNanos);
auto status = gnssHalAidl->injectLocation(location);
checkAidlStatus(status, "IGnssAidl injectLocation() failed.");
return;
}
if (gnssHal == nullptr) {
return;
}
auto result =
gnssHal->injectLocation(latitudeDegrees, longitudeDegrees, horizontalAccuracyMeters);
checkHidlReturn(result, "IGnss injectLocation() failed.");
}
static jboolean android_location_gnss_hal_GnssNative_supports_psds(JNIEnv* /* env */, jclass) {
return (gnssPsdsAidlIface != nullptr || gnssXtraIface != nullptr) ? JNI_TRUE : JNI_FALSE;
}
static void android_location_gnss_hal_GnssNative_inject_psds_data(JNIEnv* env, jclass,
jbyteArray data, jint length,
jint psdsType) {
if (gnssPsdsAidlIface == nullptr && gnssXtraIface == nullptr) {
ALOGE("%s: IGnssPsdsAidl or IGnssXtra interface not available.", __func__);
return;
}
jbyte* bytes = reinterpret_cast<jbyte *>(env->GetPrimitiveArrayCritical(data, 0));
if (gnssPsdsAidlIface != nullptr) {
auto status = gnssPsdsAidlIface->injectPsdsData(static_cast<PsdsType>(psdsType),
std::vector<uint8_t>((const uint8_t*)bytes,
(const uint8_t*)bytes +
length));
checkAidlStatus(status, "IGnssPsdsAidl injectPsdsData() failed.");
} else if (gnssXtraIface != nullptr) {
auto result = gnssXtraIface->injectXtraData(std::string((const char*)bytes, length));
checkHidlReturn(result, "IGnssXtra injectXtraData() failed.");
}
env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
}
static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_open(
JNIEnv* env, jobject /* obj */, jlong networkHandle, jstring apn, jint apnIpType) {
if (apn == nullptr) {
jniThrowException(env, "java/lang/IllegalArgumentException", nullptr);
return;
}
if (agnssIface != nullptr) {
agnssIface->dataConnOpen(env, networkHandle, apn, apnIpType);
} else {
ALOGE("%s: IAGnss interface not available.", __func__);
return;
}
}
static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_closed(JNIEnv* /* env */,
jobject /* obj */) {
if (agnssIface != nullptr) {
agnssIface->dataConnClosed();
} else {
ALOGE("%s: IAGnss interface not available.", __func__);
return;
}
}
static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_failed(JNIEnv* /* env */,
jobject /* obj */) {
if (agnssIface != nullptr) {
agnssIface->dataConnFailed();
} else {
ALOGE("%s: IAGnss interface not available.", __func__);
return;
}
}
static void android_location_gnss_hal_GnssNative_set_agps_server(JNIEnv* env, jclass, jint type,
jstring hostname, jint port) {
if (agnssIface != nullptr) {
agnssIface->setServer(env, type, hostname, port);
} else {
ALOGE("%s: IAGnss interface not available.", __func__);
return;
}
}
static void android_location_gnss_hal_GnssNative_send_ni_response(JNIEnv* /* env */, jclass,
jint notifId, jint response) {
if (gnssNiIface == nullptr) {
ALOGE("%s: IGnssNi interface not available.", __func__);
return;
}
auto result = gnssNiIface->respond(notifId,
static_cast<IGnssNiCallback::GnssUserResponseType>(response));
checkHidlReturn(result, "IGnssNi respond() failed.");
}
static jstring android_location_gnss_hal_GnssNative_get_internal_state(JNIEnv* env, jclass) {
/*
* TODO: Create a jobject to represent GnssDebug.
*/
if (gnssDebugIface == nullptr) {
ALOGE("%s: IGnssDebug interface not available.", __func__);
return nullptr;
}
return gnssDebugIface->getDebugData(env);
}
static void android_location_gnss_hal_GnssNative_request_power_stats(JNIEnv* env) {
if (gnssPowerIndicationIface == nullptr) {
return;
}
auto status = gnssPowerIndicationIface->requestGnssPowerStats();
checkAidlStatus(status, "IGnssPowerIndication requestGnssPowerStats() failed.");
}
static jboolean android_location_gnss_hal_GnssNative_is_gnss_visibility_control_supported(
JNIEnv* /* env */, jclass) {
return (gnssVisibilityControlIface != nullptr) ? JNI_TRUE : JNI_FALSE;
}
static void android_location_GnssNetworkConnectivityHandler_update_network_state(JNIEnv* env,
jobject /* obj */,
jboolean connected,
jint type,
jboolean roaming,
jboolean available,
jstring apn,
jlong networkHandle,
jshort capabilities) {
if (agnssRilIface == nullptr) {
ALOGE("%s: IAGnssRil interface not available.", __func__);
return;
}
agnssRilIface->updateNetworkState(connected, type, roaming, available, apn, networkHandle,
capabilities);
}
static jboolean android_location_gnss_hal_GnssNative_is_geofence_supported(JNIEnv* /* env */,
jclass) {
if (gnssGeofencingIface == nullptr) {
return JNI_FALSE;
}
return JNI_TRUE;
}
static jboolean android_location_gnss_hal_GnssNative_add_geofence(
JNIEnv* /* env */, jclass, jint geofenceId, jdouble latitude, jdouble longitude,
jdouble radius, jint last_transition, jint monitor_transition,
jint notification_responsiveness, jint unknown_timer) {
if (gnssGeofencingIface == nullptr) {
ALOGE("%s: IGnssGeofencing interface not available.", __func__);
return JNI_FALSE;
}
return gnssGeofencingIface->addGeofence(geofenceId, latitude, longitude, radius,
last_transition, monitor_transition,
notification_responsiveness, unknown_timer);
}
static jboolean android_location_gnss_hal_GnssNative_remove_geofence(JNIEnv* /* env */, jclass,
jint geofenceId) {
if (gnssGeofencingIface == nullptr) {
ALOGE("%s: IGnssGeofencing interface not available.", __func__);
return JNI_FALSE;
}
return gnssGeofencingIface->removeGeofence(geofenceId);
}
static jboolean android_location_gnss_hal_GnssNative_pause_geofence(JNIEnv* /* env */, jclass,
jint geofenceId) {
if (gnssGeofencingIface == nullptr) {
ALOGE("%s: IGnssGeofencing interface not available.", __func__);
return JNI_FALSE;
}
return gnssGeofencingIface->pauseGeofence(geofenceId);
}
static jboolean android_location_gnss_hal_GnssNative_resume_geofence(JNIEnv* /* env */, jclass,
jint geofenceId,
jint monitor_transition) {
if (gnssGeofencingIface == nullptr) {
ALOGE("%s: IGnssGeofencing interface not available.", __func__);
return JNI_FALSE;
}
return gnssGeofencingIface->resumeGeofence(geofenceId, monitor_transition);
}
static jboolean android_location_gnss_hal_GnssNative_is_antenna_info_supported(JNIEnv* env,
jclass) {
if (gnssAntennaInfoIface != nullptr) {
return JNI_TRUE;
}
return JNI_FALSE;
}
static jboolean android_location_gnss_hal_GnssNative_start_antenna_info_listening(JNIEnv* /* env */,
jclass) {
if (gnssAntennaInfoIface == nullptr) {
ALOGE("%s: IGnssAntennaInfo interface not available.", __func__);
return JNI_FALSE;
}
sp<gnss::GnssAntennaInfoCallback> cbIface = new gnss::GnssAntennaInfoCallback(mCallbacksObj);
auto result = gnssAntennaInfoIface->setCallback(cbIface);
if (!checkHidlReturn(result, "IGnssAntennaInfo setCallback() failed.")) {
return JNI_FALSE;
}
IGnssAntennaInfo::GnssAntennaInfoStatus initRet = result;
if (initRet != IGnssAntennaInfo::GnssAntennaInfoStatus::SUCCESS) {
ALOGE("An error has been found on GnssAntennaInfoInterface::init, status=%d",
static_cast<int32_t>(initRet));
return JNI_FALSE;
} else {
ALOGD("gnss antenna info has been enabled");
}
return JNI_TRUE;
}
static jboolean android_location_gnss_hal_GnssNative_stop_antenna_info_listening(JNIEnv* /* env */,
jclass) {
if (gnssAntennaInfoIface == nullptr) {
ALOGE("%s: IGnssAntennaInfo interface not available.", __func__);
return JNI_FALSE;
}
auto result = gnssAntennaInfoIface->close();
return checkHidlReturn(result, "IGnssAntennaInfo close() failed.");
}
static jboolean android_location_gnss_hal_GnssNative_is_measurement_supported(JNIEnv* env, jclass) {
if (gnssMeasurementIface != nullptr) {
return JNI_TRUE;
}
return JNI_FALSE;
}
static jboolean android_location_gnss_hal_GnssNative_start_measurement_collection(
JNIEnv* /* env */, jclass, jboolean enableFullTracking, jboolean enableCorrVecOutputs,
jint intervalMs) {
if (gnssMeasurementIface == nullptr) {
ALOGE("%s: IGnssMeasurement interface not available.", __func__);
return JNI_FALSE;
}
hardware::gnss::IGnssMeasurementInterface::Options options;
options.enableFullTracking = enableFullTracking;
options.enableCorrVecOutputs = enableCorrVecOutputs;
options.intervalMs = intervalMs;
return gnssMeasurementIface->setCallback(std::make_unique<gnss::GnssMeasurementCallback>(
mCallbacksObj),
options);
}
static jboolean android_location_gnss_hal_GnssNative_stop_measurement_collection(JNIEnv* env,
jclass) {
if (gnssMeasurementIface == nullptr) {
ALOGE("%s: IGnssMeasurement interface not available.", __func__);
return JNI_FALSE;
}
return gnssMeasurementIface->close();
}
static jboolean android_location_gnss_hal_GnssNative_is_measurement_corrections_supported(
JNIEnv* env, jclass) {
if (gnssCorrectionsIface_V1_0 != nullptr || gnssCorrectionsIface_V1_1 != nullptr) {
return JNI_TRUE;
}
return JNI_FALSE;
}
static SingleSatCorrection_V1_0 getSingleSatCorrection_1_0_withoutConstellation(
JNIEnv* env, jobject singleSatCorrectionObj) {
jint correctionFlags = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatFlags);
jint satId = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatId);
jfloat carrierFreqHz =
env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatCarrierFreq);
jfloat probSatIsLos =
env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatIsLosProb);
jfloat eplMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEpl);
jfloat eplUncMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEplUnc);
uint16_t corrFlags = static_cast<uint16_t>(correctionFlags);
jobject reflectingPlaneObj;
bool has_ref_plane = (corrFlags & GnssSingleSatCorrectionFlags::HAS_REFLECTING_PLANE) != 0;
if (has_ref_plane) {
reflectingPlaneObj =
env->CallObjectMethod(singleSatCorrectionObj, method_correctionSatRefPlane);
}
ReflectingPlane reflectingPlane;
if (has_ref_plane) {
jdouble latitudeDegreesRefPlane =
env->CallDoubleMethod(reflectingPlaneObj, method_correctionPlaneLatDeg);
jdouble longitudeDegreesRefPlane =
env->CallDoubleMethod(reflectingPlaneObj, method_correctionPlaneLngDeg);
jdouble altitudeDegreesRefPlane =
env->CallDoubleMethod(reflectingPlaneObj, method_correctionPlaneAltDeg);
jdouble azimuthDegreeRefPlane =
env->CallDoubleMethod(reflectingPlaneObj, method_correctionPlaneAzimDeg);
reflectingPlane = {
.latitudeDegrees = latitudeDegreesRefPlane,
.longitudeDegrees = longitudeDegreesRefPlane,
.altitudeMeters = altitudeDegreesRefPlane,
.azimuthDegrees = azimuthDegreeRefPlane,
};
}
SingleSatCorrection_V1_0 singleSatCorrection = {
.singleSatCorrectionFlags = corrFlags,
.svid = static_cast<uint16_t>(satId),
.carrierFrequencyHz = carrierFreqHz,
.probSatIsLos = probSatIsLos,
.excessPathLengthMeters = eplMeters,
.excessPathLengthUncertaintyMeters = eplUncMeters,
.reflectingPlane = reflectingPlane,
};
return singleSatCorrection;
}
static void getSingleSatCorrectionList_1_1(JNIEnv* env, jobject singleSatCorrectionList,
hidl_vec<SingleSatCorrection_V1_1>& list) {
for (uint16_t i = 0; i < list.size(); ++i) {
jobject singleSatCorrectionObj =
env->CallObjectMethod(singleSatCorrectionList, method_correctionListGet, i);
SingleSatCorrection_V1_0 singleSatCorrection_1_0 =
getSingleSatCorrection_1_0_withoutConstellation(env, singleSatCorrectionObj);
jint constType = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatConstType);
SingleSatCorrection_V1_1 singleSatCorrection_1_1 = {
.v1_0 = singleSatCorrection_1_0,
.constellation = static_cast<GnssConstellationType_V2_0>(constType),
};
list[i] = singleSatCorrection_1_1;
}
}
static void getSingleSatCorrectionList_1_0(JNIEnv* env, jobject singleSatCorrectionList,
hidl_vec<SingleSatCorrection_V1_0>& list) {
for (uint16_t i = 0; i < list.size(); ++i) {
jobject singleSatCorrectionObj =
env->CallObjectMethod(singleSatCorrectionList, method_correctionListGet, i);
SingleSatCorrection_V1_0 singleSatCorrection =
getSingleSatCorrection_1_0_withoutConstellation(env, singleSatCorrectionObj);
jint constType = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatConstType);
singleSatCorrection.constellation = static_cast<GnssConstellationType_V1_0>(constType),
list[i] = singleSatCorrection;
}
}
static jboolean android_location_gnss_hal_GnssNative_inject_measurement_corrections(
JNIEnv* env, jclass, jobject correctionsObj) {
if (gnssCorrectionsIface_V1_0 == nullptr && gnssCorrectionsIface_V1_1 == nullptr) {
ALOGW("Trying to inject GNSS measurement corrections on a chipset that does not"
" support them.");
return JNI_FALSE;
}
jobject singleSatCorrectionList = env->CallObjectMethod(correctionsObj,
method_correctionsGetSingleSatCorrectionList);
auto len = (singleSatCorrectionList == nullptr)
? 0
: env->CallIntMethod(singleSatCorrectionList, method_listSize);
if (len == 0) {
ALOGI("Empty correction list injected....Returning with no HAL injection");
return JNI_TRUE;
}
jdouble latitudeDegreesCorr = env->CallDoubleMethod(
correctionsObj, method_correctionsGetLatitudeDegrees);
jdouble longitudeDegreesCorr = env->CallDoubleMethod(
correctionsObj, method_correctionsGetLongitudeDegrees);
jdouble altitudeDegreesCorr = env->CallDoubleMethod(
correctionsObj, method_correctionsGetAltitudeMeters);
jdouble horizontalPositionUncertaintyMeters = env->CallDoubleMethod(
correctionsObj, method_correctionsGetHorPosUncMeters);
jdouble verticalPositionUncertaintyMeters = env->CallDoubleMethod(
correctionsObj, method_correctionsGetVerPosUncMeters);
jlong toaGpsNanosOfWeek = env->CallLongMethod(
correctionsObj, method_correctionsGetToaGpsNanosecondsOfWeek);
MeasurementCorrections_V1_0 measurementCorrections_1_0 = {
.latitudeDegrees = latitudeDegreesCorr,
.longitudeDegrees = longitudeDegreesCorr,
.altitudeMeters = altitudeDegreesCorr,
.horizontalPositionUncertaintyMeters = horizontalPositionUncertaintyMeters,
.verticalPositionUncertaintyMeters = verticalPositionUncertaintyMeters,
.toaGpsNanosecondsOfWeek = static_cast<uint64_t>(toaGpsNanosOfWeek),
};
if (gnssCorrectionsIface_V1_1 != nullptr) {
jboolean hasEnvironmentBearingCorr = env->CallBooleanMethod(
correctionsObj, method_correctionsHasEnvironmentBearing);
jfloat environmentBearingDegreesCorr = env->CallFloatMethod(
correctionsObj, method_correctionsGetEnvironmentBearingDegrees);
jfloat environmentBearingUncertaintyDegreesCorr = env->CallFloatMethod(
correctionsObj, method_correctionsGetEnvironmentBearingUncertaintyDegrees);
hidl_vec<SingleSatCorrection_V1_1> list(len);
getSingleSatCorrectionList_1_1(env, singleSatCorrectionList, list);
MeasurementCorrections_V1_1 measurementCorrections_1_1 = {
.v1_0 = measurementCorrections_1_0,
.hasEnvironmentBearing = static_cast<bool>(hasEnvironmentBearingCorr),
.environmentBearingDegrees = environmentBearingDegreesCorr,
.environmentBearingUncertaintyDegrees = environmentBearingUncertaintyDegreesCorr,
.satCorrections = list,
};
auto result = gnssCorrectionsIface_V1_1->setCorrections_1_1(measurementCorrections_1_1);
return checkHidlReturn(result, "IMeasurementCorrections 1.1 setCorrections() failed.");
}
hidl_vec<SingleSatCorrection_V1_0> list(len);
getSingleSatCorrectionList_1_0(env, singleSatCorrectionList, list);
measurementCorrections_1_0.satCorrections = list;
auto result = gnssCorrectionsIface_V1_0->setCorrections(measurementCorrections_1_0);
return checkHidlReturn(result, "IMeasurementCorrections 1.0 setCorrections() failed.");
}
static jboolean android_location_gnss_hal_GnssNative_is_navigation_message_supported(JNIEnv* env,
jclass) {
if (gnssNavigationMessageIface != nullptr) {
return JNI_TRUE;
}
return JNI_FALSE;
}
static jboolean android_location_gnss_hal_GnssNative_start_navigation_message_collection(
JNIEnv* env, jclass) {
if (gnssNavigationMessageIface == nullptr) {
ALOGE("%s: IGnssNavigationMessage interface not available.", __func__);
return JNI_FALSE;
}
return gnssNavigationMessageIface->setCallback(
std::make_unique<gnss::GnssNavigationMessageCallback>());
}
static jboolean android_location_gnss_hal_GnssNative_stop_navigation_message_collection(JNIEnv* env,
jclass) {
if (gnssNavigationMessageIface == nullptr) {
ALOGE("%s: IGnssNavigationMessage interface not available.", __func__);
return JNI_FALSE;
}
return gnssNavigationMessageIface->close();
}
static jboolean android_location_GnssConfiguration_set_emergency_supl_pdn(JNIEnv*,
jobject,
jint emergencySuplPdn) {
if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
return gnssConfigurationIface->setEmergencySuplPdn(emergencySuplPdn);
}
static jboolean android_location_GnssConfiguration_set_supl_version(JNIEnv*,
jobject,
jint version) {
if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
return gnssConfigurationIface->setSuplVersion(version);
}
static jboolean android_location_GnssConfiguration_set_supl_es(JNIEnv*,
jobject,
jint suplEs) {
if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
return gnssConfigurationIface->setSuplEs(suplEs);
}
static jboolean android_location_GnssConfiguration_set_supl_mode(JNIEnv*,
jobject,
jint mode) {
if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
return gnssConfigurationIface->setSuplMode(mode);
}
static jboolean android_location_GnssConfiguration_set_gps_lock(JNIEnv*,
jobject,
jint gpsLock) {
if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
return gnssConfigurationIface->setGpsLock(gpsLock);
}
static jboolean android_location_GnssConfiguration_set_lpp_profile(JNIEnv*,
jobject,
jint lppProfile) {
if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
return gnssConfigurationIface->setLppProfile(lppProfile);
}
static jboolean android_location_GnssConfiguration_set_gnss_pos_protocol_select(JNIEnv*,
jobject,
jint gnssPosProtocol) {
if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
return gnssConfigurationIface->setGlonassPositioningProtocol(gnssPosProtocol);
}
static jboolean android_location_GnssConfiguration_set_satellite_blocklist(JNIEnv* env, jobject,
jintArray constellations,
jintArray sv_ids) {
if (gnssConfigurationIface == nullptr) {
ALOGI("IGnssConfiguration interface does not support satellite blocklist.");
return JNI_FALSE;
}
return gnssConfigurationIface->setBlocklist(env, constellations, sv_ids);
}
static jboolean android_location_GnssConfiguration_set_es_extension_sec(
JNIEnv*, jobject, jint emergencyExtensionSeconds) {
if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
return gnssConfigurationIface->setEsExtensionSec(emergencyExtensionSeconds);
}
static jint android_location_gnss_hal_GnssNative_get_batch_size(JNIEnv*) {
if (gnssBatchingIface == nullptr) {
return 0; // batching not supported, size = 0
}
return gnssBatchingIface->getBatchSize();
}
static jboolean android_location_gnss_hal_GnssNative_init_batching(JNIEnv*, jclass) {
if (gnssBatchingIface == nullptr) {
return JNI_FALSE; // batching not supported
}
return gnssBatchingIface->init(std::make_unique<gnss::GnssBatchingCallback>());
}
static void android_location_gnss_hal_GnssNative_cleanup_batching(JNIEnv*, jclass) {
if (gnssBatchingIface == nullptr) {
return; // batching not supported
}
gnssBatchingIface->cleanup();
}
static jboolean android_location_gnss_hal_GnssNative_start_batch(JNIEnv*, jclass, jlong periodNanos,
jfloat minUpdateDistanceMeters,
jboolean wakeOnFifoFull) {
if (gnssBatchingIface == nullptr) {
return JNI_FALSE; // batching not supported
}
return gnssBatchingIface->start(periodNanos, minUpdateDistanceMeters, wakeOnFifoFull);
}
static void android_location_gnss_hal_GnssNative_flush_batch(JNIEnv*, jclass) {
if (gnssBatchingIface == nullptr) {
return; // batching not supported
}
gnssBatchingIface->flush();
}
static jboolean android_location_gnss_hal_GnssNative_stop_batch(JNIEnv*, jclass) {
if (gnssBatchingIface == nullptr) {
return JNI_FALSE; // batching not supported
}
return gnssBatchingIface->stop();
}
static jboolean android_location_GnssVisibilityControl_enable_nfw_location_access(
JNIEnv* env, jobject, jobjectArray proxyApps) {
if (gnssVisibilityControlIface == nullptr) {
ALOGI("IGnssVisibilityControl interface not available.");
return JNI_FALSE;
}
return gnssVisibilityControlIface->enableNfwLocationAccess(env, proxyApps);
}
static const JNINativeMethod sCoreMethods[] = {
/* name, signature, funcPtr */
{"native_class_init_once", "()V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_class_init_once)},
{"native_is_supported", "()Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_is_supported)},
{"native_init_once", "(Z)V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_init_once)},
};
static const JNINativeMethod sLocationProviderMethods[] = {
/* name, signature, funcPtr */
{"native_init", "()Z", reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_init)},
{"native_cleanup", "()V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_cleanup)},
{"native_set_position_mode", "(IIIIIZ)Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_set_position_mode)},
{"native_start", "()Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_start)},
{"native_stop", "()Z", reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_stop)},
{"native_delete_aiding_data", "(I)V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_delete_aiding_data)},
{"native_read_nmea", "([BI)I",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_read_nmea)},
{"native_inject_time", "(JJI)V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_inject_time)},
{"native_inject_best_location", "(IDDDFFFFFFJIJD)V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_inject_best_location)},
{"native_inject_location", "(IDDDFFFFFFJIJD)V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_inject_location)},
{"native_supports_psds", "()Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_supports_psds)},
{"native_inject_psds_data", "([BII)V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_inject_psds_data)},
{"native_agps_set_id", "(ILjava/lang/String;)V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_agps_set_id)},
{"native_agps_set_ref_location_cellid", "(IIIIJIII)V",
reinterpret_cast<void*>(
android_location_gnss_hal_GnssNative_agps_set_reference_location_cellid)},
{"native_set_agps_server", "(ILjava/lang/String;I)V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_set_agps_server)},
{"native_send_ni_response", "(II)V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_send_ni_response)},
{"native_get_internal_state", "()Ljava/lang/String;",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_get_internal_state)},
{"native_is_gnss_visibility_control_supported", "()Z",
reinterpret_cast<void*>(
android_location_gnss_hal_GnssNative_is_gnss_visibility_control_supported)},
};
static const JNINativeMethod sBatchingMethods[] = {
/* name, signature, funcPtr */
{"native_get_batch_size", "()I",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_get_batch_size)},
{"native_start_batch", "(JFZ)Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_start_batch)},
{"native_flush_batch", "()V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_flush_batch)},
{"native_stop_batch", "()Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_stop_batch)},
{"native_init_batching", "()Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_init_batching)},
{"native_cleanup_batching", "()V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_cleanup_batching)},
};
static const JNINativeMethod sAntennaInfoMethods[] = {
/* name, signature, funcPtr */
{"native_is_antenna_info_supported", "()Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_is_antenna_info_supported)},
{"native_start_antenna_info_listening", "()Z",
reinterpret_cast<void*>(
android_location_gnss_hal_GnssNative_start_antenna_info_listening)},
{"native_stop_antenna_info_listening", "()Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_stop_antenna_info_listening)},
};
static const JNINativeMethod sGeofenceMethods[] = {
/* name, signature, funcPtr */
{"native_is_geofence_supported", "()Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_is_geofence_supported)},
{"native_add_geofence", "(IDDDIIII)Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_add_geofence)},
{"native_remove_geofence", "(I)Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_remove_geofence)},
{"native_pause_geofence", "(I)Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_pause_geofence)},
{"native_resume_geofence", "(II)Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_resume_geofence)},
};
static const JNINativeMethod sMeasurementMethods[] = {
/* name, signature, funcPtr */
{"native_is_measurement_supported", "()Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_is_measurement_supported)},
{"native_start_measurement_collection", "(ZZI)Z",
reinterpret_cast<void*>(
android_location_gnss_hal_GnssNative_start_measurement_collection)},
{"native_stop_measurement_collection", "()Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_stop_measurement_collection)},
};
static const JNINativeMethod sMeasurementCorrectionsMethods[] = {
/* name, signature, funcPtr */
{"native_is_measurement_corrections_supported", "()Z",
reinterpret_cast<void*>(
android_location_gnss_hal_GnssNative_is_measurement_corrections_supported)},
{"native_inject_measurement_corrections",
"(Landroid/location/GnssMeasurementCorrections;)Z",
reinterpret_cast<void*>(
android_location_gnss_hal_GnssNative_inject_measurement_corrections)},
};
static const JNINativeMethod sNavigationMessageMethods[] = {
/* name, signature, funcPtr */
{"native_is_navigation_message_supported", "()Z",
reinterpret_cast<void*>(
android_location_gnss_hal_GnssNative_is_navigation_message_supported)},
{"native_start_navigation_message_collection", "()Z",
reinterpret_cast<void*>(
android_location_gnss_hal_GnssNative_start_navigation_message_collection)},
{"native_stop_navigation_message_collection", "()Z",
reinterpret_cast<void*>(
android_location_gnss_hal_GnssNative_stop_navigation_message_collection)},
};
static const JNINativeMethod sNetworkConnectivityMethods[] = {
/* name, signature, funcPtr */
{"native_is_agps_ril_supported", "()Z",
reinterpret_cast<void*>(
android_location_GnssNetworkConnectivityHandler_is_agps_ril_supported)},
{"native_update_network_state", "(ZIZZLjava/lang/String;JS)V",
reinterpret_cast<void*>(
android_location_GnssNetworkConnectivityHandler_update_network_state)},
{"native_agps_data_conn_open", "(JLjava/lang/String;I)V",
reinterpret_cast<void*>(
android_location_GnssNetworkConnectivityHandler_agps_data_conn_open)},
{"native_agps_data_conn_closed", "()V",
reinterpret_cast<void*>(
android_location_GnssNetworkConnectivityHandler_agps_data_conn_closed)},
{"native_agps_data_conn_failed", "()V",
reinterpret_cast<void*>(
android_location_GnssNetworkConnectivityHandler_agps_data_conn_failed)},
};
static const JNINativeMethod sConfigurationMethods[] = {
/* name, signature, funcPtr */
{"native_get_gnss_configuration_version",
"()Lcom/android/server/location/gnss/GnssConfiguration$HalInterfaceVersion;",
reinterpret_cast<void*>(
android_location_GnssConfiguration_get_gnss_configuration_version)},
{"native_set_supl_es", "(I)Z",
reinterpret_cast<void*>(android_location_GnssConfiguration_set_supl_es)},
{"native_set_supl_version", "(I)Z",
reinterpret_cast<void*>(android_location_GnssConfiguration_set_supl_version)},
{"native_set_supl_mode", "(I)Z",
reinterpret_cast<void*>(android_location_GnssConfiguration_set_supl_mode)},
{"native_set_lpp_profile", "(I)Z",
reinterpret_cast<void*>(android_location_GnssConfiguration_set_lpp_profile)},
{"native_set_gnss_pos_protocol_select", "(I)Z",
reinterpret_cast<void*>(android_location_GnssConfiguration_set_gnss_pos_protocol_select)},
{"native_set_gps_lock", "(I)Z",
reinterpret_cast<void*>(android_location_GnssConfiguration_set_gps_lock)},
{"native_set_emergency_supl_pdn", "(I)Z",
reinterpret_cast<void*>(android_location_GnssConfiguration_set_emergency_supl_pdn)},
{"native_set_satellite_blocklist", "([I[I)Z",
reinterpret_cast<void*>(android_location_GnssConfiguration_set_satellite_blocklist)},
{"native_set_es_extension_sec", "(I)Z",
reinterpret_cast<void*>(android_location_GnssConfiguration_set_es_extension_sec)},
};
static const JNINativeMethod sVisibilityControlMethods[] = {
/* name, signature, funcPtr */
{"native_enable_nfw_location_access", "([Ljava/lang/String;)Z",
reinterpret_cast<void*>(
android_location_GnssVisibilityControl_enable_nfw_location_access)},
};
static const JNINativeMethod sPowerIndicationMethods[] = {
/* name, signature, funcPtr */
{"native_request_power_stats", "()V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_request_power_stats)},
};
int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
int res;
res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
sAntennaInfoMethods, NELEM(sAntennaInfoMethods));
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
sBatchingMethods, NELEM(sBatchingMethods));
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
sGeofenceMethods, NELEM(sGeofenceMethods));
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
sMeasurementMethods, NELEM(sMeasurementMethods));
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
sMeasurementCorrectionsMethods,
NELEM(sMeasurementCorrectionsMethods));
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
sNavigationMessageMethods, NELEM(sNavigationMessageMethods));
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
res = jniRegisterNativeMethods(env,
"com/android/server/location/gnss/"
"GnssNetworkConnectivityHandler",
sNetworkConnectivityMethods, NELEM(sNetworkConnectivityMethods));
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssConfiguration",
sConfigurationMethods, NELEM(sConfigurationMethods));
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssVisibilityControl",
sVisibilityControlMethods, NELEM(sVisibilityControlMethods));
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
sPowerIndicationMethods, NELEM(sPowerIndicationMethods));
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
sLocationProviderMethods, NELEM(sLocationProviderMethods));
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
sCoreMethods, NELEM(sCoreMethods));
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
return 0;
}
} /* namespace android */