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