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