465 lines
17 KiB
C++
Executable File
465 lines
17 KiB
C++
Executable File
/*
|
|
* Copyright (C) 2021 The Android Open Source Project
|
|
*
|
|
* Copyright 2021 NXP.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include "UwbJniInternal.h"
|
|
#include "UwbEventManager.h"
|
|
#include "JniLog.h"
|
|
#include "ScopedJniEnv.h"
|
|
#include "SyncEvent.h"
|
|
#include "UwbAdaptation.h"
|
|
#include "uwb_config.h"
|
|
#include "uwb_hal_int.h"
|
|
|
|
namespace android {
|
|
|
|
const char *RANGING_DATA_CLASS_NAME = "com/android/server/uwb/data/UwbRangingData";
|
|
const char *RANGING_MEASURES_CLASS_NAME =
|
|
"com/android/server/uwb/data/UwbTwoWayMeasurement";
|
|
/* ranging tdoa measures and multicast list update ntf events are implemented as
|
|
per Fira specification.
|
|
TODO support for these class to be added in service.*/
|
|
const char *MULTICAST_UPDATE_LIST_DATA_CLASS_NAME =
|
|
"com/android/server/uwb/data/UwbMulticastListUpdateStatus";
|
|
|
|
UwbEventManager UwbEventManager::mObjUwbManager;
|
|
|
|
UwbEventManager &UwbEventManager::getInstance() { return mObjUwbManager; }
|
|
|
|
UwbEventManager::UwbEventManager() {
|
|
mVm = NULL;
|
|
mClass = NULL;
|
|
mObject = NULL;
|
|
mRangeDataClass = NULL;
|
|
mRangingTwoWayMeasuresClass = NULL;
|
|
mRangeTdoaMeasuresClass = NULL;
|
|
mMulticastUpdateListDataClass = NULL;
|
|
mOnDeviceStateNotificationReceived = NULL;
|
|
mOnRangeDataNotificationReceived = NULL;
|
|
mOnSessionStatusNotificationReceived = NULL;
|
|
mOnCoreGenericErrorNotificationReceived = NULL;
|
|
mOnMulticastListUpdateNotificationReceived = NULL;
|
|
mOnBlinkDataTxNotificationReceived = NULL;
|
|
mOnRawUciNotificationReceived = NULL;
|
|
mOnVendorUciNotificationReceived = NULL;
|
|
mOnVendorDeviceInfo = NULL;
|
|
}
|
|
|
|
void UwbEventManager::onRangeDataNotificationReceived(
|
|
tUWA_RANGE_DATA_NTF *ranging_ntf_data) {
|
|
static const char fn[] = "onRangeDataNotificationReceived";
|
|
UNUSED(fn);
|
|
|
|
ScopedJniEnv env(mVm);
|
|
if (env == NULL) {
|
|
JNI_TRACE_E("%s: jni env is null", fn);
|
|
return;
|
|
}
|
|
|
|
jobject rangeDataObject;
|
|
|
|
if (ranging_ntf_data->ranging_measure_type == MEASUREMENT_TYPE_TWOWAY) {
|
|
JNI_TRACE_I("%s: ranging_measure_type = MEASUREMENT_TYPE_TWOWAY", fn);
|
|
jmethodID rngMeasuresCtor;
|
|
jmethodID rngDataCtorTwm;
|
|
jobjectArray rangeMeasuresArray;
|
|
rangeMeasuresArray =
|
|
env->NewObjectArray(ranging_ntf_data->no_of_measurements,
|
|
mRangingTwoWayMeasuresClass, NULL);
|
|
|
|
/* Copy the data from structure to Java Object */
|
|
for (int i = 0; i < ranging_ntf_data->no_of_measurements; i++) {
|
|
jbyteArray macAddress;
|
|
jbyteArray rfu;
|
|
|
|
if (ranging_ntf_data->mac_addr_mode_indicator == SHORT_MAC_ADDRESS) {
|
|
macAddress = env->NewByteArray(2);
|
|
env->SetByteArrayRegion(
|
|
macAddress, 0, 2,
|
|
(jbyte *)ranging_ntf_data->ranging_measures.twr_range_measr[i]
|
|
.mac_addr);
|
|
rfu = env->NewByteArray(12);
|
|
env->SetByteArrayRegion(
|
|
rfu, 0, 12,
|
|
(jbyte *)ranging_ntf_data->ranging_measures.twr_range_measr[i].rfu);
|
|
} else {
|
|
macAddress = env->NewByteArray(8);
|
|
env->SetByteArrayRegion(
|
|
macAddress, 0, 8,
|
|
(jbyte *)ranging_ntf_data->ranging_measures.twr_range_measr[i]
|
|
.mac_addr);
|
|
rfu = env->NewByteArray(6);
|
|
env->SetByteArrayRegion(
|
|
rfu, 0, 6,
|
|
(jbyte *)ranging_ntf_data->ranging_measures.twr_range_measr[i].rfu);
|
|
}
|
|
rngMeasuresCtor = env->GetMethodID(mRangingTwoWayMeasuresClass, "<init>",
|
|
"([BIIIIIIIIIIII)V");
|
|
|
|
env->SetObjectArrayElement(
|
|
rangeMeasuresArray, i,
|
|
env->NewObject(
|
|
mRangingTwoWayMeasuresClass, rngMeasuresCtor, macAddress,
|
|
(int)ranging_ntf_data->ranging_measures.twr_range_measr[i].status,
|
|
(int)ranging_ntf_data->ranging_measures.twr_range_measr[i].nLos,
|
|
(int)ranging_ntf_data->ranging_measures.twr_range_measr[i]
|
|
.distance,
|
|
(int)ranging_ntf_data->ranging_measures.twr_range_measr[i]
|
|
.aoa_azimuth,
|
|
(int)ranging_ntf_data->ranging_measures.twr_range_measr[i]
|
|
.aoa_azimuth_FOM,
|
|
(int)ranging_ntf_data->ranging_measures.twr_range_measr[i]
|
|
.aoa_elevation,
|
|
(int)ranging_ntf_data->ranging_measures.twr_range_measr[i]
|
|
.aoa_elevation_FOM,
|
|
(int)ranging_ntf_data->ranging_measures.twr_range_measr[i]
|
|
.aoa_dest_azimuth,
|
|
(int)ranging_ntf_data->ranging_measures.twr_range_measr[i]
|
|
.aoa_dest_azimuth_FOM,
|
|
(int)ranging_ntf_data->ranging_measures.twr_range_measr[i]
|
|
.aoa_dest_elevation,
|
|
(int)ranging_ntf_data->ranging_measures.twr_range_measr[i]
|
|
.aoa_dest_elevation_FOM,
|
|
(int)ranging_ntf_data->ranging_measures.twr_range_measr[i]
|
|
.slot_index,
|
|
rfu));
|
|
}
|
|
|
|
rngDataCtorTwm = env->GetMethodID(
|
|
mRangeDataClass, "<init>",
|
|
"(JJIJIII[Lcom/android/server/uwb/data/UwbTwoWayMeasurement;)V");
|
|
rangeDataObject = env->NewObject(
|
|
mRangeDataClass, rngDataCtorTwm, (long)ranging_ntf_data->seq_counter,
|
|
(long)ranging_ntf_data->session_id,
|
|
(int)ranging_ntf_data->rcr_indication,
|
|
(long)ranging_ntf_data->curr_range_interval,
|
|
ranging_ntf_data->ranging_measure_type,
|
|
ranging_ntf_data->mac_addr_mode_indicator,
|
|
(int)ranging_ntf_data->no_of_measurements, rangeMeasuresArray);
|
|
}
|
|
|
|
if (mOnRangeDataNotificationReceived != NULL) {
|
|
env->CallVoidMethod(mObject, mOnRangeDataNotificationReceived,
|
|
rangeDataObject);
|
|
if (env->ExceptionCheck()) {
|
|
env->ExceptionDescribe();
|
|
env->ExceptionClear();
|
|
JNI_TRACE_E("%s: fail to send range data", fn);
|
|
}
|
|
} else {
|
|
JNI_TRACE_E("%s: rangeDataNtf MID is NULL", fn);
|
|
}
|
|
JNI_TRACE_I("%s: exit", fn);
|
|
}
|
|
|
|
void UwbEventManager::onRawUciNotificationReceived(uint8_t *data,
|
|
uint16_t length) {
|
|
JNI_TRACE_I("%s: Enter", __func__);
|
|
|
|
ScopedJniEnv env(mVm);
|
|
if (env == NULL) {
|
|
JNI_TRACE_E("%s: jni env is null", __func__);
|
|
return;
|
|
}
|
|
|
|
if (length == 0 || data == NULL) {
|
|
JNI_TRACE_E(
|
|
"%s: length is zero or data is NULL, skip sending notifications",
|
|
__func__);
|
|
return;
|
|
}
|
|
|
|
jbyteArray dataArray = env->NewByteArray(length);
|
|
env->SetByteArrayRegion(dataArray, 0, length, (jbyte *)data);
|
|
|
|
if (mOnRawUciNotificationReceived != NULL) {
|
|
env->CallVoidMethod(mObject, mOnRawUciNotificationReceived, dataArray);
|
|
if (env->ExceptionCheck()) {
|
|
env->ExceptionClear();
|
|
JNI_TRACE_E("%s: fail to send notification", __func__);
|
|
}
|
|
} else {
|
|
JNI_TRACE_E("%s: onRawUciNotificationReceived MID is NULL", __func__);
|
|
}
|
|
JNI_TRACE_I("%s: exit", __func__);
|
|
}
|
|
|
|
void UwbEventManager::onSessionStatusNotificationReceived(uint32_t sessionId,
|
|
uint8_t state,
|
|
uint8_t reasonCode) {
|
|
static const char fn[] = "notifySessionStateNotification";
|
|
UNUSED(fn);
|
|
JNI_TRACE_I("%s: enter; session ID=%x, State = %x reasonCode = %x", fn,
|
|
sessionId, state, reasonCode);
|
|
|
|
ScopedJniEnv env(mVm);
|
|
if (env == NULL) {
|
|
JNI_TRACE_E("%s: jni env is null", fn);
|
|
return;
|
|
}
|
|
|
|
if (mOnSessionStatusNotificationReceived != NULL) {
|
|
env->CallVoidMethod(mObject, mOnSessionStatusNotificationReceived,
|
|
(long)sessionId, (int)state, (int)reasonCode);
|
|
if (env->ExceptionCheck()) {
|
|
env->ExceptionClear();
|
|
JNI_TRACE_E("%s: fail to notify", fn);
|
|
}
|
|
} else {
|
|
JNI_TRACE_E("%s: sessionStatusNtf MID is null ", fn);
|
|
}
|
|
JNI_TRACE_I("%s: exit", fn);
|
|
}
|
|
|
|
void UwbEventManager::onDeviceStateNotificationReceived(uint8_t state) {
|
|
static const char fn[] = "notifyDeviceStateNotification";
|
|
UNUSED(fn);
|
|
JNI_TRACE_I("%s: enter: State = %x", fn, state);
|
|
|
|
ScopedJniEnv env(mVm);
|
|
if (env == NULL) {
|
|
JNI_TRACE_E("%s: jni env is null", fn);
|
|
return;
|
|
}
|
|
|
|
if (mOnDeviceStateNotificationReceived != NULL) {
|
|
env->CallVoidMethod(mObject, mOnDeviceStateNotificationReceived,
|
|
(int)state);
|
|
if (env->ExceptionCheck()) {
|
|
env->ExceptionClear();
|
|
JNI_TRACE_E("%s: fail to notify", fn);
|
|
}
|
|
} else {
|
|
JNI_TRACE_E("%s: deviceStatusNtf MID is null ", fn);
|
|
}
|
|
JNI_TRACE_I("%s: exit", fn);
|
|
}
|
|
|
|
void UwbEventManager::onCoreGenericErrorNotificationReceived(uint8_t state) {
|
|
static const char fn[] = "notifyCoreGenericErrorNotification";
|
|
UNUSED(fn);
|
|
JNI_TRACE_I("%s: enter: State = %x", fn, state);
|
|
|
|
ScopedJniEnv env(mVm);
|
|
if (env == NULL) {
|
|
JNI_TRACE_E("%s: jni env is null", fn);
|
|
return;
|
|
}
|
|
|
|
if (mOnCoreGenericErrorNotificationReceived != NULL) {
|
|
env->CallVoidMethod(mObject, mOnCoreGenericErrorNotificationReceived,
|
|
(int)state);
|
|
if (env->ExceptionCheck()) {
|
|
env->ExceptionClear();
|
|
JNI_TRACE_E("%s: fail to notify", fn);
|
|
}
|
|
} else {
|
|
JNI_TRACE_E("%s: genericErrorStatusNtf MID is null ", fn);
|
|
}
|
|
|
|
JNI_TRACE_I("%s: exit", fn);
|
|
}
|
|
|
|
void UwbEventManager::onMulticastListUpdateNotificationReceived(
|
|
tUWA_SESSION_UPDATE_MULTICAST_LIST_NTF *multicast_list_ntf) {
|
|
static const char fn[] = "onMulticastListUpdateNotificationReceived";
|
|
UNUSED(fn);
|
|
JNI_TRACE_I("%s: enter;", fn);
|
|
|
|
ScopedJniEnv env(mVm);
|
|
if (env == NULL) {
|
|
JNI_TRACE_E("%s: jni env is null", fn);
|
|
return;
|
|
}
|
|
|
|
if (multicast_list_ntf == NULL) {
|
|
JNI_TRACE_E("%s: multicast_list_ntf is null", fn);
|
|
return;
|
|
}
|
|
|
|
if (multicast_list_ntf->no_of_controlees > MAX_NUM_CONTROLLEES) {
|
|
JNI_TRACE_E("%s: no Of Controlees %d exceeded max allowed: %d ", fn,
|
|
multicast_list_ntf->no_of_controlees, MAX_NUM_CONTROLLEES);
|
|
return;
|
|
}
|
|
|
|
jintArray controleeMacAddressArray =
|
|
env->NewIntArray(multicast_list_ntf->no_of_controlees);
|
|
jlongArray subSessionIdArray =
|
|
env->NewLongArray(multicast_list_ntf->no_of_controlees);
|
|
jintArray statusArray =
|
|
env->NewIntArray(multicast_list_ntf->no_of_controlees);
|
|
|
|
if (multicast_list_ntf->no_of_controlees > 0) {
|
|
uint32_t controleeMacAddressList[multicast_list_ntf->no_of_controlees];
|
|
uint32_t statusList[multicast_list_ntf->no_of_controlees];
|
|
uint64_t subSessionIdList[multicast_list_ntf->no_of_controlees];
|
|
for (int i = 0; i < multicast_list_ntf->no_of_controlees; i++) {
|
|
controleeMacAddressList[i] =
|
|
multicast_list_ntf->controlee_mac_address_list[i];
|
|
statusList[i] = multicast_list_ntf->status_list[i];
|
|
}
|
|
for (int i = 0; i < multicast_list_ntf->no_of_controlees; i++) {
|
|
subSessionIdList[i] = multicast_list_ntf->subsession_id_list[i];
|
|
}
|
|
env->SetIntArrayRegion(controleeMacAddressArray, 0,
|
|
multicast_list_ntf->no_of_controlees,
|
|
(jint *)controleeMacAddressList);
|
|
env->SetLongArrayRegion(subSessionIdArray, 0,
|
|
multicast_list_ntf->no_of_controlees,
|
|
(jlong *)subSessionIdList);
|
|
env->SetIntArrayRegion(statusArray, 0, multicast_list_ntf->no_of_controlees,
|
|
(jint *)statusList);
|
|
}
|
|
jmethodID multicastUpdateListDataCtor =
|
|
env->GetMethodID(mMulticastUpdateListDataClass, "<init>", "(JII[I[J[I)V");
|
|
jobject multicastUpdateListDataObject =
|
|
env->NewObject(mMulticastUpdateListDataClass, multicastUpdateListDataCtor,
|
|
(long)multicast_list_ntf->session_id,
|
|
(int)multicast_list_ntf->remaining_list,
|
|
(int)multicast_list_ntf->no_of_controlees,
|
|
controleeMacAddressArray, subSessionIdArray, statusArray);
|
|
|
|
if (mOnMulticastListUpdateNotificationReceived != NULL) {
|
|
env->CallVoidMethod(mObject, mOnMulticastListUpdateNotificationReceived,
|
|
multicastUpdateListDataObject);
|
|
if (env->ExceptionCheck()) {
|
|
env->ExceptionClear();
|
|
JNI_TRACE_E("%s: fail to send Multicast update list ntf", fn);
|
|
}
|
|
} else {
|
|
JNI_TRACE_E("%s: MulticastUpdateListNtf MID is null ", fn);
|
|
}
|
|
JNI_TRACE_I("%s: exit", fn);
|
|
}
|
|
|
|
void UwbEventManager::onBlinkDataTxNotificationReceived(uint8_t status) {
|
|
static const char fn[] = "onBlinkDataTxNotificationReceived";
|
|
UNUSED(fn);
|
|
JNI_TRACE_I("%s: enter: State = %x", fn, status);
|
|
|
|
ScopedJniEnv env(mVm);
|
|
if (env == NULL) {
|
|
JNI_TRACE_E("%s: jni env is null", fn);
|
|
return;
|
|
}
|
|
|
|
if (mOnBlinkDataTxNotificationReceived != NULL) {
|
|
env->CallVoidMethod(mObject, mOnBlinkDataTxNotificationReceived,
|
|
(int)status);
|
|
if (env->ExceptionCheck()) {
|
|
env->ExceptionClear();
|
|
JNI_TRACE_E("%s: fail to notify", fn);
|
|
}
|
|
} else {
|
|
JNI_TRACE_E("%s: BlikDataTxNtf MID is null ", fn);
|
|
}
|
|
JNI_TRACE_I("%s: exit", fn);
|
|
}
|
|
|
|
void UwbEventManager::onVendorUciNotificationReceived(uint8_t gid, uint8_t oid, uint8_t* data, uint16_t length) {
|
|
static const char fn[] = "onVendorUciNotificationReceived";
|
|
UNUSED(fn);
|
|
|
|
ScopedJniEnv env(mVm);
|
|
if (env == NULL) {
|
|
JNI_TRACE_E("%s: jni env is null", fn);
|
|
return;
|
|
}
|
|
|
|
jbyteArray dataArray = env->NewByteArray(length);
|
|
env->SetByteArrayRegion(dataArray, 0, length, (jbyte*)data);
|
|
|
|
if (mOnVendorUciNotificationReceived != NULL) {
|
|
env->CallVoidMethod(mObject, mOnVendorUciNotificationReceived, (int)gid, (int)oid, dataArray);
|
|
if (env->ExceptionCheck()) {
|
|
env->ExceptionClear();
|
|
JNI_TRACE_E("%s: fail to send notification", __func__);
|
|
}
|
|
} else {
|
|
JNI_TRACE_E("%s: onVendorUciNotificationReceived MID is NULL", __func__);
|
|
}
|
|
JNI_TRACE_I("%s: exit", __func__);
|
|
}
|
|
|
|
void UwbEventManager::onVendorDeviceInfo(uint8_t* data, uint8_t length) {
|
|
static const char fn[] = "onVendorDeviceInfo";
|
|
UNUSED(fn);
|
|
if((length <= 0) || (data == NULL)) {
|
|
JNI_TRACE_E("%s: data len is Zero or vendorDevice info is NULL", fn);
|
|
return;
|
|
}
|
|
|
|
ScopedJniEnv env(mVm);
|
|
|
|
jbyteArray dataArray = env->NewByteArray(length);
|
|
env->SetByteArrayRegion(dataArray, 0, length, (jbyte*)data);
|
|
if (mOnVendorDeviceInfo != NULL) {
|
|
env->CallVoidMethod(mObject, mOnVendorDeviceInfo, dataArray);
|
|
if (env->ExceptionCheck()) {
|
|
env->ExceptionClear();
|
|
JNI_TRACE_E("%s: fail to vendor info", __func__);
|
|
}
|
|
} else {
|
|
JNI_TRACE_E("%s: onVendorDeviceInfo MID is NULL", __func__);
|
|
}
|
|
JNI_TRACE_I("%s: exit", __func__);
|
|
}
|
|
|
|
void UwbEventManager::doLoadSymbols(JNIEnv *env, jobject thiz) {
|
|
static const char fn[] = "UwbEventManager::doLoadSymbols";
|
|
UNUSED(fn);
|
|
JNI_TRACE_I("%s: enter", fn);
|
|
env->GetJavaVM(&mVm);
|
|
|
|
jclass clazz = env->GetObjectClass(thiz);
|
|
if (clazz != NULL) {
|
|
mClass = (jclass)env->NewGlobalRef(clazz);
|
|
// The reference is only used as a proxy for callbacks.
|
|
mObject = env->NewGlobalRef(thiz);
|
|
|
|
mOnDeviceStateNotificationReceived =
|
|
env->GetMethodID(clazz, "onDeviceStatusNotificationReceived", "(I)V");
|
|
mOnRangeDataNotificationReceived =
|
|
env->GetMethodID(clazz, "onRangeDataNotificationReceived",
|
|
"(Lcom/android/server/uwb/data/UwbRangingData;)V");
|
|
mOnSessionStatusNotificationReceived = env->GetMethodID(
|
|
clazz, "onSessionStatusNotificationReceived", "(JII)V");
|
|
mOnCoreGenericErrorNotificationReceived = env->GetMethodID(
|
|
clazz, "onCoreGenericErrorNotificationReceived", "(I)V");
|
|
|
|
// TDB, this should be reworked
|
|
mOnMulticastListUpdateNotificationReceived = env->GetMethodID(
|
|
clazz, "onMulticastListUpdateNotificationReceived",
|
|
"(Lcom/android/server/uwb/data/UwbMulticastListUpdateStatus;)V");
|
|
mOnRawUciNotificationReceived = env->GetMethodID(clazz,
|
|
"onRawUciNotificationReceived", "([B)V");
|
|
mOnVendorUciNotificationReceived = env->GetMethodID(clazz,
|
|
"onVendorUciNotificationReceived", "(II[B)V");
|
|
mOnVendorDeviceInfo = env->GetMethodID(clazz,
|
|
"onVendorDeviceInfo", "([B)V");
|
|
|
|
uwb_jni_cache_jclass(env, RANGING_DATA_CLASS_NAME, &mRangeDataClass);
|
|
uwb_jni_cache_jclass(env, RANGING_MEASURES_CLASS_NAME,
|
|
&mRangingTwoWayMeasuresClass);
|
|
uwb_jni_cache_jclass(env, MULTICAST_UPDATE_LIST_DATA_CLASS_NAME,
|
|
&mMulticastUpdateListDataClass);
|
|
}
|
|
JNI_TRACE_I("%s: exit", fn);
|
|
}
|
|
} // namespace android
|