• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     return true;
107   };
108   ProcMemInfo meminfo(getpid());
109   meminfo.ForEachVmaFromMaps(vmaCollectorCb);
110 }
111 
112 namespace google_camera_hal {
113 
114 // HAL external capture session library path
115 #if GCH_HWL_USE_DLOPEN
116 #if defined(_LP64)
117 constexpr char kExternalCaptureSessionDir[] =
118     "/vendor/lib64/camera/capture_sessions/";
119 #else  // defined(_LP64)
120 constexpr char kExternalCaptureSessionDir[] =
121     "/vendor/lib/camera/capture_sessions/";
122 #endif
123 #endif
124 
Create(std::unique_ptr<CameraDeviceHwl> camera_device_hwl,CameraBufferAllocatorHwl * camera_allocator_hwl,const std::vector<std::string> * configure_streams_libs)125 std::unique_ptr<CameraDevice> CameraDevice::Create(
126     std::unique_ptr<CameraDeviceHwl> camera_device_hwl,
127     CameraBufferAllocatorHwl* camera_allocator_hwl,
128     const std::vector<std::string>* configure_streams_libs) {
129   ATRACE_CALL();
130   auto device = std::unique_ptr<CameraDevice>(new CameraDevice());
131 
132   if (device == nullptr) {
133     ALOGE("%s: Creating CameraDevice failed.", __FUNCTION__);
134     return nullptr;
135   }
136 
137   status_t res =
138       device->Initialize(std::move(camera_device_hwl), camera_allocator_hwl);
139   if (res != OK) {
140     ALOGE("%s: Initializing CameraDevice failed: %s (%d).", __FUNCTION__,
141           strerror(-res), res);
142     return nullptr;
143   }
144 
145   ALOGI("%s: Created a camera device for public(%u)", __FUNCTION__,
146         device->GetPublicCameraId());
147   device->configure_streams_libs_ = configure_streams_libs;
148 
149   return device;
150 }
151 
Initialize(std::unique_ptr<CameraDeviceHwl> camera_device_hwl,CameraBufferAllocatorHwl * camera_allocator_hwl)152 status_t CameraDevice::Initialize(
153     std::unique_ptr<CameraDeviceHwl> camera_device_hwl,
154     CameraBufferAllocatorHwl* camera_allocator_hwl) {
155   ATRACE_CALL();
156   if (camera_device_hwl == nullptr) {
157     ALOGE("%s: camera_device_hwl cannot be nullptr.", __FUNCTION__);
158     return BAD_VALUE;
159   }
160 
161   public_camera_id_ = camera_device_hwl->GetCameraId();
162   camera_device_hwl_ = std::move(camera_device_hwl);
163   camera_allocator_hwl_ = camera_allocator_hwl;
164   status_t res = LoadExternalCaptureSession();
165   if (res != OK) {
166     ALOGE("%s: Loading external capture sessions failed: %s(%d)", __FUNCTION__,
167           strerror(-res), res);
168     return res;
169   }
170 
171   std::unique_ptr<HalCameraMetadata> static_metadata;
172   res = camera_device_hwl_->GetCameraCharacteristics(&static_metadata);
173   if (res != OK) {
174     ALOGE("%s: Getting camera characteristics failed: %s(%d)", __FUNCTION__,
175           strerror(-res), res);
176     return res;
177   }
178 
179   res = utils::GetStreamUseCases(
180       static_metadata.get(),
181       &camera_id_to_stream_use_cases_[camera_device_hwl_->GetCameraId()]);
182   if (res != OK) {
183     ALOGE(
184         "%s: Initializing logical stream use case for camera id %u failed: "
185         "%s(%d)",
186         __FUNCTION__, camera_device_hwl_->GetCameraId(), strerror(-res), res);
187     return res;
188   }
189   res = utils::GetPhysicalCameraStreamUseCases(camera_device_hwl_.get(),
190                                                &camera_id_to_stream_use_cases_);
191 
192   if (res != OK) {
193     ALOGE(
194         "%s: Initializing physical stream use case for camera id %u failed: "
195         "%s(%d)",
196         __FUNCTION__, camera_device_hwl_->GetCameraId(), strerror(-res), res);
197   }
198   return res;
199 }
200 
GetResourceCost(CameraResourceCost * cost)201 status_t CameraDevice::GetResourceCost(CameraResourceCost* cost) {
202   ATRACE_CALL();
203   return camera_device_hwl_->GetResourceCost(cost);
204 }
205 
GetCameraCharacteristics(std::unique_ptr<HalCameraMetadata> * characteristics)206 status_t CameraDevice::GetCameraCharacteristics(
207     std::unique_ptr<HalCameraMetadata>* characteristics) {
208   ATRACE_CALL();
209   status_t res = camera_device_hwl_->GetCameraCharacteristics(characteristics);
210   if (res != OK) {
211     ALOGE("%s: GetCameraCharacteristics() failed: %s (%d).", __FUNCTION__,
212           strerror(-res), res);
213     return res;
214   }
215 
216   return hal_vendor_tag_utils::ModifyCharacteristicsKeys(characteristics->get());
217 }
218 
219 // Populates the required session characteristics keys from a camera
220 // characteristics object.
generateSessionCharacteristics(const HalCameraMetadata * camera_characteristics,HalCameraMetadata * session_characteristics)221 status_t generateSessionCharacteristics(
222     const HalCameraMetadata* camera_characteristics,
223     HalCameraMetadata* session_characteristics) {
224   if (camera_characteristics == nullptr) {
225     ALOGE("%s: camera characteristics is nullptr", __FUNCTION__);
226     return BAD_VALUE;
227   }
228 
229   if (session_characteristics == nullptr) {
230     ALOGE("%s: session characteristics is nullptr", __FUNCTION__);
231     return BAD_VALUE;
232   }
233 
234   camera_metadata_ro_entry entry;
235   status_t res;
236 
237   // Get the zoom ratio key
238   res = camera_characteristics->Get(ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry);
239   if (res == OK && entry.count == 2) {
240     std::vector<float> zoom_ratio_key(entry.data.f, entry.data.f + entry.count);
241     if (session_characteristics->Set(ANDROID_CONTROL_ZOOM_RATIO_RANGE,
242                                      zoom_ratio_key.data(),
243                                      zoom_ratio_key.size()) != OK) {
244       ALOGE("%s Updating static metadata with zoom ratio range failed",
245             __FUNCTION__);
246       return UNKNOWN_ERROR;
247     }
248   }
249 
250   // Get the max digital zoom key
251   res = camera_characteristics->Get(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
252                                     &entry);
253   if (res == OK) {
254     std::vector<float> max_digital_zoom_key(entry.data.f,
255                                             entry.data.f + entry.count);
256     if (session_characteristics->Set(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
257                                      max_digital_zoom_key.data(),
258                                      max_digital_zoom_key.size()) != OK) {
259       ALOGE("%s Updating static metadata with max digital zoom failed",
260             __FUNCTION__);
261       return UNKNOWN_ERROR;
262     }
263   }
264 
265   return OK;
266 }
267 
GetSessionCharacteristics(const StreamConfiguration & stream_config,std::unique_ptr<HalCameraMetadata> & session_characteristics)268 status_t CameraDevice::GetSessionCharacteristics(
269     const StreamConfiguration& stream_config,
270     std::unique_ptr<HalCameraMetadata>& session_characteristics) {
271   ATRACE_CALL();
272   std::unique_ptr<HalCameraMetadata> camera_characteristics;
273   status_t res = camera_device_hwl_->GetSessionCharacteristics(
274       stream_config, camera_characteristics);
275   if (res != OK) {
276     ALOGE("%s: GetCameraCharacteristics() failed: %s (%d).", __FUNCTION__,
277           strerror(-res), res);
278     return res;
279   }
280 
281   // Allocating space for 10 entries and 256 bytes.
282   session_characteristics = HalCameraMetadata::Create(10, 256);
283 
284   return generateSessionCharacteristics(camera_characteristics.get(),
285                                         session_characteristics.get());
286 }
287 
GetPhysicalCameraCharacteristics(uint32_t physical_camera_id,std::unique_ptr<HalCameraMetadata> * characteristics)288 status_t CameraDevice::GetPhysicalCameraCharacteristics(
289     uint32_t physical_camera_id,
290     std::unique_ptr<HalCameraMetadata>* characteristics) {
291   ATRACE_CALL();
292   status_t res = camera_device_hwl_->GetPhysicalCameraCharacteristics(
293       physical_camera_id, characteristics);
294   if (res != OK) {
295     ALOGE("%s: GetPhysicalCameraCharacteristics() failed: %s (%d).",
296           __FUNCTION__, strerror(-res), res);
297     return res;
298   }
299 
300   return hal_vendor_tag_utils::ModifyCharacteristicsKeys(characteristics->get());
301 }
302 
SetTorchMode(TorchMode mode)303 status_t CameraDevice::SetTorchMode(TorchMode mode) {
304   ATRACE_CALL();
305   return camera_device_hwl_->SetTorchMode(mode);
306 }
307 
TurnOnTorchWithStrengthLevel(int32_t torch_strength)308 status_t CameraDevice::TurnOnTorchWithStrengthLevel(int32_t torch_strength) {
309   ATRACE_CALL();
310   return camera_device_hwl_->TurnOnTorchWithStrengthLevel(torch_strength);
311 }
312 
GetTorchStrengthLevel(int32_t & torch_strength) const313 status_t CameraDevice::GetTorchStrengthLevel(int32_t& torch_strength) const {
314   ATRACE_CALL();
315   status_t res = camera_device_hwl_->GetTorchStrengthLevel(torch_strength);
316   if (res != OK) {
317     ALOGE("%s: GetTorchStrengthLevel() failed: %s (%d).", __FUNCTION__,
318           strerror(-res), res);
319     return res;
320   }
321 
322   return res;
323 }
324 
ConstructDefaultRequestSettings(RequestTemplate type,std::unique_ptr<HalCameraMetadata> * request_settings)325 status_t CameraDevice::ConstructDefaultRequestSettings(
326     RequestTemplate type, std::unique_ptr<HalCameraMetadata>* request_settings) {
327   ATRACE_CALL();
328   return camera_device_hwl_->ConstructDefaultRequestSettings(type,
329                                                              request_settings);
330 }
331 
DumpState(int fd)332 status_t CameraDevice::DumpState(int fd) {
333   ATRACE_CALL();
334   return camera_device_hwl_->DumpState(fd);
335 }
336 
CreateCameraDeviceSession(std::unique_ptr<CameraDeviceSession> * session)337 status_t CameraDevice::CreateCameraDeviceSession(
338     std::unique_ptr<CameraDeviceSession>* session) {
339   ATRACE_CALL();
340   if (session == nullptr) {
341     ALOGE("%s: session is nullptr.", __FUNCTION__);
342     return BAD_VALUE;
343   }
344 
345   std::unique_ptr<CameraDeviceSessionHwl> session_hwl;
346   status_t res = camera_device_hwl_->CreateCameraDeviceSessionHwl(
347       camera_allocator_hwl_, &session_hwl);
348   if (res != OK) {
349     ALOGE("%s: Creating a CameraDeviceSessionHwl failed: %s(%d)", __FUNCTION__,
350           strerror(-res), res);
351     return res;
352   }
353 
354   *session = CameraDeviceSession::Create(std::move(session_hwl),
355                                          external_session_factory_entries_,
356                                          camera_allocator_hwl_);
357   if (*session == nullptr) {
358     ALOGE("%s: Creating a CameraDeviceSession failed: %s(%d)", __FUNCTION__,
359           strerror(-res), res);
360     return UNKNOWN_ERROR;
361   }
362 
363   std::thread t(LoadLibraries, configure_streams_libs_);
364   t.detach();
365 
366   return OK;
367 }
368 
IsStreamCombinationSupported(const StreamConfiguration & stream_config,bool check_settings)369 bool CameraDevice::IsStreamCombinationSupported(
370     const StreamConfiguration& stream_config, bool check_settings) {
371   if (!utils::IsStreamUseCaseSupported(stream_config, public_camera_id_,
372                                        camera_id_to_stream_use_cases_)) {
373     return false;
374   }
375 
376   bool supported = camera_device_hwl_->IsStreamCombinationSupported(
377       stream_config, check_settings);
378   if (!supported) {
379     ALOGD("%s: stream config is not supported.", __FUNCTION__);
380   }
381 
382   return supported;
383 }
384 
LoadExternalCaptureSession()385 status_t CameraDevice::LoadExternalCaptureSession() {
386   ATRACE_CALL();
387 
388   if (external_session_factory_entries_.size() > 0) {
389     ALOGI("%s: External capture session libraries already loaded; skip.",
390           __FUNCTION__);
391     return OK;
392   }
393 
394 #if GCH_HWL_USE_DLOPEN
395   for (const auto& lib_path :
396        utils::FindLibraryPaths(kExternalCaptureSessionDir)) {
397     ALOGI("%s: Loading %s", __FUNCTION__, lib_path.c_str());
398     void* lib_handle = nullptr;
399     // load shared library and never unload
400     // TODO(b/...): Switch to using build-system based HWL
401     //   loading and remove dlopen here?
402     lib_handle = dlopen(lib_path.c_str(), RTLD_NOW);
403     if (lib_handle == nullptr) {
404       ALOGW("Failed loading %s.", lib_path.c_str());
405       continue;
406     }
407 
408     GetCaptureSessionFactoryFunc external_session_factory_t =
409         reinterpret_cast<GetCaptureSessionFactoryFunc>(
410             dlsym(lib_handle, "GetCaptureSessionFactory"));
411     if (external_session_factory_t == nullptr) {
412       ALOGE("%s: dlsym failed (%s) when loading %s.", __FUNCTION__,
413             "GetCaptureSessionFactory", lib_path.c_str());
414       dlclose(lib_handle);
415       lib_handle = nullptr;
416       continue;
417     }
418 
419     external_session_factory_entries_.push_back(external_session_factory_t);
420     external_capture_session_lib_handles_.push_back(lib_handle);
421   }
422 #else
423   if (GetCaptureSessionFactory) {
424     external_session_factory_entries_.push_back(GetCaptureSessionFactory);
425   }
426 #endif
427 
428   return OK;
429 }
430 
~CameraDevice()431 CameraDevice::~CameraDevice() {
432 }
433 
GetProfiler(uint32_t camera_id,int option)434 std::unique_ptr<google::camera_common::Profiler> CameraDevice::GetProfiler(
435     uint32_t camera_id, int option) {
436   return camera_device_hwl_->GetProfiler(camera_id, option);
437 }
438 
439 }  // namespace google_camera_hal
440 }  // namespace android
441