1 /* 2 * Copyright (C) 2022 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 androidx.core.uwb.backend.impl.internal; 18 19 import androidx.annotation.NonNull; 20 import androidx.annotation.Nullable; 21 22 import com.google.common.base.Objects; 23 import com.google.common.primitives.Longs; 24 import com.google.common.primitives.Shorts; 25 26 import java.security.SecureRandom; 27 import java.util.Arrays; 28 29 /** 30 * UWB supports two addressing formats: 16-bit short address or 64-bit extended address, This class 31 * provides a way to support both formats in one class. 32 */ 33 public class UwbAddress { 34 35 public static final int SHORT_ADDRESS_LENGTH = 2; 36 public static final int EXTENDED_ADDRESS_LENGTH = 8; 37 38 /** SHORT means 16-bit address EXTENDED means 64-bit address */ 39 public enum AddressingMode { 40 SHORT, 41 EXTENDED 42 } 43 44 private final AddressingMode mAddressingMode; 45 private final byte[] mAddressBytes; 46 UwbAddress(AddressingMode mode, byte[] addressBytes)47 private UwbAddress(AddressingMode mode, byte[] addressBytes) { 48 this.mAddressingMode = mode; 49 this.mAddressBytes = addressBytes; 50 } 51 52 /** 2 bytes will be converted to short address, 8 bytes to full */ fromBytes(byte[] address)53 public static UwbAddress fromBytes(byte[] address) { 54 if (address.length == SHORT_ADDRESS_LENGTH) { 55 return new UwbAddress(AddressingMode.SHORT, address); 56 } 57 58 if (address.length == EXTENDED_ADDRESS_LENGTH) { 59 return new UwbAddress(AddressingMode.EXTENDED, address); 60 } 61 62 throw new IllegalArgumentException( 63 String.format( 64 "the address length only can be 2 bytes (SHORT) or 8 bytes (EXTENDED)," 65 + " passed in %d bytes", 66 address.length)); 67 } 68 69 /** This method provides a way to convert short to/from short address bytes */ fromShort(short address)70 public static UwbAddress fromShort(short address) { 71 return new UwbAddress(AddressingMode.SHORT, Shorts.toByteArray(address)); 72 } 73 74 /** Convert the short address to a short */ toShort(UwbAddress address)75 public static short toShort(UwbAddress address) { 76 if (address.getAddressingMode() != AddressingMode.SHORT) { 77 throw new IllegalArgumentException(); 78 } 79 80 return Shorts.fromByteArray(address.mAddressBytes); 81 } 82 83 /** This method provides a way to convert long to/from extended address bytes */ fromLong(long address)84 public static UwbAddress fromLong(long address) { 85 return new UwbAddress(AddressingMode.EXTENDED, Longs.toByteArray(address)); 86 } 87 88 /** Convert the extended address to a long */ toLong(UwbAddress address)89 public static long toLong(UwbAddress address) { 90 if (address.getAddressingMode() != AddressingMode.EXTENDED) { 91 throw new IllegalArgumentException(); 92 } 93 94 return Longs.fromByteArray(address.mAddressBytes); 95 } 96 generateRandomByteArray(int len, SecureRandom secureRandom)97 private static byte[] generateRandomByteArray(int len, SecureRandom secureRandom) { 98 byte[] bytes = new byte[len]; 99 secureRandom.nextBytes(bytes); 100 return bytes; 101 } 102 103 /** Get a randomized short address */ getRandomizedShortAddress()104 public static UwbAddress getRandomizedShortAddress() { 105 SecureRandom secureRandom = new SecureRandom(); 106 return fromBytes(generateRandomByteArray(SHORT_ADDRESS_LENGTH, secureRandom)); 107 } 108 109 /** Get a randomized extended address */ getRandomizedExtendedAddress()110 public static UwbAddress getRandomizedExtendedAddress() { 111 SecureRandom secureRandom = new SecureRandom(); 112 return fromBytes(generateRandomByteArray(EXTENDED_ADDRESS_LENGTH, secureRandom)); 113 } 114 getAddressingMode()115 public AddressingMode getAddressingMode() { 116 return mAddressingMode; 117 } 118 119 /** Get the address byte array */ toBytes()120 public byte[] toBytes() { 121 return mAddressBytes.clone(); 122 } 123 124 /** How many bytes the address takes */ size()125 public int size() { 126 if (mAddressingMode == AddressingMode.SHORT) { 127 return SHORT_ADDRESS_LENGTH; 128 } 129 130 return EXTENDED_ADDRESS_LENGTH; 131 } 132 133 /** return the address in hex format */ toHexString()134 public String toHexString() { 135 StringBuilder stringBuilder = new StringBuilder("0X"); 136 for (byte b : mAddressBytes) { 137 stringBuilder.append(String.format("%02X", b)); 138 } 139 140 return stringBuilder.toString(); 141 } 142 143 @NonNull 144 @Override toString()145 public String toString() { 146 return toHexString(); 147 } 148 149 @Override equals(@ullable Object obj)150 public boolean equals(@Nullable Object obj) { 151 if (obj instanceof UwbAddress) { 152 UwbAddress that = (UwbAddress) obj; 153 return Objects.equal(mAddressingMode, that.getAddressingMode()) 154 && Arrays.equals(mAddressBytes, that.toBytes()); 155 } 156 157 return false; 158 } 159 160 @Override hashCode()161 public int hashCode() { 162 return Objects.hashCode(mAddressingMode, Arrays.hashCode(mAddressBytes)); 163 } 164 } 165