/* * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "focus_session_strategy.h" #include "avsession_log.h" #include "audio_adapter.h" #include "avsession_sysevent.h" #include "avsession_event_handler.h" namespace OHOS::AVSession { FocusSessionStrategy::FocusSessionStrategy() { SLOGI("construct"); } FocusSessionStrategy::~FocusSessionStrategy() { SLOGI("destroy"); AudioStandard::AudioStreamManager::GetInstance()->UnregisterAudioRendererEventListener(getpid()); CancelAllPendingTasks(); } void FocusSessionStrategy::CancelAllPendingTasks() { std::lock_guard lockGuard(taskNameLock_); for (const auto& taskName : pendingTaskNames_) { AVSessionEventHandler::GetInstance().AVSessionRemoveTask(taskName); } pendingTaskNames_.clear(); } void FocusSessionStrategy::Init() { AudioAdapter::GetInstance().AddStreamRendererStateListener([this](const auto& infos) { HandleAudioRenderStateChangeEvent(infos); }); } void FocusSessionStrategy::RegisterFocusSessionChangeCallback(const FocusSessionChangeCallback& callback) { callback_ = callback; } void FocusSessionStrategy::RegisterFocusSessionSelector(const FocusSessionSelector& selector) { selector_ = selector; } void FocusSessionStrategy::SetAudioPlayingUids(std::vector audioPlayingUids) { std::lock_guard lockGuard(audioPlayingLock_); audioPlayingUids_ = audioPlayingUids; } std::vector FocusSessionStrategy::GetAudioPlayingUids() { std::lock_guard lockGuard(audioPlayingLock_); return audioPlayingUids_; } void FocusSessionStrategy::AddControlBundle(int32_t uid, int32_t pid) { std::lock_guard lockGuard(audioPlayingLock_); controlBundleList_.insert(std::make_pair(uid, pid)); } void FocusSessionStrategy::RemoveControlBundle(int32_t uid, int32_t pid) { std::lock_guard lockGuard(audioPlayingLock_); std::pair controlKey = std::make_pair(uid, pid); if (controlBundleList_.find(controlKey) != controlBundleList_.end()) { controlBundleList_.erase(controlKey); } } void FocusSessionStrategy::ProcAudioRenderChange(const AudioRendererChangeInfos& infos) { SLOGD("AudioRenderStateChange start"); std::lock_guard lockGuard(audioPlayingLock_); audioPlayingUids_.clear(); std::pair playingKey = std::make_pair(-1, -1); for (const auto& info : infos) { SLOGD("AudioRenderStateChange uid=%{public}d pid=%{public}d audioSessionId=%{public}d state=%{public}d", info->clientUID, info->clientPid, info->sessionId, info->rendererState); if (std::find(audioPlayingUids_.begin(), audioPlayingUids_.end(), info->clientUID) == audioPlayingUids_.end() && (std::count(AUDIO_PLAYING_STREAM_USAGE.begin(), AUDIO_PLAYING_STREAM_USAGE.end(), info->rendererInfo.streamUsage) != 0) && (std::count(AUDIO_PLAYING_STREAM_STATE.begin(), AUDIO_PLAYING_STREAM_STATE.end(), info->rendererState) != 0)) { audioPlayingUids_.push_back(info->clientUID); } if (info->clientUID == ancoUid && (std::count(ALLOWED_ANCO_STREAM_USAGE.begin(), ALLOWED_ANCO_STREAM_USAGE.end(), info->rendererInfo.streamUsage) == 0)) { SLOGI("Anco invalid uid=%{public}d usage=%{public}d", info->clientUID, info->rendererInfo.streamUsage); continue; } if ((std::count(ALLOWED_MEDIA_STREAM_USAGE.begin(), ALLOWED_MEDIA_STREAM_USAGE.end(), info->rendererInfo.streamUsage) == 0) && (controlBundleList_.find(std::make_pair(info->clientUID, info->clientPid)) != controlBundleList_.end())) { SLOGI("Media invalid uid=%{public}d usage=%{public}d", info->clientUID, info->rendererInfo.streamUsage); continue; } bool isPidValid = info->clientPid != 0; CHECK_AND_CONTINUE(isPidValid); { std::lock_guard lockGuard(stateLock_); std::pair key = std::make_pair(info->clientUID, info->clientPid); auto it = currentStates_.find(key); if (it == currentStates_.end()) { currentStates_[key] = stopState; } if (info->rendererState == AudioStandard::RendererState::RENDERER_RUNNING) { currentStates_[key] = runningState; playingKey = key; } if (playingKey != key) { currentStates_[key] = info->rendererState == AudioStandard::RendererState::RENDERER_RELEASED ? releaseState : stopState; } } } SLOGD("AudioRenderStateChange end"); } void FocusSessionStrategy::HandleAudioRenderStateChangeEvent(const AudioRendererChangeInfos& infos) { ProcAudioRenderChange(infos); std::pair focusSessionKey = std::make_pair(-1, -1); std::pair stopSessionKey = std::make_pair(-1, -1); { std::lock_guard lockGuard(stateLock_); for (auto it = currentStates_.begin(); it != currentStates_.end();) { if (it->second == runningState) { if (IsFocusSession(it->first)) { focusSessionKey = it->first; it++; continue; } } else { if (CheckFocusSessionStop(it->first)) { stopSessionKey = it->first; } } if (it->second == releaseState) { lastStates_.erase(it->first); it = currentStates_.erase(it); } else { it++; } } } if (focusSessionKey.first != -1 && focusSessionKey.second != -1) { UpdateFocusSession(focusSessionKey); } if (stopSessionKey.first != -1 && stopSessionKey.second != -1) { DelayStopFocusSession(stopSessionKey); } } bool FocusSessionStrategy::IsFocusSession(const std::pair key) { bool isFocus = false; auto it = lastStates_.find(key); if (it == lastStates_.end()) { isFocus = true; } else { isFocus = it->second != runningState; } lastStates_[key] = currentStates_[key]; if (isFocus) { std::string taskName = "CheckFocusStop" + std::to_string(key.second); AVSessionEventHandler::GetInstance().AVSessionRemoveTask(taskName); { std::lock_guard lockGuard(taskNameLock_); pendingTaskNames_.erase(taskName); } HISYSEVENT_BEHAVIOR("FOCUS_CHANGE", "FOCUS_SESSION_UID", key.second, "AUDIO_INFO_RENDERER_STATE", AudioStandard::RendererState::RENDERER_RUNNING, "DETAILED_MSG", "focussessionstrategy selectfocussession, current focus session info"); SLOGI("IsFocusSession uid=%{public}d isFocusTRUE", key.second); } return isFocus; } void FocusSessionStrategy::UpdateFocusSession(const std::pair key) { FocusSessionChangeInfo sessionInfo; sessionInfo.uid = key.first; sessionInfo.pid = key.second; if (selector_) { selector_(sessionInfo); } if (callback_) { callback_(sessionInfo, true); } } bool FocusSessionStrategy::CheckFocusSessionStop(const std::pair key) { bool isFocusStop = false; auto it = lastStates_.find(key); if (it == lastStates_.end()) { isFocusStop = false; } else { isFocusStop = it->second == runningState; } lastStates_[key] = currentStates_[key]; if (isFocusStop) { SLOGI("CheckFocusSessionStop uid=%{public}d pid=%{public}d isFocusStopTRUE", key.first, key.second); } return isFocusStop; } void FocusSessionStrategy::DelayStopFocusSession(const std::pair key) { std::string taskName = "CheckFocusStop" + std::to_string(key.second); { std::lock_guard lockGuard(taskNameLock_); pendingTaskNames_.insert(taskName); } AVSessionEventHandler::GetInstance().AVSessionPostTask( [this, key]() { { std::lock_guard lockGuard(stateLock_); auto it = lastStates_.find(key); CHECK_AND_RETURN_LOG(!(it != lastStates_.end() && it->second == AudioStandard::RendererState::RENDERER_RUNNING), "DelayStopFocus uid=%{public}d pid=%{public}d not found or not running", key.first, key.second); CHECK_AND_PRINT_LOG(it == lastStates_.end(), "DelayStopFocus uid=%{public}d lastState=%{public}d", it->first.first, it->second); } FocusSessionChangeInfo changeInfo; changeInfo.uid = key.first; changeInfo.pid = key.second; if (callback_) { callback_(changeInfo, false); } }, taskName, cancelTimeout); } }