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.data;
17 
18 import android.uwb.RangingMeasurement;
19 
20 import com.android.server.uwb.util.UwbUtil;
21 
22 public class UwbTwoWayMeasurement {
23     public byte[] mMacAddress;
24     public int mStatus;
25     public int mNLoS;
26     public int mDistance;
27     public float mAoaAzimuth;
28     public int mAoaAzimuthFom;
29     public float mAoaElevation;
30     public int mAoaElevationFom;
31     public float mAoaDestAzimuth;
32     public int mAoaDestAzimuthFom;
33     public float mAoaDestElevation;
34     public int mAoaDestElevationFom;
35     public int mSlotIndex;
36     public int mRssi;
37 
UwbTwoWayMeasurement(byte[] macAddress, int status, int nLoS, int distance, int aoaAzimuth, int aoaAzimuthFom, int aoaElevation, int aoaElevationFom, int aoaDestAzimuth, int aoaDestAzimuthFom, int aoaDestElevation, int aoaDestElevationFom, int slotIndex, int rssiHalfDbmAbs)38     public UwbTwoWayMeasurement(byte[] macAddress, int status, int nLoS, int distance,
39             int aoaAzimuth, int aoaAzimuthFom, int aoaElevation,
40             int aoaElevationFom, int aoaDestAzimuth, int aoaDestAzimuthFom,
41             int aoaDestElevation, int aoaDestElevationFom, int slotIndex, int rssiHalfDbmAbs) {
42 
43         this.mMacAddress = macAddress;
44         this.mStatus = status;
45         this.mNLoS = nLoS;
46         // Set distance to negative value if the status code indicates negative distance
47         this.mDistance = status == UwbUciConstants.STATUS_CODE_OK_NEGATIVE_DISTANCE_REPORT
48                 ? -distance : distance;
49         this.mAoaAzimuth = toFloatFromQFormat(aoaAzimuth);
50         this.mAoaAzimuthFom = aoaAzimuthFom;
51         this.mAoaElevation = toFloatFromQFormat(aoaElevation);
52         this.mAoaElevationFom = aoaElevationFom;
53         this.mAoaDestAzimuth = toFloatFromQFormat(aoaDestAzimuth);
54         this.mAoaDestAzimuthFom = aoaDestAzimuthFom;
55         this.mAoaDestElevation = toFloatFromQFormat(aoaDestElevation);
56         this.mAoaDestElevationFom = aoaDestElevationFom;
57         this.mSlotIndex = slotIndex;
58         /*
59          * According to FiRa UCI Generic Technical Specification v2.0.0,
60          * decode the rssi value in dBm format where the abs value was encoded in FP Q7.1 format.
61          * Just need to divide this number by two and take the negative value.
62          * If the reported RSSI is lower than RSSI_MIN, set it to RSSI_MIN to avoid exceptions.
63          */
64         this.mRssi = Math.max(-rssiHalfDbmAbs / 2, RangingMeasurement.RSSI_MIN);
65     }
66 
getMacAddress()67     public byte[] getMacAddress() {
68         return mMacAddress;
69     }
70 
getRangingStatus()71     public int getRangingStatus() {
72         return mStatus;
73     }
74 
getNLoS()75     public int getNLoS() {
76         return mNLoS;
77     }
78 
getDistance()79     public int getDistance() {
80         return mDistance;
81     }
82 
getAoaAzimuth()83     public float getAoaAzimuth() {
84         return mAoaAzimuth;
85     }
86 
getAoaAzimuthFom()87     public int getAoaAzimuthFom() {
88         return mAoaAzimuthFom;
89     }
90 
getAoaElevation()91     public float getAoaElevation() {
92         return mAoaElevation;
93     }
94 
getAoaElevationFom()95     public int getAoaElevationFom() {
96         return mAoaElevationFom;
97     }
98 
getAoaDestAzimuth()99     public float getAoaDestAzimuth() {
100         return mAoaDestAzimuth;
101     }
102 
getAoaDestAzimuthFom()103     public int getAoaDestAzimuthFom() {
104         return mAoaDestAzimuthFom;
105     }
106 
getAoaDestElevation()107     public float getAoaDestElevation() {
108         return mAoaDestElevation;
109     }
110 
getAoaDestElevationFom()111     public int getAoaDestElevationFom() {
112         return mAoaDestElevationFom;
113     }
114 
getSlotIndex()115     public int getSlotIndex() {
116         return mSlotIndex;
117     }
getRssi()118     public int getRssi() {
119         return mRssi;
120     }
121 
isStatusCodeOk()122     public boolean isStatusCodeOk() {
123         return mStatus == UwbUciConstants.STATUS_CODE_OK
124                 || mStatus == UwbUciConstants.STATUS_CODE_OK_NEGATIVE_DISTANCE_REPORT;
125     }
126 
127     /**
128      * Convert the UCI status code to success, out of range, or unknown error
129      */
convertStatusCode()130     public int convertStatusCode() {
131         switch (mStatus) {
132             case UwbUciConstants.STATUS_CODE_OK:
133             case UwbUciConstants.STATUS_CODE_OK_NEGATIVE_DISTANCE_REPORT:
134                 return RangingMeasurement.RANGING_STATUS_SUCCESS;
135             case UwbUciConstants.STATUS_CODE_INVALID_RANGE:
136                 return RangingMeasurement.RANGING_STATUS_FAILURE_OUT_OF_RANGE;
137             default:
138                 return RangingMeasurement.RANGING_STATUS_FAILURE_UNKNOWN_ERROR;
139         }
140     }
141 
toFloatFromQFormat(int value)142     private float toFloatFromQFormat(int value) {
143         return UwbUtil.convertQFormatToFloat(UwbUtil.twos_compliment(value, 16),
144                 9, 7);
145     }
146 
toString()147     public String toString() {
148         return "UwbTwoWayMeasurement { "
149                 + " MacAddress = " + UwbUtil.toHexString(mMacAddress)
150                 + ", RangingStatus = " + mStatus
151                 + ", NLoS = " + mNLoS
152                 + ", Distance = " + mDistance
153                 + ", AoaAzimuth = " + mAoaAzimuth
154                 + ", AoaAzimuthFom = " + mAoaAzimuthFom
155                 + ", AoaElevation = " + mAoaElevation
156                 + ", AoaElevationFom = " + mAoaElevationFom
157                 + ", AoaDestAzimuth = " + mAoaDestAzimuth
158                 + ", AoaDestAzimuthFom = " + mAoaDestAzimuthFom
159                 + ", AoaDestElevation = " + mAoaDestElevation
160                 + ", AoaDestElevationFom = " + mAoaDestElevationFom
161                 + ", SlotIndex = 0x" + UwbUtil.toHexString(mSlotIndex)
162                 + ", RSSI = " + mRssi
163                 + '}';
164     }
165 }
166