[ranging] Implement CS support for OOB Initiator

Bug: 372106978
Test: atest MultiDeviceRangingTestCases

Change-Id: Ib20dab6f15046bccc329b00656bcf1cc8d04514e
diff --git a/ranging/framework/java/android/ranging/ble/cs/BleCsRangingCapabilities.java b/ranging/framework/java/android/ranging/ble/cs/BleCsRangingCapabilities.java
index 08341ab..66d659e 100644
--- a/ranging/framework/java/android/ranging/ble/cs/BleCsRangingCapabilities.java
+++ b/ranging/framework/java/android/ranging/ble/cs/BleCsRangingCapabilities.java
@@ -26,8 +26,10 @@
 
 import com.android.ranging.flags.Flags;
 
+import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -42,6 +44,7 @@
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
+    @Target({ElementType.TYPE_USE})
     @IntDef({
             CS_SECURITY_LEVEL_ONE,
             CS_SECURITY_LEVEL_FOUR,
diff --git a/ranging/service/java/com/android/server/ranging/RangingEngine.java b/ranging/service/java/com/android/server/ranging/RangingEngine.java
index a7215b9..95f1faa 100644
--- a/ranging/service/java/com/android/server/ranging/RangingEngine.java
+++ b/ranging/service/java/com/android/server/ranging/RangingEngine.java
@@ -25,12 +25,17 @@
 import android.ranging.RangingDevice;
 import android.ranging.SessionConfig;
 import android.ranging.SessionHandle;
+import android.ranging.ble.cs.BleCsRangingCapabilities;
 import android.ranging.oob.OobInitiatorRangingConfig;
 import android.ranging.uwb.UwbRangingCapabilities;
 import android.util.Log;
 
 import androidx.annotation.Nullable;
 
+import com.android.server.ranging.cs.CsConfigSelector;
+import com.android.server.ranging.cs.CsConfigSelector.SelectedCsConfig;
+import com.android.server.ranging.cs.CsOobCapabilities;
+import com.android.server.ranging.cs.CsOobConfig;
 import com.android.server.ranging.oob.CapabilityResponseMessage;
 import com.android.server.ranging.oob.MessageType;
 import com.android.server.ranging.oob.OobHeader;
@@ -57,7 +62,8 @@
     private final EnumSet<RangingTechnology> mRequestedTechnologies;
     private final Map<RangingDevice, EnumSet<RangingTechnology>> mPeerTechnologies;
 
-    private final @Nullable UwbConfigSelector mUwbConfigSelector;
+    private @Nullable UwbConfigSelector mUwbConfigSelector = null;
+    private @Nullable CsConfigSelector mCsConfigSelector = null;
 
     public static class ConfigSelectionException extends Exception {
         public ConfigSelectionException(String message) {
@@ -102,12 +108,14 @@
             mRequestedTechnologies.add(RangingTechnology.UWB);
             mUwbConfigSelector = new UwbConfigSelector(
                     sessionConfig, oobConfig, uwbCapabilities, sessionHandle);
-        } else {
-            mUwbConfigSelector = null;
         }
 
         if (oobConfig.getRangingMode() != RANGING_MODE_HIGH_ACCURACY) {
-            // TODO: Other technologies
+            BleCsRangingCapabilities csCapabilities = localCapabilities.getCsCapabilities();
+            if (CsConfigSelector.isCapableOfConfig(oobConfig, csCapabilities)) {
+                mRequestedTechnologies.add(RangingTechnology.CS);
+                mCsConfigSelector = new CsConfigSelector(sessionConfig, oobConfig);
+            }
         }
 
         if (mRequestedTechnologies.isEmpty()) {
@@ -126,14 +134,21 @@
 
         EnumSet<RangingTechnology> selectedTechnologies =
                 selectTechnologiesToUseWithPeer(capabilities);
+
         UwbOobCapabilities uwbCapabilities = capabilities.getUwbCapabilities();
+        CsOobCapabilities csCapabilities = capabilities.getCsCapabilities();
+
         for (RangingTechnology technology : selectedTechnologies) {
-            // TODO: Other technologies
             if (technology == RangingTechnology.UWB
                     && uwbCapabilities != null
                     && mUwbConfigSelector != null
             ) {
                 mUwbConfigSelector.restrictConfigToCapabilities(device, uwbCapabilities);
+            } else if (technology == RangingTechnology.CS
+                    && csCapabilities != null
+                    && mCsConfigSelector != null
+            ) {
+                mCsConfigSelector.restrictConfigToCapabilities(device, csCapabilities);
             } else {
                 Log.e(TAG, "Technology " + technology + " was selected by us and peer " + device
                         + ", but one of us does not actually support it");
@@ -146,33 +161,42 @@
 
     public SelectedConfig selectConfigs() throws ConfigSelectionException {
         ImmutableSet.Builder<TechnologyConfig> localConfigs = ImmutableSet.builder();
-        ImmutableMap.Builder<RangingDevice, SetConfigurationMessage> peerConfigs =
+        ImmutableMap.Builder<RangingDevice, SetConfigurationMessage> configMessages =
                 ImmutableMap.builder();
 
         Map<RangingDevice, UwbOobConfig> uwbConfigsByPeer = new HashMap<>();
-        if (mUwbConfigSelector != null) {
+        if (mUwbConfigSelector != null && mUwbConfigSelector.hasPeersToConfigure()) {
             SelectedUwbConfig uwbConfig = mUwbConfigSelector.selectConfig();
             localConfigs.add(uwbConfig.getLocalConfig());
             uwbConfigsByPeer.putAll(uwbConfig.getPeerConfigs());
         }
 
+        Map<RangingDevice, CsOobConfig> csConfigsByPeer = new HashMap<>();
+        if (mCsConfigSelector != null && mCsConfigSelector.hasPeersToConfigure()) {
+            SelectedCsConfig csConfig = mCsConfigSelector.selectConfig();
+            localConfigs.addAll(csConfig.getLocalConfigs());
+            csConfigsByPeer.putAll(csConfig.getPeerConfigs());
+        }
+
         for (RangingDevice peer : mPeerTechnologies.keySet()) {
+            ImmutableList<RangingTechnology> peerTechnologies =
+                    ImmutableList.copyOf(mPeerTechnologies.get(peer));
+
             SetConfigurationMessage.Builder configMessage = SetConfigurationMessage.builder()
                     .setHeader(OobHeader.builder()
                             .setMessageType(MessageType.SET_CONFIGURATION)
                             .setVersion(OobHeader.OobVersion.CURRENT)
                             .build())
-                    .setRangingTechnologiesSet(ImmutableList.copyOf(mRequestedTechnologies))
-                    .setStartRangingList(ImmutableList.copyOf(mRequestedTechnologies));
+                    .setRangingTechnologiesSet(peerTechnologies)
+                    .setStartRangingList(peerTechnologies);
 
-            if (uwbConfigsByPeer.containsKey(peer)) {
-                configMessage.setUwbConfig(uwbConfigsByPeer.get(peer));
-            }
+            configMessage.setUwbConfig(uwbConfigsByPeer.get(peer));
+            configMessage.setCsConfig(csConfigsByPeer.get(peer));
 
-            peerConfigs.put(peer, configMessage.build());
+            configMessages.put(peer, configMessage.build());
         }
 
-        return new SelectedConfig(localConfigs.build(), peerConfigs.build());
+        return new SelectedConfig(localConfigs.build(), configMessages.build());
     }
 
     private EnumSet<RangingTechnology> selectTechnologiesToUseWithPeer(
diff --git a/ranging/service/java/com/android/server/ranging/cs/CsConfig.java b/ranging/service/java/com/android/server/ranging/cs/CsConfig.java
index ee81011..0dd586b 100644
--- a/ranging/service/java/com/android/server/ranging/cs/CsConfig.java
+++ b/ranging/service/java/com/android/server/ranging/cs/CsConfig.java
@@ -16,18 +16,35 @@
 
 package com.android.server.ranging.cs;
 
+import static android.ranging.raw.RawRangingDevice.UPDATE_RATE_FREQUENT;
+import static android.ranging.raw.RawRangingDevice.UPDATE_RATE_INFREQUENT;
+import static android.ranging.raw.RawRangingDevice.UPDATE_RATE_NORMAL;
+
 import android.annotation.NonNull;
 import android.ranging.RangingDevice;
 import android.ranging.RangingPreference;
 import android.ranging.SessionConfig;
 import android.ranging.ble.cs.BleCsRangingParams;
+import android.ranging.raw.RawRangingDevice;
 
 import com.android.server.ranging.RangingTechnology;
 import com.android.server.ranging.session.RangingSessionConfig.UnicastTechnologyConfig;
 
+import com.google.common.collect.ImmutableMap;
+
+import java.time.Duration;
+
 public class CsConfig implements UnicastTechnologyConfig {
     private static final String TAG = CsConfig.class.getSimpleName();
 
+    // TODO(390665219): Update this once we decide on a set of measurement intervals for channel
+    //  sounding.
+    public static final ImmutableMap<@RawRangingDevice.RangingUpdateRate Integer, Duration>
+            CS_UPDATE_RATE_DURATIONS = ImmutableMap.of(
+                    UPDATE_RATE_NORMAL, Duration.ofSeconds(3),
+                    UPDATE_RATE_INFREQUENT, Duration.ofSeconds(5),
+                    UPDATE_RATE_FREQUENT, Duration.ofMillis(200));
+
     private final SessionConfig mSessionConfig;
     private final BleCsRangingParams mRangingParams;
 
diff --git a/ranging/service/java/com/android/server/ranging/cs/CsConfigSelector.java b/ranging/service/java/com/android/server/ranging/cs/CsConfigSelector.java
new file mode 100644
index 0000000..3204904
--- /dev/null
+++ b/ranging/service/java/com/android/server/ranging/cs/CsConfigSelector.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.ranging.cs;
+
+import static android.ranging.RangingPreference.DEVICE_ROLE_INITIATOR;
+import static android.ranging.ble.cs.BleCsRangingCapabilities.CS_SECURITY_LEVEL_FOUR;
+import static android.ranging.ble.cs.BleCsRangingCapabilities.CS_SECURITY_LEVEL_ONE;
+import static android.ranging.raw.RawRangingDevice.UPDATE_RATE_FREQUENT;
+import static android.ranging.raw.RawRangingDevice.UPDATE_RATE_INFREQUENT;
+import static android.ranging.raw.RawRangingDevice.UPDATE_RATE_NORMAL;
+
+import static com.android.server.ranging.cs.CsConfig.CS_UPDATE_RATE_DURATIONS;
+
+import android.ranging.RangingDevice;
+import android.ranging.SessionConfig;
+import android.ranging.ble.cs.BleCsRangingCapabilities;
+import android.ranging.ble.cs.BleCsRangingParams;
+import android.ranging.oob.OobInitiatorRangingConfig;
+import android.ranging.raw.RawRangingDevice;
+import android.util.Range;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.server.ranging.RangingEngine.ConfigSelectionException;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+
+public class CsConfigSelector {
+    private final SessionConfig mSessionConfig;
+    private final OobInitiatorRangingConfig mOobConfig;
+    private final BiMap<RangingDevice, String> mPeerAddresses;
+    private final Map<RangingDevice, @BleCsRangingCapabilities.SecurityLevel Integer>
+            mPeerSecurityLevels;
+
+    public static boolean isCapableOfConfig(
+            @NonNull OobInitiatorRangingConfig oobConfig,
+            @Nullable BleCsRangingCapabilities capabilities
+    ) {
+        if (capabilities == null) return false;
+
+        if (!(capabilities.getSupportedSecurityLevels().contains(CS_SECURITY_LEVEL_ONE)
+                || capabilities.getSupportedSecurityLevels().contains(CS_SECURITY_LEVEL_FOUR))
+        ) return false;
+
+        if (getDurationFromUpdateRate(oobConfig.getRangingIntervalRange()).isEmpty()) return false;
+
+        return true;
+    }
+
+    public CsConfigSelector(
+            @NonNull SessionConfig sessionConfig,
+            @NonNull OobInitiatorRangingConfig oobConfig
+    ) {
+        mSessionConfig = sessionConfig;
+        mOobConfig = oobConfig;
+        mPeerAddresses = HashBiMap.create();
+        mPeerSecurityLevels = new HashMap<>();
+    }
+
+    public void restrictConfigToCapabilities(
+            @NonNull RangingDevice peer, @NonNull CsOobCapabilities capabilities
+    ) throws ConfigSelectionException {
+        mPeerAddresses.put(peer, capabilities.getBluetoothAddress());
+
+        if (mOobConfig.getSecurityLevel() == OobInitiatorRangingConfig.SECURITY_LEVEL_BASIC) {
+            if (capabilities.getSupportedSecurityTypes()
+                    .contains(CsOobConfig.CsSecurityType.LEVEL_ONE)
+            ) {
+                mPeerSecurityLevels.put(peer, CS_SECURITY_LEVEL_ONE);
+            } else {
+                throw new ConfigSelectionException("Configured security level "
+                        + OobInitiatorRangingConfig.SECURITY_LEVEL_BASIC + " but " + peer
+                        + " only supports " + capabilities.getSupportedSecurityTypes());
+            }
+        } else {
+            if (capabilities.getSupportedSecurityTypes()
+                    .contains(CsOobConfig.CsSecurityType.LEVEL_FOUR)
+            ) {
+                mPeerSecurityLevels.put(peer, CS_SECURITY_LEVEL_FOUR);
+            } else if (capabilities.getSupportedSecurityTypes()
+                    .contains(CsOobConfig.CsSecurityType.LEVEL_ONE)
+            ) {
+                mPeerSecurityLevels.put(peer, CS_SECURITY_LEVEL_ONE);
+            } else {
+                throw new ConfigSelectionException("Configured security level "
+                        + OobInitiatorRangingConfig.SECURITY_LEVEL_SECURE + " but " + peer
+                        + " only supports " + capabilities.getSupportedSecurityTypes());
+            }
+        }
+    }
+
+    public boolean hasPeersToConfigure() {
+        return !mPeerAddresses.isEmpty();
+    }
+
+    public @NonNull SelectedCsConfig selectConfig() throws ConfigSelectionException {
+        return new SelectedCsConfig();
+    }
+
+    public class SelectedCsConfig {
+        private final @RawRangingDevice.RangingUpdateRate int mRangingUpdateRate;
+
+        SelectedCsConfig() throws ConfigSelectionException {
+            mRangingUpdateRate = selectRangingUpdateRate();
+        }
+
+        public @NonNull ImmutableSet<CsConfig> getLocalConfigs() {
+            return mPeerAddresses.entrySet().stream()
+                    .map((entry) -> new CsConfig(
+                            DEVICE_ROLE_INITIATOR,
+                            new BleCsRangingParams.Builder(entry.getValue())
+                                    .setRangingUpdateRate(mRangingUpdateRate)
+                                    .setSecurityLevel(mPeerSecurityLevels.get(entry.getKey()))
+                                    .build(),
+                            mSessionConfig,
+                            entry.getKey()))
+                    .collect(ImmutableSet.toImmutableSet());
+        }
+
+        public @NonNull ImmutableMap<RangingDevice, CsOobConfig> getPeerConfigs() {
+            CsOobConfig config = CsOobConfig.builder().build();
+            return mPeerAddresses.keySet().stream()
+                    .collect(ImmutableMap.toImmutableMap(Function.identity(), (unused) -> config));
+        }
+    }
+
+    private @RawRangingDevice.RangingUpdateRate int selectRangingUpdateRate()
+            throws ConfigSelectionException {
+
+        return getDurationFromUpdateRate(mOobConfig.getRangingIntervalRange())
+                .orElseThrow(() -> new ConfigSelectionException(
+                        "Configured ranging interval range is incompatible with BLE CS"));
+    }
+
+
+    private static Optional<@RawRangingDevice.RangingUpdateRate Integer> getDurationFromUpdateRate(
+            Range<Duration> configuredRates
+    ) {
+        if (configuredRates.contains(CS_UPDATE_RATE_DURATIONS.get(UPDATE_RATE_FREQUENT))) {
+            return Optional.of(UPDATE_RATE_FREQUENT);
+        } else if (configuredRates.contains(CS_UPDATE_RATE_DURATIONS.get(UPDATE_RATE_NORMAL))) {
+            return Optional.of(UPDATE_RATE_NORMAL);
+        } else if (configuredRates.contains(CS_UPDATE_RATE_DURATIONS.get(UPDATE_RATE_INFREQUENT))) {
+            return Optional.of(UPDATE_RATE_INFREQUENT);
+        } else {
+            return Optional.empty();
+        }
+    }
+}
diff --git a/ranging/service/java/com/android/server/ranging/cs/CsOobCapabilities.java b/ranging/service/java/com/android/server/ranging/cs/CsOobCapabilities.java
index 7c3c685..4099f54 100644
--- a/ranging/service/java/com/android/server/ranging/cs/CsOobCapabilities.java
+++ b/ranging/service/java/com/android/server/ranging/cs/CsOobCapabilities.java
@@ -16,6 +16,8 @@
 
 package com.android.server.ranging.cs;
 
+import android.ranging.ble.cs.BleCsRangingCapabilities;
+
 import com.android.server.ranging.RangingTechnology;
 import com.android.server.ranging.RangingUtils.Conversions;
 import com.android.server.ranging.cs.CsOobConfig.CsSecurityType;
@@ -121,6 +123,17 @@
         return byteBuffer.array();
     }
 
+    public static CsOobCapabilities fromRangingCapabilities(
+            BleCsRangingCapabilities capabilities, String address
+    ) {
+        return CsOobCapabilities.builder()
+                .setBluetoothAddress(address)
+                .setSupportedSecurityTypes(capabilities.getSupportedSecurityLevels().stream()
+                        .map(CsSecurityType.SECURITY_TYPES::get)
+                        .collect(ImmutableList.toImmutableList()))
+                .build();
+    }
+
     /** Returns the security type for CS. */
     public abstract ImmutableList<CsSecurityType> getSupportedSecurityTypes();
 
diff --git a/ranging/service/java/com/android/server/ranging/cs/CsOobConfig.java b/ranging/service/java/com/android/server/ranging/cs/CsOobConfig.java
index 487596d..eafa7a5 100644
--- a/ranging/service/java/com/android/server/ranging/cs/CsOobConfig.java
+++ b/ranging/service/java/com/android/server/ranging/cs/CsOobConfig.java
@@ -20,6 +20,7 @@
 import com.android.server.ranging.oob.TechnologyHeader;
 
 import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
 
 import java.nio.ByteBuffer;
 
@@ -42,6 +43,9 @@
         LEVEL_THREE(3),
         LEVEL_FOUR(4);
 
+        public static final ImmutableList<CsSecurityType> SECURITY_TYPES =
+                ImmutableList.copyOf(CsSecurityType.values());
+
         private final int mValue;
 
         CsSecurityType(int value) {
diff --git a/ranging/service/java/com/android/server/ranging/oob/SetConfigurationMessage.java b/ranging/service/java/com/android/server/ranging/oob/SetConfigurationMessage.java
index 2c5f70f..ac09ee7 100644
--- a/ranging/service/java/com/android/server/ranging/oob/SetConfigurationMessage.java
+++ b/ranging/service/java/com/android/server/ranging/oob/SetConfigurationMessage.java
@@ -17,6 +17,7 @@
 package com.android.server.ranging.oob;
 
 import com.android.server.ranging.RangingTechnology;
+import com.android.server.ranging.cs.CsOobConfig;
 import com.android.server.ranging.uwb.UwbOobConfig;
 
 import com.google.auto.value.AutoValue;
@@ -73,6 +74,7 @@
 
         // Parse Configs for ranging technologies that are set
         UwbOobConfig uwbConfig = null;
+        CsOobConfig csConfig = null;
         int countTechsParsed = 0;
         while (parseCursor < payload.length && countTechsParsed++ < rangingTechnologiesSet.size()) {
             byte[] remainingBytes = Arrays.copyOfRange(payload, parseCursor, payload.length);
@@ -87,6 +89,15 @@
                     uwbConfig = UwbOobConfig.parseBytes(remainingBytes);
                     parseCursor += uwbConfig.getSize();
                     break;
+                case CS:
+                    if (csConfig != null) {
+                        throw new IllegalArgumentException(
+                                "Failed to parse SetConfigurationMessage, CsConfig already set. "
+                                        + "Bytes: " + Arrays.toString(payload));
+                    }
+                    csConfig = CsOobConfig.parseBytes(remainingBytes);
+                    parseCursor += csConfig.getSize();
+                    break;
                 default:
                     parseCursor += techHeader.getSize();
             }
@@ -134,6 +145,10 @@
     @Nullable
     public abstract UwbOobConfig getUwbConfig();
 
+    /** Returns @Nullable CsConfig data that should be used to configure CS ranging session. */
+    @Nullable
+    public abstract CsOobConfig getCsConfig();
+
     /** Returns a builder for {@link SetConfigurationMessage}. */
     public static Builder builder() {
         return new AutoValue_SetConfigurationMessage.Builder()
@@ -156,6 +171,8 @@
 
         public abstract Builder setUwbConfig(@Nullable UwbOobConfig uwbConfig);
 
+        public abstract Builder setCsConfig(@Nullable CsOobConfig csConfig);
+
         abstract SetConfigurationMessage autoBuild();
 
         public SetConfigurationMessage build() {
@@ -171,6 +188,12 @@
                             .contains(RangingTechnology.UWB)
                             == (setConfigurationMessage.getUwbConfig() != null),
                     "UwbConfig or rangingTechnologiesSet for UWB not set properly.");
+            Preconditions.checkArgument(
+                    setConfigurationMessage
+                            .getRangingTechnologiesSet()
+                            .contains(RangingTechnology.CS)
+                            == (setConfigurationMessage.getCsConfig() != null),
+                    "csConfig or rangingTechnologiesSet for CS not set properly.");
             return setConfigurationMessage;
         }
     }
diff --git a/ranging/service/java/com/android/server/ranging/session/OobResponderRangingSession.java b/ranging/service/java/com/android/server/ranging/session/OobResponderRangingSession.java
index 26697ec..6d33fc0 100644
--- a/ranging/service/java/com/android/server/ranging/session/OobResponderRangingSession.java
+++ b/ranging/service/java/com/android/server/ranging/session/OobResponderRangingSession.java
@@ -128,7 +128,7 @@
             if (uwbCapabilities != null) {
                 supportedTechnologies.add(RangingTechnology.UWB);
                 response.setUwbCapabilities(
-                        UwbOobCapabilities.fromUwbCapabilities(uwbCapabilities, mMyUwbAddress));
+                        UwbOobCapabilities.fromRangingCapabilities(uwbCapabilities, mMyUwbAddress));
             }
         }
         // TODO: Other technologies
diff --git a/ranging/service/java/com/android/server/ranging/uwb/UwbConfigSelector.java b/ranging/service/java/com/android/server/ranging/uwb/UwbConfigSelector.java
index e937341..c1727c7 100644
--- a/ranging/service/java/com/android/server/ranging/uwb/UwbConfigSelector.java
+++ b/ranging/service/java/com/android/server/ranging/uwb/UwbConfigSelector.java
@@ -171,6 +171,10 @@
         }
     }
 
+    public boolean hasPeersToConfigure() {
+        return !mPeerAddresses.isEmpty();
+    }
+
     public @NonNull SelectedUwbConfig selectConfig() throws ConfigSelectionException {
         return new SelectedUwbConfig();
     }
diff --git a/ranging/service/java/com/android/server/ranging/uwb/UwbOobCapabilities.java b/ranging/service/java/com/android/server/ranging/uwb/UwbOobCapabilities.java
index 99bb2b3..d974297 100644
--- a/ranging/service/java/com/android/server/ranging/uwb/UwbOobCapabilities.java
+++ b/ranging/service/java/com/android/server/ranging/uwb/UwbOobCapabilities.java
@@ -188,7 +188,7 @@
         return byteBuffer.array();
     }
 
-    public static UwbOobCapabilities fromUwbCapabilities(
+    public static UwbOobCapabilities fromRangingCapabilities(
             UwbRangingCapabilities capabilities, UwbAddress address
     ) {
         return UwbOobCapabilities.builder()