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