blob: 52e2b2097df7ddc52564df763669577d200ea131 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _ANDROID_SERVER_GNSS_UTILS_H
#define _ANDROID_SERVER_GNSS_UTILS_H
#pragma once
#ifndef LOG_TAG
#error LOG_TAG must be defined before including this file.
#endif
#include <android/hardware/gnss/1.0/IGnss.h>
#include <android/hardware/gnss/BnGnss.h>
#include <log/log.h>
#include <nativehelper/JNIHelp.h>
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/Log.h"
#include "jni.h"
namespace android {
namespace {
// Must match the value from GnssMeasurement.java
const uint32_t ADR_STATE_HALF_CYCLE_REPORTED = (1 << 4);
} // anonymous namespace
extern jobject mCallbacksObj;
jboolean checkHidlReturn(hardware::Return<bool>& result, const char* errorMessage);
jboolean checkAidlStatus(const android::binder::Status& status, const char* errorMessage);
void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
void callObjectMethodIgnoringResult(JNIEnv* env, jobject obj, jmethodID mid, ...);
template <class T>
void logHidlError(hardware::Return<T>& result, const char* errorMessage) {
ALOGE("%s HIDL transport error: %s", errorMessage, result.description().c_str());
}
template <class T>
jboolean checkHidlReturn(hardware::Return<T>& result, const char* errorMessage) {
if (!result.isOk()) {
logHidlError(result, errorMessage);
return JNI_FALSE;
} else {
return JNI_TRUE;
}
}
template <class T>
jboolean checkHidlReturn(hardware::Return<sp<T>>& result, const char* errorMessage) {
if (!result.isOk()) {
logHidlError(result, errorMessage);
return JNI_FALSE;
} else if ((sp<T>)result == nullptr) {
return JNI_FALSE;
} else {
return JNI_TRUE;
}
}
template <class T>
class JavaMethodHelper {
public:
// Helper function to call setter on a Java object.
static void callJavaMethod(JNIEnv* env, jclass clazz, jobject object, const char* method_name,
T value);
private:
static const char* const signature_;
};
// Define Java method signatures for all known types.
template <>
const char* const JavaMethodHelper<uint8_t>::signature_;
template <>
const char* const JavaMethodHelper<int8_t>::signature_;
template <>
const char* const JavaMethodHelper<int16_t>::signature_;
template <>
const char* const JavaMethodHelper<uint16_t>::signature_;
template <>
const char* const JavaMethodHelper<int32_t>::signature_;
template <>
const char* const JavaMethodHelper<uint32_t>::signature_;
template <>
const char* const JavaMethodHelper<int64_t>::signature_;
template <>
const char* const JavaMethodHelper<uint64_t>::signature_;
template <>
const char* const JavaMethodHelper<float>::signature_;
template <>
const char* const JavaMethodHelper<double>::signature_;
template <>
const char* const JavaMethodHelper<bool>::signature_;
template <>
const char* const JavaMethodHelper<jstring>::signature_;
template <>
const char* const JavaMethodHelper<jdoubleArray>::signature_;
template <class T>
void JavaMethodHelper<T>::callJavaMethod(JNIEnv* env, jclass clazz, jobject object,
const char* method_name, T value) {
jmethodID method = env->GetMethodID(clazz, method_name, signature_);
env->CallVoidMethod(object, method, value);
}
class JavaObject {
public:
JavaObject(JNIEnv* env, jclass clazz, jmethodID defaultCtor);
JavaObject(JNIEnv* env, jclass clazz, jmethodID stringCtor, const char* sz_arg_1);
JavaObject(JNIEnv* env, jclass clazz, jobject object);
virtual ~JavaObject() = default;
template <class T>
void callSetter(const char* method_name, T value);
template <class T>
void callSetter(const char* method_name, T* value, size_t size);
jobject get() { return object_; }
private:
JNIEnv* env_;
jclass clazz_;
jobject object_;
};
template <class T>
void JavaObject::callSetter(const char* method_name, T value) {
JavaMethodHelper<T>::callJavaMethod(env_, clazz_, object_, method_name, value);
}
#define SET(setter, value) object.callSetter("set" #setter, (value))
class ScopedJniThreadAttach {
public:
static JavaVM* sJvm;
ScopedJniThreadAttach() {
/*
* attachResult will also be JNI_OK if the thead was already attached to
* JNI before the call to AttachCurrentThread().
*/
jint attachResult = sJvm->AttachCurrentThread(&mEnv, nullptr);
LOG_ALWAYS_FATAL_IF(attachResult != JNI_OK, "Unable to attach thread. Error %d",
attachResult);
}
~ScopedJniThreadAttach() {
jint detachResult = sJvm->DetachCurrentThread();
/*
* Return if the thread was already detached. Log error for any other
* failure.
*/
if (detachResult == JNI_EDETACHED) {
return;
}
LOG_ALWAYS_FATAL_IF(detachResult != JNI_OK, "Unable to detach thread. Error %d",
detachResult);
}
JNIEnv* getEnv() {
/*
* Checking validity of mEnv in case the thread was detached elsewhere.
*/
LOG_ALWAYS_FATAL_IF(AndroidRuntime::getJNIEnv() != mEnv);
return mEnv;
}
private:
JNIEnv* mEnv = nullptr;
};
JNIEnv* getJniEnv();
} // namespace android
#endif // _ANDROID_SERVER_GNSS_UTILS_H