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