3, /* PCM_FORMAT_S24_3LE */
};
-void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
+int proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
struct pcm_config * config)
{
+ int ret = 0;
+
ALOGV("proxy_prepare(c:%d, d:%d)", profile->card, profile->device);
proxy->profile = profile;
if (config->format != PCM_FORMAT_INVALID && profile_is_format_valid(profile, config->format)) {
proxy->alsa_config.format = config->format;
} else {
+ proxy->alsa_config.format = profile->default_config.format;
ALOGW("Invalid format %d - using default %d.",
config->format, profile->default_config.format);
- proxy->alsa_config.format = profile->default_config.format;
+ // Indicate override when default format was not requested
+ if (config->format != PCM_FORMAT_INVALID) {
+ ret = -EINVAL;
+ }
}
if (config->rate != 0 && profile_is_sample_rate_valid(profile, config->rate)) {
proxy->alsa_config.rate = config->rate;
} else {
+ proxy->alsa_config.rate = profile->default_config.rate;
ALOGW("Invalid sample rate %u - using default %u.",
config->rate, profile->default_config.rate);
- proxy->alsa_config.rate = profile->default_config.rate;
+ // Indicate override when default rate was not requested
+ if (config->rate != 0) {
+ ret = -EINVAL;
+ }
}
if (config->channels != 0 && profile_is_channel_count_valid(profile, config->channels)) {
proxy->alsa_config.channels = profile_get_closest_channel_count(profile, config->channels);
ALOGW("Invalid channel count %u - using closest %u.",
config->channels, proxy->alsa_config.channels);
+ // Indicate override when default channel count was not requested
+ if (config->channels != 0) {
+ ret = -EINVAL;
+ }
}
proxy->alsa_config.period_count = profile->default_config.period_count;
// us the highest working rate
int max_rate_index = proxy_scan_rates(proxy, profile->sample_rates);
if (max_rate_index >= 0) {
- proxy->alsa_config.rate = profile->sample_rates[max_rate_index];
+ if (proxy->alsa_config.rate > profile->sample_rates[max_rate_index]) {
+ ALOGW("Limiting samplnig rate from %u to %u.",
+ proxy->alsa_config.rate, profile->sample_rates[max_rate_index]);
+ proxy->alsa_config.rate = profile->sample_rates[max_rate_index];
+ ret = -EINVAL;
+ }
}
+ return ret;
}
int proxy_open(alsa_device_proxy * proxy)
};
for (size_t i = 0; i < sizeof(alignments)/sizeof(alignments[0]); ++i) {
- uintptr_t aligned_ptr = ALIGN_TO(metadata, alignments[i].alignment);
+ uintptr_t aligned_ptr = ALIGN_TO((uintptr_t) metadata + alignmentOffset,
+ alignments[i].alignment);
if ((uintptr_t)metadata + alignmentOffset != aligned_ptr) {
ALOGE("%s: Metadata pointer is not aligned (actual %p, "
- "expected %p) to type %s",
+ "expected %p, offset %" PRIuPTR ") to type %s",
__FUNCTION__, metadata,
- (void*)aligned_ptr, alignments[i].name);
+ (void*)aligned_ptr, alignmentOffset, alignments[i].name);
return CAMERA_METADATA_VALIDATION_ERROR;
}
}
}
}
}
+
+TEST(camera_metadata, buffer_alignment) {
+ // Verify that misaligned metadata buffers only fail VALIDATION_SHIFTED, nothing else
+ const size_t entry_capacity = 50;
+ const size_t data_capacity = 450;
+ const size_t offsetRange = 16;
+ const uint32_t validAlignment = 8;
+
+ camera_metadata_t *m = NULL;
+ m = allocate_camera_metadata(entry_capacity, data_capacity);
+
+ add_test_metadata(m, 15);
+
+ size_t m_size = get_camera_metadata_size(m);
+ size_t dst_size = m_size + offsetRange;
+ uint8_t *dst = new uint8_t[dst_size];
+
+ for (size_t i = 0; i < offsetRange; i++) {
+ memset(dst, 0, dst_size);
+ memcpy(dst + i, m, m_size);
+ camera_metadata_t *m_shifted = (camera_metadata_t*)(dst + i);
+
+ int err = validate_camera_metadata_structure(m_shifted, &m_size);
+ if (i % validAlignment == 0) {
+ ASSERT_EQ(OK, err) << "For alignment shift " << i << ", expected OK" ;
+ } else {
+ ASSERT_EQ(CAMERA_METADATA_VALIDATION_SHIFTED, err) <<
+ "For alignment shift " << i << ", expected VALIDATION_SHIFTED" ;
+ }
+ }
+
+ delete[] dst;
+ FINISH_USING_CAMERA_METADATA(m);
+}