1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package libcore.io; 19 20 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; 21 22 import android.compat.annotation.UnsupportedAppUsage; 23 import android.annotation.SystemApi; 24 25 import java.nio.ByteOrder; 26 27 import dalvik.annotation.optimization.FastNative; 28 29 import libcore.util.NonNull; 30 31 /** 32 * Unsafe access to memory. 33 * 34 * @hide 35 */ 36 @SystemApi(client = MODULE_LIBRARIES) 37 public final class Memory { Memory()38 private Memory() { } 39 40 /** 41 * Used to optimize nio heap buffer bulk get operations. 'dst' must be a primitive array. 42 * 'dstOffset' is measured in units of 'sizeofElements' bytes. 43 * 44 * @hide 45 */ unsafeBulkGet(Object dst, int dstOffset, int byteCount, byte[] src, int srcOffset, int sizeofElements, boolean swap)46 public static native void unsafeBulkGet(Object dst, int dstOffset, int byteCount, 47 byte[] src, int srcOffset, int sizeofElements, boolean swap); 48 49 /** 50 * Used to optimize nio heap buffer bulk put operations. 'src' must be a primitive array. 51 * 'srcOffset' is measured in units of 'sizeofElements' bytes. 52 * @hide 53 */ unsafeBulkPut(byte[] dst, int dstOffset, int byteCount, Object src, int srcOffset, int sizeofElements, boolean swap)54 public static native void unsafeBulkPut(byte[] dst, int dstOffset, int byteCount, 55 Object src, int srcOffset, int sizeofElements, boolean swap); 56 57 /** 58 * Gets int value from a byte buffer {@code src} at offset {@code offset} using 59 * {@code order} byte order. 60 * 61 * @param src source byte buffer 62 * @param offset offset in {@code src} to get bytes from 63 * @param order byte order 64 * @return int value 65 * 66 * @hide 67 */ 68 @SystemApi(client = MODULE_LIBRARIES) peekInt(@onNull byte[] src, int offset, @NonNull ByteOrder order)69 public static int peekInt(@NonNull byte[] src, int offset, @NonNull ByteOrder order) { 70 if (order == ByteOrder.BIG_ENDIAN) { 71 return (((src[offset++] & 0xff) << 24) | 72 ((src[offset++] & 0xff) << 16) | 73 ((src[offset++] & 0xff) << 8) | 74 ((src[offset ] & 0xff) << 0)); 75 } else { 76 return (((src[offset++] & 0xff) << 0) | 77 ((src[offset++] & 0xff) << 8) | 78 ((src[offset++] & 0xff) << 16) | 79 ((src[offset ] & 0xff) << 24)); 80 } 81 } 82 83 /** 84 * @hide 85 */ peekLong(byte[] src, int offset, ByteOrder order)86 public static long peekLong(byte[] src, int offset, ByteOrder order) { 87 if (order == ByteOrder.BIG_ENDIAN) { 88 int h = ((src[offset++] & 0xff) << 24) | 89 ((src[offset++] & 0xff) << 16) | 90 ((src[offset++] & 0xff) << 8) | 91 ((src[offset++] & 0xff) << 0); 92 int l = ((src[offset++] & 0xff) << 24) | 93 ((src[offset++] & 0xff) << 16) | 94 ((src[offset++] & 0xff) << 8) | 95 ((src[offset ] & 0xff) << 0); 96 return (((long) h) << 32L) | ((long) l) & 0xffffffffL; 97 } else { 98 int l = ((src[offset++] & 0xff) << 0) | 99 ((src[offset++] & 0xff) << 8) | 100 ((src[offset++] & 0xff) << 16) | 101 ((src[offset++] & 0xff) << 24); 102 int h = ((src[offset++] & 0xff) << 0) | 103 ((src[offset++] & 0xff) << 8) | 104 ((src[offset++] & 0xff) << 16) | 105 ((src[offset ] & 0xff) << 24); 106 return (((long) h) << 32L) | ((long) l) & 0xffffffffL; 107 } 108 } 109 110 /** 111 * Gets short value from a byte buffer {@code src} at offset {@code offset} using 112 * {@code order} byte order. 113 * 114 * @param src source byte buffer 115 * @param offset offset in {@code src} to get bytes from 116 * @param order byte order 117 * @return short value 118 * 119 * @hide 120 */ 121 @SystemApi(client = MODULE_LIBRARIES) peekShort(@onNull byte[] src, int offset, @NonNull ByteOrder order)122 public static short peekShort(@NonNull byte[] src, int offset, @NonNull ByteOrder order) { 123 if (order == ByteOrder.BIG_ENDIAN) { 124 return (short) ((src[offset] << 8) | (src[offset + 1] & 0xff)); 125 } else { 126 return (short) ((src[offset + 1] << 8) | (src[offset] & 0xff)); 127 } 128 } 129 130 /** 131 * Writes given int value {@code value} to a byte buffer {@code dst} using 132 * {@code order} byte order. 133 * 134 * @param dst byte buffer where to write {@code value} 135 * @param offset offset in {@code dst} to put value to 136 * @param value int value to write 137 * @param order byte order 138 * 139 * @hide 140 */ 141 @SystemApi(client = MODULE_LIBRARIES) pokeInt(@onNull byte[] dst, int offset, int value, @NonNull ByteOrder order)142 public static void pokeInt(@NonNull byte[] dst, int offset, int value, @NonNull ByteOrder order) { 143 if (order == ByteOrder.BIG_ENDIAN) { 144 dst[offset++] = (byte) ((value >> 24) & 0xff); 145 dst[offset++] = (byte) ((value >> 16) & 0xff); 146 dst[offset++] = (byte) ((value >> 8) & 0xff); 147 dst[offset ] = (byte) ((value >> 0) & 0xff); 148 } else { 149 dst[offset++] = (byte) ((value >> 0) & 0xff); 150 dst[offset++] = (byte) ((value >> 8) & 0xff); 151 dst[offset++] = (byte) ((value >> 16) & 0xff); 152 dst[offset ] = (byte) ((value >> 24) & 0xff); 153 } 154 } 155 156 /** 157 * Writes given long value {@code value} to a byte buffer {@code dst} using 158 * {@code order} byte order. 159 * 160 * @param dst byte buffer where to write {@code value} 161 * @param offset offset in {@code dst} to put value to 162 * @param value long value to write 163 * @param order byte order 164 * 165 * @hide 166 */ 167 @SystemApi(client = MODULE_LIBRARIES) pokeLong(@onNull byte[] dst, int offset, long value, @NonNull ByteOrder order)168 public static void pokeLong(@NonNull byte[] dst, int offset, long value, @NonNull ByteOrder order) { 169 if (order == ByteOrder.BIG_ENDIAN) { 170 int i = (int) (value >> 32); 171 dst[offset++] = (byte) ((i >> 24) & 0xff); 172 dst[offset++] = (byte) ((i >> 16) & 0xff); 173 dst[offset++] = (byte) ((i >> 8) & 0xff); 174 dst[offset++] = (byte) ((i >> 0) & 0xff); 175 i = (int) value; 176 dst[offset++] = (byte) ((i >> 24) & 0xff); 177 dst[offset++] = (byte) ((i >> 16) & 0xff); 178 dst[offset++] = (byte) ((i >> 8) & 0xff); 179 dst[offset ] = (byte) ((i >> 0) & 0xff); 180 } else { 181 int i = (int) value; 182 dst[offset++] = (byte) ((i >> 0) & 0xff); 183 dst[offset++] = (byte) ((i >> 8) & 0xff); 184 dst[offset++] = (byte) ((i >> 16) & 0xff); 185 dst[offset++] = (byte) ((i >> 24) & 0xff); 186 i = (int) (value >> 32); 187 dst[offset++] = (byte) ((i >> 0) & 0xff); 188 dst[offset++] = (byte) ((i >> 8) & 0xff); 189 dst[offset++] = (byte) ((i >> 16) & 0xff); 190 dst[offset ] = (byte) ((i >> 24) & 0xff); 191 } 192 } 193 194 /** 195 * Writes given short value {@code value} to a byte buffer {@code dst} using 196 * {@code order} byte order. 197 * 198 * @param dst byte buffer where to write {@code value} 199 * @param offset offset in {@code dst} to put value to 200 * @param value short value to write 201 * @param order byte order 202 * 203 * @hide 204 */ 205 @SystemApi(client = MODULE_LIBRARIES) pokeShort(@onNull byte[] dst, int offset, short value, @NonNull ByteOrder order)206 public static void pokeShort(@NonNull byte[] dst, int offset, short value, @NonNull ByteOrder order) { 207 if (order == ByteOrder.BIG_ENDIAN) { 208 dst[offset++] = (byte) ((value >> 8) & 0xff); 209 dst[offset ] = (byte) ((value >> 0) & 0xff); 210 } else { 211 dst[offset++] = (byte) ((value >> 0) & 0xff); 212 dst[offset ] = (byte) ((value >> 8) & 0xff); 213 } 214 } 215 216 /** 217 * Copies {@code byteCount} bytes from the source {@code srcObject} to the 218 * destination {@code dstObject}. The objects are either instances of 219 * {@code DirectByteBuffer} or {@code byte[]}. The offsets in the {@code byte[]} 220 * case must include the {@link Buffer#arrayOffset()} if the array came from a 221 * {@link Buffer#array()} call. 222 * 223 * <p>We could make this private and provide the four type-safe variants, but then 224 * {@link ByteBuffer#put(ByteBuffer)} would need to work out which to call based on 225 * whether the source and destination buffers are direct or not. 226 * 227 * @param dstObject destination buffer 228 * @param dstOffset offset in the destination buffer 229 * @param srcObject source buffer 230 * @param srcOffset offset in the source buffer 231 * @param byteCount number of bytes to copy 232 * 233 * @hide make type-safe before making public? 234 */ 235 @SystemApi(client = MODULE_LIBRARIES) memmove(@onNull Object dstObject, int dstOffset, @NonNull Object srcObject, int srcOffset, long byteCount)236 public static native void memmove(@NonNull Object dstObject, int dstOffset, @NonNull Object srcObject, int srcOffset, long byteCount); 237 238 /** 239 * @hide 240 */ 241 @UnsupportedAppUsage 242 @FastNative peekByte(long address)243 public static native byte peekByte(long address); 244 245 /** 246 * @hide 247 */ 248 @UnsupportedAppUsage peekInt(long address, boolean swap)249 public static int peekInt(long address, boolean swap) { 250 int result = peekIntNative(address); 251 if (swap) { 252 result = Integer.reverseBytes(result); 253 } 254 return result; 255 } 256 @FastNative peekIntNative(long address)257 private static native int peekIntNative(long address); 258 259 /** 260 * @hide 261 */ 262 @UnsupportedAppUsage peekLong(long address, boolean swap)263 public static long peekLong(long address, boolean swap) { 264 long result = peekLongNative(address); 265 if (swap) { 266 result = Long.reverseBytes(result); 267 } 268 return result; 269 } 270 @FastNative peekLongNative(long address)271 private static native long peekLongNative(long address); 272 273 /** 274 * @hide 275 */ peekShort(long address, boolean swap)276 public static short peekShort(long address, boolean swap) { 277 short result = peekShortNative(address); 278 if (swap) { 279 result = Short.reverseBytes(result); 280 } 281 return result; 282 } 283 @FastNative peekShortNative(long address)284 private static native short peekShortNative(long address); 285 286 /** 287 * @hide 288 */ 289 @UnsupportedAppUsage 290 @FastNative peekByteArray(long address, byte[] dst, int dstOffset, int byteCount)291 public static native void peekByteArray(long address, byte[] dst, int dstOffset, int byteCount); 292 293 /** 294 * @hide 295 */ 296 @FastNative peekCharArray(long address, char[] dst, int dstOffset, int charCount, boolean swap)297 public static native void peekCharArray(long address, char[] dst, int dstOffset, int charCount, boolean swap); 298 299 /** 300 * @hide 301 */ 302 @FastNative peekDoubleArray(long address, double[] dst, int dstOffset, int doubleCount, boolean swap)303 public static native void peekDoubleArray(long address, double[] dst, int dstOffset, int doubleCount, boolean swap); 304 305 /** 306 * @hide 307 */ 308 @FastNative peekFloatArray(long address, float[] dst, int dstOffset, int floatCount, boolean swap)309 public static native void peekFloatArray(long address, float[] dst, int dstOffset, int floatCount, boolean swap); 310 311 /** 312 * @hide 313 */ 314 @FastNative peekIntArray(long address, int[] dst, int dstOffset, int intCount, boolean swap)315 public static native void peekIntArray(long address, int[] dst, int dstOffset, int intCount, boolean swap); 316 317 /** 318 * @hide 319 */ 320 @FastNative peekLongArray(long address, long[] dst, int dstOffset, int longCount, boolean swap)321 public static native void peekLongArray(long address, long[] dst, int dstOffset, int longCount, boolean swap); 322 323 /** 324 * @hide 325 */ 326 @FastNative peekShortArray(long address, short[] dst, int dstOffset, int shortCount, boolean swap)327 public static native void peekShortArray(long address, short[] dst, int dstOffset, int shortCount, boolean swap); 328 329 /** 330 * @hide 331 */ 332 @UnsupportedAppUsage 333 @FastNative pokeByte(long address, byte value)334 public static native void pokeByte(long address, byte value); 335 336 /** 337 * @hide 338 */ 339 @UnsupportedAppUsage pokeInt(long address, int value, boolean swap)340 public static void pokeInt(long address, int value, boolean swap) { 341 if (swap) { 342 value = Integer.reverseBytes(value); 343 } 344 pokeIntNative(address, value); 345 } 346 @FastNative pokeIntNative(long address, int value)347 private static native void pokeIntNative(long address, int value); 348 349 /** 350 * @hide 351 */ 352 @UnsupportedAppUsage pokeLong(long address, long value, boolean swap)353 public static void pokeLong(long address, long value, boolean swap) { 354 if (swap) { 355 value = Long.reverseBytes(value); 356 } 357 pokeLongNative(address, value); 358 } 359 @FastNative pokeLongNative(long address, long value)360 private static native void pokeLongNative(long address, long value); 361 362 /** 363 * @hide 364 */ pokeShort(long address, short value, boolean swap)365 public static void pokeShort(long address, short value, boolean swap) { 366 if (swap) { 367 value = Short.reverseBytes(value); 368 } 369 pokeShortNative(address, value); 370 } 371 @FastNative pokeShortNative(long address, short value)372 private static native void pokeShortNative(long address, short value); 373 374 /** 375 * @hide 376 */ 377 @UnsupportedAppUsage pokeByteArray(long address, byte[] src, int offset, int count)378 public static native void pokeByteArray(long address, byte[] src, int offset, int count); 379 380 /** 381 * @hide 382 */ pokeCharArray(long address, char[] src, int offset, int count, boolean swap)383 public static native void pokeCharArray(long address, char[] src, int offset, int count, boolean swap); 384 385 /** 386 * @hide 387 */ pokeDoubleArray(long address, double[] src, int offset, int count, boolean swap)388 public static native void pokeDoubleArray(long address, double[] src, int offset, int count, boolean swap); 389 390 /** 391 * @hide 392 */ pokeFloatArray(long address, float[] src, int offset, int count, boolean swap)393 public static native void pokeFloatArray(long address, float[] src, int offset, int count, boolean swap); 394 395 /** 396 * @hide 397 */ pokeIntArray(long address, int[] src, int offset, int count, boolean swap)398 public static native void pokeIntArray(long address, int[] src, int offset, int count, boolean swap); 399 400 /** 401 * @hide 402 */ pokeLongArray(long address, long[] src, int offset, int count, boolean swap)403 public static native void pokeLongArray(long address, long[] src, int offset, int count, boolean swap); 404 405 /** 406 * @hide 407 */ pokeShortArray(long address, short[] src, int offset, int count, boolean swap)408 public static native void pokeShortArray(long address, short[] src, int offset, int count, boolean swap); 409 } 410