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