• 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 
17 package com.android.server.uwb.params;
18 
19 import static com.android.server.uwb.config.CapabilityParam.AOA_AZIMUTH_180;
20 import static com.android.server.uwb.config.CapabilityParam.AOA_AZIMUTH_90;
21 import static com.android.server.uwb.config.CapabilityParam.AOA_ELEVATION;
22 import static com.android.server.uwb.config.CapabilityParam.AOA_FOM;
23 import static com.android.server.uwb.config.CapabilityParam.AOA_RESULT_REQ_INTERLEAVING;
24 import static com.android.server.uwb.config.CapabilityParam.BLOCK_STRIDING;
25 import static com.android.server.uwb.config.CapabilityParam.CC_CONSTRAINT_LENGTH_K3;
26 import static com.android.server.uwb.config.CapabilityParam.CC_CONSTRAINT_LENGTH_K7;
27 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_10;
28 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_12;
29 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_13;
30 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_14;
31 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_5;
32 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_6;
33 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_8;
34 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_9;
35 import static com.android.server.uwb.config.CapabilityParam.DS_TWR_DEFERRED;
36 import static com.android.server.uwb.config.CapabilityParam.DS_TWR_NON_DEFERRED;
37 import static com.android.server.uwb.config.CapabilityParam.DYNAMIC_STS;
38 import static com.android.server.uwb.config.CapabilityParam.DYNAMIC_STS_RESPONDER_SPECIFIC_SUBSESSION_KEY;
39 import static com.android.server.uwb.config.CapabilityParam.INITIATOR;
40 import static com.android.server.uwb.config.CapabilityParam.MANY_TO_MANY;
41 import static com.android.server.uwb.config.CapabilityParam.ONE_TO_MANY;
42 import static com.android.server.uwb.config.CapabilityParam.RESPONDER;
43 import static com.android.server.uwb.config.CapabilityParam.SP0;
44 import static com.android.server.uwb.config.CapabilityParam.SP1;
45 import static com.android.server.uwb.config.CapabilityParam.SP3;
46 import static com.android.server.uwb.config.CapabilityParam.SS_TWR_DEFERRED;
47 import static com.android.server.uwb.config.CapabilityParam.SS_TWR_NON_DEFERRED;
48 import static com.android.server.uwb.config.CapabilityParam.STATIC_STS;
49 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_AOA;
50 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_AOA_RESULT_REQ_INTERLEAVING;
51 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_BLOCK_STRIDING;
52 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_BPRF_PARAMETER_SETS;
53 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_CC_CONSTRAINT_LENGTH;
54 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_CHANNELS;
55 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_DEVICE_ROLES;
56 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_EXTENDED_MAC_ADDRESS;
57 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_FIRA_MAC_VERSION_RANGE;
58 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_FIRA_PHY_VERSION_RANGE;
59 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_HPRF_PARAMETER_SETS;
60 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MULTI_NODE_MODES;
61 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RANGING_METHOD;
62 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RFRAME_CONFIG;
63 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_STS_CONFIG;
64 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_UWB_INITIATION_TIME;
65 import static com.android.server.uwb.config.CapabilityParam.UNICAST;
66 import static com.android.server.uwb.config.CapabilityParam.UWB_INITIATION_TIME;
67 
68 import com.google.uwb.support.base.FlagEnum;
69 import com.google.uwb.support.base.Params;
70 import com.google.uwb.support.fira.FiraParams;
71 import com.google.uwb.support.fira.FiraParams.BprfParameterSetCapabilityFlag;
72 import com.google.uwb.support.fira.FiraParams.DeviceRoleCapabilityFlag;
73 import com.google.uwb.support.fira.FiraParams.HprfParameterSetCapabilityFlag;
74 import com.google.uwb.support.fira.FiraParams.MultiNodeCapabilityFlag;
75 import com.google.uwb.support.fira.FiraParams.PsduDataRateCapabilityFlag;
76 import com.google.uwb.support.fira.FiraParams.RangingRoundCapabilityFlag;
77 import com.google.uwb.support.fira.FiraParams.RframeCapabilityFlag;
78 import com.google.uwb.support.fira.FiraParams.StsCapabilityFlag;
79 import com.google.uwb.support.fira.FiraProtocolVersion;
80 import com.google.uwb.support.fira.FiraSpecificationParams;
81 
82 import java.math.BigInteger;
83 import java.util.ArrayList;
84 import java.util.EnumSet;
85 import java.util.List;
86 import java.util.stream.IntStream;
87 
88 public class FiraDecoder extends TlvDecoder {
89     @Override
getParams(TlvDecoderBuffer tlvs, Class<T> paramType)90     public <T extends Params> T getParams(TlvDecoderBuffer tlvs, Class<T> paramType) {
91         if (FiraSpecificationParams.class.equals(paramType)) {
92             return (T) getFiraSpecificationParamsFromTlvBuffer(tlvs);
93         }
94         return null;
95     }
96 
isBitSet(int flags, int mask)97     private static boolean isBitSet(int flags, int mask) {
98         return (flags & mask) != 0;
99     }
100 
getFiraSpecificationParamsFromTlvBuffer(TlvDecoderBuffer tlvs)101     private FiraSpecificationParams getFiraSpecificationParamsFromTlvBuffer(TlvDecoderBuffer tlvs) {
102         FiraSpecificationParams.Builder builder = new FiraSpecificationParams.Builder();
103         byte[] phyVersions = tlvs.getByteArray(SUPPORTED_FIRA_PHY_VERSION_RANGE);
104         builder.setMinPhyVersionSupported(FiraProtocolVersion.fromBytes(phyVersions, 0));
105         builder.setMaxPhyVersionSupported(FiraProtocolVersion.fromBytes(phyVersions, 2));
106         byte[] macVersions = tlvs.getByteArray(SUPPORTED_FIRA_MAC_VERSION_RANGE);
107         builder.setMinMacVersionSupported(FiraProtocolVersion.fromBytes(macVersions, 0));
108         builder.setMaxMacVersionSupported(FiraProtocolVersion.fromBytes(macVersions, 2));
109 
110         byte deviceRolesUci = tlvs.getByte(SUPPORTED_DEVICE_ROLES);
111         EnumSet<DeviceRoleCapabilityFlag> deviceRoles =
112                 EnumSet.noneOf(DeviceRoleCapabilityFlag.class);
113         if (isBitSet(deviceRolesUci, INITIATOR)) {
114             // This assumes both controller + controlee is supported.
115             deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLLER_INITIATOR_SUPPORT);
116             deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLEE_INITIATOR_SUPPORT);
117         }
118         if (isBitSet(deviceRolesUci, RESPONDER)) {
119             // This assumes both controller + controlee is supported.
120             deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLLER_RESPONDER_SUPPORT);
121             deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLEE_RESPONDER_SUPPORT);
122         }
123         builder.setDeviceRoleCapabilities(deviceRoles);
124 
125         byte rangingMethodUci = tlvs.getByte(SUPPORTED_RANGING_METHOD);
126         EnumSet<RangingRoundCapabilityFlag> rangingRoundFlag = EnumSet.noneOf(
127                 RangingRoundCapabilityFlag.class);
128         if (isBitSet(rangingMethodUci, DS_TWR_DEFERRED)) {
129             rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_DS_TWR_SUPPORT);
130         }
131         if (isBitSet(rangingMethodUci, SS_TWR_DEFERRED)) {
132             rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_SS_TWR_SUPPORT);
133         }
134         builder.setRangingRoundCapabilities(rangingRoundFlag);
135 
136         // TODO(b/209053358): This does not align with UCI spec.
137         if (isBitSet(rangingMethodUci, DS_TWR_NON_DEFERRED)
138                 || isBitSet(rangingMethodUci, SS_TWR_NON_DEFERRED)) {
139             builder.hasNonDeferredModeSupport(true);
140         }
141 
142         byte stsConfigUci = tlvs.getByte(SUPPORTED_STS_CONFIG);
143         EnumSet<StsCapabilityFlag> stsCapabilityFlag = EnumSet.noneOf(StsCapabilityFlag.class);
144         if (isBitSet(stsConfigUci, STATIC_STS)) {
145             stsCapabilityFlag.add(StsCapabilityFlag.HAS_STATIC_STS_SUPPORT);
146         }
147         if (isBitSet(stsConfigUci, DYNAMIC_STS)) {
148             stsCapabilityFlag.add(StsCapabilityFlag.HAS_DYNAMIC_STS_SUPPORT);
149         }
150         if (isBitSet(stsConfigUci, DYNAMIC_STS_RESPONDER_SPECIFIC_SUBSESSION_KEY)) {
151             stsCapabilityFlag.add(
152                     StsCapabilityFlag.HAS_DYNAMIC_STS_INDIVIDUAL_CONTROLEE_KEY_SUPPORT);
153         }
154         builder.setStsCapabilities(stsCapabilityFlag);
155 
156         byte multiNodeUci = tlvs.getByte(SUPPORTED_MULTI_NODE_MODES);
157         EnumSet<MultiNodeCapabilityFlag> multiNodeFlag =
158                 EnumSet.noneOf(MultiNodeCapabilityFlag.class);
159         if (isBitSet(multiNodeUci, UNICAST)) {
160             multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_UNICAST_SUPPORT);
161         }
162         if (isBitSet(multiNodeUci, ONE_TO_MANY)) {
163             multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_ONE_TO_MANY_SUPPORT);
164         }
165         if (isBitSet(multiNodeUci, MANY_TO_MANY)) {
166             multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_MANY_TO_MANY_SUPPORT);
167         }
168         builder.setMultiNodeCapabilities(multiNodeFlag);
169 
170         byte blockStridingUci = tlvs.getByte(SUPPORTED_BLOCK_STRIDING);
171         if (isBitSet(blockStridingUci, BLOCK_STRIDING)) {
172             builder.hasBlockStridingSupport(true);
173         }
174 
175         byte initiationTimeUci = tlvs.getByte(SUPPORTED_UWB_INITIATION_TIME);
176         if (isBitSet(initiationTimeUci, UWB_INITIATION_TIME)) {
177             builder.hasInitiationTimeSupport(true);
178         }
179 
180         byte channelsUci = tlvs.getByte(SUPPORTED_CHANNELS);
181         List<Integer> channels = new ArrayList<>();
182         if (isBitSet(channelsUci, CHANNEL_5)) {
183             channels.add(5);
184         }
185         if (isBitSet(channelsUci, CHANNEL_6)) {
186             channels.add(6);
187         }
188         if (isBitSet(channelsUci, CHANNEL_8)) {
189             channels.add(8);
190         }
191         if (isBitSet(channelsUci, CHANNEL_9)) {
192             channels.add(9);
193         }
194         if (isBitSet(channelsUci, CHANNEL_10)) {
195             channels.add(10);
196         }
197         if (isBitSet(channelsUci, CHANNEL_12)) {
198             channels.add(12);
199         }
200         if (isBitSet(channelsUci, CHANNEL_13)) {
201             channels.add(13);
202         }
203         if (isBitSet(channelsUci, CHANNEL_14)) {
204             channels.add(14);
205         }
206         builder.setSupportedChannels(channels);
207 
208         byte rframeConfigUci = tlvs.getByte(SUPPORTED_RFRAME_CONFIG);
209         EnumSet<RframeCapabilityFlag> rframeConfigFlag =
210                 EnumSet.noneOf(RframeCapabilityFlag.class);
211         if (isBitSet(rframeConfigUci, SP0)) {
212             rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP0_RFRAME_SUPPORT);
213         }
214         if (isBitSet(rframeConfigUci, SP1)) {
215             rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP1_RFRAME_SUPPORT);
216         }
217         if (isBitSet(rframeConfigUci, SP3)) {
218             rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP3_RFRAME_SUPPORT);
219         }
220         builder.setRframeCapabilities(rframeConfigFlag);
221 
222         byte bprfSets = tlvs.getByte(SUPPORTED_BPRF_PARAMETER_SETS);
223         int bprfSetsValue = Integer.valueOf(bprfSets);
224         EnumSet<BprfParameterSetCapabilityFlag> bprfFlag;
225         bprfFlag = FlagEnum.toEnumSet(bprfSetsValue, BprfParameterSetCapabilityFlag.values());
226         builder.setBprfParameterSetCapabilities(bprfFlag);
227 
228         byte[] hprfSets = tlvs.getByteArray(SUPPORTED_HPRF_PARAMETER_SETS);
229         // Extend the 5 bytes from HAL to 8 bytes for long.
230         long hprfSetsValue = new BigInteger(hprfSets).longValue();
231         EnumSet<HprfParameterSetCapabilityFlag> hprfFlag;
232         hprfFlag = FlagEnum.longToEnumSet(
233                 hprfSetsValue, HprfParameterSetCapabilityFlag.values());
234         builder.setHprfParameterSetCapabilities(hprfFlag);
235 
236         EnumSet<FiraParams.PrfCapabilityFlag> prfFlag =
237                 EnumSet.noneOf(FiraParams.PrfCapabilityFlag.class);
238         boolean hasBprfSupport = bprfSets != 0;
239         if (hasBprfSupport) {
240             prfFlag.add(FiraParams.PrfCapabilityFlag.HAS_BPRF_SUPPORT);
241         }
242         boolean hasHprfSupport =
243                 IntStream.range(0, hprfSets.length).parallel().anyMatch(i -> hprfSets[i] != 0);
244         if (hasHprfSupport) {
245             prfFlag.add(FiraParams.PrfCapabilityFlag.HAS_HPRF_SUPPORT);
246         }
247         builder.setPrfCapabilities(prfFlag);
248 
249         byte ccConstraintUci = tlvs.getByte(SUPPORTED_CC_CONSTRAINT_LENGTH);
250         EnumSet<PsduDataRateCapabilityFlag> psduRateFlag =
251                 EnumSet.noneOf(PsduDataRateCapabilityFlag.class);
252         if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K3) && hasBprfSupport) {
253             psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_6M81_SUPPORT);
254         }
255         if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K7) && hasBprfSupport) {
256             psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_7M80_SUPPORT);
257         }
258         if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K3) && hasHprfSupport) {
259             psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_27M2_SUPPORT);
260         }
261         if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K7) && hasHprfSupport) {
262             psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_31M2_SUPPORT);
263         }
264         builder.setPsduDataRateCapabilities(psduRateFlag);
265 
266         byte aoaUci = tlvs.getByte(SUPPORTED_AOA);
267         EnumSet<FiraParams.AoaCapabilityFlag> aoaFlag =
268                 EnumSet.noneOf(FiraParams.AoaCapabilityFlag.class);
269         if (isBitSet(aoaUci, AOA_AZIMUTH_90)) {
270             aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_AZIMUTH_SUPPORT);
271         }
272         if (isBitSet(aoaUci, AOA_AZIMUTH_180)) {
273             aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_FULL_AZIMUTH_SUPPORT);
274         }
275         if (isBitSet(aoaUci, AOA_ELEVATION)) {
276             aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_ELEVATION_SUPPORT);
277         }
278         if (isBitSet(aoaUci, AOA_FOM)) {
279             aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_FOM_SUPPORT);
280         }
281         byte aoaInterleavingUci = tlvs.getByte(SUPPORTED_AOA_RESULT_REQ_INTERLEAVING);
282         if (isBitSet(aoaInterleavingUci, AOA_RESULT_REQ_INTERLEAVING)) {
283             aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_INTERLEAVING_SUPPORT);
284         }
285         builder.setAoaCapabilities(aoaFlag);
286 
287         // TODO(b/209053358): This is not present in the FiraSpecificationParams.
288         byte extendedMacUci = tlvs.getByte(SUPPORTED_EXTENDED_MAC_ADDRESS);
289         return builder.build();
290     }
291 }
292