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 "camera_device.h"
21
22 #include <dlfcn.h>
23 #include <errno.h>
24 #include <log/log.h>
25 #include <meminfo/procmeminfo.h>
26 #include <stdio.h>
27 #include <sys/mman.h>
28 #include <sys/stat.h>
29 #include <utils/Trace.h>
30
31 #include <thread>
32
33 #include "utils.h"
34 #include "vendor_tags.h"
35
36 using android::meminfo::ProcMemInfo;
37 using namespace android::meminfo;
38
39 namespace android {
40
MadviseFileForRange(size_t madvise_size_limit_bytes,size_t map_size_bytes,const uint8_t * map_begin,const uint8_t * map_end,const std::string & file_name)41 void MadviseFileForRange(size_t madvise_size_limit_bytes, size_t map_size_bytes,
42 const uint8_t* map_begin, const uint8_t* map_end,
43 const std::string& file_name) {
44 // Ideal blockTransferSize for madvising files (128KiB)
45 static const size_t kIdealIoTransferSizeBytes = 128 * 1024;
46 size_t target_size_bytes =
47 std::min<size_t>(map_size_bytes, madvise_size_limit_bytes);
48 if (target_size_bytes == 0) {
49 return;
50 }
51 std::string trace_tag =
52 "madvising " + file_name + " size=" + std::to_string(target_size_bytes);
53 ATRACE_NAME(trace_tag.c_str());
54 // Based on requested size (target_size_bytes)
55 const uint8_t* target_pos = map_begin + target_size_bytes;
56
57 // Clamp endOfFile if its past map_end
58 if (target_pos > map_end) {
59 target_pos = map_end;
60 }
61
62 // Madvise the whole file up to target_pos in chunks of
63 // kIdealIoTransferSizeBytes (to MADV_WILLNEED)
64 // Note:
65 // madvise(MADV_WILLNEED) will prefetch max(fd readahead size, optimal
66 // block size for device) per call, hence the need for chunks. (128KB is a
67 // good default.)
68 for (const uint8_t* madvise_start = map_begin; madvise_start < target_pos;
69 madvise_start += kIdealIoTransferSizeBytes) {
70 void* madvise_addr =
71 const_cast<void*>(reinterpret_cast<const void*>(madvise_start));
72 size_t madvise_length =
73 std::min(kIdealIoTransferSizeBytes,
74 static_cast<size_t>(target_pos - madvise_start));
75 int status = madvise(madvise_addr, madvise_length, MADV_WILLNEED);
76 // In case of error we stop madvising rest of the file
77 if (status < 0) {
78 break;
79 }
80 }
81 }
82
ReadAheadVma(const Vma & vma,const size_t madvise_size_limit_bytes)83 static void ReadAheadVma(const Vma& vma, const size_t madvise_size_limit_bytes) {
84 const uint8_t* map_begin = reinterpret_cast<uint8_t*>(vma.start);
85 const uint8_t* map_end = reinterpret_cast<uint8_t*>(vma.end);
86 MadviseFileForRange(madvise_size_limit_bytes,
87 static_cast<size_t>(map_end - map_begin), map_begin,
88 map_end, vma.name);
89 }
90
LoadLibraries(const std::vector<std::string> * libs)91 static void LoadLibraries(const std::vector<std::string>* libs) {
92 auto vmaCollectorCb = [&libs](const Vma& vma) {
93 const static size_t kMadviseSizeLimitBytes =
94 std::numeric_limits<size_t>::max();
95 // Read ahead for anonymous VMAs and for specific files.
96 // vma.flags represents a VMAs rwx bits.
97 if (vma.inode == 0 && !vma.is_shared && vma.flags) {
98 ReadAheadVma(vma, kMadviseSizeLimitBytes);
99 } else if (vma.inode != 0 && libs != nullptr &&
100 std::any_of(libs->begin(), libs->end(),
101 [&vma](std::string lib_name) {
102 return lib_name.compare(vma.name) == 0;
103 })) {
104 ReadAheadVma(vma, kMadviseSizeLimitBytes);
105 }
106 };
107 ProcMemInfo meminfo(getpid());
108 meminfo.ForEachVmaFromMaps(vmaCollectorCb);
109 }
110
111 namespace google_camera_hal {
112
113 // HAL external capture session library path
114 #if GCH_HWL_USE_DLOPEN
115 #if defined(_LP64)
116 constexpr char kExternalCaptureSessionDir[] =
117 "/vendor/lib64/camera/capture_sessions/";
118 #else // defined(_LP64)
119 constexpr char kExternalCaptureSessionDir[] =
120 "/vendor/lib/camera/capture_sessions/";
121 #endif
122 #endif
123
Create(std::unique_ptr<CameraDeviceHwl> camera_device_hwl,CameraBufferAllocatorHwl * camera_allocator_hwl,const std::vector<std::string> * configure_streams_libs)124 std::unique_ptr<CameraDevice> CameraDevice::Create(
125 std::unique_ptr<CameraDeviceHwl> camera_device_hwl,
126 CameraBufferAllocatorHwl* camera_allocator_hwl,
127 const std::vector<std::string>* configure_streams_libs) {
128 ATRACE_CALL();
129 auto device = std::unique_ptr<CameraDevice>(new CameraDevice());
130
131 if (device == nullptr) {
132 ALOGE("%s: Creating CameraDevice failed.", __FUNCTION__);
133 return nullptr;
134 }
135
136 status_t res =
137 device->Initialize(std::move(camera_device_hwl), camera_allocator_hwl);
138 if (res != OK) {
139 ALOGE("%s: Initializing CameraDevice failed: %s (%d).", __FUNCTION__,
140 strerror(-res), res);
141 return nullptr;
142 }
143
144 ALOGI("%s: Created a camera device for public(%u)", __FUNCTION__,
145 device->GetPublicCameraId());
146 device->configure_streams_libs_ = configure_streams_libs;
147
148 return device;
149 }
150
Initialize(std::unique_ptr<CameraDeviceHwl> camera_device_hwl,CameraBufferAllocatorHwl * camera_allocator_hwl)151 status_t CameraDevice::Initialize(
152 std::unique_ptr<CameraDeviceHwl> camera_device_hwl,
153 CameraBufferAllocatorHwl* camera_allocator_hwl) {
154 ATRACE_CALL();
155 if (camera_device_hwl == nullptr) {
156 ALOGE("%s: camera_device_hwl cannot be nullptr.", __FUNCTION__);
157 return BAD_VALUE;
158 }
159
160 public_camera_id_ = camera_device_hwl->GetCameraId();
161 camera_device_hwl_ = std::move(camera_device_hwl);
162 camera_allocator_hwl_ = camera_allocator_hwl;
163 status_t res = LoadExternalCaptureSession();
164 if (res != OK) {
165 ALOGE("%s: Loading external capture sessions failed: %s(%d)", __FUNCTION__,
166 strerror(-res), res);
167 return res;
168 }
169
170 std::unique_ptr<HalCameraMetadata> static_metadata;
171 res = camera_device_hwl_->GetCameraCharacteristics(&static_metadata);
172 if (res != OK) {
173 ALOGE("%s: Getting camera characteristics failed: %s(%d)", __FUNCTION__,
174 strerror(-res), res);
175 return res;
176 }
177
178 res = utils::GetStreamUseCases(static_metadata.get(), &stream_use_cases_);
179 if (res != OK) {
180 ALOGE("%s: Getting stream use cases failed: %s(%d)", __FUNCTION__,
181 strerror(-res), res);
182 return res;
183 }
184
185 return OK;
186 }
187
GetResourceCost(CameraResourceCost * cost)188 status_t CameraDevice::GetResourceCost(CameraResourceCost* cost) {
189 ATRACE_CALL();
190 return camera_device_hwl_->GetResourceCost(cost);
191 }
192
GetCameraCharacteristics(std::unique_ptr<HalCameraMetadata> * characteristics)193 status_t CameraDevice::GetCameraCharacteristics(
194 std::unique_ptr<HalCameraMetadata>* characteristics) {
195 ATRACE_CALL();
196 status_t res = camera_device_hwl_->GetCameraCharacteristics(characteristics);
197 if (res != OK) {
198 ALOGE("%s: GetCameraCharacteristics() failed: %s (%d).", __FUNCTION__,
199 strerror(-res), res);
200 return res;
201 }
202
203 return hal_vendor_tag_utils::ModifyCharacteristicsKeys(characteristics->get());
204 }
205
GetPhysicalCameraCharacteristics(uint32_t physical_camera_id,std::unique_ptr<HalCameraMetadata> * characteristics)206 status_t CameraDevice::GetPhysicalCameraCharacteristics(
207 uint32_t physical_camera_id,
208 std::unique_ptr<HalCameraMetadata>* characteristics) {
209 ATRACE_CALL();
210 status_t res = camera_device_hwl_->GetPhysicalCameraCharacteristics(
211 physical_camera_id, characteristics);
212 if (res != OK) {
213 ALOGE("%s: GetPhysicalCameraCharacteristics() failed: %s (%d).",
214 __FUNCTION__, strerror(-res), res);
215 return res;
216 }
217
218 return hal_vendor_tag_utils::ModifyCharacteristicsKeys(characteristics->get());
219 }
220
SetTorchMode(TorchMode mode)221 status_t CameraDevice::SetTorchMode(TorchMode mode) {
222 ATRACE_CALL();
223 return camera_device_hwl_->SetTorchMode(mode);
224 }
225
TurnOnTorchWithStrengthLevel(int32_t torch_strength)226 status_t CameraDevice::TurnOnTorchWithStrengthLevel(int32_t torch_strength) {
227 ATRACE_CALL();
228 return camera_device_hwl_->TurnOnTorchWithStrengthLevel(torch_strength);
229 }
230
GetTorchStrengthLevel(int32_t & torch_strength) const231 status_t CameraDevice::GetTorchStrengthLevel(int32_t& torch_strength) const {
232 ATRACE_CALL();
233 status_t res = camera_device_hwl_->GetTorchStrengthLevel(torch_strength);
234 if (res != OK) {
235 ALOGE("%s: GetTorchStrengthLevel() failed: %s (%d).", __FUNCTION__,
236 strerror(-res), res);
237 return res;
238 }
239
240 return res;
241 }
242
DumpState(int fd)243 status_t CameraDevice::DumpState(int fd) {
244 ATRACE_CALL();
245 return camera_device_hwl_->DumpState(fd);
246 }
247
CreateCameraDeviceSession(std::unique_ptr<CameraDeviceSession> * session)248 status_t CameraDevice::CreateCameraDeviceSession(
249 std::unique_ptr<CameraDeviceSession>* session) {
250 ATRACE_CALL();
251 if (session == nullptr) {
252 ALOGE("%s: session is nullptr.", __FUNCTION__);
253 return BAD_VALUE;
254 }
255
256 std::unique_ptr<CameraDeviceSessionHwl> session_hwl;
257 status_t res = camera_device_hwl_->CreateCameraDeviceSessionHwl(
258 camera_allocator_hwl_, &session_hwl);
259 if (res != OK) {
260 ALOGE("%s: Creating a CameraDeviceSessionHwl failed: %s(%d)", __FUNCTION__,
261 strerror(-res), res);
262 return res;
263 }
264
265 *session = CameraDeviceSession::Create(std::move(session_hwl),
266 external_session_factory_entries_,
267 camera_allocator_hwl_);
268 if (*session == nullptr) {
269 ALOGE("%s: Creating a CameraDeviceSession failed: %s(%d)", __FUNCTION__,
270 strerror(-res), res);
271 return UNKNOWN_ERROR;
272 }
273
274 std::thread t(LoadLibraries, configure_streams_libs_);
275 t.detach();
276
277 return OK;
278 }
279
IsStreamCombinationSupported(const StreamConfiguration & stream_config)280 bool CameraDevice::IsStreamCombinationSupported(
281 const StreamConfiguration& stream_config) {
282 if (!utils::IsStreamUseCaseSupported(stream_config, stream_use_cases_)) {
283 return false;
284 }
285
286 bool supported =
287 camera_device_hwl_->IsStreamCombinationSupported(stream_config);
288 if (!supported) {
289 ALOGD("%s: stream config is not supported.", __FUNCTION__);
290 }
291
292 return supported;
293 }
294
LoadExternalCaptureSession()295 status_t CameraDevice::LoadExternalCaptureSession() {
296 ATRACE_CALL();
297
298 if (external_session_factory_entries_.size() > 0) {
299 ALOGI("%s: External capture session libraries already loaded; skip.",
300 __FUNCTION__);
301 return OK;
302 }
303
304 #if GCH_HWL_USE_DLOPEN
305 for (const auto& lib_path :
306 utils::FindLibraryPaths(kExternalCaptureSessionDir)) {
307 ALOGI("%s: Loading %s", __FUNCTION__, lib_path.c_str());
308 void* lib_handle = nullptr;
309 // load shared library and never unload
310 // TODO(b/...): Switch to using build-system based HWL
311 // loading and remove dlopen here?
312 lib_handle = dlopen(lib_path.c_str(), RTLD_NOW);
313 if (lib_handle == nullptr) {
314 ALOGW("Failed loading %s.", lib_path.c_str());
315 continue;
316 }
317
318 GetCaptureSessionFactoryFunc external_session_factory_t =
319 reinterpret_cast<GetCaptureSessionFactoryFunc>(
320 dlsym(lib_handle, "GetCaptureSessionFactory"));
321 if (external_session_factory_t == nullptr) {
322 ALOGE("%s: dlsym failed (%s) when loading %s.", __FUNCTION__,
323 "GetCaptureSessionFactory", lib_path.c_str());
324 dlclose(lib_handle);
325 lib_handle = nullptr;
326 continue;
327 }
328
329 external_session_factory_entries_.push_back(external_session_factory_t);
330 external_capture_session_lib_handles_.push_back(lib_handle);
331 }
332 #else
333 if (GetCaptureSessionFactory) {
334 external_session_factory_entries_.push_back(GetCaptureSessionFactory);
335 }
336 #endif
337
338 return OK;
339 }
340
~CameraDevice()341 CameraDevice::~CameraDevice() {
342 }
343
GetProfiler(uint32_t camera_id,int option)344 std::unique_ptr<google::camera_common::Profiler> CameraDevice::GetProfiler(
345 uint32_t camera_id, int option) {
346 return camera_device_hwl_->GetProfiler(camera_id, option);
347 }
348
349 } // namespace google_camera_hal
350 } // namespace android
351