1 /*
2  * Copyright (C) 2021 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.uwb.params;
18 
19 import com.android.server.uwb.config.ConfigParam;
20 
21 import java.nio.ByteBuffer;
22 import java.nio.ByteOrder;
23 import java.util.Arrays;
24 
25 /***
26  * This assumes little endian data and 1 byte tags. This is intended for handling UCI interface
27  * data.
28  */
29 public class TlvBuffer {
30     private static final String TAG = "TlvBuffer";
31     private static final int MAX_BUFFER_SIZE = 512;
32     private final ByteBuffer mBuffer;
33     private final int mNoOfParams;
34 
TlvBuffer(byte[] tlvArray, int noOfParams)35     public TlvBuffer(byte[] tlvArray, int noOfParams) {
36         mBuffer = ByteBuffer.wrap(tlvArray);
37         mNoOfParams = noOfParams;
38     }
39 
getByteArray()40     public byte[] getByteArray() {
41         return mBuffer.array();
42     }
43 
getNoOfParams()44     public int getNoOfParams() {
45         return mNoOfParams;
46     }
47 
48     public static final class Builder {
49         ByteBuffer mBuffer = ByteBuffer.allocate(MAX_BUFFER_SIZE);
50         int mNoOfParams = 0;
51         ByteOrder mOrder = ByteOrder.BIG_ENDIAN;
52 
putOrder(ByteOrder order)53         public TlvBuffer.Builder putOrder(ByteOrder order) {
54             mOrder = order;
55             return this;
56         }
57 
putByte(int tagType, byte b)58         public TlvBuffer.Builder putByte(int tagType, byte b) {
59             addHeader(tagType, Byte.BYTES);
60             this.mBuffer.put(b);
61             this.mNoOfParams++;
62             return this;
63         }
64 
putByteArray(int tagType, byte[] bArray)65         public TlvBuffer.Builder putByteArray(int tagType, byte[] bArray) {
66             if (bArray == null) return this;
67             return putByteArray(tagType, bArray.length, bArray);
68         }
69 
putByteArray(int tagType, int length, byte[] bArray)70         public TlvBuffer.Builder putByteArray(int tagType, int length, byte[] bArray) {
71             addHeader(tagType, length);
72             this.mBuffer.put(bArray);
73             this.mNoOfParams++;
74             return this;
75         }
76 
putShort(int tagType, short data)77         public TlvBuffer.Builder putShort(int tagType, short data) {
78             addHeader(tagType, Short.BYTES);
79             this.mBuffer.put(TlvUtil.getLeBytes(data));
80             this.mNoOfParams++;
81             return this;
82         }
83 
putShortArray(int tagType, short[] sArray)84         public TlvBuffer.Builder putShortArray(int tagType, short[] sArray) {
85             if (sArray == null) return this;
86             return putShortArray(tagType, sArray.length, sArray);
87         }
88 
putShortArray(int tagType, int length, short[] sArray)89         public TlvBuffer.Builder putShortArray(int tagType, int length, short[] sArray) {
90             addHeader(tagType, length * Short.BYTES);
91             for (int i = 0; i < length; i++) {
92                 this.mBuffer.put(TlvUtil.getLeBytes(sArray[i]));
93             }
94             this.mNoOfParams++;
95             return this;
96         }
97 
putInt(int tagType, int data)98         public TlvBuffer.Builder putInt(int tagType, int data) {
99             addHeader(tagType, Integer.BYTES);
100             this.mBuffer.put(TlvUtil.getLeBytes(data));
101             this.mNoOfParams++;
102             return this;
103         }
104 
putLong(int tagType, long data)105         public TlvBuffer.Builder putLong(int tagType, long data) {
106             addHeader(tagType, Long.BYTES);
107             this.mBuffer.put(TlvUtil.getLeBytes(data));
108             this.mNoOfParams++;
109             return this;
110         }
111 
build()112         public TlvBuffer build() {
113             return new TlvBuffer(Arrays.copyOf(this.mBuffer.array(), this.mBuffer.position()),
114                     this.mNoOfParams);
115         }
116 
addHeader(int tagType, int length)117         private void addHeader(int tagType, int length) {
118             mBuffer.put(ConfigParam.getTagBytes(tagType));
119             mBuffer.put((byte) length);
120         }
121     }
122 }
123