From a4c577da4bd628b526dff4779e964b93dac89559 Mon Sep 17 00:00:00 2001 From: Shinru Han Date: Mon, 15 Nov 2021 20:40:23 +0800 Subject: [PATCH] Add AGnss AIDL HAL (frameworks/base) Bug: 205185251 Test: atest VtsHalGnssTargetTest Change-Id: I034ea0b7d8148900ce9be22a1ef3928beebe067a --- ...d_server_location_GnssLocationProvider.cpp | 273 ++---------------- services/core/jni/gnss/AGnss.cpp | 141 +++++++++ services/core/jni/gnss/AGnss.h | 86 ++++++ services/core/jni/gnss/AGnssCallback.cpp | 133 +++++++++ services/core/jni/gnss/AGnssCallback.h | 134 +++++++++ services/core/jni/gnss/Android.bp | 2 + services/core/jni/gnss/Utils.h | 24 ++ 7 files changed, 546 insertions(+), 247 deletions(-) create mode 100644 services/core/jni/gnss/AGnss.cpp create mode 100644 services/core/jni/gnss/AGnss.h create mode 100644 services/core/jni/gnss/AGnssCallback.cpp create mode 100644 services/core/jni/gnss/AGnssCallback.h diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index 45048530603aa..029254c93dfcc 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -37,10 +37,7 @@ #include #include #include -#include #include -#include -#include #include #include #include @@ -52,6 +49,7 @@ #include "android_runtime/AndroidRuntime.h" #include "android_runtime/Log.h" +#include "gnss/AGnss.h" #include "gnss/GnssAntennaInfoCallback.h" #include "gnss/GnssBatching.h" #include "gnss/GnssConfiguration.h" @@ -69,7 +67,6 @@ static jclass class_gnssPowerStats; static jmethodID method_reportLocation; static jmethodID method_reportStatus; static jmethodID method_reportSvStatus; -static jmethodID method_reportAGpsStatus; static jmethodID method_reportNmea; static jmethodID method_setTopHalCapabilities; static jmethodID method_setGnssYearOfHardware; @@ -163,10 +160,6 @@ using IGnssDebug_V2_0 = android::hardware::gnss::V2_0::IGnssDebug; using IGnssAntennaInfo = android::hardware::gnss::V2_1::IGnssAntennaInfo; 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; -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 IMeasurementCorrections_V1_0 = android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections; using IMeasurementCorrections_V1_1 = android::hardware::gnss::measurement_corrections::V1_1::IMeasurementCorrections; @@ -182,6 +175,7 @@ using android::hardware::gnss::GnssPowerStats; using android::hardware::gnss::IGnssPowerIndication; using android::hardware::gnss::IGnssPowerIndicationCallback; using android::hardware::gnss::PsdsType; +using IAGnssAidl = android::hardware::gnss::IAGnss; using IGnssAidl = android::hardware::gnss::IGnss; using IGnssCallbackAidl = android::hardware::gnss::IGnssCallback; using IGnssBatchingAidl = android::hardware::gnss::IGnssBatching; @@ -215,8 +209,6 @@ sp gnssPsdsAidlIface = nullptr; sp gnssXtraIface = nullptr; sp agnssRilIface = nullptr; sp agnssRilIface_V2_0 = nullptr; -sp agnssIface = nullptr; -sp agnssIface_V2_0 = nullptr; sp gnssDebugIface = nullptr; sp gnssDebugIface_V2_0 = nullptr; sp gnssNiIface = nullptr; @@ -231,6 +223,7 @@ std::unique_ptr gnssMeasurementIface = std::unique_ptr gnssNavigationMessageIface = nullptr; std::unique_ptr gnssBatchingIface = nullptr; std::unique_ptr gnssGeofencingIface = nullptr; +std::unique_ptr agnssIface = nullptr; #define WAKE_LOCK_NAME "GPS" @@ -255,34 +248,6 @@ static inline jboolean boolToJbool(bool value) { return value ? JNI_TRUE : JNI_FALSE; } -struct ScopedJniString { - ScopedJniString(JNIEnv* env, jstring javaString) : mEnv(env), mJavaString(javaString) { - mNativeString = mEnv->GetStringUTFChars(mJavaString, nullptr); - } - - ~ScopedJniString() { - if (mNativeString != nullptr) { - mEnv->ReleaseStringUTFChars(mJavaString, mNativeString); - } - } - - const char* c_str() const { - return mNativeString; - } - - operator hidl_string() const { - return hidl_string(mNativeString); - } - -private: - ScopedJniString(const ScopedJniString&) = delete; - ScopedJniString& operator=(const ScopedJniString&) = delete; - - JNIEnv* mEnv; - jstring mJavaString; - const char* mNativeString; -}; - static GnssLocation_V1_0 createGnssLocation_V1_0( jint gnssLocationFlags, jdouble latitudeDegrees, jdouble longitudeDegrees, jdouble altitudeMeters, jfloat speedMetersPerSec, jfloat bearingDegrees, @@ -805,122 +770,6 @@ Return GnssVisibilityControlCallback::isInEmergencySession() { return result; } -/* - * AGnssCallback_V1_0 implements callback methods required by the IAGnssCallback 1.0 interface. - */ -struct AGnssCallback_V1_0 : public IAGnssCallback_V1_0 { - // Methods from ::android::hardware::gps::V1_0::IAGnssCallback follow. - Return agnssStatusIpV6Cb( - const IAGnssCallback_V1_0::AGnssStatusIpV6& agps_status) override; - - Return agnssStatusIpV4Cb( - const IAGnssCallback_V1_0::AGnssStatusIpV4& agps_status) override; - private: - jbyteArray convertToIpV4(uint32_t ip); -}; - -Return AGnssCallback_V1_0::agnssStatusIpV6Cb( - const IAGnssCallback_V1_0::AGnssStatusIpV6& agps_status) { - JNIEnv* env = getJniEnv(); - jbyteArray byteArray = nullptr; - - byteArray = env->NewByteArray(16); - if (byteArray != nullptr) { - env->SetByteArrayRegion(byteArray, 0, 16, - (const jbyte*)(agps_status.ipV6Addr.data())); - } else { - ALOGE("Unable to allocate byte array for IPv6 address."); - } - - IF_ALOGD() { - // log the IP for reference in case there is a bogus value pushed by HAL - char str[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, agps_status.ipV6Addr.data(), str, INET6_ADDRSTRLEN); - ALOGD("AGPS IP is v6: %s", str); - } - - jsize byteArrayLength = byteArray != nullptr ? env->GetArrayLength(byteArray) : 0; - ALOGV("Passing AGPS IP addr: size %d", byteArrayLength); - env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, - agps_status.type, agps_status.status, byteArray); - - checkAndClearExceptionFromCallback(env, __FUNCTION__); - - if (byteArray) { - env->DeleteLocalRef(byteArray); - } - - return Void(); -} - -Return AGnssCallback_V1_0::agnssStatusIpV4Cb( - const IAGnssCallback_V1_0::AGnssStatusIpV4& agps_status) { - JNIEnv* env = getJniEnv(); - jbyteArray byteArray = nullptr; - - uint32_t ipAddr = agps_status.ipV4Addr; - byteArray = convertToIpV4(ipAddr); - - IF_ALOGD() { - /* - * log the IP for reference in case there is a bogus value pushed by - * HAL. - */ - char str[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN); - ALOGD("AGPS IP is v4: %s", str); - } - - jsize byteArrayLength = - byteArray != nullptr ? env->GetArrayLength(byteArray) : 0; - ALOGV("Passing AGPS IP addr: size %d", byteArrayLength); - env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, - agps_status.type, agps_status.status, byteArray); - - checkAndClearExceptionFromCallback(env, __FUNCTION__); - - if (byteArray) { - env->DeleteLocalRef(byteArray); - } - return Void(); -} - -jbyteArray AGnssCallback_V1_0::convertToIpV4(uint32_t ip) { - if (INADDR_NONE == ip) { - return nullptr; - } - - JNIEnv* env = getJniEnv(); - jbyteArray byteArray = env->NewByteArray(4); - if (byteArray == nullptr) { - ALOGE("Unable to allocate byte array for IPv4 address"); - return nullptr; - } - - jbyte ipv4[4]; - ALOGV("Converting IPv4 address byte array (net_order) %x", ip); - memcpy(ipv4, &ip, sizeof(ipv4)); - env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*)ipv4); - return byteArray; -} - -/* - * AGnssCallback_V2_0 implements callback methods required by the IAGnssCallback 2.0 interface. - */ -struct AGnssCallback_V2_0 : public IAGnssCallback_V2_0 { - // Methods from ::android::hardware::gps::V2_0::IAGnssCallback follow. - Return agnssStatusCb(IAGnssCallback_V2_0::AGnssType type, - IAGnssCallback_V2_0::AGnssStatusValue status) override; -}; - -Return AGnssCallback_V2_0::agnssStatusCb(IAGnssCallback_V2_0::AGnssType type, - IAGnssCallback_V2_0::AGnssStatusValue status) { - JNIEnv* env = getJniEnv(); - env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, type, status, nullptr); - checkAndClearExceptionFromCallback(env, __FUNCTION__); - return Void(); -} - /* * AGnssRilCallback implements the callback methods required by the AGnssRil * interface. @@ -990,7 +839,6 @@ static void android_location_gnss_hal_GnssNative_class_init_once(JNIEnv* env, jc "(ZLandroid/location/Location;)V"); method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V"); method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "(I[I[F[F[F[F[F)V"); - method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V"); method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V"); method_setTopHalCapabilities = env->GetMethodID(clazz, "setTopHalCapabilities", "(I)V"); method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V"); @@ -1077,6 +925,7 @@ static void android_location_gnss_hal_GnssNative_class_init_once(JNIEnv* env, jc gnss::GnssConfiguration_class_init_once(env); gnss::GnssMeasurement_class_init_once(env, clazz); gnss::GnssNavigationMessage_class_init_once(env, clazz); + gnss::AGnss_class_init_once(env, clazz); gnss::Utils_class_init_once(env); } @@ -1147,19 +996,21 @@ static void android_location_gnss_hal_GnssNative_init_once(JNIEnv* env, jobject } } - if (gnssHal_V2_0 != nullptr) { + if (gnssHalAidl != nullptr) { + sp agnssAidl; + auto status = gnssHalAidl->getExtensionAGnss(&agnssAidl); + if (checkAidlStatus(status, "Unable to get a handle to AGnss interface.")) { + agnssIface = std::make_unique(agnssAidl); + } + } else if (gnssHal_V2_0 != nullptr) { auto agnss_V2_0 = gnssHal_V2_0->getExtensionAGnss_2_0(); - if (!agnss_V2_0.isOk()) { - ALOGD("Unable to get a handle to AGnss_V2_0"); - } else { - agnssIface_V2_0 = agnss_V2_0; + if (checkHidlReturn(agnss_V2_0, "Unable to get a handle to AGnss_V2_0")) { + agnssIface = std::make_unique(agnss_V2_0); } } else if (gnssHal != nullptr) { auto agnss_V1_0 = gnssHal->getExtensionAGnss(); - if (!agnss_V1_0.isOk()) { - ALOGD("Unable to get a handle to AGnss"); - } else { - agnssIface = agnss_V1_0; + if (checkHidlReturn(agnss_V1_0, "Unable to get a handle to AGnss_V1_0")) { + agnssIface = std::make_unique(agnss_V1_0); } } @@ -1452,16 +1303,9 @@ static jboolean android_location_gnss_hal_GnssNative_init(JNIEnv* /* env */, jcl } } - // Set IAGnss.hal callback. - if (agnssIface_V2_0 != nullptr) { - sp aGnssCbIface = new AGnssCallback_V2_0(); - auto agnssStatus = agnssIface_V2_0->setCallback(aGnssCbIface); - checkHidlReturn(agnssStatus, "IAGnss 2.0 setCallback() failed."); - } else if (agnssIface != nullptr) { - sp aGnssCbIface = new AGnssCallback_V1_0(); - auto agnssStatus = agnssIface->setCallback(aGnssCbIface); - checkHidlReturn(agnssStatus, "IAGnss setCallback() failed."); - } else { + // Set IAGnss callback. + if (agnssIface == nullptr || + !agnssIface->setCallback(std::make_unique())) { ALOGI("Unable to initialize IAGnss interface."); } @@ -1737,61 +1581,6 @@ static void android_location_gnss_hal_GnssNative_inject_psds_data(JNIEnv* env, j env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT); } -struct AGnssDispatcher { - static void dataConnOpen(sp agnssIface, JNIEnv* env, jstring apn, jint apnIpType); - static void dataConnOpen(sp agnssIface_V2_0, JNIEnv* env, jlong networkHandle, - jstring apn, jint apnIpType); - - template - static void dataConnClosed(sp agnssIface); - - template - static void dataConnFailed(sp agnssIface); - - template - static void setServer(sp agnssIface, JNIEnv* env, jint type, jstring hostname, jint port); - -private: - AGnssDispatcher() = delete; -}; - -void AGnssDispatcher::dataConnOpen(sp agnssIface, JNIEnv* env, jstring apn, - jint apnIpType) { - ScopedJniString jniApn{env, apn}; - auto result = agnssIface->dataConnOpen(jniApn, - static_cast(apnIpType)); - checkHidlReturn(result, "IAGnss dataConnOpen() failed. APN and its IP type not set."); -} - -void AGnssDispatcher::dataConnOpen(sp agnssIface_V2_0, JNIEnv* env, - jlong networkHandle, jstring apn, jint apnIpType) { - ScopedJniString jniApn{env, apn}; - auto result = agnssIface_V2_0->dataConnOpen(static_cast(networkHandle), jniApn, - static_cast(apnIpType)); - checkHidlReturn(result, "IAGnss 2.0 dataConnOpen() failed. APN and its IP type not set."); -} - -template -void AGnssDispatcher::dataConnClosed(sp agnssIface) { - auto result = agnssIface->dataConnClosed(); - checkHidlReturn(result, "IAGnss dataConnClosed() failed."); -} - -template -void AGnssDispatcher::dataConnFailed(sp agnssIface) { - auto result = agnssIface->dataConnFailed(); - checkHidlReturn(result, "IAGnss dataConnFailed() failed."); -} - -template -void AGnssDispatcher::setServer(sp agnssIface, JNIEnv* env, jint type, jstring hostname, - jint port) { - ScopedJniString jniHostName{env, hostname}; - auto result = agnssIface->setServer(static_cast(type), - jniHostName, port); - checkHidlReturn(result, "IAGnss setServer() failed. Host name and port not set."); -} - static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_open( JNIEnv* env, jobject /* obj */, jlong networkHandle, jstring apn, jint apnIpType) { if (apn == nullptr) { @@ -1799,10 +1588,8 @@ static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_open( return; } - if (agnssIface_V2_0 != nullptr) { - AGnssDispatcher::dataConnOpen(agnssIface_V2_0, env, networkHandle, apn, apnIpType); - } else if (agnssIface != nullptr) { - AGnssDispatcher::dataConnOpen(agnssIface, env, apn, apnIpType); + if (agnssIface != nullptr) { + agnssIface->dataConnOpen(env, networkHandle, apn, apnIpType); } else { ALOGE("%s: IAGnss interface not available.", __func__); return; @@ -1811,10 +1598,8 @@ static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_open( static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_closed(JNIEnv* /* env */, jobject /* obj */) { - if (agnssIface_V2_0 != nullptr) { - AGnssDispatcher::dataConnClosed(agnssIface_V2_0); - } else if (agnssIface != nullptr) { - AGnssDispatcher::dataConnClosed(agnssIface); + if (agnssIface != nullptr) { + agnssIface->dataConnClosed(); } else { ALOGE("%s: IAGnss interface not available.", __func__); return; @@ -1823,10 +1608,8 @@ static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_close static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_failed(JNIEnv* /* env */, jobject /* obj */) { - if (agnssIface_V2_0 != nullptr) { - AGnssDispatcher::dataConnFailed(agnssIface_V2_0); - } else if (agnssIface != nullptr) { - AGnssDispatcher::dataConnFailed(agnssIface); + if (agnssIface != nullptr) { + agnssIface->dataConnFailed(); } else { ALOGE("%s: IAGnss interface not available.", __func__); return; @@ -1835,12 +1618,8 @@ static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_faile static void android_location_gnss_hal_GnssNative_set_agps_server(JNIEnv* env, jclass, jint type, jstring hostname, jint port) { - if (agnssIface_V2_0 != nullptr) { - AGnssDispatcher::setServer(agnssIface_V2_0, env, type, - hostname, port); - } else if (agnssIface != nullptr) { - AGnssDispatcher::setServer(agnssIface, env, type, - hostname, port); + if (agnssIface != nullptr) { + agnssIface->setServer(env, type, hostname, port); } else { ALOGE("%s: IAGnss interface not available.", __func__); return; diff --git a/services/core/jni/gnss/AGnss.cpp b/services/core/jni/gnss/AGnss.cpp new file mode 100644 index 0000000000000..00403d6313066 --- /dev/null +++ b/services/core/jni/gnss/AGnss.cpp @@ -0,0 +1,141 @@ +/* + * 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 to overwrite the default value. +#define LOG_TAG "AGnssJni" + +#include "AGnss.h" + +#include "Utils.h" + +using android::hardware::gnss::IAGnss; +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 AGnssType = android::hardware::gnss::IAGnssCallback::AGnssType; + +namespace android::gnss { + +// Implementation of AGnss (AIDL HAL) + +AGnss::AGnss(const sp& iAGnss) : mIAGnss(iAGnss) { + assert(mIAGnss != nullptr); +} + +jboolean AGnss::setCallback(const std::unique_ptr& callback) { + auto status = mIAGnss->setCallback(callback->getAidl()); + return checkAidlStatus(status, "IAGnssAidl setCallback() failed."); +} + +jboolean AGnss::dataConnOpen(JNIEnv* env, jlong networkHandle, jstring apn, jint apnIpType) { + ScopedJniString jniApn{env, apn}; + auto status = mIAGnss->dataConnOpen(networkHandle, String16(jniApn.c_str()), + static_cast(apnIpType)); + return checkAidlStatus(status, + "IAGnssAidl dataConnOpen() failed. APN and its IP type not set."); +} + +jboolean AGnss::dataConnClosed() { + auto status = mIAGnss->dataConnClosed(); + return checkAidlStatus(status, "IAGnssAidl dataConnClosed() failed."); +} + +jboolean AGnss::dataConnFailed() { + auto status = mIAGnss->dataConnFailed(); + return checkAidlStatus(status, "IAGnssAidl dataConnFailed() failed."); +} + +jboolean AGnss::setServer(JNIEnv* env, jint type, jstring hostname, jint port) { + ScopedJniString jniHostName{env, hostname}; + auto status = + mIAGnss->setServer(static_cast(type), String16(jniHostName.c_str()), port); + return checkAidlStatus(status, "IAGnssAidl setServer() failed. Host name and port not set."); +} + +// Implementation of AGnss_V1_0 + +AGnss_V1_0::AGnss_V1_0(const sp& iAGnss) : mIAGnss_V1_0(iAGnss) { + assert(mIAGnss_V1_0 != nullptr); +} + +jboolean AGnss_V1_0::setCallback(const std::unique_ptr& callback) { + auto result = mIAGnss_V1_0->setCallback(callback->getV1_0()); + return checkHidlReturn(result, "IAGnss_V1_0 setCallback() failed."); +} + +jboolean AGnss_V1_0::dataConnOpen(JNIEnv* env, jlong, jstring apn, jint apnIpType) { + ScopedJniString jniApn{env, apn}; + auto result = + mIAGnss_V1_0->dataConnOpen(jniApn, static_cast(apnIpType)); + return checkHidlReturn(result, + "IAGnss_V1_0 dataConnOpen() failed. APN and its IP type not set."); +} + +jboolean AGnss_V1_0::dataConnClosed() { + auto result = mIAGnss_V1_0->dataConnClosed(); + return checkHidlReturn(result, "IAGnss_V1_0 dataConnClosed() failed."); +} + +jboolean AGnss_V1_0::dataConnFailed() { + auto result = mIAGnss_V1_0->dataConnFailed(); + return checkHidlReturn(result, "IAGnss_V1_0 dataConnFailed() failed."); +} + +jboolean AGnss_V1_0::setServer(JNIEnv* env, jint type, jstring hostname, jint port) { + ScopedJniString jniHostName{env, hostname}; + auto result = mIAGnss_V1_0->setServer(static_cast(type), + jniHostName, port); + return checkHidlReturn(result, "IAGnss_V1_0 setServer() failed. Host name and port not set."); +} + +// Implementation of AGnss_V2_0 + +AGnss_V2_0::AGnss_V2_0(const sp& iAGnss) : mIAGnss_V2_0(iAGnss) { + assert(mIAGnss_V2_0 != nullptr); +} + +jboolean AGnss_V2_0::setCallback(const std::unique_ptr& callback) { + auto result = mIAGnss_V2_0->setCallback(callback->getV2_0()); + return checkHidlReturn(result, "IAGnss_V2_0 setCallback() failed."); +} + +jboolean AGnss_V2_0::dataConnOpen(JNIEnv* env, jlong networkHandle, jstring apn, jint apnIpType) { + ScopedJniString jniApn{env, apn}; + auto result = mIAGnss_V2_0->dataConnOpen(static_cast(networkHandle), jniApn, + static_cast(apnIpType)); + return checkHidlReturn(result, + "IAGnss_V2_0 dataConnOpen() failed. APN and its IP type not set."); +} + +jboolean AGnss_V2_0::dataConnClosed() { + auto result = mIAGnss_V2_0->dataConnClosed(); + return checkHidlReturn(result, "IAGnss_V2_0 dataConnClosed() failed."); +} + +jboolean AGnss_V2_0::dataConnFailed() { + auto result = mIAGnss_V2_0->dataConnFailed(); + return checkHidlReturn(result, "IAGnss_V2_0 dataConnFailed() failed."); +} + +jboolean AGnss_V2_0::setServer(JNIEnv* env, jint type, jstring hostname, jint port) { + ScopedJniString jniHostName{env, hostname}; + auto result = mIAGnss_V2_0->setServer(static_cast(type), + jniHostName, port); + return checkHidlReturn(result, "IAGnss_V2_0 setServer() failed. Host name and port not set."); +} + +} // namespace android::gnss diff --git a/services/core/jni/gnss/AGnss.h b/services/core/jni/gnss/AGnss.h new file mode 100644 index 0000000000000..2828b82b92c13 --- /dev/null +++ b/services/core/jni/gnss/AGnss.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_AGNSS_H +#define _ANDROID_SERVER_GNSS_AGNSS_H + +#pragma once + +#ifndef LOG_TAG +#error LOG_TAG must be defined before including this file. +#endif + +#include +#include + +#include "AGnssCallback.h" +#include "jni.h" + +namespace android::gnss { + +class AGnssInterface { +public: + virtual ~AGnssInterface() {} + virtual jboolean setCallback(const std::unique_ptr& callback) = 0; + virtual jboolean dataConnOpen(JNIEnv* env, jlong networkHandle, jstring apn, + jint apnIpType) = 0; + virtual jboolean dataConnClosed() = 0; + virtual jboolean dataConnFailed() = 0; + virtual jboolean setServer(JNIEnv* env, jint type, jstring hostname, jint port) = 0; +}; + +class AGnss : public AGnssInterface { +public: + AGnss(const sp& iAGnss); + jboolean setCallback(const std::unique_ptr& callback) override; + jboolean dataConnOpen(JNIEnv* env, jlong networkHandle, jstring apn, jint apnIpType) override; + jboolean dataConnClosed() override; + jboolean dataConnFailed() override; + jboolean setServer(JNIEnv* env, jint type, jstring hostname, jint port) override; + +private: + const sp mIAGnss; +}; + +class AGnss_V1_0 : public AGnssInterface { +public: + AGnss_V1_0(const sp& iAGnss); + jboolean setCallback(const std::unique_ptr& callback) override; + jboolean dataConnOpen(JNIEnv* env, jlong, jstring apn, jint apnIpType) override; + jboolean dataConnClosed() override; + jboolean dataConnFailed() override; + jboolean setServer(JNIEnv* env, jint type, jstring hostname, jint port) override; + +private: + const sp mIAGnss_V1_0; +}; + +class AGnss_V2_0 : public AGnssInterface { +public: + AGnss_V2_0(const sp& iAGnss); + jboolean setCallback(const std::unique_ptr& callback) override; + jboolean dataConnOpen(JNIEnv* env, jlong networkHandle, jstring apn, jint apnIpType) override; + jboolean dataConnClosed() override; + jboolean dataConnFailed() override; + jboolean setServer(JNIEnv* env, jint type, jstring hostname, jint port) override; + +private: + const sp mIAGnss_V2_0; +}; + +} // namespace android::gnss + +#endif // _ANDROID_SERVER_GNSS_AGNSS_H diff --git a/services/core/jni/gnss/AGnssCallback.cpp b/services/core/jni/gnss/AGnssCallback.cpp new file mode 100644 index 0000000000000..466cdfa78de6a --- /dev/null +++ b/services/core/jni/gnss/AGnssCallback.cpp @@ -0,0 +1,133 @@ +/* + * 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 "AGnssCbJni" + +#include "AGnssCallback.h" + +namespace android::gnss { + +using binder::Status; +using hardware::Return; +using hardware::Void; +using IAGnssCallback_V1_0 = android::hardware::gnss::V1_0::IAGnssCallback; +using IAGnssCallback_V2_0 = android::hardware::gnss::V2_0::IAGnssCallback; + +namespace { + +jmethodID method_reportAGpsStatus; + +} + +void AGnss_class_init_once(JNIEnv* env, jclass clazz) { + method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V"); +} + +Status AGnssCallbackAidl::agnssStatusCb(AGnssType type, AGnssStatusValue status) { + AGnssCallbackUtil::agnssStatusCbImpl(type, status); + return Status::ok(); +} + +Return AGnssCallback_V1_0::agnssStatusIpV6Cb( + const IAGnssCallback_V1_0::AGnssStatusIpV6& agps_status) { + JNIEnv* env = getJniEnv(); + jbyteArray byteArray = nullptr; + + byteArray = env->NewByteArray(16); + if (byteArray != nullptr) { + env->SetByteArrayRegion(byteArray, 0, 16, (const jbyte*)(agps_status.ipV6Addr.data())); + } else { + ALOGE("Unable to allocate byte array for IPv6 address."); + } + + IF_ALOGD() { + // log the IP for reference in case there is a bogus value pushed by HAL + char str[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, agps_status.ipV6Addr.data(), str, INET6_ADDRSTRLEN); + ALOGD("AGPS IP is v6: %s", str); + } + + jsize byteArrayLength = byteArray != nullptr ? env->GetArrayLength(byteArray) : 0; + ALOGV("Passing AGPS IP addr: size %d", byteArrayLength); + env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status.type, + agps_status.status, byteArray); + + checkAndClearExceptionFromCallback(env, __FUNCTION__); + + if (byteArray) { + env->DeleteLocalRef(byteArray); + } + + return Void(); +} + +Return AGnssCallback_V1_0::agnssStatusIpV4Cb( + const IAGnssCallback_V1_0::AGnssStatusIpV4& agps_status) { + JNIEnv* env = getJniEnv(); + jbyteArray byteArray = nullptr; + + uint32_t ipAddr = agps_status.ipV4Addr; + byteArray = convertToIpV4(ipAddr); + + IF_ALOGD() { + /* + * log the IP for reference in case there is a bogus value pushed by + * HAL. + */ + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN); + ALOGD("AGPS IP is v4: %s", str); + } + + jsize byteArrayLength = byteArray != nullptr ? env->GetArrayLength(byteArray) : 0; + ALOGV("Passing AGPS IP addr: size %d", byteArrayLength); + env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status.type, + agps_status.status, byteArray); + + checkAndClearExceptionFromCallback(env, __FUNCTION__); + + if (byteArray) { + env->DeleteLocalRef(byteArray); + } + return Void(); +} + +jbyteArray AGnssCallback_V1_0::convertToIpV4(uint32_t ip) { + if (INADDR_NONE == ip) { + return nullptr; + } + + JNIEnv* env = getJniEnv(); + jbyteArray byteArray = env->NewByteArray(4); + if (byteArray == nullptr) { + ALOGE("Unable to allocate byte array for IPv4 address"); + return nullptr; + } + + jbyte ipv4[4]; + ALOGV("Converting IPv4 address byte array (net_order) %x", ip); + memcpy(ipv4, &ip, sizeof(ipv4)); + env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*)ipv4); + return byteArray; +} + +Return AGnssCallback_V2_0::agnssStatusCb(IAGnssCallback_V2_0::AGnssType type, + IAGnssCallback_V2_0::AGnssStatusValue status) { + AGnssCallbackUtil::agnssStatusCbImpl(type, status); + return Void(); +} + +} // namespace android::gnss diff --git a/services/core/jni/gnss/AGnssCallback.h b/services/core/jni/gnss/AGnssCallback.h new file mode 100644 index 0000000000000..e9bb4717fe605 --- /dev/null +++ b/services/core/jni/gnss/AGnssCallback.h @@ -0,0 +1,134 @@ +/* + * 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_AGNSSCALLBACK_H +#define _ANDROID_SERVER_GNSS_AGNSSCALLBACK_H + +#pragma once + +#ifndef LOG_TAG +#error LOG_TAG must be defined before including this file. +#endif + +#include +#include +#include +#include +#include + +#include + +#include "Utils.h" +#include "jni.h" + +namespace android::gnss { + +namespace { + +extern jmethodID method_reportAGpsStatus; + +} + +void AGnss_class_init_once(JNIEnv* env, jclass clazz); + +/* + * AGnssCallbackAidl class implements the callback methods required by the + * android::hardware::gnss::IAGnss interface. + */ +class AGnssCallbackAidl : public android::hardware::gnss::BnAGnssCallback { +public: + binder::Status agnssStatusCb(AGnssType type, AGnssStatusValue status) override; +}; + +/* + * AGnssCallback_V1_0 implements callback methods required by the IAGnssCallback 1.0 interface. + */ +class AGnssCallback_V1_0 : public android::hardware::gnss::V1_0::IAGnssCallback { +public: + // Methods from ::android::hardware::gps::V1_0::IAGnssCallback follow. + hardware::Return agnssStatusIpV6Cb( + const android::hardware::gnss::V1_0::IAGnssCallback::AGnssStatusIpV6& agps_status) + override; + + hardware::Return agnssStatusIpV4Cb( + const android::hardware::gnss::V1_0::IAGnssCallback::AGnssStatusIpV4& agps_status) + override; + +private: + jbyteArray convertToIpV4(uint32_t ip); +}; + +/* + * AGnssCallback_V2_0 implements callback methods required by the IAGnssCallback 2.0 interface. + */ +class AGnssCallback_V2_0 : public android::hardware::gnss::V2_0::IAGnssCallback { +public: + // Methods from ::android::hardware::gps::V2_0::IAGnssCallback follow. + hardware::Return agnssStatusCb( + android::hardware::gnss::V2_0::IAGnssCallback::AGnssType type, + android::hardware::gnss::V2_0::IAGnssCallback::AGnssStatusValue status) override; +}; + +class AGnssCallback { +public: + AGnssCallback() {} + sp getAidl() { + if (callbackAidl == nullptr) { + callbackAidl = sp::make(); + } + return callbackAidl; + } + + sp getV1_0() { + if (callbackV1_0 == nullptr) { + callbackV1_0 = sp::make(); + } + return callbackV1_0; + } + + sp getV2_0() { + if (callbackV2_0 == nullptr) { + callbackV2_0 = sp::make(); + } + return callbackV2_0; + } + +private: + sp callbackAidl; + sp callbackV1_0; + sp callbackV2_0; +}; + +struct AGnssCallbackUtil { + template + static void agnssStatusCbImpl(const T& type, const U& status); + +private: + AGnssCallbackUtil() = delete; +}; + +template +void AGnssCallbackUtil::agnssStatusCbImpl(const T& type, const U& status) { + ALOGD("%s. type: %d, status:%d", __func__, static_cast(type), + static_cast(status)); + JNIEnv* env = getJniEnv(); + env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, type, status, nullptr); + checkAndClearExceptionFromCallback(env, __FUNCTION__); +} + +} // namespace android::gnss + +#endif // _ANDROID_SERVER_GNSS_AGNSSCALLBACK_H \ No newline at end of file diff --git a/services/core/jni/gnss/Android.bp b/services/core/jni/gnss/Android.bp index ac50bfa5c4429..e49e81c046d24 100644 --- a/services/core/jni/gnss/Android.bp +++ b/services/core/jni/gnss/Android.bp @@ -23,6 +23,8 @@ cc_library_shared { ], srcs: [ + "AGnss.cpp", + "AGnssCallback.cpp", "GnssAntennaInfoCallback.cpp", "GnssBatching.cpp", "GnssBatchingCallback.cpp", diff --git a/services/core/jni/gnss/Utils.h b/services/core/jni/gnss/Utils.h index 1bd69c46527e5..2640a7774c261 100644 --- a/services/core/jni/gnss/Utils.h +++ b/services/core/jni/gnss/Utils.h @@ -196,6 +196,30 @@ private: JNIEnv* mEnv = nullptr; }; +struct ScopedJniString { + ScopedJniString(JNIEnv* env, jstring javaString) : mEnv(env), mJavaString(javaString) { + mNativeString = mEnv->GetStringUTFChars(mJavaString, nullptr); + } + + ~ScopedJniString() { + if (mNativeString != nullptr) { + mEnv->ReleaseStringUTFChars(mJavaString, mNativeString); + } + } + + const char* c_str() const { return mNativeString; } + + operator hardware::hidl_string() const { return hardware::hidl_string(mNativeString); } + +private: + ScopedJniString(const ScopedJniString&) = delete; + ScopedJniString& operator=(const ScopedJniString&) = delete; + + JNIEnv* mEnv; + jstring mJavaString; + const char* mNativeString; +}; + JNIEnv* getJniEnv(); template