diff --git a/frameworks/js/napi/audiorenderer/napi_audio_renderer.cpp b/frameworks/js/napi/audiorenderer/napi_audio_renderer.cpp index bc824c208bd3923dd5d6333da5ebd51ae6d9bdb3..70cabb770da761ad70c6175198f3297a153892bf 100644 --- a/frameworks/js/napi/audiorenderer/napi_audio_renderer.cpp +++ b/frameworks/js/napi/audiorenderer/napi_audio_renderer.cpp @@ -103,6 +103,7 @@ napi_status NapiAudioRenderer::InitNapiAudioRenderer(napi_env env, napi_value &c DECLARE_NAPI_FUNCTION("off", Off), DECLARE_NAPI_FUNCTION("setSilentModeAndMixWithOthers", SetSilentModeAndMixWithOthers), DECLARE_NAPI_FUNCTION("getSilentModeAndMixWithOthers", GetSilentModeAndMixWithOthers), + DECLARE_NAPI_FUNCTION("setDefaultOutputDevice", SetDefaultOutputDevice), }; napi_status status = napi_define_class(env, NAPI_AUDIO_RENDERER_CLASS_NAME.c_str(), @@ -1569,6 +1570,36 @@ napi_value NapiAudioRenderer::GetSilentModeAndMixWithOthers(napi_env env, napi_c return result; } +napi_value NapiAudioRenderer::SetDefaultOutputDevice(napi_env env, napi_callback_info info) +{ + napi_value result = nullptr; + size_t argc = ARGS_ONE; + napi_value argv[ARGS_ONE] = {}; + auto *napiAudioRenderer = GetParamWithSync(env, info, argc, argv); + CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID, + "mandatory parameters are left unspecified"), "argcCount invaild"); + + napi_valuetype valueType = napi_undefined; + napi_typeof(env, argv[PARAM0], &valueType); + CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID, + "incorrect parameter types: The type of mode must be number"), "valueType params"); + + int32_t deviceType; + NapiParamUtils::GetValueInt32(env, deviceType, argv[PARAM0]); + CHECK_AND_RETURN_RET_LOG(NapiAudioEnum::IsLegalInputArgumentDefaultOutputDeviceType(deviceType), + NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM, + "parameter verification failed: The param of mode must be enum deviceType"), "unsupport params"); + + CHECK_AND_RETURN_RET_LOG(napiAudioRenderer!= nullptr, result, "napiAudioRenderer is nullptr"); + CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr"); + int32_t ret = + napiAudioRenderer->audioRenderer_->SetDefaultOutputDevice(static_cast(deviceType)); + CHECK_AND_RETURN_RET_LOG(ret != ERR_ILLEGAL_STATE, + NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_ILLEGAL_STATE), "err illegal state"); + + return result; +} + napi_value NapiAudioRenderer::RegisterCallback(napi_env env, napi_value jsThis, napi_value *argv, const std::string &cbName) { diff --git a/frameworks/js/napi/audiorenderer/napi_audio_renderer.h b/frameworks/js/napi/audiorenderer/napi_audio_renderer.h index 16afb204d2ed323b66f5879734e1cc262d6cd669..d87bd386287d29445e8f11399ab3f419e9321da7 100644 --- a/frameworks/js/napi/audiorenderer/napi_audio_renderer.h +++ b/frameworks/js/napi/audiorenderer/napi_audio_renderer.h @@ -127,6 +127,7 @@ private: static napi_value Off(napi_env env, napi_callback_info info); static napi_value SetSilentModeAndMixWithOthers(napi_env env, napi_callback_info info); static napi_value GetSilentModeAndMixWithOthers(napi_env env, napi_callback_info info); + static napi_value SetDefaultOutputDevice(napi_env env, napi_callback_info info); static napi_status WriteArrayBufferToNative(std::shared_ptr context); diff --git a/frameworks/js/napi/common/napi_audio_enum.cpp b/frameworks/js/napi/common/napi_audio_enum.cpp index 4747bdc432a475e47f96ed6632355a7dcd48a912..62d95bf584bc70aabc5b4c9456555462dc471bc4 100644 --- a/frameworks/js/napi/common/napi_audio_enum.cpp +++ b/frameworks/js/napi/common/napi_audio_enum.cpp @@ -1198,6 +1198,22 @@ bool NapiAudioEnum::IsLegalInputArgumentDeviceType(int32_t deviceType) return result; } +bool NapiAudioEnum::IsLegalInputArgumentDefaultOutputDeviceType(int32_t deviceType) +{ + bool result = false; + switch (deviceType) { + case DeviceType::DEVICE_TYPE_EARPIECE: + case DeviceType::DEVICE_TYPE_SPEAKER: + case DeviceType::DEVICE_TYPE_DEFAULT: + result = true; + break; + default: + result = false; + break; + } + return result; +} + int32_t NapiAudioEnum::GetJsAudioVolumeType(AudioStreamType volumeType) { int32_t result = MEDIA; diff --git a/frameworks/js/napi/common/napi_audio_enum.h b/frameworks/js/napi/common/napi_audio_enum.h index 51bd98a34b4930f97a94cb683d56d9f777bf497f..f017670676dc4efbc88dcb2433acddc295b6b70e 100644 --- a/frameworks/js/napi/common/napi_audio_enum.h +++ b/frameworks/js/napi/common/napi_audio_enum.h @@ -95,6 +95,7 @@ public: static bool IsLegalInputArgumentRingMode(int32_t ringMode); static bool IsLegalInputArgumentVolumeAdjustType(int32_t adjustType); static bool IsLegalInputArgumentDeviceType(int32_t deviceType); + static bool IsLegalInputArgumentDefaultOutputDeviceType(int32_t deviceType); static bool IsLegalInputArgumentDeviceFlag(int32_t deviceFlag); static bool IsLegalInputArgumentActiveDeviceType(int32_t activeDeviceFlag); static int32_t GetJsAudioVolumeType(AudioStreamType volumeType); diff --git a/frameworks/native/audiopolicy/include/audio_policy_manager.h b/frameworks/native/audiopolicy/include/audio_policy_manager.h index 3d9e5dda0ede6fab33d98c826a89c23f4efa1b92..6cc494c964e7f6fcaa9dfebaceda9dcf224ac3e1 100644 --- a/frameworks/native/audiopolicy/include/audio_policy_manager.h +++ b/frameworks/native/audiopolicy/include/audio_policy_manager.h @@ -417,6 +417,9 @@ public: int32_t LoadSplitModule(const std::string &splitArgs, const std::string &networkId); + int32_t SetDefaultOutputDevice(const DeviceType deviceType, const uint32_t sessionID, + const StreamUsage streamUsage, bool isRunning); + private: AudioPolicyManager() {} ~AudioPolicyManager() {} diff --git a/frameworks/native/audiorenderer/include/audio_renderer_private.h b/frameworks/native/audiorenderer/include/audio_renderer_private.h index 2c1d95e3ac07015a6fe7d2fa6d1ac910a6ae9425..fe5b940b9ce33448786234ae78a3946cb99b90ca 100644 --- a/frameworks/native/audiorenderer/include/audio_renderer_private.h +++ b/frameworks/native/audiorenderer/include/audio_renderer_private.h @@ -128,6 +128,8 @@ public: void EnableVoiceModemCommunicationStartStream(bool enable) override; + int32_t SetDefaultOutputDevice(DeviceType deviceType) override; + static inline AudioStreamParams ConvertToAudioStreamParams(const AudioRendererParams params) { AudioStreamParams audioStreamParams; diff --git a/frameworks/native/audiorenderer/src/audio_renderer.cpp b/frameworks/native/audiorenderer/src/audio_renderer.cpp index 908464c47cb4ac1c6b3606dcae5d409e10779885..3ef2ea5d7d6b3728b32c2c965880dd844053a736 100644 --- a/frameworks/native/audiorenderer/src/audio_renderer.cpp +++ b/frameworks/native/audiorenderer/src/audio_renderer.cpp @@ -1846,5 +1846,17 @@ void AudioRendererPrivate::EnableVoiceModemCommunicationStartStream(bool enable) { isEnableVoiceModemCommunicationStartStream_ = enable; } + +int32_t AudioRendererPrivate::SetDefaultOutputDevice(DeviceType deviceType) +{ + bool isSupportedStreamUsage = (find(AUDIO_DEFAULT_OUTPUT_DEVICE_SUPPORTED_STREAM_USAGES.begin(), + AUDIO_DEFAULT_OUTPUT_DEVICE_SUPPORTED_STREAM_USAGES.end(), rendererInfo_.streamUsage) != + AUDIO_DEFAULT_OUTPUT_DEVICE_SUPPORTED_STREAM_USAGES.end()); + CHECK_AND_RETURN_RET_LOG(isSupportedStreamUsage, ERR_NOT_SUPPORTED, "stream usage not supported"); + int32_t ret = AudioPolicyManager::GetInstance().SetDefaultOutputDevice(deviceType, sessionID_, + rendererInfo_.streamUsage, GetStatus() == RENDERER_RUNNING); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "select default output device failed"); + return SUCCESS; +} } // namespace AudioStandard } // namespace OHOS diff --git a/frameworks/native/ohaudio/OHAudioRenderer.cpp b/frameworks/native/ohaudio/OHAudioRenderer.cpp index 456a86327a7d45f86b1c92628766849e62a0355e..ef70cdebd4a1715cab43e22487d68fefd701078f 100644 --- a/frameworks/native/ohaudio/OHAudioRenderer.cpp +++ b/frameworks/native/ohaudio/OHAudioRenderer.cpp @@ -337,6 +337,19 @@ OH_AudioStream_Result OH_AudioRenderer_GetSilentModeAndMixWithOthers( return AUDIOSTREAM_SUCCESS; } +OH_AudioStream_Result OH_AudioRenderer_SetDefaultOutputDevice( + OH_AudioRenderer* renderer, OH_AudioDevice_Type deviceType) +{ + OHOS::AudioStandard::OHAudioRenderer *audioRenderer = convertRenderer(renderer); + CHECK_AND_RETURN_RET_LOG(audioRenderer != nullptr, AUDIOSTREAM_ERROR_INVALID_PARAM, "convert renderer failed"); + bool result = (deviceType == AUDIO_DEVICE_TYPE_EARPIECE || deviceType == AUDIO_DEVICE_TYPE_SPEAKER || + deviceType == AUDIO_DEVICE_TYPE_DEFAULT) ? true : false; + CHECK_AND_RETURN_RET_LOG(result != true, AUDIOSTREAM_ERROR_ILLEGAL_STATE, "unsupport params"); + int32_t ret = audioRenderer->SetDefaultOutputDevice((OHOS::AudioStandard::DeviceType)deviceType); + CHECK_AND_RETURN_RET_LOG(ret != AUDIOSTREAM_SUCCESS, AUDIOSTREAM_ERROR_INVALID_PARAM, "err illegal state"); + return AUDIOSTREAM_SUCCESS; +} + namespace OHOS { namespace AudioStandard { OHAudioRenderer::OHAudioRenderer() @@ -783,6 +796,12 @@ bool OHAudioRenderer::GetSilentModeAndMixWithOthers() return audioRenderer_->GetSilentModeAndMixWithOthers(); } +int32_t OHAudioRenderer::SetDefaultOutputDevice(DeviceType deviceType) +{ + CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, ERROR, "renderer client is nullptr"); + return audioRenderer_->SetDefaultOutputDevice(deviceType); +} + void OHAudioRenderer::SetRendererCallbackType(WriteDataCallbackType writeDataCallbackType) { writeDataCallbackType_ = writeDataCallbackType; diff --git a/frameworks/native/ohaudio/OHAudioRenderer.h b/frameworks/native/ohaudio/OHAudioRenderer.h index d80703b83a5673d769b24668855b9baf1a200581..325a691e0980678b01aeba83419480eb0ca709a8 100644 --- a/frameworks/native/ohaudio/OHAudioRenderer.h +++ b/frameworks/native/ohaudio/OHAudioRenderer.h @@ -201,6 +201,7 @@ class OHAudioRenderer { void SetInterruptMode(InterruptMode mode); void SetSilentModeAndMixWithOthers(bool on); bool GetSilentModeAndMixWithOthers(); + int32_t SetDefaultOutputDevice(DeviceType deviceType); void SetRendererCallbackType(WriteDataCallbackType writeDataCallbackType); WriteDataCallbackType GetRendererCallbackType(); diff --git a/interfaces/inner_api/native/audiocommon/include/audio_stream_info.h b/interfaces/inner_api/native/audiocommon/include/audio_stream_info.h index 1ccc53d73d81616a09c1eae1ce4f60b4691adad0..ef5c3af1353278168d66f89f004d8534b106c5e4 100644 --- a/interfaces/inner_api/native/audiocommon/include/audio_stream_info.h +++ b/interfaces/inner_api/native/audiocommon/include/audio_stream_info.h @@ -601,6 +601,13 @@ const std::unordered_map STREAM_USAGE_MAP = { {"STREAM_USAGE_VOICE_RINGTONE", STREAM_USAGE_VOICE_RINGTONE}, }; +const std::vector AUDIO_DEFAULT_OUTPUT_DEVICE_SUPPORTED_STREAM_USAGES { + STREAM_USAGE_VOICE_COMMUNICATION, + STREAM_USAGE_VOICE_MESSAGE, + STREAM_USAGE_VIDEO_COMMUNICATION, + STREAM_USAGE_VOICE_MODEM_COMMUNICATION, +}; + struct BufferDesc { uint8_t *buffer; size_t bufLength; diff --git a/interfaces/inner_api/native/audiorenderer/include/audio_renderer.h b/interfaces/inner_api/native/audiorenderer/include/audio_renderer.h index bb7b933378524f619217444b53debc56dcb3e357..7b8305d5f60034740425e0b9c2c8d6045035d349 100644 --- a/interfaces/inner_api/native/audiorenderer/include/audio_renderer.h +++ b/interfaces/inner_api/native/audiorenderer/include/audio_renderer.h @@ -930,6 +930,13 @@ public: virtual void EnableVoiceModemCommunicationStartStream(bool enable) = 0; + /** + * @brief Temporarily changes the current audio route. + * @param deviceType to set. The available deviceTypes are EARPIECE/SPEAKER/DEFAULT. + * @since 12 + */ + virtual int32_t SetDefaultOutputDevice(DeviceType deviceType) = 0; + private: static int32_t CreateCheckParam(const AudioRendererOptions &rendererOptions, const AppInfo &appInfo); diff --git a/interfaces/kits/c/audio_renderer/native_audiorenderer.h b/interfaces/kits/c/audio_renderer/native_audiorenderer.h index a31ceddd970848fb4a69fa2206e009e82dba6673..e80a18f179406609a6f5e5591f12a809a58e7608 100644 --- a/interfaces/kits/c/audio_renderer/native_audiorenderer.h +++ b/interfaces/kits/c/audio_renderer/native_audiorenderer.h @@ -40,6 +40,7 @@ #include #include "native_audiostream_base.h" +#include "native_audio_device_base.h" #include "multimedia/native_audio_channel_layout.h" #ifdef __cplusplus extern "C" { @@ -386,6 +387,24 @@ OH_AudioStream_Result OH_AudioRenderer_SetSilentModeAndMixWithOthers( */ OH_AudioStream_Result OH_AudioRenderer_GetSilentModeAndMixWithOthers( OH_AudioRenderer* renderer, bool* on); + +/** + * Temporarily changes the current audio route. + * This function can only apply on audiorenderers whose streamUsage is + * STREAM_USAGE_VOICE_COMMUNICATION/STREAM_USAGE_VIDEO_COMMUNICATION/STREAM_USAGE_VOICE_MESSAGE + * Setting the device will only take effect if no other accessory such as headphones are in use + * + * @since 13 + * + * @param renderer Renderer generated by OH_AudioStreamBuilder_GenerateRenderer() + * @param deviceType the available deviceTypes is EARPIECE/SPEAKER/DEFAULT + * EARPIECE: Built-in earpiece + * SPEAKER: Built-in speaker + * DEFAULT: system default output device + * @return {@link #AUDIOSTREAM_SUCCESS} or an undesired error. + */ +OH_AudioStream_Result OH_AudioRenderer_SetDefaultOutputDevice( + OH_AudioRenderer* renderer, OH_AudioDevice_Type devicetype); #ifdef __cplusplus } #endif diff --git a/services/audio_policy/client/include/audio_policy_base.h b/services/audio_policy/client/include/audio_policy_base.h index ae5402919867461e13a14cc64b86cefae56dece0..1c49aec0dbfacc26ea2a24c792da33b0a3ea217f 100644 --- a/services/audio_policy/client/include/audio_policy_base.h +++ b/services/audio_policy/client/include/audio_policy_base.h @@ -330,6 +330,9 @@ public: virtual int32_t LoadSplitModule(const std::string &splitArgs, const std::string &networkId) = 0; + virtual int32_t SetDefaultOutputDevice(const DeviceType deviceType, const uint32_t sessionID, + const StreamUsage streamUsage, bool isRunning) = 0; + public: DECLARE_INTERFACE_DESCRIPTOR(u"IAudioPolicy"); }; diff --git a/services/audio_policy/client/include/audio_policy_manager_stub.h b/services/audio_policy/client/include/audio_policy_manager_stub.h index 02180e35924f9e4e915475f634eeb0ac89f2b7d2..a05c187e2801893064b05a10098bbed53af1d259 100644 --- a/services/audio_policy/client/include/audio_policy_manager_stub.h +++ b/services/audio_policy/client/include/audio_policy_manager_stub.h @@ -166,6 +166,7 @@ private: void DeactivateAudioSessionInternal(MessageParcel &data, MessageParcel &reply); void IsAudioSessionActivatedInternal(MessageParcel &data, MessageParcel &reply); void LoadSplitModuleInternal(MessageParcel &data, MessageParcel &reply); + void SetDefaultOutputDeviceInternal(MessageParcel &data, MessageParcel &reply); void OnMiddleNinRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option); void OnMiddleEigRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option); diff --git a/services/audio_policy/client/include/audio_policy_proxy.h b/services/audio_policy/client/include/audio_policy_proxy.h index df9c98f27cb01c9c6735e1e670b799c89752677b..7b61db170f29bc8c620983317f96708c27989393 100644 --- a/services/audio_policy/client/include/audio_policy_proxy.h +++ b/services/audio_policy/client/include/audio_policy_proxy.h @@ -316,6 +316,9 @@ public: int32_t LoadSplitModule(const std::string &splitArgs, const std::string &networkId) override; + int32_t SetDefaultOutputDevice(const DeviceType deviceType, const uint32_t sessionID, + const StreamUsage streamUsage, bool isRunning) override; + private: static inline BrokerDelegator mDdelegator; void WriteStreamChangeInfo(MessageParcel &data, const AudioMode &mode, diff --git a/services/audio_policy/client/src/audio_policy_manager.cpp b/services/audio_policy/client/src/audio_policy_manager.cpp index ac6851c697c714d7cde3ee7d5942a857cc439cc6..bfba0d9d5d7c5bcd62ce9089fdc1418e14699870 100644 --- a/services/audio_policy/client/src/audio_policy_manager.cpp +++ b/services/audio_policy/client/src/audio_policy_manager.cpp @@ -1916,6 +1916,14 @@ int32_t AudioPolicyManager::LoadSplitModule(const std::string &splitArgs, const return gsp->LoadSplitModule(splitArgs, networkId); } +int32_t AudioPolicyManager::SetDefaultOutputDevice(const DeviceType deviceType, const uint32_t sessionID, + const StreamUsage streamUsage, bool isRunning) +{ + const sptr gsp = GetAudioPolicyManagerProxy(); + CHECK_AND_RETURN_RET_LOG(gsp != nullptr, -1, "audio policy manager proxy is NULL."); + return gsp->SetDefaultOutputDevice(deviceType, sessionID, streamUsage, isRunning); +} + AudioPolicyManager& AudioPolicyManager::GetInstance() { static AudioPolicyManager policyManager; diff --git a/services/audio_policy/client/src/proxy/audio_policy_proxy.cpp b/services/audio_policy/client/src/proxy/audio_policy_proxy.cpp index 9b47b287cc63f22dec8b483326251624e4ede79e..4b007473c0fb3fc83e471930420d3b190a07ac84 100644 --- a/services/audio_policy/client/src/proxy/audio_policy_proxy.cpp +++ b/services/audio_policy/client/src/proxy/audio_policy_proxy.cpp @@ -1855,5 +1855,25 @@ int32_t AudioPolicyProxy::InjectInterruption(const std::string networkId, Interr return reply.ReadInt32(); } +int32_t AudioPolicyProxy::SetDefaultOutputDevice(const DeviceType deviceType, const uint32_t sessionID, + const StreamUsage streamUsage, bool isRunning) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + bool ret = data.WriteInterfaceToken(GetDescriptor()); + CHECK_AND_RETURN_RET_LOG(ret, -1, "WriteInterfaceToken failed"); + data.WriteInt32(static_cast(deviceType)); + data.WriteUint32(sessionID); + data.WriteInt32(static_cast(streamUsage)); + data.WriteBool(isRunning); + + int error = Remote()->SendRequest( + static_cast(AudioPolicyInterfaceCode::SET_DEFAULT_OUTPUT_DEVICE), data, reply, option); + CHECK_AND_RETURN_RET_LOG(error == ERR_NONE, error, "SendRequest failed, error: %{public}d", error); + return reply.ReadInt32(); +} + } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_policy/common/include/audio_policy_ipc_interface_code.h b/services/audio_policy/common/include/audio_policy_ipc_interface_code.h index 4500b8c169f201aa6612ffa36f7066bf289265b9..4fdda32fffcee07835564713714ac07a820f6076 100644 --- a/services/audio_policy/common/include/audio_policy_ipc_interface_code.h +++ b/services/audio_policy/common/include/audio_policy_ipc_interface_code.h @@ -156,7 +156,8 @@ enum class AudioPolicyInterfaceCode { DEACTIVATE_AUDIO_SESSION, IS_AUDIO_SESSION_ACTIVATED, LOAD_SPLIT_MODULE, - AUDIO_POLICY_MANAGER_CODE_MAX = LOAD_SPLIT_MODULE, + SET_DEFAULT_OUTPUT_DEVICE, + AUDIO_POLICY_MANAGER_CODE_MAX = SET_DEFAULT_OUTPUT_DEVICE, }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_policy/server/include/audio_policy_server.h b/services/audio_policy/server/include/audio_policy_server.h index 8030bcadff07baea887d88d9fd48ee44311847da..e15e2bafbe0de2b71970839fc58ac5105cd109c6 100644 --- a/services/audio_policy/server/include/audio_policy_server.h +++ b/services/audio_policy/server/include/audio_policy_server.h @@ -401,6 +401,9 @@ public: int32_t LoadSplitModule(const std::string &splitArgs, const std::string &networkId) override; + int32_t SetDefaultOutputDevice(const DeviceType deviceType, const uint32_t sessionID, + const StreamUsage streamUsage, bool isRunning) override; + class RemoteParameterCallback : public AudioParameterCallback { public: RemoteParameterCallback(sptr server); diff --git a/services/audio_policy/server/include/audio_stream_collector.h b/services/audio_policy/server/include/audio_stream_collector.h index b8249ccd686d5f2cd54a282e7a801bc930c74da3..b32fb5591ecf766f30a1bc0756c446bc996375f9 100644 --- a/services/audio_policy/server/include/audio_stream_collector.h +++ b/services/audio_policy/server/include/audio_stream_collector.h @@ -76,6 +76,7 @@ public: void ResetRendererStreamDeviceInfo(const AudioDeviceDescriptor& updatedDesc); void ResetCapturerStreamDeviceInfo(const AudioDeviceDescriptor& updatedDesc); StreamUsage GetLastestRunningCallStreamUsage(); + std::vector GetAllRendererSessionIDForUID(int32_t uid); private: std::mutex streamsInfoMutex_; std::map, int32_t> rendererStatequeue_; diff --git a/services/audio_policy/server/include/service/audio_device_manager.h b/services/audio_policy/server/include/service/audio_device_manager.h index c5f532e7d17e7be99b1af2ef73ea1e9530bf6923..6a8b2620f85ad2fcfae62f4abad969339a825325 100644 --- a/services/audio_policy/server/include/service/audio_device_manager.h +++ b/services/audio_policy/server/include/service/audio_device_manager.h @@ -27,6 +27,8 @@ namespace OHOS { namespace AudioStandard { using namespace std; +constexpr int32_t NEED_TO_FETCH = 1; + typedef function &desc)> IsPresentFunc; std::string GetEncryptAddr(const std::string &addr); class AudioDeviceManager { @@ -82,6 +84,12 @@ public: bool IsDeviceConnected(sptr &audioDeviceDescriptors); bool IsVirtualConnectedDevice(const sptr &selectedDesc); int32_t UpdateDeviceDescDeviceId(sptr &deviceDescriptor); + int32_t SetDefaultOutputDevice(const DeviceType deviceType, const uint32_t sessionID, + const StreamUsage streamUsage, bool isRunning); + int32_t UpdateDefaultOutputDeviceWhenStarting(const uint32_t sessionID); + int32_t UpdateDefaultOutputDeviceWhenStopping(const uint32_t sessionID); + unique_ptr GetSelectedMediaRenderDevice(); + unique_ptr GetSelectedCallRenderDevice(); private: AudioDeviceManager(); @@ -157,6 +165,12 @@ private: sptr speaker_ = nullptr; sptr defalutMic_ = nullptr; bool hasEarpiece_ = false; + unordered_map> selectedDefaultOutputDeviceInfo_; + vector> mediaDefaultOutputDevices_; + vector> callDefaultOutputDevices_; + DeviceType selectedMediaDefaultOutputDevice_ = DEVICE_TYPE_DEFAULT; + DeviceType selectedCallDefaultOutputDevice_ = DEVICE_TYPE_DEFAULT; + std::mutex selectDefaultOutputDeviceMutex_; }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_policy/server/include/service/audio_policy_service.h b/services/audio_policy/server/include/service/audio_policy_service.h index 96b60a7eb5e4b90d55bfc4203e13b53d2163063b..e1cd6e7fe16c250019f922d9a288b06248fa6384 100644 --- a/services/audio_policy/server/include/service/audio_policy_service.h +++ b/services/audio_policy/server/include/service/audio_policy_service.h @@ -545,6 +545,9 @@ public: int32_t LoadSplitModule(const std::string &splitArgs, const std::string &networkId); + int32_t SetDefaultOutputDevice(const DeviceType deviceType, const uint32_t sessionID, + const StreamUsage streamUsage, bool isRunning); + private: AudioPolicyService() :audioPolicyManager_(AudioPolicyManagerFactory::GetAudioPolicyManager()), @@ -995,6 +998,7 @@ private: void UpdateDeviceList(AudioDeviceDescriptor &updatedDesc, bool isConnected, std::vector> &descForCb, AudioStreamDeviceChangeReasonExt &reason); + void UpdateDefaultOutputDeviceWhenStopping(int32_t uid); bool isUpdateRouteSupported_ = true; bool isCurrentRemoteRenderer = false; diff --git a/services/audio_policy/server/src/audio_policy_manager_stub.cpp b/services/audio_policy/server/src/audio_policy_manager_stub.cpp index 0e65c962741424948ce6b55b73d77ca1749f054a..3d12ef969c1ef0021dc1855a1f390056451e8a9b 100644 --- a/services/audio_policy/server/src/audio_policy_manager_stub.cpp +++ b/services/audio_policy/server/src/audio_policy_manager_stub.cpp @@ -163,6 +163,7 @@ const char *g_audioPolicyCodeStrs[] = { "DEACTIVATE_AUDIO_SESSION", "IS_AUDIO_SESSION_ACTIVATED", "LOAD_SPLIT_MODULE", + "SET_DEFAULT_OUTPUT_DEVICE", }; constexpr size_t codeNums = sizeof(g_audioPolicyCodeStrs) / sizeof(const char *); @@ -1285,6 +1286,16 @@ void AudioPolicyManagerStub::ReleaseAudioInterruptZoneInternal(MessageParcel &da reply.WriteInt32(result); } +void AudioPolicyManagerStub::SetDefaultOutputDeviceInternal(MessageParcel &data, MessageParcel &reply) +{ + DeviceType deviceType = static_cast(data.ReadInt32()); + uint32_t sessionID = data.ReadUint32(); + StreamUsage streamUsage = static_cast(data.ReadInt32()); + bool isRunning = data.ReadBool(); + int32_t result = SetDefaultOutputDevice(deviceType, sessionID, streamUsage, isRunning); + reply.WriteInt32(result); +} + void AudioPolicyManagerStub::OnMiddleNinRemoteRequest( uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { @@ -1301,6 +1312,9 @@ void AudioPolicyManagerStub::OnMiddleNinRemoteRequest( case static_cast(AudioPolicyInterfaceCode::SET_HEAD_TRACKING_ENABLED_FOR_DEVICE): SetHeadTrackingEnabledForDeviceInternal(data, reply); break; + case static_cast(AudioPolicyInterfaceCode::SET_DEFAULT_OUTPUT_DEVICE): + SetDefaultOutputDeviceInternal(data, reply); + break; default: AUDIO_ERR_LOG("default case, need check AudioPolicyManagerStub"); IPCObjectStub::OnRemoteRequest(code, data, reply, option); diff --git a/services/audio_policy/server/src/audio_policy_server.cpp b/services/audio_policy/server/src/audio_policy_server.cpp index dd45d9875e47039c6c334a2a246efdf85e29f3d8..fad72037405733341f339f013583f7e06c0da6b1 100644 --- a/services/audio_policy/server/src/audio_policy_server.cpp +++ b/services/audio_policy/server/src/audio_policy_server.cpp @@ -2835,5 +2835,11 @@ int32_t AudioPolicyServer::LoadSplitModule(const std::string &splitArgs, const s return audioPolicyService_.LoadSplitModule(splitArgs, networkId); } +int32_t AudioPolicyServer::SetDefaultOutputDevice(const DeviceType deviceType, const uint32_t sessionID, + const StreamUsage streamUsage, bool isRunning) +{ + return audioPolicyService_.SetDefaultOutputDevice(deviceType, sessionID, streamUsage, isRunning); +} + } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_policy/server/src/audio_stream_collector.cpp b/services/audio_policy/server/src/audio_stream_collector.cpp index 6d1e9325e36bfc7c51b8302ec75a53e5f4b43559..65c35201d82ba153d85c2897f586de7d3a2c73a8 100644 --- a/services/audio_policy/server/src/audio_stream_collector.cpp +++ b/services/audio_policy/server/src/audio_stream_collector.cpp @@ -1201,5 +1201,16 @@ StreamUsage AudioStreamCollector::GetLastestRunningCallStreamUsage() return STREAM_USAGE_UNKNOWN; } +std::vector AudioStreamCollector::GetAllRendererSessionIDForUID(int32_t uid) +{ + std::lock_guard lock(streamsInfoMutex_); + std::vector sessionIDSet; + for (const auto &changeInfo : audioRendererChangeInfos_) { + if (changeInfo->clientUID == uid) { + sessionIDSet.push_back(changeInfo->sessionId); + } + } + return sessionIDSet; +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_policy/server/src/service/audio_device_manager.cpp b/services/audio_policy/server/src/service/audio_device_manager.cpp index 2f333da8e5eadec90208769cfc1d3a412b0e9f28..164a75b51dd6109f9ac885cf0cf92ff24b87d164 100644 --- a/services/audio_policy/server/src/service/audio_device_manager.cpp +++ b/services/audio_policy/server/src/service/audio_device_manager.cpp @@ -1104,6 +1104,172 @@ int32_t AudioDeviceManager::UpdateDeviceDescDeviceId(sptr deviceDescriptor->deviceId_ = (*itr)->deviceId_; return SUCCESS; } + +int32_t AudioDeviceManager::SetDefaultOutputDevice(const DeviceType deviceType, const uint32_t sessionID, + const StreamUsage streamUsage, bool isRunning) +{ + std::lock_guard lock(selectDefaultOutputDeviceMutex_); + selectedDefaultOutputDeviceInfo_[sessionID] = std::make_pair(deviceType, streamUsage); + if (!isRunning) { + AUDIO_INFO_LOG("no need to set default output device since current stream has not started"); + return SUCCESS; + } + AUDIO_INFO_LOG("stream %{public}u with usage %{public}d selects output device %{public}d", + sessionID, streamUsage, deviceType); + if (streamUsage == STREAM_USAGE_VOICE_MESSAGE) { + // select media default output device + auto it = std::find_if(mediaDefaultOutputDevices_.begin(), mediaDefaultOutputDevices_.end(), + [&sessionID](const std::pair &mediaDefaultOutputDevice) { + return mediaDefaultOutputDevice.first == sessionID; + }); + if (it != mediaDefaultOutputDevices_.end()) { + mediaDefaultOutputDevices_.erase(it); + } + mediaDefaultOutputDevices_.push_back(std::make_pair(sessionID, deviceType)); + if (selectedMediaDefaultOutputDevice_ != deviceType) { + AUDIO_INFO_LOG("media default output device changes from %{public}d to %{public}d", + selectedMediaDefaultOutputDevice_, deviceType); + selectedMediaDefaultOutputDevice_ = deviceType; + return NEED_TO_FETCH; + } + } else if (streamUsage == STREAM_USAGE_VOICE_COMMUNICATION || streamUsage == STREAM_USAGE_VIDEO_COMMUNICATION || + streamUsage == STREAM_USAGE_VOICE_MODEM_COMMUNICATION) { + // select call default output device + auto it = std::find_if(callDefaultOutputDevices_.begin(), callDefaultOutputDevices_.end(), + [&sessionID](const std::pair &callDefaultOutputDevice) { + return callDefaultOutputDevice.first == sessionID; + }); + if (it != callDefaultOutputDevices_.end()) { + callDefaultOutputDevices_.erase(it); + } + callDefaultOutputDevices_.push_back(std::make_pair(sessionID, deviceType)); + if (selectedCallDefaultOutputDevice_ != deviceType) { + AUDIO_INFO_LOG("call default output device changes from %{public}d to %{public}d", + selectedCallDefaultOutputDevice_, deviceType); + selectedCallDefaultOutputDevice_ = deviceType; + return NEED_TO_FETCH; + } + } else { + AUDIO_ERR_LOG("Invalid stream usage %{public}d", streamUsage); + return ERROR; + } + return SUCCESS; +} + +int32_t AudioDeviceManager::UpdateDefaultOutputDeviceWhenStarting(const uint32_t sessionID) +{ + std::lock_guard lock(selectDefaultOutputDeviceMutex_); + if (!selectedDefaultOutputDeviceInfo_.count(sessionID)) { + AUDIO_DEBUG_LOG("no need to update default output device since current stream has not set"); + return SUCCESS; + } + DeviceType deviceType = selectedDefaultOutputDeviceInfo_[sessionID].first; + StreamUsage streamUsage = selectedDefaultOutputDeviceInfo_[sessionID].second; + if (streamUsage == STREAM_USAGE_VOICE_MESSAGE) { + // select media default output device + auto it = std::find_if(mediaDefaultOutputDevices_.begin(), mediaDefaultOutputDevices_.end(), + [&sessionID](const std::pair &mediaDefaultOutputDevice) { + return mediaDefaultOutputDevice.first == sessionID; + }); + if (it != mediaDefaultOutputDevices_.end()) { + mediaDefaultOutputDevices_.erase(it); + } + mediaDefaultOutputDevices_.push_back(std::make_pair(sessionID, deviceType)); + AUDIO_INFO_LOG("changes from %{public}d to %{public}d because media stream %{public}u starts", + selectedMediaDefaultOutputDevice_, deviceType, sessionID); + selectedMediaDefaultOutputDevice_ = deviceType; + } else if (streamUsage == STREAM_USAGE_VOICE_COMMUNICATION || streamUsage == STREAM_USAGE_VIDEO_COMMUNICATION || + streamUsage == STREAM_USAGE_VOICE_MODEM_COMMUNICATION) { + // select call default output device + auto it = std::find_if(callDefaultOutputDevices_.begin(), callDefaultOutputDevices_.end(), + [&sessionID](const std::pair &callDefaultOutputDevice) { + return callDefaultOutputDevice.first == sessionID; + }); + if (it != callDefaultOutputDevices_.end()) { + callDefaultOutputDevices_.erase(it); + } + callDefaultOutputDevices_.push_back(std::make_pair(sessionID, deviceType)); + AUDIO_INFO_LOG("changes from %{public}d to %{public}d because call stream %{public}u starts", + selectedCallDefaultOutputDevice_, deviceType, sessionID); + selectedCallDefaultOutputDevice_ = deviceType; + } + return SUCCESS; +} + +int32_t AudioDeviceManager::UpdateDefaultOutputDeviceWhenStopping(const uint32_t sessionID) +{ + std::lock_guard lock(selectDefaultOutputDeviceMutex_); + if (!selectedDefaultOutputDeviceInfo_.count(sessionID)) { + AUDIO_DEBUG_LOG("no need to update default output device since current stream has not set"); + return SUCCESS; + } + StreamUsage streamUsage = selectedDefaultOutputDeviceInfo_[sessionID].second; + if (streamUsage == STREAM_USAGE_VOICE_MESSAGE) { + // select media default output device + auto it = std::find_if(mediaDefaultOutputDevices_.begin(), mediaDefaultOutputDevices_.end(), + [&sessionID](const std::pair &mediaDefaultOutputDevice) { + return mediaDefaultOutputDevice.first == sessionID; + }); + if (it == mediaDefaultOutputDevices_.end()) { + return SUCCESS; + } + mediaDefaultOutputDevices_.erase(it); + DeviceType currDeviceType; + if (mediaDefaultOutputDevices_.empty()) { + currDeviceType = DEVICE_TYPE_DEFAULT; + } else { + currDeviceType = mediaDefaultOutputDevices_.back().second; + } + AUDIO_INFO_LOG("changes from %{public}d to %{public}d because media stream %{public}u stops", + selectedMediaDefaultOutputDevice_, currDeviceType, sessionID); + selectedMediaDefaultOutputDevice_ = currDeviceType; + } else if (streamUsage == STREAM_USAGE_VOICE_COMMUNICATION || streamUsage == STREAM_USAGE_VIDEO_COMMUNICATION || + streamUsage == STREAM_USAGE_VOICE_MODEM_COMMUNICATION) { + // select call default output device + auto it = std::find_if(callDefaultOutputDevices_.begin(), callDefaultOutputDevices_.end(), + [&sessionID](const std::pair &callDefaultOutputDevice) { + return callDefaultOutputDevice.first == sessionID; + }); + if (it == callDefaultOutputDevices_.end()) { + return SUCCESS; + } + callDefaultOutputDevices_.erase(it); + DeviceType currDeviceType; + if (callDefaultOutputDevices_.empty()) { + currDeviceType = DEVICE_TYPE_DEFAULT; + } else { + currDeviceType = callDefaultOutputDevices_.back().second; + } + AUDIO_INFO_LOG("changes from %{public}d to %{public}d because call stream %{public}u stops", + selectedCallDefaultOutputDevice_, currDeviceType, sessionID); + selectedCallDefaultOutputDevice_ = currDeviceType; + } + return SUCCESS; +} + +unique_ptr AudioDeviceManager::GetSelectedMediaRenderDevice() +{ + std::lock_guard lock(selectDefaultOutputDeviceMutex_); + unique_ptr devDesc = nullptr; + if (selectedMediaDefaultOutputDevice_ == DEVICE_TYPE_EARPIECE) { + devDesc = make_unique(earpiece_); + } else if (selectedMediaDefaultOutputDevice_ == DEVICE_TYPE_SPEAKER) { + devDesc = make_unique(speaker_); + } + return devDesc; +} + +unique_ptr AudioDeviceManager::GetSelectedCallRenderDevice() +{ + std::lock_guard lock(selectDefaultOutputDeviceMutex_); + unique_ptr devDesc = nullptr; + if (selectedCallDefaultOutputDevice_ == DEVICE_TYPE_EARPIECE) { + devDesc = make_unique(earpiece_); + } else if (selectedCallDefaultOutputDevice_ == DEVICE_TYPE_SPEAKER) { + devDesc = make_unique(speaker_); + } + return devDesc; +} // LCOV_EXCL_STOP } } diff --git a/services/audio_policy/server/src/service/audio_policy_service.cpp b/services/audio_policy/server/src/service/audio_policy_service.cpp index 8957063be7b40daba57953c2ac166ed10505ee70..cf7e438af2787ef063df81fce7acc3599cd6a5ca 100644 --- a/services/audio_policy/server/src/service/audio_policy_service.cpp +++ b/services/audio_policy/server/src/service/audio_policy_service.cpp @@ -4914,7 +4914,9 @@ int32_t AudioPolicyService::UpdateTracker(AudioMode &mode, AudioStreamChangeInfo DynamicUnloadModule(PIPE_TYPE_MULTICHANNEL); } - if (mode == AUDIO_MODE_PLAYBACK && (rendererState == RENDERER_STOPPED || rendererState == RENDERER_PAUSED)) { + if (mode == AUDIO_MODE_PLAYBACK && (rendererState == RENDERER_STOPPED || rendererState == RENDERER_PAUSED || + rendererState == RENDERER_RELEASED)) { + audioDeviceManager_.UpdateDefaultOutputDeviceWhenStopping(streamChangeInfo.audioRendererChangeInfo.sessionId); FetchDevice(true); } @@ -4963,6 +4965,8 @@ void AudioPolicyService::FetchOutputDeviceForTrack(AudioStreamChangeInfo &stream make_unique(streamChangeInfo.audioRendererChangeInfo)); streamCollector_.GetRendererStreamInfo(streamChangeInfo, *rendererChangeInfo[0]); + audioDeviceManager_.UpdateDefaultOutputDeviceWhenStarting(streamChangeInfo.audioRendererChangeInfo.sessionId); + FetchOutputDevice(rendererChangeInfo, reason); } @@ -5041,6 +5045,8 @@ void AudioPolicyService::RegisteredTrackerClientDied(pid_t uid) { std::lock_guard deviceLock(deviceStatusUpdateSharedMutex_); + UpdateDefaultOutputDeviceWhenStopping(static_cast(uid)); + RemoveAudioCapturerMicrophoneDescriptor(static_cast(uid)); streamCollector_.RegisteredTrackerClientDied(static_cast(uid)); @@ -8467,6 +8473,27 @@ int32_t AudioPolicyService::LoadSplitModule(const std::string &splitArgs, const return openRet; } +int32_t AudioPolicyService::SetDefaultOutputDevice(const DeviceType deviceType, const uint32_t sessionID, + const StreamUsage streamUsage, bool isRunning) +{ + CHECK_AND_RETURN_RET_LOG(hasEarpiece_, ERR_NOT_SUPPORTED, "the device has no earpiece"); + int32_t ret = audioDeviceManager_.SetDefaultOutputDevice(deviceType, sessionID, streamUsage, isRunning); + if (ret == NEED_TO_FETCH) { + FetchDevice(true); + return SUCCESS; + } + return ret; +} + +void AudioPolicyService::UpdateDefaultOutputDeviceWhenStopping(int32_t uid) +{ + std::vector sessionIDSet = streamCollector_.GetAllRendererSessionIDForUID(uid); + for (const auto &sessionID : sessionIDSet) { + audioDeviceManager_.UpdateDefaultOutputDeviceWhenStopping(sessionID); + } + FetchDevice(true); +} + void AudioA2dpOffloadManager::OnA2dpPlayingStateChanged(const std::string &deviceAddress, int32_t playingState) { AUDIO_INFO_LOG("Current A2dpOffload MacAddr:%{public}s, incoming MacAddr:%{public}s, state:%{public}d", diff --git a/services/audio_policy/server/src/service/routers/default_router.cpp b/services/audio_policy/server/src/service/routers/default_router.cpp index 6275146a1d00f003b74813b5fe2189f6775a11d9..b895e4e24ef90e1a1f369dbbb767b6743f34f430 100644 --- a/services/audio_policy/server/src/service/routers/default_router.cpp +++ b/services/audio_policy/server/src/service/routers/default_router.cpp @@ -25,7 +25,10 @@ namespace AudioStandard { unique_ptr DefaultRouter::GetMediaRenderDevice(StreamUsage streamUsage, int32_t clientUID) { - unique_ptr desc = AudioDeviceManager::GetAudioDeviceManager().GetRenderDefaultDevice(); + unique_ptr desc = AudioDeviceManager::GetAudioDeviceManager().GetSelectedMediaRenderDevice(); + if (desc == nullptr) { + desc = AudioDeviceManager::GetAudioDeviceManager().GetRenderDefaultDevice(); + } AUDIO_DEBUG_LOG("streamUsage %{public}d clientUID %{public}d fetch device %{public}d", streamUsage, clientUID, desc->deviceType_); return desc; @@ -33,8 +36,10 @@ unique_ptr DefaultRouter::GetMediaRenderDevice(StreamUsag unique_ptr DefaultRouter::GetCallRenderDevice(StreamUsage streamUsage, int32_t clientUID) { - unique_ptr desc = - AudioDeviceManager::GetAudioDeviceManager().GetCommRenderDefaultDevice(streamUsage); + unique_ptr desc = AudioDeviceManager::GetAudioDeviceManager().GetSelectedCallRenderDevice(); + if (desc == nullptr) { + desc = AudioDeviceManager::GetAudioDeviceManager().GetCommRenderDefaultDevice(streamUsage); + } AUDIO_DEBUG_LOG("streamUsage %{public}d clientUID %{public}d fetch device %{public}d", streamUsage, clientUID, desc->deviceType_); return desc;