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 #define LOG_TAG "HardwareBuffer" 18 19 #include "jni.h" 20 #include <nativehelper/JNIHelp.h> 21 22 #include "android_os_Parcel.h" 23 24 #include <android/hardware_buffer.h> 25 #include <android_runtime/android_graphics_GraphicBuffer.h> 26 #include <android_runtime/android_hardware_HardwareBuffer.h> 27 #include <android_runtime/AndroidRuntime.h> 28 #include <android_runtime/Log.h> 29 #include <private/android/AHardwareBufferHelpers.h> 30 31 #include <binder/Parcel.h> 32 33 #include <private/gui/ComposerService.h> 34 #include <ui/PixelFormat.h> 35 36 #include <hardware/gralloc1.h> 37 #include <grallocusage/GrallocUsageConversion.h> 38 39 #include "core_jni_helpers.h" 40 41 using namespace android; 42 43 // ---------------------------------------------------------------------------- 44 // Defines 45 // ---------------------------------------------------------------------------- 46 47 // Debug 48 static constexpr bool kDebugGraphicBuffer = false; 49 50 // ---------------------------------------------------------------------------- 51 // Types 52 // ---------------------------------------------------------------------------- 53 54 static struct { 55 jclass clazz; 56 jfieldID mNativeObject; 57 jmethodID ctor; 58 } gHardwareBufferClassInfo; 59 60 class GraphicBufferWrapper { 61 public: 62 explicit GraphicBufferWrapper(const sp<GraphicBuffer>& buffer) 63 : buffer(buffer) {} 64 65 sp<GraphicBuffer> buffer; 66 }; 67 68 // ---------------------------------------------------------------------------- 69 // HardwareBuffer lifecycle 70 // ---------------------------------------------------------------------------- 71 72 static jlong android_hardware_HardwareBuffer_create(JNIEnv* env, jobject clazz, 73 jint width, jint height, jint format, jint layers, jlong usage) { 74 75 // TODO: update createGraphicBuffer to take two 64-bit values. 76 int pixelFormat = android_hardware_HardwareBuffer_convertToPixelFormat(format); 77 if (pixelFormat == 0) { 78 if (kDebugGraphicBuffer) { 79 ALOGW("createGraphicBufferAlloc() invalid pixel format in HardwareBuffer.create()"); 80 } 81 return NULL; 82 } 83 84 uint64_t grallocUsage = AHardwareBuffer_convertToGrallocUsageBits(usage); 85 sp<GraphicBuffer> buffer = new GraphicBuffer(width, height, pixelFormat, layers, 86 grallocUsage, std::string("HardwareBuffer pid [") + std::to_string(getpid()) +"]"); 87 status_t error = buffer->initCheck(); 88 if (error < 0) { 89 if (kDebugGraphicBuffer) { 90 ALOGW("createGraphicBuffer() failed in HardwareBuffer.create()"); 91 } 92 return NULL; 93 } 94 95 GraphicBufferWrapper* wrapper = new GraphicBufferWrapper(buffer); 96 return reinterpret_cast<jlong>(wrapper); 97 } 98 99 static jlong android_hardware_HardwareBuffer_createFromGraphicBuffer(JNIEnv* env, jobject clazz, jobject graphicBuffer) { 100 sp<GraphicBuffer> buffer(android_graphics_GraphicBuffer_getNativeGraphicsBuffer(env, 101 graphicBuffer)); 102 GraphicBufferWrapper* wrapper = new GraphicBufferWrapper(buffer); 103 return reinterpret_cast<jlong>(wrapper); 104 } 105 106 static void destroyWrapper(GraphicBufferWrapper* wrapper) { 107 delete wrapper; 108 } 109 110 static jlong android_hardware_HardwareBuffer_getNativeFinalizer(JNIEnv* env, jobject clazz) { 111 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyWrapper)); 112 } 113 114 static jboolean android_hardware_HardwareBuffer_isSupported(JNIEnv* env, jobject clazz, 115 jint width, jint height, jint format, jint layers, jlong usage) { 116 117 AHardwareBuffer_Desc desc; 118 desc.width = width; 119 desc.height = height; 120 desc.format = format; 121 desc.layers = layers; 122 desc.usage = usage; 123 desc.stride = 0; 124 desc.rfu0 = 0; 125 desc.rfu1 = 0; 126 return AHardwareBuffer_isSupported(&desc); 127 } 128 129 //---------------------------------------------------------------------------- 130 // Accessors 131 // ---------------------------------------------------------------------------- 132 133 static inline GraphicBuffer* GraphicBufferWrapper_to_GraphicBuffer( 134 jlong nativeObject) { 135 return reinterpret_cast<GraphicBufferWrapper*>(nativeObject)->buffer.get(); 136 } 137 138 static jint android_hardware_HardwareBuffer_getWidth(JNIEnv* env, jobject clazz, 139 jlong nativeObject) { 140 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject); 141 return static_cast<jint>(buffer->getWidth()); 142 } 143 144 static jint android_hardware_HardwareBuffer_getHeight(JNIEnv* env, 145 jobject clazz, jlong nativeObject) { 146 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject); 147 return static_cast<jint>(buffer->getHeight()); 148 } 149 150 static jint android_hardware_HardwareBuffer_getFormat(JNIEnv* env, 151 jobject clazz, jlong nativeObject) { 152 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject); 153 return static_cast<jint>(android_hardware_HardwareBuffer_convertFromPixelFormat( 154 buffer->getPixelFormat())); 155 } 156 157 static jint android_hardware_HardwareBuffer_getLayers(JNIEnv* env, 158 jobject clazz, jlong nativeObject) { 159 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject); 160 return static_cast<jint>(buffer->getLayerCount()); 161 } 162 163 static jlong android_hardware_HardwareBuffer_getUsage(JNIEnv* env, 164 jobject clazz, jlong nativeObject) { 165 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject); 166 return AHardwareBuffer_convertFromGrallocUsageBits(buffer->getUsage()); 167 } 168 169 static jlong android_hardware_HardwareBuffer_estimateSize(jlong nativeObject) { 170 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject); 171 172 uint32_t bpp = bytesPerPixel(buffer->getPixelFormat()); 173 if (bpp == 0) { 174 // If the pixel format is not recognized, use 1 as default. 175 bpp = 1; 176 } 177 178 const uint32_t bufferStride = 179 buffer->getStride() > 0 ? buffer->getStride() : buffer->getWidth(); 180 return static_cast<jlong>(buffer->getHeight() * bufferStride * bpp); 181 } 182 183 // ---------------------------------------------------------------------------- 184 // Serialization 185 // ---------------------------------------------------------------------------- 186 187 static void android_hardware_HardwareBuffer_write(JNIEnv* env, jobject clazz, 188 jlong nativeObject, jobject dest) { 189 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject); 190 Parcel* parcel = parcelForJavaObject(env, dest); 191 if (parcel) { 192 parcel->write(*buffer); 193 } 194 } 195 196 static jlong android_hardware_HardwareBuffer_read(JNIEnv* env, jobject clazz, 197 jobject in) { 198 Parcel* parcel = parcelForJavaObject(env, in); 199 if (parcel) { 200 sp<GraphicBuffer> buffer = new GraphicBuffer(); 201 parcel->read(*buffer); 202 return reinterpret_cast<jlong>(new GraphicBufferWrapper(buffer)); 203 } 204 205 return NULL; 206 } 207 208 // ---------------------------------------------------------------------------- 209 // Public functions 210 // ---------------------------------------------------------------------------- 211 212 namespace android { 213 214 AHardwareBuffer* android_hardware_HardwareBuffer_getNativeHardwareBuffer( 215 JNIEnv* env, jobject hardwareBufferObj) { 216 if (env->IsInstanceOf(hardwareBufferObj, gHardwareBufferClassInfo.clazz)) { 217 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer( 218 env->GetLongField(hardwareBufferObj, gHardwareBufferClassInfo.mNativeObject)); 219 return AHardwareBuffer_from_GraphicBuffer(buffer); 220 221 } else { 222 return nullptr; 223 } 224 } 225 226 GraphicBuffer* android_hardware_HardwareBuffer_getNativeGraphicBuffer( 227 JNIEnv* env, jobject hardwareBufferObj) { 228 if (env->IsInstanceOf(hardwareBufferObj, gHardwareBufferClassInfo.clazz)) { 229 return GraphicBufferWrapper_to_GraphicBuffer( 230 env->GetLongField(hardwareBufferObj, gHardwareBufferClassInfo.mNativeObject)); 231 } else { 232 return nullptr; 233 } 234 } 235 236 jobject android_hardware_HardwareBuffer_createFromAHardwareBuffer( 237 JNIEnv* env, AHardwareBuffer* hardwareBuffer) { 238 GraphicBuffer* buffer = AHardwareBuffer_to_GraphicBuffer(hardwareBuffer); 239 GraphicBufferWrapper* wrapper = new GraphicBufferWrapper(buffer); 240 jobject hardwareBufferObj = env->NewObject(gHardwareBufferClassInfo.clazz, 241 gHardwareBufferClassInfo.ctor, reinterpret_cast<jlong>(wrapper)); 242 if (hardwareBufferObj == NULL) { 243 delete wrapper; 244 if (env->ExceptionCheck()) { 245 ALOGE("Could not create instance of HardwareBuffer from AHardwareBuffer."); 246 LOGE_EX(env); 247 env->ExceptionClear(); 248 } 249 return nullptr; 250 } 251 return hardwareBufferObj; 252 } 253 254 uint32_t android_hardware_HardwareBuffer_convertFromPixelFormat(uint32_t format) { 255 return AHardwareBuffer_convertFromPixelFormat(format); 256 } 257 258 uint32_t android_hardware_HardwareBuffer_convertToPixelFormat(uint32_t format) { 259 return AHardwareBuffer_convertToPixelFormat(format); 260 } 261 262 uint64_t android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t usage) { 263 return AHardwareBuffer_convertToGrallocUsageBits(usage); 264 } 265 266 } // namespace android 267 268 // ---------------------------------------------------------------------------- 269 // JNI Glue 270 // ---------------------------------------------------------------------------- 271 272 const char* const kClassPathName = "android/hardware/HardwareBuffer"; 273 274 // clang-format off 275 static const JNINativeMethod gMethods[] = { 276 { "nCreateHardwareBuffer", "(IIIIJ)J", 277 (void*) android_hardware_HardwareBuffer_create }, 278 { "nCreateFromGraphicBuffer", "(Landroid/graphics/GraphicBuffer;)J", 279 (void*) android_hardware_HardwareBuffer_createFromGraphicBuffer }, 280 { "nGetNativeFinalizer", "()J", 281 (void*) android_hardware_HardwareBuffer_getNativeFinalizer }, 282 { "nWriteHardwareBufferToParcel", "(JLandroid/os/Parcel;)V", 283 (void*) android_hardware_HardwareBuffer_write }, 284 { "nReadHardwareBufferFromParcel", "(Landroid/os/Parcel;)J", 285 (void*) android_hardware_HardwareBuffer_read }, 286 { "nIsSupported", "(IIIIJ)Z", 287 (void*) android_hardware_HardwareBuffer_isSupported }, 288 289 // --------------- @FastNative ---------------------- 290 { "nGetWidth", "(J)I", (void*) android_hardware_HardwareBuffer_getWidth }, 291 { "nGetHeight", "(J)I", (void*) android_hardware_HardwareBuffer_getHeight }, 292 { "nGetFormat", "(J)I", (void*) android_hardware_HardwareBuffer_getFormat }, 293 { "nGetLayers", "(J)I", (void*) android_hardware_HardwareBuffer_getLayers }, 294 { "nGetUsage", "(J)J", (void*) android_hardware_HardwareBuffer_getUsage }, 295 296 // --------------- @CriticalNative ---------------------- 297 { "nEstimateSize", "(J)J", (void*) android_hardware_HardwareBuffer_estimateSize }, 298 }; 299 // clang-format on 300 301 int register_android_hardware_HardwareBuffer(JNIEnv* env) { 302 int err = RegisterMethodsOrDie(env, kClassPathName, gMethods, 303 NELEM(gMethods)); 304 305 jclass clazz = FindClassOrDie(env, "android/hardware/HardwareBuffer"); 306 gHardwareBufferClassInfo.clazz = MakeGlobalRefOrDie(env, clazz); 307 gHardwareBufferClassInfo.mNativeObject = GetFieldIDOrDie(env, 308 gHardwareBufferClassInfo.clazz, "mNativeObject", "J"); 309 gHardwareBufferClassInfo.ctor = GetMethodIDOrDie(env, 310 gHardwareBufferClassInfo.clazz, "<init>", "(J)V"); 311 312 return err; 313 } 314