• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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