• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef LOG_TAG
16 #define LOG_TAG "AudioA2dpOffloadManager"
17 #endif
18 
19 #include "audio_a2dp_offload_manager.h"
20 #include <ability_manager_client.h>
21 #include "iservice_registry.h"
22 #include "parameter.h"
23 #include "parameters.h"
24 #include "audio_utils.h"
25 #include "audio_policy_log.h"
26 #include "audio_utils.h"
27 #include "audio_manager_listener_stub.h"
28 #include "audio_inner_call.h"
29 #include "media_monitor_manager.h"
30 #include "audio_affinity_manager.h"
31 #include "audio_stream_collector.h"
32 #include "audio_policy_manager_factory.h"
33 #include "audio_spatialization_manager.h"
34 #include "audio_spatialization_service.h"
35 #include "audio_router_center.h"
36 
37 #include "audio_policy_utils.h"
38 #include "audio_server_proxy.h"
39 
40 namespace OHOS {
41 namespace AudioStandard {
42 const int32_t A2DP_PLAYING = 2;
43 const int32_t A2DP_STOPPED = 1;
44 const int32_t DATA_LINK_CONNECTING = 10;
45 const int32_t DATA_LINK_CONNECTED = 11;
46 const int32_t CONNECTION_TIMEOUT_IN_MS = 1000; // 1000ms
47 
48 #ifdef BLUETOOTH_ENABLE
49 const unsigned int BLUETOOTH_TIME_OUT_SECONDS = 8;
50 #endif
51 
GetEncryptAddr(const std::string & addr)52 static std::string GetEncryptAddr(const std::string &addr)
53 {
54     const int32_t START_POS = 6;
55     const int32_t END_POS = 13;
56     const int32_t ADDRESS_STR_LEN = 17;
57     if (addr.empty() || addr.length() != ADDRESS_STR_LEN) {
58         return std::string("");
59     }
60     std::string tmp = "**:**:**:**:**:**";
61     std::string out = addr;
62     for (int i = START_POS; i <= END_POS; i++) {
63         out[i] = tmp[i];
64     }
65     return out;
66 }
67 
OnA2dpPlayingStateChanged(const std::string & deviceAddress,int32_t playingState)68 void AudioA2dpOffloadManager::OnA2dpPlayingStateChanged(const std::string &deviceAddress, int32_t playingState)
69 {
70     A2dpOffloadConnectionState state = audioA2dpOffloadFlag_.GetCurrentOffloadConnectedState();
71     AUDIO_INFO_LOG("OnA2dpPlayingStateChanged current A2dpOffload MacAddr:%{public}s, incoming MacAddr:%{public}s, "
72         "currentStatus:%{public}d, incommingState:%{public}d", GetEncryptAddr(a2dpOffloadDeviceAddress_).c_str(),
73         GetEncryptAddr(deviceAddress).c_str(), state, playingState);
74     if (deviceAddress != a2dpOffloadDeviceAddress_) {
75         if (playingState == A2DP_STOPPED && state == CONNECTION_STATUS_CONNECTED) {
76             return;
77         }
78         // below is A2dp(not offload scenario)
79         audioA2dpOffloadFlag_.SetCurrentOffloadConnectedState(CONNECTION_STATUS_DISCONNECTED);
80         return;
81     }
82 
83     // deviceAddress matched
84     if (playingState == A2DP_PLAYING) {
85         if (state == CONNECTION_STATUS_CONNECTING) {
86             AUDIO_INFO_LOG("OnA2dpPlayingStateChanged state change "
87                 "from %{public}d to %{public}d", state, CONNECTION_STATUS_CONNECTED);
88 
89             for (int32_t sessionId : connectionTriggerSessionIds_) {
90                 AudioServerProxy::GetInstance().UpdateSessionConnectionStateProxy(sessionId, DATA_LINK_CONNECTED);
91             }
92             std::vector<int32_t>().swap(connectionTriggerSessionIds_);
93             connectionCV_.notify_all();
94         }
95         audioA2dpOffloadFlag_.SetCurrentOffloadConnectedState(CONNECTION_STATUS_CONNECTED);
96     } else if (playingState == A2DP_STOPPED) {
97         AUDIO_INFO_LOG("OnA2dpPlayingStateChanged state change "
98             "from %{public}d to %{public}d", state, CONNECTION_STATUS_DISCONNECTED);
99         audioA2dpOffloadFlag_.SetCurrentOffloadConnectedState(CONNECTION_STATUS_DISCONNECTED);
100         a2dpOffloadDeviceAddress_ = "";
101         std::vector<int32_t>().swap(connectionTriggerSessionIds_);
102     } else {
103         // at the current moment, we only handle the PLAYING and STOPPED state,
104         // will handle other state in the future
105         AUDIO_INFO_LOG("OnA2dpPlayingStateChanged state: %{public}d, "
106             "received unexpected state:%{public}d", state, playingState);
107     }
108 }
109 
ConnectA2dpOffload(const std::string & deviceAddress,const std::vector<int32_t> & sessionIds)110 void AudioA2dpOffloadManager::ConnectA2dpOffload(const std::string &deviceAddress,
111     const std::vector<int32_t> &sessionIds)
112 {
113     AUDIO_INFO_LOG("start connecting a2dpOffload for MacAddr:%{public}s.", GetEncryptAddr(deviceAddress).c_str());
114     A2dpOffloadConnectionState state = audioA2dpOffloadFlag_.GetCurrentOffloadConnectedState();
115     a2dpOffloadDeviceAddress_ = deviceAddress;
116     connectionTriggerSessionIds_.assign(sessionIds.begin(), sessionIds.end());
117 
118     for (int32_t sessionId : connectionTriggerSessionIds_) {
119         AudioServerProxy::GetInstance().UpdateSessionConnectionStateProxy(sessionId, DATA_LINK_CONNECTING);
120     }
121 
122     if (state == CONNECTION_STATUS_CONNECTED || state == CONNECTION_STATUS_CONNECTING) {
123         AUDIO_INFO_LOG("state already in %{public}d, "
124             "status, no need to trigger another waiting", state);
125         return;
126     }
127 
128     std::thread switchThread(&AudioA2dpOffloadManager::WaitForConnectionCompleted, this);
129     switchThread.detach();
130     AUDIO_INFO_LOG("state change from %{public}d to %{public}d",
131         state, CONNECTION_STATUS_CONNECTING);
132     audioA2dpOffloadFlag_.SetCurrentOffloadConnectedState(CONNECTION_STATUS_CONNECTING);
133 }
134 
WaitForConnectionCompleted()135 void AudioA2dpOffloadManager::WaitForConnectionCompleted()
136 {
137     std::unique_lock<std::mutex> waitLock(connectionMutex_);
138     bool connectionCompleted = connectionCV_.wait_for(waitLock,
139         std::chrono::milliseconds(CONNECTION_TIMEOUT_IN_MS), [this] {
140             return audioA2dpOffloadFlag_.GetCurrentOffloadConnectedState() == CONNECTION_STATUS_CONNECTED;
141         });
142     // a2dp connection timeout, anyway we should notify client dataLink OK in order to allow the data flow begin
143     AUDIO_INFO_LOG("WaitForConnectionCompleted unblocked, connectionCompleted is %{public}d", connectionCompleted);
144 
145     if (!connectionCompleted) {
146         AUDIO_INFO_LOG("state change from %{public}d to %{public}d",
147             audioA2dpOffloadFlag_.GetCurrentOffloadConnectedState(), CONNECTION_STATUS_TIMEOUT);
148         audioA2dpOffloadFlag_.SetCurrentOffloadConnectedState(CONNECTION_STATUS_CONNECTED);
149         for (int32_t sessionId : connectionTriggerSessionIds_) {
150             AudioServerProxy::GetInstance().UpdateSessionConnectionStateProxy(sessionId, DATA_LINK_CONNECTED);
151         }
152         std::vector<int32_t>().swap(connectionTriggerSessionIds_);
153     }
154     waitLock.unlock();
155     FetchStreamForA2dpOffload(false);
156     return;
157 }
158 
IsA2dpOffloadConnecting(int32_t sessionId)159 bool AudioA2dpOffloadManager::IsA2dpOffloadConnecting(int32_t sessionId)
160 {
161     if (audioA2dpOffloadFlag_.GetCurrentOffloadConnectedState() == CONNECTION_STATUS_CONNECTING) {
162         if (std::find(connectionTriggerSessionIds_.begin(), connectionTriggerSessionIds_.end(), sessionId) !=
163             connectionTriggerSessionIds_.end()) {
164             return true;
165         }
166     }
167     return false;
168 }
169 
IsA2dpOffloadConnected()170 bool AudioA2dpOffloadManager::IsA2dpOffloadConnected()
171 {
172     return audioA2dpOffloadFlag_.GetCurrentOffloadConnectedState() == CONNECTION_STATUS_CONNECTED;
173 }
174 
OffloadStartPlaying(const std::vector<int32_t> & sessionIds)175 int32_t AudioA2dpOffloadManager::OffloadStartPlaying(const std::vector<int32_t> &sessionIds)
176 {
177 #ifdef BLUETOOTH_ENABLE
178     AUDIO_INFO_LOG("OffloadStartPlaying, a2dpOffloadFlag_: %{public}d, sessionIds: %{public}zu",
179         GetA2dpOffloadFlag(), sessionIds.size());
180     if (GetA2dpOffloadFlag() != A2DP_OFFLOAD || sessionIds.size() == 0) {
181         return SUCCESS;
182     }
183     int32_t ret = audioA2dpOffloadFlag_.OffloadStartPlaying(sessionIds);
184     A2dpOffloadConnectionState state = audioA2dpOffloadFlag_.GetCurrentOffloadConnectedState();
185     if (ret == SUCCESS && (state != CONNECTION_STATUS_CONNECTED)) {
186         ConnectA2dpOffload(Bluetooth::AudioA2dpManager::GetActiveA2dpDevice(), sessionIds);
187     }
188     return ret;
189 #else
190     return SUCCESS;
191 #endif
192 }
193 
OffloadStopPlaying(const std::vector<int32_t> & sessionIds)194 int32_t AudioA2dpOffloadManager::OffloadStopPlaying(const std::vector<int32_t> &sessionIds)
195 {
196 #ifdef BLUETOOTH_ENABLE
197     AUDIO_PRERELEASE_LOGI("OffloadStopPlaying, a2dpOffloadFlag_: %{public}d, sessionIds: %{public}zu",
198         GetA2dpOffloadFlag(), sessionIds.size());
199     if (GetA2dpOffloadFlag() != A2DP_OFFLOAD || sessionIds.size() == 0) {
200         return SUCCESS;
201     }
202     return audioA2dpOffloadFlag_.OffloadStopPlaying(sessionIds);
203 #else
204     return SUCCESS;
205 #endif
206 }
207 
SetA2dpOffloadFlag(BluetoothOffloadState state)208 void AudioA2dpOffloadManager::SetA2dpOffloadFlag(BluetoothOffloadState state)
209 {
210     audioA2dpOffloadFlag_.SetA2dpOffloadFlag(state);
211 }
212 
GetA2dpOffloadFlag()213 BluetoothOffloadState AudioA2dpOffloadManager::GetA2dpOffloadFlag()
214 {
215     return audioA2dpOffloadFlag_.GetA2dpOffloadFlag();
216 }
217 
UpdateA2dpOffloadFlagForAllStream(std::unordered_map<uint32_t,bool> & sessionIDToSpatializationEnableMap,DeviceType deviceType)218 void AudioA2dpOffloadManager::UpdateA2dpOffloadFlagForAllStream(
219     std::unordered_map<uint32_t, bool> &sessionIDToSpatializationEnableMap, DeviceType deviceType)
220 {
221 #ifdef BLUETOOTH_ENABLE
222     vector<Bluetooth::A2dpStreamInfo> allSessionInfos;
223     Bluetooth::A2dpStreamInfo a2dpStreamInfo;
224     vector<shared_ptr<AudioRendererChangeInfo>> audioRendererChangeInfos;
225     streamCollector_.GetCurrentRendererChangeInfos(audioRendererChangeInfos);
226     std::vector<int32_t> stopPlayingStream(0);
227     for (auto &changeInfo : audioRendererChangeInfos) {
228         if (changeInfo->rendererState != RENDERER_RUNNING) {
229             stopPlayingStream.emplace_back(changeInfo->sessionId);
230             continue;
231         }
232         a2dpStreamInfo.sessionId = changeInfo->sessionId;
233         a2dpStreamInfo.streamType = streamCollector_.GetStreamType(changeInfo->sessionId);
234         if (sessionIDToSpatializationEnableMap.count(static_cast<uint32_t>(a2dpStreamInfo.sessionId))) {
235             a2dpStreamInfo.isSpatialAudio =
236                 sessionIDToSpatializationEnableMap[static_cast<uint32_t>(a2dpStreamInfo.sessionId)];
237         } else {
238             a2dpStreamInfo.isSpatialAudio = 0;
239         }
240         allSessionInfos.push_back(a2dpStreamInfo);
241     }
242     if (stopPlayingStream.size() > 0) {
243         OffloadStopPlaying(stopPlayingStream);
244     }
245     UpdateA2dpOffloadFlag(allSessionInfos, deviceType);
246 #endif
247     AUDIO_DEBUG_LOG("deviceType %{public}d", deviceType);
248 }
249 
UpdateA2dpOffloadFlagForAllStream(DeviceType deviceType)250 int32_t AudioA2dpOffloadManager::UpdateA2dpOffloadFlagForAllStream(DeviceType deviceType)
251 {
252     int32_t activeSessionsSize = 0;
253 #ifdef BLUETOOTH_ENABLE
254     vector<Bluetooth::A2dpStreamInfo> allSessionInfos;
255     Bluetooth::A2dpStreamInfo a2dpStreamInfo;
256     vector<shared_ptr<AudioRendererChangeInfo>> audioRendererChangeInfos;
257     streamCollector_.GetCurrentRendererChangeInfos(audioRendererChangeInfos);
258     {
259         AudioXCollie audioXCollie("AudioA2dpOffloadManager::UpdateA2dpOffloadFlagForAllStream",
260             BLUETOOTH_TIME_OUT_SECONDS);
261         std::vector<int32_t> stopPlayingStream(0);
262         for (auto &changeInfo : audioRendererChangeInfos) {
263             if (changeInfo->rendererState != RENDERER_RUNNING) {
264                 stopPlayingStream.emplace_back(changeInfo->sessionId);
265                 continue;
266             }
267             a2dpStreamInfo.sessionId = changeInfo->sessionId;
268             a2dpStreamInfo.streamType = streamCollector_.GetStreamType(changeInfo->sessionId);
269             StreamUsage tempStreamUsage = changeInfo->rendererInfo.streamUsage;
270             AudioSpatializationState spatialState =
271                 AudioSpatializationService::GetAudioSpatializationService().GetSpatializationState(tempStreamUsage);
272             a2dpStreamInfo.isSpatialAudio = spatialState.spatializationEnabled;
273             allSessionInfos.push_back(a2dpStreamInfo);
274         }
275         if (stopPlayingStream.size() > 0) {
276             OffloadStopPlaying(stopPlayingStream);
277         }
278     }
279     UpdateA2dpOffloadFlag(allSessionInfos, deviceType);
280     activeSessionsSize = static_cast<int32_t>(allSessionInfos.size());
281 #endif
282     AUDIO_DEBUG_LOG("deviceType %{public}d", deviceType);
283     return activeSessionsSize;
284 }
285 
UpdateOffloadWhenActiveDeviceSwitchFromA2dp()286 void AudioA2dpOffloadManager::UpdateOffloadWhenActiveDeviceSwitchFromA2dp()
287 {
288     AUDIO_PRERELEASE_LOGI("a2dpOffloadFlag change from %{public}d to %{public}d", GetA2dpOffloadFlag(),
289         NO_A2DP_DEVICE);
290     std::vector<int32_t> allSessions;
291     GetAllRunningStreamSession(allSessions);
292     OffloadStopPlaying(allSessions);
293     SetA2dpOffloadFlag(NO_A2DP_DEVICE);
294     for (auto it = allSessions.begin(); it != allSessions.end(); ++it) {
295         audioOffloadStream_.ResetOffloadMode(*it);
296     }
297 }
298 
299 #ifdef BLUETOOTH_ENABLE
UpdateA2dpOffloadFlag(const std::vector<Bluetooth::A2dpStreamInfo> & allActiveSessions,DeviceType deviceType)300 void AudioA2dpOffloadManager::UpdateA2dpOffloadFlag(const std::vector<Bluetooth::A2dpStreamInfo> &allActiveSessions,
301     DeviceType deviceType)
302 {
303     if (allActiveSessions.size() == 0) {
304         AUDIO_PRERELEASE_LOGI("no active sessions");
305         return;
306     }
307     auto receiveOffloadFlag = NO_A2DP_DEVICE;
308     if (deviceType == DEVICE_TYPE_BLUETOOTH_A2DP) {
309         receiveOffloadFlag = static_cast<BluetoothOffloadState>(Bluetooth::AudioA2dpManager::A2dpOffloadSessionRequest(
310             allActiveSessions));
311     } else if (audioActiveDevice_.GetCurrentOutputDeviceType() == DEVICE_TYPE_BLUETOOTH_A2DP &&
312         audioActiveDevice_.GetCurrentOutputDeviceNetworkId() == LOCAL_NETWORK_ID && deviceType == DEVICE_TYPE_NONE) {
313         receiveOffloadFlag = static_cast<BluetoothOffloadState>(Bluetooth::AudioA2dpManager::A2dpOffloadSessionRequest(
314             allActiveSessions));
315     }
316 
317     std::lock_guard<std::mutex> lock(switchA2dpOffloadMutex_);
318     AUDIO_PRERELEASE_LOGI("deviceType: %{public}d, currentActiveDevice_: %{public}d, allActiveSessions: %{public}zu, "
319         "a2dpOffloadFlag: %{public}d, receiveOffloadFlag: %{public}d",
320         deviceType, audioActiveDevice_.GetCurrentOutputDeviceType(), allActiveSessions.size(), GetA2dpOffloadFlag(),
321         receiveOffloadFlag);
322 
323     if (receiveOffloadFlag == NO_A2DP_DEVICE) {
324         UpdateOffloadWhenActiveDeviceSwitchFromA2dp();
325     } else if (receiveOffloadFlag != GetA2dpOffloadFlag()) {
326         if (GetA2dpOffloadFlag() == A2DP_OFFLOAD) {
327             HandleA2dpDeviceOutOffload(receiveOffloadFlag);
328         } else if (receiveOffloadFlag == A2DP_OFFLOAD) {
329             HandleA2dpDeviceInOffload(receiveOffloadFlag);
330         } else {
331             AUDIO_INFO_LOG("a2dpOffloadFlag change from %{public}d to %{public}d", GetA2dpOffloadFlag(),
332                 receiveOffloadFlag);
333             SetA2dpOffloadFlag(receiveOffloadFlag);
334         }
335     } else if (GetA2dpOffloadFlag() == A2DP_OFFLOAD) {
336         std::vector<int32_t> allSessions;
337         GetAllRunningStreamSession(allSessions);
338         OffloadStartPlaying(allSessions);
339         AudioServerProxy::GetInstance().UpdateEffectBtOffloadSupportedProxy(true);
340         audioOffloadStream_.ResetOffloadModeOnSpatializationChanged(allSessions);
341         GetA2dpOffloadCodecAndSendToDsp();
342         std::string activePort = BLUETOOTH_SPEAKER;
343         audioPolicyManager_.SuspendAudioDevice(activePort, true);
344     }
345 }
346 
347 #endif
348 
HandleA2dpDeviceOutOffload(BluetoothOffloadState a2dpOffloadFlag)349 int32_t AudioA2dpOffloadManager::HandleA2dpDeviceOutOffload(BluetoothOffloadState a2dpOffloadFlag)
350 {
351 #ifdef BLUETOOTH_ENABLE
352     AUDIO_INFO_LOG("a2dpOffloadFlag change from %{public}d to %{public}d", GetA2dpOffloadFlag(), a2dpOffloadFlag);
353     std::vector<int32_t> allSessions;
354     GetAllRunningStreamSession(allSessions);
355     OffloadStopPlaying(allSessions);
356     SetA2dpOffloadFlag(a2dpOffloadFlag);
357 
358     DeviceType dev = audioActiveDevice_.GetCurrentOutputDeviceType();
359     AudioPolicyUtils::GetInstance().UpdateEffectDefaultSink(dev);
360     AUDIO_INFO_LOG("Handle A2dpDevice Out Offload");
361 
362     FetchStreamForA2dpOffload(true);
363 
364     if (audioActiveDevice_.GetCurrentOutputDeviceType() == DEVICE_TYPE_BLUETOOTH_A2DP) {
365         return HandleActiveDevice(DEVICE_TYPE_BLUETOOTH_A2DP);
366     } else {
367         return SUCCESS;
368     }
369 #else
370     return ERROR;
371 #endif
372 }
373 
HandleA2dpDeviceInOffload(BluetoothOffloadState a2dpOffloadFlag)374 int32_t AudioA2dpOffloadManager::HandleA2dpDeviceInOffload(BluetoothOffloadState a2dpOffloadFlag)
375 {
376 #ifdef BLUETOOTH_ENABLE
377     AUDIO_INFO_LOG("a2dpOffloadFlag change from %{public}d to %{public}d", GetA2dpOffloadFlag(), a2dpOffloadFlag);
378     SetA2dpOffloadFlag(a2dpOffloadFlag);
379     GetA2dpOffloadCodecAndSendToDsp();
380     std::vector<int32_t> allSessions;
381     GetAllRunningStreamSession(allSessions);
382     OffloadStartPlaying(allSessions);
383 
384     DeviceType dev = audioActiveDevice_.GetCurrentOutputDeviceType();
385     AudioPolicyUtils::GetInstance().UpdateEffectDefaultSink(dev);
386     AUDIO_INFO_LOG("Handle A2dpDevice In Offload");
387     AudioServerProxy::GetInstance().UpdateEffectBtOffloadSupportedProxy(true);
388 
389     if (IsA2dpOffloadConnected()) {
390         AUDIO_INFO_LOG("A2dpOffload has been connected, Fetch stream");
391         FetchStreamForA2dpOffload(true);
392     }
393     return SUCCESS;
394 #else
395     return ERROR;
396 #endif
397 }
398 
GetA2dpOffloadCodecAndSendToDsp()399 void AudioA2dpOffloadManager::GetA2dpOffloadCodecAndSendToDsp()
400 {
401 #ifdef BLUETOOTH_ENABLE
402     if (audioActiveDevice_.GetCurrentOutputDeviceType() != DEVICE_TYPE_BLUETOOTH_A2DP) {
403         return;
404     }
405     Bluetooth::BluetoothRemoteDevice bluetoothRemoteDevice_
406         = Bluetooth::AudioA2dpManager::GetCurrentActiveA2dpDevice();
407     Bluetooth::A2dpOffloadCodecStatus offloadCodeStatus = Bluetooth::A2dpSource::GetProfile()->
408         GetOffloadCodecStatus(bluetoothRemoteDevice_);
409     std::string key = "AUDIO_EXT_PARAM_KEY_A2DP_OFFLOAD_CONFIG";
410     std::string value = std::to_string(offloadCodeStatus.offloadInfo.mediaPacketHeader) + ","
411         + std::to_string(offloadCodeStatus.offloadInfo.mPt) + ","
412         + std::to_string(offloadCodeStatus.offloadInfo.ssrc) + ","
413         + std::to_string(offloadCodeStatus.offloadInfo.boundaryFlag) + ","
414         + std::to_string(offloadCodeStatus.offloadInfo.broadcastFlag) + ","
415         + std::to_string(offloadCodeStatus.offloadInfo.codecType) + ","
416         + std::to_string(offloadCodeStatus.offloadInfo.maxLatency) + ","
417         + std::to_string(offloadCodeStatus.offloadInfo.scmsTEnable) + ","
418         + std::to_string(offloadCodeStatus.offloadInfo.sampleRate) + ","
419         + std::to_string(offloadCodeStatus.offloadInfo.encodedAudioBitrate) + ","
420         + std::to_string(offloadCodeStatus.offloadInfo.bitsPerSample) + ","
421         + std::to_string(offloadCodeStatus.offloadInfo.chMode) + ","
422         + std::to_string(offloadCodeStatus.offloadInfo.aclHdl) + ","
423         + std::to_string(offloadCodeStatus.offloadInfo.l2cRcid) + ","
424         + std::to_string(offloadCodeStatus.offloadInfo.mtu) + ","
425         + std::to_string(offloadCodeStatus.offloadInfo.codecSpecific0) + ","
426         + std::to_string(offloadCodeStatus.offloadInfo.codecSpecific1) + ","
427         + std::to_string(offloadCodeStatus.offloadInfo.codecSpecific2) + ","
428         + std::to_string(offloadCodeStatus.offloadInfo.codecSpecific3) + ","
429         + std::to_string(offloadCodeStatus.offloadInfo.codecSpecific4) + ","
430         + std::to_string(offloadCodeStatus.offloadInfo.codecSpecific5) + ","
431         + std::to_string(offloadCodeStatus.offloadInfo.codecSpecific6) + ","
432         + std::to_string(offloadCodeStatus.offloadInfo.codecSpecific7) + ";";
433 
434     AudioServerProxy::GetInstance().SetAudioParameterProxy(key, value);
435     AUDIO_INFO_LOG("update offloadcodec[%{public}s]", value.c_str());
436 #endif
437 }
438 
HandleActiveDevice(DeviceType deviceType)439 int32_t AudioA2dpOffloadManager::HandleActiveDevice(DeviceType deviceType)
440 {
441     DeviceType curOutputDeviceType = audioActiveDevice_.GetCurrentOutputDeviceType();
442     if (GetVolumeGroupType(curOutputDeviceType) != GetVolumeGroupType(deviceType)) {
443         audioVolumeManager_.SetVolumeForSwitchDevice(deviceType);
444     }
445     if (audioConfigManager_.GetUpdateRouteSupport()) {
446         audioActiveDevice_.UpdateActiveDeviceRoute(deviceType, DeviceFlag::OUTPUT_DEVICES_FLAG);
447     }
448     std::string sinkPortName = AudioPolicyUtils::GetInstance().GetSinkPortName(deviceType);
449     std::string sourcePortName = AudioPolicyUtils::GetInstance().GetSourcePortName(deviceType);
450     if (sinkPortName == PORT_NONE && sourcePortName == PORT_NONE) {
451         AUDIO_ERR_LOG("failed for sinkPortName and sourcePortName are none");
452         return ERR_OPERATION_FAILED;
453     }
454     if (sinkPortName != PORT_NONE) {
455         audioIOHandleMap_.GetSinkIOHandle(deviceType);
456         audioPolicyManager_.SuspendAudioDevice(sinkPortName, false);
457     }
458     if (sourcePortName != PORT_NONE) {
459         audioIOHandleMap_.GetSourceIOHandle(deviceType);
460         audioPolicyManager_.SuspendAudioDevice(sourcePortName, false);
461     }
462     audioActiveDevice_.UpdateInputDeviceInfo(deviceType);
463 
464     return SUCCESS;
465 }
466 
FetchStreamForA2dpOffload(const bool & requireReset)467 void AudioA2dpOffloadManager::FetchStreamForA2dpOffload(const bool &requireReset)
468 {
469     vector<shared_ptr<AudioRendererChangeInfo>> rendererChangeInfos;
470     streamCollector_.GetCurrentRendererChangeInfos(rendererChangeInfos);
471     AUDIO_INFO_LOG("FetchStreamForA2dpOffload start for %{public}zu stream", rendererChangeInfos.size());
472     for (auto &rendererChangeInfo : rendererChangeInfos) {
473         if (!audioDeviceCommon_.IsRendererStreamRunning(rendererChangeInfo)) {
474             continue;
475         }
476         vector<std::shared_ptr<AudioDeviceDescriptor>> descs =
477             audioRouterCenter_.FetchOutputDevices(rendererChangeInfo->rendererInfo.streamUsage,
478             rendererChangeInfo->clientUID);
479 
480         if (descs.front()->deviceType_ == DEVICE_TYPE_BLUETOOTH_A2DP) {
481             if (requireReset) {
482                 int32_t ret = audioDeviceCommon_.ActivateA2dpDevice(descs.front(), rendererChangeInfos);
483                 CHECK_AND_RETURN_LOG(ret == SUCCESS, "activate a2dp [%{public}s] failed",
484                     GetEncryptAddr(descs.front()->macAddress_).c_str());
485                 std::string activePort = BLUETOOTH_SPEAKER;
486                 audioPolicyManager_.SuspendAudioDevice(activePort, true);
487             }
488             if (rendererChangeInfo->rendererInfo.rendererFlags == AUDIO_FLAG_MMAP) {
489                 AudioServerProxy::GetInstance().ResetAudioEndpointProxy();
490             }
491             audioDeviceCommon_.FetchStreamForA2dpMchStream(rendererChangeInfo, descs);
492         }
493     }
494 }
495 
GetAllRunningStreamSession(std::vector<int32_t> & allSessions,bool doStop)496 void AudioA2dpOffloadManager::GetAllRunningStreamSession(std::vector<int32_t> &allSessions, bool doStop)
497 {
498 #ifdef BLUETOOTH_ENABLE
499     std::vector<std::shared_ptr<AudioRendererChangeInfo>> rendererChangeInfos;
500     streamCollector_.GetCurrentRendererChangeInfos(rendererChangeInfos);
501     std::vector<int32_t> stopPlayingStream(0);
502     for (auto &changeInfo : rendererChangeInfos) {
503         if (changeInfo->rendererState != RENDERER_RUNNING) {
504             if (doStop) {
505                 stopPlayingStream.push_back(changeInfo->sessionId);
506             }
507             continue;
508         }
509         allSessions.push_back(changeInfo->sessionId);
510     }
511     if (doStop && stopPlayingStream.size() > 0) {
512         OffloadStopPlaying(stopPlayingStream);
513     }
514 #endif
515 }
516 
GetVolumeGroupType(DeviceType deviceType)517 std::string AudioA2dpOffloadManager::GetVolumeGroupType(DeviceType deviceType)
518 {
519     std::string volumeGroupType = "";
520     switch (deviceType) {
521         case DEVICE_TYPE_EARPIECE:
522         case DEVICE_TYPE_SPEAKER:
523         case DEVICE_TYPE_DP:
524         case DEVICE_TYPE_HDMI:
525             volumeGroupType = "build-in";
526             break;
527         case DEVICE_TYPE_BLUETOOTH_A2DP:
528         case DEVICE_TYPE_BLUETOOTH_SCO:
529             volumeGroupType = "wireless";
530             break;
531         case DEVICE_TYPE_WIRED_HEADSET:
532         case DEVICE_TYPE_USB_HEADSET:
533         case DEVICE_TYPE_USB_ARM_HEADSET:
534             volumeGroupType = "wired";
535             break;
536         default:
537             AUDIO_ERR_LOG("device %{public}d is not supported", deviceType);
538             break;
539     }
540     return volumeGroupType;
541 }
542 
543 }
544 }