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