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