summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkocolin <kocolin@google.com>2020-07-30 11:20:51 +0800
committerkocolin <kocolin@google.com>2020-07-30 13:58:55 +0800
commit6c7dba227b49c0c2bb10a31a5c9a58d59c916724 (patch)
treea5bd8481497c7f8471460c32c87651a1a2051d2b
parent37162fb4ff78efd4e0417d0c1ebae503e73878ba (diff)
downloadcamera-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.cc87
-rw-r--r--common/hal/google_camera_hal/camera_device.h8
-rw-r--r--common/hal/google_camera_hal/camera_device_session.cc80
-rw-r--r--common/hal/google_camera_hal/camera_device_session.h10
-rw-r--r--common/hal/tests/camera_device_session_tests.cc89
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(&params);
}
-// 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;