1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "audio_concurrency_service.h"
16 #include "audio_concurrency_state_listener_proxy.h"
17
18 namespace OHOS {
19 namespace AudioStandard {
Init()20 void AudioConcurrencyService::Init()
21 {
22 AUDIO_INFO_LOG("AudioConcurrencyService Init");
23 std::unique_ptr<AudioConcurrencyParser> parser = std::make_unique<AudioConcurrencyParser>();
24 CHECK_AND_RETURN_LOG(parser != nullptr, "Create audioConcurrency parser failed!");
25 CHECK_AND_RETURN_LOG(!parser->LoadConfig(concurrencyCfgMap_), "Load audioConcurrency cfgMap failed!");
26 }
27
DispatchConcurrencyEventWithSessionId(uint32_t sessionID)28 void AudioConcurrencyService::DispatchConcurrencyEventWithSessionId(uint32_t sessionID)
29 {
30 CHECK_AND_RETURN_LOG(sessionID >= MIN_SESSIONID && sessionID <= MAX_SESSIONID,
31 "EntryPoint Taint Mark:arg sessionID: %{public}u is tained", sessionID);
32 std::lock_guard<std::mutex> lock(cbMapMutex_);
33 AUDIO_DEBUG_LOG("DispatchConcurrencyEventWithSessionId %{public}d", sessionID);
34 CHECK_AND_RETURN_LOG(concurrencyClients_.find(sessionID) != concurrencyClients_.end(),
35 "session %{public}u not exist", sessionID);
36 concurrencyClients_[sessionID]->OnConcedeStream();
37 }
38
AudioConcurrencyDeathRecipient(const std::shared_ptr<AudioConcurrencyService> & service,uint32_t sessionID)39 AudioConcurrencyService::AudioConcurrencyDeathRecipient::AudioConcurrencyDeathRecipient(
40 const std::shared_ptr<AudioConcurrencyService> &service, uint32_t sessionID)
41 : service_(service), sessionID_(sessionID)
42 {
43 }
44
OnRemoteDied(const wptr<IRemoteObject> & remote)45 void AudioConcurrencyService::AudioConcurrencyDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
46 {
47 std::shared_ptr<AudioConcurrencyService> service = service_.lock();
48 if (service != nullptr) {
49 service->UnsetAudioConcurrencyCallback(sessionID_);
50 }
51 }
52
AudioConcurrencyClient(const std::shared_ptr<AudioConcurrencyCallback> & callback,const sptr<IRemoteObject> & object,const sptr<AudioConcurrencyDeathRecipient> & deathRecipient,uint32_t sessionID)53 AudioConcurrencyService::AudioConcurrencyClient::AudioConcurrencyClient(
54 const std::shared_ptr<AudioConcurrencyCallback> &callback, const sptr<IRemoteObject> &object,
55 const sptr<AudioConcurrencyDeathRecipient> &deathRecipient, uint32_t sessionID)
56 : callback_(callback), object_(object), deathRecipient_(deathRecipient), sessionID_(sessionID)
57 {
58 AUDIO_DEBUG_LOG("callback ctor, sessionID %{public}u", sessionID_);
59 }
60
~AudioConcurrencyClient()61 AudioConcurrencyService::AudioConcurrencyClient::~AudioConcurrencyClient()
62 {
63 AUDIO_DEBUG_LOG("callback dtor, sessionID %{public}u", sessionID_);
64 if (object_ != nullptr) {
65 object_->RemoveDeathRecipient(deathRecipient_);
66 }
67 }
68
SetAudioConcurrencyCallback(const uint32_t sessionID,const sptr<IRemoteObject> & object)69 int32_t AudioConcurrencyService::SetAudioConcurrencyCallback(const uint32_t sessionID,
70 const sptr<IRemoteObject> &object)
71 {
72 std::lock_guard<std::mutex> lock(cbMapMutex_);
73
74 // maybe add check session id validation here
75
76 CHECK_AND_RETURN_RET_LOG(object != nullptr, ERR_INVALID_PARAM, "AudioConcurrencytCb object is nullptr");
77
78 sptr<IStandardConcurrencyStateListener> listener = iface_cast<IStandardConcurrencyStateListener>(object);
79 CHECK_AND_RETURN_RET_LOG(listener != nullptr, ERR_INVALID_PARAM, "AudioConcurrencytCb obj cast failed");
80
81 std::shared_ptr<AudioConcurrencyCallback> callback = std::make_shared<AudioConcurrencyListenerCallback>(listener);
82 CHECK_AND_RETURN_RET_LOG(callback != nullptr, ERR_INVALID_PARAM, "AudioConcurrencyService create cb failed");
83
84 if (concurrencyClients_.find(sessionID) == concurrencyClients_.end()) {
85 sptr<AudioConcurrencyDeathRecipient> deathRecipient = new
86 AudioConcurrencyDeathRecipient(shared_from_this(), sessionID);
87 object->AddDeathRecipient(deathRecipient);
88 std::shared_ptr<AudioConcurrencyClient> client =
89 std::make_shared<AudioConcurrencyClient>(callback, object, deathRecipient, sessionID);
90 concurrencyClients_[sessionID] = client;
91 } else {
92 AUDIO_ERR_LOG("session %{public}u already exist", sessionID);
93 return ERR_INVALID_PARAM;
94 }
95
96 return SUCCESS;
97 }
98
UnsetAudioConcurrencyCallback(const uint32_t sessionID)99 int32_t AudioConcurrencyService::UnsetAudioConcurrencyCallback(const uint32_t sessionID)
100 {
101 std::lock_guard<std::mutex> lock(cbMapMutex_);
102
103 if (concurrencyClients_.erase(sessionID) == 0) {
104 AUDIO_ERR_LOG("session %{public}u not present", sessionID);
105 return ERR_INVALID_PARAM;
106 }
107 return SUCCESS;
108 }
109
SetCallbackHandler(std::shared_ptr<AudioPolicyServerHandler> handler)110 void AudioConcurrencyService::SetCallbackHandler(std::shared_ptr<AudioPolicyServerHandler> handler)
111 {
112 handler_ = handler;
113 }
114
OnConcedeStream()115 void AudioConcurrencyService::AudioConcurrencyClient::OnConcedeStream()
116 {
117 if (callback_ != nullptr) {
118 callback_->OnConcedeStream();
119 }
120 }
121
ActivateAudioConcurrency(AudioPipeType incomingPipeType,const std::vector<std::unique_ptr<AudioRendererChangeInfo>> & audioRendererChangeInfos,const std::vector<std::unique_ptr<AudioCapturerChangeInfo>> & audioCapturerChangeInfos)122 int32_t AudioConcurrencyService::ActivateAudioConcurrency(AudioPipeType incomingPipeType,
123 const std::vector<std::unique_ptr<AudioRendererChangeInfo>> &audioRendererChangeInfos,
124 const std::vector<std::unique_ptr<AudioCapturerChangeInfo>> &audioCapturerChangeInfos)
125 {
126 AUDIO_DEBUG_LOG("ActivateAudioConcurrency incoming pipe %{public}d", incomingPipeType);
127 if (concurrencyCfgMap_.empty()) {
128 return SUCCESS;
129 }
130 for (auto it = audioRendererChangeInfos.begin(); it != audioRendererChangeInfos.end(); it++) {
131 if ((*it)->rendererInfo.pipeType == incomingPipeType && (incomingPipeType == PIPE_TYPE_OFFLOAD ||
132 incomingPipeType == PIPE_TYPE_MULTICHANNEL)) {
133 continue;
134 }
135 CHECK_AND_RETURN_RET_LOG(concurrencyCfgMap_[std::make_pair((*it)->rendererInfo.pipeType, incomingPipeType)] !=
136 CONCEDE_INCOMING, ERR_CONCEDE_INCOMING_STREAM, "existing session %{public}d, "
137 "pipe %{public}d, concede incoming pipe %{public}d", (*it)->sessionId, (*it)->rendererInfo.pipeType,
138 incomingPipeType);
139 }
140 for (auto it = audioCapturerChangeInfos.begin(); it != audioCapturerChangeInfos.end(); it++) {
141 CHECK_AND_RETURN_RET_LOG(concurrencyCfgMap_[std::make_pair((*it)->capturerInfo.pipeType, incomingPipeType)] !=
142 CONCEDE_INCOMING, ERR_CONCEDE_INCOMING_STREAM, "existing session %{public}d, "
143 "pipe %{public}d, concede incoming pipe %{public}d", (*it)->sessionId, (*it)->capturerInfo.pipeType,
144 incomingPipeType);
145 }
146 for (auto it = audioRendererChangeInfos.begin(); it != audioRendererChangeInfos.end(); it++) {
147 if ((*it)->rendererInfo.pipeType == incomingPipeType && (incomingPipeType == PIPE_TYPE_OFFLOAD ||
148 incomingPipeType == PIPE_TYPE_MULTICHANNEL)) {
149 continue;
150 }
151 ConcurrencyAction action = concurrencyCfgMap_[std::make_pair((*it)->rendererInfo.pipeType, incomingPipeType)];
152 if (action == CONCEDE_EXISTING && handler_ != nullptr) {
153 handler_->SendConcurrencyEventWithSessionIDCallback((*it)->sessionId);
154 }
155 }
156 for (auto it = audioCapturerChangeInfos.begin(); it != audioCapturerChangeInfos.end(); it++) {
157 ConcurrencyAction action = concurrencyCfgMap_[std::make_pair((*it)->capturerInfo.pipeType, incomingPipeType)];
158 if (action == CONCEDE_EXISTING && handler_ != nullptr) {
159 handler_->SendConcurrencyEventWithSessionIDCallback((*it)->sessionId);
160 }
161 }
162 return SUCCESS;
163 }
164 } // namespace AudioStandard
165 } // namespace OHOS