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 #ifndef LOG_TAG
16 #define LOG_TAG "AudioConcurrencyService"
17 #endif
18
19 #include "audio_utils.h"
20 #include "audio_stream_collector.h"
21 #include "audio_concurrency_service.h"
22 #include "audio_concurrency_state_listener_proxy.h"
23
24 namespace OHOS {
25 namespace AudioStandard {
Init()26 void AudioConcurrencyService::Init()
27 {
28 AUDIO_INFO_LOG("AudioConcurrencyService Init");
29 std::unique_ptr<AudioConcurrencyParser> parser = std::make_unique<AudioConcurrencyParser>();
30 CHECK_AND_RETURN_LOG(parser != nullptr, "Create audioConcurrency parser failed!");
31 CHECK_AND_RETURN_LOG(!parser->LoadConfig(concurrencyCfgMap_), "Load audioConcurrency cfgMap failed!");
32 }
33
DispatchConcurrencyEventWithSessionId(uint32_t sessionID)34 void AudioConcurrencyService::DispatchConcurrencyEventWithSessionId(uint32_t sessionID)
35 {
36 CHECK_AND_RETURN_LOG(sessionID >= MIN_STREAMID && sessionID <= MAX_STREAMID,
37 "EntryPoint Taint Mark:arg sessionID: %{public}u is tained", sessionID);
38 std::lock_guard<std::mutex> lock(cbMapMutex_);
39 AUDIO_DEBUG_LOG("DispatchConcurrencyEventWithSessionId %{public}d", sessionID);
40 CHECK_AND_RETURN_LOG(concurrencyClients_.find(sessionID) != concurrencyClients_.end(),
41 "session %{public}u not exist", sessionID);
42 concurrencyClients_[sessionID]->OnConcedeStream();
43 }
44
AudioConcurrencyDeathRecipient(const std::shared_ptr<AudioConcurrencyService> & service,uint32_t sessionID)45 AudioConcurrencyService::AudioConcurrencyDeathRecipient::AudioConcurrencyDeathRecipient(
46 const std::shared_ptr<AudioConcurrencyService> &service, uint32_t sessionID)
47 : service_(service), sessionID_(sessionID)
48 {
49 }
50
OnRemoteDied(const wptr<IRemoteObject> & remote)51 void AudioConcurrencyService::AudioConcurrencyDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
52 {
53 std::shared_ptr<AudioConcurrencyService> service = service_.lock();
54 if (service != nullptr) {
55 service->UnsetAudioConcurrencyCallback(sessionID_);
56 }
57 }
58
AudioConcurrencyClient(const std::shared_ptr<AudioConcurrencyCallback> & callback,const sptr<IRemoteObject> & object,const sptr<AudioConcurrencyDeathRecipient> & deathRecipient,uint32_t sessionID)59 AudioConcurrencyService::AudioConcurrencyClient::AudioConcurrencyClient(
60 const std::shared_ptr<AudioConcurrencyCallback> &callback, const sptr<IRemoteObject> &object,
61 const sptr<AudioConcurrencyDeathRecipient> &deathRecipient, uint32_t sessionID)
62 : callback_(callback), object_(object), deathRecipient_(deathRecipient), sessionID_(sessionID)
63 {
64 AUDIO_DEBUG_LOG("callback ctor, sessionID %{public}u", sessionID_);
65 }
66
~AudioConcurrencyClient()67 AudioConcurrencyService::AudioConcurrencyClient::~AudioConcurrencyClient()
68 {
69 AUDIO_DEBUG_LOG("callback dtor, sessionID %{public}u", sessionID_);
70 if (object_ != nullptr) {
71 object_->RemoveDeathRecipient(deathRecipient_);
72 }
73 }
74
SetAudioConcurrencyCallback(const uint32_t sessionID,const sptr<IRemoteObject> & object)75 int32_t AudioConcurrencyService::SetAudioConcurrencyCallback(const uint32_t sessionID,
76 const sptr<IRemoteObject> &object)
77 {
78 std::lock_guard<std::mutex> lock(cbMapMutex_);
79
80 // maybe add check session id validation here
81
82 CHECK_AND_RETURN_RET_LOG(object != nullptr, ERR_INVALID_PARAM, "AudioConcurrencytCb object is nullptr");
83
84 sptr<IStandardConcurrencyStateListener> listener = iface_cast<IStandardConcurrencyStateListener>(object);
85 CHECK_AND_RETURN_RET_LOG(listener != nullptr, ERR_INVALID_PARAM, "AudioConcurrencytCb obj cast failed");
86
87 std::shared_ptr<AudioConcurrencyCallback> callback = std::make_shared<AudioConcurrencyListenerCallback>(listener);
88 CHECK_AND_RETURN_RET_LOG(callback != nullptr, ERR_INVALID_PARAM, "AudioConcurrencyService create cb failed");
89
90 if (concurrencyClients_.find(sessionID) == concurrencyClients_.end()) {
91 sptr<AudioConcurrencyDeathRecipient> deathRecipient = new
92 AudioConcurrencyDeathRecipient(shared_from_this(), sessionID);
93 object->AddDeathRecipient(deathRecipient);
94 std::shared_ptr<AudioConcurrencyClient> client =
95 std::make_shared<AudioConcurrencyClient>(callback, object, deathRecipient, sessionID);
96 concurrencyClients_[sessionID] = client;
97 } else {
98 AUDIO_ERR_LOG("session %{public}u already exist", sessionID);
99 return ERR_INVALID_PARAM;
100 }
101
102 return SUCCESS;
103 }
104
UnsetAudioConcurrencyCallback(const uint32_t sessionID)105 int32_t AudioConcurrencyService::UnsetAudioConcurrencyCallback(const uint32_t sessionID)
106 {
107 std::lock_guard<std::mutex> lock(cbMapMutex_);
108
109 if (concurrencyClients_.erase(sessionID) == 0) {
110 AUDIO_ERR_LOG("session %{public}u not present", sessionID);
111 return ERR_INVALID_PARAM;
112 }
113 return SUCCESS;
114 }
115
SetCallbackHandler(std::shared_ptr<AudioPolicyServerHandler> handler)116 void AudioConcurrencyService::SetCallbackHandler(std::shared_ptr<AudioPolicyServerHandler> handler)
117 {
118 handler_ = handler;
119 }
120
OnConcedeStream()121 void AudioConcurrencyService::AudioConcurrencyClient::OnConcedeStream()
122 {
123 if (callback_ != nullptr) {
124 AudioStreamCollector &streamCollector = AudioStreamCollector::GetAudioStreamCollector();
125 std::vector<std::shared_ptr<AudioCapturerChangeInfo>> capturerChangeInfos;
126 streamCollector.GetCurrentCapturerChangeInfos(capturerChangeInfos);
127 for (auto &capturerChangeInfo : capturerChangeInfos) {
128 uint32_t tmpSessionId = static_cast<uint32_t>(capturerChangeInfo->sessionId);
129 if (tmpSessionId == sessionID_) {
130 SwitchStreamInfo info = {
131 sessionID_,
132 capturerChangeInfo->createrUID,
133 capturerChangeInfo->clientUID,
134 capturerChangeInfo->clientPid,
135 capturerChangeInfo->appTokenId,
136 capturerChangeInfo->capturerState,
137 };
138 SwitchStreamUtil::UpdateSwitchStreamRecord(info, SWITCH_STATE_WAITING);
139 break;
140 }
141 }
142 callback_->OnConcedeStream();
143 }
144 }
145
ActivateAudioConcurrency(AudioPipeType incomingPipeType,const std::vector<std::shared_ptr<AudioRendererChangeInfo>> & audioRendererChangeInfos,const std::vector<std::shared_ptr<AudioCapturerChangeInfo>> & audioCapturerChangeInfos)146 int32_t AudioConcurrencyService::ActivateAudioConcurrency(AudioPipeType incomingPipeType,
147 const std::vector<std::shared_ptr<AudioRendererChangeInfo>> &audioRendererChangeInfos,
148 const std::vector<std::shared_ptr<AudioCapturerChangeInfo>> &audioCapturerChangeInfos)
149 {
150 if (concurrencyCfgMap_.empty()) {
151 return SUCCESS;
152 }
153 for (auto it = audioRendererChangeInfos.begin(); it != audioRendererChangeInfos.end(); it++) {
154 if ((*it)->rendererInfo.pipeType == incomingPipeType && (incomingPipeType == PIPE_TYPE_OFFLOAD ||
155 incomingPipeType == PIPE_TYPE_MULTICHANNEL)) {
156 continue;
157 }
158 CHECK_AND_RETURN_RET_LOG(concurrencyCfgMap_[std::make_pair((*it)->rendererInfo.pipeType, incomingPipeType)] !=
159 CONCEDE_INCOMING, ERR_CONCEDE_INCOMING_STREAM, "existing session %{public}d, "
160 "pipe %{public}d, concede incoming pipe %{public}d", (*it)->sessionId, (*it)->rendererInfo.pipeType,
161 incomingPipeType);
162 }
163 for (auto it = audioCapturerChangeInfos.begin(); it != audioCapturerChangeInfos.end(); it++) {
164 CHECK_AND_RETURN_RET_LOG(concurrencyCfgMap_[std::make_pair((*it)->capturerInfo.pipeType, incomingPipeType)] !=
165 CONCEDE_INCOMING, ERR_CONCEDE_INCOMING_STREAM, "existing session %{public}d, "
166 "pipe %{public}d, concede incoming pipe %{public}d", (*it)->sessionId, (*it)->capturerInfo.pipeType,
167 incomingPipeType);
168 }
169 bool concedeIncomingVoipCap = false;
170 for (auto it = audioRendererChangeInfos.begin(); it != audioRendererChangeInfos.end(); it++) {
171 if ((*it)->rendererInfo.pipeType == incomingPipeType && (incomingPipeType == PIPE_TYPE_OFFLOAD ||
172 incomingPipeType == PIPE_TYPE_MULTICHANNEL)) {
173 continue;
174 }
175 ConcurrencyAction action = concurrencyCfgMap_[std::make_pair((*it)->rendererInfo.pipeType, incomingPipeType)];
176 if (action == CONCEDE_EXISTING && handler_ != nullptr) {
177 handler_->SendConcurrencyEventWithSessionIDCallback((*it)->sessionId);
178 }
179 }
180 for (auto it = audioCapturerChangeInfos.begin(); it != audioCapturerChangeInfos.end(); it++) {
181 ConcurrencyAction action = concurrencyCfgMap_[std::make_pair((*it)->capturerInfo.pipeType, incomingPipeType)];
182 if (action == CONCEDE_EXISTING && handler_ != nullptr) {
183 if (incomingPipeType == PIPE_TYPE_CALL_IN && (*it)->capturerInfo.pipeType == PIPE_TYPE_CALL_IN) {
184 concedeIncomingVoipCap = true;
185 }
186 handler_->SendConcurrencyEventWithSessionIDCallback((*it)->sessionId);
187 }
188 }
189 CHECK_AND_RETURN_RET_LOG(!concedeIncomingVoipCap, ERR_CONCEDE_INCOMING_STREAM,
190 "Existing call in concede incoming call in");
191 return SUCCESS;
192 }
193 } // namespace AudioStandard
194 } // namespace OHOS