summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/hal/common/hal_types.h5
-rw-r--r--common/hal/common/session_data_defs.h4
-rw-r--r--common/hal/common/vendor_tag_defs.h17
-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.cc122
-rw-r--r--common/hal/google_camera_hal/camera_device_session.h10
-rw-r--r--common/hal/google_camera_hal/hal_utils.cc18
-rw-r--r--common/hal/google_camera_hal/hal_utils.h3
-rw-r--r--common/hal/hidl_service/hidl_camera_device_session.cc6
-rw-r--r--common/hal/hidl_service/hidl_camera_provider.cc2
-rw-r--r--common/hal/hidl_service/hidl_profiler.cc43
-rw-r--r--common/hal/hidl_service/hidl_utils.cc8
-rw-r--r--common/hal/hidl_service/hidl_utils.h5
-rw-r--r--common/hal/hidl_service/service.cc2
-rw-r--r--common/hal/hwl_interface/zoom_ratio_mapper_hwl.h3
-rw-r--r--common/hal/tests/camera_device_session_tests.cc89
-rw-r--r--common/hal/utils/result_dispatcher.cc11
-rw-r--r--common/hal/utils/stream_buffer_cache_manager.cc9
-rw-r--r--common/hal/utils/utils.cc43
-rw-r--r--common/hal/utils/utils.h5
-rw-r--r--common/hal/utils/zoom_ratio_mapper.cc16
-rw-r--r--common/hal/utils/zsl_buffer_manager.cc6
-rw-r--r--common/hal/utils/zsl_buffer_manager.h8
-rw-r--r--common/profiler/profiler.cc10
25 files changed, 451 insertions, 89 deletions
diff --git a/common/hal/common/hal_types.h b/common/hal/common/hal_types.h
index 3bd188f..4fe1da0 100644
--- a/common/hal/common/hal_types.h
+++ b/common/hal/common/hal_types.h
@@ -302,6 +302,11 @@ struct Point {
uint32_t y;
};
+struct PointI {
+ int32_t x;
+ int32_t y;
+};
+
struct PointF {
float x = 0.0f;
float y = 0.0f;
diff --git a/common/hal/common/session_data_defs.h b/common/hal/common/session_data_defs.h
index 9510583..0adcbc2 100644
--- a/common/hal/common/session_data_defs.h
+++ b/common/hal/common/session_data_defs.h
@@ -42,6 +42,10 @@ namespace google_camera_hal {
enum SessionDataKey : uint64_t {
kSessionDataKeyInvalidKey = 0,
// Add HAL-visible keys here (visible to GCH and HWL).
+ // A pointer to an int variable that indicates current
+ // Eis frame delay number.
+ // The pointer will be valid for the entire session.
+ kSessionDataKeyEisFrameDelayIntPtr,
kSessionDataKeyBeginHwlKeys = 0xFFFFFFFF
};
diff --git a/common/hal/common/vendor_tag_defs.h b/common/hal/common/vendor_tag_defs.h
index d87ab63..7d93d8d 100644
--- a/common/hal/common/vendor_tag_defs.h
+++ b/common/hal/common/vendor_tag_defs.h
@@ -51,6 +51,23 @@ enum VendorTagIds : uint32_t {
kEndMarker
};
+enum class SmoothyMode : uint32_t {
+ // Stablizes frames while moves with user's intentional motion, e.g. panning.
+ // Similar to normal EIS.
+ kSteadyCamMode = 0,
+
+ // Fixes the viewport as if videos are captured on a tripod.
+ kTripodMode,
+
+ // Tracks an object of interest and keeps it at frame's salient position, e.g.
+ // center.
+ kTrackingMode,
+
+ // Uses UW camera with a larger margin. In this way, we get a better video
+ // stabilization quality, while preserving a similar FoV as the main camera.
+ kSuperstabMode
+};
+
// Logical camera vendor tags
static const std::vector<VendorTag> kLogicalCameraVendorTags = {
// Logical camera default physical camera ID
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..7bdee63 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_);
@@ -637,6 +579,28 @@ status_t CameraDeviceSession::ConfigureStreams(
const StreamConfiguration& stream_config,
std::vector<HalStream>* hal_config) {
ATRACE_CALL();
+ bool set_realtime_thread = false;
+ int32_t schedule_policy;
+ struct sched_param schedule_param = {0};
+ if (utils::SupportRealtimeThread()) {
+ bool get_thread_schedule = false;
+ if (pthread_getschedparam(pthread_self(), &schedule_policy,
+ &schedule_param) == 0) {
+ get_thread_schedule = true;
+ } else {
+ ALOGE("%s: pthread_getschedparam fail", __FUNCTION__);
+ }
+
+ if (get_thread_schedule) {
+ status_t res = utils::SetRealtimeThread(pthread_self());
+ if (res != OK) {
+ ALOGE("%s: SetRealtimeThread fail", __FUNCTION__);
+ } else {
+ set_realtime_thread = true;
+ }
+ }
+ }
+
std::lock_guard<std::mutex> lock(session_lock_);
std::lock_guard lock_capture_session(capture_session_lock_);
@@ -687,6 +651,9 @@ status_t CameraDeviceSession::ConfigureStreams(
if (capture_session_ == nullptr) {
ALOGE("%s: Cannot find a capture session compatible with stream config",
__FUNCTION__);
+ if (set_realtime_thread) {
+ utils::UpdateThreadSched(pthread_self(), schedule_policy, &schedule_param);
+ }
return BAD_VALUE;
}
@@ -694,6 +661,10 @@ status_t CameraDeviceSession::ConfigureStreams(
stream_buffer_cache_manager_ = StreamBufferCacheManager::Create();
if (stream_buffer_cache_manager_ == nullptr) {
ALOGE("%s: Failed to create stream buffer cache manager.", __FUNCTION__);
+ if (set_realtime_thread) {
+ utils::UpdateThreadSched(pthread_self(), schedule_policy,
+ &schedule_param);
+ }
return UNKNOWN_ERROR;
}
@@ -702,6 +673,10 @@ status_t CameraDeviceSession::ConfigureStreams(
if (res != OK) {
ALOGE("%s: Failed to register streams into stream buffer cache manager.",
__FUNCTION__);
+ if (set_realtime_thread) {
+ utils::UpdateThreadSched(pthread_self(), schedule_policy,
+ &schedule_param);
+ }
return res;
}
}
@@ -722,6 +697,10 @@ status_t CameraDeviceSession::ConfigureStreams(
pending_requests_tracker_ = PendingRequestsTracker::Create(*hal_config);
if (pending_requests_tracker_ == nullptr) {
ALOGE("%s: Cannot create a pending request tracker.", __FUNCTION__);
+ if (set_realtime_thread) {
+ utils::UpdateThreadSched(pthread_self(), schedule_policy,
+ &schedule_param);
+ }
return UNKNOWN_ERROR;
}
@@ -740,6 +719,10 @@ status_t CameraDeviceSession::ConfigureStreams(
last_request_settings_ = nullptr;
last_timestamp_ns_for_trace_ = 0;
+ if (set_realtime_thread) {
+ utils::UpdateThreadSched(pthread_self(), schedule_policy, &schedule_param);
+ }
+
return OK;
}
@@ -1561,6 +1544,7 @@ status_t CameraDeviceSession::RegisterStreamsIntoCacheManagerLocked(
[this, stream_id](uint32_t num_buffer,
std::vector<StreamBuffer>* buffers,
StreamBufferRequestError* status) -> status_t {
+ ATRACE_NAME("StreamBufferRequestFunc");
if (buffers == nullptr) {
ALOGE("%s: buffers is nullptr.", __FUNCTION__);
return BAD_VALUE;
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/google_camera_hal/hal_utils.cc b/common/hal/google_camera_hal/hal_utils.cc
index fb4e969..22635da 100644
--- a/common/hal/google_camera_hal/hal_utils.cc
+++ b/common/hal/google_camera_hal/hal_utils.cc
@@ -210,6 +210,24 @@ bool IsBayerCamera(const HalCameraMetadata* characteristics) {
return false;
}
+bool IsFixedFocusCamera(const HalCameraMetadata* characteristics) {
+ if (characteristics == nullptr) {
+ ALOGE("%s: characteristics (%p) is nullptr", __FUNCTION__, characteristics);
+ return false;
+ }
+
+ camera_metadata_ro_entry entry = {};
+ status_t res =
+ characteristics->Get(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE, &entry);
+ if (res != OK || entry.count != 1) {
+ ALOGE("%s: Getting ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE failed: %s(%d)",
+ __FUNCTION__, strerror(-res), res);
+ return false;
+ }
+
+ return entry.data.f[0] == 0.0f;
+}
+
bool IsRequestHdrplusCompatible(const CaptureRequest& request,
int32_t preview_stream_id) {
if (request.settings == nullptr) {
diff --git a/common/hal/google_camera_hal/hal_utils.h b/common/hal/google_camera_hal/hal_utils.h
index ec73805..1ae517d 100644
--- a/common/hal/google_camera_hal/hal_utils.h
+++ b/common/hal/google_camera_hal/hal_utils.h
@@ -67,6 +67,9 @@ bool IsBayerCamera(const HalCameraMetadata* characteristics);
bool IsRequestHdrplusCompatible(const CaptureRequest& request,
int32_t preview_stream_id);
+// Return true if this is a fixed-focus camera.
+bool IsFixedFocusCamera(const HalCameraMetadata* characteristics);
+
// Return if HDR+ stream is supported
bool IsStreamHdrplusCompatible(const StreamConfiguration& stream_config,
const HalCameraMetadata* characteristics);
diff --git a/common/hal/hidl_service/hidl_camera_device_session.cc b/common/hal/hidl_service/hidl_camera_device_session.cc
index 0b3aede..0179805 100644
--- a/common/hal/hidl_service/hidl_camera_device_session.cc
+++ b/common/hal/hidl_service/hidl_camera_device_session.cc
@@ -15,10 +15,13 @@
*/
#define LOG_TAG "GCH_HidlCameraDeviceSession"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0
#include <log/log.h>
#include <cutils/properties.h>
+#include <cutils/trace.h>
+#include <malloc.h>
#include "hidl_camera_device_session.h"
#include "hidl_profiler.h"
@@ -68,6 +71,8 @@ std::unique_ptr<HidlCameraDeviceSession> HidlCameraDeviceSession::Create(
HidlCameraDeviceSession::~HidlCameraDeviceSession() {
close();
+ // camera's closing, so flush any unused malloc pages
+ mallopt(M_PURGE, 0);
}
void HidlCameraDeviceSession::ProcessCaptureResult(
@@ -661,7 +666,6 @@ Return<void> HidlCameraDeviceSession::close() {
auto profiler_item = hidl_profiler::OnCameraClose();
device_session_ = nullptr;
}
-
return Void();
}
diff --git a/common/hal/hidl_service/hidl_camera_provider.cc b/common/hal/hidl_service/hidl_camera_provider.cc
index a7ce5e2..7193a26 100644
--- a/common/hal/hidl_service/hidl_camera_provider.cc
+++ b/common/hal/hidl_service/hidl_camera_provider.cc
@@ -157,6 +157,8 @@ status_t HidlCameraProvider::Initialize() {
};
google_camera_provider_->SetCallback(&camera_provider_callback_);
+ // purge pending malloc pages after initialization
+ mallopt(M_PURGE, 0);
return OK;
}
diff --git a/common/hal/hidl_service/hidl_profiler.cc b/common/hal/hidl_service/hidl_profiler.cc
index ff7b563..3c7e40d 100644
--- a/common/hal/hidl_service/hidl_profiler.cc
+++ b/common/hal/hidl_service/hidl_profiler.cc
@@ -36,13 +36,17 @@ struct HidlProfiler {
mode |= google::camera_common::Profiler::SetPropFlag::kStopWatch;
}
profiler = google::camera_common::Profiler::Create(mode);
- profiler->SetDumpFilePrefix(
- "/data/vendor/camera/profiler/hidl_open_close_");
- profiler->Start("Overall", 0);
+ if (profiler != nullptr) {
+ profiler->SetDumpFilePrefix(
+ "/data/vendor/camera/profiler/hidl_open_close_");
+ profiler->Start("Overall", 0);
+ }
}
~HidlProfiler() {
- profiler->End("Overall", 0);
+ if (profiler != nullptr) {
+ profiler->End("Overall", 0);
+ }
}
std::shared_ptr<google::camera_common::Profiler> profiler = nullptr;
@@ -55,14 +59,15 @@ struct HidlProfiler {
std::unique_ptr<HidlProfiler> gHidlProfiler = nullptr;
void StartNewConnector() {
- if (gHidlProfiler != nullptr) {
+ if (gHidlProfiler != nullptr && gHidlProfiler->profiler != nullptr) {
gHidlProfiler->profiler->Start("<-- IDLE -->",
++gHidlProfiler->connector_counter);
}
}
void EndConnector() {
- if (gHidlProfiler != nullptr && gHidlProfiler->connector_counter != 0) {
+ if (gHidlProfiler != nullptr && gHidlProfiler->profiler != nullptr &&
+ gHidlProfiler->connector_counter != 0) {
gHidlProfiler->profiler->End("<-- IDLE -->",
gHidlProfiler->connector_counter);
}
@@ -76,6 +81,11 @@ void EndProfiler() {
std::unique_ptr<HidlProfilerItem> OnCameraOpen() {
gHidlProfiler = std::make_unique<HidlProfiler>();
+ if (gHidlProfiler == nullptr || gHidlProfiler->profiler == nullptr) {
+ ALOGE("%s: gHidlProfiler or profiler is nullptr.", __FUNCTION__);
+ return nullptr;
+ }
+
gHidlProfiler->has_camera_open = true;
gHidlProfiler->profiler->SetUseCase("Open Camera");
@@ -88,6 +98,11 @@ std::unique_ptr<HidlProfilerItem> OnCameraFlush() {
if (gHidlProfiler == nullptr) {
gHidlProfiler = std::make_unique<HidlProfiler>();
}
+
+ if (gHidlProfiler == nullptr || gHidlProfiler->profiler == nullptr) {
+ ALOGE("%s: gHidlProfiler or profiler is nullptr.", __FUNCTION__);
+ return nullptr;
+ }
gHidlProfiler->profiler->SetUseCase("Flush Camera");
return std::make_unique<HidlProfilerItem>(gHidlProfiler->profiler, "Flush",
StartNewConnector,
@@ -99,6 +114,12 @@ std::unique_ptr<HidlProfilerItem> OnCameraClose() {
if (gHidlProfiler == nullptr) {
gHidlProfiler = std::make_unique<HidlProfiler>();
}
+
+ if (gHidlProfiler == nullptr || gHidlProfiler->profiler == nullptr) {
+ ALOGE("%s: gHidlProfiler or profiler is nullptr.", __FUNCTION__);
+ return nullptr;
+ }
+
gHidlProfiler->profiler->SetUseCase("Close Camera");
return std::make_unique<HidlProfilerItem>(gHidlProfiler->profiler, "Close",
EndProfiler);
@@ -109,6 +130,12 @@ std::unique_ptr<HidlProfilerItem> OnCameraStreamConfigure() {
if (gHidlProfiler == nullptr) {
gHidlProfiler = std::make_unique<HidlProfiler>();
}
+
+ if (gHidlProfiler == nullptr || gHidlProfiler->profiler == nullptr) {
+ ALOGE("%s: gHidlProfiler or profiler is nullptr.", __FUNCTION__);
+ return nullptr;
+ }
+
if (!gHidlProfiler->has_camera_open) {
gHidlProfiler->profiler->SetUseCase("Reconfigure Stream");
}
@@ -120,7 +147,7 @@ std::unique_ptr<HidlProfilerItem> OnCameraStreamConfigure() {
void OnFirstFrameRequest() {
EndConnector();
- if (gHidlProfiler != nullptr) {
+ if (gHidlProfiler != nullptr && gHidlProfiler->profiler != nullptr) {
gHidlProfiler->profiler->Start(
"First frame", google::camera_common::Profiler::kInvalidRequestId);
gHidlProfiler->profiler->Start(
@@ -129,7 +156,7 @@ void OnFirstFrameRequest() {
}
void OnFirstFrameResult() {
- if (gHidlProfiler != nullptr) {
+ if (gHidlProfiler != nullptr && gHidlProfiler->profiler != nullptr) {
gHidlProfiler->profiler->End(
"First frame", google::camera_common::Profiler::kInvalidRequestId);
gHidlProfiler->profiler->End(
diff --git a/common/hal/hidl_service/hidl_utils.cc b/common/hal/hidl_service/hidl_utils.cc
index 291fa3f..7967a43 100644
--- a/common/hal/hidl_service/hidl_utils.cc
+++ b/common/hal/hidl_service/hidl_utils.cc
@@ -128,8 +128,16 @@ Status ConvertToHidlStatus(status_t hal_status) {
return Status::OK;
case BAD_VALUE:
return Status::ILLEGAL_ARGUMENT;
+ case -EBUSY:
+ return Status::CAMERA_IN_USE;
+ case -EUSERS:
+ return Status::MAX_CAMERAS_IN_USE;
+ case UNKNOWN_TRANSACTION:
+ return Status::METHOD_NOT_SUPPORTED;
case INVALID_OPERATION:
return Status::OPERATION_NOT_SUPPORTED;
+ case DEAD_OBJECT:
+ return Status::CAMERA_DISCONNECTED;
default:
return Status::INTERNAL_ERROR;
}
diff --git a/common/hal/hidl_service/hidl_utils.h b/common/hal/hidl_service/hidl_utils.h
index 2116eed..72b0ac0 100644
--- a/common/hal/hidl_service/hidl_utils.h
+++ b/common/hal/hidl_service/hidl_utils.h
@@ -92,6 +92,11 @@ status_t ConverToHidlNotifyMessage(
// Convert from HAL status_t to HIDL Status
// OK is converted to Status::OK.
// BAD_VALUE is converted to Status::ILLEGAL_ARGUMENT.
+// -EBUSY is converted to Status::CAMERA_IN_USE.
+// -EUSERS is converted to Status::MAX_CAMERAS_IN_USE.
+// UNKNOWN_TRANSACTION is converted to Status::METHOD_NOT_SUPPORTED.
+// INVALID_OPERATION is converted to Status::OPERATION_NOT_SUPPORTED.
+// DEAD_OBJECT is converted to Status::CAMERA_DISCONNECTED.
// All other errors are converted to Status::INTERNAL_ERROR.
Status ConvertToHidlStatus(status_t hal_status);
diff --git a/common/hal/hidl_service/service.cc b/common/hal/hidl_service/service.cc
index 48217b7..2b203d7 100644
--- a/common/hal/hidl_service/service.cc
+++ b/common/hal/hidl_service/service.cc
@@ -23,6 +23,7 @@
#include <android/hardware/camera/provider/2.6/ICameraProvider.h>
#include <binder/ProcessState.h>
#include <hidl/LegacySupport.h>
+#include <malloc.h>
using android::hardware::defaultLazyPassthroughServiceImplementation;
using android::hardware::defaultPassthroughServiceImplementation;
@@ -38,6 +39,7 @@ int main() {
ALOGI("Google camera provider service is starting.");
// The camera HAL may communicate to other vendor components via
// /dev/vndbinder
+ mallopt(M_DECAY_TIME, 1);
android::ProcessState::initWithDriver("/dev/vndbinder");
int res;
if (kLazyService) {
diff --git a/common/hal/hwl_interface/zoom_ratio_mapper_hwl.h b/common/hal/hwl_interface/zoom_ratio_mapper_hwl.h
index 019074c..edfc825 100644
--- a/common/hal/hwl_interface/zoom_ratio_mapper_hwl.h
+++ b/common/hal/hwl_interface/zoom_ratio_mapper_hwl.h
@@ -27,6 +27,9 @@ class ZoomRatioMapperHwl {
public:
virtual ~ZoomRatioMapperHwl() = default;
+ // Limit zoom ratio if concurrent mode is on
+ virtual void LimitZoomRatioIfConcurrent(float* zoom_ratio) const = 0;
+
// Apply zoom ratio to capture request
virtual void UpdateCaptureRequest(CaptureRequest* request) = 0;
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;
diff --git a/common/hal/utils/result_dispatcher.cc b/common/hal/utils/result_dispatcher.cc
index 2f89f4f..0dd6e33 100644
--- a/common/hal/utils/result_dispatcher.cc
+++ b/common/hal/utils/result_dispatcher.cc
@@ -23,6 +23,7 @@
#include <inttypes.h>
#include "result_dispatcher.h"
+#include "utils.h"
namespace android {
namespace google_camera_hal {
@@ -50,6 +51,16 @@ ResultDispatcher::ResultDispatcher(
ATRACE_CALL();
notify_callback_thread_ =
std::thread([this] { this->NotifyCallbackThreadLoop(); });
+
+ if (utils::SupportRealtimeThread()) {
+ status_t res =
+ utils::SetRealtimeThread(notify_callback_thread_.native_handle());
+ if (res != OK) {
+ ALOGE("%s: SetRealtimeThread fail", __FUNCTION__);
+ } else {
+ ALOGI("%s: SetRealtimeThread OK", __FUNCTION__);
+ }
+ }
}
ResultDispatcher::~ResultDispatcher() {
diff --git a/common/hal/utils/stream_buffer_cache_manager.cc b/common/hal/utils/stream_buffer_cache_manager.cc
index 2e25d1c..b801b9b 100644
--- a/common/hal/utils/stream_buffer_cache_manager.cc
+++ b/common/hal/utils/stream_buffer_cache_manager.cc
@@ -26,6 +26,7 @@
#include <chrono>
#include "stream_buffer_cache_manager.h"
+#include "utils.h"
using namespace std::chrono_literals;
@@ -43,6 +44,14 @@ static constexpr auto kBufferWaitingTimeOutSec = 400ms;
StreamBufferCacheManager::StreamBufferCacheManager() {
workload_thread_ = std::thread([this] { this->WorkloadThreadLoop(); });
+ if (utils::SupportRealtimeThread()) {
+ status_t res = utils::SetRealtimeThread(workload_thread_.native_handle());
+ if (res != OK) {
+ ALOGE("%s: SetRealtimeThread fail", __FUNCTION__);
+ } else {
+ ALOGI("%s: SetRealtimeThread OK", __FUNCTION__);
+ }
+ }
}
StreamBufferCacheManager::~StreamBufferCacheManager() {
diff --git a/common/hal/utils/utils.cc b/common/hal/utils/utils.cc
index 7c94454..24d0063 100644
--- a/common/hal/utils/utils.cc
+++ b/common/hal/utils/utils.cc
@@ -19,6 +19,7 @@
#include "utils.h"
+#include <cutils/properties.h>
#include <hardware/gralloc.h>
#include "vendor_tag_defs.h"
@@ -27,6 +28,8 @@ namespace android {
namespace google_camera_hal {
namespace utils {
+const std::string kRealtimeThreadSetProp = "persist.camera.realtimethread";
+
bool IsDepthStream(const Stream& stream) {
if (stream.stream_type == StreamType::kOutput &&
stream.data_space == HAL_DATASPACE_DEPTH &&
@@ -380,6 +383,46 @@ void ConvertZoomRatio(const float zoom_ratio,
}
}
+bool SupportRealtimeThread() {
+ static bool support_real_time = false;
+ static bool first_time = false;
+ if (first_time == false) {
+ first_time = true;
+ support_real_time = property_get_bool(kRealtimeThreadSetProp.c_str(), false);
+ }
+
+ return support_real_time;
+}
+
+status_t SetRealtimeThread(pthread_t thread) {
+ struct sched_param param = {
+ .sched_priority = 1,
+ };
+ int32_t res =
+ pthread_setschedparam(thread, SCHED_FIFO | SCHED_RESET_ON_FORK, &param);
+ if (res != 0) {
+ ALOGE("%s: Couldn't set SCHED_FIFO", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ return OK;
+}
+
+status_t UpdateThreadSched(pthread_t thread, int32_t policy,
+ struct sched_param* param) {
+ if (param == nullptr) {
+ ALOGE("%s: sched_param is nullptr", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ int32_t res = pthread_setschedparam(thread, policy, param);
+ if (res != 0) {
+ ALOGE("%s: Couldn't set schedparam", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ return OK;
+}
+
} // namespace utils
} // namespace google_camera_hal
} // namespace android
diff --git a/common/hal/utils/utils.h b/common/hal/utils/utils.h
index 27e0d8b..f79773f 100644
--- a/common/hal/utils/utils.h
+++ b/common/hal/utils/utils.h
@@ -66,6 +66,11 @@ bool IsHighSpeedModeFpsCompatible(StreamConfigurationMode mode,
bool IsSessionParameterCompatible(const HalCameraMetadata* old_session,
const HalCameraMetadata* new_session);
+bool SupportRealtimeThread();
+status_t SetRealtimeThread(pthread_t thread);
+status_t UpdateThreadSched(pthread_t thread, int32_t policy,
+ struct sched_param* param);
+
// Map the rectangle to the coordination of HAL.
void ConvertZoomRatio(float zoom_ratio, const Dimension& active_array_dimension,
int32_t* left, int32_t* top, int32_t* width,
diff --git a/common/hal/utils/zoom_ratio_mapper.cc b/common/hal/utils/zoom_ratio_mapper.cc
index a8f2f28..a05604e 100644
--- a/common/hal/utils/zoom_ratio_mapper.cc
+++ b/common/hal/utils/zoom_ratio_mapper.cc
@@ -16,9 +16,11 @@
#define LOG_TAG "GCH_ZoomRatioMapper"
-#include "zoom_ratio_mapper.h"
#include <log/log.h>
+#include <cmath>
+
#include "utils.h"
+#include "zoom_ratio_mapper.h"
namespace android {
namespace google_camera_hal {
@@ -140,6 +142,14 @@ void ZoomRatioMapper::ApplyZoomRatio(const Dimension& active_array_dimension,
zoom_ratio = zoom_ratio_range_.max;
}
+ if (zoom_ratio_mapper_hwl_ != nullptr && is_request) {
+ zoom_ratio_mapper_hwl_->LimitZoomRatioIfConcurrent(&zoom_ratio);
+ }
+
+ if (fabs(zoom_ratio - entry.data.f[0]) > 1e-9) {
+ metadata->Set(ANDROID_CONTROL_ZOOM_RATIO, &zoom_ratio, entry.count);
+ }
+
for (auto tag_id : kRectToConvert) {
UpdateRects(zoom_ratio, tag_id, active_array_dimension, is_request,
metadata);
@@ -272,12 +282,12 @@ void ZoomRatioMapper::UpdatePoints(const float zoom_ratio, const uint32_t tag_id
// x, y
const uint32_t kDataSizePerPoint = 2;
const uint32_t point_num = entry.count / kDataSizePerPoint;
- std::vector<Point> points(point_num);
+ std::vector<PointI> points(point_num);
uint32_t data_index = 0;
for (uint32_t i = 0; i < point_num; i++) {
data_index = i * kDataSizePerPoint;
- Point* transformed = &points.at(i);
+ PointI* transformed = &points.at(i);
transformed->x = entry.data.i32[data_index];
transformed->y = entry.data.i32[data_index + 1];
utils::RevertZoomRatio(zoom_ratio, active_array_dimension, true,
diff --git a/common/hal/utils/zsl_buffer_manager.cc b/common/hal/utils/zsl_buffer_manager.cc
index 9183476..22e1ee8 100644
--- a/common/hal/utils/zsl_buffer_manager.cc
+++ b/common/hal/utils/zsl_buffer_manager.cc
@@ -207,6 +207,12 @@ void ZslBufferManager::FreeUnusedBuffersLocked() {
ATRACE_CALL();
if (empty_zsl_buffers_.size() <= kMaxUnusedBuffers ||
buffers_.size() <= buffer_descriptor_.immediate_num_buffers) {
+ idle_buffer_frame_counter_ = 0;
+ return;
+ }
+
+ idle_buffer_frame_counter_++;
+ if (idle_buffer_frame_counter_ <= kMaxIdelBufferFrameCounter) {
return;
}
diff --git a/common/hal/utils/zsl_buffer_manager.h b/common/hal/utils/zsl_buffer_manager.h
index f43c8cc..5deb6eb 100644
--- a/common/hal/utils/zsl_buffer_manager.h
+++ b/common/hal/utils/zsl_buffer_manager.h
@@ -121,6 +121,11 @@ class ZslBufferManager {
// kMaxUnusedBuffers, it will try to free excessive buffers.
static const uint32_t kMaxUnusedBuffers = 2;
+ // Maximum number of frames with enough unused buffers. When the number of
+ // counter > kMaxIdelBufferFrameCounter, it will try to free excessive
+ // buffers.
+ static const uint32_t kMaxIdelBufferFrameCounter = 300;
+
const bool kMemoryProfilingEnabled;
// Remove the oldest metadata.
@@ -173,6 +178,9 @@ class ZslBufferManager {
// Store the buffer descriptor when call AllocateBuffers()
// Use it for AllocateExtraBuffers()
HalBufferDescriptor buffer_descriptor_;
+
+ // Count the number when there are enough unused buffers.
+ uint32_t idle_buffer_frame_counter_ = 0;
};
} // namespace google_camera_hal
diff --git a/common/profiler/profiler.cc b/common/profiler/profiler.cc
index 2583b51..37f37f8 100644
--- a/common/profiler/profiler.cc
+++ b/common/profiler/profiler.cc
@@ -35,7 +35,9 @@ namespace {
// Profiler implementatoin.
class ProfilerImpl : public Profiler {
public:
- ProfilerImpl(SetPropFlag setting) : setting_(setting){};
+ ProfilerImpl(SetPropFlag setting) : setting_(setting){
+ object_init_time_ = CurrentTime();
+ };
~ProfilerImpl();
// Setup the name of use case the profiler is running.
@@ -124,6 +126,9 @@ class ProfilerImpl : public Profiler {
}
}
+ // Timestamp of the class object initialized.
+ int64_t object_init_time_;
+
// Create folder if not exist.
void CreateFolder(std::string folder_path);
@@ -141,7 +146,8 @@ ProfilerImpl::~ProfilerImpl() {
PrintResult();
}
if (setting_ & SetPropFlag::kDumpBit) {
- DumpResult(dump_file_prefix_ + use_case_ + ".txt");
+ DumpResult(dump_file_prefix_ + use_case_ + "-TS" +
+ std::to_string(object_init_time_) + ".txt");
}
}