1 /*
2 * Copyright (c) 2022 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
16 #include "focus_session_strategy.h"
17 #include "avsession_log.h"
18 #include "audio_adapter.h"
19 #include "avsession_sysevent.h"
20 #include "avsession_event_handler.h"
21
22 namespace OHOS::AVSession {
FocusSessionStrategy()23 FocusSessionStrategy::FocusSessionStrategy()
24 {
25 SLOGI("construct");
26 }
27
~FocusSessionStrategy()28 FocusSessionStrategy::~FocusSessionStrategy()
29 {
30 SLOGI("destroy");
31 AudioStandard::AudioStreamManager::GetInstance()->UnregisterAudioRendererEventListener(getpid());
32 }
33
Init()34 void FocusSessionStrategy::Init()
35 {
36 AudioAdapter::GetInstance().AddStreamRendererStateListener([this](const auto& infos) {
37 HandleAudioRenderStateChangeEvent(infos);
38 });
39 }
40
RegisterFocusSessionChangeCallback(const FocusSessionChangeCallback & callback)41 void FocusSessionStrategy::RegisterFocusSessionChangeCallback(const FocusSessionChangeCallback& callback)
42 {
43 callback_ = callback;
44 }
45
RegisterFocusSessionSelector(const FocusSessionSelector & selector)46 void FocusSessionStrategy::RegisterFocusSessionSelector(const FocusSessionSelector& selector)
47 {
48 selector_ = selector;
49 }
50
SetAudioPlayingUids(std::vector<int> audioPlayingUids)51 void FocusSessionStrategy::SetAudioPlayingUids(std::vector<int> audioPlayingUids)
52 {
53 std::lock_guard lockGuard(audioPlayingLock_);
54 audioPlayingUids_ = audioPlayingUids;
55 }
56
GetAudioPlayingUids()57 std::vector<int> FocusSessionStrategy::GetAudioPlayingUids()
58 {
59 std::lock_guard lockGuard(audioPlayingLock_);
60 return audioPlayingUids_;
61 }
62
ProcAudioRenderChange(const AudioRendererChangeInfos & infos)63 void FocusSessionStrategy::ProcAudioRenderChange(const AudioRendererChangeInfos& infos)
64 {
65 SLOGD("AudioRenderStateChange start");
66 std::lock_guard lockGuard(audioPlayingLock_);
67 audioPlayingUids_.clear();
68 std::pair<int32_t, int32_t> playingKey = std::make_pair(-1, -1);
69 for (const auto& info : infos) {
70 SLOGD("AudioRenderStateChange uid=%{public}d pid=%{public}d audioSessionId=%{public}d state=%{public}d",
71 info->clientUID, info->clientPid, info->sessionId, info->rendererState);
72 if (std::find(audioPlayingUids_.begin(), audioPlayingUids_.end(), info->clientUID) == audioPlayingUids_.end() &&
73 (std::count(AUDIO_PLAYING_STREAM_USAGE.begin(), AUDIO_PLAYING_STREAM_USAGE.end(),
74 info->rendererInfo.streamUsage) != 0) && (std::count(AUDIO_PLAYING_STREAM_STATE.begin(),
75 AUDIO_PLAYING_STREAM_STATE.end(), info->rendererState) != 0)) {
76 audioPlayingUids_.push_back(info->clientUID);
77 }
78 if (info->clientUID == ancoUid && (std::count(ALLOWED_ANCO_STREAM_USAGE.begin(),
79 ALLOWED_ANCO_STREAM_USAGE.end(), info->rendererInfo.streamUsage) == 0)) {
80 SLOGI("Anco invalid uid=%{public}d usage=%{public}d", info->clientUID, info->rendererInfo.streamUsage);
81 continue;
82 }
83 if ((std::count(ALLOWED_MEDIA_STREAM_USAGE.begin(),
84 ALLOWED_MEDIA_STREAM_USAGE.end(), info->rendererInfo.streamUsage) == 0)) {
85 SLOGI("Media invalid uid=%{public}d usage=%{public}d", info->clientUID, info->rendererInfo.streamUsage);
86 continue;
87 }
88 bool isPidValid = info->clientPid != 0;
89 CHECK_AND_CONTINUE(isPidValid);
90 {
91 std::lock_guard lockGuard(stateLock_);
92 std::pair<int32_t, int32_t> key = std::make_pair(info->clientUID, info->clientPid);
93 auto it = currentStates_.find(key);
94 if (it == currentStates_.end()) {
95 currentStates_[key] = stopState;
96 }
97
98 if (info->rendererState == AudioStandard::RendererState::RENDERER_RUNNING) {
99 currentStates_[key] = runningState;
100 playingKey = key;
101 }
102 if (playingKey != key) {
103 currentStates_[key] = info->rendererState == AudioStandard::RendererState::RENDERER_RELEASED ?
104 releaseState : stopState;
105 }
106 }
107 }
108 SLOGD("AudioRenderStateChange end");
109 }
110
HandleAudioRenderStateChangeEvent(const AudioRendererChangeInfos & infos)111 void FocusSessionStrategy::HandleAudioRenderStateChangeEvent(const AudioRendererChangeInfos& infos)
112 {
113 ProcAudioRenderChange(infos);
114 std::pair<int32_t, int32_t> focusSessionKey = std::make_pair(-1, -1);
115 std::pair<int32_t, int32_t> stopSessionKey = std::make_pair(-1, -1);
116 {
117 std::lock_guard lockGuard(stateLock_);
118 for (auto it = currentStates_.begin(); it != currentStates_.end();) {
119 if (it->second == runningState) {
120 if (IsFocusSession(it->first)) {
121 focusSessionKey = it->first;
122 it++;
123 continue;
124 }
125 } else {
126 if (CheckFocusSessionStop(it->first)) {
127 stopSessionKey = it->first;
128 }
129 }
130 if (it->second == releaseState) {
131 lastStates_.erase(it->first);
132 it = currentStates_.erase(it);
133 } else {
134 it++;
135 }
136 }
137 }
138 if (focusSessionKey.first != -1 && focusSessionKey.second != -1) {
139 UpdateFocusSession(focusSessionKey);
140 }
141 if (stopSessionKey.first != -1 && stopSessionKey.second != -1) {
142 DelayStopFocusSession(stopSessionKey);
143 }
144 }
145
IsFocusSession(const std::pair<int32_t,int32_t> key)146 bool FocusSessionStrategy::IsFocusSession(const std::pair<int32_t, int32_t> key)
147 {
148 bool isFocus = false;
149 auto it = lastStates_.find(key);
150 if (it == lastStates_.end()) {
151 isFocus = true;
152 } else {
153 isFocus = it->second != runningState;
154 }
155
156 lastStates_[key] = currentStates_[key];
157 if (isFocus) {
158 AVSessionEventHandler::GetInstance().AVSessionRemoveTask("CheckFocusStop" + std::to_string(key.second));
159 HISYSEVENT_BEHAVIOR("FOCUS_CHANGE", "FOCUS_SESSION_UID", key.second,
160 "AUDIO_INFO_RENDERER_STATE", AudioStandard::RendererState::RENDERER_RUNNING,
161 "DETAILED_MSG", "focussessionstrategy selectfocussession, current focus session info");
162 SLOGI("IsFocusSession uid=%{public}d isFocusTRUE", key.second);
163 }
164 return isFocus;
165 }
166
UpdateFocusSession(const std::pair<int32_t,int32_t> key)167 void FocusSessionStrategy::UpdateFocusSession(const std::pair<int32_t, int32_t> key)
168 {
169 FocusSessionChangeInfo sessionInfo;
170 sessionInfo.uid = key.first;
171 sessionInfo.pid = key.second;
172 if (selector_) {
173 selector_(sessionInfo);
174 }
175 if (callback_) {
176 callback_(sessionInfo, true);
177 }
178 }
179
CheckFocusSessionStop(const std::pair<int32_t,int32_t> key)180 bool FocusSessionStrategy::CheckFocusSessionStop(const std::pair<int32_t, int32_t> key)
181 {
182 bool isFocusStop = false;
183 auto it = lastStates_.find(key);
184 if (it == lastStates_.end()) {
185 isFocusStop = false;
186 } else {
187 isFocusStop = it->second == runningState;
188 }
189
190 lastStates_[key] = currentStates_[key];
191 if (isFocusStop) {
192 SLOGI("CheckFocusSessionStop uid=%{public}d pid=%{public}d isFocusStopTRUE", key.first, key.second);
193 }
194 return isFocusStop;
195 }
196
DelayStopFocusSession(const std::pair<int32_t,int32_t> key)197 void FocusSessionStrategy::DelayStopFocusSession(const std::pair<int32_t, int32_t> key)
198 {
199 AVSessionEventHandler::GetInstance().AVSessionPostTask(
200 [this, key]() {
201 {
202 std::lock_guard lockGuard(stateLock_);
203 auto it = lastStates_.find(key);
204 CHECK_AND_RETURN_LOG(!(it != lastStates_.end() &&
205 it->second == AudioStandard::RendererState::RENDERER_RUNNING),
206 "DelayStopFocus uid=%{public}d pid=%{public}d not found or not running", key.first, key.second);
207 SLOGE("DelayStopFocus uid=%{public}d lastState=%{public}d", it->first.first, it->second);
208 }
209 FocusSessionChangeInfo changeInfo;
210 changeInfo.uid = key.first;
211 changeInfo.pid = key.second;
212 if (callback_) {
213 callback_(changeInfo, false);
214 }
215 }, "CheckFocusStop" + std::to_string(key.second), cancelTimeout);
216 }
217 }
218