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