1 /*
2  * Copyright (C) 2023 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 package com.android.internal.widget.remotecompose.core;
17 
18 import java.util.Arrays;
19 
20 /**
21  * The base communication buffer capable of encoding and decoding various types
22  */
23 public class WireBuffer {
24     private static final int BUFFER_SIZE = 1024 * 1024 * 1;
25     int mMaxSize;
26     byte[] mBuffer;
27     int mIndex = 0;
28     int mStartingIndex = 0;
29     int mSize = 0;
30 
WireBuffer(int size)31     public WireBuffer(int size) {
32         mMaxSize = size;
33         mBuffer = new byte[mMaxSize];
34     }
35 
WireBuffer()36     public WireBuffer() {
37         this(BUFFER_SIZE);
38     }
39 
resize(int need)40     private void resize(int need) {
41         if (mSize + need >= mMaxSize) {
42             mMaxSize = Math.max(mMaxSize * 2, mSize + need);
43             mBuffer = Arrays.copyOf(mBuffer, mMaxSize);
44         }
45     }
46 
getBuffer()47     public byte[] getBuffer() {
48         return mBuffer;
49     }
50 
getMax_size()51     public int getMax_size() {
52         return mMaxSize;
53     }
54 
getIndex()55     public int getIndex() {
56         return mIndex;
57     }
58 
getSize()59     public int getSize() {
60         return mSize;
61     }
62 
setIndex(int index)63     public void setIndex(int index) {
64         this.mIndex = index;
65     }
66 
start(int type)67     public void start(int type) {
68         mStartingIndex = mIndex;
69         writeByte(type);
70     }
71 
startWithSize(int type)72     public void startWithSize(int type) {
73         mStartingIndex = mIndex;
74         writeByte(type);
75         mIndex += 4; // skip ahead for the future size
76     }
77 
endWithSize()78     public void endWithSize() {
79         int size = mIndex - mStartingIndex;
80         int currentIndex = mIndex;
81         mIndex = mStartingIndex + 1; // (type)
82         writeInt(size);
83         mIndex = currentIndex;
84     }
85 
86     /**
87      * Reset the internal buffer
88      *
89      * @param expectedSize provided hint for the buffer size
90      */
reset(int expectedSize)91     public void reset(int expectedSize) {
92         mIndex = 0;
93         mStartingIndex = 0;
94         mSize = 0;
95         if (expectedSize >= mMaxSize) {
96             resize(expectedSize);
97         }
98     }
99 
size()100     public int size() {
101         return mSize;
102     }
103 
available()104     public boolean available() {
105         return mSize - mIndex > 0;
106     }
107 
108     ///////////////////////////////////////////////////////////////////////////
109     // Read values
110     ///////////////////////////////////////////////////////////////////////////
111 
readOperationType()112     public int readOperationType() {
113         return readByte();
114     }
115 
readBoolean()116     public boolean readBoolean() {
117         byte value = mBuffer[mIndex];
118         mIndex++;
119         return (value == 1);
120     }
121 
readByte()122     public int readByte() {
123         int value = 0xFF & mBuffer[mIndex];
124         mIndex++;
125         return value;
126     }
127 
readShort()128     public int readShort() {
129         int v1 = (mBuffer[mIndex++] & 0xFF) << 8;
130         int v2 = (mBuffer[mIndex++] & 0xFF) << 0;
131         return v1 + v2;
132     }
peekInt()133     public int peekInt() {
134         int tmp = mIndex;
135         int v1 = (mBuffer[tmp++] & 0xFF) << 24;
136         int v2 = (mBuffer[tmp++] & 0xFF) << 16;
137         int v3 = (mBuffer[tmp++] & 0xFF) << 8;
138         int v4 = (mBuffer[tmp++] & 0xFF) << 0;
139         return v1 + v2 + v3 + v4;
140     }
141 
readInt()142     public int readInt() {
143         int v1 = (mBuffer[mIndex++] & 0xFF) << 24;
144         int v2 = (mBuffer[mIndex++] & 0xFF) << 16;
145         int v3 = (mBuffer[mIndex++] & 0xFF) << 8;
146         int v4 = (mBuffer[mIndex++] & 0xFF) << 0;
147         return v1 + v2 + v3 + v4;
148     }
149 
readLong()150     public long readLong() {
151         long v1 = (mBuffer[mIndex++] & 0xFFL) << 56;
152         long v2 = (mBuffer[mIndex++] & 0xFFL) << 48;
153         long v3 = (mBuffer[mIndex++] & 0xFFL) << 40;
154         long v4 = (mBuffer[mIndex++] & 0xFFL) << 32;
155         long v5 = (mBuffer[mIndex++] & 0xFFL) << 24;
156         long v6 = (mBuffer[mIndex++] & 0xFFL) << 16;
157         long v7 = (mBuffer[mIndex++] & 0xFFL) << 8;
158         long v8 = (mBuffer[mIndex++] & 0xFFL) << 0;
159         return v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8;
160     }
161 
readFloat()162     public float readFloat() {
163         return java.lang.Float.intBitsToFloat(readInt());
164     }
165 
readDouble()166     public double readDouble() {
167         return java.lang.Double.longBitsToDouble(readLong());
168     }
169 
readBuffer()170     public byte[] readBuffer() {
171         int count = readInt();
172         byte[] b = Arrays.copyOfRange(mBuffer, mIndex, mIndex + count);
173         mIndex += count;
174         return b;
175     }
176 
readBuffer(int maxSize)177     public byte[] readBuffer(int maxSize) {
178         int count = readInt();
179         if (count < 0 || count > maxSize) {
180             throw new RuntimeException("attempt read a buff of invalid size 0 <= "
181                     + count + " > " + maxSize);
182         }
183         byte[] b = Arrays.copyOfRange(mBuffer, mIndex, mIndex + count);
184         mIndex += count;
185         return b;
186     }
187 
readUTF8()188     public String readUTF8() {
189         byte[] stringBuffer = readBuffer();
190         return new String(stringBuffer);
191     }
192 
readUTF8(int maxSize)193     public String readUTF8(int maxSize) {
194         byte[] stringBuffer = readBuffer(maxSize);
195         return new String(stringBuffer);
196     }
197 
198     ///////////////////////////////////////////////////////////////////////////
199     // Write values
200     ///////////////////////////////////////////////////////////////////////////
201 
writeBoolean(boolean value)202     public void writeBoolean(boolean value) {
203         resize(1);
204         mBuffer[mIndex++] = (byte) ((value) ? 1 : 0);
205         mSize++;
206     }
207 
writeByte(int value)208     public void writeByte(int value) {
209         resize(1);
210         mBuffer[mIndex++] = (byte) value;
211         mSize++;
212     }
213 
writeShort(int value)214     public void writeShort(int value) {
215         int need = 2;
216         resize(need);
217         mBuffer[mIndex++] = (byte) (value >>> 8 & 0xFF);
218         mBuffer[mIndex++] = (byte) (value & 0xFF);
219         mSize += need;
220     }
221 
writeInt(int value)222     public void writeInt(int value) {
223         int need = 4;
224         resize(need);
225         mBuffer[mIndex++] = (byte) (value >>> 24 & 0xFF);
226         mBuffer[mIndex++] = (byte) (value >>> 16 & 0xFF);
227         mBuffer[mIndex++] = (byte) (value >>> 8 & 0xFF);
228         mBuffer[mIndex++] = (byte) (value & 0xFF);
229         mSize += need;
230     }
231 
writeLong(long value)232     public void writeLong(long value) {
233         int need = 8;
234         resize(need);
235         mBuffer[mIndex++] = (byte) (value >>> 56 & 0xFF);
236         mBuffer[mIndex++] = (byte) (value >>> 48 & 0xFF);
237         mBuffer[mIndex++] = (byte) (value >>> 40 & 0xFF);
238         mBuffer[mIndex++] = (byte) (value >>> 32 & 0xFF);
239         mBuffer[mIndex++] = (byte) (value >>> 24 & 0xFF);
240         mBuffer[mIndex++] = (byte) (value >>> 16 & 0xFF);
241         mBuffer[mIndex++] = (byte) (value >>> 8 & 0xFF);
242         mBuffer[mIndex++] = (byte) (value & 0xFF);
243         mSize += need;
244     }
245 
writeFloat(float value)246     public void writeFloat(float value) {
247         writeInt(Float.floatToRawIntBits(value));
248     }
249 
writeDouble(double value)250     public void writeDouble(double value) {
251         writeLong(Double.doubleToRawLongBits(value));
252     }
253 
writeBuffer(byte[] b)254     public void writeBuffer(byte[] b) {
255         resize(b.length + 4);
256         writeInt(b.length);
257         for (int i = 0; i < b.length; i++) {
258             mBuffer[mIndex++] = b[i];
259 
260         }
261         mSize += b.length;
262     }
263 
writeUTF8(String content)264     public void writeUTF8(String content) {
265         byte[] buffer = content.getBytes();
266         writeBuffer(buffer);
267     }
268 
269 }
270 
271