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.NonNull; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 24 import dalvik.annotation.optimization.FastNative; 25 import dalvik.system.CloseGuard; 26 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 30 import libcore.util.NativeAllocationRegistry; 31 32 /** 33 * HardwareBuffer wraps a native <code>AHardwareBuffer</code> object, which is a low-level object 34 * representing a memory buffer accessible by various hardware units. HardwareBuffer allows sharing 35 * buffers across different application processes. In particular, HardwareBuffers may be mappable 36 * to memory accessibly to various hardware systems, such as the GPU, a sensor or context hub, or 37 * other auxiliary processing units. 38 * 39 * For more information, see the NDK documentation for <code>AHardwareBuffer</code>. 40 */ 41 public final class HardwareBuffer implements Parcelable, AutoCloseable { 42 /** @hide */ 43 @Retention(RetentionPolicy.SOURCE) 44 @IntDef({RGBA_8888, RGBA_FP16, RGBA_1010102, RGBX_8888, RGB_888, RGB_565, BLOB}) 45 public @interface Format { 46 } 47 48 /** Format: 8 bits each red, green, blue, alpha */ 49 public static final int RGBA_8888 = 1; 50 /** Format: 8 bits each red, green, blue, alpha, alpha is always 0xFF */ 51 public static final int RGBX_8888 = 2; 52 /** Format: 8 bits each red, green, blue, no alpha */ 53 public static final int RGB_888 = 3; 54 /** Format: 5 bits each red and blue, 6 bits green, no alpha */ 55 public static final int RGB_565 = 4; 56 /** Format: 16 bits each red, green, blue, alpha */ 57 public static final int RGBA_FP16 = 0x16; 58 /** Format: 10 bits each red, green, blue, 2 bits alpha */ 59 public static final int RGBA_1010102 = 0x2b; 60 /** Format: opaque format used for raw data transfer; must have a height of 1 */ 61 public static final int BLOB = 0x21; 62 63 // Note: do not rename, this field is used by native code 64 private long mNativeObject; 65 66 // Invoked on destruction 67 private Runnable mCleaner; 68 69 private final CloseGuard mCloseGuard = CloseGuard.get(); 70 71 /** @hide */ 72 @Retention(RetentionPolicy.SOURCE) 73 @IntDef(flag = true, value = {USAGE_CPU_READ_RARELY, USAGE_CPU_READ_OFTEN, 74 USAGE_CPU_WRITE_RARELY, USAGE_CPU_WRITE_OFTEN, USAGE_GPU_SAMPLED_IMAGE, 75 USAGE_GPU_COLOR_OUTPUT, USAGE_PROTECTED_CONTENT, USAGE_VIDEO_ENCODE, 76 USAGE_GPU_DATA_BUFFER, USAGE_SENSOR_DIRECT_DATA}) 77 public @interface Usage {}; 78 79 /** Usage: The buffer will sometimes be read by the CPU */ 80 public static final long USAGE_CPU_READ_RARELY = 2; 81 /** Usage: The buffer will often be read by the CPU */ 82 public static final long USAGE_CPU_READ_OFTEN = 3; 83 84 /** Usage: The buffer will sometimes be written to by the CPU */ 85 public static final long USAGE_CPU_WRITE_RARELY = 2 << 4; 86 /** Usage: The buffer will often be written to by the CPU */ 87 public static final long USAGE_CPU_WRITE_OFTEN = 3 << 4; 88 89 /** Usage: The buffer will be read from by the GPU */ 90 public static final long USAGE_GPU_SAMPLED_IMAGE = 1 << 8; 91 /** Usage: The buffer will be written to by the GPU */ 92 public static final long USAGE_GPU_COLOR_OUTPUT = 1 << 9; 93 /** Usage: The buffer must not be used outside of a protected hardware path */ 94 public static final long USAGE_PROTECTED_CONTENT = 1 << 14; 95 /** Usage: The buffer will be read by a hardware video encoder */ 96 public static final long USAGE_VIDEO_ENCODE = 1 << 16; 97 /** Usage: The buffer will be used for sensor direct data */ 98 public static final long USAGE_SENSOR_DIRECT_DATA = 1 << 23; 99 /** Usage: The buffer will be used as a shader storage or uniform buffer object */ 100 public static final long USAGE_GPU_DATA_BUFFER = 1 << 24; 101 102 // The approximate size of a native AHardwareBuffer object. 103 private static final long NATIVE_HARDWARE_BUFFER_SIZE = 232; 104 /** 105 * Creates a new <code>HardwareBuffer</code> instance. 106 * 107 * <p>Calling this method will throw an <code>IllegalStateException</code> if 108 * format is not a supported Format type.</p> 109 * 110 * @param width The width in pixels of the buffer 111 * @param height The height in pixels of the buffer 112 * @param format The format of each pixel, one of {@link #RGBA_8888}, {@link #RGBA_FP16}, 113 * {@link #RGBX_8888}, {@link #RGB_565}, {@link #RGB_888}, {@link #RGBA_1010102}, {@link #BLOB} 114 * @param layers The number of layers in the buffer 115 * @param usage Flags describing how the buffer will be used, one of 116 * {@link #USAGE_CPU_READ_RARELY}, {@link #USAGE_CPU_READ_OFTEN}, 117 * {@link #USAGE_CPU_WRITE_RARELY}, {@link #USAGE_CPU_WRITE_OFTEN}, 118 * {@link #USAGE_GPU_SAMPLED_IMAGE}, {@link #USAGE_GPU_COLOR_OUTPUT}, 119 * {@link #USAGE_GPU_DATA_BUFFER}, {@link #USAGE_PROTECTED_CONTENT}, 120 * {@link #USAGE_SENSOR_DIRECT_DATA}, {@link #USAGE_VIDEO_ENCODE} 121 * @return A <code>HardwareBuffer</code> instance if successful, or throws an 122 * IllegalArgumentException if the dimensions passed are invalid (either zero, negative, or 123 * too large to allocate), if the format is not supported, if the requested number of layers 124 * is less than one or not supported, or if the passed usage flags are not a supported set. 125 */ 126 @NonNull create(int width, int height, @Format int format, int layers, @Usage long usage)127 public static HardwareBuffer create(int width, int height, @Format int format, int layers, 128 @Usage long usage) { 129 if (!HardwareBuffer.isSupportedFormat(format)) { 130 throw new IllegalArgumentException("Invalid pixel format " + format); 131 } 132 if (width <= 0) { 133 throw new IllegalArgumentException("Invalid width " + width); 134 } 135 if (height <= 0) { 136 throw new IllegalArgumentException("Invalid height " + height); 137 } 138 if (layers <= 0) { 139 throw new IllegalArgumentException("Invalid layer count " + layers); 140 } 141 if (format == BLOB && height != 1) { 142 throw new IllegalArgumentException("Height must be 1 when using the BLOB format"); 143 } 144 long nativeObject = nCreateHardwareBuffer(width, height, format, layers, usage); 145 if (nativeObject == 0) { 146 throw new IllegalArgumentException("Unable to create a HardwareBuffer, either the " + 147 "dimensions passed were too large, too many image layers were requested, " + 148 "or an invalid set of usage flags was passed"); 149 } 150 return new HardwareBuffer(nativeObject); 151 } 152 153 /** 154 * Private use only. See {@link #create(int, int, int, int, long)}. May also be 155 * called from JNI using an already allocated native <code>HardwareBuffer</code>. 156 */ HardwareBuffer(long nativeObject)157 private HardwareBuffer(long nativeObject) { 158 mNativeObject = nativeObject; 159 160 ClassLoader loader = HardwareBuffer.class.getClassLoader(); 161 NativeAllocationRegistry registry = new NativeAllocationRegistry( 162 loader, nGetNativeFinalizer(), NATIVE_HARDWARE_BUFFER_SIZE); 163 mCleaner = registry.registerNativeAllocation(this, mNativeObject); 164 mCloseGuard.open("close"); 165 } 166 167 @Override finalize()168 protected void finalize() throws Throwable { 169 try { 170 mCloseGuard.warnIfOpen(); 171 close(); 172 } finally { 173 super.finalize(); 174 } 175 } 176 177 /** 178 * Returns the width of this buffer in pixels. 179 */ getWidth()180 public int getWidth() { 181 if (isClosed()) { 182 throw new IllegalStateException("This HardwareBuffer has been closed and its width " 183 + "cannot be obtained."); 184 } 185 return nGetWidth(mNativeObject); 186 } 187 188 /** 189 * Returns the height of this buffer in pixels. 190 */ getHeight()191 public int getHeight() { 192 if (isClosed()) { 193 throw new IllegalStateException("This HardwareBuffer has been closed and its height " 194 + "cannot be obtained."); 195 } 196 return nGetHeight(mNativeObject); 197 } 198 199 /** 200 * Returns the format of this buffer, one of {@link #RGBA_8888}, {@link #RGBA_FP16}, 201 * {@link #RGBX_8888}, {@link #RGB_565}, {@link #RGB_888}, {@link #RGBA_1010102}, {@link #BLOB}. 202 */ 203 @Format getFormat()204 public int getFormat() { 205 if (isClosed()) { 206 throw new IllegalStateException("This HardwareBuffer has been closed and its format " 207 + "cannot be obtained."); 208 } 209 return nGetFormat(mNativeObject); 210 } 211 212 /** 213 * Returns the number of layers in this buffer. 214 */ getLayers()215 public int getLayers() { 216 if (isClosed()) { 217 throw new IllegalStateException("This HardwareBuffer has been closed and its layer " 218 + "count cannot be obtained."); 219 } 220 return nGetLayers(mNativeObject); 221 } 222 223 /** 224 * Returns the usage flags of the usage hints set on this buffer. 225 */ getUsage()226 public long getUsage() { 227 if (isClosed()) { 228 throw new IllegalStateException("This HardwareBuffer has been closed and its usage " 229 + "cannot be obtained."); 230 } 231 return nGetUsage(mNativeObject); 232 } 233 234 /** @removed replaced by {@link #close()} */ 235 @Deprecated destroy()236 public void destroy() { 237 close(); 238 } 239 240 /** @removed replaced by {@link #isClosed()} */ 241 @Deprecated isDestroyed()242 public boolean isDestroyed() { 243 return isClosed(); 244 } 245 246 /** 247 * Destroys this buffer immediately. Calling this method frees up any 248 * underlying native resources. After calling this method, this buffer 249 * must not be used in any way. 250 * 251 * @see #isClosed() 252 */ 253 @Override close()254 public void close() { 255 if (!isClosed()) { 256 mCloseGuard.close(); 257 mNativeObject = 0; 258 mCleaner.run(); 259 mCleaner = null; 260 } 261 } 262 263 /** 264 * Indicates whether this buffer has been closed. A closed buffer cannot 265 * be used in any way: the buffer cannot be written to a parcel, etc. 266 * 267 * @return True if this <code>HardwareBuffer</code> is in a closed state, 268 * false otherwise. 269 * 270 * @see #close() 271 */ isClosed()272 public boolean isClosed() { 273 return mNativeObject == 0; 274 } 275 276 @Override describeContents()277 public int describeContents() { 278 return Parcelable.CONTENTS_FILE_DESCRIPTOR; 279 } 280 281 /** 282 * Flatten this object in to a Parcel. 283 * 284 * <p>Calling this method will throw an <code>IllegalStateException</code> if 285 * {@link #close()} has been previously called.</p> 286 * 287 * @param dest The Parcel in which the object should be written. 288 * @param flags Additional flags about how the object should be written. 289 * May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}. 290 */ 291 @Override writeToParcel(Parcel dest, int flags)292 public void writeToParcel(Parcel dest, int flags) { 293 if (isClosed()) { 294 throw new IllegalStateException("This HardwareBuffer has been closed and cannot be " 295 + "written to a parcel."); 296 } 297 nWriteHardwareBufferToParcel(mNativeObject, dest); 298 } 299 300 public static final Parcelable.Creator<HardwareBuffer> CREATOR = 301 new Parcelable.Creator<HardwareBuffer>() { 302 public HardwareBuffer createFromParcel(Parcel in) { 303 long nativeObject = nReadHardwareBufferFromParcel(in); 304 if (nativeObject != 0) { 305 return new HardwareBuffer(nativeObject); 306 } 307 return null; 308 } 309 310 public HardwareBuffer[] newArray(int size) { 311 return new HardwareBuffer[size]; 312 } 313 }; 314 315 /** 316 * Validates whether a particular format is supported by HardwareBuffer. 317 * 318 * @param format The format to validate. 319 * 320 * @return True if <code>format</code> is a supported format. false otherwise. 321 * See {@link #create(int, int, int, int, long)}. 322 */ isSupportedFormat(@ormat int format)323 private static boolean isSupportedFormat(@Format int format) { 324 switch(format) { 325 case RGBA_8888: 326 case RGBA_FP16: 327 case RGBA_1010102: 328 case RGBX_8888: 329 case RGB_565: 330 case RGB_888: 331 case BLOB: 332 return true; 333 } 334 return false; 335 } 336 nCreateHardwareBuffer(int width, int height, int format, int layers, long usage)337 private static native long nCreateHardwareBuffer(int width, int height, int format, int layers, 338 long usage); nGetNativeFinalizer()339 private static native long nGetNativeFinalizer(); nWriteHardwareBufferToParcel(long nativeObject, Parcel dest)340 private static native void nWriteHardwareBufferToParcel(long nativeObject, Parcel dest); nReadHardwareBufferFromParcel(Parcel in)341 private static native long nReadHardwareBufferFromParcel(Parcel in); 342 @FastNative nGetWidth(long nativeObject)343 private static native int nGetWidth(long nativeObject); 344 @FastNative nGetHeight(long nativeObject)345 private static native int nGetHeight(long nativeObject); 346 @FastNative nGetFormat(long nativeObject)347 private static native int nGetFormat(long nativeObject); 348 @FastNative nGetLayers(long nativeObject)349 private static native int nGetLayers(long nativeObject); 350 @FastNative nGetUsage(long nativeObject)351 private static native long nGetUsage(long nativeObject); 352 } 353