Merge "Add AGnss AIDL HAL (frameworks/base)"

This commit is contained in:
TreeHugger Robot
2021-12-07 22:50:36 +00:00
committed by Android (Google) Code Review
7 changed files with 546 additions and 247 deletions

View File

@@ -37,10 +37,7 @@
#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
#include <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
#include <arpa/inet.h>
#include <binder/IServiceManager.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <nativehelper/JNIHelp.h>
#include <pthread.h>
#include <string.h>
@@ -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<IGnssPsdsAidl> gnssPsdsAidlIface = nullptr;
sp<IGnssXtra> gnssXtraIface = nullptr;
sp<IAGnssRil_V1_0> agnssRilIface = nullptr;
sp<IAGnssRil_V2_0> agnssRilIface_V2_0 = nullptr;
sp<IAGnss_V1_0> agnssIface = nullptr;
sp<IAGnss_V2_0> agnssIface_V2_0 = nullptr;
sp<IGnssDebug_V1_0> gnssDebugIface = nullptr;
sp<IGnssDebug_V2_0> gnssDebugIface_V2_0 = nullptr;
sp<IGnssNi> gnssNiIface = nullptr;
@@ -231,6 +223,7 @@ std::unique_ptr<android::gnss::GnssMeasurementInterface> gnssMeasurementIface =
std::unique_ptr<android::gnss::GnssNavigationMessageInterface> gnssNavigationMessageIface = nullptr;
std::unique_ptr<android::gnss::GnssBatchingInterface> gnssBatchingIface = nullptr;
std::unique_ptr<android::gnss::GnssGeofenceInterface> gnssGeofencingIface = nullptr;
std::unique_ptr<android::gnss::AGnssInterface> agnssIface = nullptr;
#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<bool> 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<void> agnssStatusIpV6Cb(
const IAGnssCallback_V1_0::AGnssStatusIpV6& agps_status) override;
Return<void> agnssStatusIpV4Cb(
const IAGnssCallback_V1_0::AGnssStatusIpV4& agps_status) override;
private:
jbyteArray convertToIpV4(uint32_t ip);
};
Return<void> 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<void> 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<void> agnssStatusCb(IAGnssCallback_V2_0::AGnssType type,
IAGnssCallback_V2_0::AGnssStatusValue status) override;
};
Return<void> 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<IAGnssAidl> agnssAidl;
auto status = gnssHalAidl->getExtensionAGnss(&agnssAidl);
if (checkAidlStatus(status, "Unable to get a handle to AGnss interface.")) {
agnssIface = std::make_unique<gnss::AGnss>(agnssAidl);
}
} else if (gnssHal_V2_0 != nullptr) {
auto agnss_V2_0 = gnssHal_V2_0->getExtensionAGnss_2_0();
if (!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<gnss::AGnss_V2_0>(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<gnss::AGnss_V1_0>(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<IAGnssCallback_V2_0> aGnssCbIface = new AGnssCallback_V2_0();
auto agnssStatus = agnssIface_V2_0->setCallback(aGnssCbIface);
checkHidlReturn(agnssStatus, "IAGnss 2.0 setCallback() failed.");
} else if (agnssIface != nullptr) {
sp<IAGnssCallback_V1_0> 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<gnss::AGnssCallback>())) {
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<IAGnss_V1_0> agnssIface, JNIEnv* env, jstring apn, jint apnIpType);
static void dataConnOpen(sp<IAGnss_V2_0> agnssIface_V2_0, JNIEnv* env, jlong networkHandle,
jstring apn, jint apnIpType);
template <class T>
static void dataConnClosed(sp<T> agnssIface);
template <class T>
static void dataConnFailed(sp<T> agnssIface);
template <class T, class U>
static void setServer(sp<T> agnssIface, JNIEnv* env, jint type, jstring hostname, jint port);
private:
AGnssDispatcher() = delete;
};
void AGnssDispatcher::dataConnOpen(sp<IAGnss_V1_0> agnssIface, JNIEnv* env, jstring apn,
jint apnIpType) {
ScopedJniString jniApn{env, apn};
auto result = agnssIface->dataConnOpen(jniApn,
static_cast<IAGnss_V1_0::ApnIpType>(apnIpType));
checkHidlReturn(result, "IAGnss dataConnOpen() failed. APN and its IP type not set.");
}
void AGnssDispatcher::dataConnOpen(sp<IAGnss_V2_0> agnssIface_V2_0, JNIEnv* env,
jlong networkHandle, jstring apn, jint apnIpType) {
ScopedJniString jniApn{env, apn};
auto result = agnssIface_V2_0->dataConnOpen(static_cast<uint64_t>(networkHandle), jniApn,
static_cast<IAGnss_V2_0::ApnIpType>(apnIpType));
checkHidlReturn(result, "IAGnss 2.0 dataConnOpen() failed. APN and its IP type not set.");
}
template<class T>
void AGnssDispatcher::dataConnClosed(sp<T> agnssIface) {
auto result = agnssIface->dataConnClosed();
checkHidlReturn(result, "IAGnss dataConnClosed() failed.");
}
template<class T>
void AGnssDispatcher::dataConnFailed(sp<T> agnssIface) {
auto result = agnssIface->dataConnFailed();
checkHidlReturn(result, "IAGnss dataConnFailed() failed.");
}
template <class T, class U>
void AGnssDispatcher::setServer(sp<T> agnssIface, JNIEnv* env, jint type, jstring hostname,
jint port) {
ScopedJniString jniHostName{env, hostname};
auto result = agnssIface->setServer(static_cast<typename U::AGnssType>(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<IAGnss_V2_0, IAGnssCallback_V2_0>(agnssIface_V2_0, env, type,
hostname, port);
} else if (agnssIface != nullptr) {
AGnssDispatcher::setServer<IAGnss_V1_0, IAGnssCallback_V1_0>(agnssIface, env, type,
hostname, port);
if (agnssIface != nullptr) {
agnssIface->setServer(env, type, hostname, port);
} else {
ALOGE("%s: IAGnss interface not available.", __func__);
return;

View File

@@ -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 <log/log.h> 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>& iAGnss) : mIAGnss(iAGnss) {
assert(mIAGnss != nullptr);
}
jboolean AGnss::setCallback(const std::unique_ptr<AGnssCallback>& 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<IAGnss::ApnIpType>(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<AGnssType>(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_V1_0>& iAGnss) : mIAGnss_V1_0(iAGnss) {
assert(mIAGnss_V1_0 != nullptr);
}
jboolean AGnss_V1_0::setCallback(const std::unique_ptr<AGnssCallback>& 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<IAGnss_V1_0::ApnIpType>(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<IAGnssCallback_V1_0::AGnssType>(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_V2_0>& iAGnss) : mIAGnss_V2_0(iAGnss) {
assert(mIAGnss_V2_0 != nullptr);
}
jboolean AGnss_V2_0::setCallback(const std::unique_ptr<AGnssCallback>& 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<uint64_t>(networkHandle), jniApn,
static_cast<IAGnss_V2_0::ApnIpType>(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<IAGnssCallback_V2_0::AGnssType>(type),
jniHostName, port);
return checkHidlReturn(result, "IAGnss_V2_0 setServer() failed. Host name and port not set.");
}
} // namespace android::gnss

View File

@@ -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 <android/hardware/gnss/BnAGnss.h>
#include <log/log.h>
#include "AGnssCallback.h"
#include "jni.h"
namespace android::gnss {
class AGnssInterface {
public:
virtual ~AGnssInterface() {}
virtual jboolean setCallback(const std::unique_ptr<AGnssCallback>& 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<android::hardware::gnss::IAGnss>& iAGnss);
jboolean setCallback(const std::unique_ptr<AGnssCallback>& 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<android::hardware::gnss::IAGnss> mIAGnss;
};
class AGnss_V1_0 : public AGnssInterface {
public:
AGnss_V1_0(const sp<android::hardware::gnss::V1_0::IAGnss>& iAGnss);
jboolean setCallback(const std::unique_ptr<AGnssCallback>& 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<android::hardware::gnss::V1_0::IAGnss> mIAGnss_V1_0;
};
class AGnss_V2_0 : public AGnssInterface {
public:
AGnss_V2_0(const sp<android::hardware::gnss::V2_0::IAGnss>& iAGnss);
jboolean setCallback(const std::unique_ptr<AGnssCallback>& 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<android::hardware::gnss::V2_0::IAGnss> mIAGnss_V2_0;
};
} // namespace android::gnss
#endif // _ANDROID_SERVER_GNSS_AGNSS_H

View File

@@ -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<void> 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<void> 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<void> AGnssCallback_V2_0::agnssStatusCb(IAGnssCallback_V2_0::AGnssType type,
IAGnssCallback_V2_0::AGnssStatusValue status) {
AGnssCallbackUtil::agnssStatusCbImpl(type, status);
return Void();
}
} // namespace android::gnss

View File

@@ -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 <android/hardware/gnss/1.0/IAGnss.h>
#include <android/hardware/gnss/2.0/IAGnss.h>
#include <android/hardware/gnss/BnAGnssCallback.h>
#include <arpa/inet.h>
#include <log/log.h>
#include <vector>
#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<void> agnssStatusIpV6Cb(
const android::hardware::gnss::V1_0::IAGnssCallback::AGnssStatusIpV6& agps_status)
override;
hardware::Return<void> 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<void> agnssStatusCb(
android::hardware::gnss::V2_0::IAGnssCallback::AGnssType type,
android::hardware::gnss::V2_0::IAGnssCallback::AGnssStatusValue status) override;
};
class AGnssCallback {
public:
AGnssCallback() {}
sp<AGnssCallbackAidl> getAidl() {
if (callbackAidl == nullptr) {
callbackAidl = sp<AGnssCallbackAidl>::make();
}
return callbackAidl;
}
sp<AGnssCallback_V1_0> getV1_0() {
if (callbackV1_0 == nullptr) {
callbackV1_0 = sp<AGnssCallback_V1_0>::make();
}
return callbackV1_0;
}
sp<AGnssCallback_V2_0> getV2_0() {
if (callbackV2_0 == nullptr) {
callbackV2_0 = sp<AGnssCallback_V2_0>::make();
}
return callbackV2_0;
}
private:
sp<AGnssCallbackAidl> callbackAidl;
sp<AGnssCallback_V1_0> callbackV1_0;
sp<AGnssCallback_V2_0> callbackV2_0;
};
struct AGnssCallbackUtil {
template <class T, class U>
static void agnssStatusCbImpl(const T& type, const U& status);
private:
AGnssCallbackUtil() = delete;
};
template <class T, class U>
void AGnssCallbackUtil::agnssStatusCbImpl(const T& type, const U& status) {
ALOGD("%s. type: %d, status:%d", __func__, static_cast<int32_t>(type),
static_cast<int32_t>(status));
JNIEnv* env = getJniEnv();
env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, type, status, nullptr);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
}
} // namespace android::gnss
#endif // _ANDROID_SERVER_GNSS_AGNSSCALLBACK_H

View File

@@ -23,6 +23,8 @@ cc_library_shared {
],
srcs: [
"AGnss.cpp",
"AGnssCallback.cpp",
"GnssAntennaInfoCallback.cpp",
"GnssBatching.cpp",
"GnssBatchingCallback.cpp",

View File

@@ -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 <class T>