• 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.CCC_CHANNEL_5;
20 import static com.android.server.uwb.config.CapabilityParam.CCC_CHANNEL_9;
21 import static com.android.server.uwb.config.CapabilityParam.CCC_CHAPS_PER_SLOT_12;
22 import static com.android.server.uwb.config.CapabilityParam.CCC_CHAPS_PER_SLOT_24;
23 import static com.android.server.uwb.config.CapabilityParam.CCC_CHAPS_PER_SLOT_3;
24 import static com.android.server.uwb.config.CapabilityParam.CCC_CHAPS_PER_SLOT_4;
25 import static com.android.server.uwb.config.CapabilityParam.CCC_CHAPS_PER_SLOT_6;
26 import static com.android.server.uwb.config.CapabilityParam.CCC_CHAPS_PER_SLOT_8;
27 import static com.android.server.uwb.config.CapabilityParam.CCC_CHAPS_PER_SLOT_9;
28 import static com.android.server.uwb.config.CapabilityParam.CCC_HOPPING_CONFIG_MODE_ADAPTIVE;
29 import static com.android.server.uwb.config.CapabilityParam.CCC_HOPPING_CONFIG_MODE_CONTINUOUS;
30 import static com.android.server.uwb.config.CapabilityParam.CCC_HOPPING_CONFIG_MODE_NONE;
31 import static com.android.server.uwb.config.CapabilityParam.CCC_HOPPING_SEQUENCE_AES;
32 import static com.android.server.uwb.config.CapabilityParam.CCC_HOPPING_SEQUENCE_DEFAULT;
33 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_CHANNELS;
34 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_CHAPS_PER_SLOT;
35 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_HOPPING_CONFIG_MODES_AND_SEQUENCES;
36 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_MAX_RANGING_SESSION_NUMBER;
37 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_MIN_UWB_INITIATION_TIME_MS;
38 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_PULSE_SHAPE_COMBOS;
39 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_RAN_MULTIPLIER;
40 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_SYNC_CODES;
41 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_UWB_CONFIGS;
42 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_VERSIONS;
43 
44 import static com.google.uwb.support.ccc.CccParams.CHAPS_PER_SLOT_12;
45 import static com.google.uwb.support.ccc.CccParams.CHAPS_PER_SLOT_24;
46 import static com.google.uwb.support.ccc.CccParams.CHAPS_PER_SLOT_3;
47 import static com.google.uwb.support.ccc.CccParams.CHAPS_PER_SLOT_4;
48 import static com.google.uwb.support.ccc.CccParams.CHAPS_PER_SLOT_6;
49 import static com.google.uwb.support.ccc.CccParams.CHAPS_PER_SLOT_8;
50 import static com.google.uwb.support.ccc.CccParams.CHAPS_PER_SLOT_9;
51 import static com.google.uwb.support.ccc.CccParams.HOPPING_CONFIG_MODE_ADAPTIVE;
52 import static com.google.uwb.support.ccc.CccParams.HOPPING_CONFIG_MODE_CONTINUOUS;
53 import static com.google.uwb.support.ccc.CccParams.HOPPING_CONFIG_MODE_NONE;
54 import static com.google.uwb.support.ccc.CccParams.HOPPING_SEQUENCE_AES;
55 import static com.google.uwb.support.ccc.CccParams.HOPPING_SEQUENCE_DEFAULT;
56 import static com.google.uwb.support.ccc.CccParams.UWB_CHANNEL_5;
57 import static com.google.uwb.support.ccc.CccParams.UWB_CHANNEL_9;
58 
59 import android.util.Log;
60 
61 import com.android.server.uwb.config.ConfigParam;
62 
63 import com.google.uwb.support.base.Params;
64 import com.google.uwb.support.ccc.CccProtocolVersion;
65 import com.google.uwb.support.ccc.CccPulseShapeCombo;
66 import com.google.uwb.support.ccc.CccRangingStartedParams;
67 import com.google.uwb.support.ccc.CccSpecificationParams;
68 
69 import java.nio.ByteBuffer;
70 import java.nio.ByteOrder;
71 
72 /**
73  * CCC decoder
74  */
75 public class CccDecoder extends TlvDecoder {
76     private static final String TAG = "CccDecoder";
77 
78     @Override
getParams(TlvDecoderBuffer tlvs, Class<T> paramsType)79     public <T extends Params> T getParams(TlvDecoderBuffer tlvs, Class<T> paramsType)
80             throws IllegalArgumentException {
81         if (CccRangingStartedParams.class.equals(paramsType)) {
82             return (T) getCccRangingStartedParamsFromTlvBuffer(tlvs);
83         }
84         if (CccSpecificationParams.class.equals(paramsType)) {
85             return (T) getCccSpecificationParamsFromTlvBuffer(tlvs);
86         }
87         return null;
88     }
89 
isBitSet(int flags, int mask)90     private static boolean isBitSet(int flags, int mask) {
91         return (flags & mask) != 0;
92     }
93 
getCccRangingStartedParamsFromTlvBuffer(TlvDecoderBuffer tlvs)94     private CccRangingStartedParams getCccRangingStartedParamsFromTlvBuffer(TlvDecoderBuffer tlvs) {
95         byte[] hopModeKey = tlvs.getByteArray(ConfigParam.HOP_MODE_KEY);
96         int hopModeKeyInt = ByteBuffer.wrap(hopModeKey).order(ByteOrder.LITTLE_ENDIAN).getInt();
97         return new CccRangingStartedParams.Builder()
98                 // STS_Index0  0 - 0x3FFFFFFFF
99                 .setStartingStsIndex(tlvs.getInt(ConfigParam.STS_INDEX))
100                 .setHopModeKey(hopModeKeyInt)
101                 //  UWB_Time0 0 - 0xFFFFFFFFFFFFFFFF  UWB_INITIATION_TIME
102                 .setUwbTime0(tlvs.getLong(ConfigParam.UWB_TIME0))
103                 // RANGING_INTERVAL = RAN_Multiplier * 96
104                 .setRanMultiplier(tlvs.getInt(ConfigParam.RANGING_INTERVAL) / 96)
105                 .setSyncCodeIndex(tlvs.getByte(ConfigParam.PREAMBLE_CODE_INDEX))
106                 .build();
107     }
108 
getCccSpecificationParamsFromTlvBuffer(TlvDecoderBuffer tlvs)109     private CccSpecificationParams getCccSpecificationParamsFromTlvBuffer(TlvDecoderBuffer tlvs) {
110         CccSpecificationParams.Builder builder = new CccSpecificationParams.Builder();
111         byte[] versions = tlvs.getByteArray(CCC_SUPPORTED_VERSIONS);
112         if (versions.length % 2 != 0) {
113             throw new IllegalArgumentException("Invalid supported protocol versions len "
114                     + versions.length);
115         }
116         for (int i = 0; i < versions.length; i += 2) {
117             builder.addProtocolVersion(CccProtocolVersion.fromBytes(versions, i));
118         }
119         byte[] configs = tlvs.getByteArray(CCC_SUPPORTED_UWB_CONFIGS);
120         for (int i = 0; i < configs.length; i++) {
121             builder.addUwbConfig(configs[i]);
122         }
123         byte[] pulse_shape_combos = tlvs.getByteArray(CCC_SUPPORTED_PULSE_SHAPE_COMBOS);
124         for (int i = 0; i < pulse_shape_combos.length; i++) {
125             builder.addPulseShapeCombo(CccPulseShapeCombo.fromBytes(pulse_shape_combos, i));
126         }
127         builder.setRanMultiplier(tlvs.getInt(CCC_SUPPORTED_RAN_MULTIPLIER));
128         byte chapsPerslot = tlvs.getByte(CCC_SUPPORTED_CHAPS_PER_SLOT);
129         if (isBitSet(chapsPerslot, CCC_CHAPS_PER_SLOT_3)) {
130             builder.addChapsPerSlot(CHAPS_PER_SLOT_3);
131         }
132         if (isBitSet(chapsPerslot, CCC_CHAPS_PER_SLOT_4)) {
133             builder.addChapsPerSlot(CHAPS_PER_SLOT_4);
134         }
135         if (isBitSet(chapsPerslot, CCC_CHAPS_PER_SLOT_6)) {
136             builder.addChapsPerSlot(CHAPS_PER_SLOT_6);
137         }
138         if (isBitSet(chapsPerslot, CCC_CHAPS_PER_SLOT_8)) {
139             builder.addChapsPerSlot(CHAPS_PER_SLOT_8);
140         }
141         if (isBitSet(chapsPerslot, CCC_CHAPS_PER_SLOT_9)) {
142             builder.addChapsPerSlot(CHAPS_PER_SLOT_9);
143         }
144         if (isBitSet(chapsPerslot, CCC_CHAPS_PER_SLOT_12)) {
145             builder.addChapsPerSlot(CHAPS_PER_SLOT_12);
146         }
147         if (isBitSet(chapsPerslot, CCC_CHAPS_PER_SLOT_24)) {
148             builder.addChapsPerSlot(CHAPS_PER_SLOT_24);
149         }
150         // Don't use TlvDecodeBuffer#getInt() to avoid conversion to little endian.
151         int syncCodes = ByteBuffer.wrap(tlvs.getByteArray(CCC_SUPPORTED_SYNC_CODES)).getInt();
152         for (int i = 0; i < 32; i++) {
153             if (isBitSet(syncCodes, 1 << i)) {
154                 builder.addSyncCode(i + 1);
155             }
156         }
157         byte channels = tlvs.getByte(CCC_SUPPORTED_CHANNELS);
158         if (isBitSet(channels, CCC_CHANNEL_5)) {
159             builder.addChannel(UWB_CHANNEL_5);
160         }
161         if (isBitSet(channels, CCC_CHANNEL_9)) {
162             builder.addChannel(UWB_CHANNEL_9);
163         }
164         byte hoppingConfigModesAndSequences =
165                 tlvs.getByte(CCC_SUPPORTED_HOPPING_CONFIG_MODES_AND_SEQUENCES);
166         if (isBitSet(hoppingConfigModesAndSequences, CCC_HOPPING_CONFIG_MODE_NONE)) {
167             builder.addHoppingConfigMode(HOPPING_CONFIG_MODE_NONE);
168         }
169         if (isBitSet(hoppingConfigModesAndSequences, CCC_HOPPING_CONFIG_MODE_CONTINUOUS)) {
170             builder.addHoppingConfigMode(HOPPING_CONFIG_MODE_CONTINUOUS);
171         }
172         if (isBitSet(hoppingConfigModesAndSequences, CCC_HOPPING_CONFIG_MODE_ADAPTIVE)) {
173             builder.addHoppingConfigMode(HOPPING_CONFIG_MODE_ADAPTIVE);
174         }
175         if (isBitSet(hoppingConfigModesAndSequences, CCC_HOPPING_SEQUENCE_AES)) {
176             builder.addHoppingSequence(HOPPING_SEQUENCE_AES);
177         }
178         if (isBitSet(hoppingConfigModesAndSequences, CCC_HOPPING_SEQUENCE_DEFAULT)) {
179             builder.addHoppingSequence(HOPPING_SEQUENCE_DEFAULT);
180         }
181 
182         try {
183             int maxRangingSessionNumber = tlvs.getInt(CCC_SUPPORTED_MAX_RANGING_SESSION_NUMBER);
184             builder.setMaxRangingSessionNumber(maxRangingSessionNumber);
185         } catch (IllegalArgumentException e) {
186             Log.w(TAG, "SUPPORTED_MAX_RANGING_SESSION_NUMBER not found");
187         }
188 
189         try {
190             int minUwbInitiationTimeMs = tlvs.getInt(CCC_SUPPORTED_MIN_UWB_INITIATION_TIME_MS);
191             builder.setMinUwbInitiationTimeMs(minUwbInitiationTimeMs);
192         } catch (IllegalArgumentException e) {
193             Log.w(TAG, "SUPPORTED_MIN_UWB_INITIATION_TIME_MS not found");
194         }
195         return builder.build();
196     }
197 }
198