1 /*
2 * Copyright (c) 2025 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 "AudioPipeSelector"
17 #endif
18
19 #include "audio_pipe_selector.h"
20 #include "audio_stream_collector.h"
21 #include "audio_stream_info.h"
22 #include "audio_definition_adapter_info.h"
23 #include "audio_policy_utils.h"
24 #include <algorithm>
25
26 namespace OHOS {
27 namespace AudioStandard {
28
29 static std::map<int, AudioPipeType> flagPipeTypeMap_ = {
30 {AUDIO_OUTPUT_FLAG_NORMAL, PIPE_TYPE_NORMAL_OUT},
31 {AUDIO_INPUT_FLAG_NORMAL, PIPE_TYPE_NORMAL_IN},
32 {AUDIO_OUTPUT_FLAG_FAST, PIPE_TYPE_NORMAL_OUT},
33 {AUDIO_INPUT_FLAG_FAST, PIPE_TYPE_NORMAL_IN},
34 {AUDIO_OUTPUT_FLAG_LOWPOWER, PIPE_TYPE_OFFLOAD},
35 {AUDIO_OUTPUT_FLAG_MULTICHANNEL, PIPE_TYPE_MULTICHANNEL},
36 {AUDIO_OUTPUT_FLAG_DIRECT, PIPE_TYPE_DIRECT_OUT},
37 };
38
IsRemoteOffloadNeedRecreate(std::shared_ptr<AudioPipeInfo> newPipe,std::shared_ptr<AudioPipeInfo> oldPipe)39 static bool IsRemoteOffloadNeedRecreate(std::shared_ptr<AudioPipeInfo> newPipe, std::shared_ptr<AudioPipeInfo> oldPipe)
40 {
41 CHECK_AND_RETURN_RET(newPipe != nullptr && oldPipe != nullptr, false);
42 CHECK_AND_RETURN_RET(newPipe->moduleInfo_.className == "remote_offload" &&
43 oldPipe->moduleInfo_.className == "remote_offload", false);
44 return (newPipe->moduleInfo_.format != oldPipe->moduleInfo_.format) ||
45 (newPipe->moduleInfo_.rate != oldPipe->moduleInfo_.rate) ||
46 (newPipe->moduleInfo_.channels != oldPipe->moduleInfo_.channels) ||
47 (newPipe->moduleInfo_.bufferSize != oldPipe->moduleInfo_.bufferSize);
48 }
49
AudioPipeSelector()50 AudioPipeSelector::AudioPipeSelector() : configManager_(AudioPolicyConfigManager::GetInstance())
51 {
52 }
53
GetPipeSelector()54 std::shared_ptr<AudioPipeSelector> AudioPipeSelector::GetPipeSelector()
55 {
56 static std::shared_ptr<AudioPipeSelector> instance = std::make_shared<AudioPipeSelector>();
57 return instance;
58 }
59
FetchPipeAndExecute(std::shared_ptr<AudioStreamDescriptor> & streamDesc)60 std::vector<std::shared_ptr<AudioPipeInfo>> AudioPipeSelector::FetchPipeAndExecute(
61 std::shared_ptr<AudioStreamDescriptor> &streamDesc)
62 {
63 std::vector<std::shared_ptr<AudioPipeInfo>> pipeInfoList = AudioPipeManager::GetPipeManager()->GetPipeList();
64
65 if (streamDesc->routeFlag_ == AUDIO_FLAG_NONE) {
66 AUDIO_INFO_LOG("Need update route flag");
67 ScanPipeListForStreamDesc(pipeInfoList, streamDesc);
68 }
69 AUDIO_INFO_LOG("Original Pipelist size: %{public}zu, stream routeFlag: 0x%{public}x to fetch",
70 pipeInfoList.size(), streamDesc->routeFlag_);
71
72 std::vector<std::shared_ptr<AudioPipeInfo>> selectedPipeInfoList {};
73 for (auto &curPipeInfo : pipeInfoList) {
74 if (curPipeInfo->pipeRole_ == static_cast<AudioPipeRole>(streamDesc->audioMode_)) {
75 selectedPipeInfoList.push_back(curPipeInfo);
76 }
77 }
78
79 streamDesc->streamAction_ = AUDIO_STREAM_ACTION_NEW;
80 std::shared_ptr<PipeStreamPropInfo> streamPropInfo = std::make_shared<PipeStreamPropInfo>();
81 configManager_.GetStreamPropInfo(streamDesc, streamPropInfo);
82 UpdataDeviceStreamInfo(streamDesc, streamPropInfo);
83 std::shared_ptr<AdapterPipeInfo> pipeInfoPtr = streamPropInfo->pipeInfo_.lock();
84 if (pipeInfoPtr == nullptr) {
85 AUDIO_ERR_LOG("Pipe info is null");
86 return selectedPipeInfoList;
87 }
88 for (auto &pipeInfo : selectedPipeInfoList) {
89 std::shared_ptr<PolicyAdapterInfo> adapterInfoPtr = pipeInfoPtr->adapterInfo_.lock();
90 if (adapterInfoPtr == nullptr) {
91 AUDIO_ERR_LOG("Adapter info is null");
92 continue;
93 }
94 AUDIO_INFO_LOG("[Cur][XML]: {adapterName}[%{public}s][%{public}s], {routeFlag}[%{public}x][%{public}x]",
95 pipeInfo->adapterName_.c_str(), adapterInfoPtr->adapterName.c_str(),
96 pipeInfo->routeFlag_, streamDesc->routeFlag_);
97
98 if (pipeInfo->adapterName_ == adapterInfoPtr->adapterName &&
99 pipeInfo->routeFlag_ == streamDesc->routeFlag_) {
100 pipeInfo->streamDescriptors_.push_back(streamDesc);
101 pipeInfo->streamDescMap_[streamDesc->sessionId_] = streamDesc;
102 pipeInfo->pipeAction_ = PIPE_ACTION_UPDATE;
103 AUDIO_INFO_LOG("[PipeFetchInfo] use existing Pipe %{public}s for stream %{public}u",
104 pipeInfo->ToString().c_str(), streamDesc->sessionId_);
105 return selectedPipeInfoList;
106 }
107 }
108 AudioPipeInfo info = {};
109 ConvertStreamDescToPipeInfo(streamDesc, streamPropInfo, info);
110 info.pipeAction_ = PIPE_ACTION_NEW;
111 selectedPipeInfoList.push_back(std::make_shared<AudioPipeInfo>(info));
112 AUDIO_INFO_LOG("[PipeFetchInfo] use new Pipe %{public}s for stream %{public}u",
113 info.ToString().c_str(), streamDesc->sessionId_);
114 return selectedPipeInfoList;
115 }
116
UpdataDeviceStreamInfo(std::shared_ptr<AudioStreamDescriptor> & streamDesc,std::shared_ptr<PipeStreamPropInfo> streamPropInfo)117 void AudioPipeSelector::UpdataDeviceStreamInfo(std::shared_ptr<AudioStreamDescriptor> &streamDesc,
118 std::shared_ptr<PipeStreamPropInfo> streamPropInfo)
119 {
120 if (streamDesc->newDeviceDescs_.empty() || streamPropInfo == nullptr || streamDesc->newDeviceDescs_.front() ==
121 nullptr) {
122 AUDIO_WARNING_LOG("new device desc is empty!");
123 return;
124 }
125 std::shared_ptr<AudioDeviceDescriptor> temp = streamDesc->newDeviceDescs_.front();
126 DeviceStreamInfo streamInfo;
127 streamInfo.format = streamPropInfo->format_;
128 streamInfo.samplingRate = {static_cast<AudioSamplingRate>(streamPropInfo->sampleRate_)};
129 streamInfo.SetChannels({streamPropInfo->channels_});
130 temp->audioStreamInfo_ = {streamInfo};
131 std::string info = streamInfo.Serialize();
132 AUDIO_INFO_LOG("DeviceStreamInfo:%{public}s", info.c_str());
133 }
134
135 // get each streamDesc's final routeFlag after concurrency
DecideFinalRouteFlag(std::vector<std::shared_ptr<AudioStreamDescriptor>> & streamDescs)136 void AudioPipeSelector::DecideFinalRouteFlag(std::vector<std::shared_ptr<AudioStreamDescriptor>> &streamDescs)
137 {
138 CHECK_AND_RETURN_LOG(streamDescs.size() != 0, "streamDescs is empty!");
139 streamDescs[0]->routeFlag_ = GetRouteFlagByStreamDesc(streamDescs[0]);
140 if (streamDescs.size() == 1) {
141 return;
142 }
143
144 SortStreamDescsByStartTime(streamDescs);
145 for (size_t cmpStreamIdx = 1; cmpStreamIdx < streamDescs.size(); ++cmpStreamIdx) {
146 streamDescs[cmpStreamIdx]->routeFlag_ = GetRouteFlagByStreamDesc(streamDescs[cmpStreamIdx]);
147 // calculate concurrency in time order
148 for (size_t curStreamDescIdx = 0; curStreamDescIdx < cmpStreamIdx; ++curStreamDescIdx) {
149 ProcessConcurrency(streamDescs[curStreamDescIdx], streamDescs[cmpStreamIdx]);
150 }
151 }
152 }
153
154 // add streamDescs to prefer newPipe based on final routeFlag, create newPipe if needed
ProcessNewPipeList(std::vector<std::shared_ptr<AudioPipeInfo>> & newPipeInfoList,std::vector<std::shared_ptr<AudioStreamDescriptor>> & streamDescs)155 void AudioPipeSelector::ProcessNewPipeList(std::vector<std::shared_ptr<AudioPipeInfo>> &newPipeInfoList,
156 std::vector<std::shared_ptr<AudioStreamDescriptor>> &streamDescs)
157 {
158 std::string adapterName{};
159 for (auto &streamDesc : streamDescs) {
160 std::string streamDescAdapterName = GetAdapterNameByStreamDesc(streamDesc);
161 // find if curStream's prefer pipe has already exist
162 auto newPipeIter = std::find_if(newPipeInfoList.begin(), newPipeInfoList.end(),
163 [&](const std::shared_ptr<AudioPipeInfo> &newPipeInfo) {
164 return newPipeInfo->routeFlag_ == streamDesc->routeFlag_ &&
165 newPipeInfo->adapterName_ == streamDescAdapterName;
166 });
167 if (newPipeIter != newPipeInfoList.end()) {
168 (*newPipeIter)->streamDescriptors_.push_back(streamDesc);
169 (*newPipeIter)->streamDescMap_[streamDesc->sessionId_] = streamDesc;
170 AUDIO_INFO_LOG("[PipeFetchInfo] use existing Pipe %{public}s for stream %{public}u, routeFlag %{public}d",
171 (*newPipeIter)->ToString().c_str(), streamDesc->sessionId_, streamDesc->routeFlag_);
172 continue;
173 }
174 // if not find, need open
175 HandlePipeNotExist(newPipeInfoList, streamDesc);
176 }
177 }
178
179 // based on old--new pipeinfo to judge streamAction and pipeAction
DecidePipesAndStreamAction(std::vector<std::shared_ptr<AudioPipeInfo>> & newPipeInfoList,std::map<uint32_t,std::shared_ptr<AudioPipeInfo>> streamDescToOldPipeInfo)180 void AudioPipeSelector::DecidePipesAndStreamAction(std::vector<std::shared_ptr<AudioPipeInfo>> &newPipeInfoList,
181 std::map<uint32_t, std::shared_ptr<AudioPipeInfo>> streamDescToOldPipeInfo)
182 {
183 // get each streamDesc in each newPipe to judge action
184 for (auto &newPipeInfo : newPipeInfoList) {
185 if (newPipeInfo->pipeAction_ != PIPE_ACTION_NEW) {
186 newPipeInfo->pipeAction_ = PIPE_ACTION_UPDATE;
187 }
188 AUDIO_INFO_LOG("[PipeFetchInfo] Name %{public}s, PipeAction: %{public}d",
189 newPipeInfo->name_.c_str(), newPipeInfo->pipeAction_);
190
191 for (auto &streamDesc : newPipeInfo->streamDescriptors_) {
192 if (streamDescToOldPipeInfo.find(streamDesc->sessionId_) == streamDescToOldPipeInfo.end()) {
193 AUDIO_WARNING_LOG("[PipeFetchInfo] cannot find %{public}d in OldPipeList!", streamDesc->sessionId_);
194 continue;
195 }
196 streamDesc->streamAction_ = JudgeStreamAction(newPipeInfo, streamDescToOldPipeInfo[streamDesc->sessionId_]);
197 AUDIO_INFO_LOG(" |--[PipeFetchInfo] SessionId %{public}d, PipeRouteFlag %{public}d --> %{public}d, "
198 "streamAction %{public}d", streamDesc->sessionId_,
199 streamDescToOldPipeInfo[streamDesc->sessionId_]->routeFlag_,
200 newPipeInfo->routeFlag_, streamDesc->streamAction_);
201 }
202 if (newPipeInfo->streamDescriptors_.size() == 0) {
203 AUDIO_INFO_LOG(" |--[PipeFetchInfo] Empty");
204 }
205 }
206 }
207
FetchPipesAndExecute(std::vector<std::shared_ptr<AudioStreamDescriptor>> & streamDescs)208 std::vector<std::shared_ptr<AudioPipeInfo>> AudioPipeSelector::FetchPipesAndExecute(
209 std::vector<std::shared_ptr<AudioStreamDescriptor>> &streamDescs)
210 {
211 std::vector<std::shared_ptr<AudioPipeInfo>> oldPipeInfoList{};
212 if (streamDescs.size() == 0) {
213 return oldPipeInfoList;
214 }
215 // get all existing pipes and select render/capture pipes
216 std::vector<std::shared_ptr<AudioPipeInfo>> pipeInfoList = AudioPipeManager::GetPipeManager()->GetPipeList();
217 for (auto &curPipeInfo : pipeInfoList) {
218 if (curPipeInfo->pipeRole_ == static_cast<AudioPipeRole>(streamDescs[0]->audioMode_)) {
219 oldPipeInfoList.push_back(curPipeInfo);
220 }
221 }
222
223 // Record current pipe--stream info for later use (Judge stream action)
224 std::map<uint32_t, std::shared_ptr<AudioPipeInfo>> streamDescToPipeInfo;
225 for (auto &pipeInfo : oldPipeInfoList) {
226 pipeInfo->pipeAction_ = PIPE_ACTION_DEFAULT;
227 for (auto &streamDesc : pipeInfo->streamDescriptors_) {
228 streamDescToPipeInfo[streamDesc->sessionId_] = pipeInfo;
229 }
230 }
231
232 // deep copy to newPipeInfoList and clear all streams
233 std::vector<std::shared_ptr<AudioPipeInfo>> newPipeInfoList;
234 for (auto &pipeInfo : oldPipeInfoList) {
235 std::shared_ptr<AudioPipeInfo> temp = std::make_shared<AudioPipeInfo>(*pipeInfo);
236 temp->streamDescriptors_.clear();
237 temp->streamDescMap_.clear();
238 newPipeInfoList.push_back(temp);
239 }
240
241 DecideFinalRouteFlag(streamDescs);
242 ProcessNewPipeList(newPipeInfoList, streamDescs);
243 DecidePipesAndStreamAction(newPipeInfoList, streamDescToPipeInfo);
244
245 // check is pipe update
246 for (auto &pipeInfo : oldPipeInfoList) {
247 if (pipeInfo->streamDescriptors_.size() == 0) {
248 pipeInfo->pipeAction_ = PIPE_ACTION_DEFAULT;
249 }
250 }
251 return newPipeInfoList;
252 }
253
HandlePipeNotExist(std::vector<std::shared_ptr<AudioPipeInfo>> & newPipeInfoList,std::shared_ptr<AudioStreamDescriptor> & streamDesc)254 void AudioPipeSelector::HandlePipeNotExist(std::vector<std::shared_ptr<AudioPipeInfo>> &newPipeInfoList,
255 std::shared_ptr<AudioStreamDescriptor> &streamDesc)
256 {
257 AudioPipeInfo pipeInfo = {};
258 std::shared_ptr<PipeStreamPropInfo> streamPropInfo = std::make_shared<PipeStreamPropInfo>();
259 configManager_.GetStreamPropInfo(streamDesc, streamPropInfo);
260 ConvertStreamDescToPipeInfo(streamDesc, streamPropInfo, pipeInfo);
261 pipeInfo.pipeAction_ = PIPE_ACTION_NEW;
262 std::shared_ptr<AudioPipeInfo> tempPipeInfo = std::make_shared<AudioPipeInfo>(pipeInfo);
263 newPipeInfoList.push_back(tempPipeInfo);
264 AUDIO_INFO_LOG("[PipeFetchInfo] use new Pipe %{public}s for stream %{public}u with action %{public}d, "
265 "routeFlag %{public}d", tempPipeInfo->ToString().c_str(), streamDesc->sessionId_, streamDesc->streamAction_,
266 streamDesc->routeFlag_);
267 }
268
ScanPipeListForStreamDesc(std::vector<std::shared_ptr<AudioPipeInfo>> & pipeInfoList,std::shared_ptr<AudioStreamDescriptor> streamDesc)269 void AudioPipeSelector::ScanPipeListForStreamDesc(std::vector<std::shared_ptr<AudioPipeInfo>> &pipeInfoList,
270 std::shared_ptr<AudioStreamDescriptor> streamDesc)
271 {
272 CHECK_AND_RETURN_LOG(streamDesc != nullptr, "streamDesc is nullptr");
273 streamDesc->routeFlag_ = GetRouteFlagByStreamDesc(streamDesc);
274 AUDIO_INFO_LOG("Route flag: %{public}u", streamDesc->routeFlag_);
275
276 for (auto &pipeInfo : pipeInfoList) {
277 bool isUpdate = false;
278 for (auto &streamDescInPipe : pipeInfo->streamDescriptors_) {
279 isUpdate = ProcessConcurrency(streamDescInPipe, streamDesc);
280 AUDIO_INFO_LOG("isUpdate: %{public}d, action: %{public}d", isUpdate, streamDescInPipe->streamAction_);
281 }
282 pipeInfo->pipeAction_ = isUpdate ? PIPE_ACTION_UPDATE : pipeInfo->pipeAction_;
283 }
284 AUDIO_INFO_LOG("Route flag after concurrency: %{public}u", streamDesc->routeFlag_);
285 }
286
GetPipeType(uint32_t flag,AudioMode audioMode)287 AudioPipeType AudioPipeSelector::GetPipeType(uint32_t flag, AudioMode audioMode)
288 {
289 if (audioMode == AUDIO_MODE_PLAYBACK) {
290 if (flag & AUDIO_OUTPUT_FLAG_FAST) {
291 if (flag & AUDIO_OUTPUT_FLAG_VOIP) {
292 return PIPE_TYPE_CALL_OUT;
293 } else {
294 return PIPE_TYPE_LOWLATENCY_OUT;
295 }
296 } else if (flag & AUDIO_OUTPUT_FLAG_DIRECT) {
297 if (flag & AUDIO_OUTPUT_FLAG_VOIP) {
298 return PIPE_TYPE_CALL_OUT;
299 } else {
300 return PIPE_TYPE_DIRECT_OUT;
301 }
302 } else if (flag & AUDIO_OUTPUT_FLAG_MULTICHANNEL) {
303 return PIPE_TYPE_MULTICHANNEL;
304 } else if (flag & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
305 return PIPE_TYPE_OFFLOAD;
306 } else {
307 return PIPE_TYPE_NORMAL_OUT;
308 }
309 } else {
310 if (flag & AUDIO_INPUT_FLAG_FAST) {
311 if (flag & AUDIO_INPUT_FLAG_VOIP) {
312 return PIPE_TYPE_CALL_IN;
313 } else {
314 return PIPE_TYPE_LOWLATENCY_IN;
315 }
316 } else {
317 return PIPE_TYPE_NORMAL_IN;
318 }
319 }
320 }
321
IncomingConcurrency(std::shared_ptr<AudioStreamDescriptor> stream,std::shared_ptr<AudioStreamDescriptor> cmpStream)322 void AudioPipeSelector::IncomingConcurrency(std::shared_ptr<AudioStreamDescriptor> stream,
323 std::shared_ptr<AudioStreamDescriptor> cmpStream)
324 {
325 // normal, mmap or voipmmap can't concurrency, if concede existing must concede incoming
326 if (cmpStream->audioMode_ == AUDIO_MODE_RECORD && stream->audioMode_ == AUDIO_MODE_RECORD) {
327 cmpStream->routeFlag_ = AUDIO_INPUT_FLAG_NORMAL;
328 AUDIO_INFO_LOG("capture in: %{public}u old: %{public}u", cmpStream->sessionId_, stream->sessionId_);
329 }
330 }
331
IsSameAdapter(std::shared_ptr<AudioStreamDescriptor> streamDescA,std::shared_ptr<AudioStreamDescriptor> streamDescB)332 bool AudioPipeSelector::IsSameAdapter(std::shared_ptr<AudioStreamDescriptor> streamDescA,
333 std::shared_ptr<AudioStreamDescriptor> streamDescB)
334 {
335 CHECK_AND_RETURN_RET(streamDescA != nullptr && streamDescB != nullptr && streamDescA->newDeviceDescs_.size() != 0 &&
336 streamDescB->newDeviceDescs_.size() != 0, true);
337 bool hasRemote = false;
338 for (auto deviceDescA : streamDescA->newDeviceDescs_) {
339 CHECK_AND_CONTINUE(deviceDescA != nullptr);
340 AudioPipeType pipeTypeA = GetPipeType(streamDescA->routeFlag_, streamDescA->audioMode_);
341 bool isRemoteA = deviceDescA->networkId_ != LOCAL_NETWORK_ID;
342 hasRemote = isRemoteA ? true : hasRemote;
343 std::string portNameA = AudioPolicyUtils::GetInstance().GetSinkPortName(deviceDescA->deviceType_, pipeTypeA);
344
345 for (auto deviceDescB : streamDescB->newDeviceDescs_) {
346 CHECK_AND_CONTINUE(deviceDescB != nullptr);
347 AudioPipeType pipeTypeB = GetPipeType(streamDescB->routeFlag_, streamDescB->audioMode_);
348 bool isRemoteB = deviceDescB->networkId_ != LOCAL_NETWORK_ID;
349 hasRemote = isRemoteB ? true : hasRemote;
350 std::string portNameB = AudioPolicyUtils::GetInstance().GetSinkPortName(deviceDescB->deviceType_,
351 pipeTypeB);
352 CHECK_AND_RETURN_RET(!(isRemoteA == isRemoteB && portNameA == portNameB), true);
353 }
354 }
355 CHECK_AND_RETURN_RET(hasRemote, true);
356 AUDIO_INFO_LOG("diff adapter, not need concurrency");
357 return false;
358 }
359
ProcessConcurrency(std::shared_ptr<AudioStreamDescriptor> stream,std::shared_ptr<AudioStreamDescriptor> cmpStream)360 bool AudioPipeSelector::ProcessConcurrency(std::shared_ptr<AudioStreamDescriptor> stream,
361 std::shared_ptr<AudioStreamDescriptor> cmpStream)
362 {
363 bool isUpdate = false;
364 std::map<std::pair<AudioPipeType, AudioPipeType>, ConcurrencyAction> ruleMap =
365 AudioStreamCollector::GetAudioStreamCollector().GetConcurrencyMap();
366 ConcurrencyAction action = ruleMap[std::make_pair(GetPipeType(stream->routeFlag_, stream->audioMode_),
367 GetPipeType(cmpStream->routeFlag_, cmpStream->audioMode_))];
368 action = IsSameAdapter(stream, cmpStream) ? action : PLAY_BOTH;
369 AUDIO_INFO_LOG("Action: %{public}u %{public}u -- %{public}u", action, stream->sessionId_, cmpStream->sessionId_);
370 uint32_t newFlag;
371 switch (action) {
372 case PLAY_BOTH:
373 stream->streamAction_ = AUDIO_STREAM_ACTION_DEFAULT;
374 break;
375 case CONCEDE_INCOMING:
376 stream->streamAction_ = AUDIO_STREAM_ACTION_DEFAULT;
377 cmpStream->routeFlag_ = cmpStream->audioMode_ == AUDIO_MODE_PLAYBACK ?
378 AUDIO_OUTPUT_FLAG_NORMAL : AUDIO_INPUT_FLAG_NORMAL;
379 break;
380 case CONCEDE_EXISTING:
381 // if concede existing, maybe need concede incomming
382 IncomingConcurrency(stream, cmpStream);
383 isUpdate = true;
384 newFlag = stream->audioMode_ == AUDIO_MODE_PLAYBACK ?
385 AUDIO_OUTPUT_FLAG_NORMAL : AUDIO_INPUT_FLAG_NORMAL;
386 stream->streamAction_ = AUDIO_STREAM_ACTION_RECREATE;
387 stream->routeFlag_ = newFlag;
388 break;
389 default:
390 break;
391 }
392 return isUpdate;
393 }
394
GetRouteFlagByStreamDesc(std::shared_ptr<AudioStreamDescriptor> streamDesc)395 uint32_t AudioPipeSelector::GetRouteFlagByStreamDesc(std::shared_ptr<AudioStreamDescriptor> streamDesc)
396 {
397 uint32_t flag = AUDIO_FLAG_NONE;
398 CHECK_AND_RETURN_RET_LOG(streamDesc != nullptr, flag, "streamDesc is nullptr");
399 flag = configManager_.GetRouteFlag(streamDesc);
400 return flag;
401 }
402
GetAdapterNameByStreamDesc(std::shared_ptr<AudioStreamDescriptor> streamDesc)403 std::string AudioPipeSelector::GetAdapterNameByStreamDesc(std::shared_ptr<AudioStreamDescriptor> streamDesc)
404 {
405 std::string name = "";
406 CHECK_AND_RETURN_RET_LOG(streamDesc != nullptr, name, "streamDesc is nullptr");
407 std::shared_ptr<PipeStreamPropInfo> streamPropInfo = std::make_shared<PipeStreamPropInfo>();
408 configManager_.GetStreamPropInfo(streamDesc, streamPropInfo);
409 CHECK_AND_RETURN_RET_LOG(streamPropInfo != nullptr, "", "StreamProp Info is null");
410
411 std::shared_ptr<AdapterPipeInfo> pipeInfoPtr = streamPropInfo->pipeInfo_.lock();
412 if (pipeInfoPtr == nullptr) {
413 AUDIO_ERR_LOG("Adapter info is null");
414 return "";
415 }
416
417 std::shared_ptr<PolicyAdapterInfo> adapterInfoPtr = pipeInfoPtr->adapterInfo_.lock();
418 if (adapterInfoPtr == nullptr) {
419 AUDIO_ERR_LOG("Pipe info is null");
420 return "";
421 }
422 name = adapterInfoPtr->adapterName;
423 return name;
424 }
425
FillSpecialPipeInfo(AudioPipeInfo & info,std::shared_ptr<AdapterPipeInfo> pipeInfoPtr,std::shared_ptr<AudioStreamDescriptor> streamDesc,std::shared_ptr<PipeStreamPropInfo> streamPropInfo)426 static void FillSpecialPipeInfo(AudioPipeInfo &info, std::shared_ptr<AdapterPipeInfo> pipeInfoPtr,
427 std::shared_ptr<AudioStreamDescriptor> streamDesc, std::shared_ptr<PipeStreamPropInfo> streamPropInfo)
428 {
429 if (pipeInfoPtr->name_ == "multichannel_output") {
430 info.moduleInfo_.className = "multichannel";
431 info.moduleInfo_.fileName = "mch_dump_file";
432 info.moduleInfo_.fixedLatency = "1"; // for fix max request
433 info.moduleInfo_.bufferSize =
434 std::to_string(((streamPropInfo->bufferSize_ / std::stoul(info.moduleInfo_.channels)) * STEREO));
435 AUDIO_INFO_LOG("Buffer size: %{public}s", info.moduleInfo_.bufferSize.c_str());
436 } else if (pipeInfoPtr->name_ == "offload_output") {
437 info.moduleInfo_.className = "offload";
438 info.moduleInfo_.offloadEnable = "1";
439 info.moduleInfo_.fixedLatency = "1";
440 info.moduleInfo_.fileName = "offload_dump_file";
441 } else if (pipeInfoPtr->name_ == "dp_multichannel_output") {
442 info.moduleInfo_.className = "dp_multichannel";
443 info.moduleInfo_.fileName = "mch_dump_file";
444 info.moduleInfo_.fixedLatency = "1";
445 info.moduleInfo_.bufferSize = std::to_string(streamPropInfo->bufferSize_);
446 } else if (pipeInfoPtr->name_ == "offload_distributed_output") {
447 info.moduleInfo_.className = "remote_offload";
448 info.moduleInfo_.offloadEnable = "1";
449 info.moduleInfo_.fixedLatency = "1";
450 info.moduleInfo_.fileName = "remote_offload_dump_file";
451 info.moduleInfo_.name =
452 AudioPolicyUtils::GetInstance().GetRemoteModuleName(streamDesc->newDeviceDescs_[0]->networkId_,
453 AudioPolicyUtils::GetInstance().GetDeviceRole(streamDesc->newDeviceDescs_[0]->deviceType_)) + "_offload";
454 }
455 }
456
ConvertStreamDescToPipeInfo(std::shared_ptr<AudioStreamDescriptor> streamDesc,std::shared_ptr<PipeStreamPropInfo> streamPropInfo,AudioPipeInfo & info)457 void AudioPipeSelector::ConvertStreamDescToPipeInfo(std::shared_ptr<AudioStreamDescriptor> streamDesc,
458 std::shared_ptr<PipeStreamPropInfo> streamPropInfo, AudioPipeInfo &info)
459 {
460 CHECK_AND_RETURN_LOG(streamPropInfo != nullptr, "streamPropInfo is nullptr");
461 std::shared_ptr<AdapterPipeInfo> pipeInfoPtr = streamPropInfo->pipeInfo_.lock();
462 if (pipeInfoPtr == nullptr) {
463 AUDIO_ERR_LOG("Adapter info is null");
464 return ;
465 }
466
467 std::shared_ptr<PolicyAdapterInfo> adapterInfoPtr = pipeInfoPtr->adapterInfo_.lock();
468 if (adapterInfoPtr == nullptr) {
469 AUDIO_ERR_LOG("Pipe info is null");
470 return ;
471 }
472
473 info.moduleInfo_.format = AudioDefinitionPolicyUtils::enumToFormatStr[streamPropInfo->format_];
474 info.moduleInfo_.rate = std::to_string(streamPropInfo->sampleRate_);
475 info.moduleInfo_.channels = std::to_string(AudioDefinitionPolicyUtils::ConvertLayoutToAudioChannel(
476 streamPropInfo->channelLayout_));
477 info.moduleInfo_.bufferSize = std::to_string(streamPropInfo->bufferSize_);
478
479 info.moduleInfo_.lib = pipeInfoPtr->paProp_.lib_;
480 info.moduleInfo_.role = pipeInfoPtr->paProp_.role_;
481 info.moduleInfo_.name = pipeInfoPtr->paProp_.moduleName_;
482 info.moduleInfo_.adapterName = adapterInfoPtr->adapterName;
483 info.moduleInfo_.className = adapterInfoPtr->adapterName;
484 info.moduleInfo_.OpenMicSpeaker = configManager_.GetUpdateRouteSupport() ? "1" : "0";
485
486 AUDIO_INFO_LOG("Pipe name: %{public}s", pipeInfoPtr->name_.c_str());
487 FillSpecialPipeInfo(info, pipeInfoPtr, streamDesc, streamPropInfo);
488
489 info.moduleInfo_.deviceType = std::to_string(streamDesc->newDeviceDescs_[0]->deviceType_);
490 info.moduleInfo_.networkId = streamDesc->newDeviceDescs_[0]->networkId_;
491 info.moduleInfo_.sourceType = std::to_string(streamDesc->capturerInfo_.sourceType);
492
493 info.streamDescriptors_.push_back(streamDesc);
494 info.streamDescMap_[streamDesc->sessionId_] = streamDesc;
495 info.routeFlag_ = streamDesc->routeFlag_;
496 info.adapterName_ = adapterInfoPtr->adapterName;
497 info.pipeRole_ = pipeInfoPtr->role_;
498 info.name_ = pipeInfoPtr->name_;
499 info.InitAudioStreamInfo();
500 }
501
JudgeStreamAction(std::shared_ptr<AudioPipeInfo> newPipe,std::shared_ptr<AudioPipeInfo> oldPipe)502 AudioStreamAction AudioPipeSelector::JudgeStreamAction(
503 std::shared_ptr<AudioPipeInfo> newPipe, std::shared_ptr<AudioPipeInfo> oldPipe)
504 {
505 CHECK_AND_RETURN_RET(!IsRemoteOffloadNeedRecreate(newPipe, oldPipe), AUDIO_STREAM_ACTION_RECREATE);
506 if (newPipe->adapterName_ == oldPipe->adapterName_ && newPipe->routeFlag_ == oldPipe->routeFlag_) {
507 return AUDIO_STREAM_ACTION_DEFAULT;
508 }
509 if ((oldPipe->routeFlag_ & AUDIO_OUTPUT_FLAG_FAST) || (newPipe->routeFlag_ & AUDIO_OUTPUT_FLAG_FAST) ||
510 (oldPipe->routeFlag_ & AUDIO_OUTPUT_FLAG_DIRECT) || (newPipe->routeFlag_ & AUDIO_OUTPUT_FLAG_DIRECT)) {
511 return AUDIO_STREAM_ACTION_RECREATE;
512 } else {
513 return AUDIO_STREAM_ACTION_MOVE;
514 }
515 }
516
SortStreamDescsByStartTime(std::vector<std::shared_ptr<AudioStreamDescriptor>> & streamDescs)517 void AudioPipeSelector::SortStreamDescsByStartTime(std::vector<std::shared_ptr<AudioStreamDescriptor>> &streamDescs)
518 {
519 sort(streamDescs.begin(), streamDescs.end(), [](const std::shared_ptr<AudioStreamDescriptor> &streamDesc1,
520 const std::shared_ptr<AudioStreamDescriptor> &streamDesc2) {
521 return streamDesc1->createTimeStamp_ < streamDesc2->createTimeStamp_;
522 });
523 }
524 } // namespace AudioStandard
525 } // namespace OHOS