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 17 package com.android.server.uwb.params; 18 19 import static com.google.uwb.support.ccc.CccParams.RANGE_DATA_NTF_CONFIG_ENABLE_AOA_EDGE_TRIG; 20 import static com.google.uwb.support.ccc.CccParams.RANGE_DATA_NTF_CONFIG_ENABLE_AOA_LEVEL_TRIG; 21 import static com.google.uwb.support.ccc.CccParams.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_EDGE_TRIG; 22 import static com.google.uwb.support.ccc.CccParams.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_LEVEL_TRIG; 23 24 import com.android.server.uwb.UwbInjector; 25 import com.android.server.uwb.config.ConfigParam; 26 import com.android.server.uwb.data.UwbCccConstants; 27 import com.android.server.uwb.data.UwbUciConstants; 28 import com.android.server.uwb.util.UwbUtil; 29 30 import com.google.uwb.support.base.Params; 31 import com.google.uwb.support.base.ProtocolVersion; 32 import com.google.uwb.support.ccc.CccOpenRangingParams; 33 import com.google.uwb.support.ccc.CccParams; 34 import com.google.uwb.support.ccc.CccRangingReconfiguredParams; 35 import com.google.uwb.support.fira.FiraParams; 36 37 public class CccEncoder extends TlvEncoder { 38 private final UwbInjector mUwbInjector; 39 CccEncoder(UwbInjector uwbInjector)40 public CccEncoder(UwbInjector uwbInjector) { 41 mUwbInjector = uwbInjector; 42 } 43 44 @Override getTlvBuffer(Params param, ProtocolVersion protocolVersion)45 public TlvBuffer getTlvBuffer(Params param, ProtocolVersion protocolVersion) { 46 if (param instanceof CccOpenRangingParams) { 47 return getTlvBufferFromCccOpenRangingParams(param); 48 } 49 50 if (param instanceof CccRangingReconfiguredParams) { 51 return getTlvBufferFromCccRangingReconfiguredParams(param); 52 } 53 return null; 54 } 55 getTlvBufferFromCccOpenRangingParams(Params baseParam)56 private TlvBuffer getTlvBufferFromCccOpenRangingParams(Params baseParam) { 57 CccOpenRangingParams params = (CccOpenRangingParams) baseParam; 58 int hoppingConfig = params.getHoppingConfigMode(); 59 int hoppingSequence = params.getHoppingSequence(); 60 61 int hoppingMode = CccParams.HOPPING_CONFIG_MODE_NONE; 62 byte[] protocolVer = params.getProtocolVersion().toBytes(); 63 64 switch (hoppingConfig) { 65 66 case CccParams.HOPPING_CONFIG_MODE_CONTINUOUS: 67 if (hoppingSequence == CccParams.HOPPING_SEQUENCE_DEFAULT) { 68 hoppingMode = UwbCccConstants.HOPPING_CONFIG_MODE_CONTINUOUS_DEFAULT; 69 } else { 70 hoppingMode = UwbCccConstants.HOPPING_CONFIG_MODE_CONTINUOUS_AES; 71 } 72 break; 73 case CccParams.HOPPING_CONFIG_MODE_ADAPTIVE: 74 if (hoppingSequence == CccParams.HOPPING_SEQUENCE_DEFAULT) { 75 hoppingMode = UwbCccConstants.HOPPING_CONFIG_MODE_MODE_ADAPTIVE_DEFAULT; 76 } else { 77 hoppingMode = UwbCccConstants.HOPPING_CONFIG_MODE_MODE_ADAPTIVE_AES; 78 } 79 break; 80 } 81 82 TlvBuffer.Builder tlvBufferBuilder = new TlvBuffer.Builder() 83 .putByte(ConfigParam.DEVICE_TYPE, 84 (byte) UwbUciConstants.DEVICE_TYPE_CONTROLLER) // DEVICE_TYPE 85 .putByte(ConfigParam.STS_CONFIG, 86 (byte) UwbUciConstants.STS_MODE_DYNAMIC) // STS_CONFIG 87 .putByte(ConfigParam.CHANNEL_NUMBER, (byte) params.getChannel()) // CHANNEL_ID 88 .putByte(ConfigParam.NUMBER_OF_CONTROLEES, 89 (byte) params.getNumResponderNodes()) // NUMBER_OF_ANCHORS 90 .putInt(ConfigParam.RANGING_INTERVAL, 91 params.getRanMultiplier() * 96) //RANGING_INTERVAL = RAN_Multiplier * 96 92 .putByte(ConfigParam.DEVICE_ROLE, 93 (byte) UwbUciConstants.RANGING_DEVICE_ROLE_INITIATOR) // DEVICE_ROLE 94 .putByte(ConfigParam.MULTI_NODE_MODE, 95 (byte) FiraParams.MULTI_NODE_MODE_ONE_TO_MANY) // MULTI_NODE_MODE 96 .putByte(ConfigParam.SLOTS_PER_RR, 97 (byte) params.getNumSlotsPerRound()) // SLOTS_PER_RR 98 .putByte(ConfigParam.HOPPING_MODE, (byte) hoppingMode) // HOPPING_MODE 99 .putByteArray(ConfigParam.RANGING_PROTOCOL_VER, 100 ConfigParam.RANGING_PROTOCOL_VER_BYTE_COUNT, 101 new byte[] { protocolVer[1], protocolVer[0] }) // RANGING_PROTOCOL_VER 102 .putShort(ConfigParam.UWB_CONFIG_ID, (short) params.getUwbConfig()) // UWB_CONFIG_ID 103 .putByte(ConfigParam.PULSESHAPE_COMBO, 104 params.getPulseShapeCombo().toBytes()[0]) // PULSESHAPE_COMBO 105 .putShort(ConfigParam.URSK_TTL, (short) 0x2D0) // URSK_TTL 106 // T(Slotk) = N(Chap_per_Slot) * T(Chap) 107 // T(Chap) = 400RSTU 108 // reference : digital key release 3 20.2 MAC Time Grid 109 .putShort(ConfigParam.SLOT_DURATION, 110 (short) (params.getNumChapsPerSlot() * 400)) // SLOT_DURATION 111 .putByte(ConfigParam.PREAMBLE_CODE_INDEX, 112 (byte) params.getSyncCodeIndex()); // PREAMBLE_CODE_INDEX 113 if (params.getStsIndex() != CccParams.STS_INDEX_UNSET) { 114 tlvBufferBuilder.putInt(ConfigParam.STS_INDEX, params.getStsIndex()); 115 } 116 if (params.getAbsoluteInitiationTimeUs() > 0) { 117 tlvBufferBuilder.putLong(ConfigParam.UWB_INITIATION_TIME, 118 params.getAbsoluteInitiationTimeUs()); 119 } else if (params.getInitiationTimeMs() != CccParams.UWB_INITIATION_TIME_MS_UNSET) { 120 tlvBufferBuilder.putLong( 121 ConfigParam.UWB_INITIATION_TIME, params.getInitiationTimeMs()); 122 } 123 if (mUwbInjector.getDeviceConfigFacade().isCccSupportedRangeDataNtfConfig()) { 124 tlvBufferBuilder 125 .putByte(ConfigParam.RANGE_DATA_NTF_CONFIG, 126 (byte) params.getRangeDataNtfConfig()) 127 .putShort(ConfigParam.RANGE_DATA_NTF_PROXIMITY_NEAR, 128 (short) params.getRangeDataNtfProximityNear()) 129 .putShort(ConfigParam.RANGE_DATA_NTF_PROXIMITY_FAR, 130 (short) params.getRangeDataNtfProximityFar()); 131 132 if (hasAoaBoundInRangeDataNtfConfig(params.getRangeDataNtfConfig())) { 133 tlvBufferBuilder.putShortArray(ConfigParam.RANGE_DATA_NTF_AOA_BOUND, new short[] { 134 // TODO (b/235355249): Verify this conversion. This is using AOA value 135 // in UwbTwoWayMeasurement to external RangingMeasurement conversion as 136 // reference. 137 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 138 UwbUtil.radianTodegree( 139 params.getRangeDataNtfAoaAzimuthLower()), 9, 7), 16), 140 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 141 UwbUtil.radianTodegree( 142 params.getRangeDataNtfAoaAzimuthUpper()), 9, 7), 16), 143 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 144 UwbUtil.radianTodegree( 145 params.getRangeDataNtfAoaElevationLower()), 9, 7), 16), 146 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 147 UwbUtil.radianTodegree( 148 params.getRangeDataNtfAoaElevationUpper()), 9, 7), 16), 149 }); 150 } 151 } else { 152 tlvBufferBuilder 153 .putByte(ConfigParam.RANGE_DATA_NTF_CONFIG, 154 (byte) UwbUciConstants.RANGE_DATA_NTF_CONFIG_DISABLE); // RNG_DATA_NTF 155 } 156 return tlvBufferBuilder.build(); 157 } 158 getTlvBufferFromCccRangingReconfiguredParams(Params baseParam)159 private TlvBuffer getTlvBufferFromCccRangingReconfiguredParams(Params baseParam) { 160 CccRangingReconfiguredParams params = (CccRangingReconfiguredParams) baseParam; 161 TlvBuffer.Builder tlvBuilder = new TlvBuffer.Builder(); 162 163 Integer rangeDataNtfConfig = params.getRangeDataNtfConfig(); 164 Integer rangeDataProximityNear = params.getRangeDataProximityNear(); 165 Integer rangeDataProximityFar = params.getRangeDataProximityFar(); 166 Double rangeDataAoaAzimuthLower = params.getRangeDataAoaAzimuthLower(); 167 Double rangeDataAoaAzimuthUpper = params.getRangeDataAoaAzimuthUpper(); 168 Double rangeDataAoaElevationLower = params.getRangeDataAoaElevationLower(); 169 Double rangeDataAoaElevationUpper = params.getRangeDataAoaElevationUpper(); 170 171 if (rangeDataNtfConfig != null) { 172 tlvBuilder.putByte(ConfigParam.RANGE_DATA_NTF_CONFIG, 173 (byte) rangeDataNtfConfig.intValue()); 174 } 175 if (rangeDataProximityNear != null) { 176 tlvBuilder.putShort(ConfigParam.RANGE_DATA_NTF_PROXIMITY_NEAR, 177 (short) rangeDataProximityNear.intValue()); 178 } 179 if (rangeDataProximityFar != null) { 180 tlvBuilder.putShort(ConfigParam.RANGE_DATA_NTF_PROXIMITY_FAR, 181 (short) rangeDataProximityFar.intValue()); 182 } 183 if (rangeDataNtfConfig != null && hasAoaBoundInRangeDataNtfConfig(rangeDataNtfConfig)) { 184 if ((rangeDataAoaAzimuthLower != null && rangeDataAoaAzimuthUpper != null) 185 || (rangeDataAoaElevationLower != null && rangeDataAoaElevationUpper != null)) { 186 rangeDataAoaAzimuthLower = rangeDataAoaAzimuthLower != null 187 ? rangeDataAoaAzimuthLower 188 : FiraParams.RANGE_DATA_NTF_AOA_AZIMUTH_LOWER_DEFAULT; 189 rangeDataAoaAzimuthUpper = rangeDataAoaAzimuthUpper != null 190 ? rangeDataAoaAzimuthUpper 191 : FiraParams.RANGE_DATA_NTF_AOA_AZIMUTH_UPPER_DEFAULT; 192 rangeDataAoaElevationLower = rangeDataAoaElevationLower != null 193 ? rangeDataAoaElevationLower 194 : FiraParams.RANGE_DATA_NTF_AOA_ELEVATION_LOWER_DEFAULT; 195 rangeDataAoaElevationUpper = rangeDataAoaElevationUpper != null 196 ? rangeDataAoaElevationUpper 197 : FiraParams.RANGE_DATA_NTF_AOA_ELEVATION_UPPER_DEFAULT; 198 tlvBuilder.putShortArray(ConfigParam.RANGE_DATA_NTF_AOA_BOUND, new short[]{ 199 // TODO (b/235355249): Verify this conversion. This is using AOA value 200 // in UwbTwoWayMeasurement to external RangingMeasurement conversion as 201 // reference. 202 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 203 UwbUtil.radianTodegree( 204 rangeDataAoaAzimuthLower.floatValue()), 9, 7), 16), 205 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 206 UwbUtil.radianTodegree( 207 rangeDataAoaAzimuthUpper.floatValue()), 9, 7), 16), 208 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 209 UwbUtil.radianTodegree( 210 rangeDataAoaElevationLower.floatValue()), 9, 7), 16), 211 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 212 UwbUtil.radianTodegree( 213 rangeDataAoaElevationUpper.floatValue()), 9, 7), 16), 214 }); 215 } 216 } 217 return tlvBuilder.build(); 218 } 219 hasAoaBoundInRangeDataNtfConfig(int rangeDataNtfConfig)220 private static boolean hasAoaBoundInRangeDataNtfConfig(int rangeDataNtfConfig) { 221 return rangeDataNtfConfig == RANGE_DATA_NTF_CONFIG_ENABLE_AOA_LEVEL_TRIG 222 || rangeDataNtfConfig == RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_LEVEL_TRIG 223 || rangeDataNtfConfig == RANGE_DATA_NTF_CONFIG_ENABLE_AOA_EDGE_TRIG 224 || rangeDataNtfConfig == RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_EDGE_TRIG; 225 } 226 } 227