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