| // Copyright 2016 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "camera3_test/camera3_device_fixture.h" |
| |
| #include "camera3_test/camera3_device_impl.h" |
| |
| #include <base/check.h> |
| |
| namespace camera3_test { |
| |
| Camera3Device::Camera3Device(int cam_id) |
| : impl_(new Camera3DeviceImpl(cam_id)) {} |
| |
| Camera3Device::~Camera3Device() {} |
| |
| int Camera3Device::Initialize(Camera3Module* cam_module) { |
| DCHECK(impl_); |
| return impl_->Initialize(cam_module); |
| } |
| |
| void Camera3Device::Destroy() { |
| DCHECK(impl_); |
| impl_->Destroy(); |
| } |
| |
| void Camera3Device::RegisterProcessCaptureResultCallback( |
| Camera3Device::ProcessCaptureResultCallback cb) { |
| DCHECK(impl_); |
| impl_->RegisterProcessCaptureResultCallback(cb); |
| } |
| |
| void Camera3Device::RegisterNotifyCallback(Camera3Device::NotifyCallback cb) { |
| DCHECK(impl_); |
| impl_->RegisterNotifyCallback(cb); |
| } |
| |
| void Camera3Device::RegisterResultMetadataOutputBufferCallback( |
| Camera3Device::ProcessResultMetadataOutputBuffersCallback cb) { |
| DCHECK(impl_); |
| impl_->RegisterResultMetadataOutputBufferCallback(cb); |
| } |
| |
| void Camera3Device::RegisterPartialMetadataCallback( |
| Camera3Device::ProcessPartialMetadataCallback cb) { |
| DCHECK(impl_); |
| impl_->RegisterPartialMetadataCallback(cb); |
| } |
| |
| bool Camera3Device::IsTemplateSupported(int32_t type) { |
| DCHECK(impl_); |
| return impl_->IsTemplateSupported(type); |
| } |
| |
| const camera_metadata_t* Camera3Device::ConstructDefaultRequestSettings( |
| int type) { |
| DCHECK(impl_); |
| return impl_->ConstructDefaultRequestSettings(type); |
| } |
| |
| void Camera3Device::AddOutputStream( |
| int format, |
| int width, |
| int height, |
| camera3_stream_rotation_t crop_rotate_scale_degrees) { |
| DCHECK(impl_); |
| impl_->AddStream(format, width, height, |
| static_cast<int>(crop_rotate_scale_degrees), |
| CAMERA3_STREAM_OUTPUT); |
| } |
| |
| void Camera3Device::AddInputStream(int format, int width, int height) { |
| DCHECK(impl_); |
| impl_->AddStream(format, width, height, 0, CAMERA3_STREAM_INPUT); |
| } |
| |
| void Camera3Device::AddBidirectionalStream(int format, int width, int height) { |
| DCHECK(impl_); |
| impl_->AddStream(format, width, height, 0, CAMERA3_STREAM_BIDIRECTIONAL); |
| } |
| |
| void Camera3Device::AddOutputStreamWithRawDegrees( |
| int format, int width, int height, int crop_rotate_scale_degrees) { |
| DCHECK(impl_); |
| impl_->AddStream(format, width, height, crop_rotate_scale_degrees, |
| CAMERA3_STREAM_OUTPUT); |
| } |
| |
| int Camera3Device::ConfigureStreams( |
| std::vector<const camera3_stream_t*>* streams) { |
| DCHECK(impl_); |
| return impl_->ConfigureStreams(streams); |
| } |
| |
| int Camera3Device::AllocateOutputStreamBuffers( |
| std::vector<camera3_stream_buffer_t>* output_buffers) { |
| DCHECK(impl_); |
| return impl_->AllocateOutputStreamBuffers(output_buffers); |
| } |
| |
| int Camera3Device::AllocateOutputBuffersByStreams( |
| const std::vector<const camera3_stream_t*>& streams, |
| std::vector<camera3_stream_buffer_t>* output_buffers) { |
| DCHECK(impl_); |
| return impl_->AllocateOutputBuffersByStreams(streams, output_buffers); |
| } |
| |
| int Camera3Device::RegisterOutputBuffer( |
| const camera3_stream_t& stream, cros::ScopedBufferHandle unique_buffer) { |
| DCHECK(impl_); |
| return impl_->RegisterOutputBuffer(stream, std::move(unique_buffer)); |
| } |
| |
| int Camera3Device::ProcessCaptureRequest( |
| camera3_capture_request_t* capture_request) { |
| DCHECK(impl_); |
| return impl_->ProcessCaptureRequest(capture_request); |
| } |
| |
| int Camera3Device::WaitShutter(const struct timespec& timeout) { |
| DCHECK(impl_); |
| return impl_->WaitShutter(timeout); |
| } |
| |
| int Camera3Device::WaitCaptureResult(const struct timespec& timeout) { |
| DCHECK(impl_); |
| return impl_->WaitCaptureResult(timeout); |
| } |
| |
| int Camera3Device::Flush() { |
| DCHECK(impl_); |
| return impl_->Flush(); |
| } |
| |
| const Camera3Device::StaticInfo* Camera3Device::GetStaticInfo() const { |
| DCHECK(impl_); |
| return impl_->GetStaticInfo(); |
| } |
| |
| Camera3Device::StaticInfo::StaticInfo(const camera_info& cam_info) |
| : characteristics_(const_cast<camera_metadata_t*>( |
| cam_info.static_camera_characteristics)) {} |
| |
| bool Camera3Device::StaticInfo::IsKeyAvailable(uint32_t tag) const { |
| return AreKeysAvailable(std::vector<uint32_t>(1, tag)); |
| } |
| |
| bool Camera3Device::StaticInfo::AreKeysAvailable( |
| std::vector<uint32_t> tags) const { |
| for (const auto& tag : tags) { |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry(characteristics_, tag, &entry)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| uint8_t Camera3Device::StaticInfo::GetHardwareLevel() const { |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry(characteristics_, |
| ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, |
| &entry) != 0) { |
| ADD_FAILURE() |
| << "Cannot find the metadata ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL"; |
| return -EINVAL; |
| } |
| return entry.data.u8[0]; |
| } |
| |
| bool Camera3Device::StaticInfo::IsHardwareLevelAtLeast(uint8_t level) const { |
| return isHardwareLevelSupported(GetHardwareLevel(), level); |
| } |
| |
| bool Camera3Device::StaticInfo::IsHardwareLevelAtLeastFull() const { |
| return IsHardwareLevelAtLeast(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL); |
| } |
| |
| bool Camera3Device::StaticInfo::IsHardwareLevelAtLeastExternal() const { |
| return IsHardwareLevelAtLeast(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL); |
| } |
| |
| bool Camera3Device::StaticInfo::IsCapabilitySupported( |
| uint8_t capability) const { |
| EXPECT_GE(capability, 0) << "Capability must be non-negative"; |
| |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry(characteristics_, |
| ANDROID_REQUEST_AVAILABLE_CAPABILITIES, |
| &entry) == 0) { |
| return std::find(entry.data.u8, entry.data.u8 + entry.count, capability) != |
| entry.data.u8 + entry.count; |
| } |
| return false; |
| } |
| |
| bool Camera3Device::StaticInfo::IsDepthOutputSupported() const { |
| return IsCapabilitySupported( |
| ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT); |
| } |
| |
| bool Camera3Device::StaticInfo::IsColorOutputSupported() const { |
| return IsCapabilitySupported( |
| ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE); |
| } |
| |
| bool Camera3Device::StaticInfo::HasAvailableRequestKey(int32_t key) const { |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry(characteristics_, |
| ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, |
| &entry) == 0) { |
| return std::find(entry.data.i32, entry.data.i32 + entry.count, key) != |
| entry.data.i32 + entry.count; |
| } |
| return false; |
| } |
| |
| std::set<uint8_t> Camera3Device::StaticInfo::GetAvailableModes( |
| int32_t key, int32_t min_value, int32_t max_value) const { |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry(characteristics_, key, &entry) != 0) { |
| ADD_FAILURE() << "Cannot find the metadata " |
| << get_camera_metadata_tag_name(key); |
| return std::set<uint8_t>(); |
| } |
| std::set<uint8_t> modes; |
| for (size_t i = 0; i < entry.count; i++) { |
| uint8_t mode = entry.data.u8[i]; |
| // Each element must be distinct |
| EXPECT_TRUE(modes.find(mode) == modes.end()) |
| << "Duplicate modes " << mode << " for the metadata " |
| << get_camera_metadata_tag_name(key); |
| EXPECT_TRUE(mode >= min_value && mode <= max_value) |
| << "Mode " << mode << " is outside of [" << min_value << "," |
| << max_value << "] for the metadata " |
| << get_camera_metadata_tag_name(key); |
| modes.insert(mode); |
| } |
| return modes; |
| } |
| |
| std::set<uint8_t> Camera3Device::StaticInfo::GetAvailableEdgeModes() const { |
| std::set<uint8_t> modes = GetAvailableModes( |
| ANDROID_EDGE_AVAILABLE_EDGE_MODES, ANDROID_EDGE_MODE_OFF, |
| ANDROID_EDGE_MODE_ZERO_SHUTTER_LAG); |
| |
| // Full device should always include OFF and FAST |
| if (IsHardwareLevelAtLeastFull()) { |
| EXPECT_TRUE((modes.find(ANDROID_EDGE_MODE_OFF) != modes.end()) && |
| (modes.find(ANDROID_EDGE_MODE_FAST) != modes.end())) |
| << "Full device must contain OFF and FAST edge modes"; |
| } |
| |
| // FAST and HIGH_QUALITY mode must be both present or both not present |
| EXPECT_TRUE((modes.find(ANDROID_EDGE_MODE_FAST) != modes.end()) == |
| (modes.find(ANDROID_EDGE_MODE_HIGH_QUALITY) != modes.end())) |
| << "FAST and HIGH_QUALITY mode must both present or both not present"; |
| |
| return modes; |
| } |
| |
| std::set<uint8_t> Camera3Device::StaticInfo::GetAvailableNoiseReductionModes() |
| const { |
| std::set<uint8_t> modes = |
| GetAvailableModes(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES, |
| ANDROID_NOISE_REDUCTION_MODE_OFF, |
| ANDROID_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG); |
| |
| // Full device should always include OFF and FAST |
| if (IsHardwareLevelAtLeastFull()) { |
| EXPECT_TRUE((modes.find(ANDROID_NOISE_REDUCTION_MODE_OFF) != modes.end()) && |
| (modes.find(ANDROID_NOISE_REDUCTION_MODE_FAST) != modes.end())) |
| << "Full device must contain OFF and FAST noise reduction modes"; |
| } |
| |
| // FAST and HIGH_QUALITY mode must be both present or both not present |
| EXPECT_TRUE( |
| (modes.find(ANDROID_NOISE_REDUCTION_MODE_FAST) != modes.end()) == |
| (modes.find(ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY) != modes.end())) |
| << "FAST and HIGH_QUALITY mode must both present or both not present"; |
| |
| return modes; |
| } |
| |
| std::set<uint8_t> Camera3Device::StaticInfo::GetAvailableColorAberrationModes() |
| const { |
| std::set<uint8_t> modes = |
| GetAvailableModes(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, |
| ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF, |
| ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY); |
| |
| EXPECT_TRUE((modes.find(ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF) != |
| modes.end()) || |
| (modes.find(ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST) != |
| modes.end())) |
| << "Camera devices must always support either OFF or FAST mode"; |
| |
| // FAST and HIGH_QUALITY mode must be both present or both not present |
| EXPECT_TRUE( |
| (modes.find(ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST) != |
| modes.end()) == |
| (modes.find(ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY) != |
| modes.end())) |
| << "FAST and HIGH_QUALITY mode must both present or both not present"; |
| |
| return modes; |
| } |
| |
| std::set<uint8_t> Camera3Device::StaticInfo::GetAvailableToneMapModes() const { |
| std::set<uint8_t> modes = GetAvailableModes( |
| ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES, |
| ANDROID_TONEMAP_MODE_CONTRAST_CURVE, ANDROID_TONEMAP_MODE_PRESET_CURVE); |
| |
| EXPECT_TRUE(modes.find(ANDROID_TONEMAP_MODE_FAST) != modes.end()) |
| << "Camera devices must always support FAST mode"; |
| |
| // FAST and HIGH_QUALITY mode must be both present |
| EXPECT_TRUE(modes.find(ANDROID_TONEMAP_MODE_HIGH_QUALITY) != modes.end()) |
| << "FAST and HIGH_QUALITY mode must both present"; |
| |
| return modes; |
| } |
| |
| std::set<std::pair<int32_t, int32_t>> |
| Camera3Device::StaticInfo::GetAvailableFpsRanges() const { |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry( |
| characteristics_, ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, |
| &entry) != 0) { |
| ADD_FAILURE() << "Cannot find the metadata " |
| "ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES"; |
| return {}; |
| } |
| if (entry.count % 2 != 0) { |
| ADD_FAILURE() << "Unexpected amount of entries of " |
| "ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES"; |
| return {}; |
| } |
| std::set<std::pair<int32_t, int32_t>> available_fps_ranges; |
| for (size_t i = 0; i < entry.count; i += 2) { |
| int32_t min_fps = entry.data.i32[i]; |
| int32_t max_fps = entry.data.i32[i + 1]; |
| available_fps_ranges.insert({min_fps, max_fps}); |
| } |
| return available_fps_ranges; |
| } |
| |
| void Camera3Device::StaticInfo::GetStreamConfigEntry( |
| camera_metadata_ro_entry_t* entry) const { |
| entry->count = 0; |
| |
| camera_metadata_ro_entry_t local_entry = {}; |
| ASSERT_EQ( |
| 0, find_camera_metadata_ro_entry( |
| characteristics_, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, |
| &local_entry)) |
| << "Fail to find metadata key " |
| "ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS"; |
| ASSERT_NE(0u, local_entry.count) << "Camera stream configuration is empty"; |
| ASSERT_EQ(0u, local_entry.count % kNumOfElementsInStreamConfigEntry) |
| << "Camera stream configuration parsing error"; |
| *entry = local_entry; |
| } |
| |
| std::set<int32_t> Camera3Device::StaticInfo::GetAvailableFormats( |
| int32_t direction) const { |
| camera_metadata_ro_entry_t available_config = {}; |
| GetStreamConfigEntry(&available_config); |
| std::set<int32_t> formats; |
| for (size_t i = 0; i < available_config.count; |
| i += kNumOfElementsInStreamConfigEntry) { |
| int32_t format = available_config.data.i32[i + STREAM_CONFIG_FORMAT_INDEX]; |
| int32_t in_or_out = |
| available_config.data.i32[i + STREAM_CONFIG_DIRECTION_INDEX]; |
| if (in_or_out == direction) { |
| formats.insert(format); |
| } |
| } |
| return formats; |
| } |
| |
| bool Camera3Device::StaticInfo::IsFormatAvailable(int format) const { |
| camera_metadata_ro_entry_t available_config = {}; |
| GetStreamConfigEntry(&available_config); |
| for (uint32_t i = 0; i < available_config.count; |
| i += kNumOfElementsInStreamConfigEntry) { |
| if (available_config.data.i32[i + STREAM_CONFIG_FORMAT_INDEX] == format) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| std::vector<ResolutionInfo> |
| Camera3Device::StaticInfo::GetSortedOutputResolutions(int32_t format) const { |
| return GetSortedResolutions(format, true); |
| } |
| |
| std::vector<ResolutionInfo> |
| Camera3Device::StaticInfo::GetSortedInputResolutions(int32_t format) const { |
| return GetSortedResolutions(format, false); |
| } |
| |
| std::vector<ResolutionInfo> Camera3Device::StaticInfo::GetSortedResolutions( |
| int32_t format, bool is_output) const { |
| camera_metadata_ro_entry_t available_config = {}; |
| GetStreamConfigEntry(&available_config); |
| std::vector<ResolutionInfo> available_resolutions; |
| const int32_t direction = |
| is_output ? ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT |
| : ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT; |
| for (uint32_t i = 0; i < available_config.count; |
| i += kNumOfElementsInStreamConfigEntry) { |
| int32_t fmt = available_config.data.i32[i + STREAM_CONFIG_FORMAT_INDEX]; |
| int32_t width = available_config.data.i32[i + STREAM_CONFIG_WIDTH_INDEX]; |
| int32_t height = available_config.data.i32[i + STREAM_CONFIG_HEIGHT_INDEX]; |
| int32_t in_or_out = |
| available_config.data.i32[i + STREAM_CONFIG_DIRECTION_INDEX]; |
| if (fmt == format && in_or_out == direction) { |
| available_resolutions.emplace_back(width, height); |
| } |
| } |
| std::sort(available_resolutions.begin(), available_resolutions.end()); |
| return available_resolutions; |
| } |
| |
| bool Camera3Device::StaticInfo::GetInputOutputConfigurationMap( |
| std::map<int32_t, std::vector<int32_t>>* config_map) const { |
| camera_metadata_ro_entry_t entry = {}; |
| if (find_camera_metadata_ro_entry( |
| characteristics_, ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP, |
| &entry)) { |
| ADD_FAILURE() << "Cannot find the metadata " |
| "ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP"; |
| return false; |
| } |
| |
| /* format of the map is : input format, num_output_formats, |
| * outputFormat1,..,outputFormatN */ |
| uint32_t num_out; |
| const int32_t* p = entry.data.i32; |
| for (const int32_t* end = p + entry.count; p < end; p += num_out) { |
| int32_t in_format = *(p++); |
| num_out = *(p++); |
| config_map->emplace(std::piecewise_construct, |
| std::forward_as_tuple(in_format), |
| std::forward_as_tuple(p, p + num_out)); |
| } |
| return true; |
| } |
| |
| bool Camera3Device::StaticInfo::IsAELockSupported() const { |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry( |
| characteristics_, ANDROID_CONTROL_AE_LOCK_AVAILABLE, &entry) != 0) { |
| ADD_FAILURE() |
| << "Cannot find the metadata ANDROID_CONTROL_AE_LOCK_AVAILABLE"; |
| return false; |
| } |
| return entry.data.u8[0] == ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE; |
| } |
| |
| bool Camera3Device::StaticInfo::IsAWBLockSupported() const { |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry( |
| characteristics_, ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &entry) != 0) { |
| ADD_FAILURE() |
| << "Cannot find the metadata ANDROID_CONTROL_AWB_LOCK_AVAILABLE"; |
| return false; |
| } |
| return entry.data.u8[0] == ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE; |
| } |
| |
| int32_t Camera3Device::StaticInfo::GetPartialResultCount() const { |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry(characteristics_, |
| ANDROID_REQUEST_PARTIAL_RESULT_COUNT, |
| &entry) != 0) { |
| // Optional key. Default value is 1 if key is missing. |
| return 1; |
| } |
| return entry.data.i32[0]; |
| } |
| |
| uint8_t Camera3Device::StaticInfo::GetRequestPipelineMaxDepth() const { |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry( |
| characteristics_, ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &entry) != 0) { |
| ADD_FAILURE() |
| << "Cannot find the metadata ANDROID_REQUEST_PIPELINE_MAX_DEPTH"; |
| return -EINVAL; |
| } |
| return entry.data.u8[0]; |
| } |
| |
| int32_t Camera3Device::StaticInfo::GetJpegMaxSize() const { |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry(characteristics_, ANDROID_JPEG_MAX_SIZE, |
| &entry) != 0) { |
| ADD_FAILURE() << "Cannot find the metadata ANDROID_JPEG_MAX_SIZE"; |
| return -EINVAL; |
| } |
| return entry.data.i32[0]; |
| } |
| |
| int32_t Camera3Device::StaticInfo::GetSensorOrientation() const { |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry(characteristics_, |
| ANDROID_SENSOR_ORIENTATION, &entry) != 0) { |
| ADD_FAILURE() << "Cannot find the metadata ANDROID_SENSOR_ORIENTATION"; |
| return -EINVAL; |
| } |
| return entry.data.i32[0]; |
| } |
| |
| int32_t Camera3Device::StaticInfo::GetAvailableThumbnailSizes( |
| std::vector<ResolutionInfo>* resolutions) const { |
| const size_t kNumOfEntriesForSize = 2; |
| enum { WIDTH_ENTRY_INDEX, HEIGHT_ENTRY_INDEX }; |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry(characteristics_, |
| ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, |
| &entry) != 0) { |
| ADD_FAILURE() |
| << "Cannot find the metadata ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES"; |
| return -EINVAL; |
| } |
| if (entry.count % kNumOfEntriesForSize) { |
| ADD_FAILURE() << "Camera JPEG available thumbnail sizes parsing error"; |
| return -EINVAL; |
| } |
| for (size_t i = 0; i < entry.count; i += kNumOfEntriesForSize) { |
| resolutions->emplace_back(entry.data.i32[i + WIDTH_ENTRY_INDEX], |
| entry.data.i32[i + HEIGHT_ENTRY_INDEX]); |
| } |
| return 0; |
| } |
| |
| int32_t Camera3Device::StaticInfo::GetAvailableFocalLengths( |
| std::vector<float>* focal_lengths) const { |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry(characteristics_, |
| ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, |
| &entry) != 0) { |
| ADD_FAILURE() |
| << "Cannot find the metadata ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS"; |
| return -EINVAL; |
| } |
| if (entry.count == 0) { |
| ADD_FAILURE() << "There should be at least one available focal length"; |
| return -EINVAL; |
| } |
| for (size_t i = 0; i < entry.count; i++) { |
| EXPECT_LT(0.0f, entry.data.f[i]) |
| << "Available focal length " << entry.data.f[i] |
| << " should be positive"; |
| focal_lengths->push_back(entry.data.f[i]); |
| } |
| EXPECT_EQ( |
| focal_lengths->size(), |
| std::set<float>(focal_lengths->begin(), focal_lengths->end()).size()) |
| << "Avaliable focal lengths should be distinct"; |
| return 0; |
| } |
| |
| int32_t Camera3Device::StaticInfo::GetAvailableApertures( |
| std::vector<float>* apertures) const { |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry(characteristics_, |
| ANDROID_LENS_INFO_AVAILABLE_APERTURES, |
| &entry) != 0) { |
| ADD_FAILURE() |
| << "Cannot find the metadata ANDROID_LENS_INFO_AVAILABLE_APERTURES"; |
| return -EINVAL; |
| } |
| if (entry.count == 0) { |
| ADD_FAILURE() << "There should be at least one available apertures"; |
| return -EINVAL; |
| } |
| for (size_t i = 0; i < entry.count; i++) { |
| EXPECT_LT(0.0f, entry.data.f[i]) |
| << "Available apertures " << entry.data.f[i] << " should be positive"; |
| apertures->push_back(entry.data.f[i]); |
| } |
| EXPECT_EQ(apertures->size(), |
| std::set<float>(apertures->begin(), apertures->end()).size()) |
| << "Avaliable apertures should be distinct"; |
| return 0; |
| } |
| |
| int32_t Camera3Device::StaticInfo::GetAvailableAFModes( |
| std::vector<uint8_t>* af_modes) const { |
| camera_metadata_ro_entry_t entry; |
| if (find_camera_metadata_ro_entry( |
| characteristics_, ANDROID_CONTROL_AF_AVAILABLE_MODES, &entry) == 0) { |
| for (size_t i = 0; i < entry.count; i++) { |
| af_modes->push_back(entry.data.u8[i]); |
| } |
| } |
| return 0; |
| } |
| |
| int32_t Camera3Device::StaticInfo::GetAvailableTestPatternModes( |
| std::vector<int32_t>* test_pattern_modes) const { |
| camera_metadata_ro_entry_t entry; |
| int32_t result = find_camera_metadata_ro_entry( |
| characteristics_, ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, &entry); |
| if (result == 0) { |
| for (size_t i = 0; i < entry.count; i++) { |
| test_pattern_modes->push_back(entry.data.i32[i]); |
| } |
| } |
| return result; |
| } |
| |
| int32_t Camera3Device::StaticInfo::GetAvailableFaceDetectModes( |
| std::set<uint8_t>* face_detect_modes) const { |
| camera_metadata_ro_entry_t entry; |
| int32_t result = find_camera_metadata_ro_entry( |
| characteristics_, ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, |
| &entry); |
| if (result == 0) { |
| for (size_t i = 0; i < entry.count; i++) { |
| face_detect_modes->insert(entry.data.u8[i]); |
| } |
| } |
| return result; |
| } |
| |
| int32_t Camera3Device::StaticInfo::GetAeMaxRegions() const { |
| constexpr size_t kMaxRegionsAeIdx = 0; |
| camera_metadata_ro_entry_t entry; |
| int32_t result = find_camera_metadata_ro_entry( |
| characteristics_, ANDROID_CONTROL_MAX_REGIONS, &entry); |
| return (result == 0 && entry.count > kMaxRegionsAeIdx) |
| ? entry.data.i32[kMaxRegionsAeIdx] |
| : 0; |
| } |
| |
| int32_t Camera3Device::StaticInfo::GetAwbMaxRegions() const { |
| constexpr size_t kMaxRegionsAwbIdx = 1; |
| camera_metadata_ro_entry_t entry; |
| int32_t result = find_camera_metadata_ro_entry( |
| characteristics_, ANDROID_CONTROL_MAX_REGIONS, &entry); |
| return (result == 0 && entry.count > kMaxRegionsAwbIdx) |
| ? entry.data.i32[kMaxRegionsAwbIdx] |
| : 0; |
| } |
| |
| int32_t Camera3Device::StaticInfo::GetAfMaxRegions() const { |
| constexpr size_t kMaxRegionsAfIdx = 2; |
| camera_metadata_ro_entry_t entry; |
| int32_t result = find_camera_metadata_ro_entry( |
| characteristics_, ANDROID_CONTROL_MAX_REGIONS, &entry); |
| return (result == 0 && entry.count > kMaxRegionsAfIdx) |
| ? entry.data.i32[kMaxRegionsAfIdx] |
| : 0; |
| } |
| |
| int32_t Camera3Device::StaticInfo::GetSensorPixelArraySize( |
| uint32_t* width, uint32_t* height) const { |
| if (!width || !height) { |
| return -EINVAL; |
| } |
| camera_metadata_ro_entry_t entry; |
| int32_t result = find_camera_metadata_ro_entry( |
| characteristics_, ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, &entry); |
| if (result == 0 && entry.count == 2) { |
| *width = entry.data.i32[0]; |
| *height = entry.data.i32[1]; |
| } else if (result == 0) { |
| return -ENOENT; |
| } |
| return result; |
| } |
| |
| std::set<int32_t> Camera3Device::StaticInfo::GetAvailableRequestKeys() const { |
| camera_metadata_ro_entry_t entry = {}; |
| if (find_camera_metadata_ro_entry(characteristics_, |
| ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, |
| &entry) != 0 || |
| entry.count == 0) { |
| ADD_FAILURE() << "Fail to find metadata key " |
| "ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS"; |
| return std::set<int32_t>(); |
| } |
| return std::set<int32_t>(entry.data.i32, entry.data.i32 + entry.count); |
| } |
| |
| // Test fixture |
| |
| void Camera3DeviceFixture::SetUp() { |
| ASSERT_EQ(0, cam_device_.Initialize(&cam_module_)) |
| << "Camera device initialization fails"; |
| cam_device_.RegisterResultMetadataOutputBufferCallback( |
| base::Bind(&Camera3DeviceFixture::ProcessResultMetadataOutputBuffers, |
| base::Unretained(this))); |
| cam_device_.RegisterPartialMetadataCallback(base::Bind( |
| &Camera3DeviceFixture::ProcessPartialMetadata, base::Unretained(this))); |
| } |
| |
| void Camera3DeviceFixture::TearDown() { |
| cam_device_.Destroy(); |
| } |
| |
| // Test cases |
| |
| // Test spec: |
| // - Camera ID |
| class Camera3DeviceSimpleTest : public Camera3DeviceFixture, |
| public ::testing::WithParamInterface<int> { |
| public: |
| Camera3DeviceSimpleTest() : Camera3DeviceFixture(GetParam()) {} |
| }; |
| |
| TEST_P(Camera3DeviceSimpleTest, SensorOrientationTest) { |
| // Chromebook has a hardware requirement that the top of the camera should |
| // match the top of the display in tablet mode. |
| ASSERT_EQ(0, cam_device_.GetStaticInfo()->GetSensorOrientation()) |
| << "Invalid camera sensor orientation"; |
| } |
| |
| // Test spec: |
| // - Camera ID |
| // - Capture type |
| class Camera3DeviceDefaultSettings |
| : public Camera3DeviceFixture, |
| public ::testing::WithParamInterface<std::tuple<int, int>> { |
| public: |
| Camera3DeviceDefaultSettings() |
| : Camera3DeviceFixture(std::get<0>(GetParam())) {} |
| }; |
| |
| static bool IsMetadataKeyAvailable(const camera_metadata_t* settings, |
| int32_t key) { |
| camera_metadata_ro_entry_t entry; |
| return find_camera_metadata_ro_entry(settings, key, &entry) == 0; |
| } |
| |
| static void ExpectKeyValue(const camera_metadata_t* settings, |
| int32_t key, |
| const char* key_name, |
| int32_t value, |
| int32_t compare_type) { |
| camera_metadata_ro_entry_t entry; |
| ASSERT_EQ(0, find_camera_metadata_ro_entry(settings, key, &entry)) |
| << "Cannot find the metadata " << key_name; |
| if (compare_type == 0) { |
| ASSERT_EQ(value, entry.data.i32[0]) |
| << "Wrong value of metadata " << key_name; |
| } else { |
| ASSERT_NE(value, entry.data.i32[0]) |
| << "Wrong value of metadata " << key_name; |
| } |
| } |
| #define EXPECT_KEY_VALUE_EQ(settings, key, value) \ |
| ExpectKeyValue(settings, key, #key, value, 0) |
| #define EXPECT_KEY_VALUE_NE(settings, key, value) \ |
| ExpectKeyValue(settings, key, #key, value, 1) |
| |
| static void ExpectKeyValueNotEqualsI64(const camera_metadata_t* settings, |
| int32_t key, |
| const char* key_name, |
| int64_t value) { |
| camera_metadata_ro_entry_t entry; |
| ASSERT_EQ(0, find_camera_metadata_ro_entry(settings, key, &entry)) |
| << "Cannot find the metadata " << key_name; |
| ASSERT_NE(value, entry.data.i64[0]) << "Wrong value of metadata " << key_name; |
| } |
| #define EXPECT_KEY_VALUE_NE_I64(settings, key, value) \ |
| ExpectKeyValueNotEqualsI64(settings, key, #key, value) |
| |
| TEST_P(Camera3DeviceDefaultSettings, ConstructDefaultSettings) { |
| int type = std::get<1>(GetParam()); |
| auto static_info = cam_device_.GetStaticInfo(); |
| |
| const camera_metadata_t* default_settings; |
| default_settings = cam_device_.ConstructDefaultRequestSettings(type); |
| if (!default_settings) { |
| if (type == CAMERA3_TEMPLATE_MANUAL && |
| !static_info->IsCapabilitySupported( |
| ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) { |
| return; |
| } else if ( |
| type == CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG && |
| !static_info->IsCapabilitySupported( |
| ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING)) { |
| return; |
| } |
| } |
| ASSERT_NE(nullptr, default_settings) << "Camera default settings are NULL"; |
| |
| // Reference: camera2/cts/CameraDeviceTest.java#captureTemplateTestByCamera |
| if (!cam_device_.IsTemplateSupported(type)) { |
| return; |
| } else if (type != CAMERA3_TEMPLATE_PREVIEW && |
| static_info->IsDepthOutputSupported() && |
| !static_info->IsColorOutputSupported()) { |
| // Depth-only devices need only support PREVIEW template |
| return; |
| } |
| |
| // Reference: camera2/cts/CameraDeviceTest.java#checkRequestForTemplate |
| // 3A settings--control mode |
| if (type == CAMERA3_TEMPLATE_MANUAL) { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_CONTROL_MODE, |
| ANDROID_CONTROL_MODE_OFF); |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_CONTROL_AE_MODE, |
| ANDROID_CONTROL_AE_MODE_OFF); |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_CONTROL_AWB_MODE, |
| ANDROID_CONTROL_AWB_MODE_OFF); |
| } else { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_CONTROL_AE_MODE, |
| ANDROID_CONTROL_AE_MODE_ON); |
| |
| EXPECT_KEY_VALUE_EQ(default_settings, |
| ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, 0); |
| |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, |
| ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE); |
| |
| // if AE lock is not supported, expect the control key to be non-existent or |
| // false |
| if (static_info->IsAELockSupported() || |
| IsMetadataKeyAvailable(default_settings, ANDROID_CONTROL_AE_LOCK)) { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_CONTROL_AE_LOCK, |
| ANDROID_CONTROL_AE_LOCK_OFF); |
| } |
| |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_CONTROL_AF_TRIGGER, |
| ANDROID_CONTROL_AF_TRIGGER_IDLE); |
| |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_CONTROL_AWB_MODE, |
| ANDROID_CONTROL_AWB_MODE_AUTO); |
| |
| // if AWB lock is not supported, expect the control key to be non-existent |
| // or false |
| if (static_info->IsAWBLockSupported() || |
| IsMetadataKeyAvailable(default_settings, ANDROID_CONTROL_AWB_LOCK)) { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_CONTROL_AWB_LOCK, |
| ANDROID_CONTROL_AWB_LOCK_OFF); |
| } |
| |
| // Check 3A regions |
| // TODO(hywu): CONTROL_AE_REGIONS, CONTROL_AWB_REGIONS, CONTROL_AF_REGIONS? |
| } |
| |
| // Sensor settings |
| // TODO(hywu): LENS_APERTURE, LENS_FILTER_DENSITY, LENS_FOCAL_LENGTH, |
| // LENS_OPTICAL_STABILIZATION_MODE? |
| // BLACK_LEVEL_LOCK? |
| |
| if (static_info->IsKeyAvailable(ANDROID_BLACK_LEVEL_LOCK)) { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_BLACK_LEVEL_LOCK, |
| ANDROID_BLACK_LEVEL_LOCK_OFF); |
| } |
| |
| if (static_info->IsKeyAvailable(ANDROID_SENSOR_FRAME_DURATION)) { |
| EXPECT_KEY_VALUE_NE_I64(default_settings, ANDROID_SENSOR_FRAME_DURATION, 0); |
| } |
| |
| if (static_info->IsKeyAvailable(ANDROID_SENSOR_EXPOSURE_TIME)) { |
| EXPECT_KEY_VALUE_NE_I64(default_settings, ANDROID_SENSOR_EXPOSURE_TIME, 0); |
| } |
| |
| if (static_info->IsKeyAvailable(ANDROID_SENSOR_SENSITIVITY)) { |
| EXPECT_KEY_VALUE_NE(default_settings, ANDROID_SENSOR_SENSITIVITY, 0); |
| } |
| |
| // ISP-processing settings |
| |
| // CTS expects the default mode is OFF. |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_STATISTICS_FACE_DETECT_MODE, |
| ANDROID_STATISTICS_FACE_DETECT_MODE_OFF); |
| |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_FLASH_MODE, |
| ANDROID_FLASH_MODE_OFF); |
| |
| if (static_info->IsKeyAvailable(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE)) { |
| // If the device doesn't support RAW, all template should have OFF as |
| // default |
| if (!static_info->IsCapabilitySupported( |
| ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW)) { |
| EXPECT_KEY_VALUE_EQ(default_settings, |
| ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, |
| ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF); |
| } |
| } |
| |
| bool support_reprocessing = |
| static_info->IsCapabilitySupported( |
| ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING) || |
| static_info->IsCapabilitySupported( |
| ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING); |
| |
| if (type == CAMERA3_TEMPLATE_STILL_CAPTURE) { |
| // Not enforce high quality here, as some devices may not effectively have |
| // high quality mode |
| if (static_info->IsKeyAvailable(ANDROID_COLOR_CORRECTION_MODE)) { |
| EXPECT_KEY_VALUE_NE(default_settings, ANDROID_COLOR_CORRECTION_MODE, |
| ANDROID_COLOR_CORRECTION_MODE_TRANSFORM_MATRIX); |
| } |
| |
| // Edge enhancement, noise reduction and aberration correction modes. |
| EXPECT_EQ(IsMetadataKeyAvailable(default_settings, ANDROID_EDGE_MODE), |
| static_info->IsKeyAvailable(ANDROID_EDGE_AVAILABLE_EDGE_MODES)) |
| << "Edge mode must be present in request if available edge modes are " |
| "present in metadata, and vice-versa"; |
| if (static_info->IsKeyAvailable(ANDROID_EDGE_MODE)) { |
| std::set<uint8_t> edge_modes = static_info->GetAvailableEdgeModes(); |
| // Don't need check fast as fast or high quality must be both present or |
| // both not. |
| if (edge_modes.find(ANDROID_EDGE_MODE_HIGH_QUALITY) != edge_modes.end()) { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_EDGE_MODE, |
| ANDROID_EDGE_MODE_HIGH_QUALITY); |
| } else { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_EDGE_MODE, |
| ANDROID_EDGE_MODE_OFF); |
| } |
| } |
| |
| EXPECT_EQ( |
| IsMetadataKeyAvailable(default_settings, ANDROID_NOISE_REDUCTION_MODE), |
| static_info->IsKeyAvailable( |
| ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES)) |
| << "Noise reduction mode must be present in request if available noise " |
| "reductions are present in metadata, and vice-versa"; |
| if (static_info->IsKeyAvailable( |
| ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES)) { |
| std::set<uint8_t> nr_modes = |
| static_info->GetAvailableNoiseReductionModes(); |
| // Don't need check fast as fast or high quality must be both present or |
| // both not |
| if (nr_modes.find(ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY) != |
| nr_modes.end()) { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_NOISE_REDUCTION_MODE, |
| ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY); |
| } else { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_NOISE_REDUCTION_MODE, |
| ANDROID_NOISE_REDUCTION_MODE_OFF); |
| } |
| } |
| |
| EXPECT_EQ(IsMetadataKeyAvailable(default_settings, |
| ANDROID_COLOR_CORRECTION_ABERRATION_MODE), |
| static_info->IsKeyAvailable( |
| ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES)) |
| << "Aberration correction mode must be present in request if available " |
| "aberration correction reductions are present in metadata, and " |
| "vice-versa"; |
| if (static_info->IsKeyAvailable(ANDROID_COLOR_CORRECTION_ABERRATION_MODE)) { |
| std::set<uint8_t> aberration_modes = |
| static_info->GetAvailableColorAberrationModes(); |
| // Don't need check fast as fast or high quality must be both present or |
| // both not |
| if (aberration_modes.find( |
| ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY) != |
| aberration_modes.end()) { |
| EXPECT_KEY_VALUE_EQ( |
| default_settings, ANDROID_COLOR_CORRECTION_ABERRATION_MODE, |
| ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY); |
| } else { |
| EXPECT_KEY_VALUE_EQ(default_settings, |
| ANDROID_COLOR_CORRECTION_ABERRATION_MODE, |
| ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF); |
| } |
| } |
| } else if (type == CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG && |
| support_reprocessing) { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_EDGE_MODE, |
| ANDROID_EDGE_MODE_ZERO_SHUTTER_LAG); |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_NOISE_REDUCTION_MODE, |
| ANDROID_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG); |
| } else if (type == CAMERA3_TEMPLATE_PREVIEW || |
| type == CAMERA3_TEMPLATE_VIDEO_RECORD) { |
| if (static_info->IsKeyAvailable(ANDROID_EDGE_MODE)) { |
| std::set<uint8_t> edge_modes = static_info->GetAvailableEdgeModes(); |
| if (edge_modes.find(ANDROID_EDGE_MODE_FAST) != edge_modes.end()) { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_EDGE_MODE, |
| ANDROID_EDGE_MODE_FAST); |
| } else { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_EDGE_MODE, |
| ANDROID_EDGE_MODE_OFF); |
| } |
| } |
| |
| if (static_info->IsKeyAvailable(ANDROID_NOISE_REDUCTION_MODE)) { |
| std::set<uint8_t> nr_modes = |
| static_info->GetAvailableNoiseReductionModes(); |
| if (nr_modes.find(ANDROID_NOISE_REDUCTION_MODE_FAST) != nr_modes.end()) { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_NOISE_REDUCTION_MODE, |
| ANDROID_NOISE_REDUCTION_MODE_FAST); |
| } else { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_NOISE_REDUCTION_MODE, |
| ANDROID_NOISE_REDUCTION_MODE_OFF); |
| } |
| } |
| |
| if (static_info->IsKeyAvailable(ANDROID_COLOR_CORRECTION_ABERRATION_MODE)) { |
| std::set<uint8_t> aberration_modes = |
| static_info->GetAvailableColorAberrationModes(); |
| if (aberration_modes.find( |
| ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST) != |
| aberration_modes.end()) { |
| EXPECT_KEY_VALUE_EQ(default_settings, |
| ANDROID_COLOR_CORRECTION_ABERRATION_MODE, |
| ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST); |
| } else { |
| EXPECT_KEY_VALUE_EQ(default_settings, |
| ANDROID_COLOR_CORRECTION_ABERRATION_MODE, |
| ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF); |
| } |
| } |
| } else { |
| if (static_info->IsKeyAvailable(ANDROID_EDGE_MODE)) { |
| ASSERT_TRUE(IsMetadataKeyAvailable(default_settings, ANDROID_EDGE_MODE)); |
| } |
| |
| if (static_info->IsKeyAvailable(ANDROID_NOISE_REDUCTION_MODE)) { |
| ASSERT_TRUE(IsMetadataKeyAvailable(default_settings, |
| ANDROID_NOISE_REDUCTION_MODE)); |
| } |
| |
| if (static_info->IsKeyAvailable(ANDROID_COLOR_CORRECTION_ABERRATION_MODE)) { |
| ASSERT_TRUE(IsMetadataKeyAvailable( |
| default_settings, ANDROID_COLOR_CORRECTION_ABERRATION_MODE)); |
| } |
| } |
| |
| // Tone map and lens shading modes. |
| if (type == CAMERA3_TEMPLATE_STILL_CAPTURE) { |
| EXPECT_EQ( |
| IsMetadataKeyAvailable(default_settings, ANDROID_TONEMAP_MODE), |
| static_info->IsKeyAvailable(ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES)) |
| << "Tonemap mode must be present in request if available tonemap modes " |
| "are present in metadata, and vice-versa"; |
| if (static_info->IsKeyAvailable(ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES)) { |
| std::set<uint8_t> tone_map_modes = |
| static_info->GetAvailableToneMapModes(); |
| if (tone_map_modes.find(ANDROID_TONEMAP_MODE_HIGH_QUALITY) != |
| tone_map_modes.end()) { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_TONEMAP_MODE, |
| ANDROID_TONEMAP_MODE_HIGH_QUALITY); |
| } else { |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_TONEMAP_MODE, |
| ANDROID_TONEMAP_MODE_FAST); |
| } |
| } |
| |
| // Still capture template should have android.statistics.lensShadingMapMode |
| // ON when RAW capability is supported. |
| if (static_info->IsKeyAvailable(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE) && |
| static_info->IsCapabilitySupported( |
| ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW)) { |
| EXPECT_KEY_VALUE_EQ(default_settings, |
| ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, |
| ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_ON); |
| } |
| } else { |
| if (static_info->IsKeyAvailable(ANDROID_TONEMAP_MODE)) { |
| EXPECT_KEY_VALUE_NE(default_settings, ANDROID_TONEMAP_MODE, |
| ANDROID_TONEMAP_MODE_CONTRAST_CURVE); |
| EXPECT_KEY_VALUE_NE(default_settings, ANDROID_TONEMAP_MODE, |
| ANDROID_TONEMAP_MODE_GAMMA_VALUE); |
| EXPECT_KEY_VALUE_NE(default_settings, ANDROID_TONEMAP_MODE, |
| ANDROID_TONEMAP_MODE_PRESET_CURVE); |
| } |
| if (static_info->IsKeyAvailable(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE)) { |
| EXPECT_KEY_VALUE_NE(default_settings, |
| ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, 0); |
| } |
| } |
| |
| EXPECT_KEY_VALUE_EQ(default_settings, ANDROID_CONTROL_CAPTURE_INTENT, type); |
| } |
| |
| // Test spec: |
| // - Camera ID |
| // - Capture type |
| class CreateInvalidTemplate |
| : public Camera3DeviceFixture, |
| public ::testing::WithParamInterface<std::tuple<int, int>> { |
| public: |
| CreateInvalidTemplate() : Camera3DeviceFixture(std::get<0>(GetParam())) {} |
| }; |
| |
| TEST_P(CreateInvalidTemplate, ConstructDefaultSettings) { |
| // Reference: |
| // camera2/cts/CameraDeviceTest.java#testCameraDeviceCreateCaptureBuilder |
| int type = std::get<1>(GetParam()); |
| ASSERT_EQ(nullptr, cam_device_.ConstructDefaultRequestSettings(type)) |
| << "Should get error due to an invalid template ID"; |
| } |
| |
| // Test spec: |
| // - Camera ID |
| class Camera3AlgoSandboxIPCErrorTest |
| : public Camera3DeviceFixture, |
| public ::testing::WithParamInterface<int> { |
| public: |
| const uint32_t kDefaultTimeoutMs = 1000; |
| |
| Camera3AlgoSandboxIPCErrorTest() |
| : Camera3DeviceFixture(GetParam()), cam_id_(GetParam()) {} |
| |
| void SetUp() override; |
| |
| protected: |
| void Notify(const camera3_notify_msg* msg); |
| |
| int cam_id_; |
| |
| sem_t ipc_error_sem_; |
| }; |
| |
| void Camera3AlgoSandboxIPCErrorTest::SetUp() { |
| Camera3DeviceFixture::SetUp(); |
| cam_device_.RegisterNotifyCallback(base::Bind( |
| &Camera3AlgoSandboxIPCErrorTest::Notify, base::Unretained(this))); |
| sem_init(&ipc_error_sem_, 0, 0); |
| } |
| |
| void Camera3AlgoSandboxIPCErrorTest::Notify(const camera3_notify_msg* msg) { |
| VLOGF_ENTER(); |
| EXPECT_EQ(CAMERA3_MSG_ERROR, msg->type) |
| << "Unexpected message type " << msg->type << " is notified"; |
| EXPECT_EQ(CAMERA3_MSG_ERROR_DEVICE, msg->message.error.error_code) |
| << "Unexpected error code " << msg->message.error.error_code |
| << " is notified"; |
| sem_post(&ipc_error_sem_); |
| } |
| |
| TEST_P(Camera3AlgoSandboxIPCErrorTest, IPCErrorBeforeOpen) { |
| cam_device_.Destroy(); |
| (void)system("stop cros-camera-algo"); |
| ASSERT_EQ(nullptr, cam_module_.OpenDevice(cam_id_)) |
| << "Camera device should not be opened successfully"; |
| |
| (void)system("start cros-camera-algo"); |
| ASSERT_EQ(0, cam_device_.Initialize(&cam_module_)) |
| << "Camera device initialization fails"; |
| } |
| |
| TEST_P(Camera3AlgoSandboxIPCErrorTest, IPCErrorAfterOpen) { |
| (void)system("stop cros-camera-algo"); |
| struct timespec timeout; |
| memset(&timeout, 0, sizeof(timeout)); |
| if (clock_gettime(CLOCK_REALTIME, &timeout)) { |
| LOG(ERROR) << "Failed to get clock time"; |
| } |
| timeout.tv_sec += kDefaultTimeoutMs / 1000; |
| timeout.tv_nsec += (kDefaultTimeoutMs % 1000) * 1000; |
| ASSERT_EQ(0, sem_timedwait(&ipc_error_sem_, &timeout)); |
| |
| (void)system("start cros-camera-algo"); |
| cam_device_.Destroy(); |
| ASSERT_EQ(0, cam_device_.Initialize(&cam_module_)) |
| << "Camera device initialization fails"; |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(Camera3DeviceTest, |
| Camera3DeviceSimpleTest, |
| ::testing::ValuesIn(Camera3Module().GetCameraIds())); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| Camera3DeviceTest, |
| Camera3DeviceDefaultSettings, |
| ::testing::Combine(::testing::ValuesIn(Camera3Module().GetCameraIds()), |
| ::testing::Values(CAMERA3_TEMPLATE_PREVIEW, |
| CAMERA3_TEMPLATE_STILL_CAPTURE, |
| CAMERA3_TEMPLATE_VIDEO_RECORD, |
| CAMERA3_TEMPLATE_VIDEO_SNAPSHOT, |
| CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG, |
| CAMERA3_TEMPLATE_MANUAL))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| Camera3DeviceTest, |
| CreateInvalidTemplate, |
| ::testing::Combine(::testing::ValuesIn(Camera3Module().GetCameraIds()), |
| ::testing::Values(CAMERA3_TEMPLATE_PREVIEW - 1, |
| CAMERA3_TEMPLATE_MANUAL + 1))); |
| |
| INSTANTIATE_TEST_SUITE_P(Camera3DeviceTest, |
| Camera3AlgoSandboxIPCErrorTest, |
| ::testing::ValuesIn(Camera3Module().GetCameraIds())); |
| |
| } // namespace camera3_test |