• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "AudioOffloadStream"
17 #endif
18 
19 #include "audio_offload_stream.h"
20 #include <ability_manager_client.h>
21 #include "iservice_registry.h"
22 #include "parameter.h"
23 #include "parameters.h"
24 #include "audio_policy_log.h"
25 #include "media_monitor_manager.h"
26 #include "audio_spatialization_service.h"
27 
28 #include "audio_policy_utils.h"
29 #include "audio_server_proxy.h"
30 #include "audio_config_manager.h"
31 
32 namespace OHOS {
33 namespace AudioStandard {
34 
35 const int32_t UID_AUDIO = 1041;
36 const int32_t dAudioClientUid = 3055;
37 static const int32_t WAIT_OFFLOAD_CLOSE_TIME_S = 10; // 10s
38 
PrintSinkInput(SinkInput sinkInput)39 inline std::string PrintSinkInput(SinkInput sinkInput)
40 {
41     std::stringstream value;
42     value << "streamId:[" << sinkInput.streamId << "] ";
43     value << "streamType:[" << sinkInput.streamType << "] ";
44     value << "uid:[" << sinkInput.uid << "] ";
45     value << "pid:[" << sinkInput.pid << "] ";
46     value << "statusMark:[" << sinkInput.statusMark << "] ";
47     value << "sinkName:[" << sinkInput.sinkName << "] ";
48     value << "startTime:[" << sinkInput.startTime << "]";
49     return value.str();
50 }
51 
HandlePowerStateChanged(PowerMgr::PowerState state)52 void AudioOffloadStream::HandlePowerStateChanged(PowerMgr::PowerState state)
53 {
54     if (currentPowerState_ == state) {
55         return;
56     }
57     currentPowerState_ = state;
58     if (!audioActiveDevice_.CheckActiveOutputDeviceSupportOffload()) {
59         return;
60     }
61     if (offloadSessionID_.has_value()) {
62         AUDIO_DEBUG_LOG("SetOffloadMode! Offload power is state = %{public}d", state);
63         SetOffloadMode();
64     }
65 }
66 
SetOffloadAvailableFromXML(AudioModuleInfo & moduleInfo)67 void AudioOffloadStream::SetOffloadAvailableFromXML(AudioModuleInfo &moduleInfo)
68 {
69     if (moduleInfo.name == "Speaker") {
70         for (const auto &portInfo : moduleInfo.ports) {
71             if ((portInfo.adapterName == "primary") && (portInfo.offloadEnable == "1")) {
72                 isOffloadAvailable_ = true;
73             }
74         }
75     }
76 }
77 
GetOffloadAvailableFromXml() const78 bool AudioOffloadStream::GetOffloadAvailableFromXml() const
79 {
80     return isOffloadAvailable_;
81 }
82 
SetOffloadMode()83 void AudioOffloadStream::SetOffloadMode()
84 {
85     if (!GetOffloadAvailableFromXml()) {
86         AUDIO_INFO_LOG("Offload not available, skipped");
87         return;
88     }
89 
90     AUDIO_INFO_LOG("sessionId: %{public}d, PowerState: %{public}d, isAppBack: %{public}d",
91         *offloadSessionID_, static_cast<int32_t>(currentPowerState_), currentOffloadSessionIsBackground_);
92     AudioServerProxy::GetInstance().SetOffloadModeProxy(*offloadSessionID_, static_cast<int32_t>(currentPowerState_),
93         currentOffloadSessionIsBackground_);
94 }
95 
OffloadStreamSetCheck(uint32_t sessionId)96 void AudioOffloadStream::OffloadStreamSetCheck(uint32_t sessionId)
97 {
98     AudioPipeType pipeType = PIPE_TYPE_OFFLOAD;
99     int32_t ret = AudioStreamCollector::GetAudioStreamCollector().ActivateAudioConcurrency(pipeType);
100     if (ret != SUCCESS) {
101         return;
102     }
103     AudioDeviceDescriptor deviceInfo(AudioDeviceDescriptor::DEVICE_INFO);
104     std::string curOutputNetworkId = audioActiveDevice_.GetCurrentOutputDeviceNetworkId();
105     std::string curOutputMacAddr = audioActiveDevice_.GetCurrentOutputDeviceMacAddr();
106     DeviceType curOutputDeviceType = audioActiveDevice_.GetCurrentOutputDeviceType();
107     ret = streamCollector_.GetRendererDeviceInfo(sessionId, deviceInfo);
108     if (ret != SUCCESS || curOutputNetworkId != LOCAL_NETWORK_ID ||
109         curOutputDeviceType == DEVICE_TYPE_REMOTE_CAST ||
110         deviceInfo.deviceType_ != curOutputDeviceType ||
111         deviceInfo.networkId_ != curOutputNetworkId ||
112         deviceInfo.macAddress_ != curOutputMacAddr) {
113         AUDIO_INFO_LOG("sessionId[%{public}d] not fetch device, Offload Skipped", sessionId);
114         return;
115     }
116 
117     AudioStreamType streamType = streamCollector_.GetStreamType(sessionId);
118     if (!CheckStreamOffloadMode(sessionId, streamType)) {
119         return;
120     }
121 
122     auto CallingUid = IPCSkeleton::GetCallingUid();
123     AUDIO_INFO_LOG("sessionId[%{public}d]  CallingUid[%{public}d] StreamType[%{public}d] "
124                    "Getting offload stream", sessionId, CallingUid, streamType);
125     std::lock_guard<std::mutex> lock(offloadMutex_);
126 
127     if (!offloadSessionID_.has_value()) {
128         offloadSessionID_ = sessionId;
129         audioPolicyManager_.SetOffloadSessionId(sessionId);
130 
131         AUDIO_DEBUG_LOG("sessionId[%{public}d] try get offload stream", sessionId);
132         if (MoveToNewPipeInner(sessionId, PIPE_TYPE_OFFLOAD) != SUCCESS) {
133             AUDIO_ERR_LOG("sessionId[%{public}d]  CallingUid[%{public}d] StreamType[%{public}d] "
134                 "failed to offload stream", sessionId, CallingUid, streamType);
135             offloadSessionID_.reset();
136             audioPolicyManager_.ResetOffloadSessionId();
137             return;
138         }
139         SetOffloadMode();
140     } else {
141         if (sessionId == *(offloadSessionID_)) {
142             AUDIO_DEBUG_LOG("sessionId[%{public}d] is already get offload stream", sessionId);
143         } else {
144             AUDIO_DEBUG_LOG("sessionId[%{public}d] no get offload, current offload sessionId[%{public}d]",
145                 sessionId, *(offloadSessionID_));
146         }
147     }
148 
149     return;
150 }
151 
CheckStreamOffloadMode(int64_t activateSessionId,AudioStreamType streamType)152 bool AudioOffloadStream::CheckStreamOffloadMode(int64_t activateSessionId, AudioStreamType streamType)
153 {
154     if (!GetOffloadAvailableFromXml()) {
155         AUDIO_INFO_LOG("Offload not available, skipped for set");
156         return false;
157     }
158 
159     if (!audioActiveDevice_.CheckActiveOutputDeviceSupportOffload()) {
160         AUDIO_PRERELEASE_LOGI("Offload not available on current output device, skipped");
161         return false;
162     }
163 
164     if (!streamCollector_.IsOffloadAllowed(activateSessionId)) {
165         AUDIO_PRERELEASE_LOGI("Offload is not allowed, Skipped");
166         return false;
167     }
168 
169     if ((streamType != STREAM_MUSIC) && (streamType != STREAM_SPEECH)) {
170         AUDIO_DEBUG_LOG("StreamType not allowed get offload mode, Skipped");
171         return false;
172     }
173 
174     AudioPipeType pipeType;
175     streamCollector_.GetPipeType(activateSessionId, pipeType);
176     if (pipeType == PIPE_TYPE_DIRECT_MUSIC) {
177         AUDIO_INFO_LOG("stream is direct, Skipped");
178         return false;
179     }
180 
181     int32_t channelCount = streamCollector_.GetChannelCount(activateSessionId);
182     if ((channelCount != AudioChannel::MONO) && (channelCount != AudioChannel::STEREO)) {
183         AUDIO_DEBUG_LOG("ChannelNum not allowed get offload mode, Skipped");
184         return false;
185     }
186 
187     int32_t offloadUID = streamCollector_.GetUid(activateSessionId);
188     if (offloadUID == -1) {
189         AUDIO_DEBUG_LOG("offloadUID not valid, Skipped");
190         return false;
191     }
192     if (offloadUID == UID_AUDIO) {
193         AUDIO_DEBUG_LOG("Skip anco_audio out of offload mode");
194         return false;
195     }
196 
197     if (CheckSpatializationAndEffectState()) {
198         AUDIO_INFO_LOG("spatialization effect in arm, Skipped");
199         return false;
200     }
201     return true;
202 }
203 
ConstructMchAudioModuleInfo(DeviceType deviceType)204 AudioModuleInfo AudioOffloadStream::ConstructMchAudioModuleInfo(DeviceType deviceType)
205 {
206     AudioModuleInfo audioModuleInfo = {};
207     audioModuleInfo.lib = "libmodule-hdi-sink.z.so";
208     audioModuleInfo.format = "s32le"; // 32bit little endian
209     audioModuleInfo.fixedLatency = "1"; // here we need to set latency fixed for a fixed buffer size.
210 
211     // used as "sink_name" in hdi_sink.c, hope we could use name to find target sink.
212     audioModuleInfo.name = MCH_PRIMARY_SPEAKER;
213 
214     std::stringstream typeValue;
215     typeValue << static_cast<int32_t>(deviceType);
216     audioModuleInfo.deviceType = typeValue.str();
217 
218     audioModuleInfo.defaultAdapterEnable = AudioConfigManager::GetInstance().GetDefaultAdapterEnable() ? "1" : "0";
219     audioModuleInfo.adapterName = "primary";
220     audioModuleInfo.className = "multichannel"; // used in renderer_sink_adapter.c
221     audioModuleInfo.fileName = "mch_dump_file";
222 
223     audioModuleInfo.channels = "6";
224     audioModuleInfo.rate = "48000";
225     audioModuleInfo.bufferSize = "7680";
226 
227     return audioModuleInfo;
228 }
229 
CheckSpatializationAndEffectState()230 bool AudioOffloadStream::CheckSpatializationAndEffectState()
231 {
232     AudioSpatializationState spatialState =
233         AudioSpatializationService::GetAudioSpatializationService().GetSpatializationState();
234     bool effectOffloadFlag = AudioServerProxy::GetInstance().GetEffectOffloadEnabledProxy();
235     return spatialState.spatializationEnabled && !effectOffloadFlag;
236 }
237 
LoadMchModule()238 int32_t AudioOffloadStream::LoadMchModule()
239 {
240     AUDIO_INFO_LOG("load multichannel mode");
241     DeviceType deviceType = DEVICE_TYPE_SPEAKER;
242     AudioModuleInfo moduleInfo = ConstructMchAudioModuleInfo(deviceType);
243     audioIOHandleMap_.OpenPortAndInsertIOHandle(moduleInfo.name, moduleInfo);
244     return SUCCESS;
245 }
246 
UnloadMchModule()247 int32_t AudioOffloadStream::UnloadMchModule()
248 {
249     AUDIO_INFO_LOG("unload multichannel module");
250     return audioIOHandleMap_.ClosePortAndEraseIOHandle(MCH_PRIMARY_SPEAKER);
251 }
252 
MoveToNewPipeInner(uint32_t sessionId,AudioPipeType pipeType)253 int32_t AudioOffloadStream::MoveToNewPipeInner(uint32_t sessionId, AudioPipeType pipeType)
254 {
255     AudioPipeType oldPipeType;
256     streamCollector_.GetPipeType(sessionId, oldPipeType);
257     if (oldPipeType == pipeType) {
258         AUDIO_ERR_LOG("the same type [%{public}d],no need to move", pipeType);
259         return SUCCESS;
260     }
261     Trace trace("AudioOffloadStream::MoveToNewPipeInner");
262     AUDIO_INFO_LOG("start move stream into new pipe %{public}d", pipeType);
263     int32_t ret = ERROR;
264     std::string portName = PORT_NONE;
265     AudioStreamType streamType = streamCollector_.GetStreamType(sessionId);
266     DeviceType deviceType = audioActiveDevice_.GetCurrentOutputDeviceType();
267     switch (pipeType) {
268         case PIPE_TYPE_OFFLOAD: {
269             if (!CheckStreamOffloadMode(sessionId, streamType)) {
270                 return ERROR;
271             }
272             if (LoadOffloadModule() != SUCCESS) {
273                 return ERROR;
274             }
275             portName = AudioPolicyUtils::GetInstance().GetSinkPortName(deviceType, pipeType);
276             ret = MoveToOutputDevice(sessionId, portName);
277             break;
278         }
279         case PIPE_TYPE_MULTICHANNEL: {
280             if (!CheckStreamMultichannelMode(sessionId)) {
281                 return ERROR;
282             }
283 
284             if (audioIOHandleMap_.CheckIOHandleExist(MCH_PRIMARY_SPEAKER) == false) {
285                 // load moudle and move into new sink
286                 LoadMchModule();
287             }
288             portName = AudioPolicyUtils::GetInstance().GetSinkPortName(deviceType, pipeType);
289             ret = MoveToOutputDevice(sessionId, portName);
290             break;
291         }
292         case PIPE_TYPE_NORMAL_OUT: {
293             portName = AudioPolicyUtils::GetInstance().GetSinkPortName(deviceType, pipeType);
294             ret = MoveToOutputDevice(sessionId, portName);
295             break;
296         }
297         default:
298             AUDIO_WARNING_LOG("not supported for pipe type %{public}d", pipeType);
299             break;
300     }
301     if (ret == SUCCESS) {
302         streamCollector_.UpdateRendererPipeInfo(sessionId, pipeType);
303     }
304     return ret;
305 }
306 
ResetOffloadMode(int32_t sessionId)307 void AudioOffloadStream::ResetOffloadMode(int32_t sessionId)
308 {
309     AUDIO_DEBUG_LOG("Doing reset offload mode!");
310 
311     if (!audioActiveDevice_.CheckActiveOutputDeviceSupportOffload()) {
312         AUDIO_DEBUG_LOG("Resetting offload not available on this output device! Release.");
313         OffloadStreamReleaseCheck(*offloadSessionID_);
314         return;
315     }
316 
317     OffloadStreamSetCheck(sessionId);
318 }
319 
OffloadStreamReleaseCheck(uint32_t sessionId)320 void AudioOffloadStream::OffloadStreamReleaseCheck(uint32_t sessionId)
321 {
322     if (!GetOffloadAvailableFromXml()) {
323         AUDIO_INFO_LOG("Offload not available, skipped for release");
324         return;
325     }
326 
327     std::lock_guard<std::mutex> lock(offloadMutex_);
328 
329     if (((*offloadSessionID_) == sessionId) && offloadSessionID_.has_value()) {
330         AUDIO_DEBUG_LOG("Doing unset offload mode!");
331         AudioServerProxy::GetInstance().UnsetOffloadModeProxy(*offloadSessionID_);
332         AudioPipeType normalPipe = PIPE_TYPE_NORMAL_OUT;
333         MoveToNewPipe(sessionId, normalPipe);
334         streamCollector_.UpdateRendererPipeInfo(sessionId, normalPipe);
335         DynamicUnloadOffloadModule();
336         offloadSessionID_.reset();
337         audioPolicyManager_.ResetOffloadSessionId();
338         AUDIO_DEBUG_LOG("sessionId[%{public}d] release offload stream", sessionId);
339     } else {
340         if (offloadSessionID_.has_value()) {
341             AUDIO_DEBUG_LOG("sessionId[%{public}d] stopping stream not get offload, current offload [%{public}d]",
342                 sessionId, *offloadSessionID_);
343         } else {
344             AUDIO_DEBUG_LOG("sessionId[%{public}d] stopping stream not get offload, current offload stream is None",
345                 sessionId);
346         }
347     }
348     return;
349 }
350 
MoveToNewPipe(uint32_t sessionId,AudioPipeType pipeType)351 int32_t AudioOffloadStream::MoveToNewPipe(uint32_t sessionId, AudioPipeType pipeType)
352 {
353     // Check if the stream exists
354     int32_t defaultUid = -1;
355     if (defaultUid == streamCollector_.GetUid(sessionId)) {
356         AUDIO_ERR_LOG("The audio stream information [%{public}d] is illegal", sessionId);
357         return ERROR;
358     }
359     // move the stream to new pipe
360     return MoveToNewPipeInner(sessionId, pipeType);
361 }
362 
ConstructOffloadAudioModuleInfo(DeviceType deviceType)363 AudioModuleInfo AudioOffloadStream::ConstructOffloadAudioModuleInfo(DeviceType deviceType)
364 {
365     AudioModuleInfo audioModuleInfo = {};
366     audioModuleInfo.lib = "libmodule-hdi-sink.z.so";
367     audioModuleInfo.format = "s32le"; // 32bit little endian
368     audioModuleInfo.fixedLatency = "1"; // here we need to set latency fixed for a fixed buffer size.
369 
370     // used as "sink_name" in hdi_sink.c, hope we could use name to find target sink.
371     audioModuleInfo.name = OFFLOAD_PRIMARY_SPEAKER;
372 
373     std::stringstream typeValue;
374     typeValue << static_cast<int32_t>(deviceType);
375     audioModuleInfo.deviceType = typeValue.str();
376 
377     audioModuleInfo.adapterName = "primary";
378     audioModuleInfo.className = "offload"; // used in renderer_sink_adapter.c
379     audioModuleInfo.fileName = "offload_dump_file";
380     audioModuleInfo.offloadEnable = "1";
381 
382     audioModuleInfo.channels = "2";
383     audioModuleInfo.rate = "48000";
384     audioModuleInfo.bufferSize = "7680";
385 
386     return audioModuleInfo;
387 }
388 
LoadOffloadModule()389 int32_t AudioOffloadStream::LoadOffloadModule()
390 {
391     AUDIO_INFO_LOG("load offload mode");
392     std::unique_lock<std::mutex> lock(offloadCloseMutex_);
393     isOffloadOpened_.store(true);
394     offloadCloseCondition_.notify_all();
395     {
396         std::lock_guard<std::mutex> lk(offloadOpenMutex_);
397         if (audioIOHandleMap_.CheckIOHandleExist(OFFLOAD_PRIMARY_SPEAKER)) {
398             AUDIO_INFO_LOG("offload is open");
399             return SUCCESS;
400         }
401 
402         DeviceType deviceType = DEVICE_TYPE_SPEAKER;
403         AudioModuleInfo moduleInfo = ConstructOffloadAudioModuleInfo(deviceType);
404         return audioIOHandleMap_.OpenPortAndInsertIOHandle(moduleInfo.name, moduleInfo);
405     }
406     return SUCCESS;
407 }
408 
UnloadOffloadModule()409 int32_t AudioOffloadStream::UnloadOffloadModule()
410 {
411     AUDIO_INFO_LOG("unload offload module");
412     std::unique_lock<std::mutex> lock(offloadCloseMutex_);
413     // Try to wait 3 seconds before unloading the module, because the audio driver takes some time to process
414     // the shutdown process..
415     offloadCloseCondition_.wait_for(lock, std::chrono::seconds(WAIT_OFFLOAD_CLOSE_TIME_S),
416         [this] () { return isOffloadOpened_.load(); });
417     {
418         std::lock_guard<std::mutex> lk(offloadOpenMutex_);
419         if (isOffloadOpened_.load()) {
420             AUDIO_INFO_LOG("offload restart");
421             return ERROR;
422         }
423         audioIOHandleMap_.ClosePortAndEraseIOHandle(OFFLOAD_PRIMARY_SPEAKER);
424     }
425     return SUCCESS;
426 }
427 
428 
DynamicUnloadOffloadModule()429 int32_t AudioOffloadStream::DynamicUnloadOffloadModule()
430 {
431     if (isOffloadOpened_.load()) {
432         isOffloadOpened_.store(false);
433         auto unloadFirOffloadThrd = [this] { this->UnloadOffloadModule(); };
434         std::thread unloadOffloadThrd(unloadFirOffloadThrd);
435         unloadOffloadThrd.detach();
436     }
437     return SUCCESS;
438 }
439 
RemoteOffloadStreamRelease(uint32_t sessionId)440 void AudioOffloadStream::RemoteOffloadStreamRelease(uint32_t sessionId)
441 {
442     std::lock_guard<std::mutex> lock(offloadMutex_);
443     if (offloadSessionID_.has_value() && ((*offloadSessionID_) == sessionId)) {
444         AUDIO_DEBUG_LOG("Doing unset offload mode!");
445         AudioServerProxy::GetInstance().UnsetOffloadModeProxy(*offloadSessionID_);
446         AudioPipeType normalPipe = PIPE_TYPE_UNKNOWN;
447         MoveToNewPipe(sessionId, normalPipe);
448         streamCollector_.UpdateRendererPipeInfo(sessionId, normalPipe);
449         DynamicUnloadOffloadModule();
450         offloadSessionID_.reset();
451         audioPolicyManager_.ResetOffloadSessionId();
452         AUDIO_DEBUG_LOG("sessionId[%{public}d] release offload stream", sessionId);
453     }
454 }
455 
MoveToOutputDevice(uint32_t sessionId,std::string portName)456 int32_t AudioOffloadStream::MoveToOutputDevice(uint32_t sessionId, std::string portName)
457 {
458     std::vector<SinkInput> sinkInputs;
459     audioPolicyManager_.GetAllSinkInputs(sinkInputs);
460     std::vector<SinkInput> sinkInputIds = FilterSinkInputs(sessionId, sinkInputs);
461 
462     if (portName == BLUETOOTH_SPEAKER) {
463         std::string activePort = BLUETOOTH_SPEAKER;
464         audioPolicyManager_.SuspendAudioDevice(activePort, false);
465     }
466     AUDIO_INFO_LOG("move for session [%{public}d], portName %{public}s", sessionId, portName.c_str());
467     // start move.
468     uint32_t sinkId = -1; // invalid sink id, use sink name instead.
469     for (size_t i = 0; i < sinkInputIds.size(); i++) {
470         int32_t ret = audioPolicyManager_.MoveSinkInputByIndexOrName(sinkInputIds[i].paStreamId, sinkId, portName);
471         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERROR,
472             "move [%{public}d] to local failed", sinkInputIds[i].streamId);
473         audioRouteMap_.AddRouteMapInfo(sinkInputIds[i].uid, LOCAL_NETWORK_ID, sinkInputIds[i].pid);
474     }
475     return SUCCESS;
476 }
477 
CheckStreamMultichannelMode(const int64_t activateSessionId)478 bool AudioOffloadStream::CheckStreamMultichannelMode(const int64_t activateSessionId)
479 {
480     if (audioActiveDevice_.GetCurrentOutputDeviceNetworkId() != LOCAL_NETWORK_ID ||
481         audioActiveDevice_.GetCurrentOutputDeviceType() == DEVICE_TYPE_REMOTE_CAST) {
482         return false;
483     }
484 
485     // Multi-channel mode only when the number of channels is greater than 2.
486     int32_t channelCount = streamCollector_.GetChannelCount(activateSessionId);
487     if (channelCount < AudioChannel::CHANNEL_3) {
488         AUDIO_DEBUG_LOG("ChannelNum not allowed get multichannel mode, Skipped");
489         return false;
490     }
491 
492     // The multi-channel algorithm needs to be supported in the DSP
493     return AudioServerProxy::GetInstance().GetEffectOffloadEnabledProxy();
494 }
CheckStreamMode(const int64_t activateSessionId)495 void AudioOffloadStream::CheckStreamMode(const int64_t activateSessionId)
496 {
497     if (CheckStreamMultichannelMode(activateSessionId)) {
498         AudioPipeType pipeMultiChannel = PIPE_TYPE_MULTICHANNEL;
499         int32_t ret = streamCollector_.ActivateAudioConcurrency(pipeMultiChannel);
500         CHECK_AND_RETURN_LOG(ret == SUCCESS, "concede incoming multichannel");
501         MoveToNewPipeInner(activateSessionId, PIPE_TYPE_MULTICHANNEL);
502     }
503 }
504 
FilterSinkInputs(int32_t sessionId,std::vector<SinkInput> sinkInputs)505 std::vector<SinkInput> AudioOffloadStream::FilterSinkInputs(int32_t sessionId, std::vector<SinkInput> sinkInputs)
506 {
507     // find sink-input id with audioRendererFilter
508     std::vector<SinkInput> targetSinkInputs = {};
509 
510     for (size_t i = 0; i < sinkInputs.size(); i++) {
511         CHECK_AND_CONTINUE_LOG(sinkInputs[i].uid != dAudioClientUid,
512             "Find sink-input with daudio[%{public}d]", sinkInputs[i].pid);
513         CHECK_AND_CONTINUE_LOG(sinkInputs[i].streamType != STREAM_DEFAULT,
514             "Sink-input[%{public}zu] of effect sink, don't move", i);
515         AUDIO_DEBUG_LOG("sinkinput[%{public}zu]:%{public}s", i, PrintSinkInput(sinkInputs[i]).c_str());
516         if (sessionId == sinkInputs[i].streamId) {
517             targetSinkInputs.push_back(sinkInputs[i]);
518         }
519     }
520     return targetSinkInputs;
521 }
522 
ResetOffloadModeOnSpatializationChanged(std::vector<int32_t> & allSessions)523 void AudioOffloadStream::ResetOffloadModeOnSpatializationChanged(std::vector<int32_t> &allSessions)
524 {
525     AudioSpatializationState spatialState =
526         AudioSpatializationService::GetAudioSpatializationService().GetSpatializationState();
527     bool effectOffloadFlag = AudioServerProxy::GetInstance().GetEffectOffloadEnabledProxy();
528     AUDIO_INFO_LOG("spatialization: %{public}d, headTracking: %{public}d, effectOffloadFlag: %{public}d",
529         spatialState.spatializationEnabled, spatialState.headTrackingEnabled, effectOffloadFlag);
530     if (spatialState.spatializationEnabled) {
531         if (effectOffloadFlag) {
532             for (auto it = allSessions.begin(); it != allSessions.end(); it++) {
533                 OffloadStreamSetCheck(*it);
534             }
535         } else {
536             OffloadStreamReleaseCheck(*offloadSessionID_);
537         }
538     }
539 }
540 
ActivateConcurrencyFromServer(AudioPipeType incomingPipe)541 int32_t AudioOffloadStream::ActivateConcurrencyFromServer(AudioPipeType incomingPipe)
542 {
543     std::lock_guard<std::mutex> lock(offloadMutex_);
544     CHECK_AND_RETURN_RET_LOG(!offloadSessionID_.has_value(),
545         ERR_ILLEGAL_STATE, "Offload stream existing, concede incoming lowlatency stream");
546     return SUCCESS;
547 }
548 
549 }
550 }