1 /* 2 * Copyright (C) 2024 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.aliro.AliroParams.RANGE_DATA_NTF_CONFIG_ENABLE_AOA_EDGE_TRIG; 20 import static com.google.uwb.support.aliro.AliroParams.RANGE_DATA_NTF_CONFIG_ENABLE_AOA_LEVEL_TRIG; 21 import static com.google.uwb.support.aliro.AliroParams.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_EDGE_TRIG; 22 import static com.google.uwb.support.aliro.AliroParams.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.UwbAliroConstants; 27 import com.android.server.uwb.data.UwbUciConstants; 28 import com.android.server.uwb.util.UwbUtil; 29 30 import com.google.uwb.support.aliro.AliroOpenRangingParams; 31 import com.google.uwb.support.aliro.AliroParams; 32 import com.google.uwb.support.base.Params; 33 import com.google.uwb.support.base.ProtocolVersion; 34 import com.google.uwb.support.fira.FiraParams; 35 36 /** 37 * Encoder for Aliro UCI SET_APP_CONFIG CMD parameters. 38 * 39 * This started out as a copy of CccEncoder, and encodes all of the same parameters. 40 */ 41 public class AliroEncoder extends TlvEncoder { 42 private final UwbInjector mUwbInjector; 43 AliroEncoder(UwbInjector uwbInjector)44 public AliroEncoder(UwbInjector uwbInjector) { 45 mUwbInjector = uwbInjector; 46 } 47 48 @Override getTlvBuffer(Params param, ProtocolVersion protocolVersion)49 public TlvBuffer getTlvBuffer(Params param, ProtocolVersion protocolVersion) { 50 if (param instanceof AliroOpenRangingParams) { 51 return getTlvBufferFromAliroOpenRangingParams(param); 52 } 53 return null; 54 } 55 getTlvBufferFromAliroOpenRangingParams(Params baseParam)56 private TlvBuffer getTlvBufferFromAliroOpenRangingParams(Params baseParam) { 57 AliroOpenRangingParams params = (AliroOpenRangingParams) baseParam; 58 int hoppingConfig = params.getHoppingConfigMode(); 59 int hoppingSequence = params.getHoppingSequence(); 60 boolean isFiraExtensionSupported = 61 mUwbInjector.getDeviceConfigFacade().isFiraSupportedExtensionForCCC(); 62 int hoppingMode = isFiraExtensionSupported 63 ? UwbAliroConstants.ALIRO_EXTENSION_HOPPING_CONFIG_MODE_NONE : 64 AliroParams.HOPPING_CONFIG_MODE_NONE; 65 byte[] protocolVer = params.getProtocolVersion().toBytes(); 66 67 switch (hoppingConfig) { 68 69 case AliroParams.HOPPING_CONFIG_MODE_CONTINUOUS: 70 if (hoppingSequence == AliroParams.HOPPING_SEQUENCE_DEFAULT) { 71 hoppingMode = 72 isFiraExtensionSupported 73 ? UwbAliroConstants 74 .ALIRO_EXTENSION_HOPPING_CONFIG_MODE_CONTINUOUS_DEFAULT : 75 UwbAliroConstants.HOPPING_CONFIG_MODE_CONTINUOUS_DEFAULT; 76 77 } else { 78 hoppingMode = 79 isFiraExtensionSupported 80 ? UwbAliroConstants 81 .ALIRO_EXTENSION_HOPPING_CONFIG_MODE_CONTINUOUS_AES : 82 UwbAliroConstants.HOPPING_CONFIG_MODE_CONTINUOUS_AES; 83 } 84 break; 85 case AliroParams.HOPPING_CONFIG_MODE_ADAPTIVE: 86 if (hoppingSequence == AliroParams.HOPPING_SEQUENCE_DEFAULT) { 87 hoppingMode = 88 isFiraExtensionSupported 89 ? UwbAliroConstants 90 .ALIRO_EXTENSION_HOPPING_CONFIG_MODE_ADAPTIVE_DEFAULT : 91 UwbAliroConstants.HOPPING_CONFIG_MODE_ADAPTIVE_DEFAULT; 92 } else { 93 hoppingMode = 94 isFiraExtensionSupported 95 ? UwbAliroConstants 96 .ALIRO_EXTENSION_HOPPING_CONFIG_MODE_ADAPTIVE_AES : 97 UwbAliroConstants.HOPPING_CONFIG_MODE_ADAPTIVE_AES; 98 } 99 break; 100 } 101 102 TlvBuffer.Builder tlvBufferBuilder = new TlvBuffer.Builder() 103 .putByte(ConfigParam.DEVICE_TYPE, 104 mUwbInjector.getDeviceConfigFacade().isFiraSupportedExtensionForCCC() 105 ? (byte) UwbUciConstants.CCC_DEVICE_TYPE_CONTROLLER : 106 (byte) UwbUciConstants.DEVICE_TYPE_CONTROLLER) // DEVICE_TYPE 107 .putByte(ConfigParam.STS_CONFIG, 108 (byte) UwbUciConstants.STS_MODE_DYNAMIC) // STS_CONFIG 109 .putByte(ConfigParam.CHANNEL_NUMBER, (byte) params.getChannel()) // CHANNEL_ID 110 .putByte(ConfigParam.NUMBER_OF_CONTROLEES, 111 (byte) params.getNumResponderNodes()) // NUMBER_OF_ANCHORS 112 .putInt(ConfigParam.RANGING_INTERVAL, 113 params.getRanMultiplier() * 96) //RANGING_INTERVAL = RAN_Multiplier * 96 114 .putByte(ConfigParam.DEVICE_ROLE, 115 (byte) UwbUciConstants.RANGING_DEVICE_ROLE_INITIATOR) // DEVICE_ROLE 116 .putByte(ConfigParam.MULTI_NODE_MODE, 117 (byte) FiraParams.MULTI_NODE_MODE_ONE_TO_MANY) // MULTI_NODE_MODE 118 .putByte(ConfigParam.SLOTS_PER_RR, 119 (byte) params.getNumSlotsPerRound()) // SLOTS_PER_RR 120 .putByte(ConfigParam.HOPPING_MODE, (byte) hoppingMode) // HOPPING_MODE 121 .putByteArray(ConfigParam.RANGING_PROTOCOL_VER, 122 ConfigParam.RANGING_PROTOCOL_VER_BYTE_COUNT, 123 new byte[] { protocolVer[1], protocolVer[0] }) // RANGING_PROTOCOL_VER 124 .putShort(ConfigParam.UWB_CONFIG_ID, (short) params.getUwbConfig()) // UWB_CONFIG_ID 125 .putByte(ConfigParam.PULSESHAPE_COMBO, 126 params.getPulseShapeCombo().toBytes()[0]) // PULSESHAPE_COMBO 127 .putShort(ConfigParam.URSK_TTL, (short) 0x2D0) // URSK_TTL 128 // T(Slotk) = N(Chap_per_Slot) * T(Chap) 129 // T(Chap) = 400RSTU 130 // reference : digital key release 3 20.2 MAC Time Grid 131 .putShort(ConfigParam.SLOT_DURATION, 132 (short) (params.getNumChapsPerSlot() * 400)) // SLOT_DURATION 133 .putByte(ConfigParam.PREAMBLE_CODE_INDEX, 134 (byte) params.getSyncCodeIndex()) // PREAMBLE_CODE_INDEX 135 .putByte(ConfigParam.ALIRO_MAC_MODE, 136 (byte) (params.getMacModeRound() << 6 137 | params.getMacModeOffset())); // MAC_MODE 138 139 byte[] sessionKey = params.getSessionKey(); 140 if (sessionKey != null) { 141 tlvBufferBuilder.putByteArray(ConfigParam.SESSION_KEY, sessionKey); 142 } 143 144 if (params.getStsIndex() != AliroParams.STS_INDEX_UNSET) { 145 tlvBufferBuilder.putInt(ConfigParam.STS_INDEX, params.getStsIndex()); 146 } 147 if (params.getHoppingConfigMode() != AliroParams.HOPPING_CONFIG_MODE_NONE 148 && params.getHopModeKey() != AliroParams.HOP_MODE_KEY_UNSET) { 149 tlvBufferBuilder.putInt(ConfigParam.HOP_MODE_KEY, params.getHopModeKey()); 150 } 151 if (params.getAbsoluteInitiationTimeUs() > 0) { 152 tlvBufferBuilder.putLong(ConfigParam.UWB_INITIATION_TIME, 153 params.getAbsoluteInitiationTimeUs()); 154 } else if (params.getInitiationTimeMs() != AliroParams.UWB_INITIATION_TIME_MS_UNSET) { 155 tlvBufferBuilder.putLong( 156 ConfigParam.UWB_INITIATION_TIME, params.getInitiationTimeMs()); 157 } 158 // We use the same CCC DeviceConfigFacade flag for Aliro. 159 if (mUwbInjector.getDeviceConfigFacade().isCccSupportedRangeDataNtfConfig()) { 160 tlvBufferBuilder 161 .putByte(ConfigParam.RANGE_DATA_NTF_CONFIG, 162 (byte) params.getRangeDataNtfConfig()) 163 .putShort(ConfigParam.RANGE_DATA_NTF_PROXIMITY_NEAR, 164 (short) params.getRangeDataNtfProximityNear()) 165 .putShort(ConfigParam.RANGE_DATA_NTF_PROXIMITY_FAR, 166 (short) params.getRangeDataNtfProximityFar()); 167 168 if (hasAoaBoundInRangeDataNtfConfig(params.getRangeDataNtfConfig())) { 169 tlvBufferBuilder.putShortArray(ConfigParam.RANGE_DATA_NTF_AOA_BOUND, new short[] { 170 // TODO (b/235355249): Verify this conversion. This is using AOA value 171 // in UwbTwoWayMeasurement to external RangingMeasurement conversion as 172 // reference. 173 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 174 UwbUtil.radianTodegree( 175 params.getRangeDataNtfAoaAzimuthLower()), 9, 7), 16), 176 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 177 UwbUtil.radianTodegree( 178 params.getRangeDataNtfAoaAzimuthUpper()), 9, 7), 16), 179 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 180 UwbUtil.radianTodegree( 181 params.getRangeDataNtfAoaElevationLower()), 9, 7), 16), 182 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 183 UwbUtil.radianTodegree( 184 params.getRangeDataNtfAoaElevationUpper()), 9, 7), 16), 185 }); 186 } 187 } else { 188 tlvBufferBuilder 189 .putByte(ConfigParam.RANGE_DATA_NTF_CONFIG, 190 (byte) UwbUciConstants.RANGE_DATA_NTF_CONFIG_DISABLE); // RNG_DATA_NTF 191 } 192 return tlvBufferBuilder.build(); 193 } 194 hasAoaBoundInRangeDataNtfConfig(int rangeDataNtfConfig)195 private static boolean hasAoaBoundInRangeDataNtfConfig(int rangeDataNtfConfig) { 196 return rangeDataNtfConfig == RANGE_DATA_NTF_CONFIG_ENABLE_AOA_LEVEL_TRIG 197 || rangeDataNtfConfig == RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_LEVEL_TRIG 198 || rangeDataNtfConfig == RANGE_DATA_NTF_CONFIG_ENABLE_AOA_EDGE_TRIG 199 || rangeDataNtfConfig == RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_EDGE_TRIG; 200 } 201 } 202