• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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.ranging.uwb;
18 
19 import static com.google.common.collect.ImmutableList.toImmutableList;
20 
21 import android.ranging.RangingCapabilities;
22 import android.ranging.RangingManager;
23 import android.ranging.uwb.UwbAddress;
24 import android.ranging.uwb.UwbRangingCapabilities;
25 
26 import com.android.server.ranging.RangingTechnology;
27 import com.android.server.ranging.RangingUtils.Conversions;
28 import com.android.server.ranging.oob.TechnologyHeader;
29 
30 import com.google.auto.value.AutoValue;
31 import com.google.common.collect.ImmutableList;
32 
33 import java.nio.ByteBuffer;
34 import java.util.Arrays;
35 
36 /** Capability data for UWB sent as part of CapabilityResponseMessage. */
37 @AutoValue
38 public abstract class UwbOobCapabilities implements RangingCapabilities.TechnologyCapabilities {
39 
40     /** Size in bytes of all properties when serialized. */
41     private static final int EXPECTED_SIZE_BYTES = 20;
42 
43     // Size in bytes for each properties for serialization/deserialization.
44     private static final int UWB_ADDRESS_SIZE = 2;
45     private static final int CHANNELS_SIZE = 4;
46     private static final int PREAMBLES_SIZE = 4;
47     private static final int CONFIG_IDS_SIZE = 4;
48     private static final int MIN_INTERVAL_SIZE = 2;
49     private static final int MIN_SLOT_SIZE = 1;
50     private static final int DEVICE_ROLE_SIZE = 1;
51 
52     private static final int CHANNELS_SHIFT = 0;
53     private static final int PREAMBLES_SHIFT = 1;
54     private static final int CONFIG_IDS_SHIFT = 0;
55     private static final int DEVICE_ROLE_SHIFT = 1;
56 
57     /** Returns the size of the object in bytes when serialized. */
getSize()58     public static int getSize() {
59         return EXPECTED_SIZE_BYTES;
60     }
61 
62     @Override
getTechnology()63     public @RangingManager.RangingTechnology int getTechnology() {
64         return RangingTechnology.UWB.getValue();
65     }
66 
67     /**
68      * Parses the given byte array and returns {@link UwbOobCapabilities} object. Throws {@link
69      * IllegalArgumentException} on invalid input.
70      */
parseBytes(byte[] capabilitiesBytes)71     public static UwbOobCapabilities parseBytes(byte[] capabilitiesBytes) {
72         TechnologyHeader header = TechnologyHeader.parseBytes(capabilitiesBytes);
73 
74         if (capabilitiesBytes.length < EXPECTED_SIZE_BYTES) {
75             throw new IllegalArgumentException(
76                     String.format(
77                             "UwbCapabilities size is %d, expected at least %d",
78                             capabilitiesBytes.length, EXPECTED_SIZE_BYTES));
79         }
80 
81         if (capabilitiesBytes.length < header.getSize()) {
82             throw new IllegalArgumentException(
83                     String.format(
84                             "UwbCapabilities header size field is %d, but the size of the array "
85                                     + "is %d",
86                             header.getSize(), capabilitiesBytes.length));
87         }
88 
89         if (header.getRangingTechnology() != RangingTechnology.UWB) {
90             throw new IllegalArgumentException(
91                     String.format(
92                             "UwbCapabilities header technology field is %s, expected %s",
93                             header.getRangingTechnology(), RangingTechnology.UWB));
94         }
95 
96         int parseCursor = header.getHeaderSize();
97 
98         // Parse UWB Address
99         UwbAddress uwbAddress =
100                 UwbAddress.fromBytes(
101                         Arrays.copyOfRange(capabilitiesBytes, parseCursor,
102                                 parseCursor + UWB_ADDRESS_SIZE));
103         parseCursor += UWB_ADDRESS_SIZE;
104 
105         // Parse Supported Channels
106         ImmutableList<Integer> supportedChannels =
107                 Conversions.byteArrayToIntList(
108                         Arrays.copyOfRange(capabilitiesBytes, parseCursor,
109                                 parseCursor + CHANNELS_SIZE),
110                         CHANNELS_SHIFT);
111         parseCursor += CHANNELS_SIZE;
112 
113         // Parse Supported Preamble Indexes
114         ImmutableList<Integer> supportedPreambleIndexes =
115                 Conversions.byteArrayToIntList(
116                         Arrays.copyOfRange(capabilitiesBytes, parseCursor,
117                                 parseCursor + PREAMBLES_SIZE),
118                         PREAMBLES_SHIFT);
119         parseCursor += PREAMBLES_SIZE;
120 
121         // Parse Supported Config Ids
122         ImmutableList<Integer> supportedConfigIds =
123                 Conversions.byteArrayToIntList(
124                         Arrays.copyOfRange(capabilitiesBytes, parseCursor,
125                                 parseCursor + CONFIG_IDS_SIZE),
126                         CONFIG_IDS_SHIFT);
127         parseCursor += CONFIG_IDS_SIZE;
128 
129         // Parse Minimum Ranging Interval Ms
130         int minimumRangingIntervalMs =
131                 Conversions.byteArrayToInt(
132                         Arrays.copyOfRange(capabilitiesBytes, parseCursor,
133                                 parseCursor + MIN_INTERVAL_SIZE));
134         parseCursor += MIN_INTERVAL_SIZE;
135 
136         // Parse Minimum Slot Duration Ms
137         int minimumSlotDurationMs =
138                 Conversions.byteArrayToInt(
139                         Arrays.copyOfRange(capabilitiesBytes, parseCursor,
140                                 parseCursor + MIN_SLOT_SIZE));
141         parseCursor += MIN_SLOT_SIZE;
142 
143         // Parse Device Role
144         ImmutableList<Integer> deviceRoles =
145                 Conversions.byteArrayToIntList(
146                                 Arrays.copyOfRange(capabilitiesBytes, parseCursor,
147                                         parseCursor + DEVICE_ROLE_SIZE),
148                                 DEVICE_ROLE_SHIFT)
149                         .stream()
150                         .collect(toImmutableList());
151         parseCursor += DEVICE_ROLE_SIZE;
152 
153         return UwbOobCapabilities.builder()
154                 .setUwbAddress(uwbAddress)
155                 .setSupportedChannels(supportedChannels)
156                 .setSupportedConfigIds(supportedConfigIds)
157                 .setSupportedPreambleIndexes(supportedPreambleIndexes)
158                 .setMinimumRangingIntervalMs(minimumRangingIntervalMs)
159                 .setMinimumSlotDurationMs(minimumSlotDurationMs)
160                 .setSupportedDeviceRole(deviceRoles)
161                 .build();
162     }
163 
164     /** Serializes this {@link UwbOobCapabilities} object to bytes. */
toBytes()165     public final byte[] toBytes() {
166         ByteBuffer byteBuffer = ByteBuffer.allocate(EXPECTED_SIZE_BYTES);
167         byteBuffer
168                 .put(RangingTechnology.UWB.toByte())
169                 .put((byte) EXPECTED_SIZE_BYTES)
170                 .put(getUwbAddress().getAddressBytes())
171                 .put(Conversions.intListToByteArrayBitmap(getSupportedChannels(), CHANNELS_SIZE,
172                         CHANNELS_SHIFT))
173                 .put(
174                         Conversions.intListToByteArrayBitmap(
175                                 getSupportedPreambleIndexes(), PREAMBLES_SIZE, PREAMBLES_SHIFT))
176                 .put(
177                         Conversions.intListToByteArrayBitmap(
178                                 getSupportedConfigIds(), CONFIG_IDS_SIZE, CONFIG_IDS_SHIFT))
179                 .put(Conversions.intToByteArray(getMinimumRangingIntervalMs(), MIN_INTERVAL_SIZE))
180                 .put(Conversions.intToByteArray(getMinimumSlotDurationMs(), MIN_SLOT_SIZE))
181                 .put(
182                         Conversions.intListToByteArrayBitmap(
183                                 getSupportedDeviceRole().stream()
184                                         .collect(toImmutableList()),
185                                 DEVICE_ROLE_SIZE,
186                                 DEVICE_ROLE_SHIFT));
187 
188         return byteBuffer.array();
189     }
190 
fromRangingCapabilities( UwbRangingCapabilities capabilities, UwbAddress address )191     public static UwbOobCapabilities fromRangingCapabilities(
192             UwbRangingCapabilities capabilities, UwbAddress address
193     ) {
194         return UwbOobCapabilities.builder()
195                 .setUwbAddress(address)
196                 .setSupportedChannels(
197                         ImmutableList.copyOf(capabilities.getSupportedChannels()))
198                 .setSupportedPreambleIndexes(
199                         ImmutableList.copyOf(capabilities.getSupportedPreambleIndexes()))
200                 .setSupportedConfigIds(
201                         ImmutableList.copyOf(capabilities.getSupportedConfigIds()))
202                 .setMinimumRangingIntervalMs(
203                         (int) capabilities.getMinimumRangingInterval().toMillis())
204                 .setMinimumSlotDurationMs(capabilities.getSupportedSlotDurations()
205                         .stream().min(Integer::compare).get())
206                 .setSupportedDeviceRole(ImmutableList.of(
207                         UwbOobConfig.OobDeviceRole.INITIATOR,
208                         UwbOobConfig.OobDeviceRole.RESPONDER))
209                 .build();
210     }
211 
212     /** Returns the {@link UwbAddress} of the device. */
getUwbAddress()213     public abstract UwbAddress getUwbAddress();
214 
215     /** Returns a list of supported channels. */
getSupportedChannels()216     public abstract ImmutableList<Integer> getSupportedChannels();
217 
218     /** Returns a list of supported preamble indexes. */
getSupportedPreambleIndexes()219     public abstract ImmutableList<Integer> getSupportedPreambleIndexes();
220 
221     /** Returns a list of supported config Ids. */
getSupportedConfigIds()222     public abstract ImmutableList<Integer> getSupportedConfigIds();
223 
224     /** Returns minimum supported ranging interval in ms. */
getMinimumRangingIntervalMs()225     public abstract int getMinimumRangingIntervalMs();
226 
227     /** Returns minimum supported slot duration in ms. */
getMinimumSlotDurationMs()228     public abstract int getMinimumSlotDurationMs();
229 
230     /** Returns supported device roles. */
getSupportedDeviceRole()231     public abstract ImmutableList<Integer> getSupportedDeviceRole();
232 
233     /** Returns a builder for {@link UwbOobCapabilities}. */
builder()234     public static Builder builder() {
235         return new AutoValue_UwbOobCapabilities.Builder();
236     }
237 
238     /** Builder for {@link UwbOobCapabilities}. */
239     @AutoValue.Builder
240     public abstract static class Builder {
241 
setUwbAddress(UwbAddress uwbAddress)242         public abstract Builder setUwbAddress(UwbAddress uwbAddress);
243 
setSupportedChannels(ImmutableList<Integer> supportedChannels)244         public abstract Builder setSupportedChannels(ImmutableList<Integer> supportedChannels);
245 
setSupportedPreambleIndexes( ImmutableList<Integer> supportedPreambleIndexes)246         public abstract Builder setSupportedPreambleIndexes(
247                 ImmutableList<Integer> supportedPreambleIndexes);
248 
setSupportedConfigIds(ImmutableList<Integer> supportedConfigIds)249         public abstract Builder setSupportedConfigIds(ImmutableList<Integer> supportedConfigIds);
250 
setMinimumRangingIntervalMs(int minimumRangingIntervalMs)251         public abstract Builder setMinimumRangingIntervalMs(int minimumRangingIntervalMs);
252 
setMinimumSlotDurationMs(int minimumSlotDurationMs)253         public abstract Builder setMinimumSlotDurationMs(int minimumSlotDurationMs);
254 
setSupportedDeviceRole( ImmutableList<Integer> supportedDeviceRole)255         public abstract Builder setSupportedDeviceRole(
256                 ImmutableList<Integer> supportedDeviceRole);
257 
build()258         public abstract UwbOobCapabilities build();
259     }
260 }
261