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 android.ranging.RangingPreference.DEVICE_ROLE_RESPONDER; 20 21 import android.ranging.DataNotificationConfig; 22 import android.ranging.RangingDevice; 23 import android.ranging.RangingPreference; 24 import android.ranging.SessionConfig; 25 import android.ranging.uwb.UwbAddress; 26 import android.ranging.uwb.UwbComplexChannel; 27 import android.ranging.uwb.UwbRangingParams; 28 29 import androidx.annotation.NonNull; 30 31 import com.android.ranging.uwb.backend.internal.RangingParameters; 32 import com.android.ranging.uwb.backend.internal.UwbRangeDataNtfConfig; 33 import com.android.ranging.uwb.backend.internal.UwbRangeLimitsConfig; 34 import com.android.server.ranging.RangingTechnology; 35 import com.android.server.ranging.session.RangingSessionConfig.MulticastTechnologyConfig; 36 37 import com.google.common.collect.ImmutableBiMap; 38 import com.google.common.collect.ImmutableSet; 39 import com.google.uwb.support.base.RequiredParam; 40 41 import java.util.List; 42 import java.util.Objects; 43 import java.util.stream.Collectors; 44 45 /** 46 * A complete configuration for UWB ranging. This encapsulates all information contained in a 47 * configuration message sent over OOB and everything required to start a session in the underlying 48 * UWB system API. 49 */ 50 public class UwbConfig implements MulticastTechnologyConfig { 51 private static final String TAG = UwbConfig.class.getSimpleName(); 52 53 private final SessionConfig mSessionConfig; 54 private final UwbRangingParams mParameters; 55 private final int mDeviceRole; 56 private final ImmutableBiMap<RangingDevice, UwbAddress> mPeerAddresses; 57 UwbConfig(Builder builder)58 private UwbConfig(Builder builder) { 59 mParameters = builder.mParameters; 60 mSessionConfig = builder.mSessionConfig; 61 mDeviceRole = builder.mDeviceRole; 62 mPeerAddresses = builder.mPeerAddresses.get(); 63 } 64 65 @Override getTechnology()66 public @NonNull RangingTechnology getTechnology() { 67 return RangingTechnology.UWB; 68 } 69 70 @Override getPeerDevices()71 public @NonNull ImmutableSet<RangingDevice> getPeerDevices() { 72 return mPeerAddresses.keySet(); 73 } 74 75 /** Returns the length of the session key. */ getSessionKeyInfoLength()76 public final int getSessionKeyInfoLength() { 77 if (mParameters.getSessionKeyInfo() == null) { 78 return 0; 79 } else { 80 return mParameters.getSessionKeyInfo().length; 81 } 82 } 83 getParameters()84 public @NonNull UwbRangingParams getParameters() { 85 return mParameters; 86 } 87 88 @Override getDeviceRole()89 public @RangingPreference.DeviceRole int getDeviceRole() { 90 return mDeviceRole; 91 } 92 getSessionConfig()93 public SessionConfig getSessionConfig() { 94 return mSessionConfig; 95 } 96 getPeerAddresses()97 public @NonNull ImmutableBiMap<RangingDevice, UwbAddress> getPeerAddresses() { 98 return mPeerAddresses; 99 } 100 101 102 /** 103 * @return the configuration converted to a 104 * {@link androidx.core.uwb.backend.impl.internal.RangingParameters} accepted by the UWB 105 * backend. 106 */ asBackendParameters(DataNotificationConfig dataNotificationConfig)107 public RangingParameters asBackendParameters(DataNotificationConfig dataNotificationConfig) { 108 List<com.android.ranging.uwb.backend.internal.UwbAddress> peerAddresses = mPeerAddresses 109 .values() 110 .stream() 111 .map((address) -> 112 com.android.ranging.uwb.backend.internal.UwbAddress.fromBytes( 113 address.getAddressBytes())) 114 .collect(Collectors.toList()); 115 return new RangingParameters( 116 (int) mParameters.getConfigId(), 117 mParameters.getSessionId(), 118 mParameters.getSubSessionId(), 119 mParameters.getSessionKeyInfo(), 120 mParameters.getSubSessionKeyInfo(), 121 toBackend(mParameters.getComplexChannel()), 122 peerAddresses, 123 (int) mParameters.getRangingUpdateRate(), 124 toBackend(dataNotificationConfig), 125 (int) mParameters.getSlotDuration(), 126 // RangingParameters has isAoaDisabled field, Inverting here. 127 !mSessionConfig.isAngleOfArrivalNeeded(), 128 new UwbRangeLimitsConfig.Builder().setRangeMaxNumberOfMeasurements( 129 mSessionConfig.getRangingMeasurementsLimit() 130 ).build() 131 ); 132 } 133 toBackend( @onNull DataNotificationConfig rangeDataNtfConfig )134 public static @NonNull UwbRangeDataNtfConfig toBackend( 135 @NonNull DataNotificationConfig rangeDataNtfConfig 136 ) { 137 return new UwbRangeDataNtfConfig.Builder() 138 .setRangeDataConfigType((int) rangeDataNtfConfig.getNotificationConfigType()) 139 .setNtfProximityNear(rangeDataNtfConfig.getProximityNearCm()) 140 .setNtfProximityFar(rangeDataNtfConfig.getProximityFarCm()) 141 .build(); 142 } 143 toBackend( @onNull UwbComplexChannel complexChannel )144 public static @NonNull com.android.ranging.uwb.backend.internal.UwbComplexChannel toBackend( 145 @NonNull UwbComplexChannel complexChannel 146 ) { 147 return new com.android.ranging.uwb.backend.internal.UwbComplexChannel( 148 (int) complexChannel.getChannel(), (int) complexChannel.getPreambleIndex()); 149 } 150 toBackend( @onNull UwbAddress address )151 public static @NonNull com.android.ranging.uwb.backend.internal.UwbAddress toBackend( 152 @NonNull UwbAddress address 153 ) { 154 return com.android.ranging.uwb.backend.internal.UwbAddress.fromBytes( 155 address.getAddressBytes()); 156 } 157 158 159 /** Builder for {@link UwbConfig}. */ 160 public static class Builder { 161 private final UwbRangingParams mParameters; 162 private final RequiredParam<ImmutableBiMap<RangingDevice, UwbAddress>> mPeerAddresses = 163 new RequiredParam<>(); 164 private SessionConfig mSessionConfig = new SessionConfig.Builder().build(); 165 166 private int mDeviceRole = DEVICE_ROLE_RESPONDER; 167 private boolean mIsAoaNeeded = false; 168 Builder(@onNull UwbRangingParams parameters)169 public Builder(@NonNull UwbRangingParams parameters) { 170 mParameters = parameters; 171 } 172 build()173 public @NonNull UwbConfig build() { 174 return new UwbConfig(this); 175 } 176 setPeerAddresses( @onNull ImmutableBiMap<RangingDevice, UwbAddress> addresses )177 public Builder setPeerAddresses( 178 @NonNull ImmutableBiMap<RangingDevice, UwbAddress> addresses 179 ) { 180 mPeerAddresses.set(addresses); 181 return this; 182 } 183 setDeviceRole(@angingPreference.DeviceRole int deviceRole)184 public Builder setDeviceRole(@RangingPreference.DeviceRole int deviceRole) { 185 mDeviceRole = deviceRole; 186 return this; 187 } 188 setSessionConfig(SessionConfig sessionConfig)189 public Builder setSessionConfig(SessionConfig sessionConfig) { 190 mSessionConfig = sessionConfig; 191 return this; 192 } 193 } 194 195 @Override toString()196 public String toString() { 197 return "UwbConfig{" 198 + "mParameters=" 199 + mParameters 200 + ", mSessionConfig=" 201 + mSessionConfig 202 + ", mDeviceRole=" 203 + mDeviceRole 204 + ", mPeerAddresses=" 205 + mPeerAddresses 206 + " }"; 207 } 208 209 @Override equals(Object o)210 public boolean equals(Object o) { 211 if (this == o) return true; 212 if (!(o instanceof UwbConfig uwbConfig)) return false; 213 return mDeviceRole == uwbConfig.mDeviceRole && Objects.equals(mSessionConfig, 214 uwbConfig.mSessionConfig) && Objects.equals(mParameters, 215 uwbConfig.mParameters) && Objects.equals(mPeerAddresses, 216 uwbConfig.mPeerAddresses); 217 } 218 219 @Override hashCode()220 public int hashCode() { 221 return Objects.hash(mSessionConfig, mParameters, mDeviceRole, mPeerAddresses); 222 } 223 } 224