Merge changes I2f70f2ec,I9d77a59e,Ied3a657d,Ib6e9d017,I95db94ed, ... into pi-dev

* changes:
  Audio V4: Add missing VTS
  Audio V4: VTS Pause was testing resume
  Audio V4: factorize analyzeStatus
  Audio V4: fix invalid SupportedChannelMasks test
  Audio V4: setMode VTS incorrectly assume 0 was invalid
  Audio V4: XSD device category was missing hearing aid
  Audio V4: some legacy getSupported can return NOT_SUPPORTED
  Audio V4: Improve VTS error messages
diff --git a/audio/4.0/config/audio_policy_configuration.xsd b/audio/4.0/config/audio_policy_configuration.xsd
index 14e4fd6..ee17fc9 100644
--- a/audio/4.0/config/audio_policy_configuration.xsd
+++ b/audio/4.0/config/audio_policy_configuration.xsd
@@ -525,6 +525,7 @@
             <xs:enumeration value="DEVICE_CATEGORY_SPEAKER"/>
             <xs:enumeration value="DEVICE_CATEGORY_EARPIECE"/>
             <xs:enumeration value="DEVICE_CATEGORY_EXT_MEDIA"/>
+            <xs:enumeration value="DEVICE_CATEGORY_HEARING_AID"/>
         </xs:restriction>
     </xs:simpleType>
     <xs:complexType name="volume">
diff --git a/audio/common/all-versions/test/utility/include/utility/PrettyPrintAudioTypes.h b/audio/common/all-versions/test/utility/include/utility/PrettyPrintAudioTypes.h
index 88a67e0..05239ac 100644
--- a/audio/common/all-versions/test/utility/include/utility/PrettyPrintAudioTypes.h
+++ b/audio/common/all-versions/test/utility/include/utility/PrettyPrintAudioTypes.h
@@ -47,7 +47,9 @@
 namespace common {
 namespace AUDIO_HAL_VERSION {
 DEFINE_GTEST_PRINT_TO(AudioConfig)
+DEFINE_GTEST_PRINT_TO(AudioMode)
 DEFINE_GTEST_PRINT_TO(AudioDevice)
+DEFINE_GTEST_PRINT_TO(AudioFormat)
 DEFINE_GTEST_PRINT_TO(AudioChannelMask)
 }  // namespace AUDIO_HAL_VERSION
 }  // namespace common
diff --git a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
index 9484ddd..de0df40 100644
--- a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
@@ -55,6 +55,7 @@
 using ::android::sp;
 using ::android::hardware::Return;
 using ::android::hardware::hidl_bitfield;
+using ::android::hardware::hidl_enum_iterator;
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
@@ -81,6 +82,7 @@
 using ::android::hardware::audio::V4_0::SinkMetadata;
 using ::android::hardware::audio::common::V4_0::AudioChannelMask;
 using ::android::hardware::audio::common::V4_0::AudioConfig;
+using ::android::hardware::audio::common::V4_0::AudioContentType;
 using ::android::hardware::audio::common::V4_0::AudioDevice;
 using ::android::hardware::audio::common::V4_0::AudioFormat;
 using ::android::hardware::audio::common::V4_0::AudioHandleConsts;
@@ -91,6 +93,7 @@
 using ::android::hardware::audio::common::V4_0::AudioOffloadInfo;
 using ::android::hardware::audio::common::V4_0::AudioOutputFlag;
 using ::android::hardware::audio::common::V4_0::AudioSource;
+using ::android::hardware::audio::common::V4_0::AudioUsage;
 using ::android::hardware::audio::common::V4_0::ThreadInfo;
 using ::android::hardware::audio::common::utils::mkBitfield;
 
@@ -140,11 +143,11 @@
 sp<IDevicesFactory> AudioHidlTest::devicesFactory;
 
 TEST_F(AudioHidlTest, GetAudioDevicesFactoryService) {
-    doc::test("test the getService (called in SetUp)");
+    doc::test("Test the getService (called in SetUp)");
 }
 
 TEST_F(AudioHidlTest, OpenDeviceInvalidParameter) {
-    doc::test("test passing an invalid parameter to openDevice");
+    doc::test("Test passing an invalid parameter to openDevice");
     Result result;
     sp<IDevice> device;
     ASSERT_OK(devicesFactory->openDevice("Non existing device", returnIn(result, device)));
@@ -152,6 +155,19 @@
     ASSERT_TRUE(device == nullptr);
 }
 
+TEST_F(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) {
+    doc::test("Calling openDevice(\"primary\") should return the primary device.");
+    Result result;
+    sp<IDevice> baseDevice;
+    ASSERT_OK(devicesFactory->openDevice("primary", returnIn(result, baseDevice)));
+    ASSERT_OK(result);
+    ASSERT_TRUE(baseDevice != nullptr);
+
+    Return<sp<IPrimaryDevice>> primaryDevice = IPrimaryDevice::castFrom(baseDevice);
+    ASSERT_TRUE(primaryDevice.isOk());
+    ASSERT_TRUE(sp<IPrimaryDevice>(primaryDevice) != nullptr);
+}
+
 //////////////////////////////////////////////////////////////////////////////
 /////////////////////////////// openDevice primary ///////////////////////////
 //////////////////////////////////////////////////////////////////////////////
@@ -165,14 +181,11 @@
 
         if (device == nullptr) {
             Result result;
-            sp<IDevice> baseDevice;
-            ASSERT_OK(devicesFactory->openDevice("primary", returnIn(result, baseDevice)));
+            ASSERT_OK(devicesFactory->openPrimaryDevice(returnIn(result, device)));
             ASSERT_OK(result);
-            ASSERT_TRUE(baseDevice != nullptr);
+            ASSERT_TRUE(device != nullptr);
 
             environment->registerTearDown([] { device.clear(); });
-            device = IPrimaryDevice::castFrom(baseDevice);
-            ASSERT_TRUE(device != nullptr);
         }
     }
 
@@ -600,13 +613,17 @@
         const AudioConfig& config = GetParam();
         // TODO: test all flag combination
         auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE);
-        SourceMetadata metadata = {{{}}};  // create on track metadata
         testOpen(
             [&](AudioIoHandle handle, AudioConfig config, auto cb) {
-                return device->openOutputStream(handle, address, config, flags, metadata, cb);
+                return device->openOutputStream(handle, address, config, flags, initialMetadata,
+                                                cb);
             },
             config);
     }
+
+   protected:
+    const SourceMetadata initialMetadata = {
+        {{AudioUsage::MEDIA, AudioContentType::MUSIC, 1 /* gain */}}};
 };
 TEST_P(OutputStreamTest, OpenOutputStreamTest) {
     doc::test(
@@ -637,13 +654,15 @@
         const AudioConfig& config = GetParam();
         // TODO: test all supported flags and source
         auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
-        SinkMetadata metadata = {{{AudioSource::DEFAULT, 1}}};
         testOpen(
             [&](AudioIoHandle handle, AudioConfig config, auto cb) {
-                return device->openInputStream(handle, address, config, flags, metadata, cb);
+                return device->openInputStream(handle, address, config, flags, initialMetadata, cb);
             },
             config);
     }
+
+   protected:
+    const SinkMetadata initialMetadata = {{{AudioSource::DEFAULT, 1 /* gain */}}};
 };
 
 TEST_P(InputStreamTest, OpenInputStreamTest) {
@@ -727,11 +746,12 @@
     ASSERT_OK(ret);
 
     if (currentMustBeSupported) {
+        ASSERT_NE(0U, capabilities.size()) << name << " must not return an empty list";
         Property currentValue = extract((stream->*getter)());
-        EXPECT_NE(std::find(capabilities.begin(), capabilities.end(), currentValue),
-                  capabilities.end())
-            << "current " << name << " is not in the list of the supported ones "
-            << toString(capabilities);
+        EXPECT_TRUE(std::find(capabilities.begin(), capabilities.end(), currentValue) !=
+                    capabilities.end())
+            << "value returned by " << name << "() = " << testing::PrintToString(currentValue)
+            << " is not in the list of the supported ones " << toString(capabilities);
     }
 
     // Check that all declared supported values are indeed supported
@@ -757,7 +777,7 @@
                                 hidl_vec<hidl_bitfield<AudioChannelMask>>& channels) {
     Result res;
     EXPECT_OK(
-        stream->getSupportedSampleRates(extract(stream->getFormat()), returnIn(res, channels)));
+        stream->getSupportedChannelMasks(extract(stream->getFormat()), returnIn(res, channels)));
     return res;
 }
 
@@ -1039,8 +1059,30 @@
     ASSERT_RESULT(invalidStateOrNotSupported, res);
 }
 
+TEST_P(InputStreamTest, updateSinkMetadata) {
+    doc::test("The HAL should not crash on metadata change");
+
+    hidl_enum_iterator<AudioSource> range;
+    // Test all possible track configuration
+    for (AudioSource source : range) {
+        for (float volume : {0.0, 0.5, 1.0}) {
+            const SinkMetadata metadata = {{{source, volume}}};
+            ASSERT_OK(stream->updateSinkMetadata(metadata))
+                << "source=" << toString(source) << ", volume=" << volume;
+        }
+    }
+
+    // Do not test concurrent capture as this is not officially supported
+
+    // Set no metadata as if all stream track had stopped
+    ASSERT_OK(stream->updateSinkMetadata({}));
+
+    // Restore initial
+    ASSERT_OK(stream->updateSinkMetadata(initialMetadata));
+}
+
 //////////////////////////////////////////////////////////////////////////////
-///////////////////////////////// StreamIn ///////////////////////////////////
+///////////////////////////////// StreamOut //////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
 TEST_P(OutputStreamTest, getLatency) {
@@ -1195,7 +1237,7 @@
         doc::partialTest("The output stream does not support pause");
         return;
     }
-    ASSERT_RESULT(Result::INVALID_STATE, stream->resume());
+    ASSERT_RESULT(Result::INVALID_STATE, stream->pause());
 }
 
 static void testDrain(IStreamOut* stream, AudioDrain type) {
@@ -1261,6 +1303,37 @@
     ASSERT_RESULT(okOrNotSupported, stream->selectPresentation(0, 0));
 }
 
+TEST_P(OutputStreamTest, updateSourceMetadata) {
+    doc::test("The HAL should not crash on metadata change");
+
+    hidl_enum_iterator<AudioUsage> usageRange;
+    hidl_enum_iterator<AudioContentType> contentRange;
+    // Test all possible track configuration
+    for (auto usage : usageRange) {
+        for (auto content : contentRange) {
+            for (float volume : {0.0, 0.5, 1.0}) {
+                const SourceMetadata metadata = {{{usage, content, volume}}};
+                ASSERT_OK(stream->updateSourceMetadata(metadata))
+                    << "usage=" << toString(usage) << ", content=" << toString(content)
+                    << ", volume=" << volume;
+            }
+        }
+    }
+
+    // Set many track of different configuration
+    ASSERT_OK(stream->updateSourceMetadata(
+        {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 0.1},
+          {AudioUsage::VOICE_COMMUNICATION, AudioContentType::SPEECH, 1.0},
+          {AudioUsage::ALARM, AudioContentType::SONIFICATION, 0.0},
+          {AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, 0.3}}}));
+
+    // Set no metadata as if all stream track had stopped
+    ASSERT_OK(stream->updateSourceMetadata({}));
+
+    // Restore initial
+    ASSERT_OK(stream->updateSourceMetadata(initialMetadata));
+}
+
 //////////////////////////////////////////////////////////////////////////////
 /////////////////////////////// PrimaryDevice ////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
@@ -1271,19 +1344,16 @@
 }
 
 TEST_F(AudioPrimaryHidlTest, setMode) {
-    doc::test(
-        "Make sure setMode always succeeds if mode is valid "
-        "and fails otherwise");
+    doc::test("Make sure setMode always succeeds if mode is valid and fails otherwise");
     // Test Invalid values
-    for (int mode : {-1, 0, int(AudioMode::IN_COMMUNICATION) + 1}) {
-        SCOPED_TRACE("mode=" + to_string(mode));
-        ASSERT_RESULT(Result::INVALID_ARGUMENTS, device->setMode(AudioMode(mode)));
+    for (int mode : {-2, -1, int(AudioMode::IN_COMMUNICATION) + 1}) {
+        ASSERT_RESULT(Result::INVALID_ARGUMENTS, device->setMode(AudioMode(mode)))
+            << "mode=" << mode;
     }
     // Test valid values
     for (AudioMode mode : {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION, AudioMode::RINGTONE,
                            AudioMode::NORMAL /* Make sure to leave the test in normal mode */}) {
-        SCOPED_TRACE("mode=" + toString(mode));
-        ASSERT_OK(device->setMode(mode));
+        ASSERT_OK(device->setMode(mode)) << "mode=" << toString(mode);
     }
 }
 
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
index 37b7124..230b8de 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
@@ -41,23 +41,7 @@
 }
 
 Result Device::analyzeStatus(const char* funcName, int status) {
-    if (status != 0) {
-        ALOGW("Device %p %s: %s", mDevice, funcName, strerror(-status));
-    }
-    switch (status) {
-        case 0:
-            return Result::OK;
-        case -EINVAL:
-            return Result::INVALID_ARGUMENTS;
-        case -ENODATA:
-            return Result::INVALID_STATE;
-        case -ENODEV:
-            return Result::NOT_INITIALIZED;
-        case -ENOSYS:
-            return Result::NOT_SUPPORTED;
-        default:
-            return Result::INVALID_STATE;
-    }
+    return util::analyzeStatus("Device", funcName, status);
 }
 
 void Device::closeInputStream(audio_stream_in_t* stream) {
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h
index 7415112..72d7a37 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h
@@ -101,11 +101,15 @@
         halSampleRates =
             samplingRatesFromString(halListValue.string(), AudioParameter::valueListSeparator);
         sampleRates.setToExternal(halSampleRates.editArray(), halSampleRates.size());
+        // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
+        // Note that this method must succeed (non empty list) if the format is supported.
+        if (sampleRates.size() == 0) {
+            result = Result::NOT_SUPPORTED;
+        }
     }
 #ifdef AUDIO_HAL_VERSION_2_0
     _hidl_cb(sampleRates);
-#endif
-#ifdef AUDIO_HAL_VERSION_4_0
+#elif AUDIO_HAL_VERSION_4_0
     _hidl_cb(result, sampleRates);
 #endif
     return Void();
@@ -126,6 +130,11 @@
         for (size_t i = 0; i < halChannelMasks.size(); ++i) {
             channelMasks[i] = AudioChannelBitfield(halChannelMasks[i]);
         }
+        // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
+        // Note that this method must succeed (non empty list) if the format is supported.
+        if (channelMasks.size() == 0) {
+            result = Result::NOT_SUPPORTED;
+        }
     }
 #ifdef AUDIO_HAL_VERSION_2_0
     _hidl_cb(channelMasks);