1 /*
2 * Copyright (C) 2019 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_NDEBUG 0
18 #define LOG_TAG "GCH_CameraDevice"
19 #define ATRACE_TAG ATRACE_TAG_CAMERA
20 #include <dlfcn.h>
21 #include <log/log.h>
22 #include <sys/stat.h>
23 #include <utils/Trace.h>
24
25 #include "camera_device.h"
26 #include "vendor_tags.h"
27
28 namespace android {
29 namespace google_camera_hal {
30
31 // HAL external capture session library path
32 #if defined(_LP64)
33 constexpr char kExternalCaptureSessionDir[] =
34 "/vendor/lib64/camera/capture_sessions/";
35 #else // defined(_LP64)
36 constexpr char kExternalCaptureSessionDir[] =
37 "/vendor/lib/camera/capture_sessions/";
38 #endif
39
Create(std::unique_ptr<CameraDeviceHwl> camera_device_hwl,CameraBufferAllocatorHwl * camera_allocator_hwl)40 std::unique_ptr<CameraDevice> CameraDevice::Create(
41 std::unique_ptr<CameraDeviceHwl> camera_device_hwl,
42 CameraBufferAllocatorHwl* camera_allocator_hwl) {
43 ATRACE_CALL();
44 auto device = std::unique_ptr<CameraDevice>(new CameraDevice());
45
46 if (device == nullptr) {
47 ALOGE("%s: Creating CameraDevice failed.", __FUNCTION__);
48 return nullptr;
49 }
50
51 status_t res =
52 device->Initialize(std::move(camera_device_hwl), camera_allocator_hwl);
53 if (res != OK) {
54 ALOGE("%s: Initializing CameraDevice failed: %s (%d).", __FUNCTION__,
55 strerror(-res), res);
56 return nullptr;
57 }
58
59 ALOGI("%s: Created a camera device for public(%u)", __FUNCTION__,
60 device->GetPublicCameraId());
61
62 return device;
63 }
64
Initialize(std::unique_ptr<CameraDeviceHwl> camera_device_hwl,CameraBufferAllocatorHwl * camera_allocator_hwl)65 status_t CameraDevice::Initialize(
66 std::unique_ptr<CameraDeviceHwl> camera_device_hwl,
67 CameraBufferAllocatorHwl* camera_allocator_hwl) {
68 ATRACE_CALL();
69 if (camera_device_hwl == nullptr) {
70 ALOGE("%s: camera_device_hwl cannot be nullptr.", __FUNCTION__);
71 return BAD_VALUE;
72 }
73
74 public_camera_id_ = camera_device_hwl->GetCameraId();
75 camera_device_hwl_ = std::move(camera_device_hwl);
76 camera_allocator_hwl_ = camera_allocator_hwl;
77 status_t res = LoadExternalCaptureSession();
78 if (res != OK) {
79 ALOGE("%s: Loading external capture sessions failed: %s(%d)", __FUNCTION__,
80 strerror(-res), res);
81 return res;
82 }
83
84 return OK;
85 }
86
GetResourceCost(CameraResourceCost * cost)87 status_t CameraDevice::GetResourceCost(CameraResourceCost* cost) {
88 ATRACE_CALL();
89 return camera_device_hwl_->GetResourceCost(cost);
90 }
91
GetCameraCharacteristics(std::unique_ptr<HalCameraMetadata> * characteristics)92 status_t CameraDevice::GetCameraCharacteristics(
93 std::unique_ptr<HalCameraMetadata>* characteristics) {
94 ATRACE_CALL();
95 status_t res = camera_device_hwl_->GetCameraCharacteristics(characteristics);
96 if (res != OK) {
97 ALOGE("%s: GetCameraCharacteristics() failed: %s (%d).", __FUNCTION__,
98 strerror(-res), res);
99 return res;
100 }
101
102 return hal_vendor_tag_utils::ModifyCharacteristicsKeys(characteristics->get());
103 }
104
GetPhysicalCameraCharacteristics(uint32_t physical_camera_id,std::unique_ptr<HalCameraMetadata> * characteristics)105 status_t CameraDevice::GetPhysicalCameraCharacteristics(
106 uint32_t physical_camera_id,
107 std::unique_ptr<HalCameraMetadata>* characteristics) {
108 ATRACE_CALL();
109 status_t res = camera_device_hwl_->GetPhysicalCameraCharacteristics(
110 physical_camera_id, characteristics);
111 if (res != OK) {
112 ALOGE("%s: GetPhysicalCameraCharacteristics() failed: %s (%d).",
113 __FUNCTION__, strerror(-res), res);
114 return res;
115 }
116
117 return hal_vendor_tag_utils::ModifyCharacteristicsKeys(characteristics->get());
118 }
119
SetTorchMode(TorchMode mode)120 status_t CameraDevice::SetTorchMode(TorchMode mode) {
121 ATRACE_CALL();
122 return camera_device_hwl_->SetTorchMode(mode);
123 }
124
DumpState(int fd)125 status_t CameraDevice::DumpState(int fd) {
126 ATRACE_CALL();
127 return camera_device_hwl_->DumpState(fd);
128 }
129
CreateCameraDeviceSession(std::unique_ptr<CameraDeviceSession> * session)130 status_t CameraDevice::CreateCameraDeviceSession(
131 std::unique_ptr<CameraDeviceSession>* session) {
132 ATRACE_CALL();
133 if (session == nullptr) {
134 ALOGE("%s: session is nullptr.", __FUNCTION__);
135 return BAD_VALUE;
136 }
137
138 std::unique_ptr<CameraDeviceSessionHwl> session_hwl;
139 status_t res = camera_device_hwl_->CreateCameraDeviceSessionHwl(
140 camera_allocator_hwl_, &session_hwl);
141 if (res != OK) {
142 ALOGE("%s: Creating a CameraDeviceSessionHwl failed: %s(%d)", __FUNCTION__,
143 strerror(-res), res);
144 return res;
145 }
146
147 *session = CameraDeviceSession::Create(std::move(session_hwl),
148 external_session_factory_entries_,
149 camera_allocator_hwl_);
150 if (*session == nullptr) {
151 ALOGE("%s: Creating a CameraDeviceSession failed: %s(%d)", __FUNCTION__,
152 strerror(-res), res);
153 return UNKNOWN_ERROR;
154 }
155
156 return OK;
157 }
158
IsStreamCombinationSupported(const StreamConfiguration & stream_config)159 bool CameraDevice::IsStreamCombinationSupported(
160 const StreamConfiguration& stream_config) {
161 bool supported =
162 camera_device_hwl_->IsStreamCombinationSupported(stream_config);
163 if (!supported) {
164 ALOGD("%s: stream config is not supported.", __FUNCTION__);
165 }
166
167 return supported;
168 }
169
170 // Returns an array of regular files under dir_path.
FindLibraryPaths(const char * dir_path)171 static std::vector<std::string> FindLibraryPaths(const char* dir_path) {
172 std::vector<std::string> libs;
173
174 errno = 0;
175 DIR* dir = opendir(dir_path);
176 if (!dir) {
177 ALOGD("%s: Unable to open directory %s (%s)", __FUNCTION__, dir_path,
178 strerror(errno));
179 return libs;
180 }
181
182 struct dirent* entry = nullptr;
183 while ((entry = readdir(dir)) != nullptr) {
184 std::string lib_path(dir_path);
185 lib_path += entry->d_name;
186 struct stat st;
187 if (stat(lib_path.c_str(), &st) == 0) {
188 if (S_ISREG(st.st_mode)) {
189 libs.push_back(lib_path);
190 }
191 }
192 }
193
194 return libs;
195 }
196
LoadExternalCaptureSession()197 status_t CameraDevice::LoadExternalCaptureSession() {
198 ATRACE_CALL();
199
200 if (external_session_factory_entries_.size() > 0) {
201 ALOGI("%s: External capture session libraries already loaded; skip.",
202 __FUNCTION__);
203 return OK;
204 }
205
206 for (const auto& lib_path : FindLibraryPaths(kExternalCaptureSessionDir)) {
207 ALOGI("%s: Loading %s", __FUNCTION__, lib_path.c_str());
208 void* lib_handle = nullptr;
209 lib_handle = dlopen(lib_path.c_str(), RTLD_NOW);
210 if (lib_handle == nullptr) {
211 ALOGW("Failed loading %s.", lib_path.c_str());
212 continue;
213 }
214
215 GetCaptureSessionFactoryFunc external_session_factory_t =
216 reinterpret_cast<GetCaptureSessionFactoryFunc>(
217 dlsym(lib_handle, "GetCaptureSessionFactory"));
218 if (external_session_factory_t == nullptr) {
219 ALOGE("%s: dlsym failed (%s) when loading %s.", __FUNCTION__,
220 "GetCaptureSessionFactory", lib_path.c_str());
221 dlclose(lib_handle);
222 lib_handle = nullptr;
223 continue;
224 }
225
226 external_session_factory_entries_.push_back(external_session_factory_t);
227 external_capture_session_lib_handles_.push_back(lib_handle);
228 }
229
230 return OK;
231 }
232
~CameraDevice()233 CameraDevice::~CameraDevice() {
234 for (auto lib_handle : external_capture_session_lib_handles_) {
235 dlclose(lib_handle);
236 }
237 }
238
239 } // namespace google_camera_hal
240 } // namespace android
241