/* * 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 #include #include #include #include #include #include #include #include #include #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); typedef void (*StopMigrateStubFunc)(void); #if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM) and !defined(IOS_PLATFORM) #include #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 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 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 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 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 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(); 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 = std::static_pointer_cast(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(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& 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 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 writePair{"boot", bootCount}; AVSessionUtils::WritePairToFile(writePair, fileDir, fileName); cleanedBootCountByUser_[userId] = bootCount; } } bool AVSessionService::SubscribeCommonEvent() { const std::vector 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(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 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(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(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(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(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 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& topSession, const sptr& 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 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(timeSinceEpoch).count(); sessionItem->SetPlayingTime(milliseconds); SLOGI("UpdateSessionTimestamp for %{public}s", sessionItem->GetBundleName().c_str()); } void AVSessionService::UpdateTopSession(const sptr& newTopSession, int32_t userId) { AVSessionDescriptor descriptor; sptr 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>> 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(info.uid)); if (info.uid == ancoUid && isPlaying) { sptr 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 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 &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 &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& 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>> 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(sessionListForFront->size())); } UpdateLocalFrontSession(sessionListForFront); NotifySessionChange(sessionListForFront, userId); } bool AVSessionService::UpdateOrder(sptr& 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>> 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(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 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(); 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 = std::make_shared("/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(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>> AVSessionService::GetCurSessionListForFront(int32_t userId) { return GetUsersManager().GetCurSessionListForFront(userId); } inline std::shared_ptr>> 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(id.begin(), id.end())) == AVSESSION_SUCCESS, "", "hash update failed"); std::vector 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(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 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> 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> 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> listenerMap = GetUsersManager().GetSessionListener(descriptor.userId_); SLOGI("NotifySessionRelease for user:%{public}d|listenerSize:%{public}d", descriptor.userId_, static_cast(listenerMap.size())); for (const auto& [pid, listener] : listenerMap) { if (listener != nullptr) { listener->OnSessionRelease(descriptor); } } std::map> 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> listenerMap; std::map> 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 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 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> listenerMap = GetUsersManager().GetSessionListener(); for (const auto& [pid, listener] : listenerMap) { AVSESSION_TRACE_SYNC_START("AVSessionService::OnAudioSessionCheck"); if (listener != nullptr) { listener->OnAudioSessionChecked(uid); } } std::map> 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 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 result = GetOtherPlayingSession(userId, ""); hasOtherSessionPlaying = result != nullptr; HandleOtherSessionPlaying(result); } if (!hasOtherSessionPlaying) { NotifySystemUI(nullptr, isPlaying && IsCapsuleNeeded(), isMediaChange); } return true; } void AVSessionService::AddCapsuleServiceCallback(sptr& sessionItem) { sessionItem->SetServiceCallbackForNtfCapsule([this](std::string sessionId, bool isMediaChange) { std::lock_guard lockGuard(sessionServiceLock_); sptr 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 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>> 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 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& session) { session->SetServiceCallbackForAncoStart([this](std::string sessionId, std::string bundle, std::string ability) { std::lock_guard lockGuard(sessionServiceLock_); sptr 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& sessionItem) { #ifdef CASTPLUS_CAST_ENGINE_ENABLE sessionItem->SetServiceCallbackForCastNtfCapsule([this](std::string sessionId, bool isPlaying, bool isChange) { std::lock_guard lockGuard(sessionServiceLock_); sptr 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& 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 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>> 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& 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 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& sessionItem) { #ifdef CASTPLUS_CAST_ENGINE_ENABLE CHECK_AND_RETURN_LOG(sessionItem != nullptr, "session not exist for AddCastServiceCallback"); sessionItem->SetServiceCallbackForStream([this](std::string sessionId) { sptr 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 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& 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>> sessionListForFront = GetCurSessionListForFront(); UpdateLocalFrontSession(sessionListForFront); return; } std::lock_guard lockGuard(sessionServiceLock_); sptr 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 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 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(GetCallingUid())); descriptor.userId_ = userId; descriptor.sessionTag_ = tag; descriptor.sessionType_ = type; descriptor.elementName_ = elementName; descriptor.isThirdPartyApp_ = thirdPartyApp; sptr 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 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& sessionItem) { CHECK_AND_RETURN_LOG(sessionItem != nullptr, "AddExtraFrontSession sessionItem nullptr!"); std::lock_guard frontLockGuard(sessionFrontLock_); int32_t userId = sessionItem->GetUserId(); std::shared_ptr>> 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& 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 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(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& sessionItem) { if (!IsParamInvalid(tag, type, elementName)) { AudioStandard::StreamDfxManager::GetInstance().SendAudioErrorEvent(static_cast(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(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(getuid()), AudioStandard::AVSESSION_CONTROL_SESSION_IS_EXIST_LOCAL_SET, "process already has one session", false); return ERR_SESSION_IS_EXIST; } sptr 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(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 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 AVSessionService::CreateSessionInner(const std::string& tag, int32_t type, bool thirdPartyApp, const AppExecFwk::ElementName& elementName) { sptr 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 & 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& object) { sptr 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(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 AVSessionService::CreateSessionInner(const std::string& tag, int32_t type, const AppExecFwk::ElementName& elementName) { sptr 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 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 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& 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(GetCallingUid())); std::shared_ptr>> 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(descriptors.size()), topSessionName.c_str()); return AVSESSION_SUCCESS; } int32_t AVSessionService::GetNotActiveSession(std::vector& descriptors) { std::lock_guard frontLockGuard(sessionFrontLock_); int32_t userId = GetUserIdFromCallingUid(static_cast(GetCallingUid())); std::shared_ptr>> 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& descriptors) { auto containerPtr = GetUsersManager().GetContainerPtrFromUser( GetUserIdFromCallingUid(static_cast(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(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(GetCallingUid())); sptr 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& 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& descriptors) { std::string oldSortContent; int32_t userId = GetUserIdFromCallingUid(static_cast(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& descriptors) { std::lock_guard sortFileLockGuard(sessionFileLock_); std::vector 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& descriptors) { std::lock_guard sortFileLockGuard(sessionFileLock_); std::vector tempDescriptors; int32_t userId = GetUserIdFromCallingUid(static_cast(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(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& 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 avQueuePixelMap = std::make_shared(); 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& avQueueInfos) { std::lock_guard avQueueFileLockGuard(avQueueFileLock_); std::string oldAVQueueInfoContent; std::vector 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(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(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 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 innerQueuePixelMap = data.GetAVQueueImage(); if (innerQueuePixelMap != nullptr) { innerQueuePixelMap->Clear(); } std::shared_ptr innerMediaPixelMap = data.GetMediaImage(); if (innerMediaPixelMap != nullptr) { innerMediaPixelMap->Clear(); } } bool AVSessionService::CheckStartAncoMediaPlay(const std::string& bundleName, int32_t *result) { std::vector 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 dynamicLoader = std::make_unique(); typedef int32_t (*StartAVPlaybackFunc)(const std::string& bundleName, const std::string& assetId, const StartPlayInfo startPlayInfo, StartPlayType startPlayType); StartAVPlaybackFunc startAVPlayback = reinterpret_cast(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 dynamicLoader = std::make_unique(); typedef int32_t (*StartAVPlaybackFunc)(const std::string& bundleName, const std::string& assetId, const StartPlayInfo startPlayInfo, StartPlayType startPlayType); StartAVPlaybackFunc startAVPlayback = reinterpret_cast(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 &listener) { CHECK_AND_RETURN_RET_LOG(listener != nullptr, AVSESSION_ERROR, "anco Listner null"); std::lock_guard lockGuard(audioBrokerLock_); ancoMediaSessionListener_ = listener; return AVSESSION_SUCCESS; } sptr AVSessionService::CreateNewControllerForSession(pid_t pid, sptr& session) { SLOGI("pid=%{public}d sessionId=%{public}s", pid, AVSessionUtils::GetAnonySessionId(session->GetSessionId()).c_str()); sptr 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 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(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 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(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& object) { return CreateControllerInner(sessionId, object, -1); } int32_t AVSessionService::CreateControllerInner(const std::string& sessionId, sptr& object, pid_t pid) { int32_t userId = GetUserIdFromCallingUid(static_cast(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 session = GetUsersManager().GetContainerFromAll().GetSessionById(sessionId); #else sptr 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(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(getuid()), AudioStandard::AVSESSION_CONTROL_CONTROLLER_IS_EXIST_LOCAL_SET, "Controller is already existed", false); return ERR_CONTROLLER_IS_EXIST; } sptr newController = CreateNewControllerForSession(pid, session); if (newController == nullptr) { SLOGE("Create new controller failed."); AudioStandard::StreamDfxManager::GetInstance().SendAudioErrorEvent(static_cast(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& listener, int32_t userId) { std::lock_guard lockGuard(sessionListenersLock_); GetUsersManager().AddSessionListener(pid, listener, userId); } void AVSessionService::AddSessionListenerForAllUsers(pid_t pid, const sptr& 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& listener) { int32_t userId = GetUserIdFromCallingUid(static_cast(GetCallingUid())); pid_t pid = GetCallingPid(); SLOGI("Enter RegisterSessionListener process for pid:%{public}d and return target userId:%{public}d", static_cast(pid), userId); AddSessionListener(pid, listener, userId); return userId; } int32_t AVSessionService::RegisterSessionListenerForAllUsers(const sptr& listener) { pid_t pid = GetCallingPid(); SLOGI("Enter RegisterSessionListenerForAllUsers process for pid:%{public}d", static_cast(pid)); AddSessionListenerForAllUsers(pid, listener); return AVSESSION_SUCCESS; } // LCOV_EXCL_START AVControlCommand AVSessionService::GetSessionProcCommand() { AVControlCommand cmd; if (topSession_ != nullptr) { sptr 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(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(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 session, const std::string& deviceId) { CHECK_AND_RETURN_RET_LOG(session != nullptr, false, "handlevent session is null"); sptr 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>> 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>> 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 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 object; int32_t ret = 0; std::string bundleName = coldStartDescriptors[0].elementName_.GetBundleName(); sptr 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(coldStartDescriptors.size())); } } bool AVSessionService::CheckIfOtherAudioPlaying() { std::vector 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(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& observer, const sptr recipient) { std::lock_guard lockGuard(clientDeathLock_); clientDeathObservers_[pid] = observer; clientDeathRecipients_[pid] = recipient; } void AVSessionService::RemoveClientDeathObserver(pid_t pid) { std::lock_guard lockGuard(clientDeathLock_); sptr observer = clientDeathObservers_[pid]; sptr recipient = clientDeathRecipients_[pid]; if (observer && recipient) { SLOGI("remove clientDeath recipient for %{public}d", static_cast(pid)); observer->AsObject()->RemoveDeathRecipient(recipient); } clientDeathObservers_.erase(pid); clientDeathRecipients_.erase(pid); } int32_t AVSessionService::RegisterClientDeathObserver(const sptr& observer) { auto pid = GetCallingPid(); auto uid = GetCallingUid(); SLOGI("enter ClientDeathObserver register with recipient point for pid:%{public}d", static_cast(pid)); sptr 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& 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 AVSessionService::GetOtherPlayingSession(int32_t userId, std::string bundleName) { std::lock_guard frontLockGuard(sessionFrontLock_); std::shared_ptr>> 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(sessionListForFront->size()) >= otherPlayingSessionMinLen, nullptr, "sessionListForFront size less than otherPlayingSessionMinLen"); sptr 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& sessionItem) { if (GetUsersManager().GetTopSession(userId).GetRefPtr() == sessionItem.GetRefPtr()) { sptr 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 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>> 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 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& 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 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 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 remoteService = std::make_shared(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 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& 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& castAudioDescriptors, sptr & 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>& 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 & session, const std::vector& descriptors, std::vector& castSinkDescriptors, std::vector& cancelSinkDescriptors) { if (descriptors.size() != 1) { SLOGI("descriptor size is %{public}d, not support", static_cast(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 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> audioDescriptor; std::shared_ptr audioDeviceDescriptor = std::make_shared(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(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& sinkAudioDescriptors) { std::string sourceSessionInfo; int32_t ret = SetBasicInfo(sourceSessionInfo); CHECK_AND_RETURN_RET_LOG(ret == AVSESSION_SUCCESS, ret, "SetBasicInfo failed"); sptr 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& descriptors, const std::string& sourceSessionInfo, sptr & session) { std::vector castSinkDescriptors; std::vector 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& sinkAudioDescriptors, const std::string& sourceSessionInfo, const sptr & 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(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(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& sinkDevices, const std::string& sourceSessionInfo, const sptr & session) { SLOGI("cancel sinkDevices size is %{public}d", static_cast(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& 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 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& 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(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 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& session) { CHECK_AND_RETURN_RET_LOG(session != nullptr, AVSESSION_ERROR, "session is nullptr"); SLOGI("pid is %{public}d, sessionId is %{public}s", static_cast(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 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& 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(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& callback) : callback_(callback) { SLOGD("construct"); } void ClientDeathRecipient::OnRemoteDied(const wptr& 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(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(file), istreambuf_iterator(), 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(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(fileRead), istreambuf_iterator(), 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 AVSessionService::CreateWantAgent( sptr photoSession) { sptr topSession; { std::lock_guard lockGuard(sessionServiceLock_); topSession = topSession_; } CHECK_AND_RETURN_RET_LOG(!(photoSession == nullptr && topSession == nullptr), nullptr, "CreateWantAgent but null"); std::vector flags; flags.push_back(AbilityRuntime::WantAgent::WantAgentConstant::Flags::UPDATE_PRESENT_FLAG); std::vector> wants; std::shared_ptr want = std::make_shared(); std::shared_ptr 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(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(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 &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(*iter); int32_t durationInSeconds = std::chrono::duration_cast(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 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(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 wantParam = request->GetAdditionalData() == nullptr ? std::make_shared() : request->GetAdditionalData(); wantParam->SetParam(key, value); request->SetAdditionalData(wantParam); } void AddCapsule(std::string title, bool isCapsuleUpdate, std::shared_ptr pixelMap, std::shared_ptr 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 photoSession, std::shared_ptr& 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(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 AVSessionService::CreateNftRemoveWant(int32_t uid, bool isPhoto) { std::vector> wants; std::shared_ptr want = std::make_shared(); 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 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 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 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(photoSession != nullptr), addCapsule, isCapsuleUpdate); Notification::NotificationRequest request; std::shared_ptr localLiveViewContent = std::make_shared(); 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 content = std::make_shared(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 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 iPixelMap = std::make_shared(); 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 wantAgent = CreateWantAgent(photoSession); CHECK_AND_RETURN_LOG(wantAgent != nullptr, "wantAgent nullptr error"); request.SetWantAgent(wantAgent); request.SetLabel(std::to_string(userId)); std::shared_ptr 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>& sessionControllers) { std::lock_guard lockGuard(sessionListenersLock_); std::list 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> 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> 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 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 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 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 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 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 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 oldSessionStack = usersManager.GetSessionStackForAudioZone(userId); usersManager.CleanupZoneToUseridMap(userId); usersManager.UpdateZoneToUseridMap(userId); usersManager.UpdateSessionStackForAudioZone(userId); std::vector newSessionStack = usersManager.GetSessionStackForAudioZone(userId); NotifySessionStackDiffForAudioZone(userId, oldSessionStack, newSessionStack); } } void AVSessionService::NotifySessionStackDiffForAudioZone(int32_t userId, const std::vector& oldStack, const std::vector& newStack) { std::set oldSessionIds; for (const auto& desc : oldStack) { oldSessionIds.insert(desc.sessionId_); } std::set newSessionIds; for (const auto& desc : newStack) { newSessionIds.insert(desc.sessionId_); } std::vector addedSessions; for (const auto& desc : newStack) { if (oldSessionIds.find(desc.sessionId_) == oldSessionIds.end()) { addedSessions.push_back(desc); } } std::vector 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& 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 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(descriptors.size())); return AVSESSION_SUCCESS; } AVSessionService::TargetPlayInfo AVSessionService::GetTargetPlayInfoForAudioZone( int32_t userId, const std::string& bundleName) { TargetPlayInfo targetInfo; std::vector 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 dynamicLoader = std::make_unique(); typedef int32_t (*StartAVPlaybackFunc)(const std::string& bundleName, const std::string& assetId, const StartPlayInfo startPlayInfo, StartPlayType startPlayType); StartAVPlaybackFunc startAVPlayback = reinterpret_cast( 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& listener) { GetUsersManager().UpdateZoneToUseridMap(userId); pid_t pid = GetCallingPid(); SLOGI("Enter RegisterSessionListenerForUser process for pid:%{public}d and target userId:%{public}d", static_cast(pid), userId); GetUsersManager().AddSessionListenerForUser(pid, listener, userId); return AVSESSION_SUCCESS; } void AVSessionService::InitAudioZoneCallback() { audioZoneChangeCallback_ = std::make_shared(); audioZoneCallback_ = std::make_shared(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(reason)); auto service = AVSessionService::GetInstance(); if (!service) { return; } service->HandleSessionStackChangeForAudioZone(); } #endif #ifdef ENABLE_AVSESSION_SYSEVENT_CONTROL void AVSessionService::ReportSessionState(const sptr& 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>> AVSessionService::GetInnerControllers() const { std::lock_guard lockGuard(sessionServiceLock_); return controllers_; } #endif // ENABLE_AVSESSION_SYSEVENT_CONTROL } // namespace OHOS::AVSession