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