• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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