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/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/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/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; 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 };