1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.server.uwb; 17 18 import android.annotation.NonNull; 19 import android.os.PersistableBundle; 20 import android.os.RemoteException; 21 import android.util.Log; 22 import android.uwb.AngleMeasurement; 23 import android.uwb.AngleOfArrivalMeasurement; 24 import android.uwb.DistanceMeasurement; 25 import android.uwb.IUwbRangingCallbacks; 26 import android.uwb.RangingChangeReason; 27 import android.uwb.RangingMeasurement; 28 import android.uwb.RangingReport; 29 import android.uwb.SessionHandle; 30 import android.uwb.UwbAddress; 31 32 import com.android.modules.utils.build.SdkLevel; 33 import com.android.server.uwb.UwbSessionManager.UwbSession; 34 import com.android.server.uwb.data.UwbDlTDoAMeasurement; 35 import com.android.server.uwb.data.UwbOwrAoaMeasurement; 36 import com.android.server.uwb.data.UwbRadarData; 37 import com.android.server.uwb.data.UwbRadarSweepData; 38 import com.android.server.uwb.data.UwbRangingData; 39 import com.android.server.uwb.data.UwbTwoWayMeasurement; 40 import com.android.server.uwb.data.UwbUciConstants; 41 import com.android.server.uwb.params.TlvUtil; 42 import com.android.server.uwb.util.UwbUtil; 43 44 import com.google.uwb.support.aliro.AliroParams; 45 import com.google.uwb.support.aliro.AliroRangingReconfiguredParams; 46 import com.google.uwb.support.base.Params; 47 import com.google.uwb.support.ccc.CccParams; 48 import com.google.uwb.support.ccc.CccRangingReconfiguredParams; 49 import com.google.uwb.support.dltdoa.DlTDoAMeasurement; 50 import com.google.uwb.support.fira.FiraDataTransferPhaseConfigStatusCode; 51 import com.google.uwb.support.fira.FiraOnControleeRemovedParams; 52 import com.google.uwb.support.fira.FiraOpenSessionParams; 53 import com.google.uwb.support.fira.FiraParams; 54 import com.google.uwb.support.oemextension.RangingReportMetadata; 55 import com.google.uwb.support.radar.RadarData; 56 import com.google.uwb.support.radar.RadarParams; 57 import com.google.uwb.support.radar.RadarSweepData; 58 59 import java.util.ArrayList; 60 import java.util.List; 61 import java.util.Objects; 62 63 public class UwbSessionNotificationManager { 64 private static final String TAG = "UwbSessionNotiManager"; 65 private final UwbInjector mUwbInjector; 66 UwbSessionNotificationManager(@onNull UwbInjector uwbInjector)67 public UwbSessionNotificationManager(@NonNull UwbInjector uwbInjector) { 68 mUwbInjector = uwbInjector; 69 } 70 onRangingResult(UwbSession uwbSession, UwbRangingData rangingData)71 public void onRangingResult(UwbSession uwbSession, UwbRangingData rangingData) { 72 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 73 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 74 if (uwbSession.isDataDeliveryPermissionCheckNeeded()) { 75 boolean permissionGranted = mUwbInjector.checkUwbRangingPermissionForStartDataDelivery( 76 uwbSession.getAttributionSource(), "uwb ranging result"); 77 if (!permissionGranted) { 78 Log.e(TAG, "Not delivering ranging result because of permission denial" 79 + sessionHandle); 80 return; 81 } 82 uwbSession.setDataDeliveryPermissionCheckNeeded(false); 83 } 84 RangingReport rangingReport = null; 85 try { 86 rangingReport = getRangingReport(rangingData, uwbSession.getProtocolName(), 87 uwbSession.getParams(), mUwbInjector.getElapsedSinceBootNanos(), uwbSession); 88 } catch (IllegalArgumentException e) { 89 Log.e(TAG, "getRangingReport Failed."); 90 e.printStackTrace(); 91 } 92 if (rangingReport == null) { 93 Log.e(TAG, "Generated ranging report is null"); 94 return; 95 } 96 97 try { 98 RangingMeasurement filteredRangingMeasurement = rangingReport.getMeasurements().get(0); 99 mUwbInjector.getUwbMetrics().logRangingResult(uwbSession.getProfileType(), rangingData, 100 filteredRangingMeasurement); 101 } catch (Exception e) { 102 Log.e(TAG, "logRangingResult Failed."); 103 e.printStackTrace(); 104 } 105 106 if (mUwbInjector.getUwbServiceCore().isOemExtensionCbRegistered()) { 107 try { 108 rangingReport = mUwbInjector.getUwbServiceCore().getOemExtensionCallback() 109 .onRangingReportReceived(rangingReport); 110 } catch (RemoteException e) { 111 Log.e(TAG, "UwbInjector - onRangingReportReceived : Failed."); 112 e.printStackTrace(); 113 } 114 } 115 try { 116 uwbRangingCallbacks.onRangingResult(sessionHandle, rangingReport); 117 Log.i(TAG, "IUwbRangingCallbacks - onRangingResult"); 118 } catch (Exception e) { 119 Log.e(TAG, "IUwbRangingCallbacks - onRangingResult : Failed"); 120 e.printStackTrace(); 121 } 122 } 123 onRangingOpened(UwbSession uwbSession)124 public void onRangingOpened(UwbSession uwbSession) { 125 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 126 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 127 try { 128 uwbRangingCallbacks.onRangingOpened(sessionHandle); 129 Log.i(TAG, "IUwbRangingCallbacks - onRangingOpened"); 130 } catch (Exception e) { 131 Log.e(TAG, "IUwbRangingCallbacks - onRangingOpened : Failed"); 132 e.printStackTrace(); 133 } 134 } 135 onRangingOpenFailed(UwbSession uwbSession, int status)136 public void onRangingOpenFailed(UwbSession uwbSession, int status) { 137 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 138 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 139 140 try { 141 uwbRangingCallbacks.onRangingOpenFailed(sessionHandle, 142 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status), 143 UwbSessionNotificationHelper.convertUciStatusToParam( 144 uwbSession.getProtocolName(), status)); 145 Log.i(TAG, "IUwbRangingCallbacks - onRangingOpenFailed"); 146 } catch (Exception e) { 147 Log.e(TAG, "IUwbRangingCallbacks - onRangingOpenFailed : Failed"); 148 e.printStackTrace(); 149 } 150 } 151 onRangingStarted(UwbSession uwbSession, Params rangingStartedParams)152 public void onRangingStarted(UwbSession uwbSession, Params rangingStartedParams) { 153 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 154 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 155 try { 156 uwbRangingCallbacks.onRangingStarted(sessionHandle, rangingStartedParams.toBundle()); 157 Log.i(TAG, "IUwbRangingCallbacks - onRangingStarted"); 158 } catch (Exception e) { 159 Log.e(TAG, "IUwbRangingCallbacks - onRangingStarted : Failed"); 160 e.printStackTrace(); 161 } 162 } 163 164 onRangingStartFailed(UwbSession uwbSession, int status)165 public void onRangingStartFailed(UwbSession uwbSession, int status) { 166 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 167 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 168 try { 169 uwbRangingCallbacks.onRangingStartFailed(sessionHandle, 170 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status), 171 UwbSessionNotificationHelper.convertUciStatusToParam( 172 uwbSession.getProtocolName(), status)); 173 Log.i(TAG, "IUwbRangingCallbacks - onRangingStartFailed"); 174 } catch (Exception e) { 175 Log.e(TAG, "IUwbRangingCallbacks - onRangingStartFailed : Failed"); 176 e.printStackTrace(); 177 } 178 } 179 onRangingStartFailedWithUciReasonCode(UwbSession uwbSession, int reasonCode)180 public void onRangingStartFailedWithUciReasonCode(UwbSession uwbSession, int reasonCode) { 181 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 182 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 183 try { 184 int statusCode = 185 UwbSessionNotificationHelper.convertUciReasonCodeToUciStatusCode(reasonCode); 186 uwbRangingCallbacks.onRangingStartFailed(sessionHandle, 187 UwbSessionNotificationHelper.convertUciReasonCodeToApiReasonCode(reasonCode), 188 UwbSessionNotificationHelper.convertUciStatusToParam( 189 uwbSession.getProtocolName(), statusCode)); 190 Log.i(TAG, "IUwbRangingCallbacks - onRangingStartFailedWithUciReasonCode"); 191 } catch (Exception e) { 192 Log.e(TAG, "IUwbRangingCallbacks - onRangingStartFailedWithUciReasonCode : Failed"); 193 e.printStackTrace(); 194 } 195 } 196 onRangingStoppedInternal(UwbSession uwbSession, int reason, PersistableBundle params)197 private void onRangingStoppedInternal(UwbSession uwbSession, int reason, 198 PersistableBundle params) { 199 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 200 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 201 mUwbInjector.finishUwbRangingPermissionForDataDelivery(uwbSession.getAttributionSource()); 202 uwbSession.setDataDeliveryPermissionCheckNeeded(true); 203 try { 204 uwbRangingCallbacks.onRangingStopped(sessionHandle, reason, params); 205 Log.i(TAG, "IUwbRangingCallbacks - onRangingStopped"); 206 } catch (Exception e) { 207 Log.e(TAG, "IUwbRangingCallbacks - onRangingStopped : Failed"); 208 e.printStackTrace(); 209 } 210 } 211 onRangingStoppedWithUciReasonCode(UwbSession uwbSession, int reasonCode)212 public void onRangingStoppedWithUciReasonCode(UwbSession uwbSession, int reasonCode) { 213 onRangingStoppedInternal(uwbSession, 214 UwbSessionNotificationHelper.convertUciReasonCodeToApiReasonCode(reasonCode), 215 new PersistableBundle()); 216 } 217 onRangingStoppedWithApiReasonCode( UwbSession uwbSession, @RangingChangeReason int reasonCode, PersistableBundle params)218 public void onRangingStoppedWithApiReasonCode( 219 UwbSession uwbSession, @RangingChangeReason int reasonCode, PersistableBundle params) { 220 onRangingStoppedInternal(uwbSession, reasonCode, params); 221 } 222 onRangingStopped(UwbSession uwbSession, int status)223 public void onRangingStopped(UwbSession uwbSession, int status) { 224 onRangingStoppedInternal(uwbSession, 225 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode( 226 status), 227 UwbSessionNotificationHelper.convertUciStatusToParam( 228 uwbSession.getProtocolName(), status)); 229 } 230 onRangingStopFailed(UwbSession uwbSession, int status)231 public void onRangingStopFailed(UwbSession uwbSession, int status) { 232 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 233 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 234 try { 235 uwbRangingCallbacks.onRangingStopFailed(sessionHandle, 236 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode( 237 status), 238 UwbSessionNotificationHelper.convertUciStatusToParam( 239 uwbSession.getProtocolName(), status)); 240 Log.i(TAG, "IUwbRangingCallbacks - onRangingStopFailed"); 241 } catch (Exception e) { 242 Log.e(TAG, "IUwbRangingCallbacks - onRangingStopFailed : Failed"); 243 e.printStackTrace(); 244 } 245 } 246 onRangingReconfigured(UwbSession uwbSession)247 public void onRangingReconfigured(UwbSession uwbSession) { 248 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 249 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 250 PersistableBundle params; 251 if (Objects.equals(uwbSession.getProtocolName(), CccParams.PROTOCOL_NAME)) { 252 // Why are there no params defined for this bundle? 253 params = new CccRangingReconfiguredParams.Builder().build().toBundle(); 254 } else if (Objects.equals(uwbSession.getProtocolName(), AliroParams.PROTOCOL_NAME)) { 255 // Why are there no params defined for this bundle? 256 params = new AliroRangingReconfiguredParams.Builder().build().toBundle(); 257 } else { 258 // No params defined for FiRa reconfigure. 259 params = new PersistableBundle(); 260 } 261 try { 262 uwbRangingCallbacks.onRangingReconfigured(sessionHandle, params); 263 Log.i(TAG, "IUwbRangingCallbacks - onRangingReconfigured"); 264 } catch (Exception e) { 265 Log.e(TAG, "IUwbRangingCallbacks - onRangingReconfigured : Failed"); 266 e.printStackTrace(); 267 } 268 } 269 onRangingReconfigureFailed(UwbSession uwbSession, int status)270 public void onRangingReconfigureFailed(UwbSession uwbSession, int status) { 271 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 272 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 273 try { 274 uwbRangingCallbacks.onRangingReconfigureFailed(sessionHandle, 275 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode( 276 status), 277 UwbSessionNotificationHelper.convertUciStatusToParam( 278 uwbSession.getProtocolName(), status)); 279 Log.i(TAG, "IUwbRangingCallbacks - onRangingReconfigureFailed"); 280 } catch (Exception e) { 281 Log.e(TAG, "IUwbRangingCallbacks - onRangingReconfigureFailed : Failed"); 282 e.printStackTrace(); 283 } 284 } 285 onControleeAdded(UwbSession uwbSession)286 public void onControleeAdded(UwbSession uwbSession) { 287 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 288 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 289 try { 290 uwbRangingCallbacks.onControleeAdded(sessionHandle, new PersistableBundle()); 291 Log.i(TAG, "IUwbRangingCallbacks - onControleeAdded"); 292 } catch (Exception e) { 293 Log.e(TAG, "IUwbRangingCallbacks - onControleeAdded: Failed"); 294 e.printStackTrace(); 295 } 296 } 297 onControleeAddFailed(UwbSession uwbSession, int status)298 public void onControleeAddFailed(UwbSession uwbSession, int status) { 299 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 300 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 301 try { 302 uwbRangingCallbacks.onControleeAddFailed(sessionHandle, 303 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode( 304 status), 305 UwbSessionNotificationHelper.convertUciStatusToParam( 306 uwbSession.getProtocolName(), status)); 307 Log.i(TAG, "IUwbRangingCallbacks - onControleeAddFailed"); 308 } catch (Exception e) { 309 Log.e(TAG, "IUwbRangingCallbacks - onControleeAddFailed : Failed"); 310 e.printStackTrace(); 311 } 312 } 313 onControleeRemoved(UwbSession uwbSession, UwbAddress controleeAddress, @FiraOnControleeRemovedParams.Reason int reason)314 public void onControleeRemoved(UwbSession uwbSession, UwbAddress controleeAddress, 315 @FiraOnControleeRemovedParams.Reason int reason) { 316 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 317 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 318 try { 319 uwbRangingCallbacks.onControleeRemoved(sessionHandle, 320 new FiraOnControleeRemovedParams.Builder(controleeAddress).setReason(reason) 321 .build().toBundle()); 322 Log.i(TAG, "IUwbRangingCallbacks - onControleeRemoved"); 323 } catch (Exception e) { 324 Log.e(TAG, "IUwbRangingCallbacks - onControleeRemoved: Failed"); 325 e.printStackTrace(); 326 } 327 } 328 onControleeRemoveFailed(UwbSession uwbSession, int status)329 public void onControleeRemoveFailed(UwbSession uwbSession, int status) { 330 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 331 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 332 try { 333 uwbRangingCallbacks.onControleeRemoveFailed(sessionHandle, 334 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode( 335 status), 336 UwbSessionNotificationHelper.convertUciStatusToParam( 337 uwbSession.getProtocolName(), status)); 338 Log.i(TAG, "IUwbRangingCallbacks - onControleeRemoveFailed"); 339 } catch (Exception e) { 340 Log.e(TAG, "IUwbRangingCallbacks - onControleeRemoveFailed : Failed"); 341 e.printStackTrace(); 342 } 343 } 344 onRangingPaused(UwbSession uwbSession)345 public void onRangingPaused(UwbSession uwbSession) { 346 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 347 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 348 try { 349 uwbRangingCallbacks.onRangingPaused(sessionHandle, new PersistableBundle()); 350 Log.i(TAG, "IUwbRangingCallbacks - onRangingPaused"); 351 } catch (Exception e) { 352 Log.e(TAG, "IUwbRangingCallbacks - onRangingPaused: Failed"); 353 e.printStackTrace(); 354 } 355 } 356 onRangingPauseFailed(UwbSession uwbSession, int status)357 public void onRangingPauseFailed(UwbSession uwbSession, int status) { 358 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 359 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 360 try { 361 uwbRangingCallbacks.onRangingPauseFailed(sessionHandle, 362 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode( 363 status), 364 UwbSessionNotificationHelper.convertUciStatusToParam( 365 uwbSession.getProtocolName(), status)); 366 Log.i(TAG, "IUwbRangingCallbacks - onRangingPauseFailed"); 367 } catch (Exception e) { 368 Log.e(TAG, "IUwbRangingCallbacks - onRangingPauseFailed : Failed"); 369 e.printStackTrace(); 370 } 371 } 372 onRangingResumed(UwbSession uwbSession)373 public void onRangingResumed(UwbSession uwbSession) { 374 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 375 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 376 try { 377 uwbRangingCallbacks.onRangingResumed(sessionHandle, new PersistableBundle()); 378 Log.i(TAG, "IUwbRangingCallbacks - onRangingResumed"); 379 } catch (Exception e) { 380 Log.e(TAG, "IUwbRangingCallbacks - onRangingResumed: Failed"); 381 e.printStackTrace(); 382 } 383 } 384 onRangingResumeFailed(UwbSession uwbSession, int status)385 public void onRangingResumeFailed(UwbSession uwbSession, int status) { 386 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 387 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 388 try { 389 uwbRangingCallbacks.onRangingResumeFailed(sessionHandle, 390 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode( 391 status), 392 UwbSessionNotificationHelper.convertUciStatusToParam( 393 uwbSession.getProtocolName(), status)); 394 Log.i(TAG, "IUwbRangingCallbacks - onRangingResumeFailed"); 395 } catch (Exception e) { 396 Log.e(TAG, "IUwbRangingCallbacks - onRangingResumeFailed : Failed"); 397 e.printStackTrace(); 398 } 399 } 400 onRangingClosed(UwbSession uwbSession, int status)401 public void onRangingClosed(UwbSession uwbSession, int status) { 402 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 403 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 404 try { 405 uwbRangingCallbacks.onRangingClosed(sessionHandle, 406 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode( 407 status), 408 UwbSessionNotificationHelper.convertUciStatusToParam( 409 uwbSession.getProtocolName(), status)); 410 Log.i(TAG, "IUwbRangingCallbacks - onRangingClosed"); 411 } catch (Exception e) { 412 Log.e(TAG, "IUwbRangingCallbacks - onRangingClosed : Failed"); 413 e.printStackTrace(); 414 } 415 } 416 onRangingClosedWithApiReasonCode( UwbSession uwbSession, @RangingChangeReason int reasonCode)417 public void onRangingClosedWithApiReasonCode( 418 UwbSession uwbSession, @RangingChangeReason int reasonCode) { 419 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 420 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 421 try { 422 uwbRangingCallbacks.onRangingClosed(sessionHandle, reasonCode, new PersistableBundle()); 423 Log.i(TAG, "IUwbRangingCallbacks - onRangingClosed"); 424 } catch (Exception e) { 425 Log.e(TAG, "IUwbRangingCallbacks - onRangingClosed : Failed"); 426 e.printStackTrace(); 427 } 428 } 429 430 /** Notify about payload data received during the UWB ranging session. */ onDataReceived( UwbSession uwbSession, UwbAddress remoteDeviceAddress, PersistableBundle parameters, byte[] data)431 public void onDataReceived( 432 UwbSession uwbSession, UwbAddress remoteDeviceAddress, 433 PersistableBundle parameters, byte[] data) { 434 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 435 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 436 try { 437 uwbRangingCallbacks.onDataReceived( 438 sessionHandle, remoteDeviceAddress, parameters, data); 439 Log.i(TAG, "IUwbRangingCallbacks - onDataReceived"); 440 } catch (Exception e) { 441 Log.e(TAG, "IUwbRangingCallbacks - onDataReceived : Failed"); 442 e.printStackTrace(); 443 } 444 } 445 446 /** Notify about failure in receiving payload data during the UWB ranging session. */ onDataReceiveFailed( UwbSession uwbSession, UwbAddress remoteDeviceAddress, int reason, PersistableBundle parameters)447 public void onDataReceiveFailed( 448 UwbSession uwbSession, UwbAddress remoteDeviceAddress, 449 int reason, PersistableBundle parameters) { 450 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 451 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 452 try { 453 uwbRangingCallbacks.onDataReceiveFailed( 454 sessionHandle, remoteDeviceAddress, reason, parameters); 455 Log.i(TAG, "IUwbRangingCallbacks - onDataReceiveFailed"); 456 } catch (Exception e) { 457 Log.e(TAG, "IUwbRangingCallbacks - onDataReceiveFailed : Failed"); 458 e.printStackTrace(); 459 } 460 } 461 462 /** Notify about payload data sent during the UWB ranging session. */ onDataSent( UwbSession uwbSession, UwbAddress remoteDeviceAddress, PersistableBundle parameters)463 public void onDataSent( 464 UwbSession uwbSession, UwbAddress remoteDeviceAddress, PersistableBundle parameters) { 465 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 466 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 467 try { 468 uwbRangingCallbacks.onDataSent( 469 sessionHandle, remoteDeviceAddress, parameters); 470 Log.i(TAG, "IUwbRangingCallbacks - onDataSent"); 471 } catch (Exception e) { 472 Log.e(TAG, "IUwbRangingCallbacks - onDataSent : Failed"); 473 e.printStackTrace(); 474 } 475 } 476 477 /** Notify about failure in sending payload data during the UWB ranging session. */ onDataSendFailed( UwbSession uwbSession, UwbAddress remoteDeviceAddress, int reason, PersistableBundle parameters)478 public void onDataSendFailed( 479 UwbSession uwbSession, UwbAddress remoteDeviceAddress, 480 int reason, PersistableBundle parameters) { 481 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 482 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 483 try { 484 uwbRangingCallbacks.onDataSendFailed( 485 sessionHandle, remoteDeviceAddress, reason, parameters); 486 Log.i(TAG, "IUwbRangingCallbacks - onDataSendFailed"); 487 } catch (Exception e) { 488 Log.e(TAG, "IUwbRangingCallbacks - onDataSendFailed : Failed"); 489 e.printStackTrace(); 490 } 491 } 492 493 /** Notify that data transfer phase config setting is successful. */ onDataTransferPhaseConfigured(UwbSession uwbSession, int dataTransferPhaseConfigStatus)494 public void onDataTransferPhaseConfigured(UwbSession uwbSession, 495 int dataTransferPhaseConfigStatus) { 496 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 497 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 498 FiraDataTransferPhaseConfigStatusCode statusCode = 499 new FiraDataTransferPhaseConfigStatusCode.Builder() 500 .setStatusCode(dataTransferPhaseConfigStatus).build(); 501 try { 502 uwbRangingCallbacks.onDataTransferPhaseConfigured( 503 sessionHandle, statusCode.toBundle()); 504 Log.i(TAG, "IUwbRangingCallbacks - onDataTransferPhaseConfigured"); 505 } catch (Exception e) { 506 Log.e(TAG, "IUwbRangingCallbacks - onDataTransferPhaseConfigured : Failed"); 507 e.printStackTrace(); 508 } 509 } 510 511 /** Notify that data transfer phase config setting is failed. */ onDataTransferPhaseConfigFailed(UwbSession uwbSession, int dataTransferPhaseConfigStatus)512 public void onDataTransferPhaseConfigFailed(UwbSession uwbSession, 513 int dataTransferPhaseConfigStatus) { 514 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 515 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 516 int reason = 517 UwbSessionNotificationHelper.convertDataTransferPhaseConfigStatusToApiReasonCode( 518 dataTransferPhaseConfigStatus); 519 FiraDataTransferPhaseConfigStatusCode statusCode = 520 new FiraDataTransferPhaseConfigStatusCode.Builder() 521 .setStatusCode(dataTransferPhaseConfigStatus).build(); 522 try { 523 uwbRangingCallbacks.onDataTransferPhaseConfigFailed(sessionHandle, 524 reason, statusCode.toBundle()); 525 Log.i(TAG, "IUwbRangingCallbacks - onDataTransferPhaseConfigFailed"); 526 } catch (Exception e) { 527 Log.e(TAG, "IUwbRangingCallbacks - onDataTransferPhaseConfigFailed : Failed"); 528 e.printStackTrace(); 529 } 530 } 531 532 /** Notify the response for Ranging rounds update status for Dt Tag. */ onRangingRoundsUpdateStatus( UwbSession uwbSession, PersistableBundle parameters)533 public void onRangingRoundsUpdateStatus( 534 UwbSession uwbSession, PersistableBundle parameters) { 535 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 536 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 537 try { 538 uwbRangingCallbacks.onRangingRoundsUpdateDtTagStatus(sessionHandle, 539 parameters); 540 Log.i(TAG, "IUwbRangingCallbacks - onRangingRoundsUpdateDtTagStatus"); 541 } catch (Exception e) { 542 Log.e(TAG, "IUwbRangingCallbacks - onRangingRoundsUpdateDtTagStatus : Failed"); 543 e.printStackTrace(); 544 } 545 } 546 547 /** Notify that Hybrid session configuration for controller is updated. */ onHybridSessionControllerConfigured(UwbSession uwbSession, int status)548 public void onHybridSessionControllerConfigured(UwbSession uwbSession, int status) { 549 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 550 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 551 try { 552 uwbRangingCallbacks.onHybridSessionControllerConfigured(sessionHandle, 553 UwbSessionNotificationHelper.convertUciStatusToParam( 554 uwbSession.getProtocolName(), status)); 555 Log.i(TAG, "IUwbRangingCallbacks - onHybridSessionControllerConfigured"); 556 } catch (Exception e) { 557 Log.e(TAG, "IUwbRangingCallbacks - onHybridSessionControllerConfigured: Failed"); 558 e.printStackTrace(); 559 } 560 } 561 562 /** Notify that Hybrid session configuration for controller is failed to update. */ onHybridSessionControllerConfigurationFailed(UwbSession uwbSession, int status)563 public void onHybridSessionControllerConfigurationFailed(UwbSession uwbSession, int status) { 564 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 565 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 566 try { 567 uwbRangingCallbacks.onHybridSessionControllerConfigurationFailed(sessionHandle, 568 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status), 569 UwbSessionNotificationHelper.convertUciStatusToParam( 570 uwbSession.getProtocolName(), status)); 571 Log.i(TAG, "IUwbRangingCallbacks - onHybridSessionControllerConfigurationFailed"); 572 } catch (Exception e) { 573 Log.e(TAG, "IUwbRangingCallbacks - onHybridSessionControllerConfigurationFailed :" 574 + "Failed"); 575 e.printStackTrace(); 576 } 577 } 578 579 /** Notify that Hybrid session configuration for controlee is updated. */ onHybridSessionControleeConfigured(UwbSession uwbSession, int status)580 public void onHybridSessionControleeConfigured(UwbSession uwbSession, int status) { 581 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 582 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 583 try { 584 uwbRangingCallbacks.onHybridSessionControleeConfigured(sessionHandle, 585 UwbSessionNotificationHelper.convertUciStatusToParam( 586 uwbSession.getProtocolName(), status)); 587 Log.i(TAG, "IUwbRangingCallbacks - onHybridSessionControleeConfigured"); 588 } catch (Exception e) { 589 Log.e(TAG, "IUwbRangingCallbacks - onHybridSessionControleeConfigured: Failed"); 590 e.printStackTrace(); 591 } 592 } 593 594 /** Notify that Hybrid session configuration for controlee is failed to update. */ onHybridSessionControleeConfigurationFailed(UwbSession uwbSession, int status)595 public void onHybridSessionControleeConfigurationFailed(UwbSession uwbSession, int status) { 596 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 597 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 598 try { 599 uwbRangingCallbacks.onHybridSessionControleeConfigurationFailed(sessionHandle, 600 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status), 601 UwbSessionNotificationHelper.convertUciStatusToParam( 602 uwbSession.getProtocolName(), status)); 603 Log.i(TAG, "IUwbRangingCallbacks - onHybridSessionControleeConfigurationFailed"); 604 } catch (Exception e) { 605 Log.e(TAG, "IUwbRangingCallbacks - onHybridSessionControleeConfigurationFailed :" 606 + "Failed"); 607 e.printStackTrace(); 608 } 609 } 610 611 /** Notify about new radar data message. */ onRadarDataMessageReceived(UwbSession uwbSession, UwbRadarData radarData)612 public void onRadarDataMessageReceived(UwbSession uwbSession, UwbRadarData radarData) { 613 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 614 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 615 if (uwbSession.isDataDeliveryPermissionCheckNeeded()) { 616 boolean permissionGranted = 617 mUwbInjector.checkUwbRangingPermissionForStartDataDelivery( 618 uwbSession.getAttributionSource(), "uwb radar data"); 619 if (!permissionGranted) { 620 Log.e( 621 TAG, 622 "Not delivering uwb radar data because of permission denial" 623 + sessionHandle); 624 return; 625 } 626 uwbSession.setDataDeliveryPermissionCheckNeeded(false); 627 } 628 PersistableBundle radarDataBundle = getRadarData(radarData).toBundle(); 629 try { 630 // TODO: Add radar specific @SystemApi 631 // Temporary workaround to avoid adding a new @SystemApi for the short-term. 632 uwbRangingCallbacks.onDataReceived( 633 sessionHandle, UwbAddress.fromBytes(new byte[] {0x0, 0x0}), 634 radarDataBundle, new byte[] {}); 635 Log.i(TAG, "IUwbRangingCallbacks - onDataReceived with radar data"); 636 } catch (Exception e) { 637 Log.e(TAG, "IUwbRangingCallbacks - onDataReceived with radar data: Failed"); 638 e.printStackTrace(); 639 } 640 } 641 642 /** Helper function to convert UwbRadarData to RadarData. */ getRadarData(@onNull UwbRadarData radarData)643 private static RadarData getRadarData(@NonNull UwbRadarData radarData) { 644 RadarData.Builder radarDataBuilder = 645 new RadarData.Builder() 646 .setStatusCode(radarData.statusCode) 647 .setRadarDataType(radarData.radarDataType) 648 .setSamplesPerSweep(radarData.samplesPerSweep) 649 .setBitsPerSample(radarData.bitsPerSample) 650 .setSweepOffset(radarData.sweepOffset); 651 if (radarData.radarDataType == RadarParams.RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES) { 652 for (UwbRadarSweepData sweepData : radarData.radarSweepData) { 653 radarDataBuilder.addSweepData( 654 new RadarSweepData.Builder() 655 .setSequenceNumber(sweepData.sequenceNumber) 656 .setTimestamp(sweepData.timestamp) 657 .setVendorSpecificData(sweepData.vendorSpecificData) 658 .setSampleData(sweepData.sampleData) 659 .build()); 660 } 661 } 662 return radarDataBuilder.build(); 663 } 664 getRangingReport( @onNull UwbRangingData rangingData, String protocolName, Params sessionParams, long elapsedRealtimeNanos, UwbSession uwbSession)665 private static RangingReport getRangingReport( 666 @NonNull UwbRangingData rangingData, String protocolName, 667 Params sessionParams, long elapsedRealtimeNanos, UwbSession uwbSession) { 668 if (rangingData.getRangingMeasuresType() != UwbUciConstants.RANGING_MEASUREMENT_TYPE_TWO_WAY 669 && rangingData.getRangingMeasuresType() 670 != UwbUciConstants.RANGING_MEASUREMENT_TYPE_OWR_AOA 671 && rangingData.getRangingMeasuresType() 672 != UwbUciConstants.RANGING_MEASUREMENT_TYPE_DL_TDOA) { 673 return null; 674 } 675 boolean isAoaAzimuthEnabled = true; 676 boolean isAoaElevationEnabled = true; 677 boolean isDestAoaAzimuthEnabled = false; 678 boolean isDestAoaElevationEnabled = false; 679 long sessionId = 0; 680 681 // For FIRA sessions, check if AOA is enabled for the session or not. 682 if (protocolName.equals(FiraParams.PROTOCOL_NAME)) { 683 FiraOpenSessionParams openSessionParams = (FiraOpenSessionParams) sessionParams; 684 sessionId = openSessionParams.getSessionId(); 685 switch (openSessionParams.getAoaResultRequest()) { 686 case FiraParams.AOA_RESULT_REQUEST_MODE_NO_AOA_REPORT: 687 isAoaAzimuthEnabled = false; 688 isAoaElevationEnabled = false; 689 break; 690 case FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS: 691 case FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_INTERLEAVED: 692 isAoaAzimuthEnabled = true; 693 isAoaElevationEnabled = true; 694 break; 695 case FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_AZIMUTH_ONLY: 696 isAoaAzimuthEnabled = true; 697 isAoaElevationEnabled = false; 698 break; 699 case FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_ELEVATION_ONLY: 700 isAoaAzimuthEnabled = false; 701 isAoaElevationEnabled = true; 702 break; 703 default: 704 throw new IllegalArgumentException("Invalid AOA result req"); 705 } 706 if (openSessionParams.hasRangingResultReportMessage()) { 707 if (openSessionParams.hasAngleOfArrivalAzimuthReport()) { 708 isDestAoaAzimuthEnabled = true; 709 } 710 if (openSessionParams.hasAngleOfArrivalElevationReport()) { 711 isDestAoaElevationEnabled = true; 712 } 713 } 714 } 715 716 // TODO(b/256734264): The unit tests are currently not checking for this field, as 717 // RangingReport.equals() does not compare it. 718 PersistableBundle rangingReportMetadata = new RangingReportMetadata.Builder() 719 .setSessionId(sessionId) 720 .setRawNtfData(rangingData.getRawNtfData()) 721 .build() 722 .toBundle(); 723 RangingReport.Builder rangingReportBuilder = new RangingReport.Builder() 724 .addRangingReportMetadata(rangingReportMetadata); 725 726 if (rangingData.getRangingMeasuresType() 727 == UwbUciConstants.RANGING_MEASUREMENT_TYPE_TWO_WAY) { 728 List<RangingMeasurement> rangingMeasurements = new ArrayList<>(); 729 UwbTwoWayMeasurement[] uwbTwoWayMeasurement = rangingData.getRangingTwoWayMeasures(); 730 for (int i = 0; i < rangingData.getNoOfRangingMeasures(); ++i) { 731 int rangingStatus = uwbTwoWayMeasurement[i].convertStatusCode(); 732 733 RangingMeasurement.Builder rangingMeasurementBuilder = buildRangingMeasurement( 734 uwbTwoWayMeasurement[i].getMacAddress(), rangingStatus, 735 elapsedRealtimeNanos, uwbTwoWayMeasurement[i].getNLoS()); 736 int rssi = uwbTwoWayMeasurement[i].getRssi(); 737 if (rssi < 0) { 738 rangingMeasurementBuilder.setRssiDbm(rssi); 739 } 740 741 if (uwbTwoWayMeasurement[i].isStatusCodeOk()) { 742 // Distance measurement is mandatory 743 rangingMeasurementBuilder.setDistanceMeasurement( 744 buildDistanceMeasurement(uwbTwoWayMeasurement[i].getDistance())); 745 746 // Aoa measurement is optional based on configuration. 747 AngleOfArrivalMeasurement angleOfArrivalMeasurement = 748 computeAngleOfArrivalMeasurement( 749 isAoaAzimuthEnabled, isAoaElevationEnabled, 750 uwbTwoWayMeasurement[i].getAoaAzimuth(), 751 uwbTwoWayMeasurement[i].getAoaAzimuthFom(), 752 uwbTwoWayMeasurement[i].getAoaElevation(), 753 uwbTwoWayMeasurement[i].getAoaElevationFom()); 754 if (angleOfArrivalMeasurement != null) { 755 rangingMeasurementBuilder.setAngleOfArrivalMeasurement( 756 angleOfArrivalMeasurement); 757 } 758 759 // Dest AngleOfArrivalMeasurement 760 AngleOfArrivalMeasurement destinationAngleOfArrivalMeasurement = 761 computeAngleOfArrivalMeasurement( 762 isDestAoaAzimuthEnabled, isDestAoaElevationEnabled, 763 uwbTwoWayMeasurement[i].getAoaDestAzimuth(), 764 uwbTwoWayMeasurement[i].getAoaDestAzimuthFom(), 765 uwbTwoWayMeasurement[i].getAoaDestElevation(), 766 uwbTwoWayMeasurement[i].getAoaDestElevationFom()); 767 if (destinationAngleOfArrivalMeasurement != null) { 768 rangingMeasurementBuilder.setDestinationAngleOfArrivalMeasurement( 769 destinationAngleOfArrivalMeasurement); 770 } 771 } 772 773 // TODO: No ranging measurement metadata defined, added for future usage 774 PersistableBundle rangingMeasurementMetadata = new PersistableBundle(); 775 rangingMeasurementBuilder.setRangingMeasurementMetadata(rangingMeasurementMetadata); 776 777 UwbAddress addr = getComputedMacAddress(uwbTwoWayMeasurement[i].getMacAddress()); 778 UwbControlee controlee = uwbSession.getControlee(addr); 779 if (controlee != null) { 780 controlee.filterMeasurement(rangingMeasurementBuilder); 781 } 782 783 rangingMeasurements.add(rangingMeasurementBuilder.build()); 784 } 785 786 rangingReportBuilder.addMeasurements(rangingMeasurements); 787 } else if (rangingData.getRangingMeasuresType() 788 == UwbUciConstants.RANGING_MEASUREMENT_TYPE_OWR_AOA) { 789 UwbOwrAoaMeasurement uwbOwrAoaMeasurement = rangingData.getRangingOwrAoaMeasure(); 790 791 int rangingStatus = uwbOwrAoaMeasurement.getRangingStatus(); 792 RangingMeasurement.Builder rangingMeasurementBuilder = buildRangingMeasurement( 793 uwbOwrAoaMeasurement.getMacAddress(), rangingStatus, elapsedRealtimeNanos, 794 uwbOwrAoaMeasurement.getNLoS()); 795 796 if (rangingStatus == FiraParams.STATUS_CODE_OK) { 797 // AngleOfArrivalMeasurement 798 AngleOfArrivalMeasurement angleOfArrivalMeasurement = 799 computeAngleOfArrivalMeasurement( 800 isAoaAzimuthEnabled, isAoaElevationEnabled, 801 uwbOwrAoaMeasurement.getAoaAzimuth(), 802 uwbOwrAoaMeasurement.getAoaAzimuthFom(), 803 uwbOwrAoaMeasurement.getAoaElevation(), 804 uwbOwrAoaMeasurement.getAoaElevationFom()); 805 if (angleOfArrivalMeasurement != null) { 806 rangingMeasurementBuilder.setAngleOfArrivalMeasurement( 807 angleOfArrivalMeasurement); 808 } 809 } 810 811 rangingReportBuilder.addMeasurement(rangingMeasurementBuilder.build()); 812 } else if (rangingData.getRangingMeasuresType() 813 == UwbUciConstants.RANGING_MEASUREMENT_TYPE_DL_TDOA) { 814 List<RangingMeasurement> rangingMeasurements = new ArrayList<>(); 815 UwbDlTDoAMeasurement[] uwbDlTDoAMeasurements = rangingData.getUwbDlTDoAMeasurements(); 816 for (int i = 0; i < rangingData.getNoOfRangingMeasures(); ++i) { 817 int rangingStatus = uwbDlTDoAMeasurements[i].getStatus(); 818 819 RangingMeasurement.Builder rangingMeasurementBuilder = buildRangingMeasurement( 820 uwbDlTDoAMeasurements[i].getMacAddress(), rangingStatus, 821 elapsedRealtimeNanos, uwbDlTDoAMeasurements[i].getNLoS()); 822 int rssi = uwbDlTDoAMeasurements[i].getRssi(); 823 if (rssi < 0) { 824 rangingMeasurementBuilder.setRssiDbm(rssi); 825 } 826 if (rangingStatus == FiraParams.STATUS_CODE_OK) { 827 AngleOfArrivalMeasurement angleOfArrivalMeasurement = 828 computeAngleOfArrivalMeasurement( 829 isAoaAzimuthEnabled, isAoaElevationEnabled, 830 uwbDlTDoAMeasurements[i].getAoaAzimuth(), 831 uwbDlTDoAMeasurements[i].getAoaAzimuthFom(), 832 uwbDlTDoAMeasurements[i].getAoaElevation(), 833 uwbDlTDoAMeasurements[i].getAoaElevationFom()); 834 if (angleOfArrivalMeasurement != null) { 835 rangingMeasurementBuilder.setAngleOfArrivalMeasurement( 836 angleOfArrivalMeasurement); 837 } 838 } 839 DlTDoAMeasurement dlTDoAMeasurement = new DlTDoAMeasurement.Builder() 840 .setMessageType(uwbDlTDoAMeasurements[i].getMessageType()) 841 .setMessageControl(uwbDlTDoAMeasurements[i].getMessageControl()) 842 .setBlockIndex(uwbDlTDoAMeasurements[i].getBlockIndex()) 843 .setNLoS(uwbDlTDoAMeasurements[i].getNLoS()) 844 .setTxTimestamp(uwbDlTDoAMeasurements[i].getTxTimestamp()) 845 .setRxTimestamp(uwbDlTDoAMeasurements[i].getRxTimestamp()) 846 .setAnchorCfo(uwbDlTDoAMeasurements[i].getAnchorCfo()) 847 .setCfo(uwbDlTDoAMeasurements[i].getCfo()) 848 .setInitiatorReplyTime(uwbDlTDoAMeasurements[i].getInitiatorReplyTime()) 849 .setResponderReplyTime(uwbDlTDoAMeasurements[i].getResponderReplyTime()) 850 .setInitiatorResponderTof(uwbDlTDoAMeasurements[i] 851 .getInitiatorResponderTof()) 852 .setAnchorLocation(uwbDlTDoAMeasurements[i].getAnchorLocation()) 853 .setActiveRangingRounds(uwbDlTDoAMeasurements[i].getActiveRangingRounds()) 854 .setRoundIndex(uwbDlTDoAMeasurements[i].getRoundIndex()) 855 .build(); 856 rangingMeasurementBuilder.setRangingMeasurementMetadata( 857 dlTDoAMeasurement.toBundle()); 858 859 rangingMeasurements.add(rangingMeasurementBuilder.build()); 860 } 861 862 rangingReportBuilder.addMeasurements(rangingMeasurements); 863 } 864 return rangingReportBuilder.build(); 865 } 866 computeAngleOfArrivalMeasurement( boolean isAoaAzimuthEnabled, boolean isAoaElevationEnabled, float aoaAzimuth, int aoaAzimuthFom, float aoaElevation, int aoaElevationFom)867 private static AngleOfArrivalMeasurement computeAngleOfArrivalMeasurement( 868 boolean isAoaAzimuthEnabled, boolean isAoaElevationEnabled, float aoaAzimuth, 869 int aoaAzimuthFom, float aoaElevation, int aoaElevationFom) { 870 // Azimuth is required field (and elevation is an optional field), to build the 871 // AngleOfArrivalMeasurement. 872 if (isAoaAzimuthEnabled) { 873 AngleMeasurement azimuthAngleMeasurement = new AngleMeasurement( 874 UwbUtil.degreeToRadian(aoaAzimuth), 0, aoaAzimuthFom / (double) 100); 875 // AngleOfArrivalMeasurement 876 AngleOfArrivalMeasurement.Builder angleOfArrivalMeasurementBuilder = 877 new AngleOfArrivalMeasurement.Builder(azimuthAngleMeasurement); 878 879 // Elevation is optional field, to build the AngleOfArrivalMeasurement. 880 if (isAoaElevationEnabled) { 881 AngleMeasurement altitudeAngleMeasurement = new AngleMeasurement( 882 UwbUtil.degreeToRadian(aoaElevation), 0, aoaElevationFom / (double) 100); 883 angleOfArrivalMeasurementBuilder.setAltitude(altitudeAngleMeasurement); 884 } 885 886 return angleOfArrivalMeasurementBuilder.build(); 887 } 888 889 return null; 890 } 891 buildRangingMeasurement( byte[] macAddress, int rangingStatus, long elapsedRealtimeNanos, int los)892 private static RangingMeasurement.Builder buildRangingMeasurement( 893 byte[] macAddress, int rangingStatus, long elapsedRealtimeNanos, int los) { 894 return new RangingMeasurement.Builder() 895 .setRemoteDeviceAddress(getComputedMacAddress(macAddress)) 896 .setStatus(rangingStatus) 897 .setElapsedRealtimeNanos(elapsedRealtimeNanos) 898 .setLineOfSight(los); 899 } 900 buildDistanceMeasurement(int distance)901 private static DistanceMeasurement buildDistanceMeasurement(int distance) { 902 return new DistanceMeasurement.Builder() 903 .setMeters(distance / (double) 100) 904 .setErrorMeters(0) 905 // TODO: Need to fetch distance FOM once it is added to UCI spec. 906 .setConfidenceLevel(1) 907 .build(); 908 } 909 getComputedMacAddress(byte[] address)910 private static UwbAddress getComputedMacAddress(byte[] address) { 911 if (!SdkLevel.isAtLeastU()) { 912 return UwbAddress.fromBytes(TlvUtil.getReverseBytes(address)); 913 } 914 return UwbAddress.fromBytes(address); 915 } 916 } 917