Files
openharmony_ci 470347d005 !3385 merge fix-session-element-spoof-lyc into master
修复AVSession伪造ElementName导致任意指向WantAgent的安全问题

Created-by: devil_red
Commit-by: 红袍小恶魔
Merged-by: openharmony_ci
Description: ## 问题

三方应用可通过 NDK 接口(OH_AVSession_Create,bundleName/abilityName 为直接字符串参数)或裸 IPC,向 AVSessionServiceStub::HandleCreateSessionInner 传入指向其他应用的 ElementName,入口及 IsParamInvalid 均无归属校验。SA 据此创建指向受害应用的 WantAgent(PendingWant),触发时以 SA 系统身份执行,形成身份冒用/跳转劫持。

详见 #2779

## 修复内容(按 TMG 评审意见:创建时纠正 elementName,划入兼容范畴,仅影响恶意应用)

**AVSessionService::CreateSessionInner** 新增 CorrectElementForThirdPartyCaller:

1. 系统应用/SA 调用方(thirdPartyApp=false)不处理
2. SA 进程内直调(如投播镜像会话)token 为 native,跳过——保护 cast 镜像等合法场景
3. 三方应用(hap)调用方:用调用方 uid 经 BMS 反查真实包名,与传入 elementName 比对;不一致则将 descriptor 的 bundleName 纠正为真实包名、abilityName 纠正为默认入口 ability(GetLaunchWantForBundle);反查失败保留原值(fail-open)
4. **BundleStatusAdapter** 新增 GetDefaultAbilityName,封装 BMS 默认入口 ability 解析

descriptor 在创建时即被纠正,下游展示/跳转/遥测归因全部基于真实身份,无需逐出口修补。

## UT

新增 CreateSessionInnerCorrectElement001/002:覆盖系统调用方不纠正、非 hap 调用方不纠正两条路径。

## 兼容性

- 合法应用 element 本就等于真实包名,纠正为 no-op,零行为变化
- anco/投播/系统组件场景不受影响
- 唯一行为变化:传入他人包名的异常/恶意调用,其会话归属被纠正为真实身份(TMG 评审已裁定划入兼容范畴)

Close #2779

See merge request: openharmony/multimedia_av_session!3385
2026-08-22 15:56:31 +08:00

5452 lines
242 KiB
C++

/*
* Copyright (c) 2022-2025 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 <sstream>
#include <iomanip>
#include <iostream>
#include <regex>
#include <dlfcn.h>
#include <thread>
#include <cerrno>
#include <chrono>
#include <climits>
#include <filesystem>
#include "avsession_service.h"
#include "notification_content.h"
#include "notification_helper.h"
#include "notification_request.h"
#include "notification_constant.h"
#include "parameter.h"
#include "parameters.h"
#include "pcm_cast_session.h"
#include "remote_session_capability_set.h"
#include "remote_session_source_proxy.h"
#include "remote_session_sink_proxy.h"
#include "hash_calculator.h"
#include "accesstoken_kit.h"
#include "permission_checker.h"
#include "system_ability_definition.h"
#include "params_config_operator.h"
#include "ability_connect_helper.h"
#include "extension_connect_helper.h"
#include "want_agent_helper.h"
#include "avsession_radar.h"
#include "avsession_storage_event.h"
#include "array_wrapper.h"
#include "bool_wrapper.h"
#include "int_wrapper.h"
#include "image_source.h"
#include "avsession_pixel_map_adapter.h"
#include "avsession_dynamic_insight.h"
#include "avsession_utils.h"
#include "audio_system_manager.h"
#include "stream_dfx_manager.h"
#include "audio_errors.h"
#ifdef CAR_FEATURE_ENABLE
#include "audio_zone_manager.h"
#endif
typedef void (*MigrateStubFunc)(std::function<void(std::string, std::string, std::string, std::string)>);
typedef void (*StopMigrateStubFunc)(void);
#if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM) and !defined(IOS_PLATFORM)
#include <malloc.h>
#endif
using namespace std;
using namespace OHOS::AudioStandard;
namespace OHOS::AVSession {
#ifdef CAR_FEATURE_ENABLE
AVSessionService* AVSessionService::instance_ = nullptr;
#endif
static const std::string AVSESSION_DYNAMIC_INSIGHT_LIBRARY_PATH = std::string("libavsession_dynamic_insight.z.so");
static const int32_t COLLABORATION_SA_ID = 70633;
static const int32_t ANCO_BROKER_SA_ID = 66849;
static const int32_t AVSESSION_CONTINUE = 1;
#ifdef CASTPLUS_CAST_ENGINE_ENABLE
static const int32_t AFTER_SCREEN_ON_TREE = 2;
#endif
#ifndef START_STOP_ON_DEMAND_ENABLE
const std::string BOOTEVENT_AVSESSION_SERVICE_READY = "bootevent.avsessionservice.ready";
#endif
#ifdef ENABLE_AVSESSION_SYSEVENT_CONTROL
static const int32_t CONTROL_COLD_START = 2;
#endif
static const int32_t DEFAULT_IMAGE_SIZE = 256;
static const std::string DEFAULT_FOLD_SCREEN_TYPE = "0,0,0,0";
static const int32_t OUTER_SCREEN_TYPE_VALUE = 3;
const std::string PAD_DEVICE_TYPE = "tablet";
const std::string PC_DEVICE_TYPE = "2in1";
const std::string PHONE_DEVICE_TYPE = "phone";
static const std::set<std::string> DESKTOP_LYRICS_SUPPORTED_DEVICES = {
PHONE_DEVICE_TYPE,
PC_DEVICE_TYPE,
PAD_DEVICE_TYPE,
};
enum DESKTOP_LYRICS_ABILITY_STATE {
DESKTOP_LYRICS_ABILITY_DEFAULT = 0,
DESKTOP_LYRICS_ABILITY_CONNECTING = 1,
DESKTOP_LYRICS_ABILITY_CONNECTED = 2,
DESKTOP_LYRICS_ABILITY_DISCONNECTING = 3,
DESKTOP_LYRICS_ABILITY_DISCONNECTED = 4,
};
const std::map<int, int32_t> keyCodeToCommandMap_ = {
{MMI::KeyEvent::KEYCODE_MEDIA_PLAY_PAUSE, AVControlCommand::SESSION_CMD_PLAY},
{MMI::KeyEvent::KEYCODE_MEDIA_PLAY, AVControlCommand::SESSION_CMD_PLAY},
{MMI::KeyEvent::KEYCODE_MEDIA_PAUSE, AVControlCommand::SESSION_CMD_PAUSE},
{MMI::KeyEvent::KEYCODE_MEDIA_STOP, AVControlCommand::SESSION_CMD_STOP},
{MMI::KeyEvent::KEYCODE_MEDIA_NEXT, AVControlCommand::SESSION_CMD_PLAY_NEXT},
{MMI::KeyEvent::KEYCODE_MEDIA_PREVIOUS, AVControlCommand::SESSION_CMD_PLAY_PREVIOUS},
{MMI::KeyEvent::KEYCODE_MEDIA_REWIND, AVControlCommand::SESSION_CMD_REWIND},
{MMI::KeyEvent::KEYCODE_MEDIA_FAST_FORWARD, AVControlCommand::SESSION_CMD_FAST_FORWARD},
};
const std::map<int32_t, int32_t> cmdToOffsetMap_ = {
{AVControlCommand::SESSION_CMD_SET_TARGET_LOOP_MODE, 9},
{AVControlCommand::SESSION_CMD_PLAY, 8},
{AVControlCommand::SESSION_CMD_PAUSE, 7},
{AVControlCommand::SESSION_CMD_PLAY_NEXT, 6},
{AVControlCommand::SESSION_CMD_PLAY_PREVIOUS, 5},
{AVControlCommand::SESSION_CMD_FAST_FORWARD, 4},
{AVControlCommand::SESSION_CMD_REWIND, 3},
{AVControlCommand::SESSION_CMD_SEEK, 2},
{AVControlCommand::SESSION_CMD_SET_LOOP_MODE, 1},
{AVControlCommand::SESSION_CMD_TOGGLE_FAVORITE, 0}
};
class NotificationSubscriber : public Notification::NotificationLocalLiveViewSubscriber {
void OnConnected() {}
void OnDisconnected() {}
void OnResponse(int32_t notificationId, sptr<Notification::NotificationButtonOption> buttonOption) {}
void OnDied() {}
};
static const auto NOTIFICATION_SUBSCRIBER = NotificationSubscriber();
#ifndef START_STOP_ON_DEMAND_ENABLE
REGISTER_SYSTEM_ABILITY_BY_ID(AVSessionService, AVSESSION_SERVICE_ID, true);
#else
REGISTER_SYSTEM_ABILITY_BY_ID(AVSessionService, AVSESSION_SERVICE_ID, false);
#endif
bool g_isCapsuleLive2 = system::GetBoolParameter("persist.systemui.live2", false);
std::shared_ptr<Media::PixelMap> g_defaultMediaImage = nullptr;
Notification::NotificationRequest g_NotifyRequest;
AVSessionService::AVSessionService(int32_t systemAbilityId, bool runOnCreate)
: SystemAbility(systemAbilityId, runOnCreate)
{
#ifdef CAR_FEATURE_ENABLE
instance_ = this;
#endif
}
AVSessionService::~AVSessionService()
{
GetUsersManager().ClearCache();
}
void AVSessionService::OnStart()
{
SLOGI("OnStart SA with process check");
GetUsersManager().ClearCache();
CHECK_AND_RETURN_LOG(Publish(this), "publish avsession service failed");
OnStartProcess();
UpdateControlListFromFile();
}
void AVSessionService::OnStartProcess()
{
dumpHelper_ = std::make_unique<AVSessionDumper>();
CommandSendLimit::GetInstance().StartTimer();
ParamsConfigOperator::GetInstance().InitConfig();
auto ret = ParamsConfigOperator::GetInstance().GetValueIntByKey("historicalRecordMaxNum", &maxHistoryNums_);
if (ret == AVSESSION_ERROR) {
maxHistoryNums_ = defMaxHistoryNum;
}
#ifdef ENABLE_BACKGROUND_AUDIO_CONTROL
backgroundAudioController_.Init(this);
AddInnerSessionListener(&backgroundAudioController_);
{
std::lock_guard lockGuard(sessionServiceLock_);
for (auto& session : GetContainer().GetAllSessions()) {
CHECK_AND_CONTINUE(session != nullptr);
SLOGI("backgroundAudioController add sessionCreateBef:%{public}s",
AVSessionUtils::GetAnonySessionId(session->GetSessionId()).c_str());
backgroundAudioController_.OnSessionCreate(session->GetDescriptor());
}
}
#endif
AddSystemAbilityListener(MULTIMODAL_INPUT_SERVICE_ID);
AddSystemAbilityListener(AUDIO_POLICY_SERVICE_ID);
AddSystemAbilityListener(APP_MGR_SERVICE_ID);
AddSystemAbilityListener(DISTRIBUTED_HARDWARE_DEVICEMANAGER_SA_ID);
AddSystemAbilityListener(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
AddSystemAbilityListener(COLLABORATION_SA_ID);
AddSystemAbilityListener(MEMORY_MANAGER_SA_ID);
AddSystemAbilityListener(SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN);
AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID);
AddSystemAbilityListener(ANCO_BROKER_SA_ID);
HISYSEVENT_REGITER;
STORAGE_EVENT_INIT;
HISYSEVENT_BEHAVIOR("SESSION_SERVICE_START", "SERVICE_NAME", "AVSessionService",
"SERVICE_ID", AVSESSION_SERVICE_ID, "DETAILED_MSG", "avsession service start success");
#ifndef START_STOP_ON_DEMAND_ENABLE
if (!system::GetBoolParameter(BOOTEVENT_AVSESSION_SERVICE_READY.c_str(), false)) {
system::SetParameter(BOOTEVENT_AVSESSION_SERVICE_READY.c_str(), "true");
SLOGI("set boot avsession service started true");
}
#endif
AVSessionUtils::PublishCommonEvent("usual.event.AVSESSION_START");
}
void AVSessionService::OnDump()
{
}
int32_t AVSessionService::OnIdle(const SystemAbilityOnDemandReason& idleReason)
{
SLOGI("OnIdle SA, idle reason %{public}d, %{public}s, %{public}s.",
idleReason.GetId(), idleReason.GetName().c_str(), idleReason.GetValue().c_str());
uint32_t ret = GetUsersManager().GetContainerFromAll().GetAllSessions().size();
if (ret != 0) {
SLOGI("IPC is not used for a long time, there are %{public}d sessions.", ret);
return -1;
}
std::lock_guard lockGuard(migrateProxyMapLock_);
for (const auto& pair : migrateAVSessionProxyMap_) {
std::shared_ptr<MigrateAVSessionProxy> migrateAVSessionProxy =
std::static_pointer_cast<MigrateAVSessionProxy>(pair.second);
CHECK_AND_CONTINUE(migrateAVSessionProxy != nullptr);
CHECK_AND_RETURN_RET_LOG(!migrateAVSessionProxy->CheckMediaAlive(), -1,
"migrate proxy with media alive, should not stop");
}
return 0;
}
void AVSessionService::OnActive(const SystemAbilityOnDemandReason& activeReason)
{
SLOGI("OnActive SA, idle reason %{public}d, %{public}s, %{public}s",
activeReason.GetId(), activeReason.GetName().c_str(), activeReason.GetValue().c_str());
}
void AVSessionService::OnStop()
{
PublishEvent(remoteMediaNone);
if (migrateStubFuncHandle_ != nullptr) {
StopMigrateStubFunc stopMigrateStub =
reinterpret_cast<StopMigrateStubFunc>(dlsym(migrateStubFuncHandle_, "StopMigrateStub"));
if (stopMigrateStub == nullptr) {
SLOGE("failed to find library, reason: %{public}sn", dlerror());
} else {
stopMigrateStub();
}
#ifndef TEST_COVERAGE
dlclose(migrateStubFuncHandle_);
#endif
}
#ifdef CASTPLUS_CAST_ENGINE_ENABLE
CollaborationManagerURLCasting::GetInstance().UnRegisterLifecycleCallback();
CollaborationManagerURLCasting::ReleaseInstance();
CollaborationManagerHiPlay::GetInstance().UnRegisterLifecycleCallback();
CollaborationManagerHiPlay::ReleaseInstance();
#endif
CommandSendLimit::GetInstance().StopTimer();
STORAGE_EVENT_UNINIT;
HISYSEVENT_UNREGISTER;
NotifyProcessStatus(false);
UnSubscribeCommonEvent();
BundleStatusAdapter::ReleaseInstance();
}
EventSubscriber::EventSubscriber(const EventFwk::CommonEventSubscribeInfo &subscriberInfo, AVSessionService *ptr)
: EventFwk::CommonEventSubscriber(subscriberInfo)
{
servicePtr_ = ptr;
}
void EventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &eventData)
{
const AAFwk::Want &want = eventData.GetWant();
std::string action = want.GetAction();
SLOGI("OnReceiveEvent action:%{public}s.", action.c_str());
if (servicePtr_ == nullptr) {
SLOGE("OnReceiveEvent get action:%{public}s with servicePtr_ null", action.c_str());
return;
}
if (action.compare(EventFwk::CommonEventSupport::COMMON_EVENT_USER_FOREGROUND) == 0) {
int32_t userIdForeground = eventData.GetCode();
servicePtr_->HandleUserEvent(AVSessionUsersManager::accountEventSwitched, userIdForeground);
} else if (action.compare(EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED) == 0) {
int32_t userIdSwitched = eventData.GetCode();
servicePtr_->HandleUserEvent(AVSessionUsersManager::accountEventSwitched, userIdSwitched);
} else if (action.compare(EventFwk::CommonEventSupport::COMMON_EVENT_USER_REMOVED) == 0) {
int32_t userId = eventData.GetCode();
servicePtr_->HandleUserEvent(AVSessionUsersManager::accountEventRemoved, userId);
} else if (action.compare(EventFwk::CommonEventSupport::COMMON_EVENT_USER_UNLOCKED) == 0) {
int32_t userId = eventData.GetCode();
servicePtr_->RegisterBundleDeleteEventForHistory(userId);
} else if (action.compare(EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED) == 0) {
int32_t userId = servicePtr_->GetUsersManager().GetCurrentUserId();
servicePtr_->HandleFirstUnlockCleanup(userId);
} else if (action.compare(EventFwk::CommonEventSupport::COMMON_EVENT_BOOT_COMPLETED) == 0 ||
action.compare(EventFwk::CommonEventSupport::COMMON_EVENT_LOCKED_BOOT_COMPLETED) == 0) {
servicePtr_->InitCastEngineService();
} else if (action.compare("EVENT_REMOVE_MEDIACONTROLLER_LIVEVIEW") == 0) {
int32_t uid = want.GetIntParam("uid", 0);
bool isPhoto = want.GetBoolParam("isPhoto", false);
servicePtr_->HandleRemoveMediaCardEvent(uid, isPhoto);
} else if (action.compare("EVENT_AVSESSION_MEDIA_CAPSULE_STATE_CHANGE") == 0) {
std::string param = eventData.GetData();
SLOGI("OnReceiveEvent notify data:%{public}s", param.c_str());
servicePtr_->HandleMediaCardStateChangeEvent(param);
} else if (action.compare(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED) == 0) {
std::string bundleName = want.GetElement().GetBundleName();
SLOGI("package remove %{public}s", bundleName.c_str());
servicePtr_->HandleBundleRemoveEvent(bundleName);
} else if (action.compare("usual.event.CAST_SESSION_CREATE") == 0) {
#ifdef CASTPLUS_CAST_ENGINE_ENABLE
AVRouter::GetInstance().SetSinkCastSessionInfo(want);
if (AVRouter::GetInstance().GetCastSide() == CAST_SIDE::CAST_SOURCE &&
AVRouter::GetInstance().GetMirrorCastHandle() == -1) {
servicePtr_->StopSourceCast();
} else {
servicePtr_->checkEnableCast(true);
AVRouter::GetInstance().NotifyCastSessionCreated();
}
#endif
} else if (action.compare("usual.event.MEDIA_NTF_SWITCH") == 0) {
bool isMediaNtfEnable = want.GetBoolParam("isMediaNtfEnable", true);
servicePtr_->UpdateNtfEnable(isMediaNtfEnable);
} else if (action.compare("HYBRID_MODE_SWITCH") == 0) {
int32_t targetMode = want.GetIntParam("targetMode", 0);
int32_t hotSwitchStage = want.GetIntParam("stage", 0);
// pcMode=1, phoneMode=0, hotSwitchStage=2, dms init done
SLOGI("on receiveEvent HYBRID_MODE_SWITCH %{public}d, hotSwitchStage %{public}d", targetMode, hotSwitchStage);
servicePtr_->SetPcMode(targetMode == 1);
#ifdef CASTPLUS_CAST_ENGINE_ENABLE
if (targetMode == 0 && hotSwitchStage == AFTER_SCREEN_ON_TREE) {
servicePtr_->HotSwitchReportCastDisplay();
}
#endif
}
}
std::string AVSessionService::GetAVQueueDir(int32_t userId)
{
return GetUsersManager().GetDirForCurrentUser(userId) + AVQUEUE_FILE_NAME;
}
std::string AVSessionService::GetAVSortDir(int32_t userId)
{
return GetUsersManager().GetDirForCurrentUser(userId) + SORT_FILE_NAME;
}
void AVSessionService::HandleUserEvent(const std::string &type, const int &userId)
{
// del capsule before account switching
int32_t curUserId = GetUsersManager().GetCurrentUserId();
if (type == AVSessionUsersManager::accountEventSwitched && userId != curUserId && hasMediaCapsule_.load()) {
SLOGI("userSwitch userId:%{public}d curUserId:%{public}d hasCapsule:%{public}d",
userId, curUserId, hasMediaCapsule_.load());
std::lock_guard lockGuard(sessionServiceLock_);
NotifySystemUI(nullptr, false, false);
}
GetUsersManager().NotifyAccountsEvent(type, userId);
if (type == AVSessionUsersManager::accountEventSwitched) {
SLOGI("userSwitch and updateTopSession for userId:%{public}d", userId);
UpdateTopSession(GetUsersManager().GetTopSession(), userId);
}
}
void AVSessionService::HandleRemoveMediaCardEvent(int32_t uid, bool isPhoto)
{
std::lock_guard lockGuard(sessionServiceLock_);
if (isPhoto) {
for (auto& session : GetContainer().GetAllSessions()) {
if (session != nullptr && session->GetUid() == uid) {
AVCastControlCommand castCmd;
castCmd.SetCommand(AVCastControlCommand::CAST_CONTROL_CMD_PAUSE);
session->SendControlCommandToCast(castCmd);
}
}
} else {
hasRemoveEvent_ = true;
hasMediaCapsule_.store(false);
if (!topSession_) {
return;
}
auto ret = BackgroundTaskMgr::BackgroundTaskMgrHelper::AVSessionNotifyUpdateNotification(
topSession_->GetUid(), topSession_->GetPid(), false);
if (ret != AVSESSION_SUCCESS) {
SLOGE("AVSessionNotifyUpdateNotification failed, uid = %{public}d, pid = %{public}d, ret = %{public}d",
topSession_->GetUid(), topSession_->GetPid(), ret);
}
AVSessionEventHandler::GetInstance().AVSessionRemoveTask("NotifyFlowControl");
if (topSession_->IsCastConnected()) {
AVCastControlCommand castCmd;
castCmd.SetCommand(AVCastControlCommand::CAST_CONTROL_CMD_PAUSE);
topSession_->SendControlCommandToCast(castCmd);
} else {
AVControlCommand cmd;
cmd.SetCommand(AVControlCommand::SESSION_CMD_PAUSE);
topSession_->ExecuteControllerCommand(cmd);
}
}
}
bool AVSessionService::IsLocalSessionPlaying(const sptr<AVSessionItem>& session)
{
CHECK_AND_RETURN_RET_LOG(session != nullptr, false, "IsLocalSessionPlaying session is null");
return AudioAdapter::GetInstance().GetRendererRunning(session->GetUid(), session->GetPid()) ||
(session->GetUid() == audioBrokerUid &&
session->GetPlaybackState().GetState() == AVPlaybackState::PLAYBACK_STATE_PLAY);
}
bool AVSessionService::IsTopSessionPlaying()
{
std::lock_guard lockGuard(sessionServiceLock_);
if (!topSession_) {
return false;
}
bool isPlaying = topSession_->IsCasting() ?
(topSession_->GetCastAVPlaybackState().GetState() == AVPlaybackState::PLAYBACK_STATE_PLAY) :
IsLocalSessionPlaying(topSession_);
return isPlaying;
}
void AVSessionService::HandleMediaCardStateChangeEvent(std::string isAppear)
{
if (isAppear == "APPEAR") {
isMediaCardOpen_ = true;
AVSessionEventHandler::GetInstance().AVSessionRemoveTask("CheckCardStateChangeStop");
hasCardStateChangeStopTask_ = false;
} else if (isAppear == "DISAPPEAR") {
isMediaCardOpen_ = false;
if (IsTopSessionPlaying() || hasRemoveEvent_.load()) {
SLOGI("HandleMediaCardState hasRemoveEvent_:%{public}d ", hasRemoveEvent_.load());
return;
}
hasCardStateChangeStopTask_ = true;
AVSessionEventHandler::GetInstance().AVSessionPostTask(
[this]() {
if (IsTopSessionPlaying() || hasRemoveEvent_.load() || isMediaCardOpen_.load()) {
SLOGI("HandleMediaCardState hasRemoveEvent_:%{public}d isMediaCardOpen_:%{public}d",
hasRemoveEvent_.load(), isMediaCardOpen_.load());
return;
}
{
std::lock_guard lockGuard(sessionServiceLock_);
NotifySystemUI(nullptr, false, false);
hasCardStateChangeStopTask_ = false;
}
}, "CheckCardStateChangeStop", cancelTimeout);
}
}
void AVSessionService::HandleBundleRemoveEvent(const std::string bundleName)
{
int32_t curUserId = GetUsersManager().GetCurrentUserId();
DeleteHistoricalRecord(bundleName, curUserId);
}
void AVSessionService::HandleFirstUnlockCleanup(int32_t userId)
{
if (userId <= 0) {
userId = GetUsersManager().GetCurrentUserId();
}
int32_t bootCount = OHOS::system::GetIntParameter("persist.startup.bootcount", -1);
auto it = cleanedBootCountByUser_.find(userId);
bool cleanedThisBoot = (bootCount >= 0) && (it != cleanedBootCountByUser_.end()) && (it->second == bootCount);
CHECK_AND_RETURN_LOG(!cleanedThisBoot,
"already cleaned this boot for user %{public}d, bootcount=%{public}d", userId, bootCount);
std::string fileDir = GetUsersManager().GetDirForCurrentUser(userId);
std::string fileName = "unlock_clean_flag";
std::pair<std::string, int32_t> readPair;
int32_t recordedBootCount =
AVSessionUtils::ReadPairFromFile(readPair, fileDir, fileName) ? readPair.second : -1;
if (bootCount >= 0 && recordedBootCount == bootCount) {
cleanedBootCountByUser_[userId] = bootCount;
return;
}
SLOGI("HandleFirstUnlockCleanup clean cache for user %{public}d, bootcount=%{public}d", userId, bootCount);
GetUsersManager().CleanupCacheOnUnlock(userId);
if (bootCount >= 0) {
std::pair<std::string, int32_t> writePair{"boot", bootCount};
AVSessionUtils::WritePairToFile(writePair, fileDir, fileName);
cleanedBootCountByUser_[userId] = bootCount;
}
}
bool AVSessionService::SubscribeCommonEvent()
{
const std::vector<std::string> systemEvents = {
EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF,
EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_ON,
EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_LOCKED,
EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED,
EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED,
EventFwk::CommonEventSupport::COMMON_EVENT_USER_FOREGROUND,
EventFwk::CommonEventSupport::COMMON_EVENT_USER_REMOVED,
EventFwk::CommonEventSupport::COMMON_EVENT_USER_UNLOCKED,
EventFwk::CommonEventSupport::COMMON_EVENT_BOOT_COMPLETED,
EventFwk::CommonEventSupport::COMMON_EVENT_LOCKED_BOOT_COMPLETED,
EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED,
};
EventFwk::MatchingSkills systemSkills;
for (auto &event : systemEvents) {
systemSkills.AddEvent(event);
}
EventFwk::CommonEventSubscribeInfo systemSubscribeInfo(systemSkills);
CHECK_AND_RETURN_RET_LOG(systemSubscriber_ == nullptr, true, "already have systemSubscriber");
systemSubscriber_ = std::make_shared<EventSubscriber>(systemSubscribeInfo, this);
bool ret = EventFwk::CommonEventManager::SubscribeCommonEvent(systemSubscriber_);
CHECK_AND_CALL_FUNC_RETURN_RET_LOG(ret, false, UnSubscribeCommonEvent(),
"SubscribeCommonEvent system events failed!");
CHECK_AND_RETURN_RET_LOG(customSubscribers_.empty(), true, "already have customSubscribers");
const std::map<std::string, std::string> customizedEventPermissionMap = {
{ "usual.event.CAST_SESSION_CREATE", "ohos.permission.MANAGE_MEDIA_RESOURCES" },
{ "EVENT_REMOVE_MEDIACONTROLLER_LIVEVIEW", "ohos.permission.MANAGE_MEDIA_RESOURCES" },
{ "EVENT_AVSESSION_MEDIA_CAPSULE_STATE_CHANGE", "ohos.permission.MANAGE_MEDIA_RESOURCES" },
{ "usual.event.MEDIA_NTF_SWITCH", "ohos.permission.MANAGE_MEDIA_RESOURCES" },
{ "HYBRID_MODE_SWITCH", "ohos.permission.MANAGE_MEDIA_RESOURCES" },
};
for (const auto &[event, permission] : customizedEventPermissionMap) {
EventFwk::MatchingSkills customSkills;
customSkills.AddEvent(event);
EventFwk::CommonEventSubscribeInfo customSubscribeInfo(customSkills);
customSubscribeInfo.SetPermission(permission);
auto customSubscriber = std::make_shared<EventSubscriber>(customSubscribeInfo, this);
ret = EventFwk::CommonEventManager::SubscribeCommonEvent(customSubscriber);
CHECK_AND_CALL_FUNC_RETURN_RET_LOG(ret, false, UnSubscribeCommonEvent(),
"SubscribeCommonEvent custom event %{public}s failed!", event.c_str());
customSubscribers_.push_back(customSubscriber);
}
return ret;
}
bool AVSessionService::UnSubscribeCommonEvent()
{
bool subscribeResult = false;
if (systemSubscriber_ != nullptr) {
subscribeResult = EventFwk::CommonEventManager::UnSubscribeCommonEvent(systemSubscriber_);
systemSubscriber_ = nullptr;
}
SLOGI("UnSubscribeCommonEvent subscribeResult = %{public}d", subscribeResult);
for (const auto &customSubscriber : customSubscribers_) {
subscribeResult = EventFwk::CommonEventManager::UnSubscribeCommonEvent(customSubscriber);
SLOGI("UnSubscribeCustomEvent subscribeResult = %{public}d", subscribeResult);
}
customSubscribers_.clear();
return subscribeResult;
}
void AVSessionService::PullMigrateStub()
{
migrateStubFuncHandle_ = dlopen("libavsession_migration.z.so", RTLD_NOW);
if (migrateStubFuncHandle_ == nullptr) {
SLOGE("failed to dlopen library, reason: %{public}sn", dlerror());
return;
}
MigrateStubFunc startMigrateStub =
reinterpret_cast<MigrateStubFunc>(dlsym(migrateStubFuncHandle_, "StartMigrateStub"));
if (startMigrateStub == nullptr) {
SLOGE("failed to find library, reason: %{public}sn", dlerror());
return;
}
std::thread([startMigrateStub, this]() {
SLOGI("create thread to keep MigrateStub");
startMigrateStub([this](std::string deviceId, std::string serviceName, std::string extraInfo,
std::string state) { SuperLauncher(deviceId, serviceName, extraInfo, state); });
}).detach();
}
void AVSessionService::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
{
SLOGI("Receive SA: %{public}d start callback.", systemAbilityId);
switch (systemAbilityId) {
case MULTIMODAL_INPUT_SERVICE_ID:
InitKeyEvent();
break;
case AUDIO_POLICY_SERVICE_ID:
InitAudio();
break;
case APP_MGR_SERVICE_ID:
InitAMS();
break;
#ifdef DEVICE_MANAGER_ENABLE
case DISTRIBUTED_HARDWARE_DEVICEMANAGER_SA_ID:
InitDM();
break;
#endif
case BUNDLE_MGR_SERVICE_SYS_ABILITY_ID:
InitBMS();
InitRadarBMS();
break;
case COLLABORATION_SA_ID:
InitCollaboration();
PullMigrateStub();
break;
case MEMORY_MANAGER_SA_ID:
NotifyProcessStatus(true);
SetCritical(true);
break;
case SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN:
InitAccountMgr();
break;
case COMMON_EVENT_SERVICE_ID:
InitCommonEventService();
break;
case ANCO_BROKER_SA_ID: {
std::lock_guard lockGuard(audioBrokerLock_);
isAudioBrokerStart_ = true;
SLOGI("audio broker sa start %{public}d", isAudioBrokerStart_);
break;
}
default:
SLOGE("undefined system ability %{public}d", systemAbilityId);
}
}
void AVSessionService::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
{
SLOGI("remove system ability %{public}d", systemAbilityId);
if (systemAbilityId == ANCO_BROKER_SA_ID) {
std::lock_guard lockGuard(audioBrokerLock_);
isAudioBrokerStart_ = false;
SLOGI("audio broker sa close %{public}d", isAudioBrokerStart_);
ancoMediaSessionListener_ = nullptr;
}
}
void AVSessionService::NotifyProcessStatus(bool isStart)
{
int pid = getpid();
void *libMemMgrClientHandle = dlopen("libmemmgrclient.z.so", RTLD_NOW);
if (!libMemMgrClientHandle) {
SLOGE("dlopen libmemmgrclient library failed");
return;
}
void *notifyProcessStatusFunc = dlsym(libMemMgrClientHandle, "notify_process_status");
if (!notifyProcessStatusFunc) {
SLOGE("dlsm notify_process_status failed");
#ifndef TEST_COVERAGE
dlclose(libMemMgrClientHandle);
#endif
return;
}
auto notifyProcessStatus = reinterpret_cast<int(*)(int, int, int, int)>(notifyProcessStatusFunc);
int ret = -1;
if (isStart) {
SLOGI("notify to memmgr when av_session is started");
ret = notifyProcessStatus(pid, saType, 1, AVSESSION_SERVICE_ID); // 1 indicates the service is started
} else {
SLOGI("notify to memmgr when av_session is stopped");
ret = notifyProcessStatus(pid, saType, 0, AVSESSION_SERVICE_ID); // 0 indicates the service is stopped
}
if (ret != 0) {
SLOGE("notifyProcessStatus failed");
}
#ifndef TEST_COVERAGE
dlclose(libMemMgrClientHandle);
#endif
}
void AVSessionService::SetCritical(bool isCritical)
{
int pid = getpid();
void *libMemMgrClientHandle = dlopen("libmemmgrclient.z.so", RTLD_NOW);
if (!libMemMgrClientHandle) {
SLOGE("dlopen libmemmgrclient library failed");
return;
}
void *setCriticalFunc = dlsym(libMemMgrClientHandle, "set_critical");
if (!setCriticalFunc) {
SLOGE("dlsm set_critical failed");
#ifndef TEST_COVERAGE
dlclose(libMemMgrClientHandle);
#endif
return;
}
auto setCritical = reinterpret_cast<int(*)(int, bool, int)>(setCriticalFunc);
SLOGI("notify to memmgr as av_session isCritical:%{public}d", isCritical);
// 1 indicates the service is started
if (setCritical(pid, isCritical, AVSESSION_SERVICE_ID) != 0) {
SLOGE("setCritical failed");
}
#ifndef TEST_COVERAGE
dlclose(libMemMgrClientHandle);
#endif
}
void AVSessionService::InitKeyEvent()
{
SLOGI("enter init keyEvent");
std::vector<int32_t> keyCodes = {
MMI::KeyEvent::KEYCODE_MEDIA_PLAY,
MMI::KeyEvent::KEYCODE_MEDIA_PAUSE,
MMI::KeyEvent::KEYCODE_MEDIA_PLAY_PAUSE,
MMI::KeyEvent::KEYCODE_MEDIA_STOP,
MMI::KeyEvent::KEYCODE_MEDIA_NEXT,
MMI::KeyEvent::KEYCODE_MEDIA_PREVIOUS,
MMI::KeyEvent::KEYCODE_MEDIA_REWIND,
MMI::KeyEvent::KEYCODE_MEDIA_FAST_FORWARD,
MMI::KeyEvent::KEYCODE_HEADSETHOOK,
};
KeyEventAdapter::GetInstance().SubscribeKeyEvent(
keyCodes, [this](const auto& keyEvent) { SendSystemAVKeyEvent(*keyEvent); });
}
void ReportFocusSessionChange(const sptr<AVSessionItem>& topSession, const sptr<AVSessionItem>& newTopSession)
{
HISYSEVENT_BEHAVIOR("FOCUS_CHANGE",
"OLD_BUNDLE_NAME", topSession->GetDescriptor().elementName_.GetBundleName(),
"OLD_MODULE_NAME", topSession->GetDescriptor().elementName_.GetModuleName(),
"OLD_ABILITY_NAME", topSession->GetAbilityName(), "OLD_SESSION_PID", topSession->GetPid(),
"OLD_SESSION_UID", topSession->GetUid(), "OLD_SESSION_ID", topSession->GetSessionId(),
"OLD_SESSION_TAG", topSession->GetDescriptor().sessionTag_,
"OLD_SESSION_TYPE", topSession->GetDescriptor().sessionType_,
"BUNDLE_NAME", newTopSession->GetDescriptor().elementName_.GetBundleName(),
"MODULE_NAME", newTopSession->GetDescriptor().elementName_.GetModuleName(),
"ABILITY_NAME", newTopSession->GetAbilityName(), "SESSION_PID", newTopSession->GetPid(),
"SESSION_UID", newTopSession->GetUid(), "SESSION_ID", newTopSession->GetSessionId(),
"SESSION_TAG", newTopSession->GetDescriptor().sessionTag_,
"SESSION_TYPE", newTopSession->GetDescriptor().sessionType_,
"DETAILED_MSG", "avsessionservice handlefocussession, updatetopsession");
}
void AVSessionService::UpdateSessionTimestamp(sptr<AVSessionItem> sessionItem)
{
CHECK_AND_RETURN_LOG(sessionItem != nullptr, "UpdateSessionTimestamp sessionItem is null");
auto now = std::chrono::system_clock::now();
auto timeSinceEpoch = now.time_since_epoch();
auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(timeSinceEpoch).count();
sessionItem->SetPlayingTime(milliseconds);
SLOGI("UpdateSessionTimestamp for %{public}s", sessionItem->GetBundleName().c_str());
}
void AVSessionService::UpdateTopSession(const sptr<AVSessionItem>& newTopSession, int32_t userId)
{
AVSessionDescriptor descriptor;
sptr<AVSessionItem> topSession = nullptr;
int32_t userIdForNewTopSession = newTopSession != nullptr ? newTopSession->GetUserId() :
(userId <= 0 ? GetUsersManager().GetCurrentUserId() : userId);
{
std::lock_guard lockGuard(sessionServiceLock_);
if (newTopSession == nullptr) {
if (topSession_ != nullptr && GetUsersManager().GetCurrentUserId() == userIdForNewTopSession) {
topSession_->SetTop(false);
topSession_ = nullptr;
}
GetUsersManager().SetTopSession(nullptr, userIdForNewTopSession);
SLOGI("set topSession to nullptr for userId:%{public}d", userIdForNewTopSession);
HISYSEVENT_BEHAVIOR("FOCUS_CHANGE", "DETAILED_MSG", "avsessionservice set topsession to nullptr");
return;
}
SLOGI("updateNewTop uid=%{public}d|pid=%{public}d|userId:%{public}d|sessionId=%{public}s",
newTopSession->GetUid(), newTopSession->GetPid(), userIdForNewTopSession,
AVSessionUtils::GetAnonySessionId(newTopSession->GetSessionId()).c_str());
if (userIdForNewTopSession == GetUsersManager().GetCurrentUserId()) {
if (topSession_ != nullptr) {
topSession_->SetTop(false);
ReportFocusSessionChange(topSession_, newTopSession);
}
topSession_ = newTopSession;
// update topsession playingtime
UpdateSessionTimestamp(topSession_);
#ifdef CASTPLUS_CAST_ENGINE_ENABLE
MirrorToStreamCast(topSession_);
#endif // CASTPLUS_CAST_ENGINE_ENABLE
}
GetUsersManager().SetTopSession(newTopSession, userIdForNewTopSession);
newTopSession->SetTop(true);
descriptor = newTopSession->GetDescriptor();
topSession = topSession_;
}
NotifyTopSessionChanged(descriptor);
#ifdef CAR_FEATURE_ENABLE
NotifyTopSessionChangeForAudioZone(descriptor);
#endif
if (topSession != nullptr && !topSession->IsCasting()) {
std::string preloadSessionId = topSession->GetSessionId();
NotifyLocalFrontSessionChangeForMigrate(preloadSessionId);
}
}
void AVSessionService::HandleChangeTopSession(int32_t infoUid, int32_t infoPid, int32_t userId)
{
std::lock_guard frontLockGuard(sessionFrontLock_);
std::shared_ptr<std::list<sptr<AVSessionItem>>> sessionListForFront = GetCurSessionListForFront(userId);
CHECK_AND_RETURN_LOG(sessionListForFront != nullptr, "sessionListForFront ptr nullptr!");
for (const auto& session : *sessionListForFront) {
if (session->GetUid() == infoUid && session->GetPid() == infoPid &&
(session->GetSessionType() != "voice_call" && session->GetSessionType() != "video_call")) {
UpdateTopSession(session);
CHECK_AND_RETURN_LOG(topSession_ != nullptr, "topSession is nullptr!");
if (topSession_->GetSessionType() == "audio" || topSession_->GetSessionType() == "video") {
AVSessionService::NotifySystemUI(nullptr, IsCapsuleNeeded(), false);
auto ret = BackgroundTaskMgr::BackgroundTaskMgrHelper::AVSessionNotifyUpdateNotification(
topSession_->GetUid(), topSession_->GetPid(), true);
SLOGD("HandleChangeTopSession Notify Bg, uid = %{public}d, pid = %{public}d, ret = %{public}d",
topSession_->GetUid(), topSession_->GetPid(), ret);
}
return;
}
}
}
// LCOV_EXCL_START
void AVSessionService::HandleFocusSession(const FocusSessionStrategy::FocusSessionChangeInfo& info, bool isPlaying)
{
std::lock_guard lockGuard(sessionServiceLock_);
SLOGI("uid=%{public}d, pid=%{public}d curTop:%{public}s",
info.uid, info.pid, (topSession_ == nullptr ? "null" : topSession_->GetBundleName()).c_str());
int32_t userId = GetUserIdFromCallingUid(static_cast<int32_t>(info.uid));
if (info.uid == ancoUid && isPlaying) {
sptr<AVSessionItem> sessionItem = GetUsersManager().GetContainerFromUser(userId).GetSessionByUid(info.uid);
CHECK_AND_RETURN_LOG(sessionItem != nullptr, "handle focusession no anco_audio");
ancoSession_ = sessionItem;
UpdateSessionTimestamp(ancoSession_);
SLOGI("HandleFocusSession updateancoSession");
return;
}
if ((topSession_ && topSession_->GetUid() == info.uid && topSession_->GetPid() == info.pid) &&
topSession_->IsCastConnected()) {
SLOGI("cur topSession:%{public}s isCastConnected", topSession_->GetBundleName().c_str());
return;
}
if (topSession_ && topSession_->GetUid() == info.uid && topSession_->GetPid() == info.pid) {
SLOGI(" HandleFocusSession focusSession is current topSession:%{public}d|%{public}d.", userId, isPlaying);
if (topSession_->GetSessionType() == "audio" || topSession_->GetSessionType() == "video") {
auto hasOtherPlayingSession = false;
if (!isPlaying) {
sptr<AVSessionItem> result = GetOtherPlayingSession(userId, "");
hasOtherPlayingSession = (result != nullptr);
HandleOtherSessionPlaying(result);
}
bool notPublishNotification = !isPlaying &&
(isMediaCardOpen_ || hasRemoveEvent_.load() || hasCardStateChangeStopTask_.load());
CHECK_AND_RETURN_LOG(!notPublishNotification,
"isPlaying:%{public}d isCardOpen_:%{public}d hasRemoveEvent_:%{public}d hasRemoveTask_:%{public}d",
isPlaying, isMediaCardOpen_.load(), hasRemoveEvent_.load(), hasCardStateChangeStopTask_.load());
if (isPlaying) {
auto ret = BackgroundTaskMgr::BackgroundTaskMgrHelper::AVSessionNotifyUpdateNotification(
topSession_->GetUid(), topSession_->GetPid(), true);
SLOGD("call AVSessionNotifyUpdateNotification, uid = %{public}d, pid = %{public}d, ret = %{public}d",
topSession_->GetUid(), topSession_->GetPid(), ret);
}
if (!hasOtherPlayingSession) {
AVSessionService::NotifySystemUI(nullptr, isPlaying && IsCapsuleNeeded(), false);
}
#ifdef START_STOP_ON_DEMAND_ENABLE
PublishEvent(mediaPlayStateTrue);
#endif
}
return;
}
CHECK_AND_RETURN_LOG(isPlaying, "focusSession no play");
HandleChangeTopSession(info.uid, info.pid, userId);
}
// LCOV_EXCL_STOP
// LCOV_EXCL_START
bool AVSessionService::InsertSessionItemToCJSON(sptr<AVSessionItem> &session, cJSON* valuesArray)
{
CHECK_AND_RETURN_RET_LOG(session != nullptr, false, "session get null");
CHECK_AND_RETURN_RET_LOG(valuesArray != nullptr, false, "valuesArray get null");
cJSON* newValue = cJSON_CreateObject();
CHECK_AND_RETURN_RET_LOG(newValue != nullptr, false, "newValue get null");
cJSON_AddStringToObject(newValue, "sessionId", session->GetSessionId().c_str());
cJSON_AddStringToObject(newValue, "bundleName", session->GetBundleName().c_str());
cJSON_AddStringToObject(newValue, "abilityName", session->GetAbilityName().c_str());
cJSON_AddStringToObject(newValue, "sessionType", session->GetSessionType().c_str());
cJSON_AddStringToObject(newValue, "sessionTag", session->GetSessionTag().c_str());
if (cJSON_GetArraySize(valuesArray) <= 0) {
cJSON_AddItemToArray(valuesArray, newValue);
} else {
cJSON_InsertItemInArray(valuesArray, 0, newValue);
}
if (cJSON_IsInvalid(valuesArray)) {
SLOGE("get newValueArray invalid");
return false;
}
return true;
}
// LCOV_EXCL_STOP
// LCOV_EXCL_START
void AVSessionService::RefreshFocusSessionSort(sptr<AVSessionItem> &session)
{
std::lock_guard sortFileLockGuard(sessionFileLock_);
std::string oldSortContent;
if (!LoadStringFromFileEx(GetAVSortDir(), oldSortContent)) {
SLOGE("LoadStringFromFileEx failed when refresh focus session sort!");
return;
}
cJSON* valuesArray = cJSON_Parse(oldSortContent.c_str());
CHECK_AND_RETURN_LOG(valuesArray != nullptr, "cjson parse nullptr");
if (cJSON_IsInvalid(valuesArray) || !cJSON_IsArray(valuesArray)) {
SLOGE("parse json invalid");
cJSON_Delete(valuesArray);
return;
}
bool sessionExist = false;
int arraySize = cJSON_GetArraySize(valuesArray);
for (int i = arraySize - 1; i >= 0; --i) {
cJSON* itemToDelete = cJSON_GetArrayItem(valuesArray, i);
CHECK_AND_CONTINUE(itemToDelete != nullptr && !cJSON_IsInvalid(itemToDelete));
cJSON* bundleNameItem = cJSON_GetObjectItem(itemToDelete, "bundleName");
cJSON* abilityNameItem = cJSON_GetObjectItem(itemToDelete, "abilityName");
if (bundleNameItem == nullptr || cJSON_IsInvalid(bundleNameItem) || !cJSON_IsString(bundleNameItem) ||
abilityNameItem == nullptr || cJSON_IsInvalid(abilityNameItem) || !cJSON_IsString(abilityNameItem)) {
SLOGI("not contain bundleName or abilityName, pass");
continue;
}
if (strcmp(session->GetBundleName().c_str(), bundleNameItem->valuestring) == 0 &&
strcmp(session->GetAbilityName().c_str(), abilityNameItem->valuestring) == 0) {
cJSON_DeleteItemFromArray(valuesArray, i);
sessionExist = true;
break;
}
}
if (sessionExist) {
InsertSessionItemToCJSON(session, valuesArray);
}
std::string newSortContentStr = DoCJSONArrayTransformToString(valuesArray);
if (!SaveStringToFileEx(GetAVSortDir(), newSortContentStr)) {
SLOGE("SaveStringToFileEx failed when refresh focus session sort!");
}
cJSON_Delete(valuesArray);
}
std::string AVSessionService::DoCJSONArrayTransformToString(cJSON* valueItem)
{
CHECK_AND_RETURN_RET_LOG(valueItem != nullptr && !cJSON_IsInvalid(valueItem), "", "valueItem invalid");
char* newSortContent = cJSON_Print(valueItem);
CHECK_AND_RETURN_RET_LOG(newSortContent != nullptr, "", "newValueArray print fail nullptr");
std::string newSortContentStr(newSortContent);
cJSON_free(newSortContent);
return newSortContentStr;
}
// LCOV_EXCL_STOP
void AVSessionService::UpdateFrontSession(sptr<AVSessionItem>& sessionItem, bool isAdd)
{
CHECK_AND_RETURN_LOG(sessionItem != nullptr, "sessionItem get nullptr!");
int32_t userId = sessionItem->GetUserId();
HILOG_COMM_INFO("UpdateFrontSession with bundle=%{public}s, isAdd=%{public}d",
sessionItem->GetBundleName().c_str(), isAdd);
{
std::lock_guard lockGuard(controlListLock_);
CHECK_AND_RETURN_LOG(controlBundleNameSet_.find(sessionItem->GetBundleName()) == controlBundleNameSet_.end(),
"session is in controlList, dont add to front");
}
std::lock_guard frontLockGuard(sessionFrontLock_);
std::shared_ptr<std::list<sptr<AVSessionItem>>> sessionListForFront = GetCurSessionListForFront(userId);
CHECK_AND_RETURN_LOG(sessionListForFront != nullptr, "sessionListForFront ptr nullptr!");
CHECK_AND_RETURN_LOG(sessionItem->GetSessionType() != sessionTypePhoto, "session type is photo");
auto ret = BackgroundTaskMgr::BackgroundTaskMgrHelper::AVSessionNotifyUpdateNotification(
sessionItem->GetUid(), sessionItem->GetPid(), isAdd);
if (ret != AVSESSION_SUCCESS) {
SLOGE("AVSessionNotifyUpdateNotification failed, uid = %{public}d, pid = %{public}d, ret = %{public}d",
sessionItem->GetUid(), sessionItem->GetPid(), ret);
}
auto it = std::find(sessionListForFront->begin(), sessionListForFront->end(), sessionItem);
if (isAdd) {
if (it != sessionListForFront->end()) {
SLOGI("sessionListForFront has same session bundle=%{public}s", sessionItem->GetBundleName().c_str());
return;
}
sessionListForFront->push_front(sessionItem);
if (IsLocalSessionPlaying(sessionItem)) {
SLOGI("Renderer Running, RepublishNotification for uid=%{public}d", sessionItem->GetUid());
UpdateTopSession(sessionItem);
NotifySystemUI(nullptr, IsCapsuleNeeded(), false);
}
} else {
HandleTopSessionRelease(userId, sessionItem);
sessionListForFront->remove(sessionItem);
#ifdef CASTPLUS_CAST_ENGINE_ENABLE
NotifySystemCommonEvent(SESSION_RELEASE, "");
#endif
SLOGI("sessionListForFront with size %{public}d", static_cast<int32_t>(sessionListForFront->size()));
}
UpdateLocalFrontSession(sessionListForFront);
NotifySessionChange(sessionListForFront, userId);
}
bool AVSessionService::UpdateOrder(sptr<AVSessionItem>& sessionItem)
{
CHECK_AND_RETURN_RET_LOG(sessionItem != nullptr, false, "session is nullptr!");
int32_t userId = sessionItem->GetUserId();
GetUsersManager().GetContainerFromUser(userId).UpdateSessionSort(sessionItem);
RefreshFocusSessionSort(sessionItem);
std::lock_guard frontLockGuard(sessionFrontLock_);
std::shared_ptr<std::list<sptr<AVSessionItem>>> sessionListForFront =
GetCurSessionListForFront(sessionItem->GetUserId());
CHECK_AND_RETURN_RET_LOG(sessionListForFront != nullptr, false, "sessionListForFront ptr nullptr!");
CHECK_AND_RETURN_RET_LOG(sessionItem->GetSessionType() != sessionTypePhoto,
false, "session type is photo");
auto it = std::find(sessionListForFront->begin(), sessionListForFront->end(), sessionItem);
if (it != sessionListForFront->end()) {
SLOGI("session is in sessionListForFront_, need to change order of it.");
sessionListForFront->remove(sessionItem);
sessionListForFront->push_front(sessionItem);
UpdateSessionTimestamp(sessionItem);
NotifySessionChange(sessionListForFront, userId);
}
return true;
}
bool AVSessionService::SelectFocusSession(const FocusSessionStrategy::FocusSessionChangeInfo& info)
{
int32_t userId = GetUserIdFromCallingUid(static_cast<int32_t>(info.uid));
for (auto& session : GetUsersManager().GetContainerFromUser(userId).GetAllSessions()) {
CHECK_AND_CONTINUE(session != nullptr);
if (session->GetDescriptor().sessionTag_ == "RemoteCast" || session->GetPid() != info.pid) {
continue;
}
bool ret = UpdateOrder(session);
CHECK_AND_RETURN_RET_LOG(ret, false, "UpdateOrder fail");
return true;
}
return false;
}
void AVSessionService::InitAudio()
{
SLOGI("enter");
AudioAdapter::GetInstance().Init();
focusSessionStrategy_.Init();
focusSessionStrategy_.RegisterFocusSessionChangeCallback([this] (const auto& info, bool isPlaying) {
HandleFocusSession(info, isPlaying);
});
focusSessionStrategy_.RegisterFocusSessionSelector([this] (const auto& info) {
return SelectFocusSession(info);
});
queryAllowedPlaybackCallbackFunc_ = GetAllowedPlaybackCallbackFunc();
auto ret = AudioAdapter::GetInstance().RegisterAllowedPlaybackCallback(queryAllowedPlaybackCallbackFunc_);
if (ret != AVSESSION_SUCCESS) {
SLOGE("register query allowed playback callback failed!");
}
#ifdef CAR_FEATURE_ENABLE
InitAudioZoneCallback();
#endif
}
sptr <AVSessionItem> AVSessionService::SelectSessionByUid(const AudioRendererChangeInfo& info)
{
for (const auto& session : GetContainer().GetAllSessions()) {
if (session != nullptr && session->GetUid() == info.clientUID) {
return session;
}
}
SLOGI("AudioRendererInfo with uid: %{public}d does not have a corresponding session.", info.clientUID);
return nullptr;
}
void AVSessionService::InitAMS()
{
SLOGI("enter");
AppManagerAdapter::GetInstance().Init();
AppManagerAdapter::GetInstance().SetServiceCallbackForAppStateChange([this] (int uid, int state) {
SLOGD("uid = %{public}d, state = %{public}d", uid, state);
HandleAppStateChange(uid, state);
});
}
#ifdef DEVICE_MANAGER_ENABLE
void AVSessionService::InitDM()
{
SLOGI("enter");
auto callback = std::make_shared<AVSessionInitDMCallback>();
CHECK_AND_RETURN_LOG(callback != nullptr, "no memory");
int32_t ret = OHOS::DistributedHardware::DeviceManager::GetInstance().InitDeviceManager("av_session", callback);
CHECK_AND_RETURN_LOG(ret == 0, "InitDeviceManager error ret is %{public}d", ret);
DoTargetDevListenWithDM();
}
#endif
void AVSessionService::InitBMS()
{
std::lock_guard sortFileLockGuard(sessionFileLock_);
SLOGI("enter");
BundleStatusAdapter::GetInstance().Init();
int userId = GetUsersManager().GetCurrentUserId();
if (userId < 0) {
SLOGE("InitBMS with userId: %{public}d, not valid, return and wait for InitAccountMgr", userId);
return;
}
RegisterBundleDeleteEventForHistory(userId);
}
void AVSessionService::InitAccountMgr()
{
SLOGI("InitAccountMgr in");
GetUsersManager().Init();
RegisterBundleDeleteEventForHistory();
}
void AVSessionService::InitCommonEventService()
{
SLOGI("InitCommonEventService in");
bool ret = SubscribeCommonEvent();
CHECK_AND_RETURN_LOG(ret, "SubscribeCommonEvent error!");
}
void AVSessionService::InitCollaboration()
{
SLOGI("InitCollaboration in");
#ifdef CASTPLUS_CAST_ENGINE_ENABLE
std::shared_ptr<PluginLib> pluginLib = std::make_shared<PluginLib>("/system/lib64/libcfwk_allconnect_client.z.so");
CHECK_AND_RETURN_LOG((pluginLib != nullptr), "dlopen lib err");
CollaborationManagerURLCasting::GetInstance().ReadCollaborationManagerSo(pluginLib);
CollaborationManagerURLCasting::GetInstance().RegisterLifecycleCallback();
CollaborationManagerHiPlay::GetInstance().ReadCollaborationManagerSo(pluginLib);
CollaborationManagerHiPlay::GetInstance().RegisterLifecycleCallback();
#endif
}
void AVSessionService::InitCastEngineService()
{
SLOGI("InitCastEngineService in");
#ifdef CASTPLUS_CAST_ENGINE_ENABLE
SLOGI("GetDeviceEnableCast, Prop=%{public}d", static_cast<int>(isCastableDevice_));
#endif
}
void AVSessionService::RegisterBundleDeleteEventForHistory(int32_t userId)
{
if (userId <= 0) {
userId = GetUsersManager().GetCurrentUserId();
SLOGI("do RegisterBundleDeleteEventForHistory with cur userId:%{public}d", userId);
} else {
SLOGI("do RegisterBundleDeleteEventForHistory with recv userId:%{public}d", userId);
}
std::string oldSortContent;
if (LoadStringFromFileEx(GetAVSortDir(userId), oldSortContent)) {
cJSON* valuesArray = cJSON_Parse(oldSortContent.c_str());
CHECK_AND_RETURN_LOG(valuesArray != nullptr, "parse json get nullptr");
if (cJSON_IsInvalid(valuesArray) || !cJSON_IsArray(valuesArray)) {
SLOGE("parse json not valid");
cJSON_Delete(valuesArray);
return;
}
auto callback = [this](std::string bundleName, int32_t userId) {
SLOGI("recv delete bundle:%{public}s at user:%{public}d", bundleName.c_str(), userId);
DeleteAVQueueInfoRecord(bundleName, userId);
DeleteHistoricalRecord(bundleName, userId);
NotifyHistoricalRecordChange(bundleName, userId);
};
cJSON* valueItem = nullptr;
cJSON_ArrayForEach(valueItem, valuesArray) {
CHECK_AND_CONTINUE(valueItem != nullptr && !cJSON_IsInvalid(valueItem));
cJSON* bundleNameItem = cJSON_GetObjectItem(valueItem, "bundleName");
CHECK_AND_CONTINUE(bundleNameItem != nullptr &&
!cJSON_IsInvalid(bundleNameItem) && cJSON_IsString(bundleNameItem));
std::string bundleNameStr(bundleNameItem->valuestring);
if (!BundleStatusAdapter::GetInstance().SubscribeBundleStatusEvent(bundleNameStr, callback, userId)) {
SLOGE("SubscribeBundleStatusEvent failed for bundle:%{public}s", bundleNameStr.c_str());
}
}
cJSON_Delete(valuesArray);
}
}
SessionContainer& AVSessionService::GetContainer()
{
return GetUsersManager().GetContainer();
}
AVSessionUsersManager& AVSessionService::GetUsersManager()
{
static AVSessionUsersManager usersManager;
return usersManager;
}
inline std::shared_ptr<std::list<sptr<AVSessionItem>>> AVSessionService::GetCurSessionListForFront(int32_t userId)
{
return GetUsersManager().GetCurSessionListForFront(userId);
}
inline std::shared_ptr<std::list<sptr<AVSessionItem>>> AVSessionService::GetCurKeyEventSessionList(int32_t userId)
{
return GetUsersManager().GetCurSessionListForKeyEvent(userId);
}
std::string AVSessionService::AllocSessionId()
{
auto curNum = sessionSeqNum_++;
std::string id = std::to_string(GetCallingPid()) + "-" + std::to_string(GetCallingUid()) + "-" +
std::to_string(curNum);
HashCalculator hashCalculator;
CHECK_AND_RETURN_RET_LOG(hashCalculator.Init() == AVSESSION_SUCCESS, "", "hash init failed");
CHECK_AND_RETURN_RET_LOG(hashCalculator.Update(std::vector<uint8_t>(id.begin(), id.end())) == AVSESSION_SUCCESS,
"", "hash update failed");
std::vector<uint8_t> hash;
CHECK_AND_RETURN_RET_LOG(hashCalculator.GetResult(hash) == AVSESSION_SUCCESS, "", "hash get result failed");
std::stringstream stream;
for (const auto byte : hash) {
stream << std::uppercase << std::hex << std::setfill('0') << std::setw(allocSpace) << static_cast<int>(byte);
}
return stream.str();
}
bool AVSessionService::AbilityHasSession(pid_t pid, int32_t userId)
{
std::lock_guard lockGuard(sessionServiceLock_);
return (userId <= 0) ?
GetContainer().PidHasSession(pid) : GetUsersManager().GetContainerFromUser(userId).PidHasSession(pid);
}
sptr<AVControllerItem> AVSessionService::GetPresentController(pid_t pid, const std::string& sessionId)
{
std::lock_guard lockGuard(sessionServiceLock_);
auto it = controllers_.find(pid);
if (it != controllers_.end()) {
for (const auto& controller: it->second) {
if (controller != nullptr && controller->HasSession(sessionId)) {
return controller;
}
}
}
SLOGI("Not found controller for pid:%{public}d, sessionId:%{public}s.", pid,
AVSessionUtils::GetAnonySessionId(sessionId).c_str());
return nullptr;
}
void AVSessionService::NotifySessionCreate(const AVSessionDescriptor& descriptor)
{
std::lock_guard lockGuard(sessionListenersLock_);
auto audioSystemManager = AudioStandard::AudioSystemManager::GetInstance();
if (audioSystemManager != nullptr) {
auto ret = audioSystemManager->NotifySessionStateChange(descriptor.uid_, descriptor.pid_, true);
if (ret != AVSESSION_SUCCESS) {
SLOGE("NotifySessionStateChange failed, uid = %{public}d, pid = %{public}d, ret = %{public}d",
descriptor.uid_, descriptor.pid_, ret);
}
} else {
SLOGE("AudioSystemManager is nullptr");
}
std::map<pid_t, sptr<ISessionListener>> listenerMap = GetUsersManager().GetSessionListener(descriptor.userId_);
SLOGI("NotifySessionCreate for user:%{public}d", descriptor.userId_);
#ifdef START_STOP_ON_DEMAND_ENABLE
PublishEvent(mediaPlayStateTrue);
#endif
for (const auto& [pid, listener] : listenerMap) {
AVSESSION_TRACE_SYNC_START("AVSessionService::OnSessionCreate");
if (listener != nullptr) {
listener->OnSessionCreate(descriptor);
}
}
std::map<pid_t, sptr<ISessionListener>> listenerMapForAll = GetUsersManager().GetSessionListenerForAllUsers();
for (const auto& [pid, listener] : listenerMapForAll) {
AVSESSION_TRACE_SYNC_START("AVSessionService::OnSessionCreate");
if (listener != nullptr) {
listener->OnSessionCreate(descriptor);
}
}
{
std::lock_guard lockGuard(migrateListenersLock_);
for (const auto& listener : innerSessionListeners_) {
if (listener != nullptr) {
listener->OnSessionCreate(descriptor);
}
}
}
#ifdef CAR_FEATURE_ENABLE
auto& listenersMapByUserIdForAudioZone = GetUsersManager().GetSessionListenersMapForAudioZone();
auto listenersForUserIt = listenersMapByUserIdForAudioZone.find(descriptor.userId_);
CHECK_AND_RETURN_LOG(listenersForUserIt != listenersMapByUserIdForAudioZone.end(),
"NotifySessionCreate no listeners for user:%{public}d", descriptor.userId_);
for (const auto& [pid, listener] : listenersForUserIt->second) {
if (listener != nullptr) {
listener->OnSessionCreate(descriptor);
}
}
#endif
}
void AVSessionService::NotifySessionRelease(const AVSessionDescriptor& descriptor)
{
std::lock_guard lockGuard(sessionListenersLock_);
auto audioSystemManager = AudioStandard::AudioSystemManager::GetInstance();
if (audioSystemManager != nullptr) {
auto ret = audioSystemManager->NotifySessionStateChange(descriptor.uid_, descriptor.pid_, false);
if (ret != AVSESSION_SUCCESS) {
SLOGE("NotifySessionStateChange failed, uid = %{public}d, pid = %{public}d, ret = %{public}d",
descriptor.uid_, descriptor.pid_, ret);
}
} else {
SLOGE("AudioSystemManager is nullptr");
}
auto ret = BackgroundTaskMgr::BackgroundTaskMgrHelper::AVSessionNotifyUpdateNotification(
descriptor.uid_, descriptor.pid_, false);
if (ret != AVSESSION_SUCCESS) {
SLOGE("AVSessionNotifyUpdateNotification failed, uid = %{public}d, pid = %{public}d, ret = %{public}d",
descriptor.uid_, descriptor.pid_, ret);
}
std::map<pid_t, sptr<ISessionListener>> listenerMap = GetUsersManager().GetSessionListener(descriptor.userId_);
SLOGI("NotifySessionRelease for user:%{public}d|listenerSize:%{public}d",
descriptor.userId_, static_cast<int>(listenerMap.size()));
for (const auto& [pid, listener] : listenerMap) {
if (listener != nullptr) {
listener->OnSessionRelease(descriptor);
}
}
std::map<pid_t, sptr<ISessionListener>> listenerMapForAll = GetUsersManager().GetSessionListenerForAllUsers();
for (const auto& [pid, listener] : listenerMapForAll) {
if (listener != nullptr) {
listener->OnSessionRelease(descriptor);
}
}
{
std::lock_guard lockGuard(migrateListenersLock_);
for (const auto& listener : innerSessionListeners_) {
if (listener != nullptr) {
listener->OnSessionRelease(descriptor);
}
}
}
#ifdef CAR_FEATURE_ENABLE
auto& listenersMapByUserIdForAudioZone = GetUsersManager().GetSessionListenersMapForAudioZone();
auto listenersForUserIt = listenersMapByUserIdForAudioZone.find(descriptor.userId_);
CHECK_AND_RETURN_LOG(listenersForUserIt != listenersMapByUserIdForAudioZone.end(),
"NotifySessionRelease no listeners for user:%{public}d", descriptor.userId_);
for (const auto& [pid, listener] : listenersForUserIt->second) {
if (listener != nullptr) listener->OnSessionRelease(descriptor);
}
#endif
}
void AVSessionService::NotifyTopSessionChanged(const AVSessionDescriptor& descriptor)
{
std::map<pid_t, sptr<ISessionListener>> listenerMap;
std::map<pid_t, sptr<ISessionListener>> listenerMapForAll;
{
std::lock_guard lockGuard(sessionListenersLock_);
listenerMap = GetUsersManager().GetSessionListener(descriptor.userId_);
listenerMapForAll = GetUsersManager().GetSessionListenerForAllUsers();
}
SLOGI("NotifyTopSession for user:%{public}d", descriptor.userId_);
for (const auto& [pid, listener] : listenerMap) {
AVSESSION_TRACE_SYNC_START("AVSessionService::OnTopSessionChange");
if (listener != nullptr) {
listener->OnTopSessionChange(descriptor);
}
}
for (const auto& [pid, listener] : listenerMapForAll) {
AVSESSION_TRACE_SYNC_START("AVSessionService::OnTopSessionChange");
if (listener != nullptr) {
listener->OnTopSessionChange(descriptor);
}
}
{
std::lock_guard lockGuard(migrateListenersLock_);
for (const auto& listener : innerSessionListeners_) {
if (listener != nullptr) {
listener->OnTopSessionChange(descriptor);
}
}
}
#ifdef CAR_FEATURE_ENABLE
auto& listenersMapByUserIdForAudioZone = GetUsersManager().GetSessionListenersMapForAudioZone();
auto listenersForUserIt = listenersMapByUserIdForAudioZone.find(descriptor.userId_);
CHECK_AND_RETURN_LOG(listenersForUserIt != listenersMapByUserIdForAudioZone.end(),
"NotifyTopSessionChange no listeners for user:%{public}d", descriptor.userId_);
for (const auto& [pid, listener] : listenersForUserIt->second) {
if (listener != nullptr) {
listener->OnTopSessionChange(descriptor);
}
}
#endif
}
void AVSessionService::LowQualityCheck(int32_t uid, int32_t pid, AudioStandard::StreamUsage streamUsage,
AudioStandard::RendererState rendererState)
{
int32_t userId = GetUserIdFromCallingUid(uid);
auto containerPtr = GetUsersManager().GetContainerPtrFromUser(userId);
CHECK_AND_RETURN_LOG(containerPtr != nullptr, "get containerPtr null");
sptr<AVSessionItem> session = containerPtr->GetSessionByUid(uid);
CHECK_AND_RETURN_LOG(session != nullptr, "session not exist for LowQualityCheck");
AVMetaData meta = session->GetMetaDataWithoutImg();
bool hasTitle = !meta.GetTitle().empty();
bool hasImage = meta.GetMediaImage() != nullptr || !meta.GetMediaImageUri().empty();
if ((hasTitle || hasImage) && (session->GetSupportCommand().size() != 0)) {
SLOGD("LowQualityCheck pass for %{public}s, return", session->GetBundleName().c_str());
return;
}
int32_t commandQuality = 0;
for (auto cmd : session->GetSupportCommand()) {
auto it = cmdToOffsetMap_.find(cmd);
if (it != cmdToOffsetMap_.end()) {
commandQuality += (1 << it->second);
}
}
SLOGD("LowQualityCheck report for %{public}s", session->GetBundleName().c_str());
AVSessionSysEvent::BackControlReportInfo reportInfo;
reportInfo.bundleName_ = session->GetBundleName();
reportInfo.streamUsage_ = streamUsage;
reportInfo.isBack_ = AppManagerAdapter::GetInstance().IsAppBackground(uid, pid);
reportInfo.playDuration_ = -1;
reportInfo.isAudioActive_ = true;
reportInfo.metaDataQuality_ = (hasTitle << 1) + hasImage;
reportInfo.cmdQuality_ = commandQuality;
reportInfo.playbackState_ = session->GetPlaybackState().GetState();
AVSessionSysEvent::GetInstance().AddLowQualityInfo(reportInfo);
}
void AVSessionService::PlayStateCheck(int32_t uid, AudioStandard::StreamUsage streamUsage,
AudioStandard::RendererState rState)
{
int32_t userId = GetUserIdFromCallingUid(uid);
sptr<AVSessionItem> session = GetUsersManager().GetContainerFromUser(userId).GetSessionByUid(uid);
CHECK_AND_RETURN_LOG(session != nullptr, "session not exist for LowQualityCheck");
AVPlaybackState aState = session->GetPlaybackState();
if ((rState == AudioStandard::RENDERER_RUNNING && aState.GetState() != AVPlaybackState::PLAYBACK_STATE_PLAY) ||
((rState == AudioStandard::RENDERER_PAUSED || rState == AudioStandard::RENDERER_STOPPED) &&
aState.GetState() == AVPlaybackState::PLAYBACK_STATE_PLAY)) {
SLOGD("PlayStateCheck report for %{public}s", session->GetBundleName().c_str());
HISYSEVENT_FAULT("AVSESSION_WRONG_STATE",
"BUNDLE_NAME", session->GetBundleName(),
"RENDERER_STATE", rState,
"AVSESSION_STATE", aState.GetState());
}
}
void AVSessionService::NotifyBackgroundReportCheck(const int32_t uid, const int32_t pid,
AudioStandard::StreamUsage streamUsage, AudioStandard::RendererState rendererState)
{
// low quality check
if (rendererState == AudioStandard::RENDERER_RUNNING) {
AVSessionEventHandler::GetInstance().AVSessionPostTask(
[this, uid, pid, streamUsage, rendererState]() {
LowQualityCheck(uid, pid, streamUsage, rendererState);
}, "LowQualityCheck", lowQualityTimeout);
}
// error renderer state check
AVSessionEventHandler::GetInstance().AVSessionPostTask(
[this, uid, streamUsage, rendererState]() {
PlayStateCheck(uid, streamUsage, rendererState);
}, "PlayStateCheck", errorStateTimeout);
}
// LCOV_EXCL_START
void AVSessionService::NotifyAudioSessionCheck(const int32_t uid)
{
std::lock_guard lockGuard(sessionListenersLock_);
std::map<pid_t, sptr<ISessionListener>> listenerMap = GetUsersManager().GetSessionListener();
for (const auto& [pid, listener] : listenerMap) {
AVSESSION_TRACE_SYNC_START("AVSessionService::OnAudioSessionCheck");
if (listener != nullptr) {
listener->OnAudioSessionChecked(uid);
}
}
std::map<pid_t, sptr<ISessionListener>> listenerMapForAll = GetUsersManager().GetSessionListenerForAllUsers();
for (const auto& [pid, listener] : listenerMapForAll) {
AVSESSION_TRACE_SYNC_START("AVSessionService::OnAudioSessionCheck");
if (listener != nullptr) {
listener->OnAudioSessionChecked(uid);
}
}
{
std::lock_guard lockGuard(migrateListenersLock_);
for (const auto& listener : innerSessionListeners_) {
if (listener != nullptr) {
listener->OnAudioSessionChecked(uid);
}
}
}
}
// LCOV_EXCL_STOP
bool AVSessionService::CheckAncoAudio()
{
for (const auto& session : GetContainer().GetAllSessions()) {
if (session->GetBundleName() == "anco_audio") {
return true;
}
}
return false;
}
// LCOV_EXCL_START
void AVSessionService::HandleCallStartEvent()
{
SLOGI("Call mediaController player in sink side when cast state is connected.");
AbilityConnectHelper::GetInstance().StartAbilityForegroundByCall(MEDIA_CONTROL_BUNDLENAME,
MEDIA_CONTROL_ABILITYNAME);
}
// LCOV_EXCL_STOP
bool AVSessionService::ProcTopSessionPlaying(sptr<AVSessionItem> session, bool isPlaying, bool isMediaChange)
{
CHECK_AND_RETURN_RET_LOG(topSession_ != nullptr && (topSession_.GetRefPtr() == session.GetRefPtr()), false,
"session isnt topsession");
SLOGI("ProcTopSessionPlaying topSession is %{public}s isPlaying %{public}d isMediaChange %{public}d",
topSession_->GetBundleName().c_str(), isPlaying, isMediaChange);
CHECK_AND_RETURN_RET_LOG(isPlaying || (!isMediaCardOpen_.load() && !hasRemoveEvent_.load()), true,
"ProcTopSessionPlaying del isCardOpen_:%{public}d hasRemoveEvent_:%{public}d",
isMediaCardOpen_.load(), hasRemoveEvent_.load());
auto hasOtherSessionPlaying = false;
if (!isPlaying) {
int32_t userId = topSession_->GetUserId();
userId = userId < 0 ? GetUsersManager().GetCurrentUserId() : userId;
sptr<AVSessionItem> result = GetOtherPlayingSession(userId, "");
hasOtherSessionPlaying = result != nullptr;
HandleOtherSessionPlaying(result);
}
if (!hasOtherSessionPlaying) {
NotifySystemUI(nullptr, isPlaying && IsCapsuleNeeded(), isMediaChange);
}
return true;
}
void AVSessionService::AddCapsuleServiceCallback(sptr<AVSessionItem>& sessionItem)
{
sessionItem->SetServiceCallbackForNtfCapsule([this](std::string sessionId, bool isMediaChange) {
std::lock_guard lockGuard(sessionServiceLock_);
sptr<AVSessionItem> session = GetContainer().GetSessionById(sessionId);
CHECK_AND_RETURN_LOG(hasMediaCapsule_.load(), "notifysystemui but no capsule here");
if (session && topSession_ && (topSession_.GetRefPtr() == session.GetRefPtr())) {
if (isAncoMediaSessionChange_) {
UpdateTopSession(session);
SLOGI("isAncoMediaSessionChange_ UpdateTopSession %{public}s", session->GetBundleName().c_str());
isAncoMediaSessionChange_ = false;
}
SLOGI("MediaCapsule topsession %{public}s updateImage", topSession_->GetBundleName().c_str());
NotifySystemUI(nullptr, IsCapsuleNeeded() && hasMediaCapsule_.load(), isMediaChange);
}
});
sessionItem->SetServiceCallbackForMediaSession([this](std::string sessionId, bool isPlaying, bool isMediaChange) {
// only use for anco mediasession
std::lock_guard lockGuard(sessionServiceLock_);
sptr<AVSessionItem> session = GetContainer().GetSessionById(sessionId);
CHECK_AND_RETURN_LOG(session != nullptr, "session not exist");
bool isProcSameTop = ProcTopSessionPlaying(session, isPlaying, isMediaChange);
SLOGI("ProcTopSessionPlaying isAncoMediaSessionChange_ %{public}d", isAncoMediaSessionChange_);
CHECK_AND_RETURN_LOG(!isProcSameTop || isAncoMediaSessionChange_, "same top session");
CHECK_AND_RETURN_LOG(isPlaying, "anco media session is not playing");
FocusSessionStrategy::FocusSessionChangeInfo sessionInfo;
sessionInfo.uid = session->GetUid();
sessionInfo.pid = session->GetPid();
SelectFocusSession(sessionInfo);
std::lock_guard frontLockGuard(sessionFrontLock_);
std::shared_ptr<std::list<sptr<AVSessionItem>>> sessionListForFront = GetCurSessionListForFront();
CHECK_AND_RETURN_LOG(sessionListForFront != nullptr, "sessionListForFront ptr nullptr!");
auto it = std::find(sessionListForFront->begin(), sessionListForFront->end(), session);
CHECK_AND_RETURN_LOG(it != sessionListForFront->end(), "mediasession not in frontlist");
UpdateTopSession(session);
if (isAncoMediaSessionChange_) {
isAncoMediaSessionChange_ = false;
}
NotifySystemUI(nullptr, isPlaying && IsCapsuleNeeded(), isMediaChange);
});
sessionItem->SetServiceCallbackForBgPlayModeChange([this](std::string sessionId, int32_t mode) {
std::lock_guard lockGuard(sessionServiceLock_);
sptr<AVSessionItem> session = GetContainer().GetSessionById(sessionId);
bool isUpdateForTop = session != nullptr && topSession_ != nullptr &&
(topSession_.GetRefPtr() == session.GetRefPtr());
if (isUpdateForTop) {
SLOGI("BgPlayModeChange topsession %{public}s", topSession_->GetBundleName().c_str());
NotifySystemUI(nullptr, IsCapsuleNeeded(), false);
}
});
}
void AVSessionService::AddAncoColdStartServiceCallback(sptr<AVSessionItem>& session)
{
session->SetServiceCallbackForAncoStart([this](std::string sessionId, std::string bundle, std::string ability) {
std::lock_guard lockGuard(sessionServiceLock_);
sptr<AVSessionItem> sessionItem = GetContainer().GetSessionById(sessionId);
CHECK_AND_RETURN_LOG(sessionItem != nullptr, "session not exist for AncoStartCallback");
AppExecFwk::ElementName elementName;
elementName.SetBundleName(bundle);
elementName.SetAbilityName(ability);
SaveSessionInfoInFile(sessionItem->GetSessionTag(), sessionId, sessionItem->GetSessionType(), elementName);
});
}
void AVSessionService::AddCastCapsuleServiceCallback(sptr<AVSessionItem>& sessionItem)
{
#ifdef CASTPLUS_CAST_ENGINE_ENABLE
sessionItem->SetServiceCallbackForCastNtfCapsule([this](std::string sessionId, bool isPlaying, bool isChange) {
std::lock_guard lockGuard(sessionServiceLock_);
sptr<AVSessionItem> session = GetContainer().GetSessionById(sessionId);
CHECK_AND_RETURN_LOG(session != nullptr, "castSession not exist");
CHECK_AND_RETURN_LOG(session->GetSessionType() != sessionTypePhoto, "session type is photo");
bool isProcSameTop = ProcTopSessionPlaying(session, isPlaying, isChange);
CHECK_AND_RETURN_LOG(!isProcSameTop, "same top session");
bool castChange = topSession_ && topSession_->IsCasting() && (topSession_.GetRefPtr() != session.GetRefPtr());
if ((topSession_ == nullptr || castChange) && isPlaying) {
SLOGI("MediaCapsule fresh castSession %{public}s to top, isMediaChange %{public}d",
session->GetBundleName().c_str(), isChange);
UpdateTopSession(session);
NotifySystemUI(nullptr, isPlaying, isChange);
bool updateOrderResult = UpdateOrder(session);
CHECK_AND_RETURN_LOG(updateOrderResult, "UpdateOrder fail");
}
});
#endif // CASTPLUS_CAST_ENGINE_ENABLE
}
void AVSessionService::AddKeyEventServiceCallback(sptr<AVSessionItem>& sessionItem)
{
sessionItem->SetServiceCallbackForKeyEvent([this](std::string sessionId) {
int32_t err = PermissionChecker::GetInstance().CheckPermission(
PermissionChecker::CHECK_MEDIA_RESOURCES_PERMISSION);
CHECK_AND_RETURN_LOG(err == AVSESSION_SUCCESS, "Add KeyEventSession, CheckPermission failed!");
std::lock_guard lockGuard(sessionServiceLock_);
sptr<AVSessionItem> session = GetContainer().GetSessionById(sessionId);
CHECK_AND_RETURN_LOG(session != nullptr, "session not exist for KeyEvent");
{
std::lock_guard lockGuard(keyEventListLock_);
int userId = session->GetUserId();
std::shared_ptr<std::list<sptr<AVSessionItem>>> keyEventList = GetCurKeyEventSessionList(userId);
CHECK_AND_RETURN_LOG(keyEventList != nullptr, "keyEventList ptr nullptr!");
auto it = std::find(keyEventList->begin(), keyEventList->end(), session);
if (it == keyEventList->end()) {
SLOGI("keyEventList add=%{public}s", session->GetBundleName().c_str());
keyEventList->push_front(session);
return;
}
}
});
}
void AVSessionService::AddUpdateTopServiceCallback(sptr<AVSessionItem>& sessionItem)
{
sessionItem->SetServiceCallbackForUpdateTop([this](std::string sessionId) {
int32_t err = PermissionChecker::GetInstance().CheckPermission(
PermissionChecker::CHECK_MEDIA_RESOURCES_PERMISSION);
CHECK_AND_RETURN_LOG(err == AVSESSION_SUCCESS, "update top, CheckPermission failed!");
std::lock_guard lockGuard(sessionServiceLock_);
sptr<AVSessionItem> session = GetContainer().GetSessionById(sessionId);
CHECK_AND_RETURN_LOG(session != nullptr && IsLocalSessionPlaying(session), "session not valid for updateTop");
SLOGI("PLAY with param updateTopSession=%{public}s", session->GetBundleName().c_str());
UpdateTopSession(session);
FocusSessionStrategy::FocusSessionChangeInfo sessionInfo;
sessionInfo.uid = session->GetUid();
sessionInfo.pid = session->GetPid();
SelectFocusSession(sessionInfo);
NotifySystemUI(nullptr, IsCapsuleNeeded(), false);
});
}
void AVSessionService::AddCastServiceCallback(sptr<AVSessionItem>& sessionItem)
{
#ifdef CASTPLUS_CAST_ENGINE_ENABLE
CHECK_AND_RETURN_LOG(sessionItem != nullptr, "session not exist for AddCastServiceCallback");
sessionItem->SetServiceCallbackForStream([this](std::string sessionId) {
sptr<AVSessionItem> session = GetContainer().GetSessionById(sessionId);
CHECK_AND_RETURN_LOG(session != nullptr, "Session not exist");
MirrorToStreamCast(session);
});
sessionItem->SetServiceCallbackForStopSinkCast([this]() {
std::lock_guard lockGuard(sessionServiceLock_);
SLOGI("Start release cast session");
for (const auto& session : GetContainer().GetAllSessions()) {
if (session != nullptr && session->GetDescriptor().sessionTag_ == "RemoteCast") {
std::string sessionId = session->GetDescriptor().sessionId_;
SLOGI("Already has a cast session %{public}s", AVSessionUtils::GetAnonySessionId(sessionId).c_str());
session->StopCastSession();
}
}
});
sessionItem->SetServiceCallbackForPhotoCast([this](std::string sessionId, bool isConnect) {
sptr<AVSessionItem> session = GetUsersManager().GetContainerFromAll().GetSessionById(sessionId);
CHECK_AND_RETURN_LOG(session != nullptr, "session not exist");
if (isConnect) {
NotifySystemUI(session, true, false);
} else {
int32_t ret = Notification::NotificationHelper::CancelNotification(
std::to_string(session->GetDescriptor().userId_), photoNotifyId);
SLOGI("CancelNotification PHOTO with userId:%{public}d, ret=%{public}d",
session->GetDescriptor().userId_, ret);
}
});
sessionItem->SetServiceCallbackForPcMode([this]() {
return isPcMode_.load();
});
#endif // CASTPLUS_CAST_ENGINE_ENABLE
}
void AVSessionService::ServiceCallback(sptr<AVSessionItem>& sessionItem)
{
if (sessionItem == nullptr) {
SLOGE("sessionItem is null when serviceCallback");
return;
}
sessionItem->SetServiceCallbackForRelease([this](AVSessionItem& session) {
HandleSessionRelease(session.GetDescriptor().sessionId_, true);
});
sessionItem->SetServiceCallbackForAVQueueInfo([this](AVSessionItem& session) {
AddAvQueueInfoToFile(session);
});
sessionItem->SetServiceCallbackForCallStart([this](AVSessionItem& session) {
HandleCallStartEvent();
});
sessionItem->SetServiceCallbackForUpdateSession([this](std::string sessionId, bool isAdd) {
if (sessionId == sessionCastState_) {
std::shared_ptr<std::list<sptr<AVSessionItem>>> sessionListForFront = GetCurSessionListForFront();
UpdateLocalFrontSession(sessionListForFront);
return;
}
std::lock_guard lockGuard(sessionServiceLock_);
sptr<AVSessionItem> session = GetUsersManager().GetContainerFromAll().GetSessionById(sessionId);
CHECK_AND_RETURN_LOG(session != nullptr, "session not exist for UpdateFrontSession.");
UpdateFrontSession(session, isAdd);
});
sessionItem->SetServiceCallbackForUpdateExtras([this](std::string sessionId) {
std::lock_guard lockGuard(sessionServiceLock_);
sptr<AVSessionItem> session = GetContainer().GetSessionById(sessionId);
CHECK_AND_RETURN_LOG(session != nullptr, "session not exist for UpdateFrontSession");
if (topSession_ && topSession_.GetRefPtr() == session.GetRefPtr()) {
NotifySystemUI(nullptr, IsCapsuleNeeded() && hasMediaCapsule_.load(), false);
}
});
AddCapsuleServiceCallback(sessionItem);
AddCastCapsuleServiceCallback(sessionItem);
AddKeyEventServiceCallback(sessionItem);
AddUpdateTopServiceCallback(sessionItem);
AddAncoColdStartServiceCallback(sessionItem);
AddCastServiceCallback(sessionItem);
}
sptr<AVSessionItem> AVSessionService::CreateNewSession(const std::string& tag, int32_t type, bool thirdPartyApp,
const AppExecFwk::ElementName& elementName)
{
HILOG_COMM_INFO("%{public}s %{public}d %{public}s %{public}s thirdPartyApp=%{public}d", tag.c_str(), type,
elementName.GetBundleName().c_str(), elementName.GetAbilityName().c_str(), thirdPartyApp);
AVSessionDescriptor descriptor;
descriptor.sessionId_ = AllocSessionId();
if (descriptor.sessionId_.empty()) {
SLOGE("alloc session id failed");
return nullptr;
}
int32_t userId = GetUserIdFromCallingUid(static_cast<int32_t>(GetCallingUid()));
descriptor.userId_ = userId;
descriptor.sessionTag_ = tag;
descriptor.sessionType_ = type;
descriptor.elementName_ = elementName;
descriptor.isThirdPartyApp_ = thirdPartyApp;
sptr<AVSessionItem> result = new(std::nothrow) AVSessionItem(descriptor, descriptor.userId_, this);
if (result == nullptr) {
return nullptr;
}
result->InitListener();
result->SetPid(GetCallingPid());
result->SetUid(GetCallingUid());
bool isSupported = false;
IsDesktopLyricSupported(isSupported);
result->SetDesktopLyricFeatureSupported(isSupported);
ServiceCallback(result);
if (controlListForNtf_.find(elementName.GetBundleName()) != controlListForNtf_.end()) {
SLOGI("AddControlBundle for :%{public}s ", elementName.GetBundleName().c_str());
focusSessionStrategy_.AddControlBundle(result->GetUid(), result->GetPid());
}
OutputDeviceInfo outputDeviceInfo;
DeviceInfo deviceInfo;
deviceInfo.castCategory_ = AVCastCategory::CATEGORY_LOCAL;
deviceInfo.deviceId_ = "0";
deviceInfo.deviceName_ = "LocalDevice";
outputDeviceInfo.deviceInfos_.emplace_back(deviceInfo);
result->SetOutputDevice(outputDeviceInfo);
return result;
}
bool AVSessionService::IsElementNameValid(const AppExecFwk::ElementName& elementName)
{
CHECK_AND_RETURN_RET_LOG(!elementName.GetBundleName().empty() && !elementName.GetAbilityName().empty(),
false, "bundleName:%{public}d or abilityName:%{public}d empty",
elementName.GetBundleName().empty(), elementName.GetAbilityName().empty());
std::regex nameRegex("[A-Za-z\\w\\.]*");
CHECK_AND_RETURN_RET_LOG(std::regex_match(elementName.GetBundleName(), nameRegex), false,
"err regex when check session, bundleName=%{public}s", (elementName.GetBundleName()).c_str());
CHECK_AND_RETURN_RET_LOG(std::regex_match(elementName.GetAbilityName(), nameRegex), false,
"err regex when check session, abilityName=%{public}s", (elementName.GetAbilityName()).c_str());
return true;
}
bool AVSessionService::IsParamInvalid(const std::string& tag, int32_t type, const AppExecFwk::ElementName& elementName)
{
if (tag.empty()) {
SLOGE("tag is empty when create session");
return false;
}
if (type != AVSession::SESSION_TYPE_AUDIO && type != AVSession::SESSION_TYPE_VIDEO
&& type != AVSession::SESSION_TYPE_VOICE_CALL && type != AVSession::SESSION_TYPE_VIDEO_CALL
&& type != AVSession::SESSION_TYPE_PHOTO) {
SLOGE("type is invalid when create session");
return false;
}
if (elementName.GetBundleName().empty() || elementName.GetAbilityName().empty()) {
SLOGE("element is invalid when create session");
return false;
}
CHECK_AND_RETURN_RET_LOG(GetCallingUid() != audioBrokerUid || tag != "ancoMediaSession", true, "anco not check");
CHECK_AND_RETURN_RET_LOG(IsElementNameValid(elementName), false, "element is invalid when check session");
return true;
}
void AVSessionService::CheckAndUpdateAncoMediaSession(const AppExecFwk::ElementName& elementName)
{
auto uid = GetCallingUid();
CHECK_AND_RETURN_LOG(uid == audioBrokerUid, "not broker uid");
sptr<AVSessionItem> session = GetContainer().GetSessionByUid(uid);
CHECK_AND_RETURN_LOG(session != nullptr, "anco media session is null");
auto res = GetUsersManager().UpdateSessionForCurrentUser(session->GetPid(), session->GetAbilityName(),
elementName.GetAbilityName(), session);
CHECK_AND_RETURN_LOG(res == AVSESSION_SUCCESS, "update media session fail");
session->UpdateSessionElement(elementName);
isAncoMediaSessionChange_ = true;
SLOGI("updatenewsession %{public}s %{public}s", elementName.GetBundleName().c_str(),
elementName.GetAbilityName().c_str());
}
void AVSessionService::AddExtraFrontSession(int32_t type, sptr<AVSessionItem>& sessionItem)
{
CHECK_AND_RETURN_LOG(sessionItem != nullptr, "AddExtraFrontSession sessionItem nullptr!");
std::lock_guard frontLockGuard(sessionFrontLock_);
int32_t userId = sessionItem->GetUserId();
std::shared_ptr<std::list<sptr<AVSessionItem>>> sessionListForFront = GetCurSessionListForFront(userId);
CHECK_AND_RETURN_LOG(sessionListForFront != nullptr, "AddExtraFrontSession sessionListForFront ptr nullptr!");
auto it = std::find(sessionListForFront->begin(), sessionListForFront->end(), sessionItem);
if ((type == AVSession::SESSION_TYPE_VOICE_CALL || type == AVSession::SESSION_TYPE_VIDEO_CALL) &&
it == sessionListForFront->end()) {
SLOGI(" front session add voice_call session=%{public}s", sessionItem->GetBundleName().c_str());
sessionListForFront->push_front(sessionItem);
NotifySessionChange(sessionListForFront, userId);
}
}
int32_t AVSessionService::GetSessionInner(const AppExecFwk::ElementName& elementName,
std::string& tag, sptr<IRemoteObject>& session)
{
CHECK_AND_RETURN_RET_LOG(IsElementNameValid(elementName), ERR_INVALID_PARAM, "elementName invalid");
auto pid = GetCallingPid();
auto uid = GetCallingUid();
std::lock_guard lockGuard(sessionServiceLock_);
int32_t userId = GetUserIdFromCallingUid(uid);
sptr<AVSessionItem> sessionWanted = GetUsersManager().GetContainerFromUser(userId).GetSessionByUid(uid);
CHECK_AND_RETURN_RET_LOG(sessionWanted != nullptr, ERR_SESSION_NOT_EXIST,
"process %{public}d:%{public}d has no session", pid, uid);
CHECK_AND_RETURN_RET_LOG(sessionWanted->GetPid() == pid, ERR_SESSION_NOT_EXIST,
"process pid not fit:%{public}d vs %{public}d", pid, sessionWanted->GetPid());
CHECK_AND_RETURN_RET_LOG(sessionWanted->GetBundleName() == elementName.GetBundleName(), ERR_SESSION_NOT_EXIST,
"process bundleName not fit:%{public}s vs %{public}s",
elementName.GetBundleName().c_str(), sessionWanted->GetBundleName().c_str());
SLOGI("GetSession success:%{public}d:%{public}d|%{public}s|%{public}s", pid, uid,
elementName.GetBundleName().c_str(), sessionWanted->GetSessionTag().c_str());
session = sessionWanted;
tag = sessionWanted->GetSessionTag();
return AVSESSION_SUCCESS;
}
void AVSessionService::RefreshUserFromAnco(const std::string& tag, const AppExecFwk::ElementName& elementName)
{
bool isBroker = (tag == "ancoMediaSession") && (GetCallingUid() == audioBrokerUid);
bool isAnco = (tag == "anco_audio") && (GetCallingUid() == ancoUid);
CHECK_AND_RETURN_LOG((isBroker || isAnco) && !elementName.GetDeviceID().empty(), "RefreshUserFromAnco return");
std::string deviceIdStr = elementName.GetDeviceID();
char* endptr{};
errno = 0;
long deviceIdLong = std::strtol(deviceIdStr.c_str(), &endptr, 10);
CHECK_AND_RETURN_LOG(endptr != deviceIdStr.c_str(),
"RefreshUserFromAnco returns, DeviceID is not valid char number.");
CHECK_AND_RETURN_LOG(*endptr == '\0',
"RefreshUserFromAnco returns, DeviceID contains non-number char.");
CHECK_AND_RETURN_LOG(!(errno == ERANGE && (deviceIdLong == LONG_MIN || deviceIdLong == LONG_MAX)),
"RefreshUserFromAnco returns, DeviceID is not in valid long type number range.");
CHECK_AND_RETURN_LOG(deviceIdLong >= INT32_MIN && deviceIdLong <= INT32_MAX,
"RefreshUserFromAnco returns, DeviceID is not in valid int32 type number range.");
int32_t ancoUserId = static_cast<int32_t>(deviceIdLong);
CHECK_AND_RETURN_LOG(GetUsersManager().GetCurrentUserId() != ancoUserId, "RefreshUserFromAnco same user, return");
SLOGI("RefreshUserFromAnco to: %{public}d", ancoUserId);
HandleUserEvent(AVSessionUsersManager::accountEventSwitched, ancoUserId);
}
AppExecFwk::ElementName AVSessionService::CorrectElementForThirdPartyCaller(bool thirdPartyApp,
const AppExecFwk::ElementName& elementName)
{
CHECK_AND_RETURN_RET_LOG(thirdPartyApp, elementName, "not thirdPartyApp, no need correct element");
int32_t callingUid = GetCallingUid();
std::string identity = IPCSkeleton::ResetCallingIdentity();
std::string realBundleName = BundleStatusAdapter::GetInstance().GetBundleNameFromUid(callingUid);
IPCSkeleton::SetCallingIdentity(identity);
CHECK_AND_RETURN_RET_LOG(!realBundleName.empty(), elementName,
"get real bundleName failed, uid:%{public}d, keep origin element", callingUid);
CHECK_AND_RETURN_RET_LOG(realBundleName != elementName.GetBundleName(), elementName,
"bundleName matched, no need correct element");
AppExecFwk::ElementName corrected = elementName;
corrected.SetBundleName(realBundleName);
identity = IPCSkeleton::ResetCallingIdentity();
std::string defaultAbilityName = BundleStatusAdapter::GetInstance().GetDefaultAbilityName(realBundleName,
GetUserIdFromCallingUid(callingUid));
IPCSkeleton::SetCallingIdentity(identity);
CHECK_AND_RETURN_RET_LOG(!defaultAbilityName.empty(), corrected,
"get default abilityName failed, bundleName:%{public}s to:%{public}s, uid:%{public}d, "
"keep origin abilityName",
elementName.GetBundleName().c_str(), realBundleName.c_str(), callingUid);
corrected.SetAbilityName(defaultAbilityName);
SLOGW("correct session element bundleName:%{public}s to:%{public}s, uid:%{public}d",
elementName.GetBundleName().c_str(), realBundleName.c_str(), callingUid);
return corrected;
}
int32_t AVSessionService::CreateSessionInner(const std::string& tag, int32_t type, bool thirdPartyApp,
const AppExecFwk::ElementName& elementName,
sptr<AVSessionItem>& sessionItem)
{
if (!IsParamInvalid(tag, type, elementName)) {
AudioStandard::StreamDfxManager::GetInstance().SendAudioErrorEvent(static_cast<int32_t>(getuid()),
AudioStandard::AVSESSION_CONTROL_INVALID_PARAM_LOCAL_SET, "param invalid", false);
return ERR_INVALID_PARAM;
}
RefreshUserFromAnco(tag, elementName);
AppExecFwk::ElementName sessionElement = CorrectElementForThirdPartyCaller(thirdPartyApp, elementName);
auto pid = GetCallingPid();
int32_t userId = GetUserIdFromCallingUid(static_cast<int32_t>(GetCallingUid()));
std::lock_guard lockGuard(sessionServiceLock_);
if (AbilityHasSession(pid, userId)) {
SLOGE("process %{public}d %{public}s already has one session.", pid, elementName.GetAbilityName().c_str());
CheckAndUpdateAncoMediaSession(elementName);
AudioStandard::StreamDfxManager::GetInstance().SendAudioErrorEvent(static_cast<int32_t>(getuid()),
AudioStandard::AVSESSION_CONTROL_SESSION_IS_EXIST_LOCAL_SET, "process already has one session", false);
return ERR_SESSION_IS_EXIST;
}
sptr<AVSessionItem> result = CreateNewSession(tag, type, thirdPartyApp, sessionElement);
if (result == nullptr) {
SLOGE("create new session failed");
if (dumpHelper_ != nullptr) dumpHelper_->SetErrorInfo("CreateSessionInner create new session failed");
HISYSEVENT_FAULT("CONTROL_COMMAND_FAILED", "CALLER_PID", pid, "TAG", tag, "TYPE", type, "BUNDLE_NAME",
elementName.GetBundleName(), "ERROR_MSG", "avsessionservice createsessioninner create new session failed");
AudioStandard::StreamDfxManager::GetInstance().SendAudioErrorEvent(static_cast<int32_t>(getuid()),
AudioStandard::AVSESSION_CONTROL_NO_MEMORY_LOCAL_SET, "create new session failed", false);
return ERR_NO_MEMORY;
}
CHECK_AND_RETURN_RET_LOG(
GetUsersManager().AddSessionForCurrentUser(pid, sessionElement.GetAbilityName(), result, userId)
== AVSESSION_SUCCESS, ERR_SESSION_EXCEED_MAX, "session num exceed max");
SetCriticalWhenCreate(result);
HISYSEVENT_ADD_LIFE_CYCLE_INFO(sessionElement.GetBundleName(),
AppManagerAdapter::GetInstance().IsAppBackground(GetCallingUid(), GetCallingPid()), type, true);
NotifySessionCreate(result->GetDescriptor());
#ifdef CAR_FEATURE_ENABLE
NotifySessionAddForAudioZone(result->GetDescriptor());
#endif
sessionItem = result;
AddExtraFrontSession(type, sessionItem);
if (sessionItem->GetUid() == ancoUid && IsLocalSessionPlaying(sessionItem)) {
ancoSession_ = sessionItem;
UpdateSessionTimestamp(ancoSession_);
SLOGI("CreateSessionInner updateancoSession");
}
#ifdef ENABLE_AVSESSION_SYSEVENT_CONTROL
ReportSessionState(sessionItem, SessionState::STATE_CREATE);
#endif
return AVSESSION_SUCCESS;
}
void AVSessionService::SetCriticalWhenCreate(sptr<AVSessionItem> sessionItem)
{
uint32_t currentAllSessionSize = GetUsersManager().GetContainerFromAll().GetAllSessions().size();
SLOGI("size: %{public}u, Uid: %{public}d", currentAllSessionSize, sessionItem->GetUid());
if (currentAllSessionSize == 1) {
if (sessionItem->GetUid() == ancoUid) {
SetCritical(false);
} else {
SetCritical(true);
}
} else if (currentAllSessionSize > 1) {
SetCritical(true);
}
}
sptr<AVSessionItem> AVSessionService::CreateSessionInner(const std::string& tag, int32_t type, bool thirdPartyApp,
const AppExecFwk::ElementName& elementName)
{
sptr<AVSessionItem> sessionItem;
auto res = CreateSessionInner(tag, type, thirdPartyApp, elementName, sessionItem);
CHECK_AND_RETURN_RET_LOG(res == AVSESSION_SUCCESS, nullptr, "create avSessionItem failed");
return sessionItem;
}
void AVSessionService::ReportSessionInfo(const sptr <AVSessionItem>& session, int32_t res)
{
std::string sessionId = "";
std::string sessionTag = "";
std::string sessionType = "";
std::string bundleName = "";
std::string apiParamString = "";
if (session != nullptr) {
sessionId = AVSessionUtils::GetAnonySessionId(session->GetDescriptor().sessionId_);
sessionTag = session->GetDescriptor().sessionTag_;
sessionType = session->GetSessionType();
bundleName = session->GetDescriptor().elementName_.GetBundleName();
apiParamString = "abilityName: " +
session->GetDescriptor().elementName_.GetAbilityName() + ","
+ "moduleName: " + session->GetDescriptor().elementName_.GetModuleName();
}
std::string errMsg = (res == AVSESSION_SUCCESS) ? "SUCCESS" : "create session failed";
HISYSEVENT_BEHAVIOR("SESSION_API_BEHAVIOR",
"API_NAME", "CreateSession",
"BUNDLE_NAME", bundleName,
"SESSION_ID", sessionId,
"SESSION_TAG", sessionTag,
"SESSION_TYPE", sessionType,
"API_PARAM", apiParamString,
"ERROR_CODE", res,
"ERROR_MSG", errMsg);
}
int32_t AVSessionService::CreateSessionInner(const std::string& tag, int32_t type,
const AppExecFwk::ElementName& elementName,
sptr<IRemoteObject>& object)
{
sptr<AVSessionItem> session;
auto res = CreateSessionInner(tag, type,
PermissionChecker::GetInstance().CheckPermission(PermissionChecker::CHECK_SYSTEM_PERMISSION),
elementName, session);
CHECK_AND_RETURN_RET_LOG(res == AVSESSION_SUCCESS, res, "create session fail");
std::string supportModule;
std::string profile;
if (BundleStatusAdapter::GetInstance().IsSupportPlayIntent(elementName.GetBundleName(), supportModule, profile)) {
{
std::lock_guard lockGuard(controlListLock_);
CHECK_AND_RETURN_RET_LOG(
controlBundleNameSet_.find(elementName.GetBundleName()) == controlBundleNameSet_.end(),
AVSESSION_SUCCESS, "session is in controlList, dont add to history");
}
SLOGI("bundleName=%{public}s support play intent, refreshSortFile", elementName.GetBundleName().c_str());
SaveSessionInfoInFile(tag, session->GetSessionId(), session->GetSessionType(), elementName);
}
{
std::lock_guard lockGuard1(abilityManagerLock_);
std::string bundleName = session->GetDescriptor().elementName_.GetBundleName();
std::string abilityName = session->GetDescriptor().elementName_.GetAbilityName();
auto it = abilityManager_.find(bundleName + abilityName);
if (it != abilityManager_.end() && it->second != nullptr) {
it->second->StartAbilityByCallDone(session->GetDescriptor().sessionId_);
}
}
object = session;
ReportSessionInfo(session, static_cast<int32_t>(res));
{
std::lock_guard lockGuard(isAllSessionCastLock_);
CHECK_AND_RETURN_RET_LOG(isAllSessionCast_, AVSESSION_SUCCESS, "no need to cast");
}
CHECK_AND_RETURN_RET_LOG(CastAudioForNewSession(session) == AVSESSION_SUCCESS,
AVSESSION_SUCCESS, "cast new session error");
return res;
}
sptr <IRemoteObject> AVSessionService::CreateSessionInner(const std::string& tag, int32_t type,
const AppExecFwk::ElementName& elementName)
{
sptr<IRemoteObject> object;
auto res = CreateSessionInner(tag, type, elementName, object);
CHECK_AND_RETURN_RET_LOG(res == AVSESSION_SUCCESS, nullptr, "create session fail");
return object;
}
// LCOV_EXCL_START
bool AVSessionService::InsertSessionItemToCJSONAndPrint(const std::string& tag, const std::string& sessionId,
const std::string& sessionType, const AppExecFwk::ElementName& elementName, cJSON* valuesArray)
{
CHECK_AND_RETURN_RET_LOG(valuesArray != nullptr, false, "valuesArray get null");
cJSON* newValue = cJSON_CreateObject();
CHECK_AND_RETURN_RET_LOG(newValue != nullptr, false, "newValue get null");
cJSON_AddStringToObject(newValue, "sessionId", sessionId.c_str());
std::string bundleName = elementName.GetBundleName();
sptr<AVSessionItem> session = GetContainer().GetSessionById(sessionId);
if ((session != nullptr) && (session->GetAppIndex() != 0)) {
bundleName = bundleName + "_" + std::to_string(session->GetAppIndex());
}
cJSON_AddStringToObject(newValue, "bundleName", bundleName.c_str());
cJSON_AddStringToObject(newValue, "abilityName", elementName.GetAbilityName().c_str());
cJSON_AddStringToObject(newValue, "sessionType", sessionType.c_str());
cJSON_AddStringToObject(newValue, "sessionTag", tag.c_str());
if (cJSON_GetArraySize(valuesArray) <= 0) {
cJSON_AddItemToArray(valuesArray, newValue);
} else {
cJSON_InsertItemInArray(valuesArray, 0, newValue);
}
if (cJSON_IsInvalid(valuesArray)) {
SLOGE("get newValueArray invalid");
return false;
}
std::string newSortContentStr = DoCJSONArrayTransformToString(valuesArray);
if (!SaveStringToFileEx(GetAVSortDir(), newSortContentStr)) {
SLOGE("SaveStringToFileEx failed when refresh focus session sort!");
}
return true;
}
// LCOV_EXCL_STOP
// LCOV_EXCL_START
void AVSessionService::SubscribeBundleStatusIfNeeded(const std::string& oldSortContent, const std::string& bundleName)
{
if (oldSortContent.find(bundleName) == std::string::npos) {
auto callback = [this](std::string bundleName, int32_t userId) {
SLOGI("recv delete bundle:%{public}s at user:%{public}d", bundleName.c_str(), userId);
DeleteAVQueueInfoRecord(bundleName, userId);
DeleteHistoricalRecord(bundleName, userId);
NotifyHistoricalRecordChange(bundleName, userId);
};
if (!BundleStatusAdapter::GetInstance().SubscribeBundleStatusEvent(bundleName,
callback, GetUsersManager().GetCurrentUserId())) {
SLOGE("SubscribeBundleStatusEvent failed");
}
}
}
void AVSessionService::SaveSessionInfoInFile(const std::string& tag, const std::string& sessionId,
const std::string& sessionType, const AppExecFwk::ElementName& elementName)
{
std::lock_guard sortFileLockGuard(sessionFileLock_);
SLOGI("refresh sort when session created, bundleName=%{public}s", (elementName.GetBundleName()).c_str());
std::string oldSortContent;
if (LoadStringFromFileEx(GetAVSortDir(), oldSortContent)) {
cJSON* valuesArray = cJSON_Parse(oldSortContent.c_str());
CHECK_AND_RETURN_LOG(valuesArray != nullptr, "parse json get nullptr");
if (cJSON_IsInvalid(valuesArray) || !cJSON_IsArray(valuesArray)) {
SLOGE("parse json not valid");
cJSON_Delete(valuesArray);
valuesArray = cJSON_CreateArray();
CHECK_AND_RETURN_LOG(valuesArray != nullptr, "create array json fail");
}
std::string bundleName = elementName.GetBundleName();
sptr<AVSessionItem> session = GetContainer().GetSessionById(sessionId);
if ((session != nullptr) && (session->GetAppIndex() != 0)) {
bundleName = bundleName + "_" + std::to_string(session->GetAppIndex());
}
SubscribeBundleStatusIfNeeded(oldSortContent, bundleName);
int arraySize = cJSON_GetArraySize(valuesArray);
for (int i = arraySize - 1; i >= 0; --i) {
cJSON* itemToDelete = cJSON_GetArrayItem(valuesArray, i);
CHECK_AND_CONTINUE(itemToDelete != nullptr && !cJSON_IsInvalid(itemToDelete));
cJSON* bundleNameItem = cJSON_GetObjectItem(itemToDelete, "bundleName");
cJSON* abilityNameItem = cJSON_GetObjectItem(itemToDelete, "abilityName");
if (bundleNameItem == nullptr || cJSON_IsInvalid(bundleNameItem) || !cJSON_IsString(bundleNameItem) ||
abilityNameItem == nullptr || cJSON_IsInvalid(abilityNameItem) || !cJSON_IsString(abilityNameItem)) {
SLOGI("not contain bundleName or abilityName, pass");
continue;
}
if (strcmp(bundleName.c_str(), bundleNameItem->valuestring) == 0 &&
strcmp(elementName.GetAbilityName().c_str(), abilityNameItem->valuestring) == 0) {
cJSON_DeleteItemFromArray(valuesArray, i);
}
}
InsertSessionItemToCJSONAndPrint(tag, sessionId, sessionType, elementName, valuesArray);
cJSON_Delete(valuesArray);
} else {
SLOGE("LoadStringToFile failed, filename=%{public}s", SORT_FILE_NAME);
}
}
int32_t AVSessionService::UpdateControlListFromFile()
{
std::lock_guard lockGuard(controlListLock_);
std::string controlListContent;
bool isFileLoad = LoadStringFromFileEx(controlListFile, controlListContent);
CHECK_AND_RETURN_RET_LOG(isFileLoad, AVSESSION_ERROR, "UpdateControlListFromFile read file fail, Return!");
cJSON* appValuesArray = cJSON_Parse(controlListContent.c_str());
CHECK_AND_RETURN_RET_LOG(appValuesArray != nullptr && !cJSON_IsInvalid(appValuesArray) &&
cJSON_IsArray(appValuesArray), AVSESSION_ERROR, "controlList parse json not valid");
cJSON* valueItem = nullptr;
cJSON_ArrayForEach(valueItem, appValuesArray) {
cJSON* bundleNameItem = cJSON_GetObjectItem(valueItem, "bundleName");
CHECK_AND_CONTINUE_LOG(bundleNameItem != nullptr &&
!cJSON_IsInvalid(bundleNameItem) && cJSON_IsString(bundleNameItem), "controlList get bundleName fail");
controlBundleNameSet_.insert(bundleNameItem->valuestring);
}
cJSON_Delete(appValuesArray);
return AVSESSION_SUCCESS;
}
// LCOV_EXCL_STOP
int32_t AVSessionService::GetAllSessionDescriptors(std::vector<AVSessionDescriptor>& descriptors)
{
std::string topSessionName;
{
std::lock_guard lockGuard(sessionServiceLock_);
topSessionName = (topSession_ == nullptr ? "null" : topSession_->GetBundleName());
}
std::lock_guard frontLockGuard(sessionFrontLock_);
int32_t userId = GetUserIdFromCallingUid(static_cast<int32_t>(GetCallingUid()));
std::shared_ptr<std::list<sptr<AVSessionItem>>> sessionListForFront = GetCurSessionListForFront(userId);
CHECK_AND_RETURN_RET_LOG(sessionListForFront != nullptr, AVSESSION_ERROR, "sessionListForFront ptr nullptr!");
for (const auto& session : *sessionListForFront) {
if (session != nullptr) {
descriptors.push_back(session->GetDescriptor());
}
}
SLOGI("GetAllSessionDescriptors for user:%{public}d with size=%{public}d, topSession:%{public}s",
userId, static_cast<int32_t>(descriptors.size()), topSessionName.c_str());
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::GetNotActiveSession(std::vector<AVSessionDescriptor>& descriptors)
{
std::lock_guard frontLockGuard(sessionFrontLock_);
int32_t userId = GetUserIdFromCallingUid(static_cast<int32_t>(GetCallingUid()));
std::shared_ptr<std::list<sptr<AVSessionItem>>> sessionListForFront = GetCurSessionListForFront(userId);
CHECK_AND_RETURN_RET_LOG(sessionListForFront != nullptr, AVSESSION_ERROR, "sessionListForFront ptr nullptr!");
auto containerPtr = GetUsersManager().GetContainerPtrFromUser(userId);
CHECK_AND_RETURN_RET_LOG(containerPtr != nullptr, AVSESSION_ERROR, "get containerPtr null");
for (const auto& session : containerPtr->GetAllSessions()) {
if (session != nullptr) {
auto it = std::find(sessionListForFront->begin(), sessionListForFront->end(), session);
if (it == sessionListForFront->end()) {
AVSessionDescriptor descriptor = session->GetDescriptor();
descriptors.push_back(descriptor);
}
}
}
SLOGI("GetNotActiveSession for user:%{public}d", userId);
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::GetSessionDescriptors(int32_t category, std::vector<AVSessionDescriptor>& descriptors)
{
auto containerPtr = GetUsersManager().GetContainerPtrFromUser(
GetUserIdFromCallingUid(static_cast<int32_t>(GetCallingUid())));
switch (category) {
case SessionCategory::CATEGORY_ACTIVE:
GetAllSessionDescriptors(descriptors);
break;
case SessionCategory::CATEGORY_NOT_ACTIVE:
GetNotActiveSession(descriptors);
break;
case SessionCategory::CATEGORY_ALL:
CHECK_AND_RETURN_RET_LOG(containerPtr != nullptr, AVSESSION_ERROR, "get containerPtr null");
for (const auto& session : containerPtr->GetAllSessions()) {
if (session != nullptr) {
AVSessionDescriptor descriptor = session->GetDescriptor();
descriptors.push_back(descriptor);
}
}
break;
# ifdef CASTPLUS_CAST_ENGINE_ENABLE
case SessionCategory::CATEGORY_HIPLAY:
if (pcmCastSession_ != nullptr && pcmCastSession_->CheckIsCasting()) {
AVSessionDescriptor descriptor = pcmCastSession_->GetDescriptor();
descriptors.push_back(descriptor);
}
break;
#endif //CASTPLUS_CAST_ENGINE_ENABLE
default:
SLOGE("undefined category %{public}d", category);
}
SLOGI("GetSessionDescriptors with size=%{public}d, category:%{public}d",
static_cast<int32_t>(descriptors.size()), category);
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::GetSessionDescriptorsBySessionId(const std::string& sessionId,
AVSessionDescriptor& descriptor)
{
std::lock_guard lockGuard(sessionServiceLock_);
int32_t userId = GetUserIdFromCallingUid(static_cast<int32_t>(GetCallingUid()));
sptr<AVSessionItem> session = GetUsersManager().GetContainerFromUser(userId).GetSessionById(sessionId);
CHECK_AND_RETURN_RET_LOG(session != nullptr, AVSESSION_ERROR, "session to be got is not existed");
auto pid = GetCallingPid();
auto uid = GetCallingUid();
if (pid == session->GetPid() && uid == session->GetUid()) {
descriptor = session->GetDescriptor();
return AVSESSION_SUCCESS;
}
int32_t err = PermissionChecker::GetInstance().CheckPermission(PermissionChecker::CHECK_SYSTEM_PERMISSION);
if (err != ERR_NONE) {
SLOGE("GetSessionDescriptorsBySessionId: CheckPermission failed!");
HISYSEVENT_SECURITY("CONTROL_PERMISSION_DENIED", "CALLER_UID", uid,
"CALLER_PID", pid, "SESSION_ID", sessionId,
"ERROR_MSG", "avsessionservice getsessiondescriptors by sessionid checkpermission failed");
return err;
}
descriptor = session->GetDescriptor();
return AVSESSION_SUCCESS;
}
void AVSessionService::ProcessDescriptorsFromCJSON(std::vector<AVSessionDescriptor>& descriptors, cJSON* valueItem)
{
CHECK_AND_RETURN_LOG(valueItem != nullptr && !cJSON_IsInvalid(valueItem), "valueItem get invalid");
cJSON* sessionIdItem = cJSON_GetObjectItem(valueItem, "sessionId");
if (sessionIdItem == nullptr || cJSON_IsInvalid(sessionIdItem) || !cJSON_IsString(sessionIdItem)) {
SLOGE("valueItem get sessionId fail");
return;
}
std::string sessionId(sessionIdItem->valuestring);
cJSON* bundleNameItem = cJSON_GetObjectItem(valueItem, "bundleName");
if (bundleNameItem == nullptr || cJSON_IsInvalid(bundleNameItem) || !cJSON_IsString(bundleNameItem)) {
SLOGE("valueItem get bundleName fail");
return;
}
std::string bundleName(bundleNameItem->valuestring);
{
std::lock_guard lockGuard(controlListLock_);
CHECK_AND_RETURN_LOG(controlBundleNameSet_.find(bundleName) == controlBundleNameSet_.end(),
"session is in controlList, dont add to history");
}
cJSON* abilityNameItem = cJSON_GetObjectItem(valueItem, "abilityName");
if (abilityNameItem == nullptr || cJSON_IsInvalid(abilityNameItem) || !cJSON_IsString(abilityNameItem)) {
SLOGE("valueItem get abilityName fail");
return;
}
std::string abilityName(abilityNameItem->valuestring);
std::string tag("");
cJSON* tagItem = cJSON_GetObjectItem(valueItem, "sessionTag");
if (tagItem == nullptr || cJSON_IsInvalid(tagItem) || !cJSON_IsString(tagItem)) {
SLOGE("valueItem get sessiontag fail, continue");
} else {
tag = tagItem->valuestring;
}
AVSessionDescriptor descriptor;
descriptor.sessionId_ = sessionId;
descriptor.elementName_.SetBundleName(std::string(bundleNameItem->valuestring));
descriptor.elementName_.SetAbilityName(std::string(abilityNameItem->valuestring));
descriptor.sessionTag_ = tag;
if (tag == "ancoMediaSession") {
std::lock_guard localGuard(audioBrokerLock_);
SLOGI("audio broker sa status %{public}d", isAudioBrokerStart_);
if (isAudioBrokerStart_) {
descriptors.push_back(descriptor);
}
} else {
descriptors.push_back(descriptor);
}
}
int32_t AVSessionService::GetHistoricalSessionDescriptorsFromFile(std::vector<AVSessionDescriptor>& descriptors)
{
std::string oldSortContent;
int32_t userId = GetUserIdFromCallingUid(static_cast<int32_t>(GetCallingUid()));
SLOGI("getHistoryFile for:%{public}d", userId);
if (!LoadStringFromFileEx(GetAVSortDir(userId), oldSortContent)) {
SLOGE("GetHistoricalSessionDescriptorsFromFile read sort fail, Return!");
return AVSESSION_ERROR;
}
cJSON* sortValuesArray = cJSON_Parse(oldSortContent.c_str());
CHECK_AND_RETURN_RET_LOG(sortValuesArray != nullptr, AVSESSION_ERROR, "json object is null");
if (cJSON_IsInvalid(sortValuesArray) || !cJSON_IsArray(sortValuesArray)) {
SLOGE("parse json not valid");
cJSON_Delete(sortValuesArray);
return AVSESSION_ERROR;
}
cJSON* valueItem = nullptr;
cJSON_ArrayForEach(valueItem, sortValuesArray) {
ProcessDescriptorsFromCJSON(descriptors, valueItem);
}
if (descriptors.size() == 0 && GetUsersManager().GetContainerFromUser(userId).GetAllSessions().size() == 0) {
SLOGE("GetHistoricalSessionDescriptorsFromFile read empty, return!");
}
cJSON_Delete(sortValuesArray);
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::GetColdStartSessionDescriptors(std::vector<AVSessionDescriptor>& descriptors)
{
std::lock_guard sortFileLockGuard(sessionFileLock_);
std::vector<AVSessionDescriptor> tempDescriptors;
GetHistoricalSessionDescriptorsFromFile(tempDescriptors);
for (auto iterator = tempDescriptors.begin(); iterator != tempDescriptors.end(); ++iterator) {
descriptors.push_back(*iterator);
}
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::GetHistoricalSessionDescriptors(int32_t maxSize,
std::vector<AVSessionDescriptor>& descriptors)
{
std::lock_guard sortFileLockGuard(sessionFileLock_);
std::vector<AVSessionDescriptor> tempDescriptors;
int32_t userId = GetUserIdFromCallingUid(static_cast<int32_t>(GetCallingUid()));
GetHistoricalSessionDescriptorsFromFile(tempDescriptors);
bool isNeedAllAnco = maxSize == mediaControlAncoParam;
if (maxSize < 0 || maxSize > maxHistoryNums_) {
maxSize = unSetHistoryNum;
}
for (auto iterator = tempDescriptors.begin(); iterator != tempDescriptors.end(); ++iterator) {
if (descriptors.size() >= static_cast<size_t>(maxSize)) {
break;
}
std::string sessionId(iterator->sessionId_);
auto session = GetUsersManager().GetContainerFromUser(userId).GetSessionById(sessionId);
bool checkIfContinue = session != nullptr &&
(!isNeedAllAnco || (session->GetSessionTag() != "ancoMediaSession" ||
session->GetBundleName() == iterator->elementName_.GetBundleName()));
if (checkIfContinue) {
SLOGE("GetHistoricalSessionDescriptorsFromFile find session alive, sessionId=%{public}s",
AVSessionUtils::GetAnonySessionId(sessionId).c_str());
continue;
}
descriptors.push_back(*iterator);
}
return AVSESSION_SUCCESS;
}
// LCOV_EXCL_START
void AVSessionService::ProcessAvQueueInfosFromCJSON(std::vector<AVQueueInfo>& avQueueInfos, cJSON* valueItem)
{
CHECK_AND_RETURN_LOG(valueItem != nullptr && !cJSON_IsInvalid(valueItem), "get valueItem invalid");
cJSON* bundleNameItem = cJSON_GetObjectItem(valueItem, "bundleName");
if (bundleNameItem == nullptr || cJSON_IsInvalid(bundleNameItem) || !cJSON_IsString(bundleNameItem)) {
SLOGE("valueItem get bundleName fail");
return;
}
cJSON* avQueueNameItem = cJSON_GetObjectItem(valueItem, "avQueueName");
if (avQueueNameItem == nullptr || cJSON_IsInvalid(avQueueNameItem) || !cJSON_IsString(avQueueNameItem)) {
SLOGE("valueItem get avQueueName fail");
return;
}
cJSON* avQueueIdItem = cJSON_GetObjectItem(valueItem, "avQueueId");
if (avQueueIdItem == nullptr || cJSON_IsInvalid(avQueueIdItem) || !cJSON_IsString(avQueueIdItem)) {
SLOGE("valueItem get avQueueId fail");
return;
}
cJSON* imageDirItem = cJSON_GetObjectItem(valueItem, "avQueueImageDir");
if (imageDirItem == nullptr || cJSON_IsInvalid(imageDirItem) || !cJSON_IsString(imageDirItem)) {
SLOGE("valueItem get avQueueImageDir fail");
return;
}
cJSON* imageNameItem = cJSON_GetObjectItem(valueItem, "avQueueImageName");
if (imageNameItem == nullptr || cJSON_IsInvalid(imageNameItem) || !cJSON_IsString(imageNameItem)) {
SLOGE("valueItem get avQueueImageName fail");
return;
}
cJSON* imageUri = cJSON_GetObjectItem(valueItem, "avQueueImageUri");
if (imageUri == nullptr || cJSON_IsInvalid(imageUri) || !cJSON_IsString(imageUri)) {
SLOGE("valueItem get avQueueImageUri fail");
return;
}
AVQueueInfo avQueueInfo;
avQueueInfo.SetBundleName(std::string(bundleNameItem->valuestring));
avQueueInfo.SetAVQueueName(std::string(avQueueNameItem->valuestring));
avQueueInfo.SetAVQueueId(std::string(avQueueIdItem->valuestring));
std::shared_ptr<AVSessionPixelMap> avQueuePixelMap = std::make_shared<AVSessionPixelMap>();
AVSessionUtils::ReadImageFromFile(avQueuePixelMap, std::string(imageDirItem->valuestring),
std::string(imageNameItem->valuestring));
avQueueInfo.SetAVQueueImage(avQueuePixelMap);
avQueueInfo.SetAVQueueImageUri(std::string(imageUri->valuestring));
avQueueInfos.push_back(avQueueInfo);
}
// LCOV_EXCL_STOP
// LCOV_EXCL_START
int32_t AVSessionService::GetHistoricalAVQueueInfos(int32_t maxSize, int32_t maxAppSize,
std::vector<AVQueueInfo>& avQueueInfos)
{
std::lock_guard avQueueFileLockGuard(avQueueFileLock_);
std::string oldAVQueueInfoContent;
std::vector<AVQueueInfo> tempAVQueueInfos;
if (!LoadStringFromFileEx(GetAVQueueDir(), oldAVQueueInfoContent)) {
SLOGE("GetHistoricalAVQueueInfos read avqueueinfo fail, Return!");
return AVSESSION_ERROR;
}
SLOGD("GetHistoricalAVQueueInfos with size:%{public}d limit:%{public}d", maxSize, maxAVQueueInfoLen);
maxSize = maxAVQueueInfoLen >= maxSize ? maxSize : maxAVQueueInfoLen;
cJSON* avQueueValuesArray = cJSON_Parse(oldAVQueueInfoContent.c_str());
CHECK_AND_RETURN_RET_LOG(avQueueValuesArray != nullptr, AVSESSION_ERROR, "json object is null");
if (cJSON_IsInvalid(avQueueValuesArray) || !cJSON_IsArray(avQueueValuesArray)) {
SLOGE("parse json not valid");
cJSON_Delete(avQueueValuesArray);
return AVSESSION_ERROR;
}
cJSON* valueItem = nullptr;
cJSON_ArrayForEach(valueItem, avQueueValuesArray) {
ProcessAvQueueInfosFromCJSON(tempAVQueueInfos, valueItem);
if (static_cast<int>(tempAVQueueInfos.size()) >= maxSize) {
break;
}
}
for (auto iterator = tempAVQueueInfos.begin(); iterator != tempAVQueueInfos.end(); ++iterator) {
avQueueInfos.push_back(*iterator);
}
SLOGI("GetHistoricalAVQueue size:%{public}d Limit:%{public}d", static_cast<int>(avQueueInfos.size()), maxSize);
cJSON_Delete(avQueueValuesArray);
return AVSESSION_SUCCESS;
}
// LCOV_EXCL_STOP
// LCOV_EXCL_START
bool AVSessionService::InsertAvQueueInfoToCJSONAndPrint(const std::string &bundleName,
const AVMetaData& meta, const int32_t userId, cJSON* valuesArray)
{
CHECK_AND_RETURN_RET_LOG(valuesArray != nullptr, false, "get valuesArray nullptr");
cJSON* newValue = cJSON_CreateObject();
cJSON_AddStringToObject(newValue, "bundleName", bundleName.c_str());
cJSON_AddStringToObject(newValue, "avQueueName", meta.GetAVQueueName().c_str());
cJSON_AddStringToObject(newValue, "avQueueId", meta.GetAVQueueId().c_str());
std::shared_ptr<AVSessionPixelMap> innerPixelMap = meta.GetAVQueueImage();
std::string fileDir = AVSessionUtils::GetFixedPathName(userId);
std::string fileName = bundleName + "_" + meta.GetAVQueueId() + AVSessionUtils::GetFileSuffix();
if (innerPixelMap != nullptr) {
AVSessionUtils::WriteImageToFile(innerPixelMap, fileDir, fileName);
innerPixelMap->Clear();
}
cJSON_AddStringToObject(newValue, "avQueueImageDir", fileDir.c_str());
cJSON_AddStringToObject(newValue, "avQueueImageName", fileName.c_str());
cJSON_AddStringToObject(newValue, "avQueueImageUri", meta.GetAVQueueImageUri().c_str());
if (cJSON_IsInvalid(newValue)) {
SLOGE("get newValue nullptr");
cJSON_Delete(newValue);
return false;
}
if (cJSON_IsInvalid(valuesArray)) {
SLOGE("get valuesArray invalid");
cJSON_Delete(newValue);
return false;
}
if (cJSON_GetArraySize(valuesArray) <= 0) {
cJSON_AddItemToArray(valuesArray, newValue);
} else {
cJSON_InsertItemInArray(valuesArray, 0, newValue);
}
char* newAvqueueContent = cJSON_Print(valuesArray);
if (newAvqueueContent == nullptr) {
SLOGE("newValueArray print fail");
return false;
}
std::string newAvqueueContentStr(newAvqueueContent);
if (!SaveStringToFileEx(GetAVQueueDir(userId), newAvqueueContentStr)) {
SLOGE("SaveStringToFileEx failed when refresh focus session sort!");
cJSON_free(newAvqueueContent);
return false;
}
cJSON_free(newAvqueueContent);
return true;
}
// LCOV_EXCL_STOP
// LCOV_EXCL_START
bool AVSessionService::SaveAvQueueInfo(std::string& oldContent, const std::string &bundleName,
const AVMetaData& meta, const int32_t userId)
{
cJSON* valuesArray = cJSON_Parse(oldContent.c_str());
CHECK_AND_RETURN_RET_LOG(valuesArray != nullptr, false, "json parse get nullptr");
if (cJSON_IsInvalid(valuesArray) || !cJSON_IsArray(valuesArray)) {
SLOGE("get value array invalid but createNew");
cJSON_Delete(valuesArray);
valuesArray = nullptr;
valuesArray = cJSON_CreateArray();
CHECK_AND_RETURN_RET_LOG(valuesArray != nullptr, false, "create array json again fail");
}
int arraySize = cJSON_GetArraySize(valuesArray);
for (int i = arraySize - 1; i >= 0; --i) {
cJSON* valueItem = cJSON_GetArrayItem(valuesArray, i);
CHECK_AND_CONTINUE(valueItem != nullptr && !cJSON_IsInvalid(valueItem));
cJSON* bundleNameItem = cJSON_GetObjectItem(valueItem, "bundleName");
cJSON* avQueueIdItem = cJSON_GetObjectItem(valueItem, "avQueueId");
if (bundleNameItem == nullptr || avQueueIdItem == nullptr || cJSON_IsInvalid(bundleNameItem) ||
!cJSON_IsString(bundleNameItem) || cJSON_IsInvalid(avQueueIdItem) || !cJSON_IsString(avQueueIdItem)) {
continue;
}
if (strcmp(bundleNameItem->valuestring, bundleName.c_str()) == 0 &&
strcmp(avQueueIdItem->valuestring, meta.GetAVQueueId().c_str()) == 0) {
if (i == 0) {
SLOGE("avqueue:%{public}s is first", meta.GetAVQueueId().c_str());
cJSON_Delete(valuesArray);
return false;
}
cJSON_DeleteItemFromArray(valuesArray, i);
}
}
if (cJSON_GetArraySize(valuesArray) >= maxAVQueueInfoLen) {
cJSON* valueItem = cJSON_GetArrayItem(valuesArray, cJSON_GetArraySize(valuesArray) - 1);
DeleteAVQueueImage(valueItem);
cJSON_DeleteItemFromArray(valuesArray, cJSON_GetArraySize(valuesArray) - 1);
}
bool ret = InsertAvQueueInfoToCJSONAndPrint(bundleName, meta, userId, valuesArray);
cJSON_Delete(valuesArray);
return ret;
}
// LCOV_EXCL_STOP
// LCOV_EXCL_START
void AVSessionService::DeleteAVQueueImage(cJSON* item)
{
if (item == nullptr || cJSON_IsInvalid(item)) {
return;
}
cJSON* imageDirItem = cJSON_GetObjectItem(item, "avQueueImageDir");
cJSON* imageNameItem = cJSON_GetObjectItem(item, "avQueueImageName");
if (imageDirItem == nullptr || cJSON_IsInvalid(imageDirItem) || !cJSON_IsString(imageDirItem)) {
SLOGE("invalid imageDirItem");
return;
}
if (imageNameItem == nullptr || cJSON_IsInvalid(imageNameItem) || !cJSON_IsString(imageNameItem)) {
SLOGE("invalid imageNameItem");
return;
}
std::string fileName = std::string(imageDirItem->valuestring) + std::string(imageNameItem->valuestring);
AVSessionUtils::DeleteFile(fileName);
}
// LCOV_EXCL_STOP
// LCOV_EXCL_START
void AVSessionService::AddAvQueueInfoToFile(AVSessionItem& session)
{
// check is this session support playmusiclist intent
std::lock_guard lockGuard(sessionServiceLock_);
std::string bundleName = session.GetBundleName();
std::string supportModule;
std::string profile;
if (!BundleStatusAdapter::GetInstance().IsSupportPlayIntent(bundleName, supportModule, profile)) {
SLOGE("bundleName=%{public}s does not support play intent", bundleName.c_str());
return;
}
AVMetaData meta = session.GetMetaData();
if (meta.GetAVQueueId().empty() || meta.GetAVQueueName().empty()) {
SLOGI("AddAvQueueInfoToFile avqueueinfo empty, return");
DoMetadataImgClean(meta);
return;
}
if (session.GetAppIndex() != 0) {
bundleName = bundleName + "_" + std::to_string(session.GetAppIndex());
}
std::lock_guard avQueueFileLockGuard(avQueueFileLock_);
std::string oldContent;
int32_t userId = session.GetUserId();
if (!LoadStringFromFileEx(GetAVQueueDir(userId), oldContent)) {
SLOGE("AddAvQueueInfoToFile read avqueueinfo fail, Return!");
DoMetadataImgClean(meta);
return;
}
#ifdef ENABLE_AVSESSION_SYSEVENT_CONTROL
AVSessionSysEvent::GetInstance().UpdateSupportAvqueue(session.GetBundleName(), true);
#endif
if (!SaveAvQueueInfo(oldContent, bundleName, meta, userId)) {
SLOGD("SaveAvQueueInfo same avqueueinfo, Return!");
DoMetadataImgClean(meta);
return;
}
DoMetadataImgClean(meta);
}
// LCOV_EXCL_STOP
void AVSessionService::DoMetadataImgClean(AVMetaData& data)
{
SLOGD("clear media img in DoMetadataImgClean");
std::shared_ptr<AVSessionPixelMap> innerQueuePixelMap = data.GetAVQueueImage();
if (innerQueuePixelMap != nullptr) {
innerQueuePixelMap->Clear();
}
std::shared_ptr<AVSessionPixelMap> innerMediaPixelMap = data.GetMediaImage();
if (innerMediaPixelMap != nullptr) {
innerMediaPixelMap->Clear();
}
}
bool AVSessionService::CheckStartAncoMediaPlay(const std::string& bundleName, int32_t *result)
{
std::vector<AVSessionDescriptor> tempDescriptors;
{
std::lock_guard sortFileLockGuard(sessionFileLock_);
GetHistoricalSessionDescriptorsFromFile(tempDescriptors);
}
for (auto iter = tempDescriptors.begin(); iter != tempDescriptors.end(); ++iter) {
if (iter->sessionTag_ == "ancoMediaSession" &&
iter->elementName_.GetBundleName() == bundleName) {
std::lock_guard lockGuard(audioBrokerLock_);
CHECK_AND_RETURN_RET_LOG(ancoMediaSessionListener_ != nullptr, true, "anco Listner null");
auto res = ancoMediaSessionListener_->OnStartAVPlayback(bundleName);
SLOGI("StartAncoMediaPlay for:%{public}s res:%{public}d", bundleName.c_str(), res);
*result = res;
return true;
}
}
return false;
}
int32_t AVSessionService::StartAVPlayback(const std::string& bundleName, const std::string& assetId,
const std::string& moduleName, const std::string& deviceId)
{
int32_t result = AVSESSION_ERROR;
if (CheckStartAncoMediaPlay(bundleName, &result)) {
return result;
}
auto uid = GetCallingUid();
auto CallerBundleName = BundleStatusAdapter::GetInstance().GetBundleNameFromUid(uid);
StartPlayType startPlayType = StartPlayType::APP;
if (uid == BLUETOOTH_UID) {
startPlayType = StartPlayType::BLUETOOTH;
}
if (uid == NEARLINK_UID) {
startPlayType = StartPlayType::NEARLINK;
}
StartPlayInfo startPlayInfo;
startPlayInfo.setBundleName(CallerBundleName);
startPlayInfo.setDeviceId(deviceId);
startPlayInfo.SetModuleName(moduleName);
std::unique_ptr<AVSessionDynamicLoader> dynamicLoader = std::make_unique<AVSessionDynamicLoader>();
typedef int32_t (*StartAVPlaybackFunc)(const std::string& bundleName, const std::string& assetId,
const StartPlayInfo startPlayInfo, StartPlayType startPlayType);
StartAVPlaybackFunc startAVPlayback =
reinterpret_cast<StartAVPlaybackFunc>(dynamicLoader->GetFuntion(
AVSESSION_DYNAMIC_INSIGHT_LIBRARY_PATH, "StartAVPlaybackWithId"));
if (startAVPlayback) {
#ifdef ENABLE_AVSESSION_SYSEVENT_CONTROL
ReportSessionControl(bundleName, CONTROL_COLD_START);
#endif
return (*startAVPlayback)(bundleName, assetId, startPlayInfo, startPlayType);
}
SLOGE("StartAVPlayback fail");
return AVSESSION_ERROR;
}
int32_t AVSessionService::StartAVPlayback(const std::string& bundleName, const std::string& assetId,
const std::string& moduleName)
{
int32_t result = AVSESSION_ERROR;
if (CheckStartAncoMediaPlay(bundleName, &result)) {
return result;
}
auto uid = GetCallingUid();
auto CallerBundleName = BundleStatusAdapter::GetInstance().GetBundleNameFromUid(uid);
StartPlayType startPlayType = StartPlayType::APP;
if (uid == BLUETOOTH_UID) {
startPlayType = StartPlayType::BLUETOOTH;
}
if (uid == NEARLINK_UID) {
startPlayType = StartPlayType::NEARLINK;
}
StartPlayInfo startPlayInfo;
startPlayInfo.setBundleName(CallerBundleName);
startPlayInfo.SetModuleName(moduleName);
std::unique_ptr<AVSessionDynamicLoader> dynamicLoader = std::make_unique<AVSessionDynamicLoader>();
typedef int32_t (*StartAVPlaybackFunc)(const std::string& bundleName, const std::string& assetId,
const StartPlayInfo startPlayInfo, StartPlayType startPlayType);
StartAVPlaybackFunc startAVPlayback =
reinterpret_cast<StartAVPlaybackFunc>(dynamicLoader->GetFuntion(
AVSESSION_DYNAMIC_INSIGHT_LIBRARY_PATH, "StartAVPlaybackWithId"));
if (startAVPlayback) {
#ifdef ENABLE_AVSESSION_SYSEVENT_CONTROL
ReportSessionControl(bundleName, CONTROL_COLD_START);
#endif
return (*startAVPlayback)(bundleName, assetId, startPlayInfo, startPlayType);
}
SLOGE("StartAVPlayback fail");
return AVSESSION_ERROR;
}
int32_t AVSessionService::RegisterAncoMediaSessionListener(const sptr<IAncoMediaSessionListener> &listener)
{
CHECK_AND_RETURN_RET_LOG(listener != nullptr, AVSESSION_ERROR, "anco Listner null");
std::lock_guard lockGuard(audioBrokerLock_);
ancoMediaSessionListener_ = listener;
return AVSESSION_SUCCESS;
}
sptr<AVControllerItem> AVSessionService::CreateNewControllerForSession(pid_t pid, sptr<AVSessionItem>& session)
{
SLOGI("pid=%{public}d sessionId=%{public}s", pid,
AVSessionUtils::GetAnonySessionId(session->GetSessionId()).c_str());
sptr<AVControllerItem> result = new(std::nothrow) AVControllerItem(pid, session, session->GetUserId());
if (result == nullptr) {
SLOGE("malloc controller failed");
return nullptr;
}
result->SetServiceCallbackForRelease([this](AVControllerItem& controller) { HandleControllerRelease(controller); });
session->AddController(pid, result);
return result;
}
// LCOV_EXCL_START
const cJSON* AVSessionService::GetSubNode(const cJSON* nodeItem, const std::string& name)
{
if (nodeItem == nullptr || cJSON_IsInvalid(nodeItem)) {
SLOGE("json node is invalid");
return nullptr;
}
if (name.empty()) {
SLOGE("name is invalid");
return nodeItem;
}
const cJSON* subItem = cJSON_GetObjectItem(nodeItem, name.c_str());
if (subItem == nullptr || cJSON_IsInvalid(subItem)) {
SLOGE("%{public}s is not exist in json", name.c_str());
return nullptr;
}
return subItem;
}
// LCOV_EXCL_STOP
bool AVSessionService::IsHistoricalSession(const std::string& sessionId)
{
{
std::string sortContent;
std::lock_guard sortFileLockGuard(sessionFileLock_);
if (!LoadStringFromFileEx(GetAVSortDir(), sortContent)) {
SLOGE("IsHistoricalSession read sort failed, filename=%{public}s", SORT_FILE_NAME);
return false;
}
if (sortContent.find(sessionId) == string::npos) {
SLOGE("IsHistoricalSession find session no sort, sessionId=%{public}s",
AVSessionUtils::GetAnonySessionId(sessionId).c_str());
return false;
}
}
auto session = GetContainer().GetSessionById(sessionId);
if (session != nullptr) {
SLOGE("IsHistoricalSession find session alive, sessionId=%{public}s",
AVSessionUtils::GetAnonySessionId(sessionId).c_str());
return false;
}
SLOGE("IsHistoricalSession find session historical, sessionId=%{public}s",
AVSessionUtils::GetAnonySessionId(sessionId).c_str());
return true;
}
bool AVSessionService::GetDefaultAbilityElementNameFromCJSON(std::string& sortContent,
std::string& bundleName, std::string& abilityName)
{
cJSON* sortValuesArray = cJSON_Parse(sortContent.c_str());
CHECK_AND_RETURN_RET_LOG(sortValuesArray != nullptr, false, "json object is null");
if (cJSON_IsInvalid(sortValuesArray) || !cJSON_IsArray(sortValuesArray)) {
SLOGE("sortValuesArray get invalid");
cJSON_Delete(sortValuesArray);
return false;
}
cJSON* sortValueItem = nullptr;
cJSON_ArrayForEach(sortValueItem, sortValuesArray) {
CHECK_AND_CONTINUE(sortValueItem != nullptr && !cJSON_IsInvalid(sortValueItem));
cJSON* sessionIdItem = cJSON_GetObjectItem(sortValueItem, "sessionId");
CHECK_AND_CONTINUE(sessionIdItem != nullptr &&
!cJSON_IsInvalid(sessionIdItem) && cJSON_IsString(sessionIdItem));
auto session = GetContainer().GetSessionById(std::string(sessionIdItem->valuestring));
if (session == nullptr) {
cJSON* bundleNameItem = cJSON_GetObjectItem(sortValueItem, "bundleName");
cJSON* abilityNameItem = cJSON_GetObjectItem(sortValueItem, "abilityName");
CHECK_AND_CONTINUE(bundleNameItem != nullptr &&
!cJSON_IsInvalid(bundleNameItem) && cJSON_IsString(bundleNameItem));
CHECK_AND_CONTINUE(abilityNameItem != nullptr &&
!cJSON_IsInvalid(abilityNameItem) && cJSON_IsString(abilityNameItem));
bundleName.assign(bundleNameItem->valuestring);
abilityName.assign(abilityNameItem->valuestring);
break;
} else {
SLOGE("Default start alive %{public}s",
AVSessionUtils::GetAnonySessionId(std::string(sessionIdItem->valuestring)).c_str());
cJSON_Delete(sortValuesArray);
return false;
}
}
cJSON_Delete(sortValuesArray);
return true;
}
int32_t AVSessionService::StartDefaultAbilityByCall(std::string& sessionId)
{
std::string bundleName = DEFAULT_BUNDLE_NAME;
std::string abilityName = DEFAULT_ABILITY_NAME;
std::string sortContent;
{
std::lock_guard sortFileLockGuard(sessionFileLock_);
if (!LoadStringFromFileEx(GetAVSortDir(), sortContent)) {
SLOGE("GetAllSessionDescriptors read sort fail! ");
return AVSESSION_ERROR;
}
}
if (!sortContent.empty()) {
if (!GetDefaultAbilityElementNameFromCJSON(sortContent, bundleName, abilityName)) {
SLOGE("GetDefaultAbilityElementNameFromCJSON fail");
return AVSESSION_ERROR;
}
}
std::shared_ptr<AbilityManagerAdapter> ability = nullptr;
{
std::lock_guard lockGuard(abilityManagerLock_);
auto it = abilityManager_.find(bundleName + abilityName);
if (it != abilityManager_.end()) {
ability = it->second;
} else {
ability = std::make_shared<AbilityManagerAdapter>(bundleName, abilityName);
if (ability == nullptr) {
return ERR_NO_MEMORY;
}
abilityManager_[bundleName + abilityName] = ability;
}
}
if (ability == nullptr) {
return AVSESSION_ERROR;
}
int32_t ret = ability->StartAbilityByCall(sessionId);
if (ret != ERR_START_ABILITY_IS_RUNNING) {
std::lock_guard lockGuard(abilityManagerLock_);
abilityManager_.erase(bundleName + abilityName);
}
return ret;
}
bool AVSessionService::GetElementNameBySessionIdFromCJSON(std::string& sortContent, const std::string& sessionIdNeeded,
std::string& bundleName, std::string& abilityName)
{
cJSON* sortValuesArray = cJSON_Parse(sortContent.c_str());
CHECK_AND_RETURN_RET_LOG(sortValuesArray != nullptr, false, "json object is null");
if (cJSON_IsInvalid(sortValuesArray) || !cJSON_IsArray(sortValuesArray)) {
SLOGE("sortValuesArray get invalid");
cJSON_Delete(sortValuesArray);
return false;
}
cJSON* sortValueItem = nullptr;
cJSON_ArrayForEach(sortValueItem, sortValuesArray) {
CHECK_AND_CONTINUE(sortValueItem != nullptr && !cJSON_IsInvalid(sortValueItem));
cJSON* sessionIdItem = cJSON_GetObjectItem(sortValueItem, "sessionId");
CHECK_AND_CONTINUE(sessionIdItem != nullptr &&
!cJSON_IsInvalid(sessionIdItem) && cJSON_IsString(sessionIdItem));
if (strcmp(sessionIdNeeded.c_str(), sessionIdItem->valuestring) == 0) {
cJSON* bundleNameItem = cJSON_GetObjectItem(sortValueItem, "bundleName");
cJSON* abilityNameItem = cJSON_GetObjectItem(sortValueItem, "abilityName");
CHECK_AND_CONTINUE(bundleNameItem != nullptr &&
!cJSON_IsInvalid(bundleNameItem) && cJSON_IsString(bundleNameItem));
CHECK_AND_CONTINUE(abilityNameItem != nullptr &&
!cJSON_IsInvalid(abilityNameItem) && cJSON_IsString(abilityNameItem));
bundleName.assign(bundleNameItem->valuestring);
abilityName.assign(abilityNameItem->valuestring);
break;
}
}
cJSON_Delete(sortValuesArray);
return true;
}
int32_t AVSessionService::StartAbilityByCall(const std::string& sessionIdNeeded, std::string& sessionId)
{
std::string content;
{
std::lock_guard sortFileLockGuard(sessionFileLock_);
if (!LoadStringFromFileEx(GetAVSortDir(), content)) {
SLOGE("LoadStringFromFile failed, filename=%{public}s", SORT_FILE_NAME);
return AVSESSION_ERROR;
}
}
std::string bundleName;
std::string abilityName;
if (!GetElementNameBySessionIdFromCJSON(content, sessionIdNeeded, bundleName, abilityName)) {
SLOGE("parse json failed, sessionId=%{public}s",
AVSessionUtils::GetAnonySessionId(sessionIdNeeded).c_str());
return AVSESSION_ERROR;
}
if (bundleName.empty() || abilityName.empty()) {
SLOGE("Get bundle name & ability name failed, sessionId=%{public}s",
AVSessionUtils::GetAnonySessionId(sessionIdNeeded).c_str());
return AVSESSION_ERROR;
}
std::shared_ptr<AbilityManagerAdapter> ability = nullptr;
{
std::lock_guard lockGuard(abilityManagerLock_);
auto it = abilityManager_.find(bundleName + abilityName);
if (it != abilityManager_.end()) {
ability = it->second;
} else {
ability = std::make_shared<AbilityManagerAdapter>(bundleName, abilityName);
if (ability == nullptr) {
return ERR_NO_MEMORY;
}
abilityManager_[bundleName + abilityName] = ability;
}
}
if (ability == nullptr) {
return AVSESSION_ERROR;
}
int32_t ret = ability->StartAbilityByCall(sessionId);
if (ret != ERR_START_ABILITY_IS_RUNNING) {
std::lock_guard lockGuard(abilityManagerLock_);
abilityManager_.erase(bundleName + abilityName);
}
return ret;
}
int32_t AVSessionService::CreateControllerInner(const std::string& sessionId, sptr<IRemoteObject>& object)
{
return CreateControllerInner(sessionId, object, -1);
}
int32_t AVSessionService::CreateControllerInner(const std::string& sessionId, sptr<IRemoteObject>& object, pid_t pid)
{
int32_t userId = GetUserIdFromCallingUid(static_cast<int32_t>(GetCallingUid()));
SLOGI("CreateControllerInner for sessionId:%{public}s|%{public}d|%{public}d|%{public}d",
AVSessionUtils::GetAnonySessionId(sessionId).c_str(), pid, GetCallingPid(), userId);
#ifdef CAR_FEATURE_ENABLE
sptr<AVSessionItem> session = GetUsersManager().GetContainerFromAll().GetSessionById(sessionId);
#else
sptr<AVSessionItem> session = GetUsersManager().GetContainerFromUser(userId).GetSessionById(sessionId);
#endif
if (session == nullptr) {
SLOGE("no session id %{public}s", AVSessionUtils::GetAnonySessionId(sessionId).c_str());
AudioStandard::StreamDfxManager::GetInstance().SendAudioErrorEvent(static_cast<int32_t>(getuid()),
AudioStandard::AVSESSION_CONTROL_SESSION_NOT_EXIST_LOCAL_SET, "no session", false);
return ERR_SESSION_NOT_EXIST;
}
if (pid < 0 || GetCallingPid() != getpid()) {
pid = GetCallingPid();
}
std::lock_guard lockGuard(sessionServiceLock_);
auto existController = GetPresentController(pid, sessionId);
if (existController != nullptr) {
SLOGI("Controller is already existed.");
object = existController;
AudioStandard::StreamDfxManager::GetInstance().SendAudioErrorEvent(static_cast<int32_t>(getuid()),
AudioStandard::AVSESSION_CONTROL_CONTROLLER_IS_EXIST_LOCAL_SET,
"Controller is already existed", false);
return ERR_CONTROLLER_IS_EXIST;
}
sptr<AVControllerItem> newController = CreateNewControllerForSession(pid, session);
if (newController == nullptr) {
SLOGE("Create new controller failed.");
AudioStandard::StreamDfxManager::GetInstance().SendAudioErrorEvent(static_cast<int32_t>(getuid()),
AudioStandard::AVSESSION_CONTROL_NO_MEMORY_LOCAL_SET, "Create new controller failed", false);
return ERR_NO_MEMORY;
}
controllers_[pid].push_back(newController);
object = newController;
return AVSESSION_SUCCESS;
}
void AVSessionService::AddSessionListener(pid_t pid, const sptr<ISessionListener>& listener, int32_t userId)
{
std::lock_guard lockGuard(sessionListenersLock_);
GetUsersManager().AddSessionListener(pid, listener, userId);
}
void AVSessionService::AddSessionListenerForAllUsers(pid_t pid, const sptr<ISessionListener>& listener)
{
std::lock_guard lockGuard(sessionListenersLock_);
GetUsersManager().AddSessionListenerForAllUsers(pid, listener);
}
void AVSessionService::RemoveSessionListener(pid_t pid)
{
std::lock_guard lockGuard(sessionListenersLock_);
GetUsersManager().RemoveSessionListener(pid);
}
int32_t AVSessionService::RegisterSessionListener(const sptr<ISessionListener>& listener)
{
int32_t userId = GetUserIdFromCallingUid(static_cast<int32_t>(GetCallingUid()));
pid_t pid = GetCallingPid();
SLOGI("Enter RegisterSessionListener process for pid:%{public}d and return target userId:%{public}d",
static_cast<int>(pid), userId);
AddSessionListener(pid, listener, userId);
return userId;
}
int32_t AVSessionService::RegisterSessionListenerForAllUsers(const sptr<ISessionListener>& listener)
{
pid_t pid = GetCallingPid();
SLOGI("Enter RegisterSessionListenerForAllUsers process for pid:%{public}d", static_cast<int>(pid));
AddSessionListenerForAllUsers(pid, listener);
return AVSESSION_SUCCESS;
}
// LCOV_EXCL_START
AVControlCommand AVSessionService::GetSessionProcCommand()
{
AVControlCommand cmd;
if (topSession_ != nullptr) {
sptr<AVSessionItem> procSession = topSession_;
if (IsAncoValid()) {
procSession = topSession_->GetPlayingTime() > ancoSession_->GetPlayingTime() ?
topSession_ : ancoSession_;
}
auto playbackState = procSession->GetPlaybackState();
cmd.SetCommand(playbackState.GetState() == AVPlaybackState::PLAYBACK_STATE_PLAY ?
AVControlCommand::SESSION_CMD_PAUSE : AVControlCommand::SESSION_CMD_PLAY);
} else if (IsAncoValid()) {
auto state = ancoSession_->GetPlaybackState();
cmd.SetCommand(state.GetState() == AVPlaybackState::PLAYBACK_STATE_PLAY ?
AVControlCommand::SESSION_CMD_PAUSE : AVControlCommand::SESSION_CMD_PLAY);
} else {
cmd.SetCommand(AVControlCommand::SESSION_CMD_PLAY);
}
return cmd;
}
void AVSessionService::HandleEventHandlerCallBack()
{
SLOGI("handle eventHandler callback isFirstPress_=%{public}d, pressCount_:%{public}d",
isFirstPress_.load(), pressCount_.load());
AVControlCommand cmd;
bool shouldColdPlay = false;
{
std::lock_guard lockGuard(sessionServiceLock_);
if (pressCount_.load() >= THREE_CLICK) {
cmd.SetCommand(AVControlCommand::SESSION_CMD_PLAY_PREVIOUS);
} else if (pressCount_.load() == DOUBLE_CLICK) {
cmd.SetCommand(AVControlCommand::SESSION_CMD_PLAY_NEXT);
} else if (pressCount_.load() == ONE_CLICK) {
cmd = GetSessionProcCommand();
} else {
pressCount_.store(0);
isFirstPress_.store(true);
SLOGI("press invalid return, topSession alive:%{public}d", static_cast<int>(topSession_ != nullptr));
return;
}
SLOGI("HandleEventHandlerCallBack proc cmd=%{public}d", cmd.GetCommand());
if (!topSession_) {
shouldColdPlay = true;
SLOGI("HandleEventHandlerCallBack checkTop:%{public}d|shouldColdStart=%{public}d",
static_cast<int>(topSession_ != nullptr), shouldColdPlay);
} else {
if (topSession_->GetDescriptor().sessionTag_ == "external_audio") {
SLOGI("HandleEventHandlerCallBack this is an external audio");
} else {
auto keyEvent = MMI::KeyEvent::Create();
CHECK_AND_RETURN_LOG(keyEvent != nullptr, "handlevent keyEvent is null");
CheckSessionHandleKeyEvent(true, cmd, *keyEvent, topSession_);
}
}
}
if (shouldColdPlay) {
HandleSystemKeyColdStart(cmd);
}
pressCount_.store(0);
isFirstPress_.store(true);
}
// LCOV_EXCL_STOP
bool AVSessionService::IsAncoValid()
{
std::lock_guard lockGuard(sessionServiceLock_);
return ancoSession_ != nullptr && ancoSession_->IsActive();
}
bool AVSessionService::CheckSessionHandleKeyEvent(bool procCmd, AVControlCommand cmd,
const MMI::KeyEvent& keyEvent, sptr<AVSessionItem> session, const std::string& deviceId)
{
CHECK_AND_RETURN_RET_LOG(session != nullptr, false, "handlevent session is null");
sptr<AVSessionItem> procSession = nullptr;
if (ancoSession_ == nullptr || !ancoSession_->IsActive()) {
procSession = session;
} else {
procSession = session->GetPlayingTime() > ancoSession_->GetPlayingTime() ? session : ancoSession_;
}
CHECK_AND_RETURN_RET_LOG(procSession != nullptr, false, "handlevent session is null");
SLOGI("CheckSessionHandleKeyEvent procSession:%{public}s", procSession->GetBundleName().c_str());
auto uid = GetCallingUid();
CommandInfo cmdInfo;
switch (uid) {
case BLUETOOTH_UID:
cmdInfo.SetCallerType(PlayTypeToString.at(PlayType::BLUETOOTH));
break;
case NEARLINK_UID:
cmdInfo.SetCallerType(PlayTypeToString.at(PlayType::NEARLINK));
break;
default:
break;
};
cmdInfo.SetCallerDeviceId(deviceId);
if (procCmd) {
cmd.SetCommandInfo(cmdInfo);
procSession->ExecuteControllerCommand(cmd);
SLOGI("CheckSessionHandleKeyEvent proc cmd:%{public}d", cmd.GetCommand());
} else {
procSession->HandleMediaKeyEvent(keyEvent, cmdInfo);
SLOGI("CheckSessionHandleKeyEvent proc event:%{public}d", keyEvent.GetKeyCode());
}
return true;
}
int32_t AVSessionService::HandleKeyEvent(const MMI::KeyEvent& keyEvent, const std::string& deviceId)
{
if (keyEvent.GetKeyCode() != MMI::KeyEvent::KEYCODE_HEADSETHOOK &&
keyEvent.GetKeyCode() != MMI::KeyEvent::KEYCODE_MEDIA_PLAY_PAUSE) {
std::lock_guard lockGuard(keyEventListLock_);
std::shared_ptr<std::list<sptr<AVSessionItem>>> keyEventList = GetCurKeyEventSessionList();
CHECK_AND_RETURN_RET_LOG(keyEventList != nullptr, AVSESSION_ERROR, "keyEventList ptr nullptr!");
for (const auto& session : *keyEventList) {
session->HandleMediaKeyEvent(keyEvent);
return AVSESSION_SUCCESS;
}
}
if (keyEvent.GetKeyCode() == MMI::KeyEvent::KEYCODE_HEADSETHOOK ||
keyEvent.GetKeyCode() == MMI::KeyEvent::KEYCODE_MEDIA_PLAY_PAUSE) {
pressCount_.fetch_add(1);
SLOGI("isFirstPress_=%{public}d", isFirstPress_.load());
if (isFirstPress_.exchange(false)) {
auto ret = AVSessionEventHandler::GetInstance().AVSessionPostTask([this]() {
HandleEventHandlerCallBack();
}, "SendSystemAVKeyEvent", CLICK_TIMEOUT);
CHECK_AND_RETURN_RET_LOG(ret, AVSESSION_ERROR, "init eventHandler failed");
}
return AVSESSION_SUCCESS;
}
{
std::lock_guard lockGuard(sessionServiceLock_);
AVControlCommand cmd;
if (topSession_ != nullptr && CheckSessionHandleKeyEvent(false, cmd, keyEvent, topSession_, deviceId)) {
return AVSESSION_SUCCESS;
}
}
return AVSESSION_CONTINUE;
}
int32_t AVSessionService::SendSystemAVKeyEvent(const MMI::KeyEvent& keyEvent, const AAFwk::Want &wantParam)
{
SLOGI("SendSystemAVKeyEvent get key=%{public}d.", keyEvent.GetKeyCode());
std::string deviceId = wantParam.GetStringParam("deviceId");
int32_t ret = HandleKeyEvent(keyEvent, deviceId);
if (ret != AVSESSION_CONTINUE) {
return ret;
}
{
int cmd = ConvertKeyCodeToCommand(keyEvent.GetKeyCode());
AVControlCommand controlCommand;
controlCommand.SetCommand(cmd);
SLOGI("topSession get nullptr, check if cold start for cmd %{public}d forRemoteDevice", cmd);
HandleSystemKeyColdStart(controlCommand, deviceId);
}
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::SendSystemAVKeyEvent(const MMI::KeyEvent& keyEvent)
{
SLOGI("SendSystemAVKeyEvent get key=%{public}d.", keyEvent.GetKeyCode());
int32_t ret = HandleKeyEvent(keyEvent);
if (ret != AVSESSION_CONTINUE) {
return ret;
}
{
int cmd = ConvertKeyCodeToCommand(keyEvent.GetKeyCode());
AVControlCommand controlCommand;
controlCommand.SetCommand(cmd);
SLOGI("topSession get nullptr, check if cold start for cmd %{public}d", cmd);
HandleSystemKeyColdStart(controlCommand);
}
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::ConvertKeyCodeToCommand(int keyCode)
{
auto iter = keyCodeToCommandMap_.find(keyCode);
if (iter != keyCodeToCommandMap_.end()) {
return iter->second;
} else {
return AVControlCommand::SESSION_CMD_PLAY;
}
}
void AVSessionService::HandleSystemKeyColdStart(const AVControlCommand &command, const std::string deviceId)
{
SLOGI("cmd=%{public}d with no topsession", command.GetCommand());
// try proc command for first front session
{
std::lock_guard lockGuard(sessionServiceLock_);
std::lock_guard frontLockGuard(sessionFrontLock_);
std::shared_ptr<std::list<sptr<AVSessionItem>>> sessionListForFront = GetCurSessionListForFront();
CHECK_AND_RETURN_LOG(sessionListForFront != nullptr, "sessionListForFront ptr nullptr!");
for (const auto& session : *sessionListForFront) {
CHECK_AND_CONTINUE(session != nullptr);
if (session->GetSessionType() != "voice_call" && session->GetSessionType() != "video_call") {
auto keyEvent = MMI::KeyEvent::Create();
CHECK_AND_RETURN_LOG(keyEvent != nullptr, "handle event keyevent is null");
CheckSessionHandleKeyEvent(true, command, *keyEvent, session, deviceId);
SLOGI("ExecuteCommand %{public}d for front session: %{public}s", command.GetCommand(),
session->GetBundleName().c_str());
return;
}
}
}
{
std::lock_guard lockGuard(sessionServiceLock_);
if (ancoSession_ != nullptr && ancoSession_->IsActive()) {
SLOGI("ExecuteCommand %{public}d for anco_audio without top and frontlist", command.GetCommand());
ancoSession_->ExecuteControllerCommand(command);
return;
}
}
std::vector<AVSessionDescriptor> coldStartDescriptors;
GetColdStartSessionDescriptors(coldStartDescriptors);
CHECK_AND_RETURN_LOG(coldStartDescriptors.size() > 0, "get coldStartDescriptors empty");
// try start play for first history session
if (command.GetCommand() == AVControlCommand::SESSION_CMD_PLAY ||
command.GetCommand() == AVControlCommand::SESSION_CMD_PLAY_NEXT ||
command.GetCommand() == AVControlCommand::SESSION_CMD_PLAY_PREVIOUS) {
sptr<IRemoteObject> object;
int32_t ret = 0;
std::string bundleName = coldStartDescriptors[0].elementName_.GetBundleName();
sptr<AVSessionItem> session = GetContainer().GetSessionById(coldStartDescriptors[0].sessionId_);
if ((session != nullptr) && (session->GetAppIndex() != 0)) {
bundleName = bundleName + "_" + std::to_string(session->GetAppIndex());
}
CHECK_AND_RETURN_LOG(!CheckIfOtherAudioPlaying(), "audioplaying control block");
ret = deviceId.empty() ? StartAVPlayback(bundleName, "", "")
: StartAVPlayback(bundleName, "", "", deviceId);
SLOGI("Cold play %{public}s ret=%{public}d", bundleName.c_str(), ret);
} else {
SLOGI("Cold start command=%{public}d, coldStartDescriptorsSize=%{public}d return", command.GetCommand(),
static_cast<int>(coldStartDescriptors.size()));
}
}
bool AVSessionService::CheckIfOtherAudioPlaying()
{
std::vector<int> audioPlayingUids = focusSessionStrategy_.GetAudioPlayingUids();
CHECK_AND_RETURN_RET_LOG(audioPlayingUids.empty(), true, "other audio playing:%{public}d", audioPlayingUids[0]);
return false;
}
int32_t AVSessionService::SendSystemControlCommand(const AVControlCommand &command)
{
{
std::lock_guard lockGuard(sessionServiceLock_);
SLOGI("SendSystemControlCommand with cmd:%{public}d, topSession alive:%{public}d",
command.GetCommand(), static_cast<int>(topSession_ != nullptr));
if (topSession_) {
CHECK_AND_RETURN_RET_LOG(CommandSendLimit::GetInstance().IsCommandSendEnable(GetCallingPid()),
ERR_COMMAND_SEND_EXCEED_MAX, "command excuted number exceed max");
auto keyEvent = MMI::KeyEvent::Create();
CHECK_AND_RETURN_RET_LOG(keyEvent != nullptr, AVSESSION_SUCCESS, "handlevent keyEvent is null");
CheckSessionHandleKeyEvent(true, command, *keyEvent, topSession_);
return AVSESSION_SUCCESS;
}
}
HandleSystemKeyColdStart(command);
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::SendSystemCommonCommand(const std::string& commonCommand,
const AAFwk::WantParams& commandArgs)
{
#ifdef CASTPLUS_CAST_ENGINE_ENABLE
CHECK_AND_RETURN_RET_LOG(pcmCastSession_ != nullptr, ERR_SESSION_NOT_EXIST, "Session not exist");
pcmCastSession_->ExecuteCommonCommand(commonCommand, commandArgs);
return AVSESSION_SUCCESS;
#else
return AVSESSION_SUCCESS;
#endif //CASTPLUS_CAST_ENGINE_ENABLE
}
void AVSessionService::AddClientDeathObserver(pid_t pid, const sptr<IClientDeath>& observer,
const sptr<ClientDeathRecipient> recipient)
{
std::lock_guard lockGuard(clientDeathLock_);
clientDeathObservers_[pid] = observer;
clientDeathRecipients_[pid] = recipient;
}
void AVSessionService::RemoveClientDeathObserver(pid_t pid)
{
std::lock_guard lockGuard(clientDeathLock_);
sptr<IClientDeath> observer = clientDeathObservers_[pid];
sptr<ClientDeathRecipient> recipient = clientDeathRecipients_[pid];
if (observer && recipient) {
SLOGI("remove clientDeath recipient for %{public}d", static_cast<int>(pid));
observer->AsObject()->RemoveDeathRecipient(recipient);
}
clientDeathObservers_.erase(pid);
clientDeathRecipients_.erase(pid);
}
int32_t AVSessionService::RegisterClientDeathObserver(const sptr<IClientDeath>& observer)
{
auto pid = GetCallingPid();
auto uid = GetCallingUid();
SLOGI("enter ClientDeathObserver register with recipient point for pid:%{public}d", static_cast<int>(pid));
sptr<ClientDeathRecipient> recipient =
new(std::nothrow) ClientDeathRecipient([this, pid, uid]() { OnClientDied(pid, uid); });
if (recipient == nullptr) {
SLOGE("New ClientDeathRecipient failed.");
HISYSEVENT_FAULT("CONTROL_COMMAND_FAILED", "ERROR_TYPE", "RGS_CLIENT_DEATH_OBSERVER_FAILED",
"ERROR_INFO", "avsession service register client death observer malloc failed");
return AVSESSION_ERROR;
}
if (!observer->AsObject()->AddDeathRecipient(recipient)) {
SLOGE("add death recipient failed for %{public}d failed", pid);
HISYSEVENT_FAULT("CONTROL_COMMAND_FAILED", "ERROR_TYPE", "RGS_CLIENT_DEATH_FAILED", "CALLING_PID", pid,
"ERROR_INFO", "avsession service register client death observer, add death recipient failed");
return AVSESSION_ERROR;
}
AddClientDeathObserver(pid, observer, recipient);
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::IsDesktopLyricSupported(bool &isSupported)
{
isSupported = false;
const char *deviceType = GetDeviceType();
CHECK_AND_RETURN_RET_LOG(deviceType != nullptr, AVSESSION_ERROR, "get device type failed");
std::string deviceTypeStr = std::string(deviceType);
SLOGI("deviceType:%{public}s", deviceTypeStr.c_str());
if (DESKTOP_LYRICS_SUPPORTED_DEVICES.count(deviceTypeStr) != 0) {
isSupported = true;
}
return AVSESSION_SUCCESS;
}
void AVSessionService::ClearClientResources(pid_t pid, bool continuePlay)
{
RemoveSessionListener(pid);
{
std::lock_guard lockGuard(sessionServiceLock_);
ClearSessionForClientDiedNoLock(pid, continuePlay);
ClearControllerForClientDiedNoLock(pid);
}
RemoveClientDeathObserver(pid);
}
int32_t AVSessionService::Close(void)
{
auto pid = GetCallingPid();
ClearClientResources(pid, false);
return AVSESSION_SUCCESS;
}
void AVSessionService::OnClientDied(pid_t pid, pid_t uid)
{
ClearClientResources(pid, true);
#ifdef CASTPLUS_CAST_ENGINE_ENABLE
{
std::lock_guard lockGuard(sessionServiceLock_);
if (pcmCastSession_ != nullptr && pcmCastSession_->GetCastMode() == HiPlayCastMode::APP_LEVEL
&& pcmCastSession_->GetUid() == uid) {
ClearPcmSessionForClientDiedNoLock();
}
}
AVRouter::GetInstance().IsStopCastDiscovery(pid);
{
std::lock_guard lockGuard(checkEnableCastLock_);
cacheEnableCastPids_.erase(pid);
}
if (BundleStatusAdapter::GetInstance().GetBundleNameFromUid(uid) == MEDIA_CONTROL_BUNDLENAME) {
SLOGI("mediacontroller on client die");
}
#endif // CASTPLUS_CAST_ENGINE_ENABLE
#ifdef ENABLE_AVSESSION_SYSEVENT_CONTROL
AVSessionSysEvent::GetInstance().ReportPlayingState(
BundleStatusAdapter::GetInstance().GetBundleNameFromUid(uid));
#endif
NotifyClientDieForMigrateProxy(pid);
}
// LCOV_EXCL_START
void AVSessionService::DeleteHistoricalRecord(const std::string& bundleName, int32_t userId)
{
std::lock_guard sortFileLockGuard(sessionFileLock_);
userId = userId <= 0 ? GetUsersManager().GetCurrentUserId() : userId;
if (!CheckUserDirValid(userId)) {
SLOGE("DeleteHistoricalRecord target user:%{public}d not valid, return", userId);
return;
}
SLOGI("delete historical record, bundleName=%{public}s, userId=%{public}d", bundleName.c_str(), userId);
std::string oldContent;
if (!LoadStringFromFileEx(GetAVSortDir(userId), oldContent)) {
SLOGE("LoadStringFromFile failed, filename=%{public}s", SORT_FILE_NAME);
return;
}
cJSON* valuesArray = cJSON_Parse(oldContent.c_str());
CHECK_AND_RETURN_LOG(valuesArray != nullptr, "cjson parse nullptr");
if (cJSON_IsInvalid(valuesArray) || !cJSON_IsArray(valuesArray)) {
SLOGE("parse json invalid");
cJSON_Delete(valuesArray);
return;
}
int arraySize = cJSON_GetArraySize(valuesArray);
for (int i = arraySize - 1; i >= 0; --i) {
cJSON* valueItem = cJSON_GetArrayItem(valuesArray, i);
CHECK_AND_CONTINUE(valueItem != nullptr && !cJSON_IsInvalid(valueItem));
cJSON* bundleNameItem = cJSON_GetObjectItem(valueItem, "bundleName");
cJSON* abilityNameItem = cJSON_GetObjectItem(valueItem, "abilityName");
if (bundleNameItem == nullptr || cJSON_IsInvalid(bundleNameItem) || !cJSON_IsString(bundleNameItem) ||
abilityNameItem == nullptr || cJSON_IsInvalid(abilityNameItem) || !cJSON_IsString(abilityNameItem)) {
SLOGI("not contain bundleName or abilityName, pass");
continue;
}
if (strcmp(bundleName.c_str(), bundleNameItem->valuestring) == 0) {
cJSON_DeleteItemFromArray(valuesArray, i);
break;
}
}
char* newContent = cJSON_Print(valuesArray);
if (newContent == nullptr) {
SLOGE("newContent print fail");
} else {
std::string newContentStr(newContent);
if (!SaveStringToFileEx(GetAVSortDir(userId), newContentStr)) {
SLOGE("SaveStringToFileEx failed when refresh focus session sort!");
}
cJSON_free(newContent);
}
cJSON_Delete(valuesArray);
}
// LCOV_EXCL_STOP
// LCOV_EXCL_START
void AVSessionService::DeleteAVQueueInfoRecordFromCJSON(std::string& sortContent,
const std::string& bundleName, int32_t userId)
{
cJSON* valuesArray = cJSON_Parse(sortContent.c_str());
CHECK_AND_RETURN_LOG(valuesArray != nullptr, "cjson parse nullptr");
if (cJSON_IsInvalid(valuesArray) || !cJSON_IsArray(valuesArray)) {
SLOGE("parse json invalid");
cJSON_Delete(valuesArray);
return;
}
int arraySize = cJSON_GetArraySize(valuesArray);
for (int i = arraySize - 1; i >= 0; --i) {
cJSON* valueItem = cJSON_GetArrayItem(valuesArray, i);
CHECK_AND_CONTINUE(valueItem != nullptr && !cJSON_IsInvalid(valueItem));
cJSON* bundleNameItem = cJSON_GetObjectItem(valueItem, "bundleName");
if (bundleNameItem == nullptr || cJSON_IsInvalid(bundleNameItem) || !cJSON_IsString(bundleNameItem)) {
SLOGI("bundleName from json not valid");
continue;
}
if (strcmp(bundleName.c_str(), bundleNameItem->valuestring) == 0) {
cJSON* avQueueIdItem = cJSON_GetObjectItem(valueItem, "avQueueId");
if (avQueueIdItem == nullptr || cJSON_IsInvalid(avQueueIdItem) || !cJSON_IsString(avQueueIdItem)) {
SLOGI("avQueueId from json not valid");
continue;
}
std::string avQueueId(avQueueIdItem->valuestring);
std::string fileName = AVSessionUtils::GetFixedPathName(userId) + bundleName + "_" +
avQueueId + AVSessionUtils::GetFileSuffix();
AVSessionUtils::DeleteFile(fileName);
cJSON_DeleteItemFromArray(valuesArray, i);
}
}
char* newContent = cJSON_Print(valuesArray);
if (newContent == nullptr) {
SLOGE("newContent print fail");
} else {
std::string newContentStr(newContent);
if (!SaveStringToFileEx(GetAVQueueDir(userId), newContentStr)) {
SLOGE("SaveStringToFile failed, filename=%{public}s", AVQUEUE_FILE_NAME);
}
cJSON_free(newContent);
}
cJSON_Delete(valuesArray);
}
// LCOV_EXCL_STOP
// LCOV_EXCL_START
void AVSessionService::DeleteAVQueueInfoRecord(const std::string& bundleName, int32_t userId)
{
std::lock_guard avQueueFileLockGuard(avQueueFileLock_);
if (userId <= 0) {
userId = GetUsersManager().GetCurrentUserId();
}
if (!CheckUserDirValid(userId)) {
SLOGE("DeleteAVQueueInfoRecord target user:%{public}d not valid, return", userId);
return;
}
SLOGI("DeleteAVQueueInfoRecord, bundleName=%{public}s, userId=%{public}d", bundleName.c_str(), userId);
std::string oldContent;
std::string newContent;
if (!LoadStringFromFileEx(GetAVQueueDir(userId), oldContent)) {
SLOGE("LoadStringFromFile failed, filename=%{public}s", AVQUEUE_FILE_NAME);
return;
}
DeleteAVQueueInfoRecordFromCJSON(oldContent, bundleName, userId);
}
// LCOV_EXCL_STOP
void AVSessionService::HandleOtherSessionPlaying(sptr<AVSessionItem>& session)
{
CHECK_AND_RETURN_LOG(session != nullptr, "No other sessions are currently playing");
UpdateTopSession(session);
CHECK_AND_RETURN_LOG(topSession_ != nullptr, "topSession is nullptr, update topSession fail!");
bool updateOrderResult = UpdateOrder(session);
CHECK_AND_RETURN_LOG(updateOrderResult, "UpdateOrder fail");
if (session->GetSessionType() == "audio" || session->GetSessionType() == "video") {
AVSessionService::NotifySystemUI(nullptr, IsCapsuleNeeded(), false);
}
}
sptr <AVSessionItem> AVSessionService::GetOtherPlayingSession(int32_t userId, std::string bundleName)
{
std::lock_guard frontLockGuard(sessionFrontLock_);
std::shared_ptr<std::list<sptr<AVSessionItem>>> sessionListForFront = GetCurSessionListForFront(userId);
CHECK_AND_RETURN_RET_LOG(sessionListForFront != nullptr, nullptr, "sessionListForFront ptr nullptr!");
for (const auto& session : *sessionListForFront) {
CHECK_AND_CONTINUE(session != nullptr);
bool hasSession = (session->GetSessionType() != "voice_call" && session->GetSessionType() != "video_call") &&
session->GetBundleName() != bundleName && !session->IsCasting() && IsLocalSessionPlaying(session);
if (hasSession) {
SLOGI("find other playing session, uid:%{public}d, pid:%{public}d, bundleName %{public}s",
session->GetUid(), session->GetPid(), session->GetBundleName().c_str());
return session;
}
}
CHECK_AND_RETURN_RET_LOG(!bundleName.empty(), nullptr, "bundleName is empty");
CHECK_AND_RETURN_RET_LOG(static_cast<int32_t>(sessionListForFront->size()) >= otherPlayingSessionMinLen,
nullptr, "sessionListForFront size less than otherPlayingSessionMinLen");
sptr<AVSessionItem> secondSession = *(++sessionListForFront->begin());
CHECK_AND_RETURN_RET_LOG(secondSession != nullptr, nullptr, "secondSession is nullptr!");
if (secondSession->IsCasting() &&
secondSession->GetCastAVPlaybackState().GetState() == AVPlaybackState::PLAYBACK_STATE_PLAY) {
SLOGI("find casting session, uid:%{public}d", secondSession->GetUid());
return secondSession;
}
return nullptr;
}
void AVSessionService::HandleTopSessionRelease(int32_t userId, sptr<AVSessionItem>& sessionItem)
{
if (GetUsersManager().GetTopSession(userId).GetRefPtr() == sessionItem.GetRefPtr()) {
sptr<AVSessionItem> result = GetOtherPlayingSession(userId, sessionItem->GetBundleName());
if (result != nullptr) {
HandleOtherSessionPlaying(result);
} else {
UpdateTopSession(nullptr, userId);
hasMediaCapsule_ = false;
int32_t ret = Notification::NotificationHelper::CancelNotification(std::to_string(userId),
mediacontrollerNotifyId);
SLOGI("CancelNotification with userId:%{public}d, ret=%{public}d", userId, ret);
}
}
}
void AVSessionService::HandleSessionRelease(std::string sessionId, bool continuePlay)
{
{
std::lock_guard lockGuard(sessionServiceLock_);
std::lock_guard frontLockGuard(sessionFrontLock_);
sptr<AVSessionItem> sessionItem = GetUsersManager().GetContainerFromAll().GetSessionById(sessionId);
CHECK_AND_RETURN_LOG(sessionItem != nullptr, "Session item is nullptr");
int32_t userId = sessionItem->GetUserId() < 0 ? GetUsersManager().GetCurrentUserId() : sessionItem->GetUserId();
SLOGD("HandleSessionRelease with userId:%{public}d", userId);
HILOG_COMM_INFO("HandleSessionRelease, sessionId=%{public}s, bundleName=%{public}s",
AVSessionUtils::GetAnonySessionId(sessionId).c_str(), sessionItem->GetBundleName().c_str());
#ifdef ENABLE_AVSESSION_SYSEVENT_CONTROL
ReportSessionState(sessionItem, SessionState::STATE_RELEASE);
#endif
NotifySessionRelease(sessionItem->GetDescriptor());
#ifdef CAR_FEATURE_ENABLE
NotifySessionRemoveForAudioZone(sessionItem->GetDescriptor());
#endif
if (sessionItem->GetUid() == ancoUid) {
ancoSession_ = nullptr;
SLOGI("ancoSession release in user:%{public}d", userId);
}
if (controlListForNtf_.find(sessionItem->GetBundleName()) != controlListForNtf_.end()) {
SLOGI("RemoveControlBundle for :%{public}s ", sessionItem->GetBundleName().c_str());
focusSessionStrategy_.RemoveControlBundle(sessionItem->GetUid(), sessionItem->GetPid());
}
sessionItem->DestroyTask(continuePlay);
HandleTopSessionRelease(userId, sessionItem);
if (sessionItem->GetRemoteSource() != nullptr) {
int32_t ret = CancelCastAudioForClientExit(sessionItem->GetPid(), sessionItem);
SLOGI("CancelCastAudioForClientExit ret is %{public}d", ret);
}
HISYSEVENT_ADD_LIFE_CYCLE_INFO(sessionItem->GetDescriptor().elementName_.GetBundleName(),
AppManagerAdapter::GetInstance().IsAppBackground(GetCallingUid(), GetCallingPid()),
sessionItem->GetDescriptor().sessionType_, false);
GetUsersManager().RemoveSessionForAllUser(sessionItem->GetPid(), sessionItem->GetAbilityName());
UpdateFrontSession(sessionItem, false);
{
std::lock_guard lockGuard(keyEventListLock_);
std::shared_ptr<std::list<sptr<AVSessionItem>>> keyEventList = GetCurKeyEventSessionList(userId);
CHECK_AND_RETURN_LOG(keyEventList != nullptr, "keyEventList ptr nullptr!");
auto it = std::find(keyEventList->begin(), keyEventList->end(), sessionItem);
if (it != keyEventList->end()) {
SLOGI("keyEventList remove %{public}s", sessionItem->GetBundleName().c_str());
keyEventList->erase(it);
}
}
SetCriticalWhenRelease(sessionItem);
}
HandleSessionReleaseInner();
}
void AVSessionService::SetCriticalWhenRelease(sptr<AVSessionItem> sessionItem)
{
uint32_t currentAllSessionSize = GetUsersManager().GetContainerFromAll().GetAllSessions().size();
SLOGI("size: %{public}u, Uid: %{public}d", currentAllSessionSize, sessionItem->GetUid());
if (currentAllSessionSize == 0) {
SetCritical(false);
} else if (currentAllSessionSize == 1) {
if (GetUsersManager().GetContainerFromAll().GetSessionByUid(ancoUid) != nullptr) {
SetCritical(false);
} else {
SLOGI("no anco session");
}
}
}
void AVSessionService::HandleSessionReleaseInner()
{
#ifdef START_STOP_ON_DEMAND_ENABLE
if (GetUsersManager().GetContainerFromAll().GetAllSessions().size() == 0) {
PublishEvent(mediaPlayStateFalse);
}
#endif
#ifdef CASTPLUS_CAST_ENGINE_ENABLE
SLOGI("call disable cast after session release task");
checkEnableCast(false);
#endif
}
void AVSessionService::HandleControllerRelease(AVControllerItem& controller)
{
auto pid = controller.GetPid();
std::lock_guard lockGuard(sessionServiceLock_);
auto it = controllers_.find(pid);
if (it == controllers_.end()) {
return;
}
it->second.remove(&controller);
if (it->second.empty()) {
controllers_.erase(pid);
}
}
std::int32_t AVSessionService::Dump(std::int32_t fd, const std::vector<std::u16string>& args)
{
if (fd < 0) {
SLOGE("dump fd invalid");
return ERR_INVALID_PARAM;
}
if (dumpHelper_ == nullptr) {
SLOGE("dumpHelper_ is nullptr!");
return ERR_INVALID_PARAM;
}
std::vector<std::string> argsInStr;
for (const auto& arg : args) {
SLOGI("Dump args: %s", Str16ToStr8(arg).c_str());
argsInStr.emplace_back(Str16ToStr8(arg));
}
std::string result;
dumpHelper_->Dump(argsInStr, result, *this);
std::int32_t ret = dprintf(fd, "%s", result.c_str());
if (ret < 0) {
SLOGI("dprintf to dump fd failed");
return ERR_INVALID_PARAM;
}
return AVSESSION_SUCCESS;
}
__attribute__((no_sanitize("cfi"))) std::shared_ptr<RemoteSessionCommandProcess> AVSessionService::GetService(
const std::string& deviceId)
{
SLOGI("Enter GetService.");
auto mgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (mgr == nullptr) {
SLOGE("GetService failed when GetSystemAbilityManager.");
return nullptr;
}
auto object = mgr->GetSystemAbility(AVSESSION_SERVICE_ID, deviceId);
if (object == nullptr) {
SLOGE("GetService failed to get AVSESSION_SERVICE_ID object.");
return nullptr;
}
std::shared_ptr<RemoteSessionCommandProcess> remoteService = std::make_shared<RemoteSessionCommandProcess>(object);
return remoteService;
}
bool AVSessionService::IsLocalDevice(const std::string& networkId)
{
std::string localNetworkId;
CHECK_AND_RETURN_RET_LOG(GetLocalNetworkId(localNetworkId) == AVSESSION_SUCCESS, AVSESSION_ERROR,
"GetLocalNetworkId error");
if (networkId == localNetworkId || networkId == "LocalDevice") {
SLOGI("This networkId is local device.");
return true;
}
SLOGI("This networkId is not local device.");
return false;
}
int32_t AVSessionService::GetLocalNetworkId(std::string& networkId)
{
#ifdef DEVICE_MANAGER_ENABLE
DistributedHardware::DmDeviceInfo deviceInfo;
int32_t ret = DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo("av_session", deviceInfo);
CHECK_AND_RETURN_RET_LOG(ret == 0, ret, "get local deviceInfo failed");
networkId = deviceInfo.networkId;
#else
networkId = "";
return AVSESSION_ERROR;
#endif
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::GetTrustedDeviceName(const std::string& networkId, std::string& deviceName)
{
#ifdef DEVICE_MANAGER_ENABLE
std::vector<OHOS::DistributedHardware::DmDeviceInfo> deviceList {};
#endif
if (IsLocalDevice(networkId)) {
deviceName = "LocalDevice";
return AVSESSION_SUCCESS;
}
#ifdef DEVICE_MANAGER_ENABLE
int32_t ret = GetTrustedDevicesInfo(deviceList);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "get devicesInfo failed");
for (const auto& device : deviceList) {
ret = strcmp(device.networkId, networkId.c_str());
if (ret == 0) {
deviceName = device.deviceName;
return AVSESSION_SUCCESS;
}
}
#endif
SLOGI("GetTrustedDeviceName is not find this device %{public}.6s", networkId.c_str());
return AVSESSION_ERROR;
}
#ifdef DEVICE_MANAGER_ENABLE
int32_t AVSessionService::GetTrustedDevicesInfo(std::vector<OHOS::DistributedHardware::DmDeviceInfo>& deviceList)
{
int32_t ret = DistributedHardware::DeviceManager::GetInstance().GetTrustedDeviceList("av_session", "", deviceList);
CHECK_AND_RETURN_RET_LOG(ret == 0, ret, "get trusted device list failed");
return AVSESSION_SUCCESS;
}
#endif
int32_t AVSessionService::SetBasicInfo(std::string& sessionInfo)
{
AVSessionBasicInfo basicInfo;
basicInfo.metaDataCap_ = AVMetaData::localCapability;
basicInfo.playBackStateCap_ = AVPlaybackState::localCapability;
basicInfo.controlCommandCap_ = AVControlCommand::localCapability;
int32_t ret = GetLocalNetworkId(basicInfo.networkId_);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, AVSESSION_ERROR, "GetLocalNetworkId failed");
ret = JsonUtils::SetSessionBasicInfo(sessionInfo, basicInfo);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, AVSESSION_ERROR, "SetDeviceId failed");
return AVSESSION_SUCCESS;
}
void AVSessionService::SetDeviceInfo(const std::vector<AudioStandard::AudioDeviceDescriptor>& castAudioDescriptors,
sptr <AVSessionItem>& session)
{
CHECK_AND_RETURN_LOG(session != nullptr && castAudioDescriptors.size() > 0, "invalid argument");
OutputDeviceInfo outputDeviceInfo;
outputDeviceInfo.deviceInfos_.clear();
int32_t castCategory = AVCastCategory::CATEGORY_LOCAL;
if (!IsLocalDevice(castAudioDescriptors[0].networkId_)) {
castCategory = AVCastCategory::CATEGORY_REMOTE;
}
for (const auto &audioDescriptor : castAudioDescriptors) {
DeviceInfo deviceInfo;
deviceInfo.castCategory_ = castCategory;
deviceInfo.deviceId_ = std::to_string(audioDescriptor.deviceId_);
deviceInfo.deviceName_ = audioDescriptor.deviceName_;
SLOGI("SetDeviceInfo the deviceName is %{public}s",
AVSessionUtils::GetAnonyDeviceName(audioDescriptor.deviceName_).c_str());
outputDeviceInfo.deviceInfos_.emplace_back(deviceInfo);
}
session->SetOutputDevice(outputDeviceInfo);
}
bool AVSessionService::GetAudioDescriptorByDeviceId(
const std::vector<std::shared_ptr<AudioStandard::AudioDeviceDescriptor>>& descriptors,
const std::string& deviceId,
AudioStandard::AudioDeviceDescriptor& audioDescriptor)
{
for (const auto& descriptor : descriptors) {
if (std::to_string(descriptor->deviceId_) == deviceId) {
audioDescriptor = *descriptor;
return true;
}
}
SLOGI("GetAudioDescriptorByDeviceId deviceId: is not found in all audio descriptors");
return false;
}
void AVSessionService::GetDeviceInfo(const sptr <AVSessionItem>& session,
const std::vector<AudioStandard::AudioDeviceDescriptor>& descriptors,
std::vector<AudioStandard::AudioDeviceDescriptor>& castSinkDescriptors,
std::vector<AudioStandard::AudioDeviceDescriptor>& cancelSinkDescriptors)
{
if (descriptors.size() != 1) {
SLOGI("descriptor size is %{public}d, not support", static_cast<int32_t>(descriptors.size()));
return;
}
castSinkDescriptors.push_back(descriptors[0]);
OutputDeviceInfo tempOutputDeviceInfo;
session->GetOutputDevice(tempOutputDeviceInfo);
// If not in remote, return directly
CHECK_AND_RETURN_LOG(tempOutputDeviceInfo.deviceInfos_.size() != 0, "deviceInfos size is 0, no need to cancel");
CHECK_AND_RETURN_LOG(tempOutputDeviceInfo.deviceInfos_[0].castCategory_ != 1,
"castCategory is %{public}d, no need to cancel", tempOutputDeviceInfo.deviceInfos_[0].castCategory_);
int32_t ret = GetAudioDescriptor(session->GetDescriptor().outputDeviceInfo_.deviceInfos_[0].deviceId_,
cancelSinkDescriptors);
CHECK_AND_RETURN_LOG(ret == AVSESSION_SUCCESS, "get cancelSinkDescriptors failed");
}
int32_t AVSessionService::SelectOutputDevice(const int32_t uid, const AudioDeviceDescriptor& descriptor)
{
sptr <AudioStandard::AudioRendererFilter> audioFilter = new(std::nothrow) AudioRendererFilter();
CHECK_AND_RETURN_RET_LOG(audioFilter != nullptr, ERR_NO_MEMORY, "new AudioRendererFilter failed");
audioFilter->uid = uid;
audioFilter->rendererInfo.contentType = ContentType::CONTENT_TYPE_MUSIC;
audioFilter->rendererInfo.streamUsage = StreamUsage::STREAM_USAGE_MEDIA;
std::vector<std::shared_ptr<AudioDeviceDescriptor>> audioDescriptor;
std::shared_ptr<AudioDeviceDescriptor> audioDeviceDescriptor = std::make_shared<AudioDeviceDescriptor>(descriptor);
CHECK_AND_RETURN_RET_LOG(audioDeviceDescriptor != nullptr, ERR_NO_MEMORY, "audioDeviceDescriptor is nullptr");
audioDescriptor.push_back(audioDeviceDescriptor);
SLOGI("select the device %{public}s role is %{public}d, networkId is %{public}.6s",
descriptor.deviceName_.c_str(), static_cast<int32_t>(descriptor.deviceRole_), descriptor.networkId_.c_str());
AudioSystemManager *audioSystemMgr = AudioSystemManager::GetInstance();
CHECK_AND_RETURN_RET_LOG(audioSystemMgr != nullptr, AVSESSION_ERROR, "get AudioSystemManager instance failed");
int32_t ret = audioSystemMgr->SelectOutputDevice(audioFilter, audioDescriptor);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, AVSESSION_ERROR, "SelectOutputDevice failed");
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::CastAudio(const SessionToken& token,
const std::vector<AudioStandard::AudioDeviceDescriptor>& sinkAudioDescriptors)
{
std::string sourceSessionInfo;
int32_t ret = SetBasicInfo(sourceSessionInfo);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "SetBasicInfo failed");
sptr<AVSessionItem> session = GetContainer().GetSessionById(token.sessionId);
CHECK_AND_RETURN_RET_LOG(session != nullptr, ERR_SESSION_NOT_EXIST, "session %{public}s not exist",
AVSessionUtils::GetAnonySessionId(token.sessionId).c_str());
ret = JsonUtils::SetSessionDescriptor(sourceSessionInfo, session->GetDescriptor());
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "SetDescriptorInfo failed");
ret = CastAudioProcess(sinkAudioDescriptors, sourceSessionInfo, session);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "CastAudioProcess failed");
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::CastAudioProcess(const std::vector<AudioStandard::AudioDeviceDescriptor>& descriptors,
const std::string& sourceSessionInfo,
sptr <AVSessionItem>& session)
{
std::vector<AudioDeviceDescriptor> castSinkDescriptors;
std::vector<AudioDeviceDescriptor> cancelSinkDescriptors;
GetDeviceInfo(session, descriptors, castSinkDescriptors, cancelSinkDescriptors);
if (cancelSinkDescriptors.size() > 0) {
int32_t ret = CancelCastAudioInner(cancelSinkDescriptors, sourceSessionInfo, session);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "CancelCastAudioInner failed");
}
if (castSinkDescriptors.size() > 0) {
int32_t ret = CastAudioInner(castSinkDescriptors, sourceSessionInfo, session);
if (ret != AVSESSION_SUCCESS) {
SLOGE("CastAudioInner failed, try cancel it. ret is %{public}d",
CancelCastAudioInner(castSinkDescriptors, sourceSessionInfo, session));
return ret;
}
}
SetDeviceInfo(descriptors, session);
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::CastAudioInner(const std::vector<AudioStandard::AudioDeviceDescriptor>& sinkAudioDescriptors,
const std::string& sourceSessionInfo,
const sptr <AVSessionItem>& session)
{
CHECK_AND_RETURN_RET_LOG(sinkAudioDescriptors.size() > 0, AVSESSION_ERROR, "sinkDescriptors is empty");
std::string sourceDevice;
CHECK_AND_RETURN_RET_LOG(GetLocalNetworkId(sourceDevice) == AVSESSION_SUCCESS, AVSESSION_ERROR,
"GetLocalNetworkId failed");
SLOGI("networkId_: %{public}.6s, role %{public}d", sinkAudioDescriptors[0].networkId_.c_str(),
static_cast<int32_t>(sinkAudioDescriptors[0].deviceRole_));
if (IsLocalDevice(sinkAudioDescriptors[0].networkId_)) {
int32_t ret = SelectOutputDevice(session->GetUid(), sinkAudioDescriptors[0]);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "selectOutputDevice failed");
return AVSESSION_SUCCESS;
}
SLOGI("sinkAudioDescriptors size is %{public}d", static_cast<int32_t>(sinkAudioDescriptors.size()));
for (const auto& sinkAudioDescriptor : sinkAudioDescriptors) {
std::string sinkSessionInfo;
auto service = GetService(sinkAudioDescriptor.networkId_);
CHECK_AND_RETURN_RET_LOG(service != nullptr, AVSESSION_ERROR, "GetService %{public}s failed",
sinkAudioDescriptor.networkId_.c_str());
int32_t ret = service->ProcessCastAudioCommand(RemoteServiceCommand::COMMAND_CAST_AUDIO, sourceSessionInfo,
sinkSessionInfo);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "ProcessCastAudioCommand failed");
std::string sinkCapability;
ret = JsonUtils::GetAllCapability(sinkSessionInfo, sinkCapability);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "GetAllCapability failed");
ret = session->CastAudioToRemote(sourceDevice, sinkAudioDescriptor.networkId_, sinkCapability);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "CastAudioToRemote failed");
HISYSEVENT_BEHAVIOR("SESSION_CAST",
"BUNDLE_NAME", session->GetDescriptor().elementName_.GetBundleName(),
"MODULE_NAME", session->GetDescriptor().elementName_.GetModuleName(),
"ABILITY_NAME", session->GetDescriptor().elementName_.GetAbilityName(),
"SESSION_PID", session->GetDescriptor().pid_,
"SESSION_UID", session->GetDescriptor().uid_,
"SESSION_ID", session->GetDescriptor().sessionId_,
"SESSION_TAG", session->GetDescriptor().sessionTag_,
"SESSION_TYPE", session->GetDescriptor().sessionType_,
"CAST_TYPE", 0,
"DEST_DEVICE_TYPE", sinkAudioDescriptor.deviceType_,
"DEST_DEVICE_NAME", AVSessionUtils::GetAnonyDeviceName(sinkAudioDescriptor.deviceName_).c_str(),
"DEST_DEVICE_ID", sinkAudioDescriptor.deviceId_,
"DETAILED_MSG", "avsession service cast audio");
ret = SelectOutputDevice(session->GetUid(), sinkAudioDescriptor);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "selectOutputDevice failed");
}
SLOGI("success");
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::CancelCastAudioInner(const std::vector<AudioStandard::AudioDeviceDescriptor>& sinkDevices,
const std::string& sourceSessionInfo,
const sptr <AVSessionItem>& session)
{
SLOGI("cancel sinkDevices size is %{public}d", static_cast<int32_t>(sinkDevices.size()));
CHECK_AND_RETURN_RET_LOG(!sinkDevices.empty(), AVSESSION_ERROR, "sinkDevices is empty");
for (const auto& sinkDevice : sinkDevices) {
if (IsLocalDevice(sinkDevice.networkId_)) {
SLOGI("cancel Local device %{public}.6s", sinkDevice.networkId_.c_str());
continue;
}
std::string sinkSessionInfo;
SLOGI("cancel sinkDevices sinkDevice.networkId_ is %{public}.6s", sinkDevice.networkId_.c_str());
auto service = GetService(sinkDevice.networkId_);
CHECK_AND_RETURN_RET_LOG(service != nullptr, AVSESSION_ERROR, "GetService %{public}s failed",
sinkDevice.networkId_.c_str());
int32_t ret = service->ProcessCastAudioCommand(RemoteServiceCommand::COMMAND_CANCEL_CAST_AUDIO,
sourceSessionInfo, sinkSessionInfo);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "ProcessCastAudioCommand failed");
ret = session->SourceCancelCastAudio(sinkDevice.networkId_);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "SourceCancelCastAudio failed");
}
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::CastAudioForNewSession(const sptr<AVSessionItem>& session)
{
SLOGI("new sessionId is %{public}s", AVSessionUtils::GetAnonySessionId(session->GetSessionId()).c_str());
SessionToken token;
token.sessionId = session->GetSessionId();
token.pid = session->GetPid();
token.uid = session->GetUid();
int32_t ret = AVSESSION_SUCCESS;
std::vector<AudioStandard::AudioDeviceDescriptor> castSinkDevices;
{
std::lock_guard lockGuard(outputDeviceIdLock_);
ret = GetAudioDescriptor(outputDeviceId_, castSinkDevices);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "GetAudioDescriptor failed");
}
ret = CastAudio(token, castSinkDevices);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "CastAudio error, session Id is %{public}s",
AVSessionUtils::GetAnonySessionId(token.sessionId).c_str());
SLOGI("success");
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::CastAudioForAll(const std::vector<AudioStandard::AudioDeviceDescriptor>& sinkAudioDescriptors)
{
CHECK_AND_RETURN_RET_LOG(sinkAudioDescriptors.size() > 0, ERR_INVALID_PARAM, "sinkAudioDescriptors is empty");
{
std::lock_guard lockGuard(isAllSessionCastLock_);
isAllSessionCast_ = false;
if (!IsLocalDevice(sinkAudioDescriptors[0].networkId_)) {
isAllSessionCast_ = true;
}
}
for (const auto& session : GetContainer().GetAllSessions()) {
SessionToken token;
token.sessionId = session->GetSessionId();
token.pid = session->GetPid();
token.uid = session->GetUid();
SLOGI("cast session %{public}s", AVSessionUtils::GetAnonySessionId(token.sessionId).c_str());
int32_t ret = CastAudio(token, sinkAudioDescriptors);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "CastAudio session %{public}s failed",
AVSessionUtils::GetAnonySessionId(token.sessionId).c_str());
{
std::lock_guard lockGuard(outputDeviceIdLock_);
outputDeviceId_ = session->GetDescriptor().outputDeviceInfo_.deviceInfos_[0].deviceId_;
}
}
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::ProcessCastAudioCommand(const RemoteServiceCommand command, const std::string& input,
std::string& output)
{
SLOGI("ProcessCastAudioCommand command is %{public}d", static_cast<int32_t>(command));
CHECK_AND_RETURN_RET_LOG(command > COMMAND_INVALID && command < COMMAND_MAX, AVSESSION_ERROR, "invalid command");
if (command == COMMAND_CAST_AUDIO) {
int ret = RemoteCastAudioInner(input, output);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "RemoteCastAudioInner error");
return AVSESSION_SUCCESS;
}
int ret = RemoteCancelCastAudioInner(input);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "RemoteCancelCastAudioInner error");
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::RemoteCastAudioInner(const std::string& sourceSessionInfo, std::string& sinkSessionInfo)
{
AVSessionDescriptor sourceDescriptor;
int32_t ret = JsonUtils::GetSessionDescriptor(sourceSessionInfo, sourceDescriptor);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "GetSessionDescriptor failed");
ret = SetBasicInfo(sinkSessionInfo);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, AVSESSION_ERROR, "SetBasicInfo failed");
AVSessionBasicInfo sinkDeviceInfo;
ret = JsonUtils::GetSessionBasicInfo(sinkSessionInfo, sinkDeviceInfo);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "GetBasicInfo failed");
sptr <AVSessionItem> session = CreateSessionInner(sourceDescriptor.sessionTag_, sourceDescriptor.sessionType_,
sourceDescriptor.isThirdPartyApp_,
sourceDescriptor.elementName_);
CHECK_AND_RETURN_RET_LOG(session != nullptr, AVSESSION_ERROR, "CreateSession failed");
{
std::lock_guard lockGuard(castAudioSessionMapLock_);
castAudioSessionMap_[sourceDescriptor.sessionId_] = session->GetSessionId();
}
AVSessionBasicInfo sourceDeviceInfo;
ret = JsonUtils::GetSessionBasicInfo(sourceSessionInfo, sourceDeviceInfo);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "GetBasicInfo failed");
std::string sourceCapability;
ret = JsonUtils::GetAllCapability(sourceSessionInfo, sourceCapability);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "GetAllCapability failed");
ret = session->CastAudioFromRemote(sourceDescriptor.sessionId_, sourceDeviceInfo.networkId_,
sinkDeviceInfo.networkId_, sourceCapability);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "CastAudioFromRemote failed");
JsonUtils::SetSessionDescriptor(sinkSessionInfo, session->GetDescriptor());
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::RemoteCancelCastAudioInner(const std::string& sessionInfo)
{
AVSessionBasicInfo sourceDeviceInfo;
int32_t ret = JsonUtils::GetSessionBasicInfo(sessionInfo, sourceDeviceInfo);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "GetBasicInfo failed");
AVSessionDescriptor sourceDescriptor;
ret = JsonUtils::GetSessionDescriptor(sessionInfo, sourceDescriptor);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "GetSessionDescriptor failed");
std::lock_guard lockGuard(castAudioSessionMapLock_);
auto iter = castAudioSessionMap_.find(sourceDescriptor.sessionId_);
CHECK_AND_RETURN_RET_LOG(iter != castAudioSessionMap_.end(), AVSESSION_ERROR, "no source session %{public}s",
AVSessionUtils::GetAnonySessionId(sourceDescriptor.sessionId_).c_str());
auto session = GetContainer().GetSessionById(iter->second);
CHECK_AND_RETURN_RET_LOG(session != nullptr, AVSESSION_ERROR, "no sink session %{public}s",
AVSessionUtils::GetAnonySessionId(iter->second).c_str());
ret = session->SinkCancelCastAudio();
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "SinkCancelCastAudio failed");
HandleSessionRelease(session->GetSessionId());
castAudioSessionMap_.erase(sourceDescriptor.sessionId_);
SLOGI("cancel source session %{public}s success",
AVSessionUtils::GetAnonySessionId(sourceDescriptor.sessionId_).c_str());
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::CancelCastAudioForClientExit(pid_t pid, const sptr<AVSessionItem>& session)
{
CHECK_AND_RETURN_RET_LOG(session != nullptr, AVSESSION_ERROR, "session is nullptr");
SLOGI("pid is %{public}d, sessionId is %{public}s", static_cast<int32_t>(pid),
AVSessionUtils::GetAnonySessionId(session->GetSessionId()).c_str());
std::string sourceSessionInfo;
int32_t ret = SetBasicInfo(sourceSessionInfo);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "SetBasicInfo failed");
ret = JsonUtils::SetSessionDescriptor(sourceSessionInfo, session->GetDescriptor());
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "SetDescriptorInfo failed");
std::vector<AudioStandard::AudioDeviceDescriptor> cancelSinkDevices;
ret = GetAudioDescriptor(session->GetDescriptor().outputDeviceInfo_.deviceInfos_[0].deviceId_, cancelSinkDevices);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "GetAudioDescriptor failed");
ret = CancelCastAudioInner(cancelSinkDevices, sourceSessionInfo, session);
CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "CancelCastAudioInner failed");
return AVSESSION_SUCCESS;
}
int32_t AVSessionService::GetAudioDescriptor(const std::string deviceId,
std::vector<AudioStandard::AudioDeviceDescriptor>& audioDeviceDescriptors)
{
auto audioDescriptors = AudioSystemManager::GetInstance()->GetDevices(ALL_L_D_DEVICES_FLAG);
AudioDeviceDescriptor audioDescriptor;
if (GetAudioDescriptorByDeviceId(audioDescriptors, deviceId, audioDescriptor)) {
audioDeviceDescriptors.push_back(audioDescriptor);
SLOGI("get audio networkId_ is %{public}.6s", audioDescriptor.networkId_.c_str());
return AVSESSION_SUCCESS;
}
SLOGI("can not get deviceId info");
return AVSESSION_ERROR;
}
void AVSessionService::ClearSessionForClientDiedNoLock(pid_t pid, bool continuePlay)
{
SLOGI("clear session in ");
auto sessions = GetUsersManager().GetContainerFromAll().GetSessionsByPid(pid);
for (const auto& session : sessions) {
SLOGI("check session release task for id %{public}s",
AVSessionUtils::GetAnonySessionId(session->GetSessionId()).c_str());
HandleSessionRelease(session->GetSessionId(), continuePlay);
}
}
void AVSessionService::ClearPcmSessionForClientDiedNoLock()
{
#ifdef CASTPLUS_CAST_ENGINE_ENABLE
SLOGI("clear PcmSession in ");
CHECK_AND_RETURN_LOG(pcmCastSession_ != nullptr, "pcmCastSession_ is nullptr");
pcmCastSession_->DestroyTask();
pcmCastSession_ = nullptr;
#endif //CASTPLUS_CAST_ENGINE_ENABLE
}
void AVSessionService::ClearControllerForClientDiedNoLock(pid_t pid)
{
auto it = controllers_.find(pid);
CHECK_AND_RETURN_LOG(it != controllers_.end(), "no find controller");
auto controllers = std::move(it->second);
SLOGI("remove controllers size=%{public}d without reply", static_cast<int>(controllers.size()));
if (!controllers.empty()) {
for (const auto& controller : controllers) {
controller->DestroyWithoutReply();
}
}
it = controllers_.find(pid);
CHECK_AND_RETURN_LOG(it != controllers_.end(), "no find controller");
controllers_.erase(pid);
}
ClientDeathRecipient::ClientDeathRecipient(const std::function<void()>& callback)
: callback_(callback)
{
SLOGD("construct");
}
void ClientDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& object)
{
if (callback_) {
callback_();
}
}
bool AVSessionService::CheckUserDirValid(int32_t userId)
{
std::string filePath = GetUsersManager().GetDirForCurrentUser(userId);
filesystem::path directory(filePath);
std::error_code errCode;
if (!filesystem::exists(directory, errCode)) {
SLOGE("check user dir not exsit %{public}s for user %{public}d, errCode %{public}d",
filePath.c_str(), userId, static_cast<int>(errCode.value()));
return false;
}
return true;
}
bool AVSessionService::CheckAndCreateDir(const string& filePath)
{
CHECK_AND_RETURN_RET_LOG(CheckUserDirValid(), false, "check userDir err!");
filesystem::path directory = filesystem::path(filePath).parent_path();
if (!filesystem::exists(directory)) {
SLOGI("check file not exist:%{public}s", filePath.c_str());
return false;
}
return true;
}
bool AVSessionService::FillFileWithEmptyContentEx(ofstream& fileWrite)
{
cJSON* emptyValueArray = cJSON_CreateArray();
CHECK_AND_RETURN_RET_LOG(emptyValueArray != nullptr, false, "emptyValueArray create nullptr");
if (cJSON_IsInvalid(emptyValueArray) || !cJSON_IsArray(emptyValueArray)) {
SLOGE("create emptyValueArray invalid");
cJSON_Delete(emptyValueArray);
return false;
}
char* emptyContent = cJSON_Print(emptyValueArray);
if (emptyContent == nullptr) {
SLOGE("newValueArray print fail nullptr");
cJSON_Delete(emptyValueArray);
return false;
}
std::string emptyContentStr(emptyContent);
SLOGD("LoadStringFromFileEx::Dump json object finished");
fileWrite.write(emptyContentStr.c_str(), emptyContentStr.length());
if (fileWrite.fail()) {
SLOGE("file empty init json fail !");
cJSON_free(emptyContent);
cJSON_Delete(emptyValueArray);
return false;
}
cJSON_free(emptyContent);
cJSON_Delete(emptyValueArray);
return true;
}
bool AVSessionService::LoadStringFromFileEx(const string& filePath, string& content)
{
SLOGD("file load in for path: %{public}s", filePath.c_str());
CheckAndCreateDir(filePath);
ifstream file(filePath.c_str());
if (!file.is_open()) {
SLOGD("file not open! try open first ! ");
file.open(filePath.c_str(), ios::out | ios::app);
if (!file.is_open()) {
SLOGE("open file again fail !");
return false;
}
}
file.seekg(0, ios::end);
const long fileLength = file.tellg();
SLOGD("get file length(%{public}ld)!", fileLength);
if (fileLength > maxFileLength) {
SLOGE("invalid file length(%{public}ld)!", fileLength);
return false;
}
if (fileLength <= 0) {
SLOGD("file new create empty ! try set init json ");
ofstream fileWrite;
fileWrite.open(filePath.c_str(), ios::out | ios::trunc);
if (!fileWrite.is_open()) {
SLOGE("open file in create new failed!");
file.close();
return false;
}
if (!FillFileWithEmptyContentEx(fileWrite)) {
SLOGE("file empty init json fail !");
file.close();
fileWrite.close();
return false;
}
fileWrite.close();
}
content.clear();
file.seekg(0, ios::beg);
copy(istreambuf_iterator<char>(file), istreambuf_iterator<char>(), back_inserter(content));
file.close();
return CheckStringAndCleanFile(filePath);
}
bool AVSessionService::SaveStringToFileEx(const std::string& filePath, const std::string& content)
{
SLOGD("file save in for path:%{public}s, content size:%{public}d", filePath.c_str(),
static_cast<int>(content.size()));
cJSON* checkValuesItem = cJSON_Parse(content.c_str());
CHECK_AND_RETURN_RET_LOG(checkValuesItem != nullptr, false, "cjson parse nullptr");
if (cJSON_IsInvalid(checkValuesItem)) {
SLOGE("cjson parse invalid for path:%{public}s", filePath.c_str());
cJSON_Delete(checkValuesItem);
return false;
}
cJSON_Delete(checkValuesItem);
ofstream file;
file.open(filePath.c_str(), ios::out | ios::trunc);
if (!file.is_open()) {
SLOGE("open file in save failed for path:%{public}s", filePath.c_str());
return false;
}
if (content.empty()) {
SLOGE("write content is empty, no need to do write for path:%{public}s", filePath.c_str());
file.close();
return true;
}
file.write(content.c_str(), content.length());
if (file.fail()) {
SLOGE("write content to file failed for path:%{public}s", filePath.c_str());
file.close();
return false;
}
file.close();
return CheckStringAndCleanFile(filePath);
}
bool AVSessionService::CheckStringAndCleanFile(const std::string& filePath)
{
string content {};
ifstream fileRead(filePath.c_str());
if (!fileRead.is_open()) {
SLOGD("file not open! try open first ! ");
fileRead.open(filePath.c_str(), ios::app);
if (!fileRead.is_open()) {
SLOGE("open file again fail !");
return false;
}
}
content.clear();
fileRead.seekg(0, ios::beg);
copy(istreambuf_iterator<char>(fileRead), istreambuf_iterator<char>(), back_inserter(content));
cJSON* checkValuesItem = cJSON_Parse(content.c_str());
bool isJsonDiscarded = false;
if (checkValuesItem == nullptr) {
isJsonDiscarded = true;
} else {
if (cJSON_IsInvalid(checkValuesItem)) {
isJsonDiscarded = true;
}
isJsonDiscarded = cJSON_IsArray(checkValuesItem) ? isJsonDiscarded : true;
cJSON_Delete(checkValuesItem);
}
if (isJsonDiscarded) {
SLOGE("check content discarded or not array!");
ofstream fileWrite;
fileWrite.open(filePath.c_str(), ios::out | ios::trunc);
if (!fileWrite.is_open()) {
SLOGE("open file in create new failed!");
fileRead.close();
return false;
}
if (!FillFileWithEmptyContentEx(fileWrite)) {
SLOGE("file empty init json fail! content %{public}s", content.c_str());
fileRead.close();
fileWrite.close();
return false;
}
fileWrite.close();
}
fileRead.close();
return true;
}
std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> AVSessionService::CreateWantAgent(
sptr<AVSessionItem> photoSession)
{
sptr<AVSessionItem> topSession;
{
std::lock_guard lockGuard(sessionServiceLock_);
topSession = topSession_;
}
CHECK_AND_RETURN_RET_LOG(!(photoSession == nullptr && topSession == nullptr), nullptr, "CreateWantAgent but null");
std::vector<AbilityRuntime::WantAgent::WantAgentConstant::Flags> flags;
flags.push_back(AbilityRuntime::WantAgent::WantAgentConstant::Flags::UPDATE_PRESENT_FLAG);
std::vector<std::shared_ptr<AAFwk::Want>> wants;
std::shared_ptr<AAFwk::Want> want = std::make_shared<AAFwk::Want>();
std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> launWantAgent;
string bundleName = DEFAULT_BUNDLE_NAME;
string abilityName = DEFAULT_ABILITY_NAME;
auto uid = -1;
auto isCustomer = false;
bool isAnco = false;
if (photoSession != nullptr) {
bundleName = photoSession->GetBundleName();
uid = photoSession->GetUid();
launWantAgent = std::make_shared<AbilityRuntime::WantAgent::WantAgent>(photoSession->GetLaunchAbility());
auto res = AbilityRuntime::WantAgent::WantAgentHelper::GetWant(launWantAgent, want);
isCustomer = (res == AVSESSION_SUCCESS) && (bundleName == want->GetElement().GetBundleName());
abilityName = isCustomer ? want->GetElement().GetAbilityName() : photoSession->GetAbilityName();
} else if (topSession != nullptr) {
bundleName = topSession->GetBundleName();
uid = topSession->GetUid();
launWantAgent = std::make_shared<AbilityRuntime::WantAgent::WantAgent>(topSession->GetLaunchAbility());
auto res = AbilityRuntime::WantAgent::WantAgentHelper::GetWant(launWantAgent, want);
isCustomer = (res == AVSESSION_SUCCESS) && (bundleName == want->GetElement().GetBundleName());
abilityName = isCustomer ? want->GetElement().GetAbilityName() : topSession->GetAbilityName();
isAnco = topSession->GetUid() == audioBrokerUid;
}
int32_t userId = GetUserIdFromCallingUid(uid);
SLOGI("CreateWantAgent bundle:%{public}s,ability:%{public}s,userId:%{public}d,Customer:%{public}d",
bundleName.c_str(), abilityName.c_str(), userId, isCustomer);
if (!isCustomer) {
AppExecFwk::ElementName element("", bundleName, abilityName);
want->SetElement(element);
if (isAnco) {
want->SetAction("action.system.home");
want->AddEntity("entity.system.home");
}
}
wants.push_back(want);
AbilityRuntime::WantAgent::WantAgentInfo wantAgentInfo(
0, AbilityRuntime::WantAgent::WantAgentConstant::OperationType::START_ABILITY, flags, wants, nullptr);
return isCustomer ?
launWantAgent : AbilityRuntime::WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo, userId, uid);
}
void AVSessionService::SetPcMode(bool isPcMode)
{
isPcMode_.store(isPcMode);
isPcMode ? HandlePcModeRemoveNotification() : HandlePcModeAddNotification();
}
void AVSessionService::HandlePcModeRemoveNotification()
{
std::lock_guard lockGuard(sessionServiceLock_);
CHECK_AND_RETURN_LOG(topSession_ != nullptr, "topSession_ is nullptr");
int32_t userId = topSession_->GetUserId();
CHECK_AND_RETURN_LOG(GetUsersManager().GetTopSession(userId).GetRefPtr() == topSession_.GetRefPtr(),
"topSession_ is not the top session");
hasMediaCapsule_ = false;
int32_t ret = Notification::NotificationHelper::CancelNotification(
std::to_string(userId), mediacontrollerNotifyId);
SLOGI("HandlePcModeRemoveNotification CancelNotification userId:%{public}d, ret=%{public}d", userId, ret);
}
void AVSessionService::HandlePcModeAddNotification()
{
std::lock_guard lockGuard(sessionServiceLock_);
CHECK_AND_RETURN_LOG(topSession_ != nullptr, "topSession_ is nullptr");
bool isPlaying = topSession_->IsCastConnected()
? topSession_->GetCastAVPlaybackState().GetState() == AVPlaybackState::PLAYBACK_STATE_PLAY
: IsLocalSessionPlaying(topSession_);
CHECK_AND_RETURN_LOG(isPlaying, "topSession is not playing");
NotifySystemUI(nullptr, IsCapsuleNeeded(), false);
}
bool AVSessionService::IsCapsuleNeeded()
{
std::lock_guard lockGuard(sessionServiceLock_);
CHECK_AND_RETURN_RET_LOG(topSession_ != nullptr, false, "audio broker capsule");
int32_t playMode = topSession_->GetBackgroundPlayMode();
return playMode == BackgroundPlayMode::ENABLE_BACKGROUND_PLAY || topSession_->IsCasting() ||
(playMode != BackgroundPlayMode::DISABLE_BACKGROUND_PLAY && topSession_->GetSessionType() == "audio");
}
void AVSessionService::RemoveExpired(std::list<std::chrono::system_clock::time_point> &list,
const std::chrono::system_clock::time_point &now, int32_t time)
{
auto iter = list.begin();
while (iter != list.end()) {
auto duration = now - static_cast<std::chrono::system_clock::time_point>(*iter);
int32_t durationInSeconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
if (std::abs(durationInSeconds) > time) {
iter = list.erase(iter);
} else {
break;
}
}
}
void AVSessionService::PublishEvent(int32_t mediaPlayState)
{
OHOS::AAFwk::Want want;
want.SetAction(MEDIA_CONTROL_STATE);
want.SetParam(MEDIA_PLAY_STATE, mediaPlayState);
EventFwk::CommonEventData data;
data.SetWant(want);
EventFwk::CommonEventPublishInfo publishInfo;
int ret = EventFwk::CommonEventManager::NewPublishCommonEvent(data, publishInfo);
SLOGI("NewPublishCommonEvent:%{public}d return %{public}d", mediaPlayState, ret);
}
std::string GetDefaultImageStr()
{
std::string imgStr = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQuMDAwMDAwIiBoZWlnaHQ9IjI0LjAwMDAwMCIgd"
"mlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5r"
"PSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KCTxkZXNjPgoJCQlDcmVhdGVkIHdpdGggUGl4c28uCgk8L2Rlc2M+Cgk8ZGV"
"mcy8+Cgk8ZyBvcGFjaXR5PSIwLjMwMDAwMCI+CgkJPGNpcmNsZSBpZD0i6JKZ54mIIiByPSIxMi4wMDAwMDAiIHRyYW5zZm9ybT0ibW"
"F0cml4KDAgMSAtMSAwIDEyIDEyKSIgZmlsbD0iI0ZGRkZGRiIgZmlsbC1vcGFjaXR5PSIxLjAwMDAwMCIvPgoJCTxjaXJjbGUgaWQ9I"
"uiSmeeJiCIgcj0iMTEuNTAwMDAwIiB0cmFuc2Zvcm09Im1hdHJpeCgwIDEgLTEgMCAxMiAxMikiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ry"
"b2tlLW9wYWNpdHk9IjAiIHN0cm9rZS13aWR0aD0iMS4wMDAwMDAiLz4KCTwvZz4KCTxtYXNrIGlkPSJtYXNrXzE1M183OTU5IiBmaWx"
"sPSJ3aGl0ZSI+CgkJPHBhdGggaWQ9IuW9oueKtue7k+WQiCIgZD0iTTE3LjY0MzYgNi42NTM5OUMxNy42NTM1IDYuNzE2OCAxNy42Nj"
"AxIDYuNzgwMDkgMTcuNjYzNCA2Ljg0MzUxTDE3LjY2NTkgNi45Mzg4NEwxNy42NjY2IDE0LjE2NjZDMTcuNjY2NiAxNC4xNzk3IDE3L"
"jY2NjIgMTQuMTkyNiAxNy42NjU1IDE0LjIwNTVDMTcuNjYxNiAxNC44NjgzIDE3LjY1NDYgMTUuMTgzNyAxNy41MTE0IDE1LjcxNDlD"
"MTcuMzY1OCAxNi4yNTQzIDE3LjA4MDkgMTYuNzYyMSAxNi41MTMyIDE3LjA4OTRDMTUuNDggMTcuNjg0OCAxNC4yMjggMTcuNDUwOSA"
"xMy43MTY3IDE2LjU2NjlDMTMuMjA1NCAxNS42ODI5IDEzLjYyODUgMTQuNDgzNSAxNC42NjE2IDEzLjg4ODFDMTUuMDg2MSAxMy42ND"
"M0IDE1LjYyNTcgMTMuNDI3MSAxNS45OTg5IDEzLjA4NTVDMTYuMjIzIDEyLjg4MDQgMTYuMzMyMiAxMi41ODU1IDE2LjMzMjIgMTEuO"
"TE4OEMxNi4zMzIyIDExLjkwMDQgMTYuMzMyNSAxMS44ODI0IDE2LjMzMyAxMS44NjUxTDE2LjMzMjcgOC41MDk4OUw5LjY2NjU2IDku"
"Njg2MjhMOS42NjY1NiAxNS4xMzEyQzkuNjY3MyAxNS4yNzA4IDkuNjY3MjQgMTUuNDExMyA5LjY2NjU2IDE1LjU1MDNMOS42NjY1NiA"
"xNS42NjY3QzkuNjY2NTYgMTUuNjc4MyA5LjY2NjI2IDE1LjY4OTggOS42NjU2NSAxNS43MDE0QzkuNjYxNSAxNi4zMDk2IDkuNjQ5Mz"
"UgMTYuNjIwNCA5LjUxMjA4IDE3LjEyOTVDOS4zNjY1OCAxNy42Njg4IDkuMDgxNiAxOC4xNzY3IDguNTEzOTIgMTguNTAzOUM3LjQ4M"
"DcxIDE5LjA5OTQgNi4yMjg3IDE4Ljg2NTQgNS43MTc0MSAxNy45ODE0QzUuMjA2MTIgMTcuMDk3NCA1LjYyOTIxIDE1Ljg5OCA2LjY2"
"MjM1IDE1LjMwMjZDNy4wODY3OSAxNS4wNTggNy42MjY0IDE0Ljg0MTcgNy45OTk2MyAxNC41QzguMjIzNjkgMTQuMjk0OSA4LjMzMjk"
"1IDE0IDguMzMyOTUgMTMuMzMzM0M4LjMzMjk1IDEzLjMyMjcgOC4zMzMwNyAxMy4zMTIyIDguMzMzMjUgMTMuMzAxOUw4LjMzMzI1ID"
"cuODMwNzVDOC4zMzMyNSA2Ljk2NzUzIDguOTM0MTQgNi4yMjcwNSA5Ljc2NjYgNi4wNDE1Nkw5Ljg4MTUzIDYuMDE5NzFMMTUuNTQ3N"
"SA1LjEyNzk5QzE2LjU0NzcgNC45NzA1MiAxNy40ODYyIDUuNjUzNzUgMTcuNjQzNiA2LjY1Mzk5WiIgY2xpcC1ydWxlPSJldmVub2Rk"
"IiBmaWxsPSIiIGZpbGwtb3BhY2l0eT0iMS4wMDAwMDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPgoJPC9tYXNrPgoJPHBhdGggaWQ9IuW"
"9oueKtue7k+WQiCIgZD0iTTE3LjY0MzYgNi42NTM5OUMxNy42NTM1IDYuNzE2OCAxNy42NjAxIDYuNzgwMDkgMTcuNjYzNCA2Ljg0Mz"
"UxTDE3LjY2NTkgNi45Mzg4NEwxNy42NjY2IDE0LjE2NjZDMTcuNjY2NiAxNC4xNzk3IDE3LjY2NjIgMTQuMTkyNiAxNy42NjU1IDE0L"
"jIwNTVDMTcuNjYxNiAxNC44NjgzIDE3LjY1NDYgMTUuMTgzNyAxNy41MTE0IDE1LjcxNDlDMTcuMzY1OCAxNi4yNTQzIDE3LjA4MDkg"
"MTYuNzYyMSAxNi41MTMyIDE3LjA4OTRDMTUuNDggMTcuNjg0OCAxNC4yMjggMTcuNDUwOSAxMy43MTY3IDE2LjU2NjlDMTMuMjA1NCA"
"xNS42ODI5IDEzLjYyODUgMTQuNDgzNSAxNC42NjE2IDEzLjg4ODFDMTUuMDg2MSAxMy42NDM0IDE1LjYyNTcgMTMuNDI3MSAxNS45OT"
"g5IDEzLjA4NTVDMTYuMjIzIDEyLjg4MDQgMTYuMzMyMiAxMi41ODU1IDE2LjMzMjIgMTEuOTE4OEMxNi4zMzIyIDExLjkwMDQgMTYuM"
"zMyNSAxMS44ODI0IDE2LjMzMyAxMS44NjUxTDE2LjMzMjcgOC41MDk4OUw5LjY2NjU2IDkuNjg2MjhMOS42NjY1NiAxNS4xMzEyQzku"
"NjY3MyAxNS4yNzA4IDkuNjY3MjQgMTUuNDExMyA5LjY2NjU2IDE1LjU1MDNMOS42NjY1NiAxNS42NjY3QzkuNjY2NTYgMTUuNjc4MyA"
"5LjY2NjI2IDE1LjY4OTggOS42NjU2NSAxNS43MDE0QzkuNjYxNSAxNi4zMDk2IDkuNjQ5MzUgMTYuNjIwNCA5LjUxMjA4IDE3LjEyOT"
"VDOS4zNjY1OCAxNy42Njg4IDkuMDgxNiAxOC4xNzY3IDguNTEzOTIgMTguNTAzOUM3LjQ4MDcxIDE5LjA5OTQgNi4yMjg3IDE4Ljg2N"
"TQgNS43MTc0MSAxNy45ODE0QzUuMjA2MTIgMTcuMDk3NCA1LjYyOTIxIDE1Ljg5OCA2LjY2MjM1IDE1LjMwMjZDNy4wODY3OSAxNS4w"
"NTggNy42MjY0IDE0Ljg0MTcgNy45OTk2MyAxNC41QzguMjIzNjkgMTQuMjk0OSA4LjMzMjk1IDE0IDguMzMyOTUgMTMuMzMzM0M4LjM"
"zMjk1IDEzLjMyMjcgOC4zMzMwNyAxMy4zMTIyIDguMzMzMjUgMTMuMzAxOUw4LjMzMzI1IDcuODMwNzVDOC4zMzMyNSA2Ljk2NzUzID"
"guOTM0MTQgNi4yMjcwNSA5Ljc2NjYgNi4wNDE1Nkw5Ljg4MTUzIDYuMDE5NzFMMTUuNTQ3NSA1LjEyNzk5QzE2LjU0NzcgNC45NzA1M"
"iAxNy40ODYyIDUuNjUzNzUgMTcuNjQzNiA2LjY1Mzk5WiIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsPSIjMDAwMDAwIiBmaWxsLW9w"
"YWNpdHk9IjAuNDAwMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIG1hc2s9InVybCgjbWFza18xNTNfNzk1OSkiLz4KCTxwYXRoIGlkPSL"
"lvaLnirbnu5PlkIgiIGQ9IiIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsPSIjMDAwMDAwIiBmaWxsLW9wYWNpdHk9IjAuMDAwMDAwIi"
"BmaWxsLXJ1bGU9ImV2ZW5vZGQiLz4KPC9zdmc+Cg==";
return imgStr;
}
std::shared_ptr<Media::PixelMap> ConvertDefaultImage()
{
if (g_defaultMediaImage) {
return g_defaultMediaImage;
}
std::string image = GetDefaultImageStr();
uint32_t errorCode = 0;
Media::SourceOptions opts;
auto imageSource = Media::ImageSource::CreateImageSource(reinterpret_cast<const uint8_t*>(image.c_str()),
image.length(), opts, errorCode);
if (imageSource != nullptr) {
Media::DecodeOptions dOpts;
dOpts.allocatorType = Media::AllocatorType::HEAP_ALLOC;
dOpts.desiredSize.width = DEFAULT_IMAGE_SIZE;
dOpts.desiredSize.height = DEFAULT_IMAGE_SIZE;
g_defaultMediaImage = imageSource->CreatePixelMap(dOpts, errorCode);
if (g_defaultMediaImage != nullptr) {
SLOGI("ConvertDefaultImage CreatePixelMap success");
return g_defaultMediaImage;
}
} else {
SLOGE("ConvertDefaultImage createImageSource fail");
}
return nullptr;
}
void SetNotificationExtra(Notification::NotificationRequest* request, const std::string &key, AAFwk::IInterface *value)
{
std::shared_ptr<AAFwk::WantParams> wantParam = request->GetAdditionalData() == nullptr ?
std::make_shared<AAFwk::WantParams>() : request->GetAdditionalData();
wantParam->SetParam(key, value);
request->SetAdditionalData(wantParam);
}
void AddCapsule(std::string title, bool isCapsuleUpdate, std::shared_ptr<Media::PixelMap> pixelMap,
std::shared_ptr<Notification::NotificationLocalLiveViewContent> content,
Notification::NotificationRequest* request)
{
const float scaleSize = 0.3;
if (pixelMap == nullptr) {
SLOGI("AddCapsule ConvertDefaultImage");
pixelMap = ConvertDefaultImage();
} else {
pixelMap->scale(scaleSize, scaleSize, Media::AntiAliasingOption::HIGH);
}
auto capsule = Notification::NotificationCapsule();
capsule.SetIcon(pixelMap);
capsule.SetTitle(title);
if (isCapsuleUpdate) {
SLOGI("MediaCapsule CapsuleUpdate");
SetNotificationExtra(request, "hw_capsule_icon_animation_type", OHOS::AAFwk::Integer::Box(1));
}
if (!g_isCapsuleLive2) {
capsule.SetBackgroundColor("#2E3033");
}
content->SetCapsule(capsule);
content->addFlag(Notification::NotificationLocalLiveViewContent::LiveViewContentInner::CAPSULE);
SLOGI("PublishNotification with MediaCapsule");
}
void GetBundlePixelMap(sptr<AVSessionItem> photoSession, std::shared_ptr<Media::PixelMap>& pixelMap)
{
CHECK_AND_RETURN_LOG(photoSession != nullptr, "GetBundlePixelMap photoSession nullptr error");
std::string icon;
BundleStatusAdapter::GetInstance().GetBundleIcon(photoSession->GetBundleName(),
photoSession->GetAbilityName(), icon);
CHECK_AND_RETURN_LOG(!icon.empty(), "icon is empty");
Media::SourceOptions opts;
uint32_t errorCode = 0;
auto imageSource = Media::ImageSource::CreateImageSource(reinterpret_cast<const uint8_t*>(icon.c_str()),
icon.length(), opts, errorCode);
CHECK_AND_RETURN_LOG(imageSource != nullptr, "CreateImageSource failed");
Media::DecodeOptions dOpts;
dOpts.allocatorType = Media::AllocatorType::HEAP_ALLOC;
pixelMap = imageSource->CreatePixelMap(dOpts, errorCode);
}
bool AVSessionService::NotifyFlowControl()
{
// flow control
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
RemoveExpired(flowControlPublishTimestampList_, now);
if (flowControlPublishTimestampList_.size() >= MAX_NOTIFICATION_NUM) {
SLOGE("PublishNotification Exeed MAX_NOTIFICATION_NUM");
return true;
}
flowControlPublishTimestampList_.push_back(now);
return false;
}
std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> AVSessionService::CreateNftRemoveWant(int32_t uid, bool isPhoto)
{
std::vector<std::shared_ptr<AAFwk::Want>> wants;
std::shared_ptr<AAFwk::Want> want = std::make_shared<AAFwk::Want>();
if (want != nullptr) {
AAFwk::WantParams wantParams;
wantParams.SetParam("isPhoto", AAFwk::Boolean::Box(isPhoto));
wantParams.SetParam("uid", AAFwk::Integer::Box(uid));
want->SetParams(wantParams);
want->SetAction("EVENT_REMOVE_MEDIACONTROLLER_LIVEVIEW");
wants.push_back(want);
}
AbilityRuntime::WantAgent::WantAgentInfo wantAgentInfo(
0,
AbilityRuntime::WantAgent::WantAgentConstant::OperationType::SEND_COMMON_EVENT,
AbilityRuntime::WantAgent::WantAgentConstant::Flags::UPDATE_PRESENT_FLAG,
wants,
nullptr
);
int32_t userId = GetUserIdFromCallingUid(uid);
SLOGI("CreateNftRemoveWant with userId:%{public}d|uid:%{public}d", userId, uid);
return AbilityRuntime::WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo, userId, uid);
}
std::string AVSessionService::GetLocalTitle()
{
sptr<AVSessionItem> topSession;
{
std::lock_guard lockGuard(sessionServiceLock_);
topSession = topSession_;
}
CHECK_AND_RETURN_RET_LOG(topSession != nullptr, "", "getlocalTile but topsession get null");
AVMetaData meta = topSession->GetMetaData();
bool isTitleLyric = (topSession->GetBundleName() == DEFAULT_BUNDLE_NAME) && !meta.GetDescription().empty();
bool isAncoLyric = (topSession->GetUid() == audioBrokerUid && meta.GetArtist().find("-") != std::string::npos);
std::string songName;
if (isTitleLyric) {
std::string description = meta.GetDescription();
size_t pos = description.find(";");
if (pos != std::string::npos) {
songName = description.substr(0, pos);
}
SLOGI("GetLocalTitle description:%{public}s, title:%{public}s", description.c_str(),
AVSessionUtils::GetAnonyTitle(songName.c_str()).c_str());
} else if (isAncoLyric) {
songName = topSession->GetLyricTitle();
SLOGI("GetLocalTitle isAncoLyric title:%{public}s",
AVSessionUtils::GetAnonyTitle(songName.c_str()).c_str());
}
std::string localTitle = (isTitleLyric || isAncoLyric) && !songName.empty() ? songName : meta.GetTitle();
SLOGI("GetLocalTitle localTitle:%{public}s|songName empty:%{public}d",
AVSessionUtils::GetAnonyTitle(localTitle).c_str(), songName.empty());
return localTitle;
}
void AVSessionService::DealFlowControl(int32_t uid, bool isBroker)
{
AVSessionEventHandler::GetInstance().AVSessionPostTask(
[this, uid, isBroker]() {
bool isTopSessionNtf = false;
{
std::lock_guard lockGuard(sessionServiceLock_);
isTopSessionNtf = topSession_ != nullptr && (topSession_->GetUid() == uid ||
(isBroker && topSession_->GetUid() == audioBrokerUid));
}
std::lock_guard lockGuard(notifyLock_);
hasRemoveEvent_ = false;
CHECK_AND_RETURN_LOG(isTopSessionNtf, "not top session");
auto ret = Notification::NotificationHelper::PublishNotification(g_NotifyRequest);
SLOGI("WaitPublish uid %{public}d, isTop %{public}d result %{public}d", uid, isTopSessionNtf, ret);
}, "NotifyFlowControl", CLICK_TIMEOUT);
}
// LCOV_EXCL_START
bool AVSessionService::CheckNotificationEnabled()
{
#ifdef DEVICE_MANAGER_ENABLE
bool is2in1 = (GetLocalDeviceType() == DistributedHardware::DmDeviceType::DEVICE_TYPE_2IN1);
#endif
bool isSupportOuterScreen = false;
bool is2in1WithOuterScreen = false;
{
std::string foldScreenType = system::GetParameter("const.window.foldscreen.type", DEFAULT_FOLD_SCREEN_TYPE);
std::vector<std::string> parts;
size_t start = 0;
size_t pos = foldScreenType.find(',');
while (pos != std::string::npos) {
parts.push_back(foldScreenType.substr(start, pos - start));
start = pos + 1;
pos = foldScreenType.find(',', start);
}
parts.push_back(foldScreenType.substr(start));
if (parts.size() > 1) {
isSupportOuterScreen = (std::stoi(parts[1]) == OUTER_SCREEN_TYPE_VALUE);
}
}
#ifdef DEVICE_MANAGER_ENABLE
is2in1WithOuterScreen = is2in1 && isSupportOuterScreen;
CHECK_AND_RETURN_RET_LOG(!is2in1 || is2in1WithOuterScreen, false, "2in1 not support.");
#else
CHECK_AND_RETURN_RET_LOG(!isCastableDevice_, false, "castable device is not support.");
#endif
bool isPcMode = system::GetParameter("const.window.support_window_pcmode_switch", "false") == "true" &&
system::GetParameter("persist.sceneboard.ispcmode", "false") == "true";
CHECK_AND_RETURN_RET_LOG(!isPcMode || is2in1WithOuterScreen, false, "pc mode not support.");
CHECK_AND_RETURN_RET_LOG(isNtfEnabled_.load(), false, "ntf settings off");
return true;
}
// LCOV_EXCL_START
void AVSessionService::NotifySystemUI(sptr<AVSessionItem> photoSession, bool addCapsule, bool isCapsuleUpdate)
{
CHECK_AND_RETURN_LOG(CheckNotificationEnabled(), "check notification not enabled");
int32_t result = Notification::NotificationHelper::SubscribeLocalLiveViewNotification(NOTIFICATION_SUBSCRIBER);
CHECK_AND_RETURN_LOG(result == ERR_OK, "create notification subscriber error %{public}d", result);
SLOGI("NotifySystemUI photoSession %{public}d addCapsule %{public}d isCapsuleUpdate %{public}d",
static_cast<int>(photoSession != nullptr), addCapsule, isCapsuleUpdate);
Notification::NotificationRequest request;
std::shared_ptr<Notification::NotificationLocalLiveViewContent> localLiveViewContent =
std::make_shared<Notification::NotificationLocalLiveViewContent>();
CHECK_AND_RETURN_LOG(localLiveViewContent != nullptr, "avsession item local live view content nullptr error");
localLiveViewContent->SetType(photoSession ?
systemuiLiveviewTypeCodePhoto : systemuiLiveviewTypeCodeMediacontroller);
localLiveViewContent->SetTitle("AVSession NotifySystemUI");
localLiveViewContent->SetText("AVSession NotifySystemUI");
std::shared_ptr<Notification::NotificationContent> content =
std::make_shared<Notification::NotificationContent>(localLiveViewContent);
CHECK_AND_RETURN_LOG(content != nullptr, "avsession item notification content nullptr error");
int32_t userId = photoSession ? photoSession->GetUserId() : GetUsersManager().GetCurrentUserId();
auto uid = topSession_ ? (topSession_->GetUid() == audioBrokerUid ?
BundleStatusAdapter::GetInstance().GetUidFromBundleName(topSession_->GetBundleName(), userId) :
topSession_->GetUid()) : -1;
std::shared_ptr<Media::PixelMap> pixelMap;
bool isBroker = false;
if (photoSession) {
GetBundlePixelMap(photoSession, pixelMap);
AddCapsule(photoSession->GetMetaData().GetTitle(), isCapsuleUpdate, pixelMap,
localLiveViewContent, &(request));
request.SetOwnerUid(photoSession->GetUid());
request.SetNotificationId(photoNotifyId);
} else {
if (topSession_) {
if (addCapsule) {
std::shared_ptr<AVSessionPixelMap> iPixelMap = std::make_shared<AVSessionPixelMap>();
AVQueueItem item;
topSession_->GetCurrentCastItem(item);
bool isCast = item.GetDescription() && !item.GetDescription()->GetPcmSrc();
topSession_->ReadMetaDataImg(iPixelMap, isCast);
pixelMap = AVSessionPixelMapAdapter::ConvertFromInner(iPixelMap, false);
std::string notifyText = isCast ? item.GetDescription()->GetTitle() : GetLocalTitle();
AddCapsule(notifyText, isCapsuleUpdate, pixelMap, localLiveViewContent, &(request));
AVSessionEventHandler::GetInstance().AVSessionRemoveTask("CheckCardStateChangeStop");
hasCardStateChangeStopTask_ = false;
}
if (topSession_->IsNotShowNotification()) {
SetNotificationExtra(&(request), "hw_live_view_hidden_when_keyguard", OHOS::AAFwk::Boolean::Box(true));
SLOGI("PublishNotification with hw_live_view_hidden_when_keyguard uid: %{public}d", uid);
}
}
hasMediaCapsule_ = addCapsule;
request.SetOwnerUid(uid);
request.SetNotificationId(mediacontrollerNotifyId);
isBroker = topSession_ != nullptr && topSession_->GetUid() == audioBrokerUid;
}
request.SetSlotType(Notification::NotificationConstant::SlotType::LIVE_VIEW);
request.SetContent(content);
request.SetCreatorUid(avSessionUid);
request.SetUnremovable(true);
request.SetInProgress(true);
request.SetIsAgentNotification(true);
if (isBroker) {
request.SetOwnerUserId(userId);
SetNotificationExtra(&(request), "is_ancoNotification", OHOS::AAFwk::Boolean::Box(true));
}
std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> wantAgent = CreateWantAgent(photoSession);
CHECK_AND_RETURN_LOG(wantAgent != nullptr, "wantAgent nullptr error");
request.SetWantAgent(wantAgent);
request.SetLabel(std::to_string(userId));
std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> removeWantAgent = CreateNftRemoveWant(
photoSession ? photoSession->GetUid() : uid, photoSession ? true : false);
request.SetRemovalWantAgent(removeWantAgent);
{
std::lock_guard lockGuard(notifyLock_);
g_NotifyRequest = request;
}
AVSessionEventHandler::GetInstance().AVSessionRemoveTask("NotifyFlowControl");
Notification::NotificationHelper::SetHashCodeRule(1);
if (photoSession) {
result = Notification::NotificationHelper::PublishNotification(request);
SLOGI("PublishNotification uid %{public}d, user id %{public}d, result %{public}d", uid, userId, result);
} else {
if (NotifyFlowControl()) {
DealFlowControl(uid, isBroker);
} else {
hasRemoveEvent_ = false;
result = Notification::NotificationHelper::PublishNotification(request);
SLOGI("PublishNotification uid %{public}d, user id %{public}d, result %{public}d", uid, userId, result);
}
}
}
// LCOV_EXCL_STOP
void AVSessionService::NotifyRemoteDistributedSessionControllersChanged(
const std::vector<sptr<IRemoteObject>>& sessionControllers)
{
std::lock_guard lockGuard(sessionListenersLock_);
std::list<int32_t> allUserList = GetUsersManager().GetAliveUserList();
SLOGI("NotifyRemoteDistributedSessionControllersChanged size: %{public}zu|%{public}zu",
sessionControllers.size(), allUserList.size());
#ifdef CAR_FEATURE_ENABLE
auto& listenersMapByUserIdForAudioZone = GetUsersManager().GetSessionListenersMapForAudioZone();
#endif
for (int32_t& userId : allUserList) {
std::map<pid_t, sptr<ISessionListener>> listenerMap = GetUsersManager().GetSessionListener(userId);
for (const auto& [pid, listener] : listenerMap) {
CHECK_AND_CONTINUE(listener != nullptr);
AVSESSION_TRACE_SYNC_START("AVSessionService::OnRemoteDistributedSessionChange");
listener->OnRemoteDistributedSessionChange(sessionControllers);
}
#ifdef CAR_FEATURE_ENABLE
auto listenersForUserIt = listenersMapByUserIdForAudioZone.find(userId);
CHECK_AND_CONTINUE(listenersForUserIt != listenersMapByUserIdForAudioZone.end());
for (const auto& [pid, listener] : listenersForUserIt->second) {
CHECK_AND_CONTINUE(listener != nullptr);
AVSESSION_TRACE_SYNC_START("AVSessionService::OnRemoteDistributedSessionChange");
listener->OnRemoteDistributedSessionChange(sessionControllers);
}
#endif
}
std::map<pid_t, sptr<ISessionListener>> listenerMapForAll = GetUsersManager().GetSessionListenerForAllUsers();
for (const auto& [pid, listener] : listenerMapForAll) {
AVSESSION_TRACE_SYNC_START("AVSessionService::OnRemoteDistributedSessionChange");
if (listener != nullptr) {
listener->OnRemoteDistributedSessionChange(sessionControllers);
}
}
{
std::lock_guard lockGuard(migrateListenersLock_);
for (const auto& listener : innerSessionListeners_) {
if (listener != nullptr) {
listener->OnRemoteDistributedSessionChange(sessionControllers);
}
}
}
}
void AVSessionService::InitRadarBMS()
{
AVSessionRadar::GetInstance().InitBMS();
}
std::function<bool(int32_t, int32_t)> AVSessionService::GetAllowedPlaybackCallbackFunc()
{
return [](int32_t uid, int32_t pid) -> bool {
auto mgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
CHECK_AND_RETURN_RET_LOG(mgr != nullptr, true, "SystemAbilityManager is null");
auto object = mgr->CheckSystemAbility(APP_MGR_SERVICE_ID);
CHECK_AND_RETURN_RET_LOG(object != nullptr, true, "APP_MAGR_SERVICE is null");
bool hasSession = GetContainer().PidHasSession(pid);
bool isBack = AppManagerAdapter::GetInstance().IsAppBackground(uid, pid);
bool isSystem = PermissionChecker::GetInstance().CheckSystemPermissionByUid(uid);
auto ret = hasSession || isSystem || !isBack;
SLOGI("avsession uid=%{public}d pid=%{public}d hasSession=%{public}d isBack=%{public}d isSystem=%{public}d",
uid, pid, hasSession, isBack, isSystem);
return ret;
};
}
int32_t AVSessionService::StartDesktopLyricAbility(const std::string &sessionId, const std::string &handler)
{
int32_t userId = GetUsersManager().GetCurrentUserId();
int32_t state = GetDesktopLyricAbilityState(userId);
CHECK_AND_RETURN_RET_LOG(state != DESKTOP_LYRICS_ABILITY_CONNECTING &&
state != DESKTOP_LYRICS_ABILITY_CONNECTED, AVSESSION_SUCCESS,
"desktop lyric ability is already started");
bool shouldBeRecreated = state == DESKTOP_LYRICS_ABILITY_DISCONNECTED;
SetDesktopLyricAbilityState(userId, DESKTOP_LYRICS_ABILITY_CONNECTING);
SLOGI("Start enabling the desktop lyrics feature.");
int32_t result = ExtensionConnectHelper::GetInstance().StartDesktopLyricAbility(sessionId, handler, userId,
[this](int32_t userId, int32_t state) { SetDesktopLyricAbilityState(userId, state); }, shouldBeRecreated);
if (result != AVSESSION_SUCCESS) {
SetDesktopLyricAbilityState(userId, DESKTOP_LYRICS_ABILITY_DEFAULT);
SLOGE("StartDesktopLyricAbility failed.");
}
return result;
}
int32_t AVSessionService::StopDesktopLyricAbility()
{
int32_t userId = GetUsersManager().GetCurrentUserId();
int32_t state = GetDesktopLyricAbilityState(userId);
CHECK_AND_RETURN_RET_LOG(state != DESKTOP_LYRICS_ABILITY_DISCONNECTING &&
state != DESKTOP_LYRICS_ABILITY_DISCONNECTED, AVSESSION_SUCCESS,
"desktop lyric ability is already stopped");
SetDesktopLyricAbilityState(userId, DESKTOP_LYRICS_ABILITY_DISCONNECTING);
SLOGI("Disable the desktop lyrics feature.");
ExtensionConnectHelper::GetInstance().StopDesktopLyricAbility(userId);
return AVSESSION_SUCCESS;
}
void AVSessionService::SetDesktopLyricAbilityState(int32_t userId, int32_t state)
{
std::lock_guard<std::mutex> lock(desktopLyricAbilityStateMutex_);
CHECK_AND_RETURN_LOG(state >= DESKTOP_LYRICS_ABILITY_DEFAULT && state <= DESKTOP_LYRICS_ABILITY_DISCONNECTED,
"state value invalid");
SLOGI("set userId:%{public}d: desktop lyric ability state:%{public}d", userId, state);
desktopLyricAbilityStateMap_[userId] = state;
}
int32_t AVSessionService::GetDesktopLyricAbilityState(int32_t userId)
{
std::lock_guard<std::mutex> lock(desktopLyricAbilityStateMutex_);
return desktopLyricAbilityStateMap_[userId];
}
int32_t AVSessionService::UploadDesktopLyricOperationInfo(const std::string &sessionId,
const std::string &handler, uint32_t sceneCode)
{
int32_t userId = GetUsersManager().GetCurrentUserId();
int32_t state = GetDesktopLyricAbilityState(userId);
CHECK_AND_RETURN_RET_LOG(state == DESKTOP_LYRICS_ABILITY_CONNECTED, AVSESSION_ERROR,
"desktop lyric ability is not connected");
return ExtensionConnectHelper::GetInstance().UploadDesktopLyricOperationInfo(sessionId, handler, sceneCode,
userId);
}
void AVSessionService::UpdateNtfEnable(bool isMediaNtfEnable) {
SLOGI("UpdateNtfEnable %{public}d", isMediaNtfEnable);
isNtfEnabled_.store(isMediaNtfEnable);
if (!isMediaNtfEnable) {
int32_t userId = GetUsersManager().GetCurrentUserId();
Notification::NotificationHelper::CancelNotification(std::to_string(userId), mediacontrollerNotifyId);
Notification::NotificationHelper::CancelNotification(std::to_string(userId), photoNotifyId);
}
}
#ifdef CAR_FEATURE_ENABLE
void AVSessionService::NotifySessionAddForAudioZone(const AVSessionDescriptor& descriptor)
{
std::lock_guard lockGuard(sessionListenersLock_);
GetUsersManager().UpdateZoneToUseridMap(descriptor.userId_);
std::vector<int32_t> userIdsInSameZone = GetUsersManager().GetUsersInSameAudioZone(descriptor.userId_);
auto& listenersMapByUserIdForAudioZone = GetUsersManager().GetSessionListenersMapForAudioZone();
CHECK_AND_RETURN_LOG(!listenersMapByUserIdForAudioZone.empty(),
"NotifySessionAddForAudioZone no listeners for user:%{public}d", descriptor.userId_);
for (int32_t userId : userIdsInSameZone) {
auto listenersForUserIt = listenersMapByUserIdForAudioZone.find(userId);
CHECK_AND_CONTINUE_LOG(listenersForUserIt != listenersMapByUserIdForAudioZone.end(),
"NotifySessionAddForAudioZone no listener for user:%{public}d", userId);
for (const auto& [pid, listener] : listenersForUserIt->second) {
CHECK_AND_CONTINUE_LOG(listener != nullptr,
"NotifySessionAddForAudioZone listener is null for pid=%{public}d", pid);
listener->OnSessionAddForAudioZone(descriptor.userId_, descriptor);
}
}
SLOGI("NotifySessionAddForAudioZone for user:%{public}d", descriptor.userId_);
}
void AVSessionService::NotifySessionRemoveForAudioZone(const AVSessionDescriptor& descriptor)
{
std::lock_guard lockGuard(sessionListenersLock_);
GetUsersManager().UpdateZoneToUseridMap(descriptor.userId_);
std::vector<int32_t> userIdsInSameZone = GetUsersManager().GetUsersInSameAudioZone(descriptor.userId_);
auto& listenersMapByUserIdForAudioZone = GetUsersManager().GetSessionListenersMapForAudioZone();
CHECK_AND_RETURN_LOG(!listenersMapByUserIdForAudioZone.empty(),
"NotifySessionRemoveForAudioZone no listeners for user:%{public}d", descriptor.userId_);
for (int32_t userId : userIdsInSameZone) {
auto listenersForUserIt = listenersMapByUserIdForAudioZone.find(userId);
if (listenersForUserIt == listenersMapByUserIdForAudioZone.end()) {
continue;
}
for (const auto& [pid, listener] : listenersForUserIt->second) {
CHECK_AND_CONTINUE_LOG(listener != nullptr,
"NotifySessionRemoveForAudioZone listener is null for pid=%{public}d", pid);
listener->OnSessionRemoveForAudioZone(descriptor.userId_, descriptor);
}
}
GetUsersManager().CleanupZoneToUseridMap(descriptor.userId_);
SLOGI("NotifySessionRemoveForAudioZone for user:%{public}d", descriptor.userId_);
}
void AVSessionService::NotifyTopSessionChangeForAudioZone(const AVSessionDescriptor& descriptor)
{
std::lock_guard lockGuard(sessionListenersLock_);
GetUsersManager().UpdateZoneToUseridMap(descriptor.userId_);
std::vector<int32_t> userIdsInSameZone = GetUsersManager().GetUsersInSameAudioZone(descriptor.userId_);
auto& listenersMapByUserIdForAudioZone = GetUsersManager().GetSessionListenersMapForAudioZone();
CHECK_AND_RETURN_LOG(!listenersMapByUserIdForAudioZone.empty(),
"NotifyTopSessionChangeForAudioZone no listeners for user:%{public}d", descriptor.userId_);
for (int32_t userId : userIdsInSameZone) {
auto listenersForUserIt = listenersMapByUserIdForAudioZone.find(userId);
if (listenersForUserIt == listenersMapByUserIdForAudioZone.end()) {
continue;
}
for (const auto& [pid, listener] : listenersForUserIt->second) {
CHECK_AND_CONTINUE_LOG(listener != nullptr,
"NotifyTopSessionChangeForAudioZone listener is null for pid=%{public}d", pid);
listener->OnTopSessionChangeForAudioZone(descriptor.userId_, descriptor);
}
}
SLOGI("NotifyTopSessionChangeForAudioZone for user:%{public}d", descriptor.userId_);
}
void AVSessionService::HandleSessionStackChangeForAudioZone()
{
auto& usersManager = GetUsersManager();
for (int32_t userId : usersManager.GetAliveUserList()) {
std::vector<AVSessionDescriptor> oldSessionStack = usersManager.GetSessionStackForAudioZone(userId);
usersManager.CleanupZoneToUseridMap(userId);
usersManager.UpdateZoneToUseridMap(userId);
usersManager.UpdateSessionStackForAudioZone(userId);
std::vector<AVSessionDescriptor> newSessionStack = usersManager.GetSessionStackForAudioZone(userId);
NotifySessionStackDiffForAudioZone(userId, oldSessionStack, newSessionStack);
}
}
void AVSessionService::NotifySessionStackDiffForAudioZone(int32_t userId,
const std::vector<AVSessionDescriptor>& oldStack,
const std::vector<AVSessionDescriptor>& newStack)
{
std::set<std::string> oldSessionIds;
for (const auto& desc : oldStack) {
oldSessionIds.insert(desc.sessionId_);
}
std::set<std::string> newSessionIds;
for (const auto& desc : newStack) {
newSessionIds.insert(desc.sessionId_);
}
std::vector<AVSessionDescriptor> addedSessions;
for (const auto& desc : newStack) {
if (oldSessionIds.find(desc.sessionId_) == oldSessionIds.end()) {
addedSessions.push_back(desc);
}
}
std::vector<AVSessionDescriptor> removedSessions;
for (const auto& desc : oldStack) {
if (newSessionIds.find(desc.sessionId_) == newSessionIds.end()) {
removedSessions.push_back(desc);
}
}
for (const auto& desc : addedSessions) {
NotifySessionAddForAudioZone(desc);
}
for (const auto& desc : removedSessions) {
NotifySessionRemoveForAudioZone(desc);
}
if (!newStack.empty() && !oldStack.empty()) {
if (newStack[0].sessionId_ != oldStack[0].sessionId_) {
NotifyTopSessionChangeForAudioZone(newStack[0]);
}
} else if (!newStack.empty() && oldStack.empty()) {
NotifyTopSessionChangeForAudioZone(newStack[0]);
}
}
int32_t AVSessionService::GetSessionDescriptorsForAudioZone(int32_t userId,
std::vector<AVSessionDescriptor>& descriptors)
{
CHECK_AND_RETURN_RET_LOG(userId > 0, AVSESSION_ERROR,
"GetSessionDescriptorsForAudioZone invalid userId=%{public}d", userId);
std::lock_guard frontLockGuard(sessionFrontLock_);
GetUsersManager().UpdateSessionStackForAudioZone(userId);
std::vector<AVSessionDescriptor> zoneDescriptors = GetUsersManager().GetSessionStackForAudioZone(userId);
for (const auto& desc : zoneDescriptors) {
descriptors.push_back(desc);
}
SLOGI("GetSessionDescriptorsForAudioZone for user:%{public}d with size=%{public}d",
userId, static_cast<int32_t>(descriptors.size()));
return AVSESSION_SUCCESS;
}
AVSessionService::TargetPlayInfo AVSessionService::GetTargetPlayInfoForAudioZone(
int32_t userId, const std::string& bundleName)
{
TargetPlayInfo targetInfo;
std::vector<AVSessionDescriptor> descriptors;
GetSessionDescriptorsForAudioZone(userId, descriptors);
if (descriptors.empty()) {
SLOGI("No session in audio zone, fallback to bundleName=%{public}s", bundleName.c_str());
targetInfo.bundleName = bundleName;
std::string profile;
if (!BundleStatusAdapter::GetInstance().IsSupportPlayIntent(
targetInfo.bundleName, targetInfo.moduleName, profile)) {
SLOGE("bundle=%{public}s does not support play insights", targetInfo.bundleName.c_str());
targetInfo.isValid = false;
return targetInfo;
}
targetInfo.isValid = true;
} else {
AVSessionDescriptor topSession = descriptors[0];
targetInfo.bundleName = topSession.elementName_.GetBundleName();
targetInfo.moduleName = topSession.elementName_.GetModuleName();
targetInfo.isValid = true;
SLOGI("Use top session: bundleName=%{public}s, moduleName=%{public}s",
targetInfo.bundleName.c_str(), targetInfo.moduleName.c_str());
}
return targetInfo;
}
int32_t AVSessionService::StartAVPlaybackForAudioZone(const std::string& bundleName, int32_t userId,
const std::string& assetId, const CommandInfo& info)
{
int32_t result = AVSESSION_ERROR;
if (CheckStartAncoMediaPlay(bundleName, &result)) {
return result;
}
TargetPlayInfo targetInfo = GetTargetPlayInfoForAudioZone(userId, bundleName);
if (!targetInfo.isValid) {
return AVSESSION_ERROR;
}
int32_t targetUid = BundleStatusAdapter::GetInstance().GetUidFromBundleName(targetInfo.bundleName, userId);
StartPlayType startPlayType = StartPlayType::APP;
if (targetUid == BLUETOOTH_UID) {
startPlayType = StartPlayType::BLUETOOTH;
}
if (targetUid == NEARLINK_UID) {
startPlayType = StartPlayType::NEARLINK;
}
StartPlayInfo startPlayInfo;
startPlayInfo.setBundleName(targetInfo.bundleName);
startPlayInfo.SetModuleName(targetInfo.moduleName);
SLOGI("StartAVPlaybackForAudioZone for bundleName:%{public}s, userId:%{public}d",
targetInfo.bundleName.c_str(), userId);
std::unique_ptr<AVSessionDynamicLoader> dynamicLoader = std::make_unique<AVSessionDynamicLoader>();
typedef int32_t (*StartAVPlaybackFunc)(const std::string& bundleName, const std::string& assetId,
const StartPlayInfo startPlayInfo, StartPlayType startPlayType);
StartAVPlaybackFunc startAVPlayback = reinterpret_cast<StartAVPlaybackFunc>(
dynamicLoader->GetFuntion(AVSESSION_DYNAMIC_INSIGHT_LIBRARY_PATH, "StartAVPlaybackWithId"));
if (startAVPlayback) {
#ifdef ENABLE_AVSESSION_SYSEVENT_CONTROL
ReportSessionControl(targetInfo.bundleName, CONTROL_COLD_START);
#endif
return (*startAVPlayback)(targetInfo.bundleName, assetId, startPlayInfo, startPlayType);
}
SLOGE("StartAVPlaybackForAudioZone fail");
return AVSESSION_ERROR;
}
int32_t AVSessionService::RegisterSessionListenerForUser(int32_t userId, const sptr<ISessionListener>& listener)
{
GetUsersManager().UpdateZoneToUseridMap(userId);
pid_t pid = GetCallingPid();
SLOGI("Enter RegisterSessionListenerForUser process for pid:%{public}d and target userId:%{public}d",
static_cast<int>(pid), userId);
GetUsersManager().AddSessionListenerForUser(pid, listener, userId);
return AVSESSION_SUCCESS;
}
void AVSessionService::InitAudioZoneCallback()
{
audioZoneChangeCallback_ = std::make_shared<AudioZoneChangeCallbackImpl>();
audioZoneCallback_ = std::make_shared<AudioZoneCallbackImpl>(audioZoneChangeCallback_);
auto audioZoneManager = AudioStandard::AudioZoneManager::GetInstance();
if (audioZoneManager != nullptr) {
auto ret = audioZoneManager->RegisterAudioZoneCallback(audioZoneCallback_);
SLOGI("RegisterAudioZoneCallback ret=%{public}d", ret);
} else {
SLOGE("AudioZoneManager::GetInstance() is nullptr");
}
}
void AVSessionService::DeinitAudioZoneCallback()
{
auto audioZoneManager = AudioStandard::AudioZoneManager::GetInstance();
if (audioZoneManager != nullptr && audioZoneCallback_ != nullptr) {
audioZoneManager->UnRegisterAudioZoneCallback();
audioZoneCallback_ = nullptr;
audioZoneChangeCallback_ = nullptr;
}
}
void AVSessionService::AudioZoneCallbackImpl::OnAudioZoneAdd(
const AudioStandard::AudioZoneDescriptor &zoneDescriptor)
{
int32_t zoneId = zoneDescriptor.zoneId_;
auto audioZoneManager = AudioStandard::AudioZoneManager::GetInstance();
auto audioZoneChangeCallback_ = audioZoneChangeCallbackWeak_.lock();
if (audioZoneManager != nullptr && audioZoneChangeCallback_ != nullptr) {
auto ret = audioZoneManager->RegisterAudioZoneChangeCallback(zoneId, audioZoneChangeCallback_);
SLOGI("RegisterAudioZoneChangeCallback zoneId=%{public}d ret=%{public}d", zoneId, ret);
}
}
void AVSessionService::AudioZoneCallbackImpl::OnAudioZoneRemove(int32_t zoneId)
{
auto audioZoneManager = AudioStandard::AudioZoneManager::GetInstance();
auto audioZoneChangeCallback_ = audioZoneChangeCallbackWeak_.lock();
if (audioZoneManager != nullptr && audioZoneChangeCallback_ != nullptr) {
auto ret = audioZoneManager->UnRegisterAudioZoneChangeCallback(zoneId);
SLOGI("OnAudioZoneRemove UnRegisterAudioZoneChangeCallback ret=%{public}d", ret);
}
auto service = AVSessionService::GetInstance();
if (!service) {
return;
}
service->HandleSessionStackChangeForAudioZone();
}
void AVSessionService::AudioZoneChangeCallbackImpl::OnAudioZoneChange(
const AudioStandard::AudioZoneDescriptor &zoneDescriptor, AudioStandard::AudioZoneChangeReason reason)
{
SLOGI("OnAudioZoneChange zoneId=%{public}d reason=%{public}d",
zoneDescriptor.zoneId_, static_cast<int>(reason));
auto service = AVSessionService::GetInstance();
if (!service) {
return;
}
service->HandleSessionStackChangeForAudioZone();
}
#endif
#ifdef ENABLE_AVSESSION_SYSEVENT_CONTROL
void AVSessionService::ReportSessionState(const sptr<AVSessionItem>& session, SessionState state)
{
if (session == nullptr) {
SLOGE("ReportSessionState session is null");
return;
}
std::string bundleName = session->GetBundleName();
AVSessionSysEvent::GetInstance().UpdateState(bundleName,
BundleStatusAdapter::GetInstance().GetAppVersion(bundleName), state, session->GetSessionType());
}
void AVSessionService::ReportSessionControl(const std::string& bundleName, int32_t cmd)
{
HILOG_COMM_INFO("HandleControl from %{public}d to %{public}s with %{public}d",
GetCallingUid(), bundleName.c_str(), cmd);
if (cmd == AVControlCommand::SESSION_CMD_PLAY ||
cmd == AVControlCommand::SESSION_CMD_PAUSE ||
cmd == CONTROL_COLD_START) {
auto uid = GetCallingUid();
auto callerBundleName = BundleStatusAdapter::GetInstance().GetBundleNameFromUid(uid);
AVSessionSysEvent::GetInstance().UpdateControl(bundleName, cmd,
callerBundleName.empty() ? std::to_string(uid) : callerBundleName);
}
}
int32_t AVSessionService::GetUserIdFromCallingUid(const int32_t uid)
{
int32_t userId = uid / uidToUserId;
userId = (userId <= 0) ? GetUsersManager().GetCurrentUserId() : userId;
return userId;
}
std::map<pid_t, std::list<sptr<AVControllerItem>>> AVSessionService::GetInnerControllers() const
{
std::lock_guard lockGuard(sessionServiceLock_);
return controllers_;
}
#endif // ENABLE_AVSESSION_SYSEVENT_CONTROL
} // namespace OHOS::AVSession