diff options
| -rw-r--r-- | services/core/jni/com_android_server_location_GnssLocationProvider.cpp | 286 | ||||
| -rw-r--r-- | services/core/jni/gnss/Android.bp | 2 | ||||
| -rw-r--r-- | services/core/jni/gnss/GnssBatching.cpp | 131 | ||||
| -rw-r--r-- | services/core/jni/gnss/GnssBatching.h | 86 | ||||
| -rw-r--r-- | services/core/jni/gnss/GnssBatchingCallback.cpp | 58 | ||||
| -rw-r--r-- | services/core/jni/gnss/GnssBatchingCallback.h | 128 | ||||
| -rw-r--r-- | services/core/jni/gnss/Utils.cpp | 122 | ||||
| -rw-r--r-- | services/core/jni/gnss/Utils.h | 11 |
8 files changed, 568 insertions, 256 deletions
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index 6be872f9f1ed..0a55003e77fc 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -28,7 +28,6 @@ #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/BnGnssBatchingCallback.h> #include <android/hardware/gnss/BnGnssCallback.h> #include <android/hardware/gnss/BnGnssMeasurementCallback.h> #include <android/hardware/gnss/BnGnssPowerIndicationCallback.h> @@ -52,6 +51,7 @@ #include "android_runtime/AndroidRuntime.h" #include "android_runtime/Log.h" #include "gnss/GnssAntennaInfoCallback.h" +#include "gnss/GnssBatching.h" #include "gnss/GnssConfiguration.h" #include "gnss/GnssMeasurement.h" #include "gnss/Utils.h" @@ -60,12 +60,9 @@ #include "utils/Log.h" #include "utils/misc.h" -static jclass class_location; static jclass class_gnssNavigationMessage; static jclass class_gnssPowerStats; -jobject android::mCallbacksObj = nullptr; - static jmethodID method_reportLocation; static jmethodID method_reportStatus; static jmethodID method_reportSvStatus; @@ -87,7 +84,6 @@ static jmethodID method_reportGeofenceRemoveStatus; static jmethodID method_reportGeofencePauseStatus; static jmethodID method_reportGeofenceResumeStatus; static jmethodID method_reportNavigationMessages; -static jmethodID method_reportLocationBatch; static jmethodID method_reportGnssServiceDied; static jmethodID method_reportGnssPowerStats; static jmethodID method_setSubHalMeasurementCorrectionsCapabilities; @@ -117,7 +113,6 @@ static jmethodID method_correctionPlaneAltDeg; static jmethodID method_correctionPlaneAzimDeg; static jmethodID method_reportNfwNotification; static jmethodID method_isInEmergencySession; -static jmethodID method_locationCtor; static jmethodID method_gnssNavigationMessageCtor; static jmethodID method_gnssPowerStatsCtor; static jmethodID method_setSubHalPowerIndicationCapabilities; @@ -179,10 +174,6 @@ using IAGnss_V1_0 = android::hardware::gnss::V1_0::IAGnss; using IAGnss_V2_0 = android::hardware::gnss::V2_0::IAGnss; using IAGnssCallback_V1_0 = android::hardware::gnss::V1_0::IAGnssCallback; using IAGnssCallback_V2_0 = android::hardware::gnss::V2_0::IAGnssCallback; -using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching; -using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching; -using IGnssBatchingCallback_V1_0 = android::hardware::gnss::V1_0::IGnssBatchingCallback; -using IGnssBatchingCallback_V2_0 = android::hardware::gnss::V2_0::IGnssBatchingCallback; using IMeasurementCorrections_V1_0 = android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections; using IMeasurementCorrections_V1_1 = android::hardware::gnss::measurement_corrections::V1_1::IMeasurementCorrections; @@ -199,8 +190,6 @@ using android::hardware::gnss::IGnssPowerIndication; using android::hardware::gnss::IGnssPowerIndicationCallback; using android::hardware::gnss::PsdsType; using IGnssAidl = android::hardware::gnss::IGnss; -using IGnssBatchingAidl = android::hardware::gnss::IGnssBatching; -using IGnssBatchingCallbackAidl = android::hardware::gnss::IGnssBatchingCallback; using IGnssCallbackAidl = android::hardware::gnss::IGnssCallback; using IGnssPsdsAidl = android::hardware::gnss::IGnssPsds; using IGnssPsdsCallbackAidl = android::hardware::gnss::IGnssPsdsCallback; @@ -227,7 +216,6 @@ 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<IAGnssRil_V1_0> agnssRilIface = nullptr; @@ -235,8 +223,6 @@ sp<IAGnssRil_V2_0> agnssRilIface_V2_0 = nullptr; sp<IGnssGeofencing> gnssGeofencingIface = nullptr; sp<IAGnss_V1_0> agnssIface = nullptr; sp<IAGnss_V2_0> agnssIface_V2_0 = nullptr; -sp<IGnssBatching_V1_0> gnssBatchingIface = nullptr; -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; @@ -249,6 +235,7 @@ sp<IGnssAntennaInfo> gnssAntennaInfoIface = nullptr; std::unique_ptr<GnssConfigurationInterface> gnssConfigurationIface = nullptr; std::unique_ptr<android::gnss::GnssMeasurementInterface> gnssMeasurementIface = nullptr; +std::unique_ptr<android::gnss::GnssBatchingInterface> gnssBatchingIface = nullptr; #define WAKE_LOCK_NAME "GPS" @@ -301,103 +288,6 @@ private: const char* mNativeString; }; -static jobject translateGnssLocation(JNIEnv* env, const GnssLocationAidl& location) { - JavaObject object(env, class_location, method_locationCtor, "gps"); - - uint32_t flags = static_cast<uint32_t>(location.gnssLocationFlags); - if (flags & GnssLocationAidl::HAS_LAT_LONG) { - SET(Latitude, location.latitudeDegrees); - SET(Longitude, location.longitudeDegrees); - } - if (flags & GnssLocationAidl::HAS_ALTITUDE) { - SET(Altitude, location.altitudeMeters); - } - if (flags & GnssLocationAidl::HAS_SPEED) { - SET(Speed, (float)location.speedMetersPerSec); - } - if (flags & GnssLocationAidl::HAS_BEARING) { - SET(Bearing, (float)location.bearingDegrees); - } - if (flags & GnssLocationAidl::HAS_HORIZONTAL_ACCURACY) { - SET(Accuracy, (float)location.horizontalAccuracyMeters); - } - if (flags & GnssLocationAidl::HAS_VERTICAL_ACCURACY) { - SET(VerticalAccuracyMeters, (float)location.verticalAccuracyMeters); - } - if (flags & GnssLocationAidl::HAS_SPEED_ACCURACY) { - SET(SpeedAccuracyMetersPerSecond, (float)location.speedAccuracyMetersPerSecond); - } - if (flags & GnssLocationAidl::HAS_BEARING_ACCURACY) { - SET(BearingAccuracyDegrees, (float)location.bearingAccuracyDegrees); - } - SET(Time, location.timestampMillis); - - flags = static_cast<uint32_t>(location.elapsedRealtime.flags); - if (flags & android::hardware::gnss::ElapsedRealtime::HAS_TIMESTAMP_NS) { - SET(ElapsedRealtimeNanos, location.elapsedRealtime.timestampNs); - } - if (flags & android::hardware::gnss::ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS) { - SET(ElapsedRealtimeUncertaintyNanos, - static_cast<double>(location.elapsedRealtime.timeUncertaintyNs)); - } - - return object.get(); -} - -static jobject translateGnssLocation(JNIEnv* env, - const GnssLocation_V1_0& location) { - JavaObject object(env, class_location, method_locationCtor, "gps"); - - uint16_t flags = static_cast<uint16_t>(location.gnssLocationFlags); - if (flags & GnssLocationFlags::HAS_LAT_LONG) { - SET(Latitude, location.latitudeDegrees); - SET(Longitude, location.longitudeDegrees); - } - if (flags & GnssLocationFlags::HAS_ALTITUDE) { - SET(Altitude, location.altitudeMeters); - } - if (flags & GnssLocationFlags::HAS_SPEED) { - SET(Speed, location.speedMetersPerSec); - } - if (flags & GnssLocationFlags::HAS_BEARING) { - SET(Bearing, location.bearingDegrees); - } - if (flags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) { - SET(Accuracy, location.horizontalAccuracyMeters); - } - if (flags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) { - SET(VerticalAccuracyMeters, location.verticalAccuracyMeters); - } - if (flags & GnssLocationFlags::HAS_SPEED_ACCURACY) { - SET(SpeedAccuracyMetersPerSecond, location.speedAccuracyMetersPerSecond); - } - if (flags & GnssLocationFlags::HAS_BEARING_ACCURACY) { - SET(BearingAccuracyDegrees, location.bearingAccuracyDegrees); - } - SET(Time, location.timestamp); - SET(ElapsedRealtimeNanos, android::elapsedRealtimeNano()); - - return object.get(); -} - -static jobject translateGnssLocation(JNIEnv* env, - const GnssLocation_V2_0& location) { - JavaObject object(env, class_location, translateGnssLocation(env, location.v1_0)); - - const uint16_t flags = static_cast<uint16_t>(location.elapsedRealtime.flags); - - // Overwrite ElapsedRealtimeNanos when available from HAL. - if (flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) { - SET(ElapsedRealtimeNanos, location.elapsedRealtime.timestampNs); - } - - if (flags & ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) { - SET(ElapsedRealtimeUncertaintyNanos, static_cast<double>(location.elapsedRealtime.timeUncertaintyNs)); - } - - return object.get(); -} - static GnssLocation_V1_0 createGnssLocation_V1_0( jint gnssLocationFlags, jdouble latitudeDegrees, jdouble longitudeDegrees, jdouble altitudeMeters, jfloat speedMetersPerSec, jfloat bearingDegrees, @@ -1219,66 +1109,6 @@ Return<void> AGnssRilCallback::requestRefLocCb() { return Void(); } -struct GnssBatchingCallbackUtil { - template<class T> - static Return<void> gnssLocationBatchCbImpl(const hidl_vec<T>& locations); -private: - GnssBatchingCallbackUtil() = delete; -}; - -template<class T> -Return<void> GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(const hidl_vec<T>& locations) { - JNIEnv* env = getJniEnv(); - - jobjectArray jLocations = env->NewObjectArray(locations.size(), class_location, nullptr); - - for (uint16_t i = 0; i < locations.size(); ++i) { - jobject jLocation = translateGnssLocation(env, locations[i]); - env->SetObjectArrayElement(jLocations, i, jLocation); - env->DeleteLocalRef(jLocation); - } - - env->CallVoidMethod(mCallbacksObj, method_reportLocationBatch, jLocations); - checkAndClearExceptionFromCallback(env, __FUNCTION__); - - env->DeleteLocalRef(jLocations); - - return Void(); -} - -/* - * GnssBatchingCallbackAidl class implements the callback methods required by the - * android::hardware::gnss::IGnssBatching interface. - */ -struct GnssBatchingCallbackAidl : public android::hardware::gnss::BnGnssBatchingCallback { - Status gnssLocationBatchCb(const std::vector<GnssLocationAidl>& locations) { - GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(hidl_vec<GnssLocationAidl>(locations)); - return Status::ok(); - } -}; - -/* - * GnssBatchingCallback_V1_0 class implements the callback methods required by the - * IGnssBatching 1.0 interface. - */ -struct GnssBatchingCallback_V1_0 : public IGnssBatchingCallback_V1_0 { - /** Methods from ::android::hardware::gps::V1_0::IGnssBatchingCallback follow. */ - Return<void> gnssLocationBatchCb(const hidl_vec<GnssLocation_V1_0>& locations) override { - return GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(locations); - } -}; - -/* - * GnssBatchingCallback_V2_0 class implements the callback methods required by the - * IGnssBatching 2.0 interface. - */ -struct GnssBatchingCallback_V2_0 : public IGnssBatchingCallback_V2_0 { - /** Methods from ::android::hardware::gps::V2_0::IGnssBatchingCallback follow. */ - Return<void> gnssLocationBatchCb(const hidl_vec<GnssLocation_V2_0>& locations) override { - return GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(locations); - } -}; - /* Initializes the GNSS service handle. */ static void android_location_gnss_hal_GnssNative_set_gps_service_handle() { gnssHalAidl = waitForVintfService<IGnssAidl>(); @@ -1354,10 +1184,6 @@ static void android_location_gnss_hal_GnssNative_class_init_once(JNIEnv* env, jc clazz, "reportNavigationMessage", "(Landroid/location/GnssNavigationMessage;)V"); - method_reportLocationBatch = env->GetMethodID( - clazz, - "reportLocationBatch", - "([Landroid/location/Location;)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"); @@ -1427,17 +1253,15 @@ static void android_location_gnss_hal_GnssNative_class_init_once(JNIEnv* env, jc class_gnssPowerStats = (jclass)env->NewGlobalRef(gnssPowerStatsClass); method_gnssPowerStatsCtor = env->GetMethodID(class_gnssPowerStats, "<init>", "(IJDDDDDD[D)V"); - jclass locationClass = env->FindClass("android/location/Location"); - class_location = (jclass) env->NewGlobalRef(locationClass); - method_locationCtor = env->GetMethodID(class_location, "<init>", "(Ljava/lang/String;)V"); - jclass gnssNavigationMessageClass = env->FindClass("android/location/GnssNavigationMessage"); class_gnssNavigationMessage = (jclass) env->NewGlobalRef(gnssNavigationMessageClass); method_gnssNavigationMessageCtor = env->GetMethodID(class_gnssNavigationMessage, "<init>", "()V"); + gnss::GnssAntennaInfo_class_init_once(env, clazz); + gnss::GnssBatching_class_init_once(env, clazz); gnss::GnssConfiguration_class_init_once(env); gnss::GnssMeasurement_class_init_once(env, clazz); - gnss::GnssAntennaInfo_class_init_once(env, clazz); + gnss::Utils_class_init_once(env); } /* Initialization needed at system boot and whenever GNSS service dies. */ @@ -1672,25 +1496,21 @@ static void android_location_gnss_hal_GnssNative_init_once(JNIEnv* env, jobject } if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) { - sp<IGnssBatchingAidl> gnssBatchingAidl; + sp<android::hardware::gnss::IGnssBatching> gnssBatchingAidl; auto status = gnssHalAidl->getExtensionGnssBatching(&gnssBatchingAidl); if (checkAidlStatus(status, "Unable to get a handle to GnssBatching interface.")) { - gnssBatchingAidlIface = gnssBatchingAidl; + gnssBatchingIface = std::make_unique<gnss::GnssBatching>(gnssBatchingAidl); } } else if (gnssHal_V2_0 != nullptr) { auto gnssBatching_V2_0 = gnssHal_V2_0->getExtensionGnssBatching_2_0(); - if (!gnssBatching_V2_0.isOk()) { - ALOGD("Unable to get a handle to GnssBatching_V2_0"); - } else { - gnssBatchingIface_V2_0 = gnssBatching_V2_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 (gnssBatchingIface_V2_0 == nullptr ) { + if (gnssBatchingIface == nullptr) { auto gnssBatching_V1_0 = gnssHal->getExtensionGnssBatching(); - if (!gnssBatching_V1_0.isOk()) { - ALOGD("Unable to get a handle to GnssBatching"); - } else { - gnssBatchingIface = gnssBatching_V1_0; + if (checkHidlReturn(gnssBatching_V1_0, "Unable to get a handle to GnssBatching")) { + gnssBatchingIface = std::make_unique<gnss::GnssBatching_V1_0>(gnssBatching_V1_0); } } @@ -2786,92 +2606,46 @@ static jboolean android_location_GnssConfiguration_set_es_extension_sec( } static jint android_location_gnss_hal_GnssNative_get_batch_size(JNIEnv*) { - if (gnssBatchingAidlIface != nullptr) { - int size = 0; - auto status = gnssBatchingAidlIface->getBatchSize(&size); - if (!checkAidlStatus(status, "IGnssBatchingAidl getBatchSize() failed")) { - return 0; - } - return size; - } else if (gnssBatchingIface != nullptr) { - auto result = gnssBatchingIface->getBatchSize(); - if (!checkHidlReturn(result, "IGnssBatching getBatchSize() failed.")) { - return 0; // failure in binder, don't support batching - } - return static_cast<jint>(result); + if (gnssBatchingIface == nullptr) { + return 0; // batching not supported, size = 0 } - return 0; // batching not supported, size = 0 + return gnssBatchingIface->getBatchSize(); } static jboolean android_location_gnss_hal_GnssNative_init_batching(JNIEnv*, jclass) { - if (gnssBatchingAidlIface != nullptr) { - sp<IGnssBatchingCallbackAidl> gnssBatchingCbIface = new GnssBatchingCallbackAidl(); - auto status = gnssBatchingAidlIface->init(gnssBatchingCbIface); - return checkAidlStatus(status, "IGnssBatchingAidl init() failed."); - } else if (gnssBatchingIface_V2_0 != nullptr) { - sp<IGnssBatchingCallback_V2_0> gnssBatchingCbIface_V2_0 = new GnssBatchingCallback_V2_0(); - auto result = gnssBatchingIface_V2_0->init_2_0(gnssBatchingCbIface_V2_0); - return checkHidlReturn(result, "IGnssBatching init_2_0() failed."); - } else if (gnssBatchingIface != nullptr) { - sp<IGnssBatchingCallback_V1_0> gnssBatchingCbIface_V1_0 = new GnssBatchingCallback_V1_0(); - auto result = gnssBatchingIface->init(gnssBatchingCbIface_V1_0); - return checkHidlReturn(result, "IGnssBatching init() failed."); - } else { + 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 (gnssBatchingAidlIface != nullptr) { - auto status = gnssBatchingAidlIface->cleanup(); - checkAidlStatus(status, "IGnssBatchingAidl cleanup() failed"); - } else if (gnssBatchingIface != nullptr) { - auto result = gnssBatchingIface->cleanup(); - checkHidlReturn(result, "IGnssBatching cleanup() failed."); + if (gnssBatchingIface == nullptr) { + return; // batching not supported } - return; + gnssBatchingIface->cleanup(); } static jboolean android_location_gnss_hal_GnssNative_start_batch(JNIEnv*, jclass, jlong periodNanos, jboolean wakeOnFifoFull) { - IGnssBatching_V1_0::Options options; - options.periodNanos = periodNanos; - if (wakeOnFifoFull) { - options.flags = static_cast<uint8_t>(IGnssBatching_V1_0::Flag::WAKEUP_ON_FIFO_FULL); - } else { - options.flags = 0; - } - - if (gnssBatchingAidlIface != nullptr) { - auto status = gnssBatchingAidlIface->start(periodNanos, (int)options.flags); - return checkAidlStatus(status, "IGnssBatchingAidl start() failed."); - } else if (gnssBatchingIface != nullptr) { - auto result = gnssBatchingIface->start(options); - return checkHidlReturn(result, "IGnssBatching start() failed."); + if (gnssBatchingIface == nullptr) { + return JNI_FALSE; // batching not supported } - return JNI_FALSE; // batching not supported + return gnssBatchingIface->start(periodNanos, wakeOnFifoFull); } static void android_location_gnss_hal_GnssNative_flush_batch(JNIEnv*, jclass) { - if (gnssBatchingAidlIface != nullptr) { - auto status = gnssBatchingAidlIface->flush(); - checkAidlStatus(status, "IGnssBatchingAidl flush() failed."); - } else if (gnssBatchingIface != nullptr) { - auto result = gnssBatchingIface->flush(); - checkHidlReturn(result, "IGnssBatching flush() failed."); + if (gnssBatchingIface == nullptr) { + return; // batching not supported } - return; + gnssBatchingIface->flush(); } static jboolean android_location_gnss_hal_GnssNative_stop_batch(JNIEnv*, jclass) { - if (gnssBatchingAidlIface != nullptr) { - auto status = gnssBatchingAidlIface->stop(); - return checkAidlStatus(status, "IGnssBatchingAidl stop() failed."); - } else if (gnssBatchingIface != nullptr) { - auto result = gnssBatchingIface->stop(); - return checkHidlReturn(result, "IGnssBatching stop() failed."); - } - return JNI_FALSE; // batching not supported + if (gnssBatchingIface == nullptr) { + return JNI_FALSE; // batching not supported + } + return gnssBatchingIface->stop(); } static jboolean android_location_GnssVisibilityControl_enable_nfw_location_access( diff --git a/services/core/jni/gnss/Android.bp b/services/core/jni/gnss/Android.bp index 9085fa726c60..090166a0bc1d 100644 --- a/services/core/jni/gnss/Android.bp +++ b/services/core/jni/gnss/Android.bp @@ -24,6 +24,8 @@ cc_library_shared { srcs: [ "GnssAntennaInfoCallback.cpp", + "GnssBatching.cpp", + "GnssBatchingCallback.cpp", "GnssConfiguration.cpp", "GnssMeasurement.cpp", "GnssMeasurementCallback.cpp", diff --git a/services/core/jni/gnss/GnssBatching.cpp b/services/core/jni/gnss/GnssBatching.cpp new file mode 100644 index 000000000000..b66bf21381c7 --- /dev/null +++ b/services/core/jni/gnss/GnssBatching.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2021 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 "GnssBatchingJni" + +#include "GnssBatching.h" + +#include "Utils.h" + +using android::hardware::gnss::IGnssBatching; +using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching; +using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching; + +namespace android::gnss { + +// Implementation of GnssBatching (AIDL HAL) + +GnssBatching::GnssBatching(const sp<IGnssBatching>& iGnssBatching) : mIGnssBatching(iGnssBatching) { + assert(mIGnssBatching != nullptr); +} + +jboolean GnssBatching::init(const std::unique_ptr<GnssBatchingCallback>& callback) { + auto status = mIGnssBatching->init(callback->getAidl()); + return checkAidlStatus(status, "IGnssBatchingAidl init() failed."); +} + +jint GnssBatching::getBatchSize() { + int size = 0; + auto status = mIGnssBatching->getBatchSize(&size); + if (!checkAidlStatus(status, "IGnssBatchingAidl getBatchSize() failed")) { + return 0; + } + return size; +} + +jboolean GnssBatching::start(long periodNanos, bool wakeOnFifoFull) { + int flags = (wakeOnFifoFull) ? IGnssBatching::WAKEUP_ON_FIFO_FULL : 0; + auto status = mIGnssBatching->start(periodNanos, flags); + return checkAidlStatus(status, "IGnssBatchingAidl start() failed."); +} + +jboolean GnssBatching::stop() { + auto status = mIGnssBatching->stop(); + return checkAidlStatus(status, "IGnssBatchingAidl stop() failed."); +} + +jboolean GnssBatching::flush() { + auto status = mIGnssBatching->flush(); + return checkAidlStatus(status, "IGnssBatchingAidl flush() failed."); +} + +jboolean GnssBatching::cleanup() { + auto status = mIGnssBatching->cleanup(); + return checkAidlStatus(status, "IGnssBatchingAidl cleanup() failed"); +} + +// Implementation of GnssBatching_V1_0 + +GnssBatching_V1_0::GnssBatching_V1_0(const sp<IGnssBatching_V1_0>& iGnssBatching) + : mIGnssBatching_V1_0(iGnssBatching) { + assert(mIGnssBatching_V1_0 != nullptr); +} + +jboolean GnssBatching_V1_0::init(const std::unique_ptr<GnssBatchingCallback>& callback) { + auto result = mIGnssBatching_V1_0->init(callback->getV1_0()); + return checkHidlReturn(result, "IGnssBatching_V1_0 init() failed."); +} + +jint GnssBatching_V1_0::getBatchSize() { + auto result = mIGnssBatching_V1_0->getBatchSize(); + if (!checkHidlReturn(result, "IGnssBatching getBatchSize() failed.")) { + return 0; // failure in binder, don't support batching + } + return static_cast<jint>(result); +} + +jboolean GnssBatching_V1_0::start(long periodNanos, bool wakeOnFifoFull) { + IGnssBatching_V1_0::Options options; + options.periodNanos = periodNanos; + if (wakeOnFifoFull) { + options.flags = static_cast<uint8_t>(IGnssBatching_V1_0::Flag::WAKEUP_ON_FIFO_FULL); + } else { + options.flags = 0; + } + + auto result = mIGnssBatching_V1_0->start(options); + return checkHidlReturn(result, "IGnssBatching start() failed."); +} + +jboolean GnssBatching_V1_0::stop() { + auto result = mIGnssBatching_V1_0->stop(); + return checkHidlReturn(result, "IGnssBatching stop() failed."); +} + +jboolean GnssBatching_V1_0::flush() { + auto result = mIGnssBatching_V1_0->flush(); + return checkHidlReturn(result, "IGnssBatching flush() failed."); +} + +jboolean GnssBatching_V1_0::cleanup() { + auto result = mIGnssBatching_V1_0->cleanup(); + return checkHidlReturn(result, "IGnssBatching cleanup() failed."); +} + +// Implementation of GnssBatching_V2_0 + +GnssBatching_V2_0::GnssBatching_V2_0(const sp<IGnssBatching_V2_0>& iGnssBatching) + : GnssBatching_V1_0{iGnssBatching}, mIGnssBatching_V2_0(iGnssBatching) { + assert(mIGnssBatching_V2_0 != nullptr); +} + +jboolean GnssBatching_V2_0::init(const std::unique_ptr<GnssBatchingCallback>& callback) { + auto result = mIGnssBatching_V2_0->init_2_0(callback->getV2_0()); + return checkHidlReturn(result, "IGnssBatching_V2_0 init() failed."); +} + +} // namespace android::gnss diff --git a/services/core/jni/gnss/GnssBatching.h b/services/core/jni/gnss/GnssBatching.h new file mode 100644 index 000000000000..a98ca9b0e492 --- /dev/null +++ b/services/core/jni/gnss/GnssBatching.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 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_GNSSBATCHING_H +#define _ANDROID_SERVER_GNSS_GNSSBATCHING_H + +#pragma once + +#ifndef LOG_TAG +#error LOG_TAG must be defined before including this file. +#endif + +#include <android/hardware/gnss/1.0/IGnssBatching.h> +#include <android/hardware/gnss/2.0/IGnssBatching.h> +#include <android/hardware/gnss/BnGnssBatching.h> +#include <log/log.h> + +#include "GnssBatchingCallback.h" +#include "jni.h" + +namespace android::gnss { + +class GnssBatchingInterface { +public: + virtual ~GnssBatchingInterface() {} + virtual jboolean init(const std::unique_ptr<GnssBatchingCallback>& callback) = 0; + virtual jint getBatchSize() = 0; + virtual jboolean start(long periodNanos, bool wakeupOnFifoFull) = 0; + virtual jboolean stop() = 0; + virtual jboolean flush() = 0; + virtual jboolean cleanup() = 0; +}; + +class GnssBatching : public GnssBatchingInterface { +public: + GnssBatching(const sp<android::hardware::gnss::IGnssBatching>& iGnssBatching); + jboolean init(const std::unique_ptr<GnssBatchingCallback>& callback) override; + jint getBatchSize() override; + jboolean start(long periodNanos, bool wakeupOnFifoFull) override; + jboolean stop() override; + jboolean flush() override; + jboolean cleanup() override; + +private: + const sp<android::hardware::gnss::IGnssBatching> mIGnssBatching; +}; + +class GnssBatching_V1_0 : public GnssBatchingInterface { +public: + GnssBatching_V1_0(const sp<android::hardware::gnss::V1_0::IGnssBatching>& iGnssBatching); + jboolean init(const std::unique_ptr<GnssBatchingCallback>& callback) override; + jint getBatchSize() override; + jboolean start(long periodNanos, bool wakeupOnFifoFull) override; + jboolean stop() override; + jboolean flush() override; + jboolean cleanup() override; + +private: + const sp<android::hardware::gnss::V1_0::IGnssBatching> mIGnssBatching_V1_0; +}; + +class GnssBatching_V2_0 : public GnssBatching_V1_0 { +public: + GnssBatching_V2_0(const sp<android::hardware::gnss::V2_0::IGnssBatching>& iGnssBatching); + jboolean init(const std::unique_ptr<GnssBatchingCallback>& callback) override; + +private: + const sp<android::hardware::gnss::V2_0::IGnssBatching> mIGnssBatching_V2_0; +}; + +} // namespace android::gnss + +#endif // _ANDROID_SERVER_GNSS_GNSSBATCHING_H diff --git a/services/core/jni/gnss/GnssBatchingCallback.cpp b/services/core/jni/gnss/GnssBatchingCallback.cpp new file mode 100644 index 000000000000..d2a55472b6d4 --- /dev/null +++ b/services/core/jni/gnss/GnssBatchingCallback.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2021 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 "GnssBatchingCbJni" + +#include "GnssBatchingCallback.h" + +namespace android::gnss { + +namespace { + +jmethodID method_reportLocationBatch; + +} // anonymous namespace + +using android::hardware::hidl_vec; +using binder::Status; +using hardware::Return; + +using GnssLocationAidl = android::hardware::gnss::GnssLocation; +using GnssLocation_V1_0 = android::hardware::gnss::V1_0::GnssLocation; +using GnssLocation_V2_0 = android::hardware::gnss::V2_0::GnssLocation; + +void GnssBatching_class_init_once(JNIEnv* env, jclass clazz) { + method_reportLocationBatch = + env->GetMethodID(clazz, "reportLocationBatch", "([Landroid/location/Location;)V"); +} + +Status GnssBatchingCallbackAidl::gnssLocationBatchCb( + const std::vector<android::hardware::gnss::GnssLocation>& locations) { + GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(hidl_vec<GnssLocationAidl>(locations)); + return Status::ok(); +} + +Return<void> GnssBatchingCallback_V1_0::gnssLocationBatchCb( + const hidl_vec<GnssLocation_V1_0>& locations) { + return GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(locations); +} + +Return<void> GnssBatchingCallback_V2_0::gnssLocationBatchCb( + const hidl_vec<GnssLocation_V2_0>& locations) { + return GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(locations); +} + +} // namespace android::gnss diff --git a/services/core/jni/gnss/GnssBatchingCallback.h b/services/core/jni/gnss/GnssBatchingCallback.h new file mode 100644 index 000000000000..a9dd43043162 --- /dev/null +++ b/services/core/jni/gnss/GnssBatchingCallback.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2021 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_GNSSBATCHCALLBACK_H +#define _ANDROID_SERVER_GNSS_GNSSBATCHCALLBACK_H + +#pragma once + +#ifndef LOG_TAG +#error LOG_TAG must be defined before including this file. +#endif + +#include <android/hardware/gnss/1.0/IGnssBatching.h> +#include <android/hardware/gnss/2.0/IGnssBatching.h> +#include <android/hardware/gnss/BnGnssBatchingCallback.h> +#include <log/log.h> + +#include <vector> + +#include "Utils.h" +#include "jni.h" + +namespace android::gnss { + +namespace { + +extern jmethodID method_reportLocationBatch; + +} // anonymous namespace + +void GnssBatching_class_init_once(JNIEnv* env, jclass clazz); + +class GnssBatchingCallbackAidl : public hardware::gnss::BnGnssBatchingCallback { +public: + GnssBatchingCallbackAidl() {} + android::binder::Status gnssLocationBatchCb( + const std::vector<android::hardware::gnss::GnssLocation>& locations) override; +}; + +class GnssBatchingCallback_V1_0 : public hardware::gnss::V1_0::IGnssBatchingCallback { +public: + GnssBatchingCallback_V1_0() {} + hardware::Return<void> gnssLocationBatchCb( + const hardware::hidl_vec<hardware::gnss::V1_0::GnssLocation>& locations) override; +}; + +class GnssBatchingCallback_V2_0 : public hardware::gnss::V2_0::IGnssBatchingCallback { +public: + GnssBatchingCallback_V2_0() {} + hardware::Return<void> gnssLocationBatchCb( + const hardware::hidl_vec<hardware::gnss::V2_0::GnssLocation>& locations) override; +}; + +class GnssBatchingCallback { +public: + GnssBatchingCallback() {} + sp<GnssBatchingCallbackAidl> getAidl() { + if (callbackAidl == nullptr) { + callbackAidl = sp<GnssBatchingCallbackAidl>::make(); + } + return callbackAidl; + } + + sp<GnssBatchingCallback_V1_0> getV1_0() { + if (callbackV1_0 == nullptr) { + callbackV1_0 = sp<GnssBatchingCallback_V1_0>::make(); + } + return callbackV1_0; + } + + sp<GnssBatchingCallback_V2_0> getV2_0() { + if (callbackV2_0 == nullptr) { + callbackV2_0 = sp<GnssBatchingCallback_V2_0>::make(); + } + return callbackV2_0; + } + +private: + sp<GnssBatchingCallbackAidl> callbackAidl; + sp<GnssBatchingCallback_V1_0> callbackV1_0; + sp<GnssBatchingCallback_V2_0> callbackV2_0; +}; + +struct GnssBatchingCallbackUtil { + template <class T> + static hardware::Return<void> gnssLocationBatchCbImpl(const hardware::hidl_vec<T>& locations); + +private: + GnssBatchingCallbackUtil() = delete; +}; + +template <class T> +hardware::Return<void> GnssBatchingCallbackUtil::gnssLocationBatchCbImpl( + const hardware::hidl_vec<T>& locations) { + JNIEnv* env = getJniEnv(); + + jobjectArray jLocations = env->NewObjectArray(locations.size(), class_location, nullptr); + + for (uint16_t i = 0; i < locations.size(); ++i) { + jobject jLocation = translateGnssLocation(env, locations[i]); + env->SetObjectArrayElement(jLocations, i, jLocation); + env->DeleteLocalRef(jLocation); + } + + env->CallVoidMethod(android::getCallbacksObj(), method_reportLocationBatch, jLocations); + checkAndClearExceptionFromCallback(env, __FUNCTION__); + + env->DeleteLocalRef(jLocations); + + return hardware::Void(); +} + +} // namespace android::gnss + +#endif // _ANDROID_SERVER_GNSS_GNSSBATCHCALLBACK_H
\ No newline at end of file diff --git a/services/core/jni/gnss/Utils.cpp b/services/core/jni/gnss/Utils.cpp index 8cbdfb8d294e..40a94ce62b05 100644 --- a/services/core/jni/gnss/Utils.cpp +++ b/services/core/jni/gnss/Utils.cpp @@ -18,6 +18,9 @@ #include "Utils.h" +#include <android/hardware/gnss/1.0/IGnss.h> +#include <android/hardware/gnss/2.0/IGnss.h> +#include <utils/SystemClock.h> /* * Save a pointer to JavaVm to attach/detach threads executing * callback methods that need to make JNI calls. @@ -29,9 +32,29 @@ namespace android { namespace { thread_local std::unique_ptr<ScopedJniThreadAttach> tJniThreadAttacher; +jmethodID method_locationCtor; } // anonymous namespace +jclass class_location; + +namespace gnss { +void Utils_class_init_once(JNIEnv* env) { + jclass locationClass = env->FindClass("android/location/Location"); + class_location = (jclass)env->NewGlobalRef(locationClass); + method_locationCtor = env->GetMethodID(class_location, "<init>", "(Ljava/lang/String;)V"); +} +} // namespace gnss + +jobject mCallbacksObj = nullptr; + +jobject& getCallbacksObj() { + return mCallbacksObj; +} + +using GnssLocation_V1_0 = android::hardware::gnss::V1_0::GnssLocation; +using GnssLocation_V2_0 = android::hardware::gnss::V2_0::GnssLocation; + // Define Java method signatures for all known types. template <> const char* const JavaMethodHelper<uint8_t>::signature_ = "(B)V"; @@ -130,4 +153,103 @@ JNIEnv* getJniEnv() { return env; } +template <> +jobject translateGnssLocation(JNIEnv* env, const android::hardware::gnss::GnssLocation& location) { + JavaObject object(env, class_location, method_locationCtor, "gps"); + + uint32_t flags = static_cast<uint32_t>(location.gnssLocationFlags); + if (flags & android::hardware::gnss::GnssLocation::HAS_LAT_LONG) { + SET(Latitude, location.latitudeDegrees); + SET(Longitude, location.longitudeDegrees); + } + if (flags & android::hardware::gnss::GnssLocation::HAS_ALTITUDE) { + SET(Altitude, location.altitudeMeters); + } + if (flags & android::hardware::gnss::GnssLocation::HAS_SPEED) { + SET(Speed, (float)location.speedMetersPerSec); + } + if (flags & android::hardware::gnss::GnssLocation::HAS_BEARING) { + SET(Bearing, (float)location.bearingDegrees); + } + if (flags & android::hardware::gnss::GnssLocation::HAS_HORIZONTAL_ACCURACY) { + SET(Accuracy, (float)location.horizontalAccuracyMeters); + } + if (flags & android::hardware::gnss::GnssLocation::HAS_VERTICAL_ACCURACY) { + SET(VerticalAccuracyMeters, (float)location.verticalAccuracyMeters); + } + if (flags & android::hardware::gnss::GnssLocation::HAS_SPEED_ACCURACY) { + SET(SpeedAccuracyMetersPerSecond, (float)location.speedAccuracyMetersPerSecond); + } + if (flags & android::hardware::gnss::GnssLocation::HAS_BEARING_ACCURACY) { + SET(BearingAccuracyDegrees, (float)location.bearingAccuracyDegrees); + } + SET(Time, location.timestampMillis); + + flags = static_cast<uint32_t>(location.elapsedRealtime.flags); + if (flags & android::hardware::gnss::ElapsedRealtime::HAS_TIMESTAMP_NS) { + SET(ElapsedRealtimeNanos, location.elapsedRealtime.timestampNs); + } + if (flags & android::hardware::gnss::ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS) { + SET(ElapsedRealtimeUncertaintyNanos, + static_cast<double>(location.elapsedRealtime.timeUncertaintyNs)); + } + + return object.get(); +} + +template <> +jobject translateGnssLocation(JNIEnv* env, const GnssLocation_V1_0& location) { + JavaObject object(env, class_location, method_locationCtor, "gps"); + + uint16_t flags = static_cast<uint16_t>(location.gnssLocationFlags); + if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_LAT_LONG) { + SET(Latitude, location.latitudeDegrees); + SET(Longitude, location.longitudeDegrees); + } + if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_ALTITUDE) { + SET(Altitude, location.altitudeMeters); + } + if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_SPEED) { + SET(Speed, location.speedMetersPerSec); + } + if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_BEARING) { + SET(Bearing, location.bearingDegrees); + } + if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) { + SET(Accuracy, location.horizontalAccuracyMeters); + } + if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_VERTICAL_ACCURACY) { + SET(VerticalAccuracyMeters, location.verticalAccuracyMeters); + } + if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_SPEED_ACCURACY) { + SET(SpeedAccuracyMetersPerSecond, location.speedAccuracyMetersPerSecond); + } + if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_BEARING_ACCURACY) { + SET(BearingAccuracyDegrees, location.bearingAccuracyDegrees); + } + SET(Time, location.timestamp); + SET(ElapsedRealtimeNanos, android::elapsedRealtimeNano()); + + return object.get(); +} + +template <> +jobject translateGnssLocation(JNIEnv* env, const GnssLocation_V2_0& location) { + JavaObject object(env, class_location, translateGnssLocation(env, location.v1_0)); + + const uint16_t flags = static_cast<uint16_t>(location.elapsedRealtime.flags); + + // Overwrite ElapsedRealtimeNanos when available from HAL. + if (flags & android::hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) { + SET(ElapsedRealtimeNanos, location.elapsedRealtime.timestampNs); + } + + if (flags & android::hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) { + SET(ElapsedRealtimeUncertaintyNanos, + static_cast<double>(location.elapsedRealtime.timeUncertaintyNs)); + } + + return object.get(); +} + } // namespace android diff --git a/services/core/jni/gnss/Utils.h b/services/core/jni/gnss/Utils.h index 0938a1b30dc8..1bd69c46527e 100644 --- a/services/core/jni/gnss/Utils.h +++ b/services/core/jni/gnss/Utils.h @@ -37,11 +37,19 @@ namespace { // Must match the value from GnssMeasurement.java const uint32_t ADR_STATE_HALF_CYCLE_REPORTED = (1 << 4); +extern jmethodID method_locationCtor; } // anonymous namespace +extern jclass class_location; extern jobject mCallbacksObj; +namespace gnss { +void Utils_class_init_once(JNIEnv* env); +} // namespace gnss + +jobject& getCallbacksObj(); + jboolean checkHidlReturn(hardware::Return<bool>& result, const char* errorMessage); jboolean checkAidlStatus(const android::binder::Status& status, const char* errorMessage); @@ -190,6 +198,9 @@ private: JNIEnv* getJniEnv(); +template <class T> +jobject translateGnssLocation(JNIEnv* env, const T& location); + } // namespace android #endif // _ANDROID_SERVER_GNSS_UTILS_H |