|  | // Copyright 2017 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "base/android/android_hardware_buffer_compat.h" | 
|  |  | 
|  | #include <dlfcn.h> | 
|  |  | 
|  | #include "base/android/android_info.h" | 
|  | #include "base/check.h" | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | AndroidHardwareBufferCompat::AndroidHardwareBufferCompat() { | 
|  | DCHECK(IsSupportAvailable()); | 
|  |  | 
|  | // TODO(crbug.com/40877384): If the Chromium build requires | 
|  | // __ANDROID_API__ >= 26 at some point in the future, we could directly use | 
|  | // the global functions instead of dynamic loading. However, since this would | 
|  | // be incompatible with pre-Oreo devices, this is unlikely to happen in the | 
|  | // foreseeable future, so just unconditionally use dynamic loading. | 
|  |  | 
|  | // cf. base/android/linker/linker_jni.cc | 
|  | void* main_dl_handle = dlopen(nullptr, RTLD_NOW); | 
|  |  | 
|  | *reinterpret_cast<void**>(&allocate_) = | 
|  | dlsym(main_dl_handle, "AHardwareBuffer_allocate"); | 
|  | DCHECK(allocate_); | 
|  |  | 
|  | *reinterpret_cast<void**>(&acquire_) = | 
|  | dlsym(main_dl_handle, "AHardwareBuffer_acquire"); | 
|  | DCHECK(acquire_); | 
|  |  | 
|  | *reinterpret_cast<void**>(&describe_) = | 
|  | dlsym(main_dl_handle, "AHardwareBuffer_describe"); | 
|  | DCHECK(describe_); | 
|  |  | 
|  | *reinterpret_cast<void**>(&lock_) = | 
|  | dlsym(main_dl_handle, "AHardwareBuffer_lock"); | 
|  | DCHECK(lock_); | 
|  |  | 
|  | *reinterpret_cast<void**>(&recv_handle_) = | 
|  | dlsym(main_dl_handle, "AHardwareBuffer_recvHandleFromUnixSocket"); | 
|  | DCHECK(recv_handle_); | 
|  |  | 
|  | *reinterpret_cast<void**>(&release_) = | 
|  | dlsym(main_dl_handle, "AHardwareBuffer_release"); | 
|  | DCHECK(release_); | 
|  |  | 
|  | *reinterpret_cast<void**>(&send_handle_) = | 
|  | dlsym(main_dl_handle, "AHardwareBuffer_sendHandleToUnixSocket"); | 
|  | DCHECK(send_handle_); | 
|  |  | 
|  | *reinterpret_cast<void**>(&unlock_) = | 
|  | dlsym(main_dl_handle, "AHardwareBuffer_unlock"); | 
|  | DCHECK(unlock_); | 
|  | } | 
|  |  | 
|  | // static | 
|  | bool AndroidHardwareBufferCompat::IsSupportAvailable() { | 
|  | return base::android::android_info::sdk_int() >= | 
|  | base::android::android_info::SDK_VERSION_OREO; | 
|  | } | 
|  |  | 
|  | // static | 
|  | AndroidHardwareBufferCompat& AndroidHardwareBufferCompat::GetInstance() { | 
|  | static AndroidHardwareBufferCompat compat; | 
|  | return compat; | 
|  | } | 
|  |  | 
|  | void AndroidHardwareBufferCompat::Allocate(const AHardwareBuffer_Desc* desc, | 
|  | AHardwareBuffer** out_buffer) { | 
|  | DCHECK(IsSupportAvailable()); | 
|  | allocate_(desc, out_buffer); | 
|  | } | 
|  |  | 
|  | void AndroidHardwareBufferCompat::Acquire(AHardwareBuffer* buffer) { | 
|  | DCHECK(IsSupportAvailable()); | 
|  |  | 
|  | // Null |buffer| is not allowed by |acquire_| and it fails somewhere in | 
|  | // android framework code. Hence adding a DCHECK here for documenting this | 
|  | // info and fail before. | 
|  | DCHECK(buffer); | 
|  | acquire_(buffer); | 
|  | } | 
|  |  | 
|  | void AndroidHardwareBufferCompat::Describe(const AHardwareBuffer* buffer, | 
|  | AHardwareBuffer_Desc* out_desc) { | 
|  | DCHECK(IsSupportAvailable()); | 
|  | describe_(buffer, out_desc); | 
|  | } | 
|  |  | 
|  | int AndroidHardwareBufferCompat::Lock(AHardwareBuffer* buffer, | 
|  | uint64_t usage, | 
|  | int32_t fence, | 
|  | const ARect* rect, | 
|  | void** out_virtual_address) { | 
|  | DCHECK(IsSupportAvailable()); | 
|  | return lock_(buffer, usage, fence, rect, out_virtual_address); | 
|  | } | 
|  |  | 
|  | int AndroidHardwareBufferCompat::RecvHandleFromUnixSocket( | 
|  | int socket_fd, | 
|  | AHardwareBuffer** out_buffer) { | 
|  | DCHECK(IsSupportAvailable()); | 
|  | return recv_handle_(socket_fd, out_buffer); | 
|  | } | 
|  |  | 
|  | void AndroidHardwareBufferCompat::Release(AHardwareBuffer* buffer) { | 
|  | DCHECK(IsSupportAvailable()); | 
|  | release_(buffer); | 
|  | } | 
|  |  | 
|  | int AndroidHardwareBufferCompat::SendHandleToUnixSocket( | 
|  | const AHardwareBuffer* buffer, | 
|  | int socket_fd) { | 
|  | DCHECK(IsSupportAvailable()); | 
|  | return send_handle_(buffer, socket_fd); | 
|  | } | 
|  |  | 
|  | int AndroidHardwareBufferCompat::Unlock(AHardwareBuffer* buffer, | 
|  | int32_t* fence) { | 
|  | DCHECK(IsSupportAvailable()); | 
|  | return unlock_(buffer, fence); | 
|  | } | 
|  |  | 
|  | }  // namespace base |