1 /*
2  * Copyright (c) 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 #undef LOG_TAG
16 #define LOG_TAG "AudioSessionService"
17 
18 #include "audio_session_service.h"
19 
20 #include "audio_errors.h"
21 #include "audio_log.h"
22 
23 namespace OHOS {
24 namespace AudioStandard {
25 static const std::unordered_map<AudioStreamType, AudioSessionType> SESSION_TYPE_MAP = {
26     {STREAM_ALARM, AudioSessionType::SONIFICATION},
27     {STREAM_RING, AudioSessionType::SONIFICATION},
28     {STREAM_MUSIC, AudioSessionType::MEDIA},
29     {STREAM_MOVIE, AudioSessionType::MEDIA},
30     {STREAM_GAME, AudioSessionType::MEDIA},
31     {STREAM_SPEECH, AudioSessionType::MEDIA},
32     {STREAM_NAVIGATION, AudioSessionType::MEDIA},
33     {STREAM_VOICE_MESSAGE, AudioSessionType::MEDIA},
34     {STREAM_VOICE_CALL, AudioSessionType::CALL},
35     {STREAM_VOICE_CALL_ASSISTANT, AudioSessionType::CALL},
36     {STREAM_VOICE_COMMUNICATION, AudioSessionType::VOIP},
37     {STREAM_SYSTEM, AudioSessionType::SYSTEM},
38     {STREAM_SYSTEM_ENFORCED, AudioSessionType::SYSTEM},
39     {STREAM_ACCESSIBILITY, AudioSessionType::SYSTEM},
40     {STREAM_ULTRASONIC, AudioSessionType::SYSTEM},
41     {STREAM_NOTIFICATION, AudioSessionType::NOTIFICATION},
42     {STREAM_DTMF, AudioSessionType::DTMF},
43     {STREAM_VOICE_ASSISTANT, AudioSessionType::VOICE_ASSISTANT},
44 };
45 
AudioSessionService()46 AudioSessionService::AudioSessionService()
47 {
48 }
49 
~AudioSessionService()50 AudioSessionService::~AudioSessionService()
51 {
52 }
53 
Init()54 void AudioSessionService::Init()
55 {
56     AUDIO_INFO_LOG("AudioSessionService::Init");
57 
58     sessionTimer_ = std::make_shared<AudioSessionTimer>();
59     sessionTimer_->SetAudioSessionTimerCallback(shared_from_this());
60 }
61 
IsSameTypeForAudioSession(const AudioStreamType incomingType,const AudioStreamType existedType)62 bool AudioSessionService::IsSameTypeForAudioSession(const AudioStreamType incomingType,
63     const AudioStreamType existedType)
64 {
65     if (SESSION_TYPE_MAP.count(incomingType) == 0 || SESSION_TYPE_MAP.count(existedType) == 0) {
66         AUDIO_WARNING_LOG("The stream type (new:%{public}d or old:%{public}d) is invalid!", incomingType, existedType);
67         return false;
68     }
69     return SESSION_TYPE_MAP.at(incomingType) == SESSION_TYPE_MAP.at(existedType);
70 }
71 
ActivateAudioSession(const int32_t callerPid,const AudioSessionStrategy & strategy)72 int32_t AudioSessionService::ActivateAudioSession(const int32_t callerPid, const AudioSessionStrategy &strategy)
73 {
74     AUDIO_INFO_LOG("ActivateAudioSession: callerPid %{public}d, concurrencyMode %{public}d",
75         callerPid, static_cast<int32_t>(strategy.concurrencyMode));
76     std::lock_guard<std::mutex> lock(sessionServiceMutex_);
77     if (sessionMap_.count(callerPid) != 0 && sessionMap_[callerPid] != nullptr) {
78         // The audio session of the callerPid is already created. The strategy will be updated.
79         AUDIO_INFO_LOG("The audio seesion of pid %{public}d has already been created! Update strategy.", callerPid);
80         sessionMap_[callerPid]->SetSessionStrategy(strategy);
81     } else {
82         sessionMap_[callerPid] = std::make_shared<AudioSession>(callerPid, strategy, sessionTimer_);
83         sessionMap_[callerPid]->Activate();
84     }
85 
86     if (sessionMap_[callerPid]->IsAudioSessionEmpty()) {
87         sessionTimer_->StartTimer(callerPid);
88     }
89 
90     return SUCCESS;
91 }
92 
DeactivateAudioSession(const int32_t callerPid)93 int32_t AudioSessionService::DeactivateAudioSession(const int32_t callerPid)
94 {
95     AUDIO_INFO_LOG("DeactivateAudioSession: callerPid %{public}d", callerPid);
96     std::lock_guard<std::mutex> lock(sessionServiceMutex_);
97     return DeactivateAudioSessionInternal(callerPid);
98 }
99 
DeactivateAudioSessionInternal(const int32_t callerPid,bool isSessionTimeout)100 int32_t AudioSessionService::DeactivateAudioSessionInternal(const int32_t callerPid, bool isSessionTimeout)
101 {
102     AUDIO_INFO_LOG("DeactivateAudioSessionInternal: callerPid %{public}d", callerPid);
103     if (sessionMap_.count(callerPid) == 0) {
104         // The audio session of the callerPid is not existed or has been released.
105         AUDIO_ERR_LOG("The audio seesion of pid %{public}d is not found!", callerPid);
106         return ERR_ILLEGAL_STATE;
107     }
108     sessionMap_[callerPid]->Deactivate();
109     sessionMap_.erase(callerPid);
110 
111     if (!isSessionTimeout) {
112         sessionTimer_->StopTimer(callerPid);
113     }
114 
115     return SUCCESS;
116 }
117 
IsAudioSessionActivated(const int32_t callerPid)118 bool AudioSessionService::IsAudioSessionActivated(const int32_t callerPid)
119 {
120     std::lock_guard<std::mutex> lock(sessionServiceMutex_);
121     if (sessionMap_.count(callerPid) == 0) {
122         // The audio session of the callerPid is not existed or has been released.
123         AUDIO_WARNING_LOG("The audio seesion of pid %{public}d is not found!", callerPid);
124         return false;
125     }
126     return true;
127 }
128 
SetSessionTimeOutCallback(const std::shared_ptr<SessionTimeOutCallback> & timeOutCallback)129 int32_t AudioSessionService::SetSessionTimeOutCallback(
130     const std::shared_ptr<SessionTimeOutCallback> &timeOutCallback)
131 {
132     AUDIO_INFO_LOG("SetSessionTimeOutCallback is nullptr!");
133     std::lock_guard<std::mutex> lock(sessionServiceMutex_);
134     if (timeOutCallback == nullptr) {
135         AUDIO_ERR_LOG("timeOutCallback is nullptr!");
136         return AUDIO_INVALID_PARAM;
137     }
138     timeOutCallback_ = timeOutCallback;
139     return SUCCESS;
140 }
141 
GetAudioSessionByPid(const int32_t callerPid)142 std::shared_ptr<AudioSession> AudioSessionService::GetAudioSessionByPid(const int32_t callerPid)
143 {
144     AUDIO_INFO_LOG("GetAudioSessionByPid: callerPid %{public}d", callerPid);
145     std::lock_guard<std::mutex> lock(sessionServiceMutex_);
146     if (sessionMap_.count(callerPid) == 0) {
147         AUDIO_ERR_LOG("The audio seesion of pid %{public}d is not found!", callerPid);
148         return nullptr;
149     }
150     return sessionMap_[callerPid];
151 }
152 
153 // Audio session timer callback
OnAudioSessionTimeOut(const int32_t callerPid)154 void AudioSessionService::OnAudioSessionTimeOut(const int32_t callerPid)
155 {
156     AUDIO_INFO_LOG("OnAudioSessionTimeOut: callerPid %{public}d", callerPid);
157     std::unique_lock<std::mutex> lock(sessionServiceMutex_);
158     DeactivateAudioSessionInternal(callerPid, true);
159     lock.unlock();
160 
161     auto cb = timeOutCallback_.lock();
162     if (cb == nullptr) {
163         AUDIO_ERR_LOG("timeOutCallback_ is nullptr!");
164         return;
165     }
166     cb->OnSessionTimeout(callerPid);
167 }
168 } // namespace AudioStandard
169 } // namespace OHOS
170