From ed7dfd5f35928c56642d1ead26d7c12c7846aee6 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Thu, 27 Jan 2022 15:07:15 +0100 Subject: [PATCH 1/2] Audio HAL V7.1: Add latency mode APIs Add APis for controlling the latency mode on an output stream. Latency mode control is optional but mandated if spatial audio with head tracking is supported over Bluetooth classic audio link. Bug: 187446271 Test: m android.hardware.audio@7.1-impl Change-Id: I363db3bf7f7b6439e326d0f6f4becc10b3947e7d (cherry picked from commit 040984fd449ae13ad5a9908e84c0848afbdd8aa2) Merged-In: I363db3bf7f7b6439e326d0f6f4becc10b3947e7d --- audio/7.1/Android.bp | 2 + audio/7.1/IStreamOut.hal | 47 +++++++++++++ audio/7.1/IStreamOutLatencyModeCallback.hal | 28 ++++++++ audio/7.1/types.hal | 30 +++++++++ audio/core/all-versions/default/StreamOut.cpp | 67 +++++++++++++++++++ .../default/include/core/default/StreamOut.h | 12 ++++ 6 files changed, 186 insertions(+) create mode 100644 audio/7.1/IStreamOutLatencyModeCallback.hal create mode 100644 audio/7.1/types.hal diff --git a/audio/7.1/Android.bp b/audio/7.1/Android.bp index d0d96b6cf6..52980e2626 100644 --- a/audio/7.1/Android.bp +++ b/audio/7.1/Android.bp @@ -13,11 +13,13 @@ hidl_interface { name: "android.hardware.audio@7.1", root: "android.hardware", srcs: [ + "types.hal", "IDevice.hal", "IDevicesFactory.hal", "IPrimaryDevice.hal", "IStreamIn.hal", "IStreamOut.hal", + "IStreamOutLatencyModeCallback.hal", ], interfaces: [ "android.hardware.audio@7.0", diff --git a/audio/7.1/IStreamOut.hal b/audio/7.1/IStreamOut.hal index 092a9a0f40..b2013cff8c 100644 --- a/audio/7.1/IStreamOut.hal +++ b/audio/7.1/IStreamOut.hal @@ -16,7 +16,54 @@ package android.hardware.audio@7.1; +import @7.0::Result; import @7.0::IStreamOut; +import IStreamOutLatencyModeCallback; + interface IStreamOut extends @7.0::IStreamOut { + /** + * Indicates the requested latency mode for this output stream. + * + * The requested mode can be one of the modes returned by + * getRecommendedLatencyModes() API. + * + * Optional method. + * Mandated only on specific spatial audio streams indicated by + * AUDIO_OUTPUT_FLAG_SPATIALIZER flag if they can be routed to a BT classic sink. + * + * @return retval operation completion status. + */ + setLatencyMode(LatencyMode mode) generates (Result retval); + + /** + * Indicates which latency modes are currently supported on this output stream. + * If the transport protocol (e.g Bluetooth A2DP) used by this output stream to reach + * the output device supports variable latency modes, the HAL indicates which + * modes are currently supported. + * The framework can then call setLatencyMode() with one of the supported modes to select + * the desired operation mode. + * + * Optional method. + * Mandated only on specific spatial audio streams indicated by + * AUDIO_OUTPUT_FLAG_SPATIALIZER flag if they can be routed to a BT classic sink. + * + * @return retval operation completion status. + * @return modes currrently supported latency modes. + */ + getRecommendedLatencyModes() generates (Result retval, vec modes); + + /** + * Set the callback interface for notifying changes in supported latency modes. + * + * Calling this method with a null pointer will result in releasing + * the callback. + * + * Optional method. + * Mandated only on specific spatial audio streams indicated by + * AUDIO_OUTPUT_FLAG_SPATIALIZER flag if they can be routed to a BT classic sink. + * + * @return retval operation completion status. + */ + setLatencyModeCallback(IStreamOutLatencyModeCallback callback) generates (Result retval); }; diff --git a/audio/7.1/IStreamOutLatencyModeCallback.hal b/audio/7.1/IStreamOutLatencyModeCallback.hal new file mode 100644 index 0000000000..45b453f12f --- /dev/null +++ b/audio/7.1/IStreamOutLatencyModeCallback.hal @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2022 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. + */ + + +package android.hardware.audio@7.1; + +/** + * Callback interface for output stream variable latency mode feature. + */ +interface IStreamOutLatencyModeCallback { + /** + * Called with the new list of supported latency modes when a change occurs. + */ + oneway onRecommendedLatencyModeChanged(vec modes); +}; diff --git a/audio/7.1/types.hal b/audio/7.1/types.hal new file mode 100644 index 0000000000..9d8ee4def2 --- /dev/null +++ b/audio/7.1/types.hal @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 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. + */ + +package android.hardware.audio@7.1; + +/** + * Latency modes used for the variable latency feature on output streams. + * Used by setLatencyMode() and getRecommendedLatencyModes() methods. + */ + +@export(name="audio_latency_mode_t", value_prefix="AUDIO_LATENCY_MODE_") +enum LatencyMode : int32_t { + /** No specific constraint on the latency */ + FREE = 0, + /** A relatively low latency compatible with head tracking operation (e.g less than 100ms) */ + LOW = 1, +}; diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp index d4a89d7bf9..09df4ed43d 100644 --- a/audio/core/all-versions/default/StreamOut.cpp +++ b/audio/core/all-versions/default/StreamOut.cpp @@ -761,6 +761,73 @@ int StreamOut::asyncEventCallback(stream_event_callback_type_t event, void* para ALOGW_IF(!result.isOk(), "Client callback failed: %s", result.description().c_str()); return 0; } + +#if MAJOR_VERSION == 7 && MINOR_VERSION == 1 +Return StreamOut::setLatencyMode(LatencyMode mode) { + return mStream->set_latency_mode != nullptr + ? Stream::analyzeStatus( + "set_latency_mode", + mStream->set_latency_mode(mStream, + static_cast(mode))) + : Result::NOT_SUPPORTED; +}; + +Return StreamOut::getRecommendedLatencyModes(getRecommendedLatencyModes_cb _hidl_cb) { + Result retval = Result::NOT_SUPPORTED; + hidl_vec hidlModes; + size_t num_modes = AUDIO_LATENCY_MODE_CNT; + audio_latency_mode_t modes[AUDIO_LATENCY_MODE_CNT]; + + if (mStream->get_recommended_latency_modes != nullptr && + mStream->get_recommended_latency_modes(mStream, &modes[0], &num_modes) == 0) { + if (num_modes == 0 || num_modes > AUDIO_LATENCY_MODE_CNT) { + ALOGW("%s invalid number of modes returned: %zu", __func__, num_modes); + retval = Result::INVALID_STATE; + } else { + hidlModes.resize(num_modes); + for (size_t i = 0; i < num_modes; ++i) { + hidlModes[i] = static_cast(modes[i]); + } + retval = Result::OK; + } + } + _hidl_cb(retval, hidlModes); + return Void(); +}; + +// static +void StreamOut::latencyModeCallback(audio_latency_mode_t* modes, size_t num_modes, void* cookie) { + StreamOut* self = reinterpret_cast(cookie); + sp callback = self->mLatencyModeCallback.load(); + if (callback.get() == nullptr) return; + + ALOGV("%s", __func__); + + if (num_modes == 0 || num_modes > AUDIO_LATENCY_MODE_CNT) { + ALOGW("%s invalid number of modes returned: %zu", __func__, num_modes); + return; + } + + hidl_vec hidlModes(num_modes); + for (size_t i = 0; i < num_modes; ++i) { + hidlModes[i] = static_cast(modes[i]); + } + Return result = callback->onRecommendedLatencyModeChanged(hidlModes); + ALOGW_IF(!result.isOk(), "Client callback failed: %s", result.description().c_str()); +} + +Return StreamOut::setLatencyModeCallback( + const sp& callback) { + if (mStream->set_latency_mode_callback == nullptr) return Result::NOT_SUPPORTED; + int result = mStream->set_latency_mode_callback(mStream, StreamOut::latencyModeCallback, this); + if (result == 0) { + mLatencyModeCallback = callback; + } + return Stream::analyzeStatus("set_latency_mode_callback", result, {ENOSYS} /*ignore*/); +}; + +#endif + #endif } // namespace implementation diff --git a/audio/core/all-versions/default/include/core/default/StreamOut.h b/audio/core/all-versions/default/include/core/default/StreamOut.h index 60ad5d5ea1..ce5253fe79 100644 --- a/audio/core/all-versions/default/include/core/default/StreamOut.h +++ b/audio/core/all-versions/default/include/core/default/StreamOut.h @@ -153,6 +153,12 @@ struct StreamOut : public IStreamOut { Result doUpdateSourceMetadata(const SourceMetadata& sourceMetadata); #if MAJOR_VERSION >= 7 Result doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata); +#if MAJOR_VERSION == 7 && MINOR_VERSION == 1 + Return setLatencyMode(LatencyMode mode) override; + Return getRecommendedLatencyModes(getRecommendedLatencyModes_cb _hidl_cb) override; + Return setLatencyModeCallback( + const sp& callback) override; +#endif #endif #endif // MAJOR_VERSION >= 4 @@ -163,6 +169,9 @@ struct StreamOut : public IStreamOut { mediautils::atomic_sp mCallback; // for non-blocking write and drain #if MAJOR_VERSION >= 6 mediautils::atomic_sp mEventCallback; +#if MAJOR_VERSION == 7 && MINOR_VERSION == 1 + mediautils::atomic_sp mLatencyModeCallback; +#endif #endif std::unique_ptr mCommandMQ; std::unique_ptr mDataMQ; @@ -177,6 +186,9 @@ struct StreamOut : public IStreamOut { #if MAJOR_VERSION >= 6 static int asyncEventCallback(stream_event_callback_type_t event, void* param, void* cookie); +#if MAJOR_VERSION == 7 && MINOR_VERSION == 1 + static void latencyModeCallback(audio_latency_mode_t* modes, size_t num_modes, void* cookie); +#endif #endif }; From 16894f0e06c557f407617b2236288fe87f584ca4 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Thu, 27 Jan 2022 11:50:46 +0100 Subject: [PATCH 2/2] audio: add new enums for 7.1 HAL Add the following enums to 7.1 audio HAL: - Spatial audio: spatializer output flag front wide channel masks - Bluetooth LE broadcast audio device Bug: 187446271 Test: m android.hardware.audio.common@7.1-enums Change-Id: I9bfb937ece3a07a7844877de5f355ece1141f92d (cherry picked from commit 5b8529a1da6a2fe9c5732215dd29b337da88e7ac) Merged-In: I9bfb937ece3a07a7844877de5f355ece1141f92d --- audio/7.1/config/api/current.txt | 4 ++++ audio/7.1/config/audio_policy_configuration.xsd | 4 ++++ .../include/android_audio_policy_configuration_V7_1-enums.h | 3 +++ 3 files changed, 11 insertions(+) diff --git a/audio/7.1/config/api/current.txt b/audio/7.1/config/api/current.txt index 01c2e4bbd5..0a0eb02e19 100644 --- a/audio/7.1/config/api/current.txt +++ b/audio/7.1/config/api/current.txt @@ -62,6 +62,8 @@ package android.audio.policy.configuration.V7_1 { enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1; enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1POINT2; enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1POINT4; + enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_9POINT1POINT4; + enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_9POINT1POINT6; enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_HAPTIC_AB; enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_MONO; enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_MONO_HAPTIC_A; @@ -125,6 +127,7 @@ package android.audio.policy.configuration.V7_1 { enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_AUX_DIGITAL; enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_AUX_LINE; + enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLE_BROADCAST; enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLE_HEADSET; enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLE_SPEAKER; enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; @@ -284,6 +287,7 @@ package android.audio.policy.configuration.V7_1 { enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_NON_BLOCKING; enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_PRIMARY; enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_RAW; + enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_SPATIALIZER; enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_SYNC; enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_TTS; enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_VOIP_RX; diff --git a/audio/7.1/config/audio_policy_configuration.xsd b/audio/7.1/config/audio_policy_configuration.xsd index 731bb7c75f..defb50651d 100644 --- a/audio/7.1/config/audio_policy_configuration.xsd +++ b/audio/7.1/config/audio_policy_configuration.xsd @@ -179,6 +179,7 @@ + @@ -276,6 +277,7 @@ + @@ -510,6 +512,8 @@ + + diff --git a/audio/common/7.1/enums/include/android_audio_policy_configuration_V7_1-enums.h b/audio/common/7.1/enums/include/android_audio_policy_configuration_V7_1-enums.h index 815f869e93..6f6a0ca0c1 100644 --- a/audio/common/7.1/enums/include/android_audio_policy_configuration_V7_1-enums.h +++ b/audio/common/7.1/enums/include/android_audio_policy_configuration_V7_1-enums.h @@ -97,10 +97,12 @@ static inline size_t getChannelCount(AudioChannelMask mask) { case AudioChannelMask::AUDIO_CHANNEL_OUT_13POINT_360RA: case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_13: return 13; + case AudioChannelMask::AUDIO_CHANNEL_OUT_9POINT1POINT4: case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_14: return 14; case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_15: return 15; + case AudioChannelMask::AUDIO_CHANNEL_OUT_9POINT1POINT6: case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_16: return 16; case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_17: @@ -170,6 +172,7 @@ static inline bool isOutputDevice(AudioDevice device) { case AudioDevice::AUDIO_DEVICE_OUT_ECHO_CANCELLER: case AudioDevice::AUDIO_DEVICE_OUT_BLE_HEADSET: case AudioDevice::AUDIO_DEVICE_OUT_BLE_SPEAKER: + case AudioDevice::AUDIO_DEVICE_OUT_BLE_BROADCAST: case AudioDevice::AUDIO_DEVICE_OUT_DEFAULT: case AudioDevice::AUDIO_DEVICE_OUT_STUB: return true;