mirror of
https://github.com/openharmony/multimedia_av_session.git
synced 2026-08-24 18:26:13 -04:00
470347d005
修复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
5452 lines
242 KiB
C++
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
|