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 com.google.uwb.support; 18 19 import static org.junit.Assert.assertArrayEquals; 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertTrue; 22 23 import android.os.PersistableBundle; 24 25 import androidx.test.ext.junit.runners.AndroidJUnit4; 26 import androidx.test.filters.SmallTest; 27 28 import com.google.uwb.support.aliro.AliroOpenRangingParams; 29 import com.google.uwb.support.aliro.AliroParams; 30 import com.google.uwb.support.aliro.AliroProtocolVersion; 31 import com.google.uwb.support.aliro.AliroPulseShapeCombo; 32 import com.google.uwb.support.aliro.AliroRangingError; 33 import com.google.uwb.support.aliro.AliroRangingReconfiguredParams; 34 import com.google.uwb.support.aliro.AliroRangingStartedParams; 35 import com.google.uwb.support.aliro.AliroSpecificationParams; 36 import com.google.uwb.support.aliro.AliroStartRangingParams; 37 import com.google.uwb.support.base.Params; 38 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 42 import java.util.List; 43 44 @SmallTest 45 @RunWith(AndroidJUnit4.class) 46 public class AliroTests { 47 private static final AliroProtocolVersion[] PROTOCOL_VERSIONS = 48 new AliroProtocolVersion[] { 49 new AliroProtocolVersion(1, 0), 50 new AliroProtocolVersion(2, 0), 51 new AliroProtocolVersion(2, 1) 52 }; 53 54 private static final Integer[] UWB_CONFIGS = 55 new Integer[] {AliroParams.UWB_CONFIG_0, AliroParams.UWB_CONFIG_1}; 56 private static final AliroPulseShapeCombo[] PULSE_SHAPE_COMBOS = 57 new AliroPulseShapeCombo[] { 58 new AliroPulseShapeCombo( 59 AliroParams.PULSE_SHAPE_SYMMETRICAL_ROOT_RAISED_COSINE, 60 AliroParams.PULSE_SHAPE_SYMMETRICAL_ROOT_RAISED_COSINE), 61 new AliroPulseShapeCombo( 62 AliroParams.PULSE_SHAPE_PRECURSOR_FREE, 63 AliroParams.PULSE_SHAPE_PRECURSOR_FREE), 64 new AliroPulseShapeCombo( 65 AliroParams.PULSE_SHAPE_PRECURSOR_FREE_SPECIAL, 66 AliroParams.PULSE_SHAPE_PRECURSOR_FREE_SPECIAL) 67 }; 68 private static final int RAN_MULTIPLIER = 200; 69 private static final Integer[] CHAPS_PER_SLOTS = 70 new Integer[] {AliroParams.CHAPS_PER_SLOT_4, AliroParams.CHAPS_PER_SLOT_12}; 71 private static final Integer[] SYNC_CODES = new Integer[] {10, 23}; 72 private static final Integer[] CHANNELS = 73 new Integer[] {AliroParams.UWB_CHANNEL_5, AliroParams.UWB_CHANNEL_9}; 74 private static final Integer[] HOPPING_CONFIG_MODES = 75 new Integer[] { 76 AliroParams.HOPPING_CONFIG_MODE_ADAPTIVE, 77 AliroParams.HOPPING_CONFIG_MODE_CONTINUOUS 78 }; 79 private static final Integer[] HOPPING_SEQUENCES = 80 new Integer[] {AliroParams.HOPPING_SEQUENCE_AES, AliroParams.HOPPING_SEQUENCE_DEFAULT}; 81 private static final Integer[] MAC_MODES = 82 new Integer[] {AliroParams.MAC_MODE_ROUND_1, AliroParams.MAC_MODE_ROUND_2}; 83 84 @Test testOpenRangingParams()85 public void testOpenRangingParams() { 86 AliroProtocolVersion protocolVersion = AliroParams.PROTOCOL_VERSION_1_0; 87 @AliroParams.UwbConfig int uwbConfig = AliroParams.UWB_CONFIG_1; 88 AliroPulseShapeCombo pulseShapeCombo = 89 new AliroPulseShapeCombo( 90 AliroParams.PULSE_SHAPE_PRECURSOR_FREE, 91 AliroParams.PULSE_SHAPE_PRECURSOR_FREE); 92 int sessionId = 10; 93 int ranMultiplier = 128; 94 @AliroParams.Channel int channel = AliroParams.UWB_CHANNEL_9; 95 @AliroParams.ChapsPerSlot int chapsPerSlot = AliroParams.CHAPS_PER_SLOT_6; 96 int numResponderNodes = 9; 97 @AliroParams.SlotsPerRound int numSlotsPerRound = AliroParams.SLOTS_PER_ROUND_12; 98 @AliroParams.SyncCodeIndex int syncCodeIdx = 22; 99 @AliroParams.HoppingConfigMode int hoppingConfigMode = 100 AliroParams.HOPPING_CONFIG_MODE_ADAPTIVE; 101 @AliroParams.HoppingSequence int hoppingSequence = AliroParams.HOPPING_SEQUENCE_AES; 102 long absoluteInitiationTimeUs = 20_000L; 103 int rangeDataNtfConfig = AliroParams.RANGE_DATA_NTF_CONFIG_ENABLE; 104 int rangeDataNtfProximityNear = 100; 105 int rangeDataNtfProximityFar = 200; 106 double rangeDataNtfAoaAzimuthLower = -0.7; 107 double rangeDataNtfAoaAzimuthUpper = +1.3; 108 double rangeDataNtfAoaElevationLower = -1.1; 109 double rangeDataNtfAoaElevationUpper = +1.2; 110 @AliroParams.MacModeRound int macModeRound = AliroParams.MAC_MODE_ROUND_1; 111 int macModeOffset = 0; 112 byte[] sessionKey = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 113 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; 114 115 AliroOpenRangingParams params = 116 new AliroOpenRangingParams.Builder() 117 .setProtocolVersion(protocolVersion) 118 .setUwbConfig(uwbConfig) 119 .setPulseShapeCombo(pulseShapeCombo) 120 .setSessionId(sessionId) 121 .setRanMultiplier(ranMultiplier) 122 .setChannel(channel) 123 .setNumChapsPerSlot(chapsPerSlot) 124 .setNumResponderNodes(numResponderNodes) 125 .setNumSlotsPerRound(numSlotsPerRound) 126 .setSyncCodeIndex(syncCodeIdx) 127 .setHoppingConfigMode(hoppingConfigMode) 128 .setHoppingSequence(hoppingSequence) 129 .setAbsoluteInitiationTimeUs(absoluteInitiationTimeUs) 130 .setRangeDataNtfConfig(rangeDataNtfConfig) 131 .setRangeDataNtfProximityNear(rangeDataNtfProximityNear) 132 .setRangeDataNtfProximityFar(rangeDataNtfProximityFar) 133 .setRangeDataNtfAoaAzimuthLower(rangeDataNtfAoaAzimuthLower) 134 .setRangeDataNtfAoaAzimuthUpper(rangeDataNtfAoaAzimuthUpper) 135 .setRangeDataNtfAoaElevationLower(rangeDataNtfAoaElevationLower) 136 .setRangeDataNtfAoaElevationUpper(rangeDataNtfAoaElevationUpper) 137 .setSessionKey(sessionKey) 138 .setMacModeRound(macModeRound) 139 .setMacModeOffset(macModeOffset) 140 .build(); 141 142 assertEquals(params.getProtocolVersion(), protocolVersion); 143 assertEquals(params.getUwbConfig(), uwbConfig); 144 assertEquals( 145 params.getPulseShapeCombo().getInitiatorTx(), pulseShapeCombo.getInitiatorTx()); 146 assertEquals( 147 params.getPulseShapeCombo().getResponderTx(), pulseShapeCombo.getResponderTx()); 148 assertEquals(params.getSessionId(), sessionId); 149 assertEquals(params.getSessionType(), AliroParams.SESSION_TYPE_ALIRO); 150 assertEquals(params.getRanMultiplier(), ranMultiplier); 151 assertEquals(params.getChannel(), channel); 152 assertEquals(params.getNumChapsPerSlot(), chapsPerSlot); 153 assertEquals(params.getNumResponderNodes(), numResponderNodes); 154 assertEquals(params.getNumSlotsPerRound(), numSlotsPerRound); 155 assertEquals(params.getSyncCodeIndex(), syncCodeIdx); 156 assertEquals(params.getHoppingConfigMode(), hoppingConfigMode); 157 assertEquals(params.getHoppingSequence(), hoppingSequence); 158 assertEquals(params.getAbsoluteInitiationTimeUs(), absoluteInitiationTimeUs); 159 assertEquals(params.getMacModeRound(), macModeRound); 160 assertEquals(params.getMacModeOffset(), macModeOffset); 161 assertArrayEquals(params.getSessionKey(), sessionKey); 162 163 AliroOpenRangingParams fromBundle = AliroOpenRangingParams.fromBundle(params.toBundle()); 164 assertEquals(fromBundle.getProtocolVersion(), protocolVersion); 165 assertEquals(fromBundle.getUwbConfig(), uwbConfig); 166 assertEquals( 167 fromBundle.getPulseShapeCombo().getInitiatorTx(), pulseShapeCombo.getInitiatorTx()); 168 assertEquals( 169 fromBundle.getPulseShapeCombo().getResponderTx(), pulseShapeCombo.getResponderTx()); 170 assertEquals(fromBundle.getSessionId(), sessionId); 171 assertEquals(fromBundle.getRanMultiplier(), ranMultiplier); 172 assertEquals(fromBundle.getChannel(), channel); 173 assertEquals(fromBundle.getNumChapsPerSlot(), chapsPerSlot); 174 assertEquals(fromBundle.getNumResponderNodes(), numResponderNodes); 175 assertEquals(fromBundle.getNumSlotsPerRound(), numSlotsPerRound); 176 assertEquals(fromBundle.getSyncCodeIndex(), syncCodeIdx); 177 assertEquals(fromBundle.getHoppingConfigMode(), hoppingConfigMode); 178 assertEquals(fromBundle.getHoppingSequence(), hoppingSequence); 179 assertEquals(fromBundle.getAbsoluteInitiationTimeUs(), absoluteInitiationTimeUs); 180 assertEquals(fromBundle.getRangeDataNtfConfig(), rangeDataNtfConfig); 181 assertEquals(fromBundle.getRangeDataNtfProximityNear(), rangeDataNtfProximityNear); 182 assertEquals(fromBundle.getRangeDataNtfProximityFar(), rangeDataNtfProximityFar); 183 assertEquals( 184 fromBundle.getRangeDataNtfAoaAzimuthLower(), rangeDataNtfAoaAzimuthLower, 0.1d); 185 assertEquals( 186 fromBundle.getRangeDataNtfAoaAzimuthUpper(), rangeDataNtfAoaAzimuthUpper, 0.1d); 187 assertEquals( 188 fromBundle.getRangeDataNtfAoaElevationLower(), rangeDataNtfAoaElevationLower, 0.1d); 189 assertEquals( 190 fromBundle.getRangeDataNtfAoaElevationUpper(), rangeDataNtfAoaElevationUpper, 0.1d); 191 assertEquals(fromBundle.getMacModeRound(), macModeRound); 192 assertEquals(fromBundle.getMacModeOffset(), macModeOffset); 193 assertArrayEquals(fromBundle.getSessionKey(), sessionKey); 194 195 verifyProtocolPresent(params); 196 } 197 198 @Test testRangingError()199 public void testRangingError() { 200 @AliroParams.ProtocolError int error = AliroParams.PROTOCOL_ERROR_SE_BUSY; 201 AliroRangingError params = new AliroRangingError.Builder().setError(error).build(); 202 203 assertEquals(params.getError(), error); 204 205 AliroRangingError fromBundle = AliroRangingError.fromBundle(params.toBundle()); 206 assertEquals(fromBundle.getError(), error); 207 208 verifyProtocolPresent(params); 209 verifyBundlesEqual(params, fromBundle); 210 } 211 212 @Test testRangingReconfiguredParams()213 public void testRangingReconfiguredParams() { 214 AliroRangingReconfiguredParams params = 215 new AliroRangingReconfiguredParams.Builder().build(); 216 217 AliroRangingReconfiguredParams fromBundle = 218 AliroRangingReconfiguredParams.fromBundle(params.toBundle()); 219 220 verifyProtocolPresent(params); 221 verifyBundlesEqual(params, fromBundle); 222 } 223 224 @Test testStartRangingParams()225 public void testStartRangingParams() { 226 int sessionId = 10; 227 int ranMultiplier = 128; 228 long initiationTimeMs = 10; 229 long absoluteInitiationTimeUs = 15_000L; 230 231 AliroStartRangingParams params = 232 new AliroStartRangingParams.Builder() 233 .setSessionId(sessionId) 234 .setRanMultiplier(ranMultiplier) 235 .setInitiationTimeMs(initiationTimeMs) 236 .setAbsoluteInitiationTimeUs(absoluteInitiationTimeUs) 237 .build(); 238 239 assertEquals(params.getSessionId(), sessionId); 240 assertEquals(params.getRanMultiplier(), ranMultiplier); 241 assertEquals(params.getInitiationTimeMs(), initiationTimeMs); 242 assertEquals(params.getAbsoluteInitiationTimeUs(), absoluteInitiationTimeUs); 243 244 AliroStartRangingParams fromBundle = AliroStartRangingParams.fromBundle(params.toBundle()); 245 246 assertEquals(fromBundle.getSessionId(), sessionId); 247 assertEquals(fromBundle.getRanMultiplier(), ranMultiplier); 248 assertEquals(fromBundle.getInitiationTimeMs(), initiationTimeMs); 249 assertEquals(fromBundle.getAbsoluteInitiationTimeUs(), absoluteInitiationTimeUs); 250 251 verifyProtocolPresent(params); 252 verifyBundlesEqual(params, fromBundle); 253 } 254 255 @Test testRangingStartedParams()256 public void testRangingStartedParams() { 257 int hopModeKey = 98876444; 258 int startingStsIndex = 246802468; 259 @AliroParams.SyncCodeIndex int syncCodeIndex = 10; 260 long uwbTime0 = 50; 261 int ranMultiplier = 10; 262 263 AliroRangingStartedParams params = 264 new AliroRangingStartedParams.Builder() 265 .setHopModeKey(hopModeKey) 266 .setStartingStsIndex(startingStsIndex) 267 .setSyncCodeIndex(syncCodeIndex) 268 .setUwbTime0(uwbTime0) 269 .setRanMultiplier(ranMultiplier) 270 .build(); 271 272 assertEquals(params.getHopModeKey(), hopModeKey); 273 assertEquals(params.getStartingStsIndex(), startingStsIndex); 274 assertEquals(params.getSyncCodeIndex(), syncCodeIndex); 275 assertEquals(params.getUwbTime0(), uwbTime0); 276 assertEquals(params.getRanMultiplier(), ranMultiplier); 277 278 AliroRangingStartedParams fromBundle = 279 AliroRangingStartedParams.fromBundle(params.toBundle()); 280 281 assertEquals(fromBundle.getHopModeKey(), hopModeKey); 282 assertEquals(fromBundle.getStartingStsIndex(), startingStsIndex); 283 assertEquals(fromBundle.getSyncCodeIndex(), syncCodeIndex); 284 assertEquals(fromBundle.getUwbTime0(), uwbTime0); 285 assertEquals(fromBundle.getRanMultiplier(), ranMultiplier); 286 287 verifyProtocolPresent(params); 288 verifyBundlesEqual(params, fromBundle); 289 } 290 291 @Test testSpecificationParams()292 public void testSpecificationParams() { 293 AliroSpecificationParams.Builder paramsBuilder = new AliroSpecificationParams.Builder(); 294 for (AliroProtocolVersion p : PROTOCOL_VERSIONS) { 295 paramsBuilder.addProtocolVersion(p); 296 } 297 298 for (int uwbConfig : UWB_CONFIGS) { 299 paramsBuilder.addUwbConfig(uwbConfig); 300 } 301 302 for (AliroPulseShapeCombo pulseShapeCombo : PULSE_SHAPE_COMBOS) { 303 paramsBuilder.addPulseShapeCombo(pulseShapeCombo); 304 } 305 306 paramsBuilder.setRanMultiplier(RAN_MULTIPLIER); 307 308 for (int chapsPerSlot : CHAPS_PER_SLOTS) { 309 paramsBuilder.addChapsPerSlot(chapsPerSlot); 310 } 311 312 for (int syncCode : SYNC_CODES) { 313 paramsBuilder.addSyncCode(syncCode); 314 } 315 316 for (int channel : CHANNELS) { 317 paramsBuilder.addChannel(channel); 318 } 319 320 for (int hoppingConfigMode : HOPPING_CONFIG_MODES) { 321 paramsBuilder.addHoppingConfigMode(hoppingConfigMode); 322 } 323 324 for (int hoppingSequence : HOPPING_SEQUENCES) { 325 paramsBuilder.addHoppingSequence(hoppingSequence); 326 } 327 for (int macMode : MAC_MODES) { 328 paramsBuilder.addMacMode(macMode); 329 } 330 331 AliroSpecificationParams params = paramsBuilder.build(); 332 assertArrayEquals(params.getProtocolVersions().toArray(), PROTOCOL_VERSIONS); 333 assertArrayEquals(params.getUwbConfigs().toArray(), UWB_CONFIGS); 334 assertArrayEquals(params.getPulseShapeCombos().toArray(), PULSE_SHAPE_COMBOS); 335 assertEquals(params.getRanMultiplier(), RAN_MULTIPLIER); 336 assertArrayEquals(params.getChapsPerSlot().toArray(), CHAPS_PER_SLOTS); 337 assertArrayEquals(params.getSyncCodes().toArray(), SYNC_CODES); 338 assertArrayEquals(params.getChannels().toArray(), CHANNELS); 339 assertArrayEquals(params.getHoppingConfigModes().toArray(), HOPPING_CONFIG_MODES); 340 assertArrayEquals(params.getHoppingSequences().toArray(), HOPPING_SEQUENCES); 341 assertArrayEquals(params.getMacModes().toArray(), MAC_MODES); 342 343 AliroSpecificationParams fromBundle = 344 AliroSpecificationParams.fromBundle(params.toBundle()); 345 assertArrayEquals(fromBundle.getProtocolVersions().toArray(), PROTOCOL_VERSIONS); 346 assertArrayEquals(fromBundle.getUwbConfigs().toArray(), UWB_CONFIGS); 347 assertArrayEquals(fromBundle.getPulseShapeCombos().toArray(), PULSE_SHAPE_COMBOS); 348 assertEquals(fromBundle.getRanMultiplier(), RAN_MULTIPLIER); 349 assertArrayEquals(fromBundle.getChapsPerSlot().toArray(), CHAPS_PER_SLOTS); 350 assertArrayEquals(fromBundle.getSyncCodes().toArray(), SYNC_CODES); 351 assertArrayEquals(fromBundle.getChannels().toArray(), CHANNELS); 352 assertArrayEquals(fromBundle.getHoppingConfigModes().toArray(), HOPPING_CONFIG_MODES); 353 assertArrayEquals(fromBundle.getHoppingSequences().toArray(), HOPPING_SEQUENCES); 354 assertArrayEquals(fromBundle.getMacModes().toArray(), MAC_MODES); 355 356 verifyProtocolPresent(params); 357 assertTrue(params.equals(fromBundle)); 358 359 // Add random channel to params builder to force inequality. 360 paramsBuilder.addChannel(0); 361 // Rebuild params. 362 params = paramsBuilder.build(); 363 // Test that params and fromBundle are not equal. 364 assertTrue(!params.equals(fromBundle)); 365 } 366 367 @Test testSpecificationParams_whenNoChannelsSet()368 public void testSpecificationParams_whenNoChannelsSet() { 369 AliroSpecificationParams.Builder paramsBuilder = new AliroSpecificationParams.Builder(); 370 for (AliroProtocolVersion p : PROTOCOL_VERSIONS) { 371 paramsBuilder.addProtocolVersion(p); 372 } 373 for (int uwbConfig : UWB_CONFIGS) { 374 paramsBuilder.addUwbConfig(uwbConfig); 375 } 376 for (AliroPulseShapeCombo pulseShapeCombo : PULSE_SHAPE_COMBOS) { 377 paramsBuilder.addPulseShapeCombo(pulseShapeCombo); 378 } 379 paramsBuilder.setRanMultiplier(RAN_MULTIPLIER); 380 for (int chapsPerSlot : CHAPS_PER_SLOTS) { 381 paramsBuilder.addChapsPerSlot(chapsPerSlot); 382 } 383 for (int syncCode : SYNC_CODES) { 384 paramsBuilder.addSyncCode(syncCode); 385 } 386 for (int hoppingConfigMode : HOPPING_CONFIG_MODES) { 387 paramsBuilder.addHoppingConfigMode(hoppingConfigMode); 388 } 389 for (int hoppingSequence : HOPPING_SEQUENCES) { 390 paramsBuilder.addHoppingSequence(hoppingSequence); 391 } 392 for (int macMode : MAC_MODES) { 393 paramsBuilder.addMacMode(macMode); 394 } 395 AliroSpecificationParams params = paramsBuilder.build(); 396 assertEquals(List.of(), params.getChannels()); 397 398 AliroSpecificationParams fromBundle = 399 AliroSpecificationParams.fromBundle(params.toBundle()); 400 assertEquals(List.of(), fromBundle.getChannels()); 401 } 402 verifyProtocolPresent(Params params)403 private void verifyProtocolPresent(Params params) { 404 assertTrue(Params.isProtocol(params.toBundle(), AliroParams.PROTOCOL_NAME)); 405 } 406 verifyBundlesEqual(Params params, Params fromBundle)407 private void verifyBundlesEqual(Params params, Params fromBundle) { 408 assertTrue(PersistableBundle.kindofEquals(params.toBundle(), fromBundle.toBundle())); 409 } 410 } 411