• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 
17 package android.hardware;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.IntDef;
21 import android.annotation.IntRange;
22 import android.annotation.LongDef;
23 import android.annotation.NonNull;
24 import android.compat.annotation.UnsupportedAppUsage;
25 import android.graphics.GraphicBuffer;
26 import android.os.BadParcelableException;
27 import android.os.Build;
28 import android.os.Parcel;
29 import android.os.Parcelable;
30 import android.view.SurfaceControl;
31 
32 import dalvik.annotation.optimization.CriticalNative;
33 import dalvik.annotation.optimization.FastNative;
34 import dalvik.system.CloseGuard;
35 
36 import libcore.util.NativeAllocationRegistry;
37 
38 import java.lang.annotation.Retention;
39 import java.lang.annotation.RetentionPolicy;
40 
41 /**
42  * HardwareBuffer wraps a native <code>AHardwareBuffer</code> object, which is a low-level object
43  * representing a memory buffer accessible by various hardware units. HardwareBuffer allows sharing
44  * buffers across different application processes. In particular, HardwareBuffers may be mappable
45  * to memory accessible to various hardware systems, such as the GPU, a sensor or context hub, or
46  * other auxiliary processing units.
47  *
48  * For more information, see the NDK documentation for <code>AHardwareBuffer</code>.
49  */
50 public final class HardwareBuffer implements Parcelable, AutoCloseable {
51     /** @hide */
52     @Retention(RetentionPolicy.SOURCE)
53     @IntDef(prefix = { "RGB", "BLOB", "YCBCR_", "D_", "DS_", "S_" }, value = {
54             RGBA_8888,
55             RGBA_FP16,
56             RGBA_1010102,
57             RGBX_8888,
58             RGB_888,
59             RGB_565,
60             BLOB,
61             YCBCR_420_888,
62             D_16,
63             D_24,
64             DS_24UI8,
65             D_FP32,
66             DS_FP32UI8,
67             S_UI8,
68             YCBCR_P010,
69             YCBCR_P210,
70             R_8,
71             R_16,
72             RG_1616,
73             RGBA_10101010,
74     })
75     public @interface Format {
76     }
77 
78     @Format
79     /** Format: 8 bits each red, green, blue, alpha */
80     public static final int RGBA_8888    = 1;
81     /** Format: 8 bits each red, green, blue, alpha, alpha is always 0xFF */
82     public static final int RGBX_8888    = 2;
83     /** Format: 8 bits each red, green, blue, no alpha */
84     public static final int RGB_888      = 3;
85     /** Format: 5 bits each red and blue, 6 bits green, no alpha */
86     public static final int RGB_565      = 4;
87     /** Format: 16 bits each red, green, blue, alpha */
88     public static final int RGBA_FP16    = 0x16;
89     /** Format: 10 bits each red, green, blue, 2 bits alpha */
90     public static final int RGBA_1010102 = 0x2b;
91     /** Format: opaque format used for raw data transfer; must have a height of 1 */
92     public static final int BLOB         = 0x21;
93     /** Format: Planar YCbCr 420; must have an even width and height */
94     public static final int YCBCR_420_888 = 0x23;
95     /** Format: 16 bits depth */
96     public static final int D_16         = 0x30;
97     /** Format: 24 bits depth */
98     public static final int D_24         = 0x31;
99     /** Format: 24 bits depth, 8 bits stencil */
100     public static final int DS_24UI8     = 0x32;
101     /** Format: 32 bits depth */
102     public static final int D_FP32       = 0x33;
103     /** Format: 32 bits depth, 8 bits stencil */
104     public static final int DS_FP32UI8   = 0x34;
105     /** Format: 8 bits stencil */
106     public static final int S_UI8        = 0x35;
107     /**
108      * <p>Android YUV P010 format.</p>
109      *
110      * P010 is a 4:2:0 YCbCr semiplanar format comprised of a WxH Y plane
111      * followed by a Wx(H/2) CbCr plane. Each sample is represented by a 16-bit
112      * little-endian value, with the lower 6 bits set to zero.
113      */
114     public static final int YCBCR_P010    = 0x36;
115     /**
116      * <p>Android YUV P210 format.</p>
117      *
118      * P210 is a 4:2:2 YCbCr semiplanar format comprised of a WxH Y plane
119      * followed by a WxH CbCr plane. Each sample is represented by a 16-bit
120      * little-endian value, with the lower 6 bits set to zero.
121      */
122     @FlaggedApi(android.media.codec.Flags.FLAG_P210_FORMAT_SUPPORT)
123     public static final int YCBCR_P210    = 0x3c;
124 
125     /** Format: 8 bits red */
126     @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_REQUESTED_FORMATS_V)
127     public static final int R_8           = 0x38;
128     /**
129      * Format: 16 bits red. When sampled on the GPU this is represented as an
130      * unsigned integer instead of implicit unsigned normalize.
131      * For more information see https://www.khronos.org/opengl/wiki/Normalized_Integer
132      */
133     @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_REQUESTED_FORMATS_V)
134     public static final int R_16          = 0x39;
135     /**
136      * Format: 16 bits each red, green. When sampled on the GPU this is represented
137      * as an unsigned integer instead of implicit unsigned normalize.
138      * For more information see https://www.khronos.org/opengl/wiki/Normalized_Integer
139      */
140     @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_REQUESTED_FORMATS_V)
141     public static final int RG_1616       = 0x3a;
142     /** Format: 10 bits each red, green, blue, alpha */
143     @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_REQUESTED_FORMATS_V)
144     public static final int RGBA_10101010 = 0x3b;
145 
146     // Note: do not rename, this field is used by native code
147     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
148     private long mNativeObject;
149 
150     // Invoked on destruction
151     private Runnable mCleaner;
152 
153     private final CloseGuard mCloseGuard = CloseGuard.get();
154 
155     /** @hide */
156     @Retention(RetentionPolicy.SOURCE)
157     @LongDef(flag = true, value = {USAGE_CPU_READ_RARELY, USAGE_CPU_READ_OFTEN,
158             USAGE_CPU_WRITE_RARELY, USAGE_CPU_WRITE_OFTEN, USAGE_GPU_SAMPLED_IMAGE,
159             USAGE_GPU_COLOR_OUTPUT, USAGE_COMPOSER_OVERLAY, USAGE_PROTECTED_CONTENT,
160             USAGE_VIDEO_ENCODE, USAGE_GPU_DATA_BUFFER, USAGE_SENSOR_DIRECT_DATA,
161             USAGE_GPU_CUBE_MAP, USAGE_GPU_MIPMAP_COMPLETE, USAGE_FRONT_BUFFER})
162     public @interface Usage {};
163 
164     @Usage
165     /** Usage: The buffer will sometimes be read by the CPU */
166     public static final long USAGE_CPU_READ_RARELY       = 2;
167     /** Usage: The buffer will often be read by the CPU */
168     public static final long USAGE_CPU_READ_OFTEN        = 3;
169 
170     /** Usage: The buffer will sometimes be written to by the CPU */
171     public static final long USAGE_CPU_WRITE_RARELY      = 2 << 4;
172     /** Usage: The buffer will often be written to by the CPU */
173     public static final long USAGE_CPU_WRITE_OFTEN       = 3 << 4;
174 
175     /** Usage: The buffer will be read from by the GPU */
176     public static final long USAGE_GPU_SAMPLED_IMAGE      = 1 << 8;
177     /** Usage: The buffer will be written to by the GPU */
178     public static final long USAGE_GPU_COLOR_OUTPUT       = 1 << 9;
179     /**
180      * The buffer will be used as a hardware composer overlay layer. That is, it will be displayed
181      * using the system compositor via {@link SurfaceControl}
182      *
183      * This flag is currently only needed when using
184      * {@link android.view.SurfaceControl.Transaction#setBuffer(SurfaceControl, HardwareBuffer)}
185      * to set a buffer. In all other cases, the framework adds this flag
186      * internally to buffers that could be presented in a composer overlay.
187      */
188     public static final long USAGE_COMPOSER_OVERLAY = 1 << 11;
189     /** Usage: The buffer must not be used outside of a protected hardware path */
190     public static final long USAGE_PROTECTED_CONTENT      = 1 << 14;
191     /** Usage: The buffer will be read by a hardware video encoder */
192     public static final long USAGE_VIDEO_ENCODE           = 1 << 16;
193     /** Usage: The buffer will be used for sensor direct data */
194     public static final long USAGE_SENSOR_DIRECT_DATA     = 1 << 23;
195     /** Usage: The buffer will be used as a shader storage or uniform buffer object */
196     public static final long USAGE_GPU_DATA_BUFFER        = 1 << 24;
197     /** Usage: The buffer will be used as a cube map texture */
198     public static final long USAGE_GPU_CUBE_MAP           = 1 << 25;
199     /** Usage: The buffer contains a complete mipmap hierarchy */
200     public static final long USAGE_GPU_MIPMAP_COMPLETE    = 1 << 26;
201     /** Usage: The buffer is used for front-buffer rendering. When front-buffering rendering is
202      * specified, different usages may adjust their behavior as a result. For example, when
203      * used as USAGE_GPU_COLOR_OUTPUT the buffer will behave similar to a single-buffered window.
204      * When used with USAGE_COMPOSER_OVERLAY, the system will try to prioritize the buffer
205      * receiving an overlay plane & avoid caching it in intermediate composition buffers. */
206     public static final long USAGE_FRONT_BUFFER           = 1L << 32;
207 
208     /**
209      * Creates a new <code>HardwareBuffer</code> instance.
210      *
211      * <p>Calling this method will throw an <code>IllegalStateException</code> if
212      * format is not a supported Format type.</p>
213      *
214      * @param width The width in pixels of the buffer
215      * @param height The height in pixels of the buffer
216      * @param format The @Format of each pixel
217      * @param layers The number of layers in the buffer
218      * @param usage The @Usage flags describing how the buffer will be used
219      * @return A <code>HardwareBuffer</code> instance if successful, or throws an
220      *     IllegalArgumentException if the dimensions passed are invalid (either zero, negative, or
221      *     too large to allocate), if the format is not supported, if the requested number of layers
222      *     is less than one or not supported, or if the passed usage flags are not a supported set.
223      */
224     @NonNull
create( @ntRangefrom = 1) int width, @IntRange(from = 1) int height, @Format int format, @IntRange(from = 1) int layers, @Usage long usage)225     public static HardwareBuffer create(
226             @IntRange(from = 1) int width, @IntRange(from = 1) int height,
227             @Format int format, @IntRange(from = 1) int layers, @Usage long usage) {
228         if (width <= 0) {
229             throw new IllegalArgumentException("Invalid width " + width);
230         }
231         if (height <= 0) {
232             throw new IllegalArgumentException("Invalid height " + height);
233         }
234         if (layers <= 0) {
235             throw new IllegalArgumentException("Invalid layer count " + layers);
236         }
237         if (format == BLOB && height != 1) {
238             throw new IllegalArgumentException("Height must be 1 when using the BLOB format");
239         }
240         long nativeObject = nCreateHardwareBuffer(width, height, format, layers, usage);
241         if (nativeObject == 0) {
242             throw new IllegalArgumentException("Unable to create a HardwareBuffer, either the " +
243                     "dimensions passed were too large, too many image layers were requested, " +
244                     "or an invalid set of usage flags or invalid format was passed");
245         }
246         return new HardwareBuffer(nativeObject);
247     }
248 
249     /**
250      * Queries whether the given buffer description is supported by the system. If this returns
251      * true, then the allocation may succeed until resource exhaustion occurs. If this returns
252      * false then this combination will never succeed.
253      *
254      * @param width The width in pixels of the buffer
255      * @param height The height in pixels of the buffer
256      * @param format The @Format of each pixel
257      * @param layers The number of layers in the buffer
258      * @param usage The @Usage flags describing how the buffer will be used
259      * @return True if the combination is supported, false otherwise.
260      */
isSupported(@ntRangefrom = 1) int width, @IntRange(from = 1) int height, @Format int format, @IntRange(from = 1) int layers, @Usage long usage)261     public static boolean isSupported(@IntRange(from = 1) int width, @IntRange(from = 1) int height,
262             @Format int format, @IntRange(from = 1) int layers, @Usage long usage) {
263         if (width <= 0) {
264             throw new IllegalArgumentException("Invalid width " + width);
265         }
266         if (height <= 0) {
267             throw new IllegalArgumentException("Invalid height " + height);
268         }
269         if (layers <= 0) {
270             throw new IllegalArgumentException("Invalid layer count " + layers);
271         }
272         if (format == BLOB && height != 1) {
273             throw new IllegalArgumentException("Height must be 1 when using the BLOB format");
274         }
275         return nIsSupported(width, height, format, layers, usage);
276     }
277 
278     /**
279      * @hide
280      * Returns a <code>HardwareBuffer</code> instance from <code>GraphicBuffer</code>
281      *
282      * @param graphicBuffer A GraphicBuffer to be wrapped as HardwareBuffer
283      * @return A <code>HardwareBuffer</code> instance.
284      */
285     @NonNull
createFromGraphicBuffer(@onNull GraphicBuffer graphicBuffer)286     public static HardwareBuffer createFromGraphicBuffer(@NonNull GraphicBuffer graphicBuffer) {
287         long nativeObject = nCreateFromGraphicBuffer(graphicBuffer);
288         return new HardwareBuffer(nativeObject);
289     }
290 
291     /**
292      * @hide
293      */
getRegistry(long size)294     private static NativeAllocationRegistry getRegistry(long size) {
295         final long func = nGetNativeFinalizer();
296         final Class cls = HardwareBuffer.class;
297         return com.android.libcore.readonly.Flags.nativeMetrics()
298             ? NativeAllocationRegistry.createNonmalloced(cls, func, size)
299             : NativeAllocationRegistry.createNonmalloced(cls.getClassLoader(), func, size);
300     }
301 
302     /**
303      * Private use only. See {@link #create(int, int, int, int, long)}. May also be
304      * called from JNI using an already allocated native <code>HardwareBuffer</code>.
305      */
306     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
HardwareBuffer(long nativeObject)307     private HardwareBuffer(long nativeObject) {
308         mNativeObject = nativeObject;
309         long bufferSize = nEstimateSize(nativeObject);
310         mCleaner = getRegistry(bufferSize).registerNativeAllocation(this, mNativeObject);
311         mCloseGuard.open("HardwareBuffer.close");
312     }
313 
314     @Override
finalize()315     protected void finalize() throws Throwable {
316         try {
317             mCloseGuard.warnIfOpen();
318             close();
319         } finally {
320             super.finalize();
321         }
322     }
323 
324     /**
325      * Returns the width of this buffer in pixels.
326      */
getWidth()327     public int getWidth() {
328         checkClosed("width");
329         return nGetWidth(mNativeObject);
330     }
331 
332     /**
333      * Returns the height of this buffer in pixels.
334      */
getHeight()335     public int getHeight() {
336         checkClosed("height");
337         return nGetHeight(mNativeObject);
338     }
339 
340     /**
341      * Returns the @Format of this buffer.
342      */
343     @Format
getFormat()344     public int getFormat() {
345         checkClosed("format");
346         return nGetFormat(mNativeObject);
347     }
348 
349     /**
350      * Returns the number of layers in this buffer.
351      */
getLayers()352     public int getLayers() {
353         checkClosed("layer count");
354         return nGetLayers(mNativeObject);
355     }
356 
357     /**
358      * Returns the usage flags of the usage hints set on this buffer.
359      */
getUsage()360     public long getUsage() {
361         checkClosed("usage");
362         return nGetUsage(mNativeObject);
363     }
364 
365     /**
366      * Returns the system-wide unique id for this buffer
367      *
368      * This can be useful as a cache key for associating additional objects with
369      * a given HardwareBuffer, such as associating an imported EGLImage with
370      * the target HardwareBuffer when processing a stream of buffers from
371      * ImageReader.
372      *
373      * This can also be useful for doing cross-process buffer caching. As sending
374      * a HardwareBuffer over Binder is slower than sending a long, this can be
375      * used as reliable cache key after an initial handshake that passes the
376      * HardwareBuffers themselves to later be referred to using only the id.
377      */
getId()378     public long getId() {
379         checkClosed("id");
380         return nGetId(mNativeObject);
381     }
382 
checkClosed(String name)383     private void checkClosed(String name) {
384         if (isClosed()) {
385             throw new IllegalStateException("This HardwareBuffer has been closed and its "
386                     + name + " cannot be obtained.");
387         }
388     }
389 
390     /**
391      * Destroys this buffer immediately. Calling this method frees up any
392      * underlying native resources. After calling this method, this buffer
393      * must not be used in any way.
394      *
395      * @see #isClosed()
396      */
397     @Override
close()398     public void close() {
399         if (!isClosed()) {
400             mCloseGuard.close();
401             mNativeObject = 0;
402             mCleaner.run();
403             mCleaner = null;
404         }
405     }
406 
407     /**
408      * Indicates whether this buffer has been closed. A closed buffer cannot
409      * be used in any way: the buffer cannot be written to a parcel, etc.
410      *
411      * @return True if this <code>HardwareBuffer</code> is in a closed state,
412      *         false otherwise.
413      *
414      * @see #close()
415      */
isClosed()416     public boolean isClosed() {
417         return mNativeObject == 0;
418     }
419 
420     @Override
describeContents()421     public int describeContents() {
422         return Parcelable.CONTENTS_FILE_DESCRIPTOR;
423     }
424 
425     /**
426      * Flatten this object in to a Parcel.
427      *
428      * <p>Calling this method will throw an <code>IllegalStateException</code> if
429      * {@link #close()} has been previously called.</p>
430      *
431      * @param dest The Parcel in which the object should be written.
432      * @param flags Additional flags about how the object should be written.
433      *              May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
434      */
435     @Override
writeToParcel(Parcel dest, int flags)436     public void writeToParcel(Parcel dest, int flags) {
437         if (isClosed()) {
438             throw new IllegalStateException("This HardwareBuffer has been closed and cannot be "
439                     + "written to a parcel.");
440         }
441         nWriteHardwareBufferToParcel(mNativeObject, dest);
442     }
443 
444     public static final @android.annotation.NonNull Parcelable.Creator<HardwareBuffer> CREATOR =
445             new Parcelable.Creator<HardwareBuffer>() {
446         public HardwareBuffer createFromParcel(Parcel in) {
447             if (in == null) {
448                 throw new NullPointerException("null passed to createFromParcel");
449             }
450             long nativeObject = nReadHardwareBufferFromParcel(in);
451             if (nativeObject != 0) {
452                 return new HardwareBuffer(nativeObject);
453             }
454             throw new BadParcelableException("Failed to read hardware buffer");
455         }
456 
457         public HardwareBuffer[] newArray(int size) {
458             return new HardwareBuffer[size];
459         }
460     };
461 
nCreateHardwareBuffer(int width, int height, int format, int layers, long usage)462     private static native long nCreateHardwareBuffer(int width, int height, int format, int layers,
463             long usage);
nCreateFromGraphicBuffer(GraphicBuffer graphicBuffer)464     private static native long nCreateFromGraphicBuffer(GraphicBuffer graphicBuffer);
nGetNativeFinalizer()465     private static native long nGetNativeFinalizer();
nWriteHardwareBufferToParcel(long nativeObject, Parcel dest)466     private static native void nWriteHardwareBufferToParcel(long nativeObject, Parcel dest);
nReadHardwareBufferFromParcel(Parcel in)467     private static native long nReadHardwareBufferFromParcel(Parcel in);
468     @FastNative
nGetWidth(long nativeObject)469     private static native int nGetWidth(long nativeObject);
470     @FastNative
nGetHeight(long nativeObject)471     private static native int nGetHeight(long nativeObject);
472     @FastNative
nGetFormat(long nativeObject)473     private static native int nGetFormat(long nativeObject);
474     @FastNative
nGetLayers(long nativeObject)475     private static native int nGetLayers(long nativeObject);
476     @FastNative
nGetUsage(long nativeObject)477     private static native long nGetUsage(long nativeObject);
nIsSupported(int width, int height, int format, int layers, long usage)478     private static native boolean nIsSupported(int width, int height, int format, int layers,
479             long usage);
480     @CriticalNative
nEstimateSize(long nativeObject)481     private static native long nEstimateSize(long nativeObject);
482     @CriticalNative
nGetId(long nativeObject)483     private static native long nGetId(long nativeObject);
484 }
485