• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.ranging.uwb;
18 
19 import static android.ranging.raw.RawRangingDevice.UPDATE_RATE_NORMAL;
20 
21 import android.annotation.FlaggedApi;
22 import android.annotation.IntDef;
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 import android.ranging.raw.RawRangingDevice.RangingUpdateRate;
28 
29 import com.android.ranging.flags.Flags;
30 
31 import java.lang.annotation.ElementType;
32 import java.lang.annotation.Retention;
33 import java.lang.annotation.RetentionPolicy;
34 import java.lang.annotation.Target;
35 import java.util.Arrays;
36 import java.util.Objects;
37 
38 /**
39  * UwbRangingParams encapsulates the parameters required for a UWB ranging session.
40  */
41 @FlaggedApi(Flags.FLAG_RANGING_STACK_ENABLED)
42 public final class UwbRangingParams implements Parcelable {
43 
44     private final int mSessionId;
45 
46     private final int mSubSessionId;
47 
UwbRangingParams(Parcel in)48     private UwbRangingParams(Parcel in) {
49         mSessionId = in.readInt();
50         mSubSessionId = in.readInt();
51         mConfigId = in.readInt();
52         mDeviceAddress = in.readParcelable(UwbAddress.class.getClassLoader());
53         mSessionKeyInfo = in.readBlob();
54         mSubSessionKeyInfo = in.readBlob();
55         mComplexChannel = in.readParcelable(UwbComplexChannel.class.getClassLoader());
56         mRangingUpdateRate = in.readInt();
57         mPeerAddress = in.readParcelable(UwbAddress.class.getClassLoader());
58         mSlotDurationMillis = in.readInt();
59     }
60 
61     @NonNull
62     public static final Creator<UwbRangingParams> CREATOR = new Creator<UwbRangingParams>() {
63         @Override
64         public UwbRangingParams createFromParcel(Parcel in) {
65             return new UwbRangingParams(in);
66         }
67 
68         @Override
69         public UwbRangingParams[] newArray(int size) {
70             return new UwbRangingParams[size];
71         }
72     };
73 
74     @Override
describeContents()75     public int describeContents() {
76         return 0;
77     }
78 
79     @Override
writeToParcel(@ndroidx.annotation.NonNull Parcel dest, int flags)80     public void writeToParcel(@androidx.annotation.NonNull Parcel dest, int flags) {
81         dest.writeInt(mSessionId);
82         dest.writeInt(mSubSessionId);
83         dest.writeInt(mConfigId);
84         dest.writeParcelable(mDeviceAddress, flags);
85         dest.writeBlob(mSessionKeyInfo);
86         dest.writeBlob(mSubSessionKeyInfo);
87         dest.writeParcelable(mComplexChannel, flags);
88         dest.writeInt(mRangingUpdateRate);
89         dest.writeParcelable(mPeerAddress, flags);
90         dest.writeInt(mSlotDurationMillis);
91     }
92 
93     /**
94      * Defines the roles that a device can assume within a UWB ranging session.
95      *
96      * @hide
97      */
98     @Retention(RetentionPolicy.SOURCE)
99     @Target({ElementType.TYPE_USE})
100     @IntDef({
101             CONFIG_UNICAST_DS_TWR,
102             CONFIG_MULTICAST_DS_TWR,
103             CONFIG_PROVISIONED_UNICAST_DS_TWR,
104             CONFIG_PROVISIONED_MULTICAST_DS_TWR,
105             CONFIG_PROVISIONED_INDIVIDUAL_MULTICAST_DS_TWR,
106             CONFIG_PROVISIONED_UNICAST_DS_TWR_VERY_FAST,
107     })
108     public @interface ConfigId {
109     }
110 
111     /**
112      * FiRa-defined unicast {@code STATIC STS DS-TWR} ranging, deferred mode, ranging interval
113      * Fast (120ms), Normal (240ms), Infrequent (600ms)
114      */
115     public static final int CONFIG_UNICAST_DS_TWR = 1;
116 
117     /**
118      * FiRa-defined multicast {@code STATIC STS DS-TWR} ranging, deferred mode, ranging interval
119      * Fast (120ms), Normal (200ms), Infrequent (600ms)
120      */
121     public static final int CONFIG_MULTICAST_DS_TWR = 2;
122     /** Same as {@code CONFIG_UNICAST_DS_TWR}, except P-STS security mode is enabled. */
123     public static final int CONFIG_PROVISIONED_UNICAST_DS_TWR = 3;
124     /** Same as {@code CONFIG_MULTICAST_DS_TWR}, except P-STS security mode is enabled. */
125     public static final int CONFIG_PROVISIONED_MULTICAST_DS_TWR = 4;
126     /**
127      * Same as {@code CONFIG_UNICAST_DS_TWR}, except P-STS individual controlee key mode is
128      * enabled.
129      */
130     public static final int CONFIG_PROVISIONED_INDIVIDUAL_MULTICAST_DS_TWR = 5;
131 
132     /** Same as {@code CONFIG_ID_3}, except fast ranging interval is 96 milliseconds. */
133     public static final int CONFIG_PROVISIONED_UNICAST_DS_TWR_VERY_FAST = 6;
134 
135     /** Sub session id not applicable. */
136     public static final int SUB_SESSION_UNDEFINED = -1;
137 
138     @ConfigId
139     private final int mConfigId;
140 
141     private final UwbAddress mDeviceAddress;
142 
143     private final byte[] mSessionKeyInfo;
144 
145     private final byte[] mSubSessionKeyInfo;
146 
147     private final UwbComplexChannel mComplexChannel;
148 
149     private final UwbAddress mPeerAddress;
150 
151     /**
152      * Defines slot supported slot durations.
153      *
154      * @hide
155      */
156     @Retention(RetentionPolicy.SOURCE)
157     @IntDef({
158             DURATION_1_MS,
159             DURATION_2_MS,
160     })
161     public @interface SlotDuration {
162     }
163 
164     /** 1 millisecond slot duration */
165     public static final int DURATION_1_MS = 1;
166 
167     /** 2 millisecond slot duration */
168     public static final int DURATION_2_MS = 2;
169 
170     @RangingUpdateRate
171     private final int mRangingUpdateRate;
172 
173     @SlotDuration
174     private final int mSlotDurationMillis;
175 
UwbRangingParams(Builder builder)176     private UwbRangingParams(Builder builder) {
177         mSessionId = builder.mSessionId;
178         mSubSessionId = builder.mSubSessionId;
179         mConfigId = builder.mConfigId;
180         mDeviceAddress = builder.mDeviceAddress;
181         mSessionKeyInfo = builder.mSessionKeyInfo;
182         mSubSessionKeyInfo = builder.mSubSessionKeyInfo;
183         mComplexChannel = builder.mComplexChannel;
184         mPeerAddress = builder.mPeerAddress;
185         mRangingUpdateRate = builder.mRangingUpdateRate;
186         mSlotDurationMillis = builder.mSlotDuration;
187     }
188 
189     /**
190      * Gets the session ID associated with this ranging session.
191      *
192      * @return The session ID as an integer.
193      */
getSessionId()194     public int getSessionId() {
195         return mSessionId;
196     }
197 
198     /**
199      * Gets the sub-session ID if applicable for the session.
200      *
201      * @return The sub-session ID as an integer or {@link #SUB_SESSION_UNDEFINED} if not applicable.
202      */
getSubSessionId()203     public int getSubSessionId() {
204         return mSubSessionId;
205     }
206 
207     /**
208      * Gets the configuration ID associated with this session.
209      *
210      * @return The configuration ID as an integer.
211      */
212     @ConfigId
getConfigId()213     public int getConfigId() {
214         return mConfigId;
215     }
216 
217     /**
218      * Gets the UWB address of the device.
219      *
220      * @return The {@link UwbAddress} of the device.
221      */
222     @NonNull
getDeviceAddress()223     public UwbAddress getDeviceAddress() {
224         return mDeviceAddress;
225     }
226 
227     /**
228      * Gets session key information, if available.
229      *
230      * @return A byte array containing session key info, or null if not available.
231      */
232     @Nullable
getSessionKeyInfo()233     public byte[] getSessionKeyInfo() {
234         return mSessionKeyInfo == null ? null : Arrays.copyOf(mSessionKeyInfo,
235                 mSessionKeyInfo.length);
236     }
237 
238     /**
239      * Gets sub-session key information, if available.
240      *
241      * @return A byte array containing sub-session key info, or null if not available.
242      */
243     @Nullable
getSubSessionKeyInfo()244     public byte[] getSubSessionKeyInfo() {
245         return mSubSessionKeyInfo == null ? null : Arrays.copyOf(mSubSessionKeyInfo,
246                 mSubSessionKeyInfo.length);
247     }
248 
249     /**
250      * Gets the complex channel information for this session.
251      *
252      * @return A {@link UwbComplexChannel} object containing channel and preamble index.
253      */
254     @NonNull
getComplexChannel()255     public UwbComplexChannel getComplexChannel() {
256         return mComplexChannel;
257     }
258 
259     /**
260      * Returns the UwbAddress of the peer device.
261      *
262      * @return A {@link UwbAddress} corresponding to the peer device to range with.
263      */
264     @NonNull
getPeerAddress()265     public UwbAddress getPeerAddress() {
266         return mPeerAddress;
267     }
268 
269     /**
270      * Returns the update rate for ranging operations.
271      *
272      * @return The ranging update rate.
273      */
274     @RangingUpdateRate
getRangingUpdateRate()275     public int getRangingUpdateRate() {
276         return mRangingUpdateRate;
277     }
278 
279     /**
280      * Returns slot duration of the session.
281      *
282      * @return the slot duration.
283      */
284     @SlotDuration
getSlotDuration()285     public int getSlotDuration() {
286         return mSlotDurationMillis;
287     }
288 
289 
290     /**
291      * Builder class for creating instances of {@link UwbRangingParams}
292      */
293     public static final class Builder {
294         private int mSessionId;
295         private int mSubSessionId = SUB_SESSION_UNDEFINED;
296         private int mConfigId;
297         private UwbAddress mDeviceAddress = null;
298         private byte[] mSessionKeyInfo = null;
299         private byte[] mSubSessionKeyInfo = null;
300         private UwbComplexChannel mComplexChannel = new UwbComplexChannel.Builder().build();
301         private UwbAddress mPeerAddress = null;
302         @RangingUpdateRate
303         private int mRangingUpdateRate = UPDATE_RATE_NORMAL;
304         @SlotDuration
305         private int mSlotDuration = DURATION_2_MS;
306 
307         /**
308          * Constructs a new {@link Builder} for creating a ranging session.
309          *
310          * @param sessionId     A unique identifier for the session.
311          * @param configId      The configuration ID for the ranging parameters.
312          * @param deviceAddress The {@link UwbAddress} representing the device's address.
313          *                      Must be non-null.
314          * @param peerAddress   The {@link UwbAddress} of the peer device.
315          *                      Must be non-null.
316          * @throws IllegalArgumentException if either {@code deviceAddress} or {@code peerAddress}
317          *                                  is null.
318          */
Builder(int sessionId, @ConfigId int configId, @NonNull UwbAddress deviceAddress, @NonNull UwbAddress peerAddress)319         public Builder(int sessionId, @ConfigId int configId, @NonNull UwbAddress deviceAddress,
320                 @NonNull UwbAddress peerAddress) {
321             Objects.requireNonNull(deviceAddress);
322             Objects.requireNonNull(peerAddress);
323             mSessionId = sessionId;
324             mConfigId = configId;
325             mDeviceAddress = deviceAddress;
326             mPeerAddress = peerAddress;
327         }
328 
329         /**
330          * Sets the sub-session ID for the ranging session.
331          *
332          * @param subSessionId the sub-session ID, which should be a unique identifier for the
333          *                     sub-session.
334          * @return this Builder instance for method chaining.
335          */
336         @NonNull
setSubSessionId(int subSessionId)337         public Builder setSubSessionId(int subSessionId) {
338             mSubSessionId = subSessionId;
339             return this;
340         }
341 
342         /**
343          * Sets the session key information for secure ranging.
344          *
345          * @param sessionKeyInfo a byte array containing session key information.
346          * @return this Builder instance.
347          * @throws IllegalArgumentException if the provided byte array is null.
348          */
349         @NonNull
setSessionKeyInfo(@onNull byte[] sessionKeyInfo)350         public Builder setSessionKeyInfo(@NonNull byte[] sessionKeyInfo) {
351             Objects.requireNonNull(sessionKeyInfo);
352             mSessionKeyInfo = Arrays.copyOf(sessionKeyInfo, sessionKeyInfo.length);
353             return this;
354         }
355 
356         /**
357          * Sets the sub-session key information for secure ranging.
358          *
359          * @param subSessionKeyInfo a byte array containing sub-session key information.
360          * @return this Builder instance.
361          * @throws IllegalArgumentException if the provided map is null.
362          */
363         @NonNull
setSubSessionKeyInfo(@onNull byte[] subSessionKeyInfo)364         public Builder setSubSessionKeyInfo(@NonNull byte[] subSessionKeyInfo) {
365             Objects.requireNonNull(subSessionKeyInfo);
366             mSubSessionKeyInfo = Arrays.copyOf(subSessionKeyInfo, subSessionKeyInfo.length);
367             return this;
368         }
369 
370         /**
371          * Sets the complex channel configuration for the ranging session.
372          *
373          * @param complexChannel a non-null {@link UwbComplexChannel} instance representing the
374          *                       channel and preamble configuration. For better performance always
375          *                       use a random preamble index for each ranging session.
376          * @return this Builder instance.
377          * @throws IllegalArgumentException if the provided complex channel is null.
378          */
379         @NonNull
setComplexChannel(@onNull UwbComplexChannel complexChannel)380         public Builder setComplexChannel(@NonNull UwbComplexChannel complexChannel) {
381             mComplexChannel = complexChannel;
382             return this;
383         }
384 
385         /**
386          * Sets the ranging update rate for the session.
387          * <p> Defaults to {@link RangingUpdateRate#UPDATE_RATE_NORMAL}.
388          *
389          * @param rate the ranging update rate, defined as one of the constants in
390          *             {@link RangingUpdateRate}.
391          * @return this Builder instance.
392          */
393         @NonNull
setRangingUpdateRate(@angingUpdateRate int rate)394         public Builder setRangingUpdateRate(@RangingUpdateRate int rate) {
395             mRangingUpdateRate = rate;
396             return this;
397         }
398 
399         /**
400          * Sets the slot duration in milliseconds for the ranging session.
401          * <p> Defaults to {@link #DURATION_2_MS}.
402          *
403          * @param durationMs the slot duration {@link SlotDuration}
404          * @return this Builder instance.
405          * @throws IllegalArgumentException if the provided duration is out of range.
406          */
407         @NonNull
setSlotDuration(@lotDuration int durationMs)408         public Builder setSlotDuration(@SlotDuration int durationMs) {
409             mSlotDuration = durationMs;
410             return this;
411         }
412 
413         /**
414          * Builds a new instance of {@link UwbRangingParams}.
415          *
416          * @return a new instance of {@link UwbRangingParams} created using the current state of
417          * the builder.
418          */
419         @NonNull
build()420         public UwbRangingParams build() {
421             return new UwbRangingParams(this);
422         }
423     }
424 
425     @Override
toString()426     public String toString() {
427         return "UwbRangingParams{ "
428                 + "mSessionId="
429                 + mSessionId
430                 + ", mSubSessionId="
431                 + mSubSessionId
432                 + ", mConfigId="
433                 + mConfigId
434                 + ", mDeviceAddress="
435                 + mDeviceAddress
436                 + ", mSessionKeyInfo="
437                 + Arrays.toString(mSessionKeyInfo)
438                 + ", mSubSessionKeyInfo="
439                 + Arrays.toString(mSubSessionKeyInfo)
440                 + ", mComplexChannel="
441                 + mComplexChannel
442                 + ", mPeerAddress="
443                 + mPeerAddress
444                 + ", mRangingUpdateRate="
445                 + mRangingUpdateRate
446                 + ", mSlotDurationMillis="
447                 + mSlotDurationMillis
448                 + " }";
449     }
450 
451     /**
452      * @hide
453      */
454     @Override
equals(Object o)455     public boolean equals(Object o) {
456         if (this == o) return true;
457         if (!(o instanceof UwbRangingParams that)) return false;
458         return mSessionId == that.mSessionId && mSubSessionId == that.mSubSessionId
459                 && mConfigId == that.mConfigId && mRangingUpdateRate == that.mRangingUpdateRate
460                 && mSlotDurationMillis == that.mSlotDurationMillis && Objects.equals(
461                 mDeviceAddress, that.mDeviceAddress) && Objects.deepEquals(mSessionKeyInfo,
462                 that.mSessionKeyInfo) && Objects.deepEquals(mSubSessionKeyInfo,
463                 that.mSubSessionKeyInfo) && Objects.equals(mComplexChannel,
464                 that.mComplexChannel) && Objects.equals(mPeerAddress, that.mPeerAddress);
465     }
466 
467     /**
468      * @hide
469      */
470     @Override
hashCode()471     public int hashCode() {
472         return Objects.hash(mSessionId, mSubSessionId, mConfigId, mDeviceAddress,
473                 Arrays.hashCode(mSessionKeyInfo), Arrays.hashCode(mSubSessionKeyInfo),
474                 mComplexChannel,
475                 mPeerAddress, mRangingUpdateRate, mSlotDurationMillis);
476     }
477 }
478