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