blob: d7bf201e7f3b8c07f186144ffcafade47ea93151 [file] [log] [blame]
/*
* 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.
*/
package com.android.server.uwb;
import android.annotation.NonNull;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.util.Log;
import android.uwb.AngleMeasurement;
import android.uwb.AngleOfArrivalMeasurement;
import android.uwb.DistanceMeasurement;
import android.uwb.IUwbRangingCallbacks;
import android.uwb.RangingChangeReason;
import android.uwb.RangingMeasurement;
import android.uwb.RangingReport;
import android.uwb.SessionHandle;
import android.uwb.UwbAddress;
import com.android.server.uwb.UwbSessionManager.UwbSession;
import com.android.server.uwb.data.UwbOwrAoaMeasurement;
import com.android.server.uwb.data.UwbRangingData;
import com.android.server.uwb.data.UwbTwoWayMeasurement;
import com.android.server.uwb.data.UwbUciConstants;
import com.android.server.uwb.params.TlvUtil;
import com.android.server.uwb.util.UwbUtil;
import com.google.uwb.support.base.Params;
import com.google.uwb.support.ccc.CccParams;
import com.google.uwb.support.ccc.CccRangingReconfiguredParams;
import com.google.uwb.support.fira.FiraOpenSessionParams;
import com.google.uwb.support.fira.FiraParams;
import com.google.uwb.support.oemextension.RangingReportMetadata;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class UwbSessionNotificationManager {
private static final String TAG = "UwbSessionNotiManager";
private final UwbInjector mUwbInjector;
public UwbSessionNotificationManager(@NonNull UwbInjector uwbInjector) {
mUwbInjector = uwbInjector;
}
public void onRangingResult(UwbSession uwbSession, UwbRangingData rangingData) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
boolean permissionGranted = mUwbInjector.checkUwbRangingPermissionForDataDelivery(
uwbSession.getAttributionSource(), "uwb ranging result");
if (!permissionGranted) {
Log.e(TAG, "Not delivering ranging result because of permission denial"
+ sessionHandle);
return;
}
RangingReport rangingReport = getRangingReport(rangingData, uwbSession.getProtocolName(),
uwbSession.getParams(), mUwbInjector.getElapsedSinceBootNanos());
if (mUwbInjector.getUwbServiceCore().isOemExtensionCbRegistered()) {
try {
rangingReport = mUwbInjector.getUwbServiceCore().getOemExtensionCallback()
.onRangingReportReceived(rangingReport);
} catch (RemoteException e) {
e.printStackTrace();
}
}
try {
uwbRangingCallbacks.onRangingResult(sessionHandle, rangingReport);
Log.i(TAG, "IUwbRangingCallbacks - onRangingResult");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onRangingResult : Failed");
e.printStackTrace();
}
}
public void onRangingOpened(UwbSession uwbSession) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onRangingOpened(sessionHandle);
Log.i(TAG, "IUwbRangingCallbacks - onRangingOpened");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onRangingOpened : Failed");
e.printStackTrace();
}
}
public void onRangingOpenFailed(UwbSession uwbSession, int status) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onRangingOpenFailed(sessionHandle,
UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status),
UwbSessionNotificationHelper.convertUciStatusToParam(
uwbSession.getProtocolName(), status));
Log.i(TAG, "IUwbRangingCallbacks - onRangingOpenFailed");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onRangingOpenFailed : Failed");
e.printStackTrace();
}
}
public void onRangingStarted(UwbSession uwbSession, Params rangingStartedParams) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onRangingStarted(sessionHandle, rangingStartedParams.toBundle());
Log.i(TAG, "IUwbRangingCallbacks - onRangingStarted");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onRangingStarted : Failed");
e.printStackTrace();
}
}
public void onRangingStartFailed(UwbSession uwbSession, int status) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onRangingStartFailed(sessionHandle,
UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status),
UwbSessionNotificationHelper.convertUciStatusToParam(
uwbSession.getProtocolName(), status));
Log.i(TAG, "IUwbRangingCallbacks - onRangingStartFailed");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onRangingStartFailed : Failed");
e.printStackTrace();
}
}
private void onRangingStoppedInternal(UwbSession uwbSession, int reason,
PersistableBundle params) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onRangingStopped(sessionHandle, reason, params);
Log.i(TAG, "IUwbRangingCallbacks - onRangingStopped");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onRangingStopped : Failed");
e.printStackTrace();
}
}
public void onRangingStoppedWithUciReasonCode(UwbSession uwbSession, int reasonCode) {
onRangingStoppedInternal(uwbSession,
UwbSessionNotificationHelper.convertUciReasonCodeToApiReasonCode(reasonCode),
new PersistableBundle());
}
public void onRangingStoppedWithApiReasonCode(
UwbSession uwbSession, @RangingChangeReason int reasonCode) {
onRangingStoppedInternal(uwbSession, reasonCode, new PersistableBundle());
}
public void onRangingStopped(UwbSession uwbSession, int status) {
onRangingStoppedInternal(uwbSession,
UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(
status),
UwbSessionNotificationHelper.convertUciStatusToParam(
uwbSession.getProtocolName(), status));
}
public void onRangingStopFailed(UwbSession uwbSession, int status) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onRangingStopFailed(sessionHandle,
UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(
status),
UwbSessionNotificationHelper.convertUciStatusToParam(
uwbSession.getProtocolName(), status));
Log.i(TAG, "IUwbRangingCallbacks - onRangingStopFailed");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onRangingStopFailed : Failed");
e.printStackTrace();
}
}
public void onRangingReconfigured(UwbSession uwbSession) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
PersistableBundle params;
if (Objects.equals(uwbSession.getProtocolName(), CccParams.PROTOCOL_NAME)) {
// Why are there no params defined for this bundle?
params = new CccRangingReconfiguredParams.Builder().build().toBundle();
} else {
// No params defined for FiRa reconfigure.
params = new PersistableBundle();
}
try {
uwbRangingCallbacks.onRangingReconfigured(sessionHandle, params);
Log.i(TAG, "IUwbRangingCallbacks - onRangingReconfigured");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onRangingReconfigured : Failed");
e.printStackTrace();
}
}
public void onRangingReconfigureFailed(UwbSession uwbSession, int status) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onRangingReconfigureFailed(sessionHandle,
UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(
status),
UwbSessionNotificationHelper.convertUciStatusToParam(
uwbSession.getProtocolName(), status));
Log.i(TAG, "IUwbRangingCallbacks - onRangingReconfigureFailed");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onRangingReconfigureFailed : Failed");
e.printStackTrace();
}
}
public void onControleeAdded(UwbSession uwbSession) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onControleeAdded(sessionHandle, new PersistableBundle());
Log.i(TAG, "IUwbRangingCallbacks - onControleeAdded");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onControleeAdded: Failed");
e.printStackTrace();
}
}
public void onControleeAddFailed(UwbSession uwbSession, int status) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onControleeAddFailed(sessionHandle,
UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(
status),
UwbSessionNotificationHelper.convertUciStatusToParam(
uwbSession.getProtocolName(), status));
Log.i(TAG, "IUwbRangingCallbacks - onControleeAddFailed");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onControleeAddFailed : Failed");
e.printStackTrace();
}
}
public void onControleeRemoved(UwbSession uwbSession) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onControleeRemoved(sessionHandle, new PersistableBundle());
Log.i(TAG, "IUwbRangingCallbacks - onControleeRemoved");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onControleeRemoved: Failed");
e.printStackTrace();
}
}
public void onControleeRemoveFailed(UwbSession uwbSession, int status) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onControleeRemoveFailed(sessionHandle,
UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(
status),
UwbSessionNotificationHelper.convertUciStatusToParam(
uwbSession.getProtocolName(), status));
Log.i(TAG, "IUwbRangingCallbacks - onControleeRemoveFailed");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onControleeRemoveFailed : Failed");
e.printStackTrace();
}
}
public void onRangingClosed(UwbSession uwbSession, int status) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onRangingClosed(sessionHandle,
UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(
status),
UwbSessionNotificationHelper.convertUciStatusToParam(
uwbSession.getProtocolName(), status));
Log.i(TAG, "IUwbRangingCallbacks - onRangingClosed");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onRangingClosed : Failed");
e.printStackTrace();
}
}
public void onRangingClosedWithApiReasonCode(
UwbSession uwbSession, @RangingChangeReason int reasonCode) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onRangingClosed(sessionHandle, reasonCode, new PersistableBundle());
Log.i(TAG, "IUwbRangingCallbacks - onRangingClosed");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onRangingClosed : Failed");
e.printStackTrace();
}
}
/** Notify about payload data received during the UWB ranging session. */
public void onDataReceived(
UwbSession uwbSession, UwbAddress remoteDeviceAddress,
PersistableBundle parameters, byte[] data) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onDataReceived(
sessionHandle, remoteDeviceAddress, parameters, data);
Log.i(TAG, "IUwbRangingCallbacks - onDataReceived");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onDataReceived : Failed");
e.printStackTrace();
}
}
/** Notify about failure in receiving payload data during the UWB ranging session. */
public void onDataReceiveFailed(
UwbSession uwbSession, UwbAddress remoteDeviceAddress,
int reason, PersistableBundle parameters) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onDataReceiveFailed(
sessionHandle, remoteDeviceAddress, reason, parameters);
Log.i(TAG, "IUwbRangingCallbacks - onDataReceiveFailed");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onDataReceiveFailed : Failed");
e.printStackTrace();
}
}
/** Notify about payload data sent during the UWB ranging session. */
public void onDataSent(
UwbSession uwbSession, UwbAddress remoteDeviceAddress, PersistableBundle parameters) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onDataSent(
sessionHandle, remoteDeviceAddress, parameters);
Log.i(TAG, "IUwbRangingCallbacks - onDataSent");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onDataSent : Failed");
e.printStackTrace();
}
}
/** Notify about failure in sending payload data during the UWB ranging session. */
public void onDataSendFailed(
UwbSession uwbSession, UwbAddress remoteDeviceAddress,
int reason, PersistableBundle parameters) {
SessionHandle sessionHandle = uwbSession.getSessionHandle();
IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks();
try {
uwbRangingCallbacks.onDataSendFailed(
sessionHandle, remoteDeviceAddress, reason, parameters);
Log.i(TAG, "IUwbRangingCallbacks - onDataSendFailed");
} catch (Exception e) {
Log.e(TAG, "IUwbRangingCallbacks - onDataSendFailed : Failed");
e.printStackTrace();
}
}
private static RangingReport getRangingReport(
@NonNull UwbRangingData rangingData, String protocolName,
Params sessionParams, long elapsedRealtimeNanos) {
if (rangingData.getRangingMeasuresType() != UwbUciConstants.RANGING_MEASUREMENT_TYPE_TWO_WAY
&& rangingData.getRangingMeasuresType()
!= UwbUciConstants.RANGING_MEASUREMENT_TYPE_OWR_AOA) {
return null;
}
boolean isAoaAzimuthEnabled = true;
boolean isAoaElevationEnabled = true;
boolean isDestAoaAzimuthEnabled = false;
boolean isDestAoaElevationEnabled = false;
long sessionId = 0;
// For FIRA sessions, check if AOA is enabled for the session or not.
if (protocolName.equals(FiraParams.PROTOCOL_NAME)) {
FiraOpenSessionParams openSessionParams = (FiraOpenSessionParams) sessionParams;
sessionId = openSessionParams.getSessionId();
switch (openSessionParams.getAoaResultRequest()) {
case FiraParams.AOA_RESULT_REQUEST_MODE_NO_AOA_REPORT:
isAoaAzimuthEnabled = false;
isAoaElevationEnabled = false;
break;
case FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS:
case FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_INTERLEAVED:
isAoaAzimuthEnabled = true;
isAoaElevationEnabled = true;
break;
case FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_AZIMUTH_ONLY:
isAoaAzimuthEnabled = true;
isAoaElevationEnabled = false;
break;
case FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_ELEVATION_ONLY:
isAoaAzimuthEnabled = false;
isAoaElevationEnabled = true;
break;
default:
throw new IllegalArgumentException("Invalid AOA result req");
}
if (openSessionParams.hasResultReportPhase()) {
if (openSessionParams.hasAngleOfArrivalAzimuthReport()) {
isDestAoaAzimuthEnabled = true;
}
if (openSessionParams.hasAngleOfArrivalElevationReport()) {
isDestAoaElevationEnabled = true;
}
}
}
// TODO(b/256734264): The unit tests are currently not checking for this field, as
// RangingReport.equals() does not compare it.
PersistableBundle rangingReportMetadata = new RangingReportMetadata.Builder()
.setSessionId(sessionId)
.setRawNtfData(rangingData.getRawNtfData())
.build()
.toBundle();
RangingReport.Builder rangingReportBuilder = new RangingReport.Builder()
.addRangingReportMetadata(rangingReportMetadata);
if (rangingData.getRangingMeasuresType()
== UwbUciConstants.RANGING_MEASUREMENT_TYPE_TWO_WAY) {
List<RangingMeasurement> rangingMeasurements = new ArrayList<>();
UwbTwoWayMeasurement[] uwbTwoWayMeasurement = rangingData.getRangingTwoWayMeasures();
for (int i = 0; i < rangingData.getNoOfRangingMeasures(); ++i) {
int rangingStatus = uwbTwoWayMeasurement[i].getRangingStatus();
RangingMeasurement.Builder rangingMeasurementBuilder = buildRangingMeasurement(
uwbTwoWayMeasurement[i].getMacAddress(), rangingStatus,
elapsedRealtimeNanos, uwbTwoWayMeasurement[i].getNLoS());
int rssi = uwbTwoWayMeasurement[i].getRssi();
if (rssi < 0) {
rangingMeasurementBuilder.setRssiDbm(rssi);
}
if (rangingStatus == FiraParams.STATUS_CODE_OK) {
// Distance measurement is mandatory
rangingMeasurementBuilder.setDistanceMeasurement(
buildDistanceMeasurement(uwbTwoWayMeasurement[i].getDistance()));
// Aoa measurement is optional based on configuration.
AngleOfArrivalMeasurement angleOfArrivalMeasurement =
computeAngleOfArrivalMeasurement(
isAoaAzimuthEnabled, isAoaElevationEnabled,
uwbTwoWayMeasurement[i].getAoaAzimuth(),
uwbTwoWayMeasurement[i].getAoaAzimuthFom(),
uwbTwoWayMeasurement[i].getAoaElevation(),
uwbTwoWayMeasurement[i].getAoaElevationFom());
if (angleOfArrivalMeasurement != null) {
rangingMeasurementBuilder.setAngleOfArrivalMeasurement(
angleOfArrivalMeasurement);
}
// Dest AngleOfArrivalMeasurement
AngleOfArrivalMeasurement destinationAngleOfArrivalMeasurement =
computeAngleOfArrivalMeasurement(
isDestAoaAzimuthEnabled, isDestAoaElevationEnabled,
uwbTwoWayMeasurement[i].getAoaDestAzimuth(),
uwbTwoWayMeasurement[i].getAoaDestAzimuthFom(),
uwbTwoWayMeasurement[i].getAoaDestElevation(),
uwbTwoWayMeasurement[i].getAoaDestElevationFom());
if (destinationAngleOfArrivalMeasurement != null) {
rangingMeasurementBuilder.setDestinationAngleOfArrivalMeasurement(
destinationAngleOfArrivalMeasurement);
}
}
// TODO: No ranging measurement metadata defined, added for future usage
PersistableBundle rangingMeasurementMetadata = new PersistableBundle();
rangingMeasurementBuilder.setRangingMeasurementMetadata(rangingMeasurementMetadata);
rangingMeasurements.add(rangingMeasurementBuilder.build());
}
rangingReportBuilder.addMeasurements(rangingMeasurements);
} else if (rangingData.getRangingMeasuresType()
== UwbUciConstants.RANGING_MEASUREMENT_TYPE_OWR_AOA) {
UwbOwrAoaMeasurement uwbOwrAoaMeasurement = rangingData.getRangingOwrAoaMeasure();
int rangingStatus = uwbOwrAoaMeasurement.getRangingStatus();
RangingMeasurement.Builder rangingMeasurementBuilder = buildRangingMeasurement(
uwbOwrAoaMeasurement.getMacAddress(), rangingStatus, elapsedRealtimeNanos,
uwbOwrAoaMeasurement.getNLoS());
if (rangingStatus == FiraParams.STATUS_CODE_OK) {
// AngleOfArrivalMeasurement
AngleOfArrivalMeasurement angleOfArrivalMeasurement =
computeAngleOfArrivalMeasurement(
isAoaAzimuthEnabled, isAoaElevationEnabled,
uwbOwrAoaMeasurement.getAoaAzimuth(),
uwbOwrAoaMeasurement.getAoaAzimuthFom(),
uwbOwrAoaMeasurement.getAoaElevation(),
uwbOwrAoaMeasurement.getAoaElevationFom());
if (angleOfArrivalMeasurement != null) {
rangingMeasurementBuilder.setAngleOfArrivalMeasurement(
angleOfArrivalMeasurement);
}
}
rangingReportBuilder.addMeasurement(rangingMeasurementBuilder.build());
}
return rangingReportBuilder.build();
}
private static AngleOfArrivalMeasurement computeAngleOfArrivalMeasurement(
boolean isAoaAzimuthEnabled, boolean isAoaElevationEnabled, float aoaAzimuth,
int aoaAzimuthFom, float aoaElevation, int aoaElevationFom) {
// Azimuth is required field (and elevation is an optional field), to build the
// AngleOfArrivalMeasurement.
if (isAoaAzimuthEnabled) {
AngleMeasurement azimuthAngleMeasurement = new AngleMeasurement(
UwbUtil.degreeToRadian(aoaAzimuth), 0, aoaAzimuthFom / (double) 100);
// AngleOfArrivalMeasurement
AngleOfArrivalMeasurement.Builder angleOfArrivalMeasurementBuilder =
new AngleOfArrivalMeasurement.Builder(azimuthAngleMeasurement);
// Elevation is optional field, to build the AngleOfArrivalMeasurement.
if (isAoaElevationEnabled) {
AngleMeasurement altitudeAngleMeasurement = new AngleMeasurement(
UwbUtil.degreeToRadian(aoaElevation), 0, aoaElevationFom / (double) 100);
angleOfArrivalMeasurementBuilder.setAltitude(altitudeAngleMeasurement);
}
return angleOfArrivalMeasurementBuilder.build();
}
return null;
}
private static RangingMeasurement.Builder buildRangingMeasurement(
byte[] macAddress, int rangingStatus, long elapsedRealtimeNanos, int los) {
return new RangingMeasurement.Builder()
.setRemoteDeviceAddress(UwbAddress.fromBytes(TlvUtil.getReverseBytes(macAddress)))
.setStatus(rangingStatus)
.setElapsedRealtimeNanos(elapsedRealtimeNanos)
.setLineOfSight(los);
}
private static DistanceMeasurement buildDistanceMeasurement(int distance) {
return new DistanceMeasurement.Builder()
.setMeters(distance / (double) 100)
.setErrorMeters(0)
// TODO: Need to fetch distance FOM once it is added to UCI spec.
.setConfidenceLevel(0)
.build();
}
}