1 /* 2 * Copyright (C) 2025 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.rtt; 18 19 import android.ranging.wifi.rtt.RttRangingCapabilities; 20 21 import com.android.server.ranging.RangingTechnology; 22 import com.android.server.ranging.RangingUtils; 23 import com.android.server.ranging.oob.TechnologyHeader; 24 25 import com.google.auto.value.AutoValue; 26 import com.google.common.collect.ImmutableList; 27 28 import java.nio.ByteBuffer; 29 import java.util.Arrays; 30 31 @AutoValue 32 public abstract class RttOobCapabilities { 33 34 /** Size in bytes of all properties when serialized. */ 35 private static final int EXPECTED_SIZE_BYTES = 6; 36 37 private static final int RTT_SUPPORTED_FEATURES_SIZE = 1; 38 private static final int RTT_SUPPORTED_FEATURES_SHIFT = 0; 39 parseBytes(byte[] capabilitiesBytes)40 public static RttOobCapabilities parseBytes(byte[] capabilitiesBytes) { 41 TechnologyHeader header = TechnologyHeader.parseBytes(capabilitiesBytes); 42 43 if (capabilitiesBytes.length < EXPECTED_SIZE_BYTES) { 44 throw new IllegalArgumentException( 45 String.format( 46 "RttOobCapabilities size is %d, expected at least %d", 47 capabilitiesBytes.length, EXPECTED_SIZE_BYTES)); 48 } 49 50 if (capabilitiesBytes.length < header.getSize()) { 51 throw new IllegalArgumentException( 52 String.format( 53 "RttOobCapabilities header size field is %d, but the size of the array" 54 + " is" 55 + " %d", 56 header.getSize(), capabilitiesBytes.length)); 57 } 58 59 if (header.getRangingTechnology() != RangingTechnology.RTT) { 60 throw new IllegalArgumentException( 61 String.format( 62 "RttOobCapabilities header technology field is %s, expected %s", 63 header.getRangingTechnology(), RangingTechnology.RTT)); 64 } 65 66 int parseCursor = header.getHeaderSize(); 67 68 ImmutableList<RttOobConfig.RttSupportedFeatures> supportedFeatures = 69 RangingUtils.Conversions.byteArrayToIntList( 70 Arrays.copyOfRange(capabilitiesBytes, parseCursor, 71 parseCursor + RTT_SUPPORTED_FEATURES_SIZE), 72 RTT_SUPPORTED_FEATURES_SHIFT) 73 .stream() 74 .map(RttOobConfig.RttSupportedFeatures::fromValue) 75 .collect(ImmutableList.toImmutableList()); 76 parseCursor += RTT_SUPPORTED_FEATURES_SIZE; 77 78 boolean periodicRangingSupport = capabilitiesBytes[parseCursor++] != 0; 79 int maxBandwidth = capabilitiesBytes[parseCursor++]; 80 int maxSupportedRxChain = capabilitiesBytes[parseCursor++]; 81 82 return RttOobCapabilities.builder() 83 //.setSupportedFeatures(supportedFeatures) 84 .setHasPeriodicRangingSupport(periodicRangingSupport) 85 .setMaxSupportedBandwidth(maxBandwidth) 86 .setMaxSupportedRxChain(maxSupportedRxChain) 87 .build(); 88 } 89 toBytes()90 public final byte[] toBytes() { 91 ByteBuffer byteBuffer = ByteBuffer.allocate(EXPECTED_SIZE_BYTES); 92 byteBuffer 93 .put(RangingTechnology.RTT.toByte()) 94 .put((byte) EXPECTED_SIZE_BYTES) 95 .put((byte) 1) // TODO: how to check for 11mc or 11az support 96 .put((byte) (hasPeriodicRangingSupport() ? 1 : 0)) 97 .put((byte) maxSupportedBandwidth()) 98 .put((byte) maxSupportedRxChain()); 99 100 return byteBuffer.array(); 101 } 102 fromRangingCapabilities(RttRangingCapabilities capabilities)103 public static RttOobCapabilities fromRangingCapabilities(RttRangingCapabilities capabilities) { 104 return RttOobCapabilities.builder() 105 .setHasPeriodicRangingSupport(capabilities.hasPeriodicRangingHardwareFeature()) 106 .setMaxSupportedBandwidth(capabilities.getMaxSupportedBandwidth()) 107 .setMaxSupportedRxChain(capabilities.getMaxSupportedRxChain()) 108 .build(); 109 } 110 111 //public abstract ImmutableList<RttOobConfig.RttSupportedFeatures> supportedFeatures(); hasPeriodicRangingSupport()112 public abstract boolean hasPeriodicRangingSupport(); 113 maxSupportedBandwidth()114 public abstract int maxSupportedBandwidth(); 115 maxSupportedRxChain()116 public abstract int maxSupportedRxChain(); 117 builder()118 public static Builder builder() { 119 return new AutoValue_RttOobCapabilities.Builder(); 120 } 121 122 @AutoValue.Builder 123 public abstract static class Builder { 124 //public abstract Builder setSupportedFeatures( 125 //ImmutableList<RttOobConfig.RttSupportedFeatures> value); setHasPeriodicRangingSupport(boolean value)126 public abstract Builder setHasPeriodicRangingSupport(boolean value); 127 setMaxSupportedBandwidth(int value)128 public abstract Builder setMaxSupportedBandwidth(int value); 129 setMaxSupportedRxChain(int value)130 public abstract Builder setMaxSupportedRxChain(int value); 131 autoBuild()132 public abstract RttOobCapabilities autoBuild(); 133 build()134 public RttOobCapabilities build() { 135 return autoBuild(); 136 } 137 } 138 } 139