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