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 (!HardwareBuffer.isSupportedFormat(format)) { 192 throw new IllegalArgumentException("Invalid pixel format " + format); 193 } 194 if (width <= 0) { 195 throw new IllegalArgumentException("Invalid width " + width); 196 } 197 if (height <= 0) { 198 throw new IllegalArgumentException("Invalid height " + height); 199 } 200 if (layers <= 0) { 201 throw new IllegalArgumentException("Invalid layer count " + layers); 202 } 203 if (format == BLOB && height != 1) { 204 throw new IllegalArgumentException("Height must be 1 when using the BLOB format"); 205 } 206 long nativeObject = nCreateHardwareBuffer(width, height, format, layers, usage); 207 if (nativeObject == 0) { 208 throw new IllegalArgumentException("Unable to create a HardwareBuffer, either the " + 209 "dimensions passed were too large, too many image layers were requested, " + 210 "or an invalid set of usage flags or invalid format was passed"); 211 } 212 return new HardwareBuffer(nativeObject); 213 } 214 215 /** 216 * Queries whether the given buffer description is supported by the system. If this returns 217 * true, then the allocation may succeed until resource exhaustion occurs. If this returns 218 * false then this combination will never succeed. 219 * 220 * @param width The width in pixels of the buffer 221 * @param height The height in pixels of the buffer 222 * @param format The @Format of each pixel 223 * @param layers The number of layers in the buffer 224 * @param usage The @Usage flags describing how the buffer will be used 225 * @return True if the combination is supported, false otherwise. 226 */ isSupported(@ntRangefrom = 1) int width, @IntRange(from = 1) int height, @Format int format, @IntRange(from = 1) int layers, @Usage long usage)227 public static boolean isSupported(@IntRange(from = 1) int width, @IntRange(from = 1) int height, 228 @Format int format, @IntRange(from = 1) int layers, @Usage long usage) { 229 if (!HardwareBuffer.isSupportedFormat(format)) { 230 throw new IllegalArgumentException("Invalid pixel format " + format); 231 } 232 if (width <= 0) { 233 throw new IllegalArgumentException("Invalid width " + width); 234 } 235 if (height <= 0) { 236 throw new IllegalArgumentException("Invalid height " + height); 237 } 238 if (layers <= 0) { 239 throw new IllegalArgumentException("Invalid layer count " + layers); 240 } 241 if (format == BLOB && height != 1) { 242 throw new IllegalArgumentException("Height must be 1 when using the BLOB format"); 243 } 244 return nIsSupported(width, height, format, layers, usage); 245 } 246 247 /** 248 * @hide 249 * Returns a <code>HardwareBuffer</code> instance from <code>GraphicBuffer</code> 250 * 251 * @param graphicBuffer A GraphicBuffer to be wrapped as HardwareBuffer 252 * @return A <code>HardwareBuffer</code> instance. 253 */ 254 @NonNull createFromGraphicBuffer(@onNull GraphicBuffer graphicBuffer)255 public static HardwareBuffer createFromGraphicBuffer(@NonNull GraphicBuffer graphicBuffer) { 256 long nativeObject = nCreateFromGraphicBuffer(graphicBuffer); 257 return new HardwareBuffer(nativeObject); 258 } 259 260 /** 261 * Private use only. See {@link #create(int, int, int, int, long)}. May also be 262 * called from JNI using an already allocated native <code>HardwareBuffer</code>. 263 */ 264 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) HardwareBuffer(long nativeObject)265 private HardwareBuffer(long nativeObject) { 266 mNativeObject = nativeObject; 267 long bufferSize = nEstimateSize(nativeObject); 268 ClassLoader loader = HardwareBuffer.class.getClassLoader(); 269 NativeAllocationRegistry registry = new NativeAllocationRegistry( 270 loader, nGetNativeFinalizer(), bufferSize); 271 mCleaner = registry.registerNativeAllocation(this, mNativeObject); 272 mCloseGuard.open("HardwareBuffer.close"); 273 } 274 275 @Override finalize()276 protected void finalize() throws Throwable { 277 try { 278 mCloseGuard.warnIfOpen(); 279 close(); 280 } finally { 281 super.finalize(); 282 } 283 } 284 285 /** 286 * Returns the width of this buffer in pixels. 287 */ getWidth()288 public int getWidth() { 289 if (isClosed()) { 290 throw new IllegalStateException("This HardwareBuffer has been closed and its width " 291 + "cannot be obtained."); 292 } 293 return nGetWidth(mNativeObject); 294 } 295 296 /** 297 * Returns the height of this buffer in pixels. 298 */ getHeight()299 public int getHeight() { 300 if (isClosed()) { 301 throw new IllegalStateException("This HardwareBuffer has been closed and its height " 302 + "cannot be obtained."); 303 } 304 return nGetHeight(mNativeObject); 305 } 306 307 /** 308 * Returns the @Format of this buffer. 309 */ 310 @Format getFormat()311 public int getFormat() { 312 if (isClosed()) { 313 throw new IllegalStateException("This HardwareBuffer has been closed and its format " 314 + "cannot be obtained."); 315 } 316 return nGetFormat(mNativeObject); 317 } 318 319 /** 320 * Returns the number of layers in this buffer. 321 */ getLayers()322 public int getLayers() { 323 if (isClosed()) { 324 throw new IllegalStateException("This HardwareBuffer has been closed and its layer " 325 + "count cannot be obtained."); 326 } 327 return nGetLayers(mNativeObject); 328 } 329 330 /** 331 * Returns the usage flags of the usage hints set on this buffer. 332 */ getUsage()333 public long getUsage() { 334 if (isClosed()) { 335 throw new IllegalStateException("This HardwareBuffer has been closed and its usage " 336 + "cannot be obtained."); 337 } 338 return nGetUsage(mNativeObject); 339 } 340 341 /** 342 * Destroys this buffer immediately. Calling this method frees up any 343 * underlying native resources. After calling this method, this buffer 344 * must not be used in any way. 345 * 346 * @see #isClosed() 347 */ 348 @Override close()349 public void close() { 350 if (!isClosed()) { 351 mCloseGuard.close(); 352 mNativeObject = 0; 353 mCleaner.run(); 354 mCleaner = null; 355 } 356 } 357 358 /** 359 * Indicates whether this buffer has been closed. A closed buffer cannot 360 * be used in any way: the buffer cannot be written to a parcel, etc. 361 * 362 * @return True if this <code>HardwareBuffer</code> is in a closed state, 363 * false otherwise. 364 * 365 * @see #close() 366 */ isClosed()367 public boolean isClosed() { 368 return mNativeObject == 0; 369 } 370 371 @Override describeContents()372 public int describeContents() { 373 return Parcelable.CONTENTS_FILE_DESCRIPTOR; 374 } 375 376 /** 377 * Flatten this object in to a Parcel. 378 * 379 * <p>Calling this method will throw an <code>IllegalStateException</code> if 380 * {@link #close()} has been previously called.</p> 381 * 382 * @param dest The Parcel in which the object should be written. 383 * @param flags Additional flags about how the object should be written. 384 * May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}. 385 */ 386 @Override writeToParcel(Parcel dest, int flags)387 public void writeToParcel(Parcel dest, int flags) { 388 if (isClosed()) { 389 throw new IllegalStateException("This HardwareBuffer has been closed and cannot be " 390 + "written to a parcel."); 391 } 392 nWriteHardwareBufferToParcel(mNativeObject, dest); 393 } 394 395 public static final @android.annotation.NonNull Parcelable.Creator<HardwareBuffer> CREATOR = 396 new Parcelable.Creator<HardwareBuffer>() { 397 public HardwareBuffer createFromParcel(Parcel in) { 398 long nativeObject = nReadHardwareBufferFromParcel(in); 399 if (nativeObject != 0) { 400 return new HardwareBuffer(nativeObject); 401 } 402 return null; 403 } 404 405 public HardwareBuffer[] newArray(int size) { 406 return new HardwareBuffer[size]; 407 } 408 }; 409 410 /** 411 * Validates whether a particular format is supported by HardwareBuffer. 412 * 413 * @param format The format to validate. 414 * 415 * @return True if <code>format</code> is a supported format. false otherwise. 416 * See {@link #create(int, int, int, int, long)}. 417 */ isSupportedFormat(@ormat int format)418 private static boolean isSupportedFormat(@Format int format) { 419 switch(format) { 420 case RGBA_8888: 421 case RGBA_FP16: 422 case RGBA_1010102: 423 case RGBX_8888: 424 case RGB_565: 425 case RGB_888: 426 case BLOB: 427 case YCBCR_420_888: 428 case D_16: 429 case D_24: 430 case DS_24UI8: 431 case D_FP32: 432 case DS_FP32UI8: 433 case S_UI8: 434 case YCBCR_P010: 435 return true; 436 } 437 return false; 438 } 439 nCreateHardwareBuffer(int width, int height, int format, int layers, long usage)440 private static native long nCreateHardwareBuffer(int width, int height, int format, int layers, 441 long usage); nCreateFromGraphicBuffer(GraphicBuffer graphicBuffer)442 private static native long nCreateFromGraphicBuffer(GraphicBuffer graphicBuffer); nGetNativeFinalizer()443 private static native long nGetNativeFinalizer(); nWriteHardwareBufferToParcel(long nativeObject, Parcel dest)444 private static native void nWriteHardwareBufferToParcel(long nativeObject, Parcel dest); nReadHardwareBufferFromParcel(Parcel in)445 private static native long nReadHardwareBufferFromParcel(Parcel in); 446 @FastNative nGetWidth(long nativeObject)447 private static native int nGetWidth(long nativeObject); 448 @FastNative nGetHeight(long nativeObject)449 private static native int nGetHeight(long nativeObject); 450 @FastNative nGetFormat(long nativeObject)451 private static native int nGetFormat(long nativeObject); 452 @FastNative nGetLayers(long nativeObject)453 private static native int nGetLayers(long nativeObject); 454 @FastNative nGetUsage(long nativeObject)455 private static native long nGetUsage(long nativeObject); nIsSupported(int width, int height, int format, int layers, long usage)456 private static native boolean nIsSupported(int width, int height, int format, int layers, 457 long usage); 458 @CriticalNative nEstimateSize(long nativeObject)459 private static native long nEstimateSize(long nativeObject); 460 } 461