• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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