diff options
author | kocolin <kocolin@google.com> | 2020-07-30 11:20:51 +0800 |
---|---|---|
committer | kocolin <kocolin@google.com> | 2020-07-30 13:58:55 +0800 |
commit | 6c7dba227b49c0c2bb10a31a5c9a58d59c916724 (patch) | |
tree | a5bd8481497c7f8471460c32c87651a1a2051d2b | |
parent | 37162fb4ff78efd4e0417d0c1ebae503e73878ba (diff) | |
download | camera-6c7dba227b49c0c2bb10a31a5c9a58d59c916724.tar.gz |
Camera: Preload capture session library
Pre-load the library after the device boot up instead of load/release
it every time open/close camera to avoid long loading time when memory
pressure.
Bug: 161650087
Test: camera_checklist
Change-Id: Iace407e8486cfd485175a787b96c64b75e5c5f93
-rw-r--r-- | common/hal/google_camera_hal/camera_device.cc | 87 | ||||
-rw-r--r-- | common/hal/google_camera_hal/camera_device.h | 8 | ||||
-rw-r--r-- | common/hal/google_camera_hal/camera_device_session.cc | 80 | ||||
-rw-r--r-- | common/hal/google_camera_hal/camera_device_session.h | 10 | ||||
-rw-r--r-- | common/hal/tests/camera_device_session_tests.cc | 89 |
5 files changed, 199 insertions, 75 deletions
diff --git a/common/hal/google_camera_hal/camera_device.cc b/common/hal/google_camera_hal/camera_device.cc index f7d0535..e0c4e32 100644 --- a/common/hal/google_camera_hal/camera_device.cc +++ b/common/hal/google_camera_hal/camera_device.cc @@ -17,7 +17,9 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "GCH_CameraDevice" #define ATRACE_TAG ATRACE_TAG_CAMERA +#include <dlfcn.h> #include <log/log.h> +#include <sys/stat.h> #include <utils/Trace.h> #include "camera_device.h" @@ -26,6 +28,15 @@ namespace android { namespace google_camera_hal { +// HAL external capture session library path +#if defined(_LP64) +constexpr char kExternalCaptureSessionDir[] = + "/vendor/lib64/camera/capture_sessions/"; +#else // defined(_LP64) +constexpr char kExternalCaptureSessionDir[] = + "/vendor/lib/camera/capture_sessions/"; +#endif + std::unique_ptr<CameraDevice> CameraDevice::Create( std::unique_ptr<CameraDeviceHwl> camera_device_hwl, CameraBufferAllocatorHwl* camera_allocator_hwl) { @@ -63,6 +74,12 @@ status_t CameraDevice::Initialize( public_camera_id_ = camera_device_hwl->GetCameraId(); camera_device_hwl_ = std::move(camera_device_hwl); camera_allocator_hwl_ = camera_allocator_hwl; + status_t res = LoadExternalCaptureSession(); + if (res != OK) { + ALOGE("%s: Loading external capture sessions failed: %s(%d)", __FUNCTION__, + strerror(-res), res); + return res; + } return OK; } @@ -128,6 +145,7 @@ status_t CameraDevice::CreateCameraDeviceSession( } *session = CameraDeviceSession::Create(std::move(session_hwl), + external_session_factory_entries_, camera_allocator_hwl_); if (*session == nullptr) { ALOGE("%s: Creating a CameraDeviceSession failed: %s(%d)", __FUNCTION__, @@ -149,5 +167,74 @@ bool CameraDevice::IsStreamCombinationSupported( return supported; } +// Returns an array of regular files under dir_path. +static std::vector<std::string> FindLibraryPaths(const char* dir_path) { + std::vector<std::string> libs; + + errno = 0; + DIR* dir = opendir(dir_path); + if (!dir) { + ALOGD("%s: Unable to open directory %s (%s)", __FUNCTION__, dir_path, + strerror(errno)); + return libs; + } + + struct dirent* entry = nullptr; + while ((entry = readdir(dir)) != nullptr) { + std::string lib_path(dir_path); + lib_path += entry->d_name; + struct stat st; + if (stat(lib_path.c_str(), &st) == 0) { + if (S_ISREG(st.st_mode)) { + libs.push_back(lib_path); + } + } + } + + return libs; +} + +status_t CameraDevice::LoadExternalCaptureSession() { + ATRACE_CALL(); + + if (external_session_factory_entries_.size() > 0) { + ALOGI("%s: External capture session libraries already loaded; skip.", + __FUNCTION__); + return OK; + } + + for (const auto& lib_path : FindLibraryPaths(kExternalCaptureSessionDir)) { + ALOGI("%s: Loading %s", __FUNCTION__, lib_path.c_str()); + void* lib_handle = nullptr; + lib_handle = dlopen(lib_path.c_str(), RTLD_NOW); + if (lib_handle == nullptr) { + ALOGW("Failed loading %s.", lib_path.c_str()); + continue; + } + + GetCaptureSessionFactoryFunc external_session_factory_t = + reinterpret_cast<GetCaptureSessionFactoryFunc>( + dlsym(lib_handle, "GetCaptureSessionFactory")); + if (external_session_factory_t == nullptr) { + ALOGE("%s: dlsym failed (%s) when loading %s.", __FUNCTION__, + "GetCaptureSessionFactory", lib_path.c_str()); + dlclose(lib_handle); + lib_handle = nullptr; + continue; + } + + external_session_factory_entries_.push_back(external_session_factory_t); + external_capture_session_lib_handles_.push_back(lib_handle); + } + + return OK; +} + +CameraDevice::~CameraDevice() { + for (auto lib_handle : external_capture_session_lib_handles_) { + dlclose(lib_handle); + } +} + } // namespace google_camera_hal } // namespace android diff --git a/common/hal/google_camera_hal/camera_device.h b/common/hal/google_camera_hal/camera_device.h index 4cd1f6f..865bfa4 100644 --- a/common/hal/google_camera_hal/camera_device.h +++ b/common/hal/google_camera_hal/camera_device.h @@ -38,7 +38,7 @@ class CameraDevice { std::unique_ptr<CameraDeviceHwl> camera_device_hwl, CameraBufferAllocatorHwl* camera_allocator_hwl = nullptr); - virtual ~CameraDevice() = default; + virtual ~CameraDevice(); // Get the resource cost of this camera device. status_t GetResourceCost(CameraResourceCost* cost); @@ -79,6 +79,8 @@ class CameraDevice { // supported. stream_config contains the stream configurations. bool IsStreamCombinationSupported(const StreamConfiguration& stream_config); + status_t LoadExternalCaptureSession(); + protected: CameraDevice() = default; @@ -92,6 +94,10 @@ class CameraDevice { // hwl allocator CameraBufferAllocatorHwl* camera_allocator_hwl_ = nullptr; + + std::vector<GetCaptureSessionFactoryFunc> external_session_factory_entries_; + // Opened library handles that should be closed on destruction + std::vector<void*> external_capture_session_lib_handles_; }; } // namespace google_camera_hal diff --git a/common/hal/google_camera_hal/camera_device_session.cc b/common/hal/google_camera_hal/camera_device_session.cc index 421f233..89d79c7 100644 --- a/common/hal/google_camera_hal/camera_device_session.cc +++ b/common/hal/google_camera_hal/camera_device_session.cc @@ -19,10 +19,8 @@ #define ATRACE_TAG ATRACE_TAG_CAMERA #include "camera_device_session.h" -#include <dlfcn.h> #include <inttypes.h> #include <log/log.h> -#include <sys/stat.h> #include <utils/Trace.h> #include "basic_capture_session.h" @@ -53,17 +51,9 @@ std::vector<CaptureSessionEntryFuncs> BasicCaptureSession::IsStreamConfigurationSupported, .CreateSession = BasicCaptureSession::Create}}; -// HAL external capture session library path -#if defined(_LP64) -constexpr char kExternalCaptureSessionDir[] = - "/vendor/lib64/camera/capture_sessions/"; -#else // defined(_LP64) -constexpr char kExternalCaptureSessionDir[] = - "/vendor/lib/camera/capture_sessions/"; -#endif - std::unique_ptr<CameraDeviceSession> CameraDeviceSession::Create( std::unique_ptr<CameraDeviceSessionHwl> device_session_hwl, + std::vector<GetCaptureSessionFactoryFunc> external_session_factory_entries, CameraBufferAllocatorHwl* camera_allocator_hwl) { ATRACE_CALL(); if (device_session_hwl == nullptr) { @@ -83,7 +73,8 @@ std::unique_ptr<CameraDeviceSession> CameraDeviceSession::Create( } status_t res = - session->Initialize(std::move(device_session_hwl), camera_allocator_hwl); + session->Initialize(std::move(device_session_hwl), camera_allocator_hwl, + external_session_factory_entries); if (res != OK) { ALOGE("%s: Initializing CameraDeviceSession failed: %s (%d).", __FUNCTION__, strerror(-res), res); @@ -360,7 +351,8 @@ status_t CameraDeviceSession::InitializeBufferManagement( status_t CameraDeviceSession::Initialize( std::unique_ptr<CameraDeviceSessionHwl> device_session_hwl, - CameraBufferAllocatorHwl* camera_allocator_hwl) { + CameraBufferAllocatorHwl* camera_allocator_hwl, + std::vector<GetCaptureSessionFactoryFunc> external_session_factory_entries) { ATRACE_CALL(); if (device_session_hwl == nullptr) { ALOGE("%s: device_session_hwl cannot be nullptr.", __FUNCTION__); @@ -395,7 +387,7 @@ status_t CameraDeviceSession::Initialize( return res; } - res = LoadExternalCaptureSession(); + res = LoadExternalCaptureSession(external_session_factory_entries); if (res != OK) { ALOGE("%s: Loading external capture sessions failed: %s(%d)", __FUNCTION__, strerror(-res), res); @@ -467,34 +459,8 @@ void CameraDeviceSession::InitializeZoomRatioMapper( zoom_ratio_mapper_.Initialize(¶ms); } -// Returns an array of regular files under dir_path. -static std::vector<std::string> FindLibraryPaths(const char* dir_path) { - std::vector<std::string> libs; - - errno = 0; - DIR* dir = opendir(dir_path); - if (!dir) { - ALOGD("%s: Unable to open directory %s (%s)", __FUNCTION__, dir_path, - strerror(errno)); - return libs; - } - - struct dirent* entry = nullptr; - while ((entry = readdir(dir)) != nullptr) { - std::string lib_path(dir_path); - lib_path += entry->d_name; - struct stat st; - if (stat(lib_path.c_str(), &st) == 0) { - if (S_ISREG(st.st_mode)) { - libs.push_back(lib_path); - } - } - } - - return libs; -} - -status_t CameraDeviceSession::LoadExternalCaptureSession() { +status_t CameraDeviceSession::LoadExternalCaptureSession( + std::vector<GetCaptureSessionFactoryFunc> external_session_factory_entries) { ATRACE_CALL(); if (external_capture_session_entries_.size() > 0) { @@ -503,36 +469,16 @@ status_t CameraDeviceSession::LoadExternalCaptureSession() { return OK; } - for (const auto& lib_path : FindLibraryPaths(kExternalCaptureSessionDir)) { - ALOGI("%s: Loading %s", __FUNCTION__, lib_path.c_str()); - void* lib_handle = nullptr; - lib_handle = dlopen(lib_path.c_str(), RTLD_NOW); - if (lib_handle == nullptr) { - ALOGW("Failed loading %s.", lib_path.c_str()); - continue; - } - - GetCaptureSessionFactoryFunc external_session_factory_t = - reinterpret_cast<GetCaptureSessionFactoryFunc>( - dlsym(lib_handle, "GetCaptureSessionFactory")); - if (external_session_factory_t == nullptr) { - ALOGE("%s: dlsym failed (%s) when loading %s.", __FUNCTION__, - "GetCaptureSessionFactory", lib_path.c_str()); - dlclose(lib_handle); - lib_handle = nullptr; - continue; - } - + for (const auto& external_session_factory_t : + external_session_factory_entries) { ExternalCaptureSessionFactory* external_session = external_session_factory_t(); if (!external_session) { - ALOGE("%s: External session from (%s) may be incomplete", __FUNCTION__, - lib_path.c_str()); + ALOGE("%s: External session may be incomplete", __FUNCTION__); continue; } external_capture_session_entries_.push_back(external_session); - external_capture_session_lib_handles_.push_back(lib_handle); } return OK; @@ -548,10 +494,6 @@ CameraDeviceSession::~CameraDeviceSession() { delete external_session; } - for (auto lib_handle : external_capture_session_lib_handles_) { - dlclose(lib_handle); - } - if (buffer_mapper_v4_ != nullptr) { FreeImportedBufferHandles<android::hardware::graphics::mapper::V4_0::IMapper>( buffer_mapper_v4_); diff --git a/common/hal/google_camera_hal/camera_device_session.h b/common/hal/google_camera_hal/camera_device_session.h index aacc4d0..d373c40 100644 --- a/common/hal/google_camera_hal/camera_device_session.h +++ b/common/hal/google_camera_hal/camera_device_session.h @@ -97,6 +97,7 @@ class CameraDeviceSession { // lifetime of CameraDeviceSession static std::unique_ptr<CameraDeviceSession> Create( std::unique_ptr<CameraDeviceSessionHwl> device_session_hwl, + std::vector<GetCaptureSessionFactoryFunc> external_session_factory_entries, CameraBufferAllocatorHwl* camera_allocator_hwl = nullptr); virtual ~CameraDeviceSession(); @@ -154,8 +155,10 @@ class CameraDeviceSession { } }; - status_t Initialize(std::unique_ptr<CameraDeviceSessionHwl> device_session_hwl, - CameraBufferAllocatorHwl* camera_allocator_hwl); + status_t Initialize( + std::unique_ptr<CameraDeviceSessionHwl> device_session_hwl, + CameraBufferAllocatorHwl* camera_allocator_hwl, + std::vector<GetCaptureSessionFactoryFunc> external_session_factory_entries); // Initialize the latest available gralloc buffer mapper. status_t InitializeBufferMapper(); @@ -288,7 +291,8 @@ class CameraDeviceSession { void UnregisterThermalCallback(); // Load HAL external capture session libraries. - status_t LoadExternalCaptureSession(); + status_t LoadExternalCaptureSession( + std::vector<GetCaptureSessionFactoryFunc> external_session_factory_entries); void InitializeZoomRatioMapper(HalCameraMetadata* characteristics); diff --git a/common/hal/tests/camera_device_session_tests.cc b/common/hal/tests/camera_device_session_tests.cc index 926f4ad..823ece7 100644 --- a/common/hal/tests/camera_device_session_tests.cc +++ b/common/hal/tests/camera_device_session_tests.cc @@ -15,7 +15,9 @@ */ #define LOG_TAG "CameraDeviceSessionTests" +#include <dlfcn.h> #include <log/log.h> +#include <sys/stat.h> #include <gtest/gtest.h> @@ -33,9 +35,90 @@ using ::testing::_; using ::testing::AtLeast; using ::testing::Return; +// HAL external capture session library path +#if defined(_LP64) +constexpr char kExternalCaptureSessionDir[] = + "/vendor/lib64/camera/capture_sessions/"; +#else // defined(_LP64) +constexpr char kExternalCaptureSessionDir[] = + "/vendor/lib/camera/capture_sessions/"; +#endif + +// Returns an array of regular files under dir_path. +static std::vector<std::string> FindLibraryPaths(const char* dir_path) { + std::vector<std::string> libs; + + errno = 0; + DIR* dir = opendir(dir_path); + if (!dir) { + ALOGD("%s: Unable to open directory %s (%s)", __FUNCTION__, dir_path, + strerror(errno)); + return libs; + } + + struct dirent* entry = nullptr; + while ((entry = readdir(dir)) != nullptr) { + std::string lib_path(dir_path); + lib_path += entry->d_name; + struct stat st; + if (stat(lib_path.c_str(), &st) == 0) { + if (S_ISREG(st.st_mode)) { + libs.push_back(lib_path); + } + } + } + + return libs; +} + class CameraDeviceSessionTests : public ::testing::Test { protected: static constexpr uint32_t kCaptureTimeoutMs = 3000; + std::vector<GetCaptureSessionFactoryFunc> external_session_factory_entries_; + std::vector<void*> external_capture_session_lib_handles_; + + CameraDeviceSessionTests() { + LoadExternalCaptureSession(); + } + + ~CameraDeviceSessionTests() { + for (auto lib_handle : external_capture_session_lib_handles_) { + dlclose(lib_handle); + } + } + + status_t LoadExternalCaptureSession() { + if (external_session_factory_entries_.size() > 0) { + ALOGI("%s: External capture session libraries already loaded; skip.", + __FUNCTION__); + return OK; + } + + for (const auto& lib_path : FindLibraryPaths(kExternalCaptureSessionDir)) { + ALOGI("%s: Loading %s", __FUNCTION__, lib_path.c_str()); + void* lib_handle = nullptr; + lib_handle = dlopen(lib_path.c_str(), RTLD_NOW); + if (lib_handle == nullptr) { + ALOGW("Failed loading %s.", lib_path.c_str()); + continue; + } + + GetCaptureSessionFactoryFunc external_session_factory_t = + reinterpret_cast<GetCaptureSessionFactoryFunc>( + dlsym(lib_handle, "GetCaptureSessionFactory")); + if (external_session_factory_t == nullptr) { + ALOGE("%s: dlsym failed (%s) when loading %s.", __FUNCTION__, + "GetCaptureSessionFactory", lib_path.c_str()); + dlclose(lib_handle); + lib_handle = nullptr; + continue; + } + + external_session_factory_entries_.push_back(external_session_factory_t); + } + + return OK; + } void CreateMockSessionHwlAndCheck( std::unique_ptr<MockDeviceSessionHwl>* session_hwl) { @@ -49,7 +132,8 @@ class CameraDeviceSessionTests : public ::testing::Test { std::unique_ptr<CameraDeviceSession>* session) { ASSERT_NE(session, nullptr); - *session = CameraDeviceSession::Create(std::move(session_hwl)); + *session = CameraDeviceSession::Create(std::move(session_hwl), + external_session_factory_entries_); ASSERT_NE(*session, nullptr); } @@ -238,7 +322,8 @@ class CameraDeviceSessionTests : public ::testing::Test { }; TEST_F(CameraDeviceSessionTests, Create) { - auto session = CameraDeviceSession::Create(/*device_session_hwl=*/nullptr); + auto session = CameraDeviceSession::Create(/*device_session_hwl=*/nullptr, + external_session_factory_entries_); EXPECT_EQ(session, nullptr); uint32_t num_sessions = 5; |