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.UwbRangingData; 37 import com.android.server.uwb.data.UwbTwoWayMeasurement; 38 import com.android.server.uwb.data.UwbUciConstants; 39 import com.android.server.uwb.params.TlvUtil; 40 import com.android.server.uwb.util.UwbUtil; 41 42 import com.google.uwb.support.base.Params; 43 import com.google.uwb.support.ccc.CccParams; 44 import com.google.uwb.support.ccc.CccRangingReconfiguredParams; 45 import com.google.uwb.support.dltdoa.DlTDoAMeasurement; 46 import com.google.uwb.support.fira.FiraOpenSessionParams; 47 import com.google.uwb.support.fira.FiraParams; 48 import com.google.uwb.support.oemextension.RangingReportMetadata; 49 50 import java.util.ArrayList; 51 import java.util.List; 52 import java.util.Objects; 53 54 public class UwbSessionNotificationManager { 55 private static final String TAG = "UwbSessionNotiManager"; 56 private final UwbInjector mUwbInjector; 57 UwbSessionNotificationManager(@onNull UwbInjector uwbInjector)58 public UwbSessionNotificationManager(@NonNull UwbInjector uwbInjector) { 59 mUwbInjector = uwbInjector; 60 } 61 onRangingResult(UwbSession uwbSession, UwbRangingData rangingData)62 public void onRangingResult(UwbSession uwbSession, UwbRangingData rangingData) { 63 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 64 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 65 boolean permissionGranted = mUwbInjector.checkUwbRangingPermissionForDataDelivery( 66 uwbSession.getAttributionSource(), "uwb ranging result"); 67 if (!permissionGranted) { 68 Log.e(TAG, "Not delivering ranging result because of permission denial" 69 + sessionHandle); 70 return; 71 } 72 73 RangingReport rangingReport = null; 74 try { 75 rangingReport = getRangingReport(rangingData, uwbSession.getProtocolName(), 76 uwbSession.getParams(), mUwbInjector.getElapsedSinceBootNanos(), uwbSession); 77 } catch (Exception e) { 78 Log.e(TAG, "getRangingReport Failed."); 79 e.printStackTrace(); 80 } 81 82 try { 83 RangingMeasurement filteredRangingMeasurement = rangingReport != null 84 ? rangingReport.getMeasurements().get(0) : null; 85 mUwbInjector.getUwbMetrics().logRangingResult(uwbSession.getProfileType(), rangingData, 86 filteredRangingMeasurement); 87 } catch (Exception e) { 88 Log.e(TAG, "logRangingResult Failed."); 89 e.printStackTrace(); 90 } 91 92 if (mUwbInjector.getUwbServiceCore().isOemExtensionCbRegistered()) { 93 try { 94 rangingReport = mUwbInjector.getUwbServiceCore().getOemExtensionCallback() 95 .onRangingReportReceived(rangingReport); 96 } catch (RemoteException e) { 97 Log.e(TAG, "UwbInjector - onRangingReportReceived : Failed."); 98 e.printStackTrace(); 99 } 100 } 101 try { 102 uwbRangingCallbacks.onRangingResult(sessionHandle, rangingReport); 103 Log.i(TAG, "IUwbRangingCallbacks - onRangingResult"); 104 } catch (Exception e) { 105 Log.e(TAG, "IUwbRangingCallbacks - onRangingResult : Failed"); 106 e.printStackTrace(); 107 } 108 } 109 onRangingOpened(UwbSession uwbSession)110 public void onRangingOpened(UwbSession uwbSession) { 111 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 112 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 113 try { 114 uwbRangingCallbacks.onRangingOpened(sessionHandle); 115 Log.i(TAG, "IUwbRangingCallbacks - onRangingOpened"); 116 } catch (Exception e) { 117 Log.e(TAG, "IUwbRangingCallbacks - onRangingOpened : Failed"); 118 e.printStackTrace(); 119 } 120 } 121 onRangingOpenFailed(UwbSession uwbSession, int status)122 public void onRangingOpenFailed(UwbSession uwbSession, int status) { 123 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 124 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 125 126 try { 127 uwbRangingCallbacks.onRangingOpenFailed(sessionHandle, 128 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status), 129 UwbSessionNotificationHelper.convertUciStatusToParam( 130 uwbSession.getProtocolName(), status)); 131 Log.i(TAG, "IUwbRangingCallbacks - onRangingOpenFailed"); 132 } catch (Exception e) { 133 Log.e(TAG, "IUwbRangingCallbacks - onRangingOpenFailed : Failed"); 134 e.printStackTrace(); 135 } 136 } 137 onRangingStarted(UwbSession uwbSession, Params rangingStartedParams)138 public void onRangingStarted(UwbSession uwbSession, Params rangingStartedParams) { 139 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 140 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 141 try { 142 uwbRangingCallbacks.onRangingStarted(sessionHandle, rangingStartedParams.toBundle()); 143 Log.i(TAG, "IUwbRangingCallbacks - onRangingStarted"); 144 } catch (Exception e) { 145 Log.e(TAG, "IUwbRangingCallbacks - onRangingStarted : Failed"); 146 e.printStackTrace(); 147 } 148 } 149 150 onRangingStartFailed(UwbSession uwbSession, int status)151 public void onRangingStartFailed(UwbSession uwbSession, int status) { 152 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 153 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 154 try { 155 uwbRangingCallbacks.onRangingStartFailed(sessionHandle, 156 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode(status), 157 UwbSessionNotificationHelper.convertUciStatusToParam( 158 uwbSession.getProtocolName(), status)); 159 Log.i(TAG, "IUwbRangingCallbacks - onRangingStartFailed"); 160 } catch (Exception e) { 161 Log.e(TAG, "IUwbRangingCallbacks - onRangingStartFailed : Failed"); 162 e.printStackTrace(); 163 } 164 } 165 onRangingStoppedInternal(UwbSession uwbSession, int reason, PersistableBundle params)166 private void onRangingStoppedInternal(UwbSession uwbSession, int reason, 167 PersistableBundle params) { 168 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 169 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 170 try { 171 uwbRangingCallbacks.onRangingStopped(sessionHandle, reason, params); 172 Log.i(TAG, "IUwbRangingCallbacks - onRangingStopped"); 173 } catch (Exception e) { 174 Log.e(TAG, "IUwbRangingCallbacks - onRangingStopped : Failed"); 175 e.printStackTrace(); 176 } 177 } 178 onRangingStoppedWithUciReasonCode(UwbSession uwbSession, int reasonCode)179 public void onRangingStoppedWithUciReasonCode(UwbSession uwbSession, int reasonCode) { 180 onRangingStoppedInternal(uwbSession, 181 UwbSessionNotificationHelper.convertUciReasonCodeToApiReasonCode(reasonCode), 182 new PersistableBundle()); 183 } 184 onRangingStoppedWithApiReasonCode( UwbSession uwbSession, @RangingChangeReason int reasonCode)185 public void onRangingStoppedWithApiReasonCode( 186 UwbSession uwbSession, @RangingChangeReason int reasonCode) { 187 onRangingStoppedInternal(uwbSession, reasonCode, new PersistableBundle()); 188 } 189 onRangingStopped(UwbSession uwbSession, int status)190 public void onRangingStopped(UwbSession uwbSession, int status) { 191 onRangingStoppedInternal(uwbSession, 192 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode( 193 status), 194 UwbSessionNotificationHelper.convertUciStatusToParam( 195 uwbSession.getProtocolName(), status)); 196 } 197 onRangingStopFailed(UwbSession uwbSession, int status)198 public void onRangingStopFailed(UwbSession uwbSession, int status) { 199 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 200 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 201 try { 202 uwbRangingCallbacks.onRangingStopFailed(sessionHandle, 203 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode( 204 status), 205 UwbSessionNotificationHelper.convertUciStatusToParam( 206 uwbSession.getProtocolName(), status)); 207 Log.i(TAG, "IUwbRangingCallbacks - onRangingStopFailed"); 208 } catch (Exception e) { 209 Log.e(TAG, "IUwbRangingCallbacks - onRangingStopFailed : Failed"); 210 e.printStackTrace(); 211 } 212 } 213 onRangingReconfigured(UwbSession uwbSession)214 public void onRangingReconfigured(UwbSession uwbSession) { 215 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 216 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 217 PersistableBundle params; 218 if (Objects.equals(uwbSession.getProtocolName(), CccParams.PROTOCOL_NAME)) { 219 // Why are there no params defined for this bundle? 220 params = new CccRangingReconfiguredParams.Builder().build().toBundle(); 221 } else { 222 // No params defined for FiRa reconfigure. 223 params = new PersistableBundle(); 224 } 225 try { 226 uwbRangingCallbacks.onRangingReconfigured(sessionHandle, params); 227 Log.i(TAG, "IUwbRangingCallbacks - onRangingReconfigured"); 228 } catch (Exception e) { 229 Log.e(TAG, "IUwbRangingCallbacks - onRangingReconfigured : Failed"); 230 e.printStackTrace(); 231 } 232 } 233 onRangingReconfigureFailed(UwbSession uwbSession, int status)234 public void onRangingReconfigureFailed(UwbSession uwbSession, int status) { 235 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 236 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 237 try { 238 uwbRangingCallbacks.onRangingReconfigureFailed(sessionHandle, 239 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode( 240 status), 241 UwbSessionNotificationHelper.convertUciStatusToParam( 242 uwbSession.getProtocolName(), status)); 243 Log.i(TAG, "IUwbRangingCallbacks - onRangingReconfigureFailed"); 244 } catch (Exception e) { 245 Log.e(TAG, "IUwbRangingCallbacks - onRangingReconfigureFailed : Failed"); 246 e.printStackTrace(); 247 } 248 } 249 onControleeAdded(UwbSession uwbSession)250 public void onControleeAdded(UwbSession uwbSession) { 251 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 252 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 253 try { 254 uwbRangingCallbacks.onControleeAdded(sessionHandle, new PersistableBundle()); 255 Log.i(TAG, "IUwbRangingCallbacks - onControleeAdded"); 256 } catch (Exception e) { 257 Log.e(TAG, "IUwbRangingCallbacks - onControleeAdded: Failed"); 258 e.printStackTrace(); 259 } 260 } 261 onControleeAddFailed(UwbSession uwbSession, int status)262 public void onControleeAddFailed(UwbSession uwbSession, int status) { 263 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 264 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 265 try { 266 uwbRangingCallbacks.onControleeAddFailed(sessionHandle, 267 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode( 268 status), 269 UwbSessionNotificationHelper.convertUciStatusToParam( 270 uwbSession.getProtocolName(), status)); 271 Log.i(TAG, "IUwbRangingCallbacks - onControleeAddFailed"); 272 } catch (Exception e) { 273 Log.e(TAG, "IUwbRangingCallbacks - onControleeAddFailed : Failed"); 274 e.printStackTrace(); 275 } 276 } 277 onControleeRemoved(UwbSession uwbSession)278 public void onControleeRemoved(UwbSession uwbSession) { 279 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 280 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 281 try { 282 uwbRangingCallbacks.onControleeRemoved(sessionHandle, new PersistableBundle()); 283 Log.i(TAG, "IUwbRangingCallbacks - onControleeRemoved"); 284 } catch (Exception e) { 285 Log.e(TAG, "IUwbRangingCallbacks - onControleeRemoved: Failed"); 286 e.printStackTrace(); 287 } 288 } 289 onControleeRemoveFailed(UwbSession uwbSession, int status)290 public void onControleeRemoveFailed(UwbSession uwbSession, int status) { 291 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 292 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 293 try { 294 uwbRangingCallbacks.onControleeRemoveFailed(sessionHandle, 295 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode( 296 status), 297 UwbSessionNotificationHelper.convertUciStatusToParam( 298 uwbSession.getProtocolName(), status)); 299 Log.i(TAG, "IUwbRangingCallbacks - onControleeRemoveFailed"); 300 } catch (Exception e) { 301 Log.e(TAG, "IUwbRangingCallbacks - onControleeRemoveFailed : Failed"); 302 e.printStackTrace(); 303 } 304 } 305 onRangingClosed(UwbSession uwbSession, int status)306 public void onRangingClosed(UwbSession uwbSession, int status) { 307 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 308 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 309 try { 310 uwbRangingCallbacks.onRangingClosed(sessionHandle, 311 UwbSessionNotificationHelper.convertUciStatusToApiReasonCode( 312 status), 313 UwbSessionNotificationHelper.convertUciStatusToParam( 314 uwbSession.getProtocolName(), status)); 315 Log.i(TAG, "IUwbRangingCallbacks - onRangingClosed"); 316 } catch (Exception e) { 317 Log.e(TAG, "IUwbRangingCallbacks - onRangingClosed : Failed"); 318 e.printStackTrace(); 319 } 320 } 321 onRangingClosedWithApiReasonCode( UwbSession uwbSession, @RangingChangeReason int reasonCode)322 public void onRangingClosedWithApiReasonCode( 323 UwbSession uwbSession, @RangingChangeReason int reasonCode) { 324 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 325 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 326 try { 327 uwbRangingCallbacks.onRangingClosed(sessionHandle, reasonCode, new PersistableBundle()); 328 Log.i(TAG, "IUwbRangingCallbacks - onRangingClosed"); 329 } catch (Exception e) { 330 Log.e(TAG, "IUwbRangingCallbacks - onRangingClosed : Failed"); 331 e.printStackTrace(); 332 } 333 } 334 335 /** Notify about payload data received during the UWB ranging session. */ onDataReceived( UwbSession uwbSession, UwbAddress remoteDeviceAddress, PersistableBundle parameters, byte[] data)336 public void onDataReceived( 337 UwbSession uwbSession, UwbAddress remoteDeviceAddress, 338 PersistableBundle parameters, byte[] data) { 339 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 340 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 341 try { 342 uwbRangingCallbacks.onDataReceived( 343 sessionHandle, remoteDeviceAddress, parameters, data); 344 Log.i(TAG, "IUwbRangingCallbacks - onDataReceived"); 345 } catch (Exception e) { 346 Log.e(TAG, "IUwbRangingCallbacks - onDataReceived : Failed"); 347 e.printStackTrace(); 348 } 349 } 350 351 /** Notify about failure in receiving payload data during the UWB ranging session. */ onDataReceiveFailed( UwbSession uwbSession, UwbAddress remoteDeviceAddress, int reason, PersistableBundle parameters)352 public void onDataReceiveFailed( 353 UwbSession uwbSession, UwbAddress remoteDeviceAddress, 354 int reason, PersistableBundle parameters) { 355 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 356 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 357 try { 358 uwbRangingCallbacks.onDataReceiveFailed( 359 sessionHandle, remoteDeviceAddress, reason, parameters); 360 Log.i(TAG, "IUwbRangingCallbacks - onDataReceiveFailed"); 361 } catch (Exception e) { 362 Log.e(TAG, "IUwbRangingCallbacks - onDataReceiveFailed : Failed"); 363 e.printStackTrace(); 364 } 365 } 366 367 /** Notify about payload data sent during the UWB ranging session. */ onDataSent( UwbSession uwbSession, UwbAddress remoteDeviceAddress, PersistableBundle parameters)368 public void onDataSent( 369 UwbSession uwbSession, UwbAddress remoteDeviceAddress, PersistableBundle parameters) { 370 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 371 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 372 try { 373 uwbRangingCallbacks.onDataSent( 374 sessionHandle, remoteDeviceAddress, parameters); 375 Log.i(TAG, "IUwbRangingCallbacks - onDataSent"); 376 } catch (Exception e) { 377 Log.e(TAG, "IUwbRangingCallbacks - onDataSent : Failed"); 378 e.printStackTrace(); 379 } 380 } 381 382 /** Notify about failure in sending payload data during the UWB ranging session. */ onDataSendFailed( UwbSession uwbSession, UwbAddress remoteDeviceAddress, int reason, PersistableBundle parameters)383 public void onDataSendFailed( 384 UwbSession uwbSession, UwbAddress remoteDeviceAddress, 385 int reason, PersistableBundle parameters) { 386 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 387 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 388 try { 389 uwbRangingCallbacks.onDataSendFailed( 390 sessionHandle, remoteDeviceAddress, reason, parameters); 391 Log.i(TAG, "IUwbRangingCallbacks - onDataSendFailed"); 392 } catch (Exception e) { 393 Log.e(TAG, "IUwbRangingCallbacks - onDataSendFailed : Failed"); 394 e.printStackTrace(); 395 } 396 } 397 398 /** Notify the response for Ranging rounds update status for Dt Tag. */ onRangingRoundsUpdateStatus( UwbSession uwbSession, PersistableBundle parameters)399 public void onRangingRoundsUpdateStatus( 400 UwbSession uwbSession, PersistableBundle parameters) { 401 SessionHandle sessionHandle = uwbSession.getSessionHandle(); 402 IUwbRangingCallbacks uwbRangingCallbacks = uwbSession.getIUwbRangingCallbacks(); 403 try { 404 uwbRangingCallbacks.onRangingRoundsUpdateDtTagStatus(sessionHandle, 405 parameters); 406 Log.i(TAG, "IUwbRangingCallbacks - onRangingRoundsUpdateDtTagStatus"); 407 } catch (Exception e) { 408 Log.e(TAG, "IUwbRangingCallbacks - onRangingRoundsUpdateDtTagStatus : Failed"); 409 e.printStackTrace(); 410 } 411 } 412 getRangingReport( @onNull UwbRangingData rangingData, String protocolName, Params sessionParams, long elapsedRealtimeNanos, UwbSession uwbSession)413 private static RangingReport getRangingReport( 414 @NonNull UwbRangingData rangingData, String protocolName, 415 Params sessionParams, long elapsedRealtimeNanos, UwbSession uwbSession) { 416 if (rangingData.getRangingMeasuresType() != UwbUciConstants.RANGING_MEASUREMENT_TYPE_TWO_WAY 417 && rangingData.getRangingMeasuresType() 418 != UwbUciConstants.RANGING_MEASUREMENT_TYPE_OWR_AOA 419 && rangingData.getRangingMeasuresType() 420 != UwbUciConstants.RANGING_MEASUREMENT_TYPE_DL_TDOA) { 421 return null; 422 } 423 boolean isAoaAzimuthEnabled = true; 424 boolean isAoaElevationEnabled = true; 425 boolean isDestAoaAzimuthEnabled = false; 426 boolean isDestAoaElevationEnabled = false; 427 long sessionId = 0; 428 429 // For FIRA sessions, check if AOA is enabled for the session or not. 430 if (protocolName.equals(FiraParams.PROTOCOL_NAME)) { 431 FiraOpenSessionParams openSessionParams = (FiraOpenSessionParams) sessionParams; 432 sessionId = openSessionParams.getSessionId(); 433 switch (openSessionParams.getAoaResultRequest()) { 434 case FiraParams.AOA_RESULT_REQUEST_MODE_NO_AOA_REPORT: 435 isAoaAzimuthEnabled = false; 436 isAoaElevationEnabled = false; 437 break; 438 case FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS: 439 case FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_INTERLEAVED: 440 isAoaAzimuthEnabled = true; 441 isAoaElevationEnabled = true; 442 break; 443 case FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_AZIMUTH_ONLY: 444 isAoaAzimuthEnabled = true; 445 isAoaElevationEnabled = false; 446 break; 447 case FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_ELEVATION_ONLY: 448 isAoaAzimuthEnabled = false; 449 isAoaElevationEnabled = true; 450 break; 451 default: 452 throw new IllegalArgumentException("Invalid AOA result req"); 453 } 454 if (openSessionParams.hasRangingResultReportMessage()) { 455 if (openSessionParams.hasAngleOfArrivalAzimuthReport()) { 456 isDestAoaAzimuthEnabled = true; 457 } 458 if (openSessionParams.hasAngleOfArrivalElevationReport()) { 459 isDestAoaElevationEnabled = true; 460 } 461 } 462 } 463 464 // TODO(b/256734264): The unit tests are currently not checking for this field, as 465 // RangingReport.equals() does not compare it. 466 PersistableBundle rangingReportMetadata = new RangingReportMetadata.Builder() 467 .setSessionId(sessionId) 468 .setRawNtfData(rangingData.getRawNtfData()) 469 .build() 470 .toBundle(); 471 RangingReport.Builder rangingReportBuilder = new RangingReport.Builder() 472 .addRangingReportMetadata(rangingReportMetadata); 473 474 if (rangingData.getRangingMeasuresType() 475 == UwbUciConstants.RANGING_MEASUREMENT_TYPE_TWO_WAY) { 476 List<RangingMeasurement> rangingMeasurements = new ArrayList<>(); 477 UwbTwoWayMeasurement[] uwbTwoWayMeasurement = rangingData.getRangingTwoWayMeasures(); 478 for (int i = 0; i < rangingData.getNoOfRangingMeasures(); ++i) { 479 int rangingStatus = uwbTwoWayMeasurement[i].convertStatusCode(); 480 481 RangingMeasurement.Builder rangingMeasurementBuilder = buildRangingMeasurement( 482 uwbTwoWayMeasurement[i].getMacAddress(), rangingStatus, 483 elapsedRealtimeNanos, uwbTwoWayMeasurement[i].getNLoS()); 484 int rssi = uwbTwoWayMeasurement[i].getRssi(); 485 if (rssi < 0) { 486 rangingMeasurementBuilder.setRssiDbm(rssi); 487 } 488 489 if (uwbTwoWayMeasurement[i].isStatusCodeOk()) { 490 // Distance measurement is mandatory 491 rangingMeasurementBuilder.setDistanceMeasurement( 492 buildDistanceMeasurement(uwbTwoWayMeasurement[i].getDistance())); 493 494 // Aoa measurement is optional based on configuration. 495 AngleOfArrivalMeasurement angleOfArrivalMeasurement = 496 computeAngleOfArrivalMeasurement( 497 isAoaAzimuthEnabled, isAoaElevationEnabled, 498 uwbTwoWayMeasurement[i].getAoaAzimuth(), 499 uwbTwoWayMeasurement[i].getAoaAzimuthFom(), 500 uwbTwoWayMeasurement[i].getAoaElevation(), 501 uwbTwoWayMeasurement[i].getAoaElevationFom()); 502 if (angleOfArrivalMeasurement != null) { 503 rangingMeasurementBuilder.setAngleOfArrivalMeasurement( 504 angleOfArrivalMeasurement); 505 } 506 507 // Dest AngleOfArrivalMeasurement 508 AngleOfArrivalMeasurement destinationAngleOfArrivalMeasurement = 509 computeAngleOfArrivalMeasurement( 510 isDestAoaAzimuthEnabled, isDestAoaElevationEnabled, 511 uwbTwoWayMeasurement[i].getAoaDestAzimuth(), 512 uwbTwoWayMeasurement[i].getAoaDestAzimuthFom(), 513 uwbTwoWayMeasurement[i].getAoaDestElevation(), 514 uwbTwoWayMeasurement[i].getAoaDestElevationFom()); 515 if (destinationAngleOfArrivalMeasurement != null) { 516 rangingMeasurementBuilder.setDestinationAngleOfArrivalMeasurement( 517 destinationAngleOfArrivalMeasurement); 518 } 519 } 520 521 // TODO: No ranging measurement metadata defined, added for future usage 522 PersistableBundle rangingMeasurementMetadata = new PersistableBundle(); 523 rangingMeasurementBuilder.setRangingMeasurementMetadata(rangingMeasurementMetadata); 524 525 UwbAddress addr = getComputedMacAddress(uwbTwoWayMeasurement[i].getMacAddress()); 526 UwbControlee controlee = uwbSession.getControlee(addr); 527 if (controlee != null) { 528 controlee.filterMeasurement(rangingMeasurementBuilder); 529 } 530 531 rangingMeasurements.add(rangingMeasurementBuilder.build()); 532 } 533 534 rangingReportBuilder.addMeasurements(rangingMeasurements); 535 } else if (rangingData.getRangingMeasuresType() 536 == UwbUciConstants.RANGING_MEASUREMENT_TYPE_OWR_AOA) { 537 UwbOwrAoaMeasurement uwbOwrAoaMeasurement = rangingData.getRangingOwrAoaMeasure(); 538 539 int rangingStatus = uwbOwrAoaMeasurement.getRangingStatus(); 540 RangingMeasurement.Builder rangingMeasurementBuilder = buildRangingMeasurement( 541 uwbOwrAoaMeasurement.getMacAddress(), rangingStatus, elapsedRealtimeNanos, 542 uwbOwrAoaMeasurement.getNLoS()); 543 544 if (rangingStatus == FiraParams.STATUS_CODE_OK) { 545 // AngleOfArrivalMeasurement 546 AngleOfArrivalMeasurement angleOfArrivalMeasurement = 547 computeAngleOfArrivalMeasurement( 548 isAoaAzimuthEnabled, isAoaElevationEnabled, 549 uwbOwrAoaMeasurement.getAoaAzimuth(), 550 uwbOwrAoaMeasurement.getAoaAzimuthFom(), 551 uwbOwrAoaMeasurement.getAoaElevation(), 552 uwbOwrAoaMeasurement.getAoaElevationFom()); 553 if (angleOfArrivalMeasurement != null) { 554 rangingMeasurementBuilder.setAngleOfArrivalMeasurement( 555 angleOfArrivalMeasurement); 556 } 557 } 558 559 rangingReportBuilder.addMeasurement(rangingMeasurementBuilder.build()); 560 } else if (rangingData.getRangingMeasuresType() 561 == UwbUciConstants.RANGING_MEASUREMENT_TYPE_DL_TDOA) { 562 List<RangingMeasurement> rangingMeasurements = new ArrayList<>(); 563 UwbDlTDoAMeasurement[] uwbDlTDoAMeasurements = rangingData.getUwbDlTDoAMeasurements(); 564 for (int i = 0; i < rangingData.getNoOfRangingMeasures(); ++i) { 565 int rangingStatus = uwbDlTDoAMeasurements[i].getStatus(); 566 567 RangingMeasurement.Builder rangingMeasurementBuilder = buildRangingMeasurement( 568 uwbDlTDoAMeasurements[i].getMacAddress(), rangingStatus, 569 elapsedRealtimeNanos, uwbDlTDoAMeasurements[i].getNLoS()); 570 int rssi = uwbDlTDoAMeasurements[i].getRssi(); 571 if (rssi < 0) { 572 rangingMeasurementBuilder.setRssiDbm(rssi); 573 } 574 if (rangingStatus == FiraParams.STATUS_CODE_OK) { 575 AngleOfArrivalMeasurement angleOfArrivalMeasurement = 576 computeAngleOfArrivalMeasurement( 577 isAoaAzimuthEnabled, isAoaElevationEnabled, 578 uwbDlTDoAMeasurements[i].getAoaAzimuth(), 579 uwbDlTDoAMeasurements[i].getAoaAzimuthFom(), 580 uwbDlTDoAMeasurements[i].getAoaElevation(), 581 uwbDlTDoAMeasurements[i].getAoaElevationFom()); 582 if (angleOfArrivalMeasurement != null) { 583 rangingMeasurementBuilder.setAngleOfArrivalMeasurement( 584 angleOfArrivalMeasurement); 585 } 586 } 587 DlTDoAMeasurement dlTDoAMeasurement = new DlTDoAMeasurement.Builder() 588 .setMessageType(uwbDlTDoAMeasurements[i].getMessageType()) 589 .setMessageControl(uwbDlTDoAMeasurements[i].getMessageControl()) 590 .setBlockIndex(uwbDlTDoAMeasurements[i].getBlockIndex()) 591 .setNLoS(uwbDlTDoAMeasurements[i].getNLoS()) 592 .setTxTimestamp(uwbDlTDoAMeasurements[i].getTxTimestamp()) 593 .setRxTimestamp(uwbDlTDoAMeasurements[i].getRxTimestamp()) 594 .setAnchorCfo(uwbDlTDoAMeasurements[i].getAnchorCfo()) 595 .setCfo(uwbDlTDoAMeasurements[i].getCfo()) 596 .setInitiatorReplyTime(uwbDlTDoAMeasurements[i].getInitiatorReplyTime()) 597 .setResponderReplyTime(uwbDlTDoAMeasurements[i].getResponderReplyTime()) 598 .setInitiatorResponderTof(uwbDlTDoAMeasurements[i] 599 .getInitiatorResponderTof()) 600 .setAnchorLocation(uwbDlTDoAMeasurements[i].getAnchorLocation()) 601 .setActiveRangingRounds(uwbDlTDoAMeasurements[i].getActiveRangingRounds()) 602 .setRoundIndex(uwbDlTDoAMeasurements[i].getRoundIndex()) 603 .build(); 604 605 rangingMeasurementBuilder.setRangingMeasurementMetadata( 606 dlTDoAMeasurement.toBundle()); 607 608 rangingMeasurements.add(rangingMeasurementBuilder.build()); 609 } 610 611 rangingReportBuilder.addMeasurements(rangingMeasurements); 612 } 613 return rangingReportBuilder.build(); 614 } 615 computeAngleOfArrivalMeasurement( boolean isAoaAzimuthEnabled, boolean isAoaElevationEnabled, float aoaAzimuth, int aoaAzimuthFom, float aoaElevation, int aoaElevationFom)616 private static AngleOfArrivalMeasurement computeAngleOfArrivalMeasurement( 617 boolean isAoaAzimuthEnabled, boolean isAoaElevationEnabled, float aoaAzimuth, 618 int aoaAzimuthFom, float aoaElevation, int aoaElevationFom) { 619 // Azimuth is required field (and elevation is an optional field), to build the 620 // AngleOfArrivalMeasurement. 621 if (isAoaAzimuthEnabled) { 622 AngleMeasurement azimuthAngleMeasurement = new AngleMeasurement( 623 UwbUtil.degreeToRadian(aoaAzimuth), 0, aoaAzimuthFom / (double) 100); 624 // AngleOfArrivalMeasurement 625 AngleOfArrivalMeasurement.Builder angleOfArrivalMeasurementBuilder = 626 new AngleOfArrivalMeasurement.Builder(azimuthAngleMeasurement); 627 628 // Elevation is optional field, to build the AngleOfArrivalMeasurement. 629 if (isAoaElevationEnabled) { 630 AngleMeasurement altitudeAngleMeasurement = new AngleMeasurement( 631 UwbUtil.degreeToRadian(aoaElevation), 0, aoaElevationFom / (double) 100); 632 angleOfArrivalMeasurementBuilder.setAltitude(altitudeAngleMeasurement); 633 } 634 635 return angleOfArrivalMeasurementBuilder.build(); 636 } 637 638 return null; 639 } 640 buildRangingMeasurement( byte[] macAddress, int rangingStatus, long elapsedRealtimeNanos, int los)641 private static RangingMeasurement.Builder buildRangingMeasurement( 642 byte[] macAddress, int rangingStatus, long elapsedRealtimeNanos, int los) { 643 return new RangingMeasurement.Builder() 644 .setRemoteDeviceAddress(getComputedMacAddress(macAddress)) 645 .setStatus(rangingStatus) 646 .setElapsedRealtimeNanos(elapsedRealtimeNanos) 647 .setLineOfSight(los); 648 } 649 buildDistanceMeasurement(int distance)650 private static DistanceMeasurement buildDistanceMeasurement(int distance) { 651 return new DistanceMeasurement.Builder() 652 .setMeters(distance / (double) 100) 653 .setErrorMeters(0) 654 // TODO: Need to fetch distance FOM once it is added to UCI spec. 655 .setConfidenceLevel(0) 656 .build(); 657 } 658 getComputedMacAddress(byte[] address)659 private static UwbAddress getComputedMacAddress(byte[] address) { 660 if (!SdkLevel.isAtLeastU()) { 661 return UwbAddress.fromBytes(TlvUtil.getReverseBytes(address)); 662 } 663 return UwbAddress.fromBytes(address); 664 } 665 } 666