Refactor GNSS JNI: GnssMeasurement
Bug: 171245018 Test: atest GnssPseudorangeVerificationTest Change-Id: Ic89f63716f3c10765aab0e2dd042467512650a2f
This commit is contained in:
@@ -22,6 +22,9 @@ cc_library_static {
|
||||
"BroadcastRadio/convert.cpp",
|
||||
"BroadcastRadio/regions.cpp",
|
||||
"gnss/GnssConfiguration.cpp",
|
||||
"gnss/GnssMeasurement.cpp",
|
||||
"gnss/GnssMeasurementCallback.cpp",
|
||||
"gnss/Utils.cpp",
|
||||
"stats/PowerStatsPuller.cpp",
|
||||
"stats/SubsystemSleepStatePuller.cpp",
|
||||
"com_android_server_adb_AdbDebuggingManager.cpp",
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
#include "android_runtime/AndroidRuntime.h"
|
||||
#include "android_runtime/Log.h"
|
||||
#include "gnss/GnssConfiguration.h"
|
||||
#include "gnss/GnssMeasurement.h"
|
||||
#include "gnss/Utils.h"
|
||||
#include "hardware_legacy/power.h"
|
||||
#include "jni.h"
|
||||
#include "utils/Log.h"
|
||||
@@ -56,11 +58,8 @@
|
||||
#include <string.h>
|
||||
#include <utils/SystemClock.h>
|
||||
|
||||
static jclass class_gnssMeasurementsEvent;
|
||||
static jclass class_gnssMeasurement;
|
||||
static jclass class_location;
|
||||
static jclass class_gnssNavigationMessage;
|
||||
static jclass class_gnssClock;
|
||||
static jclass class_gnssAntennaInfoBuilder;
|
||||
static jclass class_gnssPowerStats;
|
||||
static jclass class_phaseCenterOffset;
|
||||
@@ -68,7 +67,7 @@ static jclass class_sphericalCorrections;
|
||||
static jclass class_arrayList;
|
||||
static jclass class_doubleArray;
|
||||
|
||||
static jobject mCallbacksObj = nullptr;
|
||||
jobject android::mCallbacksObj = nullptr;
|
||||
|
||||
static jmethodID method_reportLocation;
|
||||
static jmethodID method_reportStatus;
|
||||
@@ -90,7 +89,6 @@ static jmethodID method_reportGeofenceAddStatus;
|
||||
static jmethodID method_reportGeofenceRemoveStatus;
|
||||
static jmethodID method_reportGeofencePauseStatus;
|
||||
static jmethodID method_reportGeofenceResumeStatus;
|
||||
static jmethodID method_reportMeasurementData;
|
||||
static jmethodID method_reportAntennaInfo;
|
||||
static jmethodID method_reportNavigationMessages;
|
||||
static jmethodID method_reportLocationBatch;
|
||||
@@ -123,11 +121,8 @@ static jmethodID method_correctionPlaneAltDeg;
|
||||
static jmethodID method_correctionPlaneAzimDeg;
|
||||
static jmethodID method_reportNfwNotification;
|
||||
static jmethodID method_isInEmergencySession;
|
||||
static jmethodID method_gnssMeasurementsEventCtor;
|
||||
static jmethodID method_locationCtor;
|
||||
static jmethodID method_gnssNavigationMessageCtor;
|
||||
static jmethodID method_gnssClockCtor;
|
||||
static jmethodID method_gnssMeasurementCtor;
|
||||
static jmethodID method_gnssAntennaInfoBuilderCtor;
|
||||
static jmethodID method_gnssPowerStatsCtor;
|
||||
static jmethodID method_phaseCenterOffsetCtor;
|
||||
@@ -145,7 +140,7 @@ static jmethodID method_setSubHalPowerIndicationCapabilities;
|
||||
* Save a pointer to JavaVm to attach/detach threads executing
|
||||
* callback methods that need to make JNI calls.
|
||||
*/
|
||||
static JavaVM* sJvm;
|
||||
JavaVM* android::ScopedJniThreadAttach::sJvm;
|
||||
|
||||
using android::OK;
|
||||
using android::sp;
|
||||
@@ -201,14 +196,6 @@ using IGnssDebug_V1_0 = android::hardware::gnss::V1_0::IGnssDebug;
|
||||
using IGnssDebug_V2_0 = android::hardware::gnss::V2_0::IGnssDebug;
|
||||
using IGnssAntennaInfo = android::hardware::gnss::V2_1::IGnssAntennaInfo;
|
||||
using IGnssAntennaInfoCallback = android::hardware::gnss::V2_1::IGnssAntennaInfoCallback;
|
||||
using IGnssMeasurement_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
|
||||
using IGnssMeasurement_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
|
||||
using IGnssMeasurement_V2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
|
||||
using IGnssMeasurement_V2_1 = android::hardware::gnss::V2_1::IGnssMeasurement;
|
||||
using IGnssMeasurementCallback_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback;
|
||||
using IGnssMeasurementCallback_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback;
|
||||
using IGnssMeasurementCallback_V2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback;
|
||||
using IGnssMeasurementCallback_V2_1 = android::hardware::gnss::V2_1::IGnssMeasurementCallback;
|
||||
using IAGnssRil_V1_0 = android::hardware::gnss::V1_0::IAGnssRil;
|
||||
using IAGnssRil_V2_0 = android::hardware::gnss::V2_0::IAGnssRil;
|
||||
using IAGnss_V1_0 = android::hardware::gnss::V1_0::IAGnss;
|
||||
@@ -246,12 +233,11 @@ struct GnssDeathRecipient : virtual public hidl_death_recipient
|
||||
ALOGE("IGNSS hidl service failed, trying to recover...");
|
||||
|
||||
JNIEnv* env = android::AndroidRuntime::getJNIEnv();
|
||||
env->CallVoidMethod(mCallbacksObj, method_reportGnssServiceDied);
|
||||
env->CallVoidMethod(android::mCallbacksObj, method_reportGnssServiceDied);
|
||||
}
|
||||
};
|
||||
|
||||
// Must match the value from GnssMeasurement.java
|
||||
static const uint32_t ADR_STATE_HALF_CYCLE_REPORTED = (1<<4);
|
||||
static const uint32_t SVID_FLAGS_HAS_BASEBAND_CN0 = (1<<4);
|
||||
|
||||
sp<GnssDeathRecipient> gnssHalDeathRecipient = nullptr;
|
||||
@@ -274,10 +260,6 @@ sp<IGnssBatching_V2_0> gnssBatchingIface_V2_0 = nullptr;
|
||||
sp<IGnssDebug_V1_0> gnssDebugIface = nullptr;
|
||||
sp<IGnssDebug_V2_0> gnssDebugIface_V2_0 = nullptr;
|
||||
sp<IGnssNi> gnssNiIface = nullptr;
|
||||
sp<IGnssMeasurement_V1_0> gnssMeasurementIface = nullptr;
|
||||
sp<IGnssMeasurement_V1_1> gnssMeasurementIface_V1_1 = nullptr;
|
||||
sp<IGnssMeasurement_V2_0> gnssMeasurementIface_V2_0 = nullptr;
|
||||
sp<IGnssMeasurement_V2_1> gnssMeasurementIface_V2_1 = nullptr;
|
||||
sp<IGnssNavigationMessage> gnssNavigationMessageIface = nullptr;
|
||||
sp<IGnssPowerIndication> gnssPowerIndicationIface = nullptr;
|
||||
sp<IMeasurementCorrections_V1_0> gnssCorrectionsIface_V1_0 = nullptr;
|
||||
@@ -286,6 +268,7 @@ sp<IGnssVisibilityControl> gnssVisibilityControlIface = nullptr;
|
||||
sp<IGnssAntennaInfo> gnssAntennaInfoIface = nullptr;
|
||||
|
||||
std::unique_ptr<GnssConfigurationInterface> gnssConfigurationIface = nullptr;
|
||||
std::unique_ptr<android::gnss::GnssMeasurementInterface> gnssMeasurementIface = nullptr;
|
||||
|
||||
#define WAKE_LOCK_NAME "GPS"
|
||||
|
||||
@@ -305,172 +288,11 @@ bool hasLatLong(const GnssLocation_V2_0& location) {
|
||||
}
|
||||
|
||||
} // namespace
|
||||
template<class T>
|
||||
class JavaMethodHelper {
|
||||
public:
|
||||
// Helper function to call setter on a Java object.
|
||||
static void callJavaMethod(
|
||||
JNIEnv* env,
|
||||
jclass clazz,
|
||||
jobject object,
|
||||
const char* method_name,
|
||||
T value);
|
||||
|
||||
private:
|
||||
static const char* const signature_;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
void JavaMethodHelper<T>::callJavaMethod(
|
||||
JNIEnv* env,
|
||||
jclass clazz,
|
||||
jobject object,
|
||||
const char* method_name,
|
||||
T value) {
|
||||
jmethodID method = env->GetMethodID(clazz, method_name, signature_);
|
||||
env->CallVoidMethod(object, method, value);
|
||||
}
|
||||
|
||||
class JavaObject {
|
||||
public:
|
||||
JavaObject(JNIEnv* env, jclass clazz, jmethodID defaultCtor);
|
||||
JavaObject(JNIEnv* env, jclass clazz, jmethodID stringCtor, const char * sz_arg_1);
|
||||
JavaObject(JNIEnv* env, jclass clazz, jobject object);
|
||||
|
||||
virtual ~JavaObject() = default;
|
||||
|
||||
template<class T>
|
||||
void callSetter(const char* method_name, T value);
|
||||
template<class T>
|
||||
void callSetter(const char* method_name, T* value, size_t size);
|
||||
jobject get();
|
||||
|
||||
private:
|
||||
JNIEnv* env_;
|
||||
jclass clazz_;
|
||||
jobject object_;
|
||||
};
|
||||
|
||||
JavaObject::JavaObject(JNIEnv* env, jclass clazz, jmethodID defaultCtor) : env_(env),
|
||||
clazz_(clazz) {
|
||||
object_ = env_->NewObject(clazz_, defaultCtor);
|
||||
}
|
||||
|
||||
|
||||
JavaObject::JavaObject(JNIEnv* env, jclass clazz, jmethodID stringCtor, const char * sz_arg_1)
|
||||
: env_(env), clazz_(clazz) {
|
||||
jstring szArg = env->NewStringUTF(sz_arg_1);
|
||||
object_ = env_->NewObject(clazz_, stringCtor, szArg);
|
||||
if (szArg) {
|
||||
env_->DeleteLocalRef(szArg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
JavaObject::JavaObject(JNIEnv* env, jclass clazz, jobject object)
|
||||
: env_(env), clazz_(clazz), object_(object) {
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void JavaObject::callSetter(const char* method_name, T value) {
|
||||
JavaMethodHelper<T>::callJavaMethod(
|
||||
env_, clazz_, object_, method_name, value);
|
||||
}
|
||||
|
||||
template<>
|
||||
void JavaObject::callSetter(
|
||||
const char* method_name, uint8_t* value, size_t size) {
|
||||
jbyteArray array = env_->NewByteArray(size);
|
||||
env_->SetByteArrayRegion(array, 0, size, reinterpret_cast<jbyte*>(value));
|
||||
jmethodID method = env_->GetMethodID(
|
||||
clazz_,
|
||||
method_name,
|
||||
"([B)V");
|
||||
env_->CallVoidMethod(object_, method, array);
|
||||
env_->DeleteLocalRef(array);
|
||||
}
|
||||
|
||||
jobject JavaObject::get() {
|
||||
return object_;
|
||||
}
|
||||
|
||||
// Define Java method signatures for all known types.
|
||||
template<>
|
||||
const char *const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
|
||||
template<>
|
||||
const char *const JavaMethodHelper<int8_t>::signature_ = "(B)V";
|
||||
template<>
|
||||
const char *const JavaMethodHelper<int16_t>::signature_ = "(S)V";
|
||||
template<>
|
||||
const char *const JavaMethodHelper<uint16_t>::signature_ = "(S)V";
|
||||
template<>
|
||||
const char *const JavaMethodHelper<int32_t>::signature_ = "(I)V";
|
||||
template<>
|
||||
const char *const JavaMethodHelper<uint32_t>::signature_ = "(I)V";
|
||||
template<>
|
||||
const char *const JavaMethodHelper<int64_t>::signature_ = "(J)V";
|
||||
template<>
|
||||
const char *const JavaMethodHelper<uint64_t>::signature_ = "(J)V";
|
||||
template<>
|
||||
const char *const JavaMethodHelper<float>::signature_ = "(F)V";
|
||||
template<>
|
||||
const char *const JavaMethodHelper<double>::signature_ = "(D)V";
|
||||
template<>
|
||||
const char *const JavaMethodHelper<bool>::signature_ = "(Z)V";
|
||||
template<>
|
||||
const char *const JavaMethodHelper<jstring>::signature_ = "(Ljava/lang/String;)V";
|
||||
template <>
|
||||
const char* const JavaMethodHelper<jdoubleArray>::signature_ = "([D)V";
|
||||
|
||||
#define SET(setter, value) object.callSetter("set" # setter, (value))
|
||||
|
||||
static inline jboolean boolToJbool(bool value) {
|
||||
return value ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static inline void logHidlError(Return<T>& result, const char* errorMessage) {
|
||||
ALOGE("%s HIDL transport error: %s", errorMessage, result.description().c_str());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static jboolean checkHidlReturn(Return<T>& result, const char* errorMessage) {
|
||||
if (!result.isOk()) {
|
||||
logHidlError(result, errorMessage);
|
||||
return JNI_FALSE;
|
||||
} else {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static jboolean checkHidlReturn(Return<bool>& result, const char* errorMessage) {
|
||||
if (!result.isOk()) {
|
||||
logHidlError(result, errorMessage);
|
||||
return JNI_FALSE;
|
||||
} else if (!result) {
|
||||
ALOGE("%s", errorMessage);
|
||||
return JNI_FALSE;
|
||||
} else {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
|
||||
if (env->ExceptionCheck()) {
|
||||
ALOGE("An exception was thrown by callback '%s'.", methodName);
|
||||
LOGE_EX(env);
|
||||
env->ExceptionClear();
|
||||
}
|
||||
}
|
||||
|
||||
static jboolean checkAidlStatus(const Status& status, const char* errorMessage) {
|
||||
if (!status.isOk()) {
|
||||
ALOGE("%s AIDL transport error: %s", errorMessage, status.toString8().c_str());
|
||||
return JNI_FALSE;
|
||||
}
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
struct ScopedJniString {
|
||||
ScopedJniString(JNIEnv* env, jstring javaString) : mEnv(env), mJavaString(javaString) {
|
||||
mNativeString = mEnv->GetStringUTFChars(mJavaString, nullptr);
|
||||
@@ -499,62 +321,6 @@ private:
|
||||
const char* mNativeString;
|
||||
};
|
||||
|
||||
class ScopedJniThreadAttach {
|
||||
public:
|
||||
ScopedJniThreadAttach() {
|
||||
/*
|
||||
* attachResult will also be JNI_OK if the thead was already attached to
|
||||
* JNI before the call to AttachCurrentThread().
|
||||
*/
|
||||
jint attachResult = sJvm->AttachCurrentThread(&mEnv, nullptr);
|
||||
LOG_ALWAYS_FATAL_IF(attachResult != JNI_OK, "Unable to attach thread. Error %d",
|
||||
attachResult);
|
||||
}
|
||||
|
||||
~ScopedJniThreadAttach() {
|
||||
jint detachResult = sJvm->DetachCurrentThread();
|
||||
/*
|
||||
* Return if the thread was already detached. Log error for any other
|
||||
* failure.
|
||||
*/
|
||||
if (detachResult == JNI_EDETACHED) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(detachResult != JNI_OK, "Unable to detach thread. Error %d",
|
||||
detachResult);
|
||||
}
|
||||
|
||||
JNIEnv* getEnv() {
|
||||
/*
|
||||
* Checking validity of mEnv in case the thread was detached elsewhere.
|
||||
*/
|
||||
LOG_ALWAYS_FATAL_IF(AndroidRuntime::getJNIEnv() != mEnv);
|
||||
return mEnv;
|
||||
}
|
||||
|
||||
private:
|
||||
JNIEnv* mEnv = nullptr;
|
||||
};
|
||||
|
||||
thread_local std::unique_ptr<ScopedJniThreadAttach> tJniThreadAttacher;
|
||||
|
||||
static JNIEnv* getJniEnv() {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
|
||||
/*
|
||||
* If env is nullptr, the thread is not already attached to
|
||||
* JNI. It is attached below and the destructor for ScopedJniThreadAttach
|
||||
* will detach it on thread exit.
|
||||
*/
|
||||
if (env == nullptr) {
|
||||
tJniThreadAttacher.reset(new ScopedJniThreadAttach());
|
||||
env = tJniThreadAttacher->getEnv();
|
||||
}
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
static jobject translateGnssLocation(JNIEnv* env,
|
||||
const GnssLocation_V1_0& location) {
|
||||
JavaObject object(env, class_location, method_locationCtor, "gps");
|
||||
@@ -1385,322 +1151,6 @@ void GnssAntennaInfoCallback::reportAntennaInfo(JNIEnv* env, const jobject anten
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
}
|
||||
|
||||
/*
|
||||
* GnssMeasurementCallback implements the callback methods required for the
|
||||
* GnssMeasurement interface.
|
||||
*/
|
||||
struct GnssMeasurementCallback : public IGnssMeasurementCallback_V2_1 {
|
||||
Return<void> gnssMeasurementCb_2_1(const IGnssMeasurementCallback_V2_1::GnssData& data)
|
||||
override;
|
||||
Return<void> gnssMeasurementCb_2_0(const IGnssMeasurementCallback_V2_0::GnssData& data)
|
||||
override;
|
||||
Return<void> gnssMeasurementCb(const IGnssMeasurementCallback_V1_1::GnssData& data) override;
|
||||
Return<void> GnssMeasurementCb(const IGnssMeasurementCallback_V1_0::GnssData& data) override;
|
||||
private:
|
||||
template<class T>
|
||||
void translateSingleGnssMeasurement(const T* measurement, JavaObject& object);
|
||||
|
||||
template<class T>
|
||||
jobjectArray translateAllGnssMeasurements(JNIEnv* env, const T* measurements, size_t count);
|
||||
|
||||
template<class T>
|
||||
void translateAndSetGnssData(const T& data);
|
||||
|
||||
template<class T>
|
||||
size_t getMeasurementCount(const T& data);
|
||||
|
||||
template<class T>
|
||||
void translateGnssClock(JavaObject& object, const T& data);
|
||||
|
||||
void setMeasurementData(JNIEnv* env, jobject clock, jobjectArray measurementArray);
|
||||
};
|
||||
|
||||
Return<void> GnssMeasurementCallback::gnssMeasurementCb_2_1(
|
||||
const IGnssMeasurementCallback_V2_1::GnssData& data) {
|
||||
translateAndSetGnssData(data);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> GnssMeasurementCallback::gnssMeasurementCb_2_0(
|
||||
const IGnssMeasurementCallback_V2_0::GnssData& data) {
|
||||
translateAndSetGnssData(data);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> GnssMeasurementCallback::gnssMeasurementCb(
|
||||
const IGnssMeasurementCallback_V1_1::GnssData& data) {
|
||||
translateAndSetGnssData(data);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> GnssMeasurementCallback::GnssMeasurementCb(
|
||||
const IGnssMeasurementCallback_V1_0::GnssData& data) {
|
||||
translateAndSetGnssData(data);
|
||||
return Void();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void GnssMeasurementCallback::translateAndSetGnssData(const T& data) {
|
||||
JNIEnv* env = getJniEnv();
|
||||
|
||||
JavaObject gnssClockJavaObject(env, class_gnssClock, method_gnssClockCtor);
|
||||
translateGnssClock(gnssClockJavaObject, data);
|
||||
jobject clock = gnssClockJavaObject.get();
|
||||
|
||||
size_t count = getMeasurementCount(data);
|
||||
jobjectArray measurementArray = translateAllGnssMeasurements(env, data.measurements.data(), count);
|
||||
setMeasurementData(env, clock, measurementArray);
|
||||
|
||||
env->DeleteLocalRef(clock);
|
||||
env->DeleteLocalRef(measurementArray);
|
||||
}
|
||||
|
||||
template<>
|
||||
size_t GnssMeasurementCallback::getMeasurementCount<IGnssMeasurementCallback_V1_0::GnssData>
|
||||
(const IGnssMeasurementCallback_V1_0::GnssData& data) {
|
||||
return data.measurementCount;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
size_t GnssMeasurementCallback::getMeasurementCount(const T& data) {
|
||||
return data.measurements.size();
|
||||
}
|
||||
|
||||
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
|
||||
template<>
|
||||
void GnssMeasurementCallback::translateSingleGnssMeasurement
|
||||
<IGnssMeasurementCallback_V1_0::GnssMeasurement>(
|
||||
const IGnssMeasurementCallback_V1_0::GnssMeasurement* measurement,
|
||||
JavaObject& object) {
|
||||
uint32_t flags = static_cast<uint32_t>(measurement->flags);
|
||||
|
||||
SET(Svid, static_cast<int32_t>(measurement->svid));
|
||||
SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
|
||||
SET(TimeOffsetNanos, measurement->timeOffsetNs);
|
||||
SET(State, static_cast<int32_t>(measurement->state));
|
||||
SET(ReceivedSvTimeNanos, measurement->receivedSvTimeInNs);
|
||||
SET(ReceivedSvTimeUncertaintyNanos,
|
||||
measurement->receivedSvTimeUncertaintyInNs);
|
||||
SET(Cn0DbHz, measurement->cN0DbHz);
|
||||
SET(PseudorangeRateMetersPerSecond, measurement->pseudorangeRateMps);
|
||||
SET(PseudorangeRateUncertaintyMetersPerSecond,
|
||||
measurement->pseudorangeRateUncertaintyMps);
|
||||
SET(AccumulatedDeltaRangeState,
|
||||
(static_cast<int32_t>(measurement->accumulatedDeltaRangeState) &
|
||||
~ADR_STATE_HALF_CYCLE_REPORTED)); // Half Cycle state not reported from Hardware in V1_0
|
||||
SET(AccumulatedDeltaRangeMeters, measurement->accumulatedDeltaRangeM);
|
||||
SET(AccumulatedDeltaRangeUncertaintyMeters,
|
||||
measurement->accumulatedDeltaRangeUncertaintyM);
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_FREQUENCY)) {
|
||||
SET(CarrierFrequencyHz, measurement->carrierFrequencyHz);
|
||||
}
|
||||
|
||||
// Intentionally not copying deprecated fields of carrierCycles,
|
||||
// carrierPhase, carrierPhaseUncertainty
|
||||
|
||||
SET(MultipathIndicator, static_cast<int32_t>(measurement->multipathIndicator));
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_SNR)) {
|
||||
SET(SnrInDb, measurement->snrDb);
|
||||
}
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL)) {
|
||||
SET(AutomaticGainControlLevelInDb, measurement->agcLevelDb);
|
||||
}
|
||||
}
|
||||
|
||||
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
|
||||
template<>
|
||||
void GnssMeasurementCallback::translateSingleGnssMeasurement
|
||||
<IGnssMeasurementCallback_V1_1::GnssMeasurement>(
|
||||
const IGnssMeasurementCallback_V1_1::GnssMeasurement* measurement_V1_1,
|
||||
JavaObject& object) {
|
||||
translateSingleGnssMeasurement(&(measurement_V1_1->v1_0), object);
|
||||
|
||||
// Set the V1_1 flag, and mark that new field has valid information for Java Layer
|
||||
SET(AccumulatedDeltaRangeState,
|
||||
(static_cast<int32_t>(measurement_V1_1->accumulatedDeltaRangeState) |
|
||||
ADR_STATE_HALF_CYCLE_REPORTED));
|
||||
}
|
||||
|
||||
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
|
||||
template<>
|
||||
void GnssMeasurementCallback::translateSingleGnssMeasurement
|
||||
<IGnssMeasurementCallback_V2_0::GnssMeasurement>(
|
||||
const IGnssMeasurementCallback_V2_0::GnssMeasurement* measurement_V2_0,
|
||||
JavaObject& object) {
|
||||
JNIEnv* env = getJniEnv();
|
||||
translateSingleGnssMeasurement(&(measurement_V2_0->v1_1), object);
|
||||
|
||||
jstring codeType = env->NewStringUTF(measurement_V2_0->codeType.c_str());
|
||||
SET(CodeType, codeType);
|
||||
|
||||
// Overwrite with v2_0.state since v2_0->v1_1->v1_0.state is deprecated.
|
||||
SET(State, static_cast<int32_t>(measurement_V2_0->state));
|
||||
|
||||
// Overwrite with v2_0.constellation since v2_0->v1_1->v1_0.constellation is deprecated.
|
||||
SET(ConstellationType, static_cast<int32_t>(measurement_V2_0->constellation));
|
||||
|
||||
if (codeType) {
|
||||
env->DeleteLocalRef(codeType);
|
||||
}
|
||||
}
|
||||
|
||||
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
|
||||
template<>
|
||||
void GnssMeasurementCallback::translateSingleGnssMeasurement
|
||||
<IGnssMeasurementCallback_V2_1::GnssMeasurement>(
|
||||
const IGnssMeasurementCallback_V2_1::GnssMeasurement* measurement_V2_1,
|
||||
JavaObject& object) {
|
||||
translateSingleGnssMeasurement(&(measurement_V2_1->v2_0), object);
|
||||
|
||||
SET(BasebandCn0DbHz, measurement_V2_1->basebandCN0DbHz);
|
||||
|
||||
if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_FULL_ISB) {
|
||||
SET(FullInterSignalBiasNanos, measurement_V2_1->fullInterSignalBiasNs);
|
||||
}
|
||||
|
||||
if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_FULL_ISB_UNCERTAINTY) {
|
||||
SET(FullInterSignalBiasUncertaintyNanos,
|
||||
measurement_V2_1->fullInterSignalBiasUncertaintyNs);
|
||||
}
|
||||
|
||||
if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_SATELLITE_ISB) {
|
||||
SET(SatelliteInterSignalBiasNanos, measurement_V2_1->satelliteInterSignalBiasNs);
|
||||
}
|
||||
|
||||
if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_SATELLITE_ISB_UNCERTAINTY) {
|
||||
SET(SatelliteInterSignalBiasUncertaintyNanos,
|
||||
measurement_V2_1->satelliteInterSignalBiasUncertaintyNs);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void GnssMeasurementCallback::translateGnssClock(JavaObject& object, const T& data) {
|
||||
translateGnssClock(object, data.clock);
|
||||
}
|
||||
|
||||
template<>
|
||||
void GnssMeasurementCallback::translateGnssClock(
|
||||
JavaObject& object, const IGnssMeasurementCallback_V1_0::GnssClock& clock) {
|
||||
uint32_t flags = static_cast<uint32_t>(clock.gnssClockFlags);
|
||||
if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_LEAP_SECOND)) {
|
||||
SET(LeapSecond, static_cast<int32_t>(clock.leapSecond));
|
||||
}
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_TIME_UNCERTAINTY)) {
|
||||
SET(TimeUncertaintyNanos, clock.timeUncertaintyNs);
|
||||
}
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_FULL_BIAS)) {
|
||||
SET(FullBiasNanos, clock.fullBiasNs);
|
||||
}
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS)) {
|
||||
SET(BiasNanos, clock.biasNs);
|
||||
}
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS_UNCERTAINTY)) {
|
||||
SET(BiasUncertaintyNanos, clock.biasUncertaintyNs);
|
||||
}
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT)) {
|
||||
SET(DriftNanosPerSecond, clock.driftNsps);
|
||||
}
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT_UNCERTAINTY)) {
|
||||
SET(DriftUncertaintyNanosPerSecond, clock.driftUncertaintyNsps);
|
||||
}
|
||||
|
||||
SET(TimeNanos, clock.timeNs);
|
||||
SET(HardwareClockDiscontinuityCount, clock.hwClockDiscontinuityCount);
|
||||
}
|
||||
|
||||
template<>
|
||||
void GnssMeasurementCallback::translateGnssClock(
|
||||
JavaObject& object, const IGnssMeasurementCallback_V2_1::GnssClock& clock) {
|
||||
JNIEnv* env = getJniEnv();
|
||||
SET(ReferenceConstellationTypeForIsb,
|
||||
static_cast<int32_t>(clock.referenceSignalTypeForIsb.constellation));
|
||||
SET(ReferenceCarrierFrequencyHzForIsb, clock.referenceSignalTypeForIsb.carrierFrequencyHz);
|
||||
|
||||
jstring referenceCodeTypeForIsb =
|
||||
env->NewStringUTF(clock.referenceSignalTypeForIsb.codeType.c_str());
|
||||
SET(ReferenceCodeTypeForIsb, referenceCodeTypeForIsb);
|
||||
|
||||
translateGnssClock(object, clock.v1_0);
|
||||
|
||||
if (referenceCodeTypeForIsb) {
|
||||
env->DeleteLocalRef(referenceCodeTypeForIsb);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void GnssMeasurementCallback::translateGnssClock(
|
||||
JavaObject& object, const IGnssMeasurementCallback_V2_0::GnssData& data) {
|
||||
auto elapsedRealtime = data.elapsedRealtime;
|
||||
uint16_t flags = static_cast<uint16_t>(elapsedRealtime.flags);
|
||||
if (flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
|
||||
SET(ElapsedRealtimeNanos, static_cast<uint64_t>(elapsedRealtime.timestampNs));
|
||||
}
|
||||
if (flags & ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) {
|
||||
SET(ElapsedRealtimeUncertaintyNanos, static_cast<double>(elapsedRealtime.timeUncertaintyNs));
|
||||
}
|
||||
translateGnssClock(object, data.clock);
|
||||
}
|
||||
|
||||
template<>
|
||||
void GnssMeasurementCallback::translateGnssClock(
|
||||
JavaObject& object, const IGnssMeasurementCallback_V2_1::GnssData& data) {
|
||||
auto elapsedRealtime = data.elapsedRealtime;
|
||||
uint16_t flags = static_cast<uint16_t>(elapsedRealtime.flags);
|
||||
if (flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
|
||||
SET(ElapsedRealtimeNanos, static_cast<uint64_t>(elapsedRealtime.timestampNs));
|
||||
}
|
||||
if (flags & ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) {
|
||||
SET(ElapsedRealtimeUncertaintyNanos, static_cast<double>(elapsedRealtime.timeUncertaintyNs));
|
||||
}
|
||||
translateGnssClock(object, data.clock);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
jobjectArray GnssMeasurementCallback::translateAllGnssMeasurements(JNIEnv* env,
|
||||
const T* measurements,
|
||||
size_t count) {
|
||||
if (count == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
jobjectArray gnssMeasurementArray = env->NewObjectArray(
|
||||
count,
|
||||
class_gnssMeasurement,
|
||||
nullptr /* initialElement */);
|
||||
|
||||
for (uint16_t i = 0; i < count; ++i) {
|
||||
JavaObject object(env, class_gnssMeasurement, method_gnssMeasurementCtor);
|
||||
translateSingleGnssMeasurement(&(measurements[i]), object);
|
||||
jobject gnssMeasurement = object.get();
|
||||
env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
|
||||
env->DeleteLocalRef(gnssMeasurement);
|
||||
}
|
||||
|
||||
return gnssMeasurementArray;
|
||||
}
|
||||
|
||||
void GnssMeasurementCallback::setMeasurementData(JNIEnv* env, jobject clock,
|
||||
jobjectArray measurementArray) {
|
||||
jobject gnssMeasurementsEvent = env->NewObject(class_gnssMeasurementsEvent,
|
||||
method_gnssMeasurementsEventCtor,
|
||||
clock,
|
||||
measurementArray);
|
||||
|
||||
env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData,
|
||||
gnssMeasurementsEvent);
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
env->DeleteLocalRef(gnssMeasurementsEvent);
|
||||
}
|
||||
|
||||
/*
|
||||
* MeasurementCorrectionsCallback implements callback methods of interface
|
||||
* IMeasurementCorrectionsCallback.hal.
|
||||
@@ -2073,10 +1523,6 @@ static void android_location_GnssNative_class_init_once(JNIEnv* env, jclass claz
|
||||
method_reportGeofencePauseStatus = env->GetMethodID(clazz, "reportGeofencePauseStatus",
|
||||
"(II)V");
|
||||
method_reportAntennaInfo = env->GetMethodID(clazz, "reportAntennaInfo", "(Ljava/util/List;)V");
|
||||
method_reportMeasurementData = env->GetMethodID(
|
||||
clazz,
|
||||
"reportMeasurementData",
|
||||
"(Landroid/location/GnssMeasurementsEvent;)V");
|
||||
method_reportNavigationMessages = env->GetMethodID(
|
||||
clazz,
|
||||
"reportNavigationMessage",
|
||||
@@ -2150,17 +1596,6 @@ static void android_location_GnssNative_class_init_once(JNIEnv* env, jclass claz
|
||||
method_correctionPlaneAltDeg = env->GetMethodID(refPlaneClass, "getAltitudeMeters", "()D");
|
||||
method_correctionPlaneAzimDeg = env->GetMethodID(refPlaneClass, "getAzimuthDegrees", "()D");
|
||||
|
||||
jclass gnssMeasurementsEventClass = env->FindClass("android/location/GnssMeasurementsEvent");
|
||||
class_gnssMeasurementsEvent= (jclass) env->NewGlobalRef(gnssMeasurementsEventClass);
|
||||
method_gnssMeasurementsEventCtor = env->GetMethodID(
|
||||
class_gnssMeasurementsEvent,
|
||||
"<init>",
|
||||
"(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
|
||||
|
||||
jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
|
||||
class_gnssMeasurement = (jclass) env->NewGlobalRef(gnssMeasurementClass);
|
||||
method_gnssMeasurementCtor = env->GetMethodID(class_gnssMeasurement, "<init>", "()V");
|
||||
|
||||
jclass gnssAntennaInfoBuilder = env->FindClass("android/location/GnssAntennaInfo$Builder");
|
||||
class_gnssAntennaInfoBuilder = (jclass)env->NewGlobalRef(gnssAntennaInfoBuilder);
|
||||
method_gnssAntennaInfoBuilderCtor =
|
||||
@@ -2206,10 +1641,6 @@ static void android_location_GnssNative_class_init_once(JNIEnv* env, jclass claz
|
||||
class_gnssNavigationMessage = (jclass) env->NewGlobalRef(gnssNavigationMessageClass);
|
||||
method_gnssNavigationMessageCtor = env->GetMethodID(class_gnssNavigationMessage, "<init>", "()V");
|
||||
|
||||
jclass gnssClockClass = env->FindClass("android/location/GnssClock");
|
||||
class_gnssClock = (jclass) env->NewGlobalRef(gnssClockClass);
|
||||
method_gnssClockCtor = env->GetMethodID(class_gnssClock, "<init>", "()V");
|
||||
|
||||
jclass arrayListClass = env->FindClass("java/util/ArrayList");
|
||||
class_arrayList = (jclass)env->NewGlobalRef(arrayListClass);
|
||||
method_arrayListCtor = env->GetMethodID(class_arrayList, "<init>", "()V");
|
||||
@@ -2219,6 +1650,7 @@ static void android_location_GnssNative_class_init_once(JNIEnv* env, jclass claz
|
||||
class_doubleArray = (jclass)env->NewGlobalRef(doubleArrayClass);
|
||||
|
||||
gnss::GnssConfiguration_class_init_once(env);
|
||||
gnss::GnssMeasurement_class_init_once(env, clazz);
|
||||
}
|
||||
|
||||
/* Initialization needed at system boot and whenever GNSS service dies. */
|
||||
@@ -2227,7 +1659,7 @@ static void android_location_GnssNative_init_once(JNIEnv* env, jobject obj,
|
||||
/*
|
||||
* Save a pointer to JVM.
|
||||
*/
|
||||
jint jvmStatus = env->GetJavaVM(&sJvm);
|
||||
jint jvmStatus = env->GetJavaVM(&android::ScopedJniThreadAttach::sJvm);
|
||||
if (jvmStatus != JNI_OK) {
|
||||
LOG_ALWAYS_FATAL("Unable to get Java VM. Error: %d", jvmStatus);
|
||||
}
|
||||
@@ -2324,40 +1756,30 @@ static void android_location_GnssNative_init_once(JNIEnv* env, jobject obj,
|
||||
gnssMeasurementIface = nullptr;
|
||||
if (gnssHal_V2_1 != nullptr) {
|
||||
auto gnssMeasurement = gnssHal_V2_1->getExtensionGnssMeasurement_2_1();
|
||||
if (!gnssMeasurement.isOk()) {
|
||||
ALOGD("Unable to get a handle to GnssMeasurement_V2_1");
|
||||
} else {
|
||||
gnssMeasurementIface_V2_1 = gnssMeasurement;
|
||||
gnssMeasurementIface_V2_0 = gnssMeasurementIface_V2_1;
|
||||
gnssMeasurementIface_V1_1 = gnssMeasurementIface_V2_0;
|
||||
gnssMeasurementIface = gnssMeasurementIface_V1_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 (!gnssMeasurement.isOk()) {
|
||||
ALOGD("Unable to get a handle to GnssMeasurement_V2_0");
|
||||
} else {
|
||||
gnssMeasurementIface_V2_0 = gnssMeasurement;
|
||||
gnssMeasurementIface_V1_1 = gnssMeasurementIface_V2_0;
|
||||
gnssMeasurementIface = gnssMeasurementIface_V1_1;
|
||||
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 (!gnssMeasurement.isOk()) {
|
||||
ALOGD("Unable to get a handle to GnssMeasurement_V1_1");
|
||||
} else {
|
||||
gnssMeasurementIface_V1_1 = gnssMeasurement;
|
||||
gnssMeasurementIface = gnssMeasurementIface_V1_1;
|
||||
}
|
||||
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 (gnssMeasurementIface == nullptr) {
|
||||
auto gnssMeasurement = gnssHal->getExtensionGnssMeasurement();
|
||||
if (!gnssMeasurement.isOk()) {
|
||||
ALOGD("Unable to get a handle to GnssMeasurement");
|
||||
} else {
|
||||
gnssMeasurementIface = gnssMeasurement;
|
||||
if (checkHidlReturn(gnssMeasurement, "Unable to get a handle to GnssMeasurement_V1_0")) {
|
||||
gnssMeasurementIface =
|
||||
std::make_unique<android::gnss::GnssMeasurement_V1_0>(gnssMeasurement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3274,36 +2696,8 @@ static jboolean android_location_GnssMeasurementsProvider_start_measurement_coll
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
sp<GnssMeasurementCallback> cbIface = new GnssMeasurementCallback();
|
||||
Return<IGnssMeasurement_V1_0::GnssMeasurementStatus> result =
|
||||
IGnssMeasurement_V1_0::GnssMeasurementStatus::ERROR_GENERIC;
|
||||
if (gnssMeasurementIface_V2_1 != nullptr) {
|
||||
result = gnssMeasurementIface_V2_1->setCallback_2_1(cbIface, enableFullTracking);
|
||||
} else if (gnssMeasurementIface_V2_0 != nullptr) {
|
||||
result = gnssMeasurementIface_V2_0->setCallback_2_0(cbIface, enableFullTracking);
|
||||
} else if (gnssMeasurementIface_V1_1 != nullptr) {
|
||||
result = gnssMeasurementIface_V1_1->setCallback_1_1(cbIface, enableFullTracking);
|
||||
} else {
|
||||
if (enableFullTracking == JNI_TRUE) {
|
||||
ALOGW("Full tracking mode not supported in 1.0 GNSS HAL.");
|
||||
}
|
||||
result = gnssMeasurementIface->setCallback(cbIface);
|
||||
}
|
||||
|
||||
if (!checkHidlReturn(result, "IGnssMeasurement setCallback() failed.")) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
IGnssMeasurement_V1_0::GnssMeasurementStatus initRet = result;
|
||||
if (initRet != IGnssMeasurement_V1_0::GnssMeasurementStatus::SUCCESS) {
|
||||
ALOGE("An error has been found on GnssMeasurementInterface::init, status=%d",
|
||||
static_cast<int32_t>(initRet));
|
||||
return JNI_FALSE;
|
||||
} else {
|
||||
ALOGD("gnss measurement infc has been enabled");
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
return gnssMeasurementIface->setCallback(sp<gnss::GnssMeasurementCallback>::make(mCallbacksObj),
|
||||
enableFullTracking);
|
||||
}
|
||||
|
||||
static jboolean android_location_GnssMeasurementsProvider_stop_measurement_collection(
|
||||
@@ -3314,8 +2708,7 @@ static jboolean android_location_GnssMeasurementsProvider_stop_measurement_colle
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
auto result = gnssMeasurementIface->close();
|
||||
return checkHidlReturn(result, "IGnssMeasurement close() failed.");
|
||||
return gnssMeasurementIface->close();
|
||||
}
|
||||
|
||||
static jboolean
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#define LOG_TAG "GnssConfigurationJni"
|
||||
|
||||
#include "GnssConfiguration.h"
|
||||
#include "Utils.h"
|
||||
|
||||
using android::hardware::gnss::GnssConstellationType;
|
||||
using GnssConstellationType_V1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
|
||||
@@ -42,29 +43,6 @@ namespace {
|
||||
jclass class_gnssConfiguration_halInterfaceVersion;
|
||||
jmethodID method_halInterfaceVersionCtor;
|
||||
|
||||
jboolean checkAidlStatus(const Status& status, const char* errorMessage) {
|
||||
if (!status.isOk()) {
|
||||
ALOGE("%s AIDL transport error: %s", errorMessage, status.toString8().c_str());
|
||||
return JNI_FALSE;
|
||||
}
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void logHidlError(Return<T>& result, const char* errorMessage) {
|
||||
ALOGE("%s HIDL transport error: %s", errorMessage, result.description().c_str());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
jboolean checkHidlReturn(Return<T>& result, const char* errorMessage) {
|
||||
if (!result.isOk()) {
|
||||
logHidlError(result, errorMessage);
|
||||
return JNI_FALSE;
|
||||
} else {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
jobject createHalInterfaceVersionJavaObject(JNIEnv* env, jint major, jint minor) {
|
||||
return env->NewObject(class_gnssConfiguration_halInterfaceVersion,
|
||||
method_halInterfaceVersionCtor, major, minor);
|
||||
|
||||
114
services/core/jni/gnss/GnssMeasurement.cpp
Normal file
114
services/core/jni/gnss/GnssMeasurement.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 before <log/log.h> to overwrite the default value.
|
||||
#define LOG_TAG "GnssMeasurementJni"
|
||||
|
||||
#include "GnssMeasurement.h"
|
||||
#include "Utils.h"
|
||||
|
||||
using android::hardware::hidl_vec;
|
||||
using android::hardware::Return;
|
||||
|
||||
using IGnssMeasurement_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
|
||||
using IGnssMeasurement_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
|
||||
using IGnssMeasurement_V2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
|
||||
using IGnssMeasurement_V2_1 = android::hardware::gnss::V2_1::IGnssMeasurement;
|
||||
|
||||
namespace {
|
||||
jboolean checkGnssMeasurementStatus(const IGnssMeasurement_V1_0::GnssMeasurementStatus& status) {
|
||||
if (status != IGnssMeasurement_V1_0::GnssMeasurementStatus::SUCCESS) {
|
||||
ALOGE("An error has been found on GnssMeasurementInterface::init, status=%d",
|
||||
static_cast<int32_t>(status));
|
||||
return JNI_FALSE;
|
||||
} else {
|
||||
ALOGD("gnss measurement infc has been enabled");
|
||||
return JNI_TRUE;
|
||||
}
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
namespace android::gnss {
|
||||
|
||||
// Implementation of GnssMeasurement_V1_0
|
||||
|
||||
GnssMeasurement_V1_0::GnssMeasurement_V1_0(const sp<IGnssMeasurement_V1_0>& iGnssMeasurement)
|
||||
: mIGnssMeasurement_V1_0(iGnssMeasurement) {}
|
||||
|
||||
jboolean GnssMeasurement_V1_0::setCallback(const sp<GnssMeasurementCallback>& callback,
|
||||
bool enableFullTracking) {
|
||||
if (enableFullTracking == true) {
|
||||
ALOGW("Full tracking is mode not supported in 1.0 GNSS HAL.");
|
||||
}
|
||||
auto status = mIGnssMeasurement_V1_0->setCallback(callback);
|
||||
if (!checkHidlReturn(status, "IGnssMeasurement setCallback() failed.")) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
return checkGnssMeasurementStatus(status);
|
||||
}
|
||||
|
||||
jboolean GnssMeasurement_V1_0::close() {
|
||||
auto result = mIGnssMeasurement_V1_0->close();
|
||||
return checkHidlReturn(result, "IGnssMeasurement close() failed.");
|
||||
}
|
||||
|
||||
// Implementation of GnssMeasurement_V1_1
|
||||
|
||||
GnssMeasurement_V1_1::GnssMeasurement_V1_1(const sp<IGnssMeasurement_V1_1>& iGnssMeasurement)
|
||||
: GnssMeasurement_V1_0{iGnssMeasurement}, mIGnssMeasurement_V1_1(iGnssMeasurement) {}
|
||||
|
||||
jboolean GnssMeasurement_V1_1::setCallback(const sp<GnssMeasurementCallback>& callback,
|
||||
bool enableFullTracking) {
|
||||
auto status = mIGnssMeasurement_V1_1->setCallback_1_1(callback, enableFullTracking);
|
||||
if (!checkHidlReturn(status, "IGnssMeasurement setCallback_V1_1() failed.")) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
return checkGnssMeasurementStatus(status);
|
||||
}
|
||||
|
||||
// Implementation of GnssMeasurement_V2_0
|
||||
|
||||
GnssMeasurement_V2_0::GnssMeasurement_V2_0(const sp<IGnssMeasurement_V2_0>& iGnssMeasurement)
|
||||
: GnssMeasurement_V1_1{iGnssMeasurement}, mIGnssMeasurement_V2_0(iGnssMeasurement) {}
|
||||
|
||||
jboolean GnssMeasurement_V2_0::setCallback(const sp<GnssMeasurementCallback>& callback,
|
||||
bool enableFullTracking) {
|
||||
auto status = mIGnssMeasurement_V2_0->setCallback_2_0(callback, enableFullTracking);
|
||||
if (!checkHidlReturn(status, "IGnssMeasurement setCallback_2_0() failed.")) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
return checkGnssMeasurementStatus(status);
|
||||
}
|
||||
|
||||
// Implementation of GnssMeasurement_V2_1
|
||||
|
||||
GnssMeasurement_V2_1::GnssMeasurement_V2_1(const sp<IGnssMeasurement_V2_1>& iGnssMeasurement)
|
||||
: GnssMeasurement_V2_0{iGnssMeasurement}, mIGnssMeasurement_V2_1(iGnssMeasurement) {}
|
||||
|
||||
jboolean GnssMeasurement_V2_1::setCallback(const sp<GnssMeasurementCallback>& callback,
|
||||
bool enableFullTracking) {
|
||||
auto status = mIGnssMeasurement_V2_1->setCallback_2_1(callback, enableFullTracking);
|
||||
if (!checkHidlReturn(status, "IGnssMeasurement setCallback_2_1() failed.")) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
return checkGnssMeasurementStatus(status);
|
||||
}
|
||||
|
||||
} // namespace android::gnss
|
||||
91
services/core/jni/gnss/GnssMeasurement.h
Normal file
91
services/core/jni/gnss/GnssMeasurement.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_SERVER_GNSS_GNSSMEASUREMENT_H
|
||||
#define _ANDROID_SERVER_GNSS_GNSSMEASUREMENT_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef LOG_TAG
|
||||
#error LOG_TAG must be defined before including this file.
|
||||
#endif
|
||||
|
||||
#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
|
||||
#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
|
||||
#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
|
||||
#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
|
||||
#include <log/log.h>
|
||||
#include "GnssMeasurementCallback.h"
|
||||
#include "jni.h"
|
||||
|
||||
namespace android::gnss {
|
||||
|
||||
class GnssMeasurementInterface {
|
||||
public:
|
||||
virtual ~GnssMeasurementInterface() {}
|
||||
virtual jboolean setCallback(const sp<GnssMeasurementCallback>& callback,
|
||||
bool enableFullTracking) = 0;
|
||||
virtual jboolean close() = 0;
|
||||
};
|
||||
|
||||
class GnssMeasurement_V1_0 : public GnssMeasurementInterface {
|
||||
public:
|
||||
GnssMeasurement_V1_0(
|
||||
const sp<android::hardware::gnss::V1_0::IGnssMeasurement>& iGnssMeasurement);
|
||||
jboolean setCallback(const sp<GnssMeasurementCallback>& callback,
|
||||
bool enableFullTracking) override;
|
||||
jboolean close() override;
|
||||
|
||||
private:
|
||||
const sp<android::hardware::gnss::V1_0::IGnssMeasurement> mIGnssMeasurement_V1_0;
|
||||
};
|
||||
|
||||
class GnssMeasurement_V1_1 : public GnssMeasurement_V1_0 {
|
||||
public:
|
||||
GnssMeasurement_V1_1(
|
||||
const sp<android::hardware::gnss::V1_1::IGnssMeasurement>& iGnssMeasurement);
|
||||
jboolean setCallback(const sp<GnssMeasurementCallback>& callback,
|
||||
bool enableFullTracking) override;
|
||||
|
||||
private:
|
||||
const sp<android::hardware::gnss::V1_1::IGnssMeasurement> mIGnssMeasurement_V1_1;
|
||||
};
|
||||
|
||||
class GnssMeasurement_V2_0 : public GnssMeasurement_V1_1 {
|
||||
public:
|
||||
GnssMeasurement_V2_0(
|
||||
const sp<android::hardware::gnss::V2_0::IGnssMeasurement>& iGnssMeasurement);
|
||||
jboolean setCallback(const sp<GnssMeasurementCallback>& callback,
|
||||
bool enableFullTracking) override;
|
||||
|
||||
private:
|
||||
const sp<android::hardware::gnss::V2_0::IGnssMeasurement> mIGnssMeasurement_V2_0;
|
||||
};
|
||||
|
||||
class GnssMeasurement_V2_1 : public GnssMeasurement_V2_0 {
|
||||
public:
|
||||
GnssMeasurement_V2_1(
|
||||
const sp<android::hardware::gnss::V2_1::IGnssMeasurement>& iGnssMeasurement);
|
||||
jboolean setCallback(const sp<GnssMeasurementCallback>& callback,
|
||||
bool enableFullTracking) override;
|
||||
|
||||
private:
|
||||
const sp<android::hardware::gnss::V2_1::IGnssMeasurement> mIGnssMeasurement_V2_1;
|
||||
};
|
||||
|
||||
} // namespace android::gnss
|
||||
|
||||
#endif // _ANDROID_SERVER_GNSS_GNSSMEASUREMENT_H
|
||||
286
services/core/jni/gnss/GnssMeasurementCallback.cpp
Normal file
286
services/core/jni/gnss/GnssMeasurementCallback.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 "GnssMeasCbJni"
|
||||
|
||||
#include "GnssMeasurementCallback.h"
|
||||
|
||||
namespace android::gnss {
|
||||
|
||||
jclass class_gnssMeasurementsEvent;
|
||||
jclass class_gnssMeasurement;
|
||||
jclass class_gnssClock;
|
||||
|
||||
jmethodID method_gnssMeasurementsEventCtor;
|
||||
jmethodID method_gnssClockCtor;
|
||||
jmethodID method_gnssMeasurementCtor;
|
||||
jmethodID method_reportMeasurementData;
|
||||
|
||||
void GnssMeasurement_class_init_once(JNIEnv* env, jclass& clazz) {
|
||||
method_reportMeasurementData = env->GetMethodID(clazz, "reportMeasurementData",
|
||||
"(Landroid/location/GnssMeasurementsEvent;)V");
|
||||
jclass gnssMeasurementsEventClass = env->FindClass("android/location/GnssMeasurementsEvent");
|
||||
class_gnssMeasurementsEvent = (jclass)env->NewGlobalRef(gnssMeasurementsEventClass);
|
||||
method_gnssMeasurementsEventCtor =
|
||||
env->GetMethodID(class_gnssMeasurementsEvent, "<init>",
|
||||
"(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
|
||||
|
||||
jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
|
||||
class_gnssMeasurement = (jclass)env->NewGlobalRef(gnssMeasurementClass);
|
||||
method_gnssMeasurementCtor = env->GetMethodID(class_gnssMeasurement, "<init>", "()V");
|
||||
|
||||
jclass gnssClockClass = env->FindClass("android/location/GnssClock");
|
||||
class_gnssClock = (jclass)env->NewGlobalRef(gnssClockClass);
|
||||
method_gnssClockCtor = env->GetMethodID(class_gnssClock, "<init>", "()V");
|
||||
}
|
||||
|
||||
hardware::Return<void> GnssMeasurementCallback::gnssMeasurementCb_2_1(
|
||||
const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data) {
|
||||
translateAndSetGnssData(data);
|
||||
return hardware::Void();
|
||||
}
|
||||
|
||||
hardware::Return<void> GnssMeasurementCallback::gnssMeasurementCb_2_0(
|
||||
const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data) {
|
||||
translateAndSetGnssData(data);
|
||||
return hardware::Void();
|
||||
}
|
||||
|
||||
hardware::Return<void> GnssMeasurementCallback::gnssMeasurementCb(
|
||||
const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssData& data) {
|
||||
translateAndSetGnssData(data);
|
||||
return hardware::Void();
|
||||
}
|
||||
|
||||
hardware::Return<void> GnssMeasurementCallback::GnssMeasurementCb(
|
||||
const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data) {
|
||||
translateAndSetGnssData(data);
|
||||
return hardware::Void();
|
||||
}
|
||||
|
||||
template <>
|
||||
size_t GnssMeasurementCallback::getMeasurementCount<
|
||||
hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData>(
|
||||
const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data) {
|
||||
return data.measurementCount;
|
||||
}
|
||||
|
||||
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateSingleGnssMeasurement<
|
||||
hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement>(
|
||||
const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement* measurement,
|
||||
JavaObject& object) {
|
||||
uint32_t flags = static_cast<uint32_t>(measurement->flags);
|
||||
|
||||
SET(Svid, static_cast<int32_t>(measurement->svid));
|
||||
SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
|
||||
SET(TimeOffsetNanos, measurement->timeOffsetNs);
|
||||
SET(State, static_cast<int32_t>(measurement->state));
|
||||
SET(ReceivedSvTimeNanos, measurement->receivedSvTimeInNs);
|
||||
SET(ReceivedSvTimeUncertaintyNanos, measurement->receivedSvTimeUncertaintyInNs);
|
||||
SET(Cn0DbHz, measurement->cN0DbHz);
|
||||
SET(PseudorangeRateMetersPerSecond, measurement->pseudorangeRateMps);
|
||||
SET(PseudorangeRateUncertaintyMetersPerSecond, measurement->pseudorangeRateUncertaintyMps);
|
||||
SET(AccumulatedDeltaRangeState,
|
||||
(static_cast<int32_t>(measurement->accumulatedDeltaRangeState) &
|
||||
~ADR_STATE_HALF_CYCLE_REPORTED)); // Half Cycle state not reported from Hardware in V1_0
|
||||
SET(AccumulatedDeltaRangeMeters, measurement->accumulatedDeltaRangeM);
|
||||
SET(AccumulatedDeltaRangeUncertaintyMeters, measurement->accumulatedDeltaRangeUncertaintyM);
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_FREQUENCY)) {
|
||||
SET(CarrierFrequencyHz, measurement->carrierFrequencyHz);
|
||||
}
|
||||
|
||||
// Intentionally not copying deprecated fields of carrierCycles,
|
||||
// carrierPhase, carrierPhaseUncertainty
|
||||
|
||||
SET(MultipathIndicator, static_cast<int32_t>(measurement->multipathIndicator));
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_SNR)) {
|
||||
SET(SnrInDb, measurement->snrDb);
|
||||
}
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL)) {
|
||||
SET(AutomaticGainControlLevelInDb, measurement->agcLevelDb);
|
||||
}
|
||||
}
|
||||
|
||||
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateSingleGnssMeasurement<
|
||||
hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement>(
|
||||
const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement* measurement_V1_1,
|
||||
JavaObject& object) {
|
||||
translateSingleGnssMeasurement(&(measurement_V1_1->v1_0), object);
|
||||
|
||||
// Set the V1_1 flag, and mark that new field has valid information for Java Layer
|
||||
SET(AccumulatedDeltaRangeState,
|
||||
(static_cast<int32_t>(measurement_V1_1->accumulatedDeltaRangeState) |
|
||||
ADR_STATE_HALF_CYCLE_REPORTED));
|
||||
}
|
||||
|
||||
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateSingleGnssMeasurement<
|
||||
hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement>(
|
||||
const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement* measurement_V2_0,
|
||||
JavaObject& object) {
|
||||
JNIEnv* env = getJniEnv();
|
||||
translateSingleGnssMeasurement(&(measurement_V2_0->v1_1), object);
|
||||
|
||||
jstring codeType = env->NewStringUTF(measurement_V2_0->codeType.c_str());
|
||||
SET(CodeType, codeType);
|
||||
|
||||
// Overwrite with v2_0.state since v2_0->v1_1->v1_0.state is deprecated.
|
||||
SET(State, static_cast<int32_t>(measurement_V2_0->state));
|
||||
|
||||
// Overwrite with v2_0.constellation since v2_0->v1_1->v1_0.constellation is deprecated.
|
||||
SET(ConstellationType, static_cast<int32_t>(measurement_V2_0->constellation));
|
||||
|
||||
if (codeType) {
|
||||
env->DeleteLocalRef(codeType);
|
||||
}
|
||||
}
|
||||
|
||||
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateSingleGnssMeasurement<
|
||||
hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement>(
|
||||
const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement* measurement_V2_1,
|
||||
JavaObject& object) {
|
||||
translateSingleGnssMeasurement(&(measurement_V2_1->v2_0), object);
|
||||
|
||||
SET(BasebandCn0DbHz, measurement_V2_1->basebandCN0DbHz);
|
||||
|
||||
if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_FULL_ISB) {
|
||||
SET(FullInterSignalBiasNanos, measurement_V2_1->fullInterSignalBiasNs);
|
||||
}
|
||||
|
||||
if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_FULL_ISB_UNCERTAINTY) {
|
||||
SET(FullInterSignalBiasUncertaintyNanos,
|
||||
measurement_V2_1->fullInterSignalBiasUncertaintyNs);
|
||||
}
|
||||
|
||||
if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_SATELLITE_ISB) {
|
||||
SET(SatelliteInterSignalBiasNanos, measurement_V2_1->satelliteInterSignalBiasNs);
|
||||
}
|
||||
|
||||
if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_SATELLITE_ISB_UNCERTAINTY) {
|
||||
SET(SatelliteInterSignalBiasUncertaintyNanos,
|
||||
measurement_V2_1->satelliteInterSignalBiasUncertaintyNs);
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateGnssClock(
|
||||
JavaObject& object,
|
||||
const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssClock& clock) {
|
||||
uint32_t flags = static_cast<uint32_t>(clock.gnssClockFlags);
|
||||
if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_LEAP_SECOND)) {
|
||||
SET(LeapSecond, static_cast<int32_t>(clock.leapSecond));
|
||||
}
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_TIME_UNCERTAINTY)) {
|
||||
SET(TimeUncertaintyNanos, clock.timeUncertaintyNs);
|
||||
}
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_FULL_BIAS)) {
|
||||
SET(FullBiasNanos, clock.fullBiasNs);
|
||||
}
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS)) {
|
||||
SET(BiasNanos, clock.biasNs);
|
||||
}
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS_UNCERTAINTY)) {
|
||||
SET(BiasUncertaintyNanos, clock.biasUncertaintyNs);
|
||||
}
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT)) {
|
||||
SET(DriftNanosPerSecond, clock.driftNsps);
|
||||
}
|
||||
|
||||
if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT_UNCERTAINTY)) {
|
||||
SET(DriftUncertaintyNanosPerSecond, clock.driftUncertaintyNsps);
|
||||
}
|
||||
|
||||
SET(TimeNanos, clock.timeNs);
|
||||
SET(HardwareClockDiscontinuityCount, clock.hwClockDiscontinuityCount);
|
||||
}
|
||||
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateGnssClock(
|
||||
JavaObject& object,
|
||||
const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssClock& clock) {
|
||||
JNIEnv* env = getJniEnv();
|
||||
SET(ReferenceConstellationTypeForIsb,
|
||||
static_cast<int32_t>(clock.referenceSignalTypeForIsb.constellation));
|
||||
SET(ReferenceCarrierFrequencyHzForIsb, clock.referenceSignalTypeForIsb.carrierFrequencyHz);
|
||||
|
||||
jstring referenceCodeTypeForIsb =
|
||||
env->NewStringUTF(clock.referenceSignalTypeForIsb.codeType.c_str());
|
||||
SET(ReferenceCodeTypeForIsb, referenceCodeTypeForIsb);
|
||||
|
||||
translateGnssClock(object, clock.v1_0);
|
||||
|
||||
if (referenceCodeTypeForIsb) {
|
||||
env->DeleteLocalRef(referenceCodeTypeForIsb);
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateGnssClock(
|
||||
JavaObject& object, const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data) {
|
||||
auto elapsedRealtime = data.elapsedRealtime;
|
||||
uint16_t flags = static_cast<uint16_t>(elapsedRealtime.flags);
|
||||
if (flags & hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
|
||||
SET(ElapsedRealtimeNanos, static_cast<uint64_t>(elapsedRealtime.timestampNs));
|
||||
}
|
||||
if (flags & hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) {
|
||||
SET(ElapsedRealtimeUncertaintyNanos,
|
||||
static_cast<double>(elapsedRealtime.timeUncertaintyNs));
|
||||
}
|
||||
translateGnssClock(object, data.clock);
|
||||
}
|
||||
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateGnssClock(
|
||||
JavaObject& object, const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data) {
|
||||
auto elapsedRealtime = data.elapsedRealtime;
|
||||
uint16_t flags = static_cast<uint16_t>(elapsedRealtime.flags);
|
||||
if (flags & hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
|
||||
SET(ElapsedRealtimeNanos, static_cast<uint64_t>(elapsedRealtime.timestampNs));
|
||||
}
|
||||
if (flags & hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) {
|
||||
SET(ElapsedRealtimeUncertaintyNanos,
|
||||
static_cast<double>(elapsedRealtime.timeUncertaintyNs));
|
||||
}
|
||||
translateGnssClock(object, data.clock);
|
||||
}
|
||||
|
||||
void GnssMeasurementCallback::setMeasurementData(JNIEnv* env, jobject clock,
|
||||
jobjectArray measurementArray) {
|
||||
jobject gnssMeasurementsEvent =
|
||||
env->NewObject(class_gnssMeasurementsEvent, method_gnssMeasurementsEventCtor, clock,
|
||||
measurementArray);
|
||||
|
||||
env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData, gnssMeasurementsEvent);
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
env->DeleteLocalRef(gnssMeasurementsEvent);
|
||||
}
|
||||
|
||||
} // namespace android::gnss
|
||||
183
services/core/jni/gnss/GnssMeasurementCallback.h
Normal file
183
services/core/jni/gnss/GnssMeasurementCallback.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_SERVER_GNSS_GNSSMEASUREMENTCALLBACK_H
|
||||
#define _ANDROID_SERVER_GNSS_GNSSMEASUREMENTCALLBACK_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef LOG_TAG
|
||||
#error LOG_TAG must be defined before including this file.
|
||||
#endif
|
||||
|
||||
#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
|
||||
#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
|
||||
#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
|
||||
#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
|
||||
#include <log/log.h>
|
||||
#include "Utils.h"
|
||||
#include "jni.h"
|
||||
|
||||
namespace android::gnss {
|
||||
|
||||
extern jclass class_gnssMeasurementsEvent;
|
||||
extern jclass class_gnssMeasurement;
|
||||
extern jclass class_gnssClock;
|
||||
|
||||
extern jmethodID method_gnssMeasurementsEventCtor;
|
||||
extern jmethodID method_gnssClockCtor;
|
||||
extern jmethodID method_gnssMeasurementCtor;
|
||||
extern jmethodID method_reportMeasurementData;
|
||||
|
||||
void GnssMeasurement_class_init_once(JNIEnv* env, jclass& clazz);
|
||||
|
||||
/*
|
||||
* GnssMeasurementCallback implements the callback methods required for the
|
||||
* GnssMeasurement interface.
|
||||
*/
|
||||
struct GnssMeasurementCallback : public hardware::gnss::V2_1::IGnssMeasurementCallback {
|
||||
GnssMeasurementCallback(jobject& callbacksObj) : mCallbacksObj(callbacksObj) {}
|
||||
hardware::Return<void> gnssMeasurementCb_2_1(
|
||||
const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data) override;
|
||||
hardware::Return<void> gnssMeasurementCb_2_0(
|
||||
const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data) override;
|
||||
hardware::Return<void> gnssMeasurementCb(
|
||||
const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssData& data) override;
|
||||
hardware::Return<void> GnssMeasurementCb(
|
||||
const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data) override;
|
||||
|
||||
private:
|
||||
template <class T>
|
||||
void translateSingleGnssMeasurement(const T* measurement, JavaObject& object);
|
||||
|
||||
template <class T>
|
||||
jobjectArray translateAllGnssMeasurements(JNIEnv* env, const T* measurements, size_t count);
|
||||
|
||||
template <class T>
|
||||
void translateAndSetGnssData(const T& data);
|
||||
|
||||
template <class T>
|
||||
size_t getMeasurementCount(const T& data);
|
||||
|
||||
template <class T>
|
||||
void translateGnssClock(JavaObject& object, const T& data);
|
||||
|
||||
void setMeasurementData(JNIEnv* env, jobject clock, jobjectArray measurementArray);
|
||||
|
||||
jobject& mCallbacksObj;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void GnssMeasurementCallback::translateAndSetGnssData(const T& data) {
|
||||
JNIEnv* env = getJniEnv();
|
||||
|
||||
JavaObject gnssClockJavaObject(env, class_gnssClock, method_gnssClockCtor);
|
||||
translateGnssClock(gnssClockJavaObject, data);
|
||||
jobject clock = gnssClockJavaObject.get();
|
||||
|
||||
size_t count = getMeasurementCount(data);
|
||||
jobjectArray measurementArray =
|
||||
translateAllGnssMeasurements(env, data.measurements.data(), count);
|
||||
setMeasurementData(env, clock, measurementArray);
|
||||
|
||||
env->DeleteLocalRef(clock);
|
||||
env->DeleteLocalRef(measurementArray);
|
||||
}
|
||||
|
||||
template <>
|
||||
size_t GnssMeasurementCallback::getMeasurementCount<
|
||||
hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData>(
|
||||
const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data);
|
||||
|
||||
template <class T>
|
||||
size_t GnssMeasurementCallback::getMeasurementCount(const T& data) {
|
||||
return data.measurements.size();
|
||||
}
|
||||
|
||||
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateSingleGnssMeasurement<
|
||||
hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement>(
|
||||
const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement* measurement,
|
||||
JavaObject& object);
|
||||
|
||||
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateSingleGnssMeasurement<
|
||||
hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement>(
|
||||
const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement* measurement_V1_1,
|
||||
JavaObject& object);
|
||||
|
||||
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateSingleGnssMeasurement<
|
||||
hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement>(
|
||||
const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement* measurement_V2_0,
|
||||
JavaObject& object);
|
||||
|
||||
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateSingleGnssMeasurement<
|
||||
hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement>(
|
||||
const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement* measurement_V2_1,
|
||||
JavaObject& object);
|
||||
|
||||
template <class T>
|
||||
void GnssMeasurementCallback::translateGnssClock(JavaObject& object, const T& data) {
|
||||
translateGnssClock(object, data.clock);
|
||||
}
|
||||
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateGnssClock(
|
||||
JavaObject& object, const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssClock& clock);
|
||||
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateGnssClock(
|
||||
JavaObject& object, const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssClock& clock);
|
||||
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateGnssClock(
|
||||
JavaObject& object, const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data);
|
||||
|
||||
template <>
|
||||
void GnssMeasurementCallback::translateGnssClock(
|
||||
JavaObject& object, const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data);
|
||||
|
||||
template <class T>
|
||||
jobjectArray GnssMeasurementCallback::translateAllGnssMeasurements(JNIEnv* env,
|
||||
const T* measurements,
|
||||
size_t count) {
|
||||
if (count == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
jobjectArray gnssMeasurementArray =
|
||||
env->NewObjectArray(count, class_gnssMeasurement, nullptr /* initialElement */);
|
||||
|
||||
for (uint16_t i = 0; i < count; ++i) {
|
||||
JavaObject object(env, class_gnssMeasurement, method_gnssMeasurementCtor);
|
||||
translateSingleGnssMeasurement(&(measurements[i]), object);
|
||||
jobject gnssMeasurement = object.get();
|
||||
env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
|
||||
env->DeleteLocalRef(gnssMeasurement);
|
||||
}
|
||||
|
||||
return gnssMeasurementArray;
|
||||
}
|
||||
|
||||
} // namespace android::gnss
|
||||
|
||||
#endif // _ANDROID_SERVER_GNSS_GNSSMEASUREMENTCALLBACK_H
|
||||
127
services/core/jni/gnss/Utils.cpp
Normal file
127
services/core/jni/gnss/Utils.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 "GnssUtilsJni"
|
||||
|
||||
#include "Utils.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
namespace {
|
||||
|
||||
thread_local std::unique_ptr<ScopedJniThreadAttach> tJniThreadAttacher;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// Define Java method signatures for all known types.
|
||||
template <>
|
||||
const char* const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
|
||||
template <>
|
||||
const char* const JavaMethodHelper<int8_t>::signature_ = "(B)V";
|
||||
template <>
|
||||
const char* const JavaMethodHelper<int16_t>::signature_ = "(S)V";
|
||||
template <>
|
||||
const char* const JavaMethodHelper<uint16_t>::signature_ = "(S)V";
|
||||
template <>
|
||||
const char* const JavaMethodHelper<int32_t>::signature_ = "(I)V";
|
||||
template <>
|
||||
const char* const JavaMethodHelper<uint32_t>::signature_ = "(I)V";
|
||||
template <>
|
||||
const char* const JavaMethodHelper<int64_t>::signature_ = "(J)V";
|
||||
template <>
|
||||
const char* const JavaMethodHelper<uint64_t>::signature_ = "(J)V";
|
||||
template <>
|
||||
const char* const JavaMethodHelper<float>::signature_ = "(F)V";
|
||||
template <>
|
||||
const char* const JavaMethodHelper<double>::signature_ = "(D)V";
|
||||
template <>
|
||||
const char* const JavaMethodHelper<bool>::signature_ = "(Z)V";
|
||||
template <>
|
||||
const char* const JavaMethodHelper<jstring>::signature_ = "(Ljava/lang/String;)V";
|
||||
template <>
|
||||
const char* const JavaMethodHelper<jdoubleArray>::signature_ = "([D)V";
|
||||
|
||||
jboolean checkAidlStatus(const android::binder::Status& status, const char* errorMessage) {
|
||||
if (!status.isOk()) {
|
||||
ALOGE("%s AIDL transport error: %s", errorMessage, status.toString8().c_str());
|
||||
return JNI_FALSE;
|
||||
}
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
jboolean checkHidlReturn(hardware::Return<bool>& result, const char* errorMessage) {
|
||||
if (!result.isOk()) {
|
||||
logHidlError(result, errorMessage);
|
||||
return JNI_FALSE;
|
||||
} else if (!result) {
|
||||
ALOGE("%s", errorMessage);
|
||||
return JNI_FALSE;
|
||||
} else {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
|
||||
if (env->ExceptionCheck()) {
|
||||
ALOGE("An exception was thrown by callback '%s'.", methodName);
|
||||
LOGE_EX(env);
|
||||
env->ExceptionClear();
|
||||
}
|
||||
}
|
||||
|
||||
JavaObject::JavaObject(JNIEnv* env, jclass clazz, jmethodID defaultCtor)
|
||||
: env_(env), clazz_(clazz) {
|
||||
object_ = env_->NewObject(clazz_, defaultCtor);
|
||||
}
|
||||
|
||||
JavaObject::JavaObject(JNIEnv* env, jclass clazz, jmethodID stringCtor, const char* sz_arg_1)
|
||||
: env_(env), clazz_(clazz) {
|
||||
jstring szArg = env->NewStringUTF(sz_arg_1);
|
||||
object_ = env_->NewObject(clazz_, stringCtor, szArg);
|
||||
if (szArg) {
|
||||
env_->DeleteLocalRef(szArg);
|
||||
}
|
||||
}
|
||||
|
||||
JavaObject::JavaObject(JNIEnv* env, jclass clazz, jobject object)
|
||||
: env_(env), clazz_(clazz), object_(object) {}
|
||||
|
||||
template <>
|
||||
void JavaObject::callSetter(const char* method_name, uint8_t* value, size_t size) {
|
||||
jbyteArray array = env_->NewByteArray(size);
|
||||
env_->SetByteArrayRegion(array, 0, size, reinterpret_cast<jbyte*>(value));
|
||||
jmethodID method = env_->GetMethodID(clazz_, method_name, "([B)V");
|
||||
env_->CallVoidMethod(object_, method, array);
|
||||
env_->DeleteLocalRef(array);
|
||||
}
|
||||
|
||||
JNIEnv* getJniEnv() {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
|
||||
/*
|
||||
* If env is nullptr, the thread is not already attached to
|
||||
* JNI. It is attached below and the destructor for ScopedJniThreadAttach
|
||||
* will detach it on thread exit.
|
||||
*/
|
||||
if (env == nullptr) {
|
||||
tJniThreadAttacher.reset(new ScopedJniThreadAttach());
|
||||
env = tJniThreadAttacher->getEnv();
|
||||
}
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
183
services/core/jni/gnss/Utils.h
Normal file
183
services/core/jni/gnss/Utils.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_SERVER_GNSS_UTILS_H
|
||||
#define _ANDROID_SERVER_GNSS_UTILS_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef LOG_TAG
|
||||
#error LOG_TAG must be defined before including this file.
|
||||
#endif
|
||||
|
||||
#include <android/hardware/gnss/1.0/IGnss.h>
|
||||
#include <android/hardware/gnss/BnGnss.h>
|
||||
#include <log/log.h>
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
#include "android_runtime/AndroidRuntime.h"
|
||||
#include "android_runtime/Log.h"
|
||||
#include "jni.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
namespace {
|
||||
|
||||
// Must match the value from GnssMeasurement.java
|
||||
const uint32_t ADR_STATE_HALF_CYCLE_REPORTED = (1 << 4);
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
extern jobject mCallbacksObj;
|
||||
|
||||
jboolean checkHidlReturn(hardware::Return<bool>& result, const char* errorMessage);
|
||||
|
||||
jboolean checkAidlStatus(const android::binder::Status& status, const char* errorMessage);
|
||||
|
||||
void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
|
||||
|
||||
template <class T>
|
||||
void logHidlError(hardware::Return<T>& result, const char* errorMessage) {
|
||||
ALOGE("%s HIDL transport error: %s", errorMessage, result.description().c_str());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
jboolean checkHidlReturn(hardware::Return<T>& result, const char* errorMessage) {
|
||||
if (!result.isOk()) {
|
||||
logHidlError(result, errorMessage);
|
||||
return JNI_FALSE;
|
||||
} else {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class JavaMethodHelper {
|
||||
public:
|
||||
// Helper function to call setter on a Java object.
|
||||
static void callJavaMethod(JNIEnv* env, jclass clazz, jobject object, const char* method_name,
|
||||
T value);
|
||||
|
||||
private:
|
||||
static const char* const signature_;
|
||||
};
|
||||
|
||||
// Define Java method signatures for all known types.
|
||||
template <>
|
||||
const char* const JavaMethodHelper<uint8_t>::signature_;
|
||||
template <>
|
||||
const char* const JavaMethodHelper<int8_t>::signature_;
|
||||
template <>
|
||||
const char* const JavaMethodHelper<int16_t>::signature_;
|
||||
template <>
|
||||
const char* const JavaMethodHelper<uint16_t>::signature_;
|
||||
template <>
|
||||
const char* const JavaMethodHelper<int32_t>::signature_;
|
||||
template <>
|
||||
const char* const JavaMethodHelper<uint32_t>::signature_;
|
||||
template <>
|
||||
const char* const JavaMethodHelper<int64_t>::signature_;
|
||||
template <>
|
||||
const char* const JavaMethodHelper<uint64_t>::signature_;
|
||||
template <>
|
||||
const char* const JavaMethodHelper<float>::signature_;
|
||||
template <>
|
||||
const char* const JavaMethodHelper<double>::signature_;
|
||||
template <>
|
||||
const char* const JavaMethodHelper<bool>::signature_;
|
||||
template <>
|
||||
const char* const JavaMethodHelper<jstring>::signature_;
|
||||
template <>
|
||||
const char* const JavaMethodHelper<jdoubleArray>::signature_;
|
||||
|
||||
template <class T>
|
||||
void JavaMethodHelper<T>::callJavaMethod(JNIEnv* env, jclass clazz, jobject object,
|
||||
const char* method_name, T value) {
|
||||
jmethodID method = env->GetMethodID(clazz, method_name, signature_);
|
||||
env->CallVoidMethod(object, method, value);
|
||||
}
|
||||
|
||||
class JavaObject {
|
||||
public:
|
||||
JavaObject(JNIEnv* env, jclass clazz, jmethodID defaultCtor);
|
||||
JavaObject(JNIEnv* env, jclass clazz, jmethodID stringCtor, const char* sz_arg_1);
|
||||
JavaObject(JNIEnv* env, jclass clazz, jobject object);
|
||||
|
||||
virtual ~JavaObject() = default;
|
||||
|
||||
template <class T>
|
||||
void callSetter(const char* method_name, T value);
|
||||
template <class T>
|
||||
void callSetter(const char* method_name, T* value, size_t size);
|
||||
jobject get() { return object_; }
|
||||
|
||||
private:
|
||||
JNIEnv* env_;
|
||||
jclass clazz_;
|
||||
jobject object_;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void JavaObject::callSetter(const char* method_name, T value) {
|
||||
JavaMethodHelper<T>::callJavaMethod(env_, clazz_, object_, method_name, value);
|
||||
}
|
||||
|
||||
#define SET(setter, value) object.callSetter("set" #setter, (value))
|
||||
|
||||
class ScopedJniThreadAttach {
|
||||
public:
|
||||
static JavaVM* sJvm;
|
||||
|
||||
ScopedJniThreadAttach() {
|
||||
/*
|
||||
* attachResult will also be JNI_OK if the thead was already attached to
|
||||
* JNI before the call to AttachCurrentThread().
|
||||
*/
|
||||
jint attachResult = sJvm->AttachCurrentThread(&mEnv, nullptr);
|
||||
LOG_ALWAYS_FATAL_IF(attachResult != JNI_OK, "Unable to attach thread. Error %d",
|
||||
attachResult);
|
||||
}
|
||||
|
||||
~ScopedJniThreadAttach() {
|
||||
jint detachResult = sJvm->DetachCurrentThread();
|
||||
/*
|
||||
* Return if the thread was already detached. Log error for any other
|
||||
* failure.
|
||||
*/
|
||||
if (detachResult == JNI_EDETACHED) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(detachResult != JNI_OK, "Unable to detach thread. Error %d",
|
||||
detachResult);
|
||||
}
|
||||
|
||||
JNIEnv* getEnv() {
|
||||
/*
|
||||
* Checking validity of mEnv in case the thread was detached elsewhere.
|
||||
*/
|
||||
LOG_ALWAYS_FATAL_IF(AndroidRuntime::getJNIEnv() != mEnv);
|
||||
return mEnv;
|
||||
}
|
||||
|
||||
private:
|
||||
JNIEnv* mEnv = nullptr;
|
||||
};
|
||||
|
||||
JNIEnv* getJniEnv();
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // _ANDROID_SERVER_GNSS_UTILS_H
|
||||
Reference in New Issue
Block a user