• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.ranging.uwb;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 
25 import com.android.ranging.flags.Flags;
26 
27 import java.security.SecureRandom;
28 import java.util.Arrays;
29 
30 /**
31  * A class representing a UWB address
32  */
33 @FlaggedApi(Flags.FLAG_RANGING_STACK_ENABLED)
34 public final class UwbAddress implements Parcelable {
35     public static final int SHORT_ADDRESS_BYTE_LENGTH = 2;
36     public static final int EXTENDED_ADDRESS_BYTE_LENGTH = 8;
37 
38     private static final byte[] sShortForbiddenUwbAddress = {(byte) 0xFF, (byte) 0xFF};
39     private static final byte[] sExtendedForbiddenUwbAddress = {
40             (byte) 0xFF,
41             (byte) 0xFF,
42             (byte) 0xFF,
43             (byte) 0xFF,
44             (byte) 0xFF,
45             (byte) 0xFF,
46             (byte) 0xFF,
47             (byte) 0xFF
48     };
49 
50     private final byte[] mAddressBytes;
51 
UwbAddress(byte[] address)52     private UwbAddress(byte[] address) {
53         mAddressBytes = address;
54     }
55 
56     /**
57      * Create a {@link android.uwb.UwbAddress} from a byte array.
58      *
59      * <p>If the provided array is {@link #SHORT_ADDRESS_BYTE_LENGTH} bytes, a short address is
60      * created. If the provided array is {@link #EXTENDED_ADDRESS_BYTE_LENGTH} bytes, then an
61      * extended address is created.
62      *
63      * @param address a byte array to convert to a {@link android.uwb.UwbAddress}
64      * @return a {@link android.uwb.UwbAddress} created from the input byte array
65      * @throws IllegalArgumentException when the length is not one of
66      *       {@link #SHORT_ADDRESS_BYTE_LENGTH} or {@link #EXTENDED_ADDRESS_BYTE_LENGTH} bytes
67      */
68     @NonNull
fromBytes(@onNull byte[] address)69     public static UwbAddress fromBytes(@NonNull byte[] address) {
70         if (address.length != SHORT_ADDRESS_BYTE_LENGTH
71                 && address.length != EXTENDED_ADDRESS_BYTE_LENGTH) {
72             throw new IllegalArgumentException("Invalid UwbAddress length " + address.length);
73         }
74         return new UwbAddress(address);
75     }
76 
77     /**
78      * Generates a new random 2 bytes {@link UwbAddress}.
79      *
80      * @return a new randomly generated {@link UwbAddress}.
81      */
82     @NonNull
createRandomShortAddress()83     public static UwbAddress createRandomShortAddress() {
84         SecureRandom secureRandom = new SecureRandom();
85         return fromBytes(generateRandomByteArray(SHORT_ADDRESS_BYTE_LENGTH, secureRandom));
86     }
87 
88     /**
89      * Generates a random 8 bytes {@link UwbAddress}.
90      *
91      * @return a randomly generated {@link UwbAddress}.
92      *
93      * @hide Intentionally hidden.
94      */
95     @NonNull
getRandomExtendedAddress()96     public static UwbAddress getRandomExtendedAddress() {
97         SecureRandom secureRandom = new SecureRandom();
98         return fromBytes(generateRandomByteArray(EXTENDED_ADDRESS_BYTE_LENGTH, secureRandom));
99     }
100 
generateRandomByteArray(int len, SecureRandom secureRandom)101     private static byte[] generateRandomByteArray(int len, SecureRandom secureRandom) {
102         byte[] bytes = new byte[len];
103         do {
104             secureRandom.nextBytes(bytes);
105         } while (isForbiddenAddress(bytes));
106         return bytes;
107     }
108 
isForbiddenAddress(byte[] address)109     private static boolean isForbiddenAddress(byte[] address) {
110         if (address.length == SHORT_ADDRESS_BYTE_LENGTH) {
111             return Arrays.equals(address, sShortForbiddenUwbAddress);
112         } else {
113             return Arrays.equals(address, sExtendedForbiddenUwbAddress);
114         }
115     }
116 
117 
118     /**
119      * Get the address as a byte array
120      *
121      * @return the byte representation of this {@link android.uwb.UwbAddress}
122      */
123     @NonNull
getAddressBytes()124     public byte[] getAddressBytes() {
125         return mAddressBytes;
126     }
127 
128     @NonNull
129     @Override
toString()130     public String toString() {
131         StringBuilder builder = new StringBuilder("0x");
132         for (byte addressByte : mAddressBytes) {
133             builder.append(String.format("%02X", addressByte));
134         }
135         return builder.toString();
136     }
137 
138     @Override
equals(@ullable Object obj)139     public boolean equals(@Nullable Object obj) {
140         if (obj instanceof UwbAddress) {
141             return Arrays.equals(mAddressBytes, ((UwbAddress) obj).getAddressBytes());
142         }
143         return false;
144     }
145 
146     @Override
hashCode()147     public int hashCode() {
148         return Arrays.hashCode(mAddressBytes);
149     }
150 
151     @Override
describeContents()152     public int describeContents() {
153         return 0;
154     }
155 
156     @Override
writeToParcel(@onNull Parcel dest, int flags)157     public void writeToParcel(@NonNull Parcel dest, int flags) {
158         dest.writeInt(mAddressBytes.length);
159         dest.writeByteArray(mAddressBytes);
160     }
161 
162     public static final @android.annotation.NonNull Creator<UwbAddress> CREATOR =
163             new Creator<UwbAddress>() {
164                 @Override
165                 public UwbAddress createFromParcel(Parcel in) {
166                     byte[] address = new byte[in.readInt()];
167                     in.readByteArray(address);
168                     return UwbAddress.fromBytes(address);
169                 }
170 
171                 @Override
172                 public UwbAddress[] newArray(int size) {
173                     return new UwbAddress[size];
174                 }
175             };
176 }
177