Audio V4: Cast conversion now deduce both types

That avoids to repeat the destination type which
can change between versions.

Bug: 38184704
Test: compile
Change-Id: I55c881afe5f6fc511ea01b19c5d46de12fb1e0d2
Signed-off-by: Kevin Rocard <krocard@google.com>
diff --git a/audio/common/all-versions/default/Android.bp b/audio/common/all-versions/default/Android.bp
index 8f6b74c..4a27bb7 100644
--- a/audio/common/all-versions/default/Android.bp
+++ b/audio/common/all-versions/default/Android.bp
@@ -33,7 +33,11 @@
     ],
 
     header_libs: [
+        "android.hardware.audio.common.util@all-versions",
         "libaudio_system_headers",
         "libhardware_headers",
     ],
+    export_header_lib_headers: [
+        "android.hardware.audio.common.util@all-versions",
+    ]
 }
diff --git a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h
index 26ad518..d6f8d3e 100644
--- a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h
+++ b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h
@@ -18,6 +18,7 @@
 #error "AUDIO_HAL_VERSION must be set before including this file."
 #endif
 
+#include <common/all-versions/VersionUtils.h>
 #include <string.h>
 
 using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioChannelMask;
@@ -32,6 +33,8 @@
 using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioStreamType;
 using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioUsage;
 
+using ::android::hardware::audio::common::utils::mkEnumConverter;
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -40,7 +43,7 @@
 
 void HidlUtils::audioConfigFromHal(const audio_config_t& halConfig, AudioConfig* config) {
     config->sampleRateHz = halConfig.sample_rate;
-    config->channelMask = AudioChannelMask(halConfig.channel_mask);
+    config->channelMask = mkEnumConverter<AudioChannelMask>(halConfig.channel_mask);
     config->format = AudioFormat(halConfig.format);
     audioOffloadInfoFromHal(halConfig.offload_info, &config->offloadInfo);
     config->frameCount = halConfig.frame_count;
@@ -58,8 +61,8 @@
 void HidlUtils::audioGainConfigFromHal(const struct audio_gain_config& halConfig,
                                        AudioGainConfig* config) {
     config->index = halConfig.index;
-    config->mode = AudioGainMode(halConfig.mode);
-    config->channelMask = AudioChannelMask(halConfig.channel_mask);
+    config->mode = mkEnumConverter<AudioGainMode>(halConfig.mode);
+    config->channelMask = mkEnumConverter<AudioChannelMask>(halConfig.channel_mask);
     for (size_t i = 0; i < sizeof(audio_channel_mask_t) * 8; ++i) {
         config->values[i] = halConfig.values[i];
     }
@@ -79,8 +82,8 @@
 }
 
 void HidlUtils::audioGainFromHal(const struct audio_gain& halGain, AudioGain* gain) {
-    gain->mode = AudioGainMode(halGain.mode);
-    gain->channelMask = AudioChannelMask(halGain.channel_mask);
+    gain->mode = mkEnumConverter<AudioGainMode>(halGain.mode);
+    gain->channelMask = mkEnumConverter<AudioChannelMask>(halGain.channel_mask);
     gain->minValue = halGain.min_value;
     gain->maxValue = halGain.max_value;
     gain->defaultValue = halGain.default_value;
@@ -119,7 +122,7 @@
 void HidlUtils::audioOffloadInfoFromHal(const audio_offload_info_t& halOffload,
                                         AudioOffloadInfo* offload) {
     offload->sampleRateHz = halOffload.sample_rate;
-    offload->channelMask = AudioChannelMask(halOffload.channel_mask);
+    offload->channelMask = mkEnumConverter<AudioChannelMask>(halOffload.channel_mask);
     offload->format = AudioFormat(halOffload.format);
     offload->streamType = AudioStreamType(halOffload.stream_type);
     offload->bitRatePerSecond = halOffload.bit_rate;
@@ -152,9 +155,9 @@
     config->id = halConfig.id;
     config->role = AudioPortRole(halConfig.role);
     config->type = AudioPortType(halConfig.type);
-    config->configMask = AudioPortConfigMask(halConfig.config_mask);
+    config->configMask = mkEnumConverter<AudioPortConfigMask>(halConfig.config_mask);
     config->sampleRateHz = halConfig.sample_rate;
-    config->channelMask = AudioChannelMask(halConfig.channel_mask);
+    config->channelMask = mkEnumConverter<AudioChannelMask>(halConfig.channel_mask);
     config->format = AudioFormat(halConfig.format);
     audioGainConfigFromHal(halConfig.gain, &config->gain);
     switch (halConfig.type) {
@@ -254,7 +257,7 @@
     }
     port->channelMasks.resize(halPort.num_channel_masks);
     for (size_t i = 0; i < halPort.num_channel_masks; ++i) {
-        port->channelMasks[i] = AudioChannelMask(halPort.channel_masks[i]);
+        port->channelMasks[i] = mkEnumConverter<AudioChannelMask>(halPort.channel_masks[i]);
     }
     port->formats.resize(halPort.num_formats);
     for (size_t i = 0; i < halPort.num_formats; ++i) {
diff --git a/audio/common/all-versions/util/include/common/all-versions/VersionUtils.h b/audio/common/all-versions/util/include/common/all-versions/VersionUtils.h
new file mode 100644
index 0000000..a998b06
--- /dev/null
+++ b/audio/common/all-versions/util/include/common/all-versions/VersionUtils.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_audio_common_VersionUtils_H_
+#define android_hardware_audio_common_VersionUtils_H_
+
+#include <hidl/HidlSupport.h>
+#include <type_traits>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace common {
+namespace utils {
+
+/** Similar to static_cast but also casts to hidl_bitfield depending on
+ * return type inference (emulated through user-define conversion).
+ */
+template <class Source, class Destination = Source>
+class EnumConverter {
+   public:
+    static_assert(std::is_enum<Source>::value || std::is_enum<Destination>::value,
+                  "Source or destination should be an enum");
+
+    explicit EnumConverter(Source source) : mSource(source) {}
+
+    operator Destination() const { return static_cast<Destination>(mSource); }
+
+    template <class = std::enable_if_t<std::is_enum<Destination>::value>>
+    operator ::android::hardware::hidl_bitfield<Destination>() {
+        return static_cast<std::underlying_type_t<Destination>>(mSource);
+    }
+
+   private:
+    const Source mSource;
+};
+template <class Destination, class Source>
+auto mkEnumConverter(Source source) {
+    return EnumConverter<Source, Destination>{source};
+}
+
+}  // namespace utils
+}  // namespace common
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_audio_common_VersionUtils_H_