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 android.annotation.FlaggedApi; 20 import android.annotation.NonNull; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.ranging.DataNotificationConfig.NotificationConfigType; 24 import android.ranging.RangingCapabilities.TechnologyCapabilities; 25 import android.ranging.RangingManager; 26 import android.ranging.raw.RawRangingDevice.RangingUpdateRate; 27 import android.ranging.uwb.UwbComplexChannel.UwbChannel; 28 import android.ranging.uwb.UwbComplexChannel.UwbPreambleCodeIndex; 29 import android.ranging.uwb.UwbRangingParams.ConfigId; 30 import android.ranging.uwb.UwbRangingParams.SlotDuration; 31 32 import com.android.ranging.flags.Flags; 33 34 import java.time.Duration; 35 import java.util.ArrayList; 36 import java.util.List; 37 38 /** 39 * Represents the capabilities of Ultra-Wideband (UWB) ranging technology. 40 * 41 * <p>This class encapsulates various UWB-related features, including support for specific 42 * measurement types (e.g., distance, azimuth, elevation), ranging configurations, and 43 * operational parameters like update rates and channel availability.</p> 44 */ 45 @FlaggedApi(Flags.FLAG_RANGING_STACK_ENABLED) 46 public final class UwbRangingCapabilities implements Parcelable, TechnologyCapabilities { 47 48 private final boolean mSupportsDistance; 49 private final boolean mSupportsAzimuthalAngle; 50 private final boolean mSupportsElevationAngle; 51 private final boolean mSupportsRangingIntervalReconfigure; 52 private final Duration mMinRangingInterval; 53 private final List<Integer> mSupportedChannels; 54 private final List<Integer> mSupportedNtfConfigs; 55 private final List<Integer> mSupportedConfigIds; 56 private final List<Integer> mSupportedSlotDurations; 57 private final List<Integer> mSupportedRangingUpdateRates; 58 private final List<Integer> mSupportedPreambleIndexes; 59 private final boolean mHasBackgroundRangingSupport; 60 private final String mCountryCode; 61 UwbRangingCapabilities(Builder builder)62 private UwbRangingCapabilities(Builder builder) { 63 mSupportsDistance = builder.mSupportsDistance; 64 mSupportsAzimuthalAngle = builder.mSupportsAzimuthalAngle; 65 mSupportsElevationAngle = builder.mSupportsElevationAngle; 66 mSupportsRangingIntervalReconfigure = builder.mSupportsRangingIntervalReconfigure; 67 mMinRangingInterval = builder.mMinRangingInterval; 68 mSupportedChannels = builder.mSupportedChannels; 69 mSupportedNtfConfigs = builder.mSupportedNtfConfigs; 70 mSupportedConfigIds = builder.mSupportedConfigIds; 71 mSupportedSlotDurations = builder.mSupportedSlotDurations; 72 mSupportedRangingUpdateRates = builder.mSupportedRangingUpdateRates; 73 mSupportedPreambleIndexes = builder.mSupportedPreambleIndexes; 74 mHasBackgroundRangingSupport = builder.mHasBackgroundRangingSupport; 75 mCountryCode = builder.mCountryCode; 76 } 77 UwbRangingCapabilities(Parcel in)78 private UwbRangingCapabilities(Parcel in) { 79 mSupportsDistance = in.readByte() != 0; 80 mSupportsAzimuthalAngle = in.readByte() != 0; 81 mSupportsElevationAngle = in.readByte() != 0; 82 mSupportsRangingIntervalReconfigure = in.readByte() != 0; 83 mMinRangingInterval = Duration.ofMillis(in.readLong()); 84 mSupportedChannels = new ArrayList<>(); 85 in.readList(mSupportedChannels, Integer.class.getClassLoader(), Integer.class); 86 mSupportedNtfConfigs = new ArrayList<>(); 87 in.readList(mSupportedNtfConfigs, Integer.class.getClassLoader(), Integer.class); 88 mSupportedConfigIds = new ArrayList<>(); 89 in.readList(mSupportedConfigIds, Integer.class.getClassLoader(), Integer.class); 90 mSupportedSlotDurations = new ArrayList<>(); 91 in.readList(mSupportedSlotDurations, Integer.class.getClassLoader(), Integer.class); 92 mSupportedRangingUpdateRates = new ArrayList<>(); 93 in.readList(mSupportedRangingUpdateRates, Integer.class.getClassLoader(), Integer.class); 94 mSupportedPreambleIndexes = new ArrayList<>(); 95 in.readList(mSupportedPreambleIndexes, Integer.class.getClassLoader(), Integer.class); 96 mHasBackgroundRangingSupport = in.readByte() != 0; 97 mCountryCode = in.readString(); 98 } 99 100 @NonNull 101 public static final Creator<UwbRangingCapabilities> CREATOR = 102 new Creator<UwbRangingCapabilities>() { 103 @Override 104 public UwbRangingCapabilities createFromParcel(Parcel in) { 105 return new UwbRangingCapabilities(in); 106 } 107 108 @Override 109 public UwbRangingCapabilities[] newArray(int size) { 110 return new UwbRangingCapabilities[size]; 111 } 112 }; 113 114 /** 115 * @hide 116 */ 117 @Override getTechnology()118 public @RangingManager.RangingTechnology int getTechnology() { 119 return RangingManager.UWB; 120 } 121 122 /** 123 * Checks if the device supports distance measurement. 124 * 125 * @return {@code true} if distance measurement is supported; {@code false} otherwise. 126 */ isDistanceMeasurementSupported()127 public boolean isDistanceMeasurementSupported() { 128 return mSupportsDistance; 129 } 130 131 /** 132 * Checks if the device hardware supports azimuthal angle measurement. 133 * 134 * @return {@code true} if azimuthal angle measurement is supported; {@code false} otherwise. 135 */ isAzimuthalAngleSupported()136 public boolean isAzimuthalAngleSupported() { 137 return mSupportsAzimuthalAngle; 138 } 139 140 /** 141 * Checks if the device hardware supports elevation angle measurement. 142 * 143 * @return {@code true} if elevation angle measurement is supported; {@code false} otherwise. 144 */ isElevationAngleSupported()145 public boolean isElevationAngleSupported() { 146 return mSupportsElevationAngle; 147 } 148 149 /** 150 * Checks if the ranging interval can be reconfigured. 151 * 152 * @return {@code true} if the interval is configurable; {@code false} otherwise. 153 */ isRangingIntervalReconfigurationSupported()154 public boolean isRangingIntervalReconfigurationSupported() { 155 return mSupportsRangingIntervalReconfigure; 156 } 157 158 /** 159 * Gets the minimum supported ranging interval. 160 * 161 * @return the minimum ranging interval. 162 */ 163 @NonNull getMinimumRangingInterval()164 public Duration getMinimumRangingInterval() { 165 return mMinRangingInterval; 166 } 167 168 /** 169 * Gets the list of supported UWB channels. 170 * 171 * @return a list of supported channel numbers. 172 */ 173 @NonNull 174 @UwbChannel getSupportedChannels()175 public List<Integer> getSupportedChannels() { 176 return List.copyOf(mSupportedChannels); 177 } 178 179 180 /** 181 * Gets the list of supported preamble indexes. 182 * 183 * @return a list of supported preamble indexes. 184 * 185 */ 186 @NonNull 187 @UwbPreambleCodeIndex getSupportedPreambleIndexes()188 public List<Integer> getSupportedPreambleIndexes() { 189 return List.copyOf(mSupportedPreambleIndexes); 190 191 } 192 193 /** 194 * Gets the list of supported notification configurations. 195 * 196 * @return a list of supported notification configuration type. 197 */ 198 @NonNull 199 @NotificationConfigType getSupportedNotificationConfigurations()200 public List<Integer> getSupportedNotificationConfigurations() { 201 return List.copyOf(mSupportedNtfConfigs); 202 } 203 204 /** 205 * Gets the list of supported configuration IDs. 206 * 207 * @return a list of supported configuration IDs. 208 */ 209 @NonNull 210 @ConfigId getSupportedConfigIds()211 public List<Integer> getSupportedConfigIds() { 212 return List.copyOf(mSupportedConfigIds); 213 } 214 215 /** 216 * Gets the list of supported slot durations in microseconds. 217 * 218 * @return a list of supported slot durations. 219 */ 220 @NonNull 221 @SlotDuration getSupportedSlotDurations()222 public List<Integer> getSupportedSlotDurations() { 223 return List.copyOf(mSupportedSlotDurations); 224 } 225 226 /** 227 * Gets the list of supported ranging update rates. 228 * 229 * @return a list of supported update rates. 230 */ 231 @NonNull 232 @RangingUpdateRate getSupportedRangingUpdateRates()233 public List<Integer> getSupportedRangingUpdateRates() { 234 return List.copyOf(mSupportedRangingUpdateRates); 235 } 236 237 /** 238 * Checks if background ranging is supported. 239 * 240 * @return {@code true} if background ranging is supported; {@code false} otherwise. 241 */ isBackgroundRangingSupported()242 public boolean isBackgroundRangingSupported() { 243 return mHasBackgroundRangingSupport; 244 } 245 246 /** 247 * Get the 2-letter ISO 3166 country code. 248 * 249 * @hide 250 */ 251 @NonNull getCountryCode()252 public String getCountryCode() { 253 return mCountryCode; 254 } 255 256 /** 257 * @hide 258 */ 259 @Override describeContents()260 public int describeContents() { 261 return 0; 262 } 263 264 @Override writeToParcel(@onNull Parcel dest, int flags)265 public void writeToParcel(@NonNull Parcel dest, int flags) { 266 dest.writeByte((byte) (mSupportsDistance ? 1 : 0)); 267 dest.writeByte((byte) (mSupportsAzimuthalAngle ? 1 : 0)); 268 dest.writeByte((byte) (mSupportsElevationAngle ? 1 : 0)); 269 dest.writeByte((byte) (mSupportsRangingIntervalReconfigure ? 1 : 0)); 270 dest.writeLong(mMinRangingInterval.toMillis()); 271 dest.writeList(mSupportedChannels); 272 dest.writeList(mSupportedNtfConfigs); 273 dest.writeList(mSupportedConfigIds); 274 dest.writeList(mSupportedSlotDurations); 275 dest.writeList(mSupportedRangingUpdateRates); 276 dest.writeList(mSupportedPreambleIndexes); 277 dest.writeByte((byte) (mHasBackgroundRangingSupport ? 1 : 0)); 278 dest.writeString(mCountryCode); 279 } 280 281 /** 282 * Builder for {@link UwbRangingCapabilities} 283 * 284 * @hide 285 */ 286 public static class Builder { 287 private boolean mSupportsDistance; 288 private boolean mSupportsAzimuthalAngle; 289 private boolean mSupportsElevationAngle; 290 private boolean mSupportsRangingIntervalReconfigure; 291 private Duration mMinRangingInterval; 292 private List<Integer> mSupportedChannels; 293 private List<Integer> mSupportedNtfConfigs; 294 private List<Integer> mSupportedConfigIds; 295 private List<Integer> mSupportedSlotDurations; 296 private List<Integer> mSupportedRangingUpdateRates; 297 private List<Integer> mSupportedPreambleIndexes; 298 private boolean mHasBackgroundRangingSupport; 299 private String mCountryCode; 300 301 /** 302 * Sets supports distance. 303 * 304 * @param supportsDistance the supports distance 305 * @return the supports distance 306 */ 307 @NonNull setSupportsDistance(boolean supportsDistance)308 public Builder setSupportsDistance(boolean supportsDistance) { 309 this.mSupportsDistance = supportsDistance; 310 return this; 311 } 312 313 /** 314 * Sets supports azimuthal angle. 315 * 316 * @param supportsAzimuthalAngle the supports azimuthal angle 317 * @return the supports azimuthal angle 318 */ 319 @NonNull setSupportsAzimuthalAngle(boolean supportsAzimuthalAngle)320 public Builder setSupportsAzimuthalAngle(boolean supportsAzimuthalAngle) { 321 this.mSupportsAzimuthalAngle = supportsAzimuthalAngle; 322 return this; 323 } 324 325 /** 326 * Sets supports elevation angle. 327 * 328 * @param supportsElevationAngle the supports elevation angle 329 * @return the supports elevation angle 330 */ 331 @NonNull setSupportsElevationAngle(boolean supportsElevationAngle)332 public Builder setSupportsElevationAngle(boolean supportsElevationAngle) { 333 this.mSupportsElevationAngle = supportsElevationAngle; 334 return this; 335 } 336 337 /** 338 * Sets supports ranging interval reconfigure. 339 * 340 * @param supportsRangingIntervalReconfigure the supports ranging interval reconfigure 341 * @return the supports ranging interval reconfigure 342 */ 343 @NonNull setSupportsRangingIntervalReconfigure( boolean supportsRangingIntervalReconfigure)344 public Builder setSupportsRangingIntervalReconfigure( 345 boolean supportsRangingIntervalReconfigure) { 346 this.mSupportsRangingIntervalReconfigure = supportsRangingIntervalReconfigure; 347 return this; 348 } 349 350 /** 351 * Sets min ranging interval. 352 * 353 * @param minRangingInterval the min ranging interval 354 * @return the min ranging interval 355 */ 356 @NonNull setMinRangingInterval(Duration minRangingInterval)357 public Builder setMinRangingInterval(Duration minRangingInterval) { 358 this.mMinRangingInterval = minRangingInterval; 359 return this; 360 } 361 362 /** 363 * Sets supported channels. 364 * 365 * @param supportedChannels the supported channels 366 * @return the supported channels 367 * @throws IllegalArgumentException if the provided list is null. 368 */ 369 @NonNull setSupportedChannels(List<Integer> supportedChannels)370 public Builder setSupportedChannels(List<Integer> supportedChannels) { 371 this.mSupportedChannels = supportedChannels; 372 return this; 373 } 374 375 /** 376 * Sets preamble indexes. 377 * 378 * @param supportedPreambleIndexes the supported preamble indexes 379 * @return {@link Builder} instance. 380 * @throws IllegalArgumentException if the provided list is null. 381 */ 382 @NonNull setSupportedPreambleIndexes(List<Integer> supportedPreambleIndexes)383 public Builder setSupportedPreambleIndexes(List<Integer> supportedPreambleIndexes) { 384 this.mSupportedPreambleIndexes = supportedPreambleIndexes; 385 return this; 386 } 387 388 /** 389 * Sets supported ntf configs. 390 * 391 * @param supportedNtfConfigs the supported ntf configs 392 * @return the supported ntf configs 393 * @throws IllegalArgumentException if the provided list is null. 394 */ 395 @NonNull setSupportedNtfConfigs(@onNull List<Integer> supportedNtfConfigs)396 public Builder setSupportedNtfConfigs(@NonNull List<Integer> supportedNtfConfigs) { 397 this.mSupportedNtfConfigs = supportedNtfConfigs; 398 return this; 399 } 400 401 /** 402 * Sets supported config ids. 403 * 404 * @param supportedConfigIds the supported config ids 405 * @return the supported config ids 406 * @throws IllegalArgumentException if the provided list is null. 407 */ 408 @NonNull setSupportedConfigIds(@onNull List<Integer> supportedConfigIds)409 public Builder setSupportedConfigIds(@NonNull List<Integer> supportedConfigIds) { 410 this.mSupportedConfigIds = supportedConfigIds; 411 return this; 412 } 413 414 /** 415 * Sets supported slot durations. 416 * 417 * @param supportedSlotDurations the supported slot durations 418 * @return the supported slot durations 419 * @throws IllegalArgumentException if the provided list is null. 420 */ 421 @NonNull setSupportedSlotDurations(@onNull List<Integer> supportedSlotDurations)422 public Builder setSupportedSlotDurations(@NonNull List<Integer> supportedSlotDurations) { 423 this.mSupportedSlotDurations = supportedSlotDurations; 424 return this; 425 } 426 427 /** 428 * Sets supported ranging update rates. 429 * 430 * @param supportedRangingUpdateRates the supported ranging update rates 431 * @return the supported ranging update rates 432 * @throws IllegalArgumentException if the provided list is null. 433 */ 434 @NonNull setSupportedRangingUpdateRates( @onNull List<Integer> supportedRangingUpdateRates)435 public Builder setSupportedRangingUpdateRates( 436 @NonNull List<Integer> supportedRangingUpdateRates) { 437 this.mSupportedRangingUpdateRates = supportedRangingUpdateRates; 438 return this; 439 } 440 441 /** 442 * Sets has background ranging support. 443 * 444 * @param hasBackgroundRangingSupport the has background ranging support 445 * @return the has background ranging support 446 */ 447 @NonNull setHasBackgroundRangingSupport(boolean hasBackgroundRangingSupport)448 public Builder setHasBackgroundRangingSupport(boolean hasBackgroundRangingSupport) { 449 this.mHasBackgroundRangingSupport = hasBackgroundRangingSupport; 450 return this; 451 } 452 453 /** 454 * @param countryCode ISO 3166 country code. 455 * @return this builder instance for method chaining. 456 */ 457 @NonNull setCountryCode(String countryCode)458 public Builder setCountryCode(String countryCode) { 459 this.mCountryCode = countryCode; 460 return this; 461 } 462 463 /** 464 * Build uwb ranging capabilities. 465 * 466 * @return the uwb ranging capabilities 467 */ 468 @NonNull build()469 public UwbRangingCapabilities build() { 470 return new UwbRangingCapabilities(this); 471 } 472 } 473 474 @Override toString()475 public String toString() { 476 return "UwbRangingCapabilities{ " 477 + "mSupportsDistance=" 478 + mSupportsDistance 479 + ", mSupportsAzimuthalAngle=" 480 + mSupportsAzimuthalAngle 481 + ", mSupportsElevationAngle=" 482 + mSupportsElevationAngle 483 + ", mSupportsRangingIntervalReconfigure=" 484 + mSupportsRangingIntervalReconfigure 485 + ", mMinRangingInterval=" 486 + mMinRangingInterval 487 + ", mSupportedChannels=" 488 + mSupportedChannels 489 + ", mSupportedNtfConfigs=" 490 + mSupportedNtfConfigs 491 + ", mSupportedConfigIds=" 492 + mSupportedConfigIds 493 + ", mSupportedSlotDurations=" 494 + mSupportedSlotDurations 495 + ", mSupportedRangingUpdateRates=" 496 + mSupportedRangingUpdateRates 497 + ", mSupportedPreambleIndexes=" 498 + mSupportedPreambleIndexes 499 + ", mHasBackgroundRangingSupport=" 500 + mHasBackgroundRangingSupport 501 + ", mCountryCode=" 502 + mCountryCode 503 + " }"; 504 } 505 } 506