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