Files
openharmony_ci 75cb61e9cf !3326 merge security-fix-lyc into master
修复avsession模块多项并发安全问题(issue #2578部分项)

Created-by: devil_red
Commit-by: 红袍小恶魔
Merged-by: openharmony_ci
Description: ## 关联 Issue

fix #2728

本 PR 修复 issue #2728 所列全部 13 个并发缺陷项(含第 7 项既有 ABBA 死锁),合并后请关闭该 issue。

## 修改内容

**services/session/server/ 服务核心层**
- **AVRouterImpl**:`castHandleToInfoMap_`/`providerManagerMap_` 全路径加锁;抽取 `GetCastProvider`/`GetHwProvider` 两个私有帮助函数,统一"锁内取 shared_ptr 快照、锁外调用"(14+3 处调用点收敛);`Init`/`Release` 的 SDK 调用全部移出锁外,仅赋值/置空在锁内;listener 回调锁外或 EventHandler 异步执行,消除锁序反转;修复 `OnCastStateChange` 持 `servicePtrLock_` 调 `checkEnableCast` 的 ABBA 死锁(快照后锁外调用)
- **HwCastProvider**:监听器列表遍历改"锁内取快照、锁外回调";`QueryCastSessionId` 补 `mutexLock_`
- **SoftbusSessionManager**:`ObtainPeerDeviceId` 补 `socketLock_`,`operator[]` 改 `find`(避免隐式插入默认项)
- **AVSessionUsersManager**:`GetContainerFromAll` 补 `userLock_`,消除惰性初始化竞争导致的会话丢失
- **AVSessionService**:`UpdateTopSession` 锁内取 `topSession_` 的 sptr 副本,消除锁外读 UAF
- **MigrateAVSessionProxy**:心跳/检查 worker 锁内取 `deviceId_` 快照

**services/session/adapter/**
- **AppManagerAdapter**:新增 `appStateChangeObserverLock_`,observer 快照后锁外调用

**frameworks/js/napi(ArkTS 绑定)**
- **NapiAVSession(握手按调用私有化)**:`SetAVPlaybackState` 改用 `PlaybackStateSyncContext{mtx,cv,ready,ret}`,删除 5 个进程级 static,根治跨会话返回码串扰;原生调用保持锁内执行(慢 IPC 不误超时),async 侧谓词等待 1s 有界预算;postTask 失败立即定死结果
- **NapiAVSession(静态暂存指针)**:新增 `napiAVSessionLock_` 保护 `napiAVSession_`,`NewInstance`/`ReCreateInstance` 锁内仅做指针赋值/快照,JS/IPC 调用全部锁外,无死锁风险

**interfaces + frameworks/common**
- **AVSessionPixelMap**:`bufferLock_` 改 `mutable`,`Marshalling` 加锁

**utils/**
- **HashCalculator**:全局 `g_context` 改 `static thread_local`,消除跨线程摘要互相破坏
- **AVSessionRadar**:新增 `deviceInfoLock_` 保护设备 id 惰性初始化与清空

## 自测

- 全部修改均为锁保护/快照/发布顺序类小步改动,已逐文件复查 diff 并做锁序审计(与现状代码组合无死锁)
- 建议在构建环境执行:avsession 相关 UT/FUZZ,以及 `CASTPLUS_CAST_ENGINE_ENABLE`、`DSOFTBUS_ENABLE` 两种开关组合编译

See merge request: openharmony/multimedia_av_session!3326
2026-08-07 18:20:25 +08:00

781 lines
32 KiB
C++

/*
* Copyright (c) 2023 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 "hw_cast_provider.h"
#include <thread>
#include <unordered_map>
#include "cast_session_manager.h"
#include "hw_cast_stream_player.h"
#include "avsession_log.h"
#include "avsession_errors.h"
#include "avsession_event_handler.h"
#include "avsession_radar.h"
#include "avsession_utils.h"
#include "display_manager_lite.h"
#include "display_info.h"
using namespace OHOS::CastEngine::CastEngineClient;
using namespace OHOS::CastEngine;
namespace OHOS::AVSession {
const uint32_t UNTRUSTED_DEVICE = 0;
const uint32_t TRUSTED_DEVICE = 1;
const std::unordered_map<int32_t, int32_t> CAST_TO_AV_DEVICE_TYPE_MAP = {
{ 0x9C, DeviceType::DEVICE_TYPE_TV },
{ 0x11, DeviceType::DEVICE_TYPE_PAD },
{ 0x83, DeviceType::DEVICE_TYPE_CAR },
{ 0xA2F, DeviceType::DEVICE_TYPE_2IN1 },
{ 0xA33, DeviceType::DEVICE_TYPE_HIPLAY },
};
int32_t ConvertCastDeviceTypeToDeviceType(int32_t castDeviceType)
{
auto it = CAST_TO_AV_DEVICE_TYPE_MAP.find(castDeviceType);
return it != CAST_TO_AV_DEVICE_TYPE_MAP.end() ? it->second : DeviceType::DEVICE_TYPE_DEFAULT_CAST_PLUS_STREAM;
}
HwCastProvider::HwCastProvider()
{
SLOGD("pre construct the HwCastProvider");
std::lock_guard lockGuard(mutexLock_);
SLOGI("construct the HwCastProvider");
}
HwCastProvider::~HwCastProvider()
{
SLOGD("pre destruct the HwCastProvider");
std::lock_guard lockGuard(mutexLock_);
SLOGI("destruct the HwCastProvider");
}
int32_t HwCastProvider::Init()
{
SLOGD("pre init the HwCastProvider");
std::lock_guard lockGuard(mutexLock_);
int32_t ret = CastSessionManager::GetInstance().RegisterListener(shared_from_this());
SLOGI("Init the HwCastProvider %{public}d", ret);
return ret;
}
int32_t HwCastProvider::StartDeviceLogging(int32_t fd, uint32_t maxSize)
{
SLOGI("start StartDeviceLogging, fd is %{public}d and maxSize is %{public}d", fd, maxSize);
return CastSessionManager::GetInstance().StartDeviceLogging(fd, maxSize);
}
int32_t HwCastProvider::StopDeviceLogging()
{
SLOGI("StopDeviceLogging");
return CastSessionManager::GetInstance().StartDeviceLogging(-1, 0);
}
bool HwCastProvider::StartDiscovery(int castCapability, std::vector<std::string> drmSchemes)
{
SLOGI("start discovery and the castCapability is %{public}d", castCapability);
castCapability = GetCastProtocolType(castCapability);
AVSessionRadarInfo info("HwCastProvider::StartDiscovery");
AVSessionRadar::GetInstance().StartCastDiscoveryBegin(info);
auto ret = CastSessionManager::GetInstance().StartDiscovery(castCapability, drmSchemes);
if (ret != 0) {
info.errorCode_ = ret;
AVSessionRadar::GetInstance().FailToStartCastDiscovery(info);
} else {
AVSessionRadar::GetInstance().StartCastDiscoveryEnd(info);
}
return ret;
}
void HwCastProvider::StopDiscovery()
{
SLOGI("stop discovery");
AVSessionRadarInfo info("HwCastProvider::StopDiscovery");
AVSessionRadar::GetInstance().StopCastDiscoveryBegin(info);
auto ret = CastSessionManager::GetInstance().StopDiscovery();
if (ret != 0) {
info.errorCode_ = ret;
AVSessionRadar::GetInstance().FailToStopCastDiscovery(info);
} else {
AVSessionRadar::GetInstance().StopCastDiscoveryEnd(info);
}
}
int32_t HwCastProvider::SetDiscoverable(const bool enable)
{
SLOGI("SetDiscoverable in %{public}d", static_cast<int32_t>(enable));
return AVSESSION_SUCCESS;
}
void HwCastProvider::Release()
{
SLOGI("cast provider release");
{
std::lock_guard lockGuard(mutexLock_);
hwCastProviderSessionMap_.clear();
avCastControllerMap_.clear();
castStateListenerList_.clear();
castFlag_.clear();
}
if (!isRelease_) {
SLOGI("release in with check pass");
isRelease_ = true;
} else {
SLOGW("already in release, check return");
return;
}
CastSessionManager::GetInstance().UnregisterListener();
SLOGD("provider release done");
}
int HwCastProvider::StartCastSession(uint32_t prototype, bool isPcm)
{
SLOGI("StartCastSession begin");
CastSessionProperty property = {};
InitCastSessionProperty(prototype, isPcm, property);
bool isHiStream = (prototype & ProtocolType::TYPE_CAST_PLUS_AUDIO) != 0;
std::shared_ptr<ICastSession> castSession = nullptr;
int ret = CastSessionManager::GetInstance().CreateCastSession(property, castSession);
if (ret != AVSESSION_SUCCESS) {
AVSessionRadarInfo info("HwCastProvider::StartCastSession");
info.errorCode_ = ret;
AVSessionRadar::GetInstance().FailToStartCast(info);
SLOGI("StartCastSession failed and return the ret is %{public}d", ret);
return AVSESSION_ERROR;
}
int castId;
{
SLOGI("StartCastSession pre check lock");
std::lock_guard lockGuard(mutexLock_);
SLOGI("StartCastSession check lock");
std::vector<bool>::iterator iter = find(castFlag_.begin(), castFlag_.end(), false);
if (iter == castFlag_.end()) {
SLOGE("StartCastSession failed");
return AVSESSION_ERROR;
}
*iter = true;
castId = iter - castFlag_.begin();
auto hwCastProviderSession = std::make_shared<HwCastProviderSession>(castSession);
if (hwCastProviderSession) {
if (hwCastProviderSession->Init() != AVSESSION_ERROR) {
SLOGI("CastSession init successed");
} else {
hwCastProviderSession->Release();
castFlag_[castId] = false;
return AVSESSION_ERROR;
}
if (isHiStream) {
hwCastProviderSession->SetProtocolType(CastEngine::ProtocolType::CAST_PLUS_AUDIO);
}
}
hwCastProviderSessionMap_[castId] = hwCastProviderSession;
}
SLOGI("StartCastSession successed and return the castId is %{public}d", castId);
return castId;
}
void HwCastProvider::StopCastSession(int castId)
{
HILOG_COMM_INFO("StopCastSession begin");
std::lock_guard lockGuard(mutexLock_);
SLOGI("StopCastSession check lock");
auto hwCastStreamPlayer = avCastControllerMap_[castId];
if (hwCastStreamPlayer) {
hwCastStreamPlayer->Release();
}
avCastControllerMap_.erase(castId);
int32_t mirrorCastId = static_cast<int32_t>((static_cast<uint64_t>(mirrorCastHandle) << 32) >> 32);
if (castId == mirrorCastId) {
return;
}
auto it = hwCastProviderSessionMap_.find(castId);
if (it == hwCastProviderSessionMap_.end()) {
SLOGE("no need to release castSession for castId %{public}d is not exit in hwCastProviderSessionMap_", castId);
return;
}
auto hwCastProviderSession = it->second;
if (hwCastProviderSession) {
hwCastProviderSession->Release();
}
hwCastProviderSessionMap_.erase(castId);
castFlag_[castId] = false;
}
bool HwCastProvider::AddCastDevice(int castId, DeviceInfo deviceInfo, uint32_t spid)
{
SLOGI("AddCastDevice with config castSession and corresonding castId is %{public}d", castId);
std::lock_guard lockGuard(mutexLock_);
SLOGI("add device check lock done");
auto it = hwCastProviderSessionMap_.find(castId);
if (it == hwCastProviderSessionMap_.end()) {
SLOGE("the castId corresonding to castSession is not exist");
return false;
}
auto hwCastProviderSession = it->second;
if (!hwCastProviderSession) {
SLOGE("the castId corresonding to castSession is nullptr");
return false;
}
return hwCastProviderSession->AddDevice(deviceInfo, spid);
}
bool HwCastProvider::AddCastDeviceWithConnectionConfig(int castId, DeviceInfo deviceInfo, uint32_t spid,
CastEngine::ConnectionConfig connectionConfig)
{
SLOGI("AddCastDeviceWithConnectionConfig with config castSession and corresponding castId is %{public}d", castId);
std::lock_guard lockGuard(mutexLock_);
SLOGI("add device check lock done");
if (hwCastProviderSessionMap_.find(castId) == hwCastProviderSessionMap_.end()) {
SLOGE("the castId corresonding to castSession is not exist");
return false;
}
auto hwCastProviderSession = hwCastProviderSessionMap_[castId];
if (!hwCastProviderSession) {
SLOGE("the castId corresonding to castSession is nullptr");
return false;
}
return hwCastProviderSession->AddDeviceWithConnectionConfig(deviceInfo, spid, connectionConfig);
}
bool HwCastProvider::RemoveCastDevice(int castId, DeviceInfo deviceInfo, const DeviceRemoveAction deviceRemoveAction)
{
SLOGI("RemoveCastDevice with config castSession and corresonding castId is %{public}d", castId);
std::lock_guard lockGuard(mutexLock_);
SLOGI("remove device check lock");
if (hwCastProviderSessionMap_.find(castId) == hwCastProviderSessionMap_.end()) {
SLOGE("the castId corresonding to castSession is not exist");
return false;
}
auto hwCastProviderSession = hwCastProviderSessionMap_[castId];
if (!hwCastProviderSession) {
SLOGE("the castId corresonding to castSession is nullptr");
return false;
}
return hwCastProviderSession->RemoveDevice(deviceInfo.realDeviceId_, deviceRemoveAction);
}
bool HwCastProvider::RegisterCastStateListener(std::shared_ptr<IAVCastStateListener> listener)
{
SLOGI("RegisterCastStateListener in");
std::lock_guard lockGuard(mutexLock_);
SLOGI("RegisterCastStateListener in pass lock");
if (listener == nullptr) {
SLOGE("RegisterCastStateListener the listener is nullptr");
return false;
}
if (find(castStateListenerList_.begin(), castStateListenerList_.end(), listener) != castStateListenerList_.end()) {
SLOGE("RegisterCastStateListener the listener is already be registered");
return false;
}
SLOGI("RegisterCastStateListener successed, and save it in the castStateListenerList_");
castStateListenerList_.emplace_back(listener);
return true;
}
bool HwCastProvider::UnRegisterCastStateListener(std::shared_ptr<IAVCastStateListener> listener)
{
SLOGI("UnRegisterCastStateListener in");
std::lock_guard lockGuard(mutexLock_);
SLOGI("UnRegisterCastStateListener in pass lock");
if (listener == nullptr) {
SLOGE("UnRegisterCastStateListener the listener is nullptr");
return false;
}
for (auto iter = castStateListenerList_.begin(); iter != castStateListenerList_.end();) {
if (*iter == listener) {
castStateListenerList_.erase(iter);
SLOGI("UnRegisterCastStateListener successed, and erase it from castStateListenerList_");
return true;
} else {
++iter;
}
}
SLOGE("listener is not found in castStateListenerList_, so UnRegisterCastStateListener failed");
return false;
}
std::shared_ptr<IAVCastControllerProxy> HwCastProvider::GetRemoteController(int castId)
{
SLOGI("get remote controller with castId %{public}d", static_cast<int32_t>(castId));
std::lock_guard lockGuard(mutexLock_);
SLOGI("get remote controller check lock with castId %{public}d", static_cast<int32_t>(castId));
if (avCastControllerMap_.find(castId) != avCastControllerMap_.end()) {
SLOGI("the castId corresonding to streamPlayer is already exist");
return avCastControllerMap_[castId];
}
if (hwCastProviderSessionMap_.find(castId) == hwCastProviderSessionMap_.end()) {
SLOGE("No castSession corresonding to castId exists");
return nullptr;
}
auto hwCastProviderSession = hwCastProviderSessionMap_[castId];
if (hwCastProviderSession == nullptr) {
SLOGE("castSession corresonding to castId is nullptr");
return nullptr;
}
std::shared_ptr<IStreamPlayer> streamPlayer = hwCastProviderSession->CreateStreamPlayer();
std::shared_ptr<HwCastStreamPlayer> hwCastStreamPlayer = std::make_shared<HwCastStreamPlayer>(streamPlayer);
if (!hwCastStreamPlayer) {
SLOGE("the created hwCastStreamPlayer is nullptr");
return nullptr;
}
if (hwCastStreamPlayer->Init() == AVSESSION_ERROR) {
SLOGE("hwCastStreamPlayer init failed");
return nullptr;
}
avCastControllerMap_[castId] = hwCastStreamPlayer;
SLOGI("Create streamPlayer finished");
return hwCastStreamPlayer;
}
bool HwCastProvider::SetStreamState(int64_t castHandle, DeviceInfo deviceInfo)
{
std::lock_guard lockGuard(mutexLock_);
int32_t castId = static_cast<int32_t>((static_cast<uint64_t>(castHandle) << 32) >> 32);
mirrorCastHandle.store(castHandle);
SLOGI("mirrorCastHandle is %{public}lld", static_cast<long long>(mirrorCastHandle.load()));
if (hwCastProviderSessionMap_.find(castId) == hwCastProviderSessionMap_.end()) {
SLOGE("SetStreamState failed for the castSession corresponding to castId is not exit");
return false;
}
auto hwCastProviderSession = hwCastProviderSessionMap_[castId];
if (hwCastProviderSession == nullptr) {
SLOGE("SetStreamState failed for the hwCastProviderSession is nullptr");
return false;
}
return hwCastProviderSession->SetStreamState(deviceInfo);
}
bool HwCastProvider::GetRemoteNetWorkId(int32_t castId, std::string deviceId, std::string &networkId)
{
SLOGI("enter GetRemoteNetWorkId");
std::lock_guard lockGuard(mutexLock_);
if (hwCastProviderSessionMap_.find(castId) == hwCastProviderSessionMap_.end()) {
SLOGE("GetRemoteNetWorkId failed for the castSession corresponding to castId is not exit");
return false;
}
auto hwCastProviderSession = hwCastProviderSessionMap_[castId];
if (hwCastProviderSession == nullptr) {
SLOGE("GetRemoteNetWorkId failed for the hwCastProviderSession is nullptr");
return false;
}
return hwCastProviderSession->GetRemoteNetWorkId(deviceId, networkId);
}
bool HwCastProvider::GetRemoteDrmCapabilities(int32_t castId, std::string deviceId,
std::vector<std::string> &drmCapabilities)
{
SLOGI("enter GetRemoteDrmCapabilities");
std::lock_guard lockGuard(mutexLock_);
if (hwCastProviderSessionMap_.find(castId) == hwCastProviderSessionMap_.end()) {
SLOGE("GetRemoteDrmCapabilities failed for the castSession corresponding to castId is not exit");
return false;
}
auto hwCastProviderSession = hwCastProviderSessionMap_[castId];
if (hwCastProviderSession == nullptr) {
SLOGE("GetRemoteDrmCapabilities failed for the hwCastProviderSession is nullptr");
return false;
}
return hwCastProviderSession->GetRemoteDrmCapabilities(deviceId, drmCapabilities);
}
int64_t HwCastProvider::GetMirrorCastHandle()
{
return mirrorCastHandle;
}
void HwCastProvider::SetMirrorCastHandle(int64_t castHandle)
{
SLOGI("SetMirrorCastHandle castHandle is %{public}lld", static_cast<long long>(castHandle));
mirrorCastHandle = castHandle;
}
void HwCastProvider::SendCommandArgsToCast(int castId, const int32_t commandType, const std::string& params)
{
SLOGI("SendCommandArgsToCast with config castSession and corresponding castId is %{public}d", castId);
std::lock_guard lockGuard(mutexLock_);
CHECK_AND_RETURN_LOG(hwCastProviderSessionMap_.find(castId) != hwCastProviderSessionMap_.end(),
"Can not find corresponding castId");
CHECK_AND_RETURN_LOG(hwCastProviderSessionMap_[castId] != nullptr, "castSession is nullptr");
hwCastProviderSessionMap_[castId]->SendCommandArgsToCast(commandType, params);
}
std::string HwCastProvider::QueryCastSessionId(const int32_t castId)
{
SLOGI("QueryCastSessionId with config castSession and corresponding castId is %{public}d", castId);
std::lock_guard lockGuard(mutexLock_);
if (hwCastProviderSessionMap_.find(castId) == hwCastProviderSessionMap_.end()) {
SLOGI("Can not find corresponding castId");
return "";
}
if (hwCastProviderSessionMap_[castId] == nullptr) {
SLOGI("castSession is nullptr");
return "";
}
return hwCastProviderSessionMap_[castId]->QueryCastSessionId();
}
bool HwCastProvider::RegisterCastSessionStateListener(int castId,
std::shared_ptr<IAVCastSessionStateListener> listener)
{
SLOGD("RegisterCastSessionStateListener for castId %{public}d", castId);
if (listener == nullptr) {
SLOGE("RegisterCastSessionStateListener failed for the listener is nullptr");
return false;
}
std::lock_guard lockGuard(mutexLock_);
SLOGI("register castsession state listener check lock with castId %{public}d", static_cast<int32_t>(castId));
if (hwCastProviderSessionMap_.find(castId) == hwCastProviderSessionMap_.end()) {
SLOGE("RegisterCastSessionStateListener failed for the castSession corresponding to castId is not exit");
return false;
}
auto hwCastProviderSession = hwCastProviderSessionMap_[castId];
if (hwCastProviderSession == nullptr) {
SLOGE("RegisterCastSessionStateListener failed for the hwCastProviderSession is nullptr");
return false;
}
return hwCastProviderSession->RegisterCastSessionStateListener(listener);
}
bool HwCastProvider::UnRegisterCastSessionStateListener(int castId,
std::shared_ptr<IAVCastSessionStateListener> listener)
{
if (listener == nullptr) {
SLOGE("UnRegisterCastSessionStateListener failed for the listener is nullptr");
return false;
}
std::lock_guard lockGuard(mutexLock_);
SLOGI("unregister castsession state listener check lock with castId %{public}d", static_cast<int32_t>(castId));
if (hwCastProviderSessionMap_.find(castId) == hwCastProviderSessionMap_.end()) {
SLOGE("UnRegisterCastSessionStateListener failed for the castSession corresponding to castId is not exit");
return false;
}
auto hwCastProviderSession = hwCastProviderSessionMap_[castId];
if (hwCastProviderSession == nullptr) {
SLOGE("UnRegisterCastSessionStateListener failed for the hwCastProviderSession is nullptr");
return false;
}
return hwCastProviderSession->UnRegisterCastSessionStateListener(listener);
}
std::vector<uint32_t> HwCastProvider::ParsePullClients(const std::string& str)
{
std::vector<uint32_t> ret;
cJSON* array = cJSON_Parse(str.c_str());
if (array == nullptr) {
return ret;
}
if (cJSON_IsInvalid(array) || !cJSON_IsArray(array)) {
SLOGE("pullClients is invalid");
cJSON_Delete(array);
return ret;
}
cJSON* item;
cJSON_ArrayForEach(item, array) {
CHECK_AND_CONTINUE(item != nullptr && !cJSON_IsInvalid(item) &&
cJSON_IsNumber(item));
ret.push_back(static_cast<uint32_t>(item->valueint));
}
cJSON_Delete(array);
return ret;
}
void HwCastProvider::buildDeviceInfo(const CastEngine::CastRemoteDevice& castRemoteDevice, DeviceInfo& deviceInfo)
{
deviceInfo.castCategory_ = AVCastCategory::CATEGORY_REMOTE;
deviceInfo.deviceType_ = ConvertCastDeviceTypeToDeviceType(static_cast<int32_t>(castRemoteDevice.rawDeviceType));
deviceInfo.ipAddress_ = castRemoteDevice.ipAddress;
deviceInfo.networkId_ = castRemoteDevice.networkId;
deviceInfo.manufacturer_ = castRemoteDevice.manufacturerName;
deviceInfo.modelName_ = castRemoteDevice.modelName;
deviceInfo.supportedProtocols_ = GetProtocolType(castRemoteDevice.protocolCapabilities);
deviceInfo.supportedDrmCapabilities_ = castRemoteDevice.drmCapabilities;
deviceInfo.isLegacy_ = castRemoteDevice.isLegacy;
deviceInfo.mediumTypes_ = static_cast<int32_t>(castRemoteDevice.mediumTypes);
SLOGI("castRemoteDevice.streamCapability %{public}s", castRemoteDevice.streamCapability.c_str());
deviceInfo.supportedPullClients_ = ParsePullClients(castRemoteDevice.streamCapability);
deviceInfo.bleMac_ = castRemoteDevice.bleMac;
deviceInfo.uuid_ = castRemoteDevice.uuid;
deviceInfo.hiPlayDeviceInfo_.supportCastMode_ = castRemoteDevice.isSupportDeviceCast ?
HiPlayCastMode::DEVICE_LEVEL : HiPlayCastMode::APP_LEVEL;
deviceInfo.realDeviceId_ = castRemoteDevice.deviceId;
}
void HwCastProvider::OnDeviceFound(const std::vector<CastRemoteDevice> &deviceList)
{
std::vector<DeviceInfo> deviceInfoList;
if (deviceList.empty()) {
SLOGW("recv empty deviceList, return");
return;
}
SLOGI("get deviceList size %{public}zu", deviceList.size());
for (const CastRemoteDevice& castRemoteDevice : deviceList) {
SLOGI("get devices with deviceName %{public}s",
AVSessionUtils::GetAnonyDeviceName(castRemoteDevice.deviceName).c_str());
if (castRemoteDevice.serviceInfos.empty()) { // not car device
DeviceInfo deviceInfo;
deviceInfo.deviceId_ = castRemoteDevice.deviceId;
deviceInfo.deviceName_ = castRemoteDevice.deviceName;
deviceInfo.authenticationStatus_ = castRemoteDevice.isTrushed ? TRUSTED_DEVICE : UNTRUSTED_DEVICE;
buildDeviceInfo(castRemoteDevice, deviceInfo);
deviceInfoList.emplace_back(deviceInfo);
} else { // car device
for (const ServiceInfo& info : castRemoteDevice.serviceInfos) {
DeviceInfo deviceInfo;
std::string screenId = std::to_string(info.screenId);
deviceInfo.deviceId_ = castRemoteDevice.deviceId + screenId;
deviceInfo.deviceName_ = castRemoteDevice.deviceName + info.serviceName;
deviceInfo.authenticationStatus_ = info.isTrusted ? TRUSTED_DEVICE : UNTRUSTED_DEVICE;
deviceInfo.screenId_ = info.screenId;
buildDeviceInfo(castRemoteDevice, deviceInfo);
deviceInfoList.emplace_back(deviceInfo);
}
}
}
std::vector<std::shared_ptr<IAVCastStateListener>> listenersSnapshot;
{
std::lock_guard lockGuard(mutexLock_);
listenersSnapshot = castStateListenerList_;
}
for (auto listener : listenersSnapshot) {
if (listener != nullptr) {
SLOGI("trigger the OnDeviceAvailable for registered listeners");
listener->OnDeviceAvailable(deviceInfoList);
}
}
}
void HwCastProvider::OnLogEvent(const int32_t eventId, const int64_t param)
{
SLOGI("eventId is %{public}d, param is %{public}" PRId64, eventId, param);
std::vector<std::shared_ptr<IAVCastStateListener>> listenersSnapshot;
{
std::lock_guard lockGuard(mutexLock_);
listenersSnapshot = castStateListenerList_;
}
for (auto listener : listenersSnapshot) {
if (listener != nullptr) {
SLOGI("trigger the OnDeviceLogEvent for registered listeners");
if (eventId == DeviceLogEventCode::DEVICE_LOG_FULL) {
listener->OnDeviceLogEvent(DeviceLogEventCode::DEVICE_LOG_FULL, param);
} else {
listener->OnDeviceLogEvent(DeviceLogEventCode::DEVICE_LOG_EXCEPTION, param);
}
}
}
}
void HwCastProvider::OnDeviceOffline(const std::string& deviceId)
{
SLOGI("Received on device offline event");
std::vector<std::shared_ptr<IAVCastStateListener>> listenersSnapshot;
{
std::lock_guard lockGuard(mutexLock_);
listenersSnapshot = castStateListenerList_;
}
for (auto listener : listenersSnapshot) {
if (listener != nullptr) {
SLOGI("trigger the OnDeviceOffline for registered listeners");
listener->OnDeviceOffline(deviceId);
}
}
}
void HwCastProvider::NotifyCastSessionCreated(const std::string castSessionId)
{
std::shared_ptr<ICastSession> castSession = nullptr;
CastSessionManager::GetInstance().GetCastSession(castSessionId, castSession);
CHECK_AND_RETURN_LOG(castSession != nullptr, "get cast session failed");
SLOGI("Cast provider received session create common event");
std::weak_ptr<HwCastProvider> weakThis = shared_from_this();
AVSessionEventHandler::GetInstance().AVSessionPostTask([weakThis, castSession]() {
auto sharedThis = weakThis.lock();
CHECK_AND_RETURN_LOG(sharedThis, "HwCastProvider already destroyed");
SLOGI("Cast pvd received session create event and create task thread");
std::vector<std::shared_ptr<IAVCastStateListener>> listenersSnapshot;
{
std::lock_guard lockGuard(sharedThis->mutexLock_);
listenersSnapshot = sharedThis->castStateListenerList_;
}
for (auto listener : listenersSnapshot) {
if (listener != nullptr) {
listener->OnSessionNeedDestroy();
SLOGI("Cast pvd received session create event and session destroy check done");
}
}
int32_t castId;
{
std::lock_guard lockGuard(sharedThis->mutexLock_);
std::vector<bool>::iterator iter = find(sharedThis->castFlag_.begin(), sharedThis->castFlag_.end(), false);
if (iter == sharedThis->castFlag_.end()) {
SLOGE("Do not trigger callback due to the castFlag_ used up.");
return;
}
*iter = true;
castId = iter - sharedThis->castFlag_.begin();
SLOGI("Cast task thread to find flag");
}
auto hwCastProviderSession = std::make_shared<HwCastProviderSession>(castSession);
hwCastProviderSession->Init();
{
std::lock_guard lockGuard(sharedThis->mutexLock_);
sharedThis->hwCastProviderSessionMap_[castId] = hwCastProviderSession;
SLOGI("Cast task thread not to create player");
}
SLOGI("Create streamPlayer finished %{public}d", castId);
for (auto listener : listenersSnapshot) {
if (listener != nullptr) {
listener->OnSessionCreated(castId);
}
}
SLOGI("do session create notify finished %{public}d", castId);
}, "OnSessionCreated", 0);
}
void HwCastProvider::DestroyCastSessionCreated(const std::string castSessionId)
{
std::shared_ptr<ICastSession> castSession = nullptr;
CastSessionManager::GetInstance().GetCastSession(castSessionId, castSession);
auto hwCastProviderSession = std::make_shared<HwCastProviderSession>(castSession);
hwCastProviderSession->Release();
}
void HwCastProvider::OnSessionCreated(const std::shared_ptr<CastEngine::ICastSession> &castSession)
{
SLOGI("Cast provider received session create event");
std::weak_ptr<HwCastProvider> weakThis = shared_from_this();
AVSessionEventHandler::GetInstance().AVSessionPostTask([weakThis, castSession]() {
auto sharedThis = weakThis.lock();
CHECK_AND_RETURN_LOG(sharedThis, "HwCastProvider already destroyed");
SLOGI("Cast pvd received session create event and create task thread");
std::vector<std::shared_ptr<IAVCastStateListener>> listenersSnapshot;
{
std::lock_guard lockGuard(sharedThis->mutexLock_);
listenersSnapshot = sharedThis->castStateListenerList_;
}
for (auto listener : listenersSnapshot) {
if (listener != nullptr) {
listener->OnSessionNeedDestroy();
SLOGI("Cast pvd received session create event and session destroy check done");
}
}
int32_t castId;
{
std::lock_guard lockGuard(sharedThis->mutexLock_);
std::vector<bool>::iterator iter = find(sharedThis->castFlag_.begin(), sharedThis->castFlag_.end(), false);
if (iter == sharedThis->castFlag_.end()) {
SLOGE("Do not trigger callback due to the castFlag_ used up.");
return;
}
*iter = true;
castId = iter - sharedThis->castFlag_.begin();
SLOGI("Cast task thread to find flag");
}
auto hwCastProviderSession = std::make_shared<HwCastProviderSession>(castSession);
hwCastProviderSession->Init();
{
std::lock_guard lockGuard(sharedThis->mutexLock_);
sharedThis->hwCastProviderSessionMap_[castId] = hwCastProviderSession;
SLOGI("Cast task thread to create player");
std::shared_ptr<IStreamPlayer> streamPlayer = hwCastProviderSession->CreateStreamPlayer();
std::shared_ptr<HwCastStreamPlayer> hwCastStreamPlayer = std::make_shared<HwCastStreamPlayer>(streamPlayer);
hwCastStreamPlayer->Init();
sharedThis->avCastControllerMap_[castId] = hwCastStreamPlayer;
}
SLOGI("Create streamPlayer finished %{public}d", castId);
for (auto listener : listenersSnapshot) {
if (listener != nullptr) {
listener->OnSessionCreated(castId);
}
}
SLOGI("do session create notify finished %{public}d", castId);
}, "OnSessionCreated", 0);
}
void HwCastProvider::OnServiceDied()
{
std::vector<std::shared_ptr<IAVCastStateListener>> listenersSnapshot;
{
std::lock_guard lockGuard(mutexLock_);
listenersSnapshot = castStateListenerList_;
}
for (auto listener : listenersSnapshot) {
if (listener != nullptr) {
SLOGI("trigger the OnServiceDied for registered listeners");
listener->OnCastServerDied();
}
}
}
int32_t HwCastProvider::GetProtocolType(uint32_t castProtocolType)
{
int32_t protocolType = (castProtocolType & ProtocolType::TYPE_CAST_PLUS_STREAM) |
(castProtocolType & ProtocolType::TYPE_DLNA) |
((castProtocolType & static_cast<int>(CastEngine::ProtocolType::CAST_PLUS_AUDIO)) ?
ProtocolType::TYPE_CAST_PLUS_AUDIO : 0);
return protocolType;
}
int HwCastProvider::GetCastProtocolType(int castCapability)
{
uint32_t capability = static_cast<uint32_t>(castCapability);
int castProtocolType = static_cast<int>((capability & ProtocolType::TYPE_CAST_PLUS_MIRROR ?
static_cast<uint32_t>(CastEngine::ProtocolType::CAST_PLUS_MIRROR) : 0) |
(capability & ProtocolType::TYPE_CAST_PLUS_STREAM ?
static_cast<uint32_t>(CastEngine::ProtocolType::CAST_PLUS_STREAM) : 0) |
(capability & ProtocolType::TYPE_DLNA ? static_cast<uint32_t>(CastEngine::ProtocolType::DLNA) : 0) |
(capability & ProtocolType::TYPE_CAST_PLUS_AUDIO ?
static_cast<uint32_t>(CastEngine::ProtocolType::CAST_PLUS_AUDIO) : 0));
return castProtocolType;
}
void HwCastProvider::InitCastSessionProperty(uint32_t prototype, bool isPcm, CastSessionProperty& property)
{
property.protocolType = CastEngine::ProtocolType::CAST_PLUS_STREAM;
bool isHiScreen = (prototype & ProtocolType::TYPE_CAST_PLUS_STREAM) != 0;
if (isPcm) {
property.protocolType = isHiScreen ? CastEngine::ProtocolType::CAST_PLUS_MIRROR :
CastEngine::ProtocolType::CAST_PLUS_AUDIO;
}
property.endType = CastEngine::EndType::CAST_SOURCE;
if (isPcm && isHiScreen) {
property.audioProperty.codec = 1;
property.videoProperty.codecType = CastEngine::VideoCodecType::H265;
sptr<Rosen::DisplayLite> display = Rosen::DisplayManagerLite::GetInstance().GetDefaultDisplay();
CHECK_AND_RETURN_LOG(display != nullptr, "display is nullptr");
auto displayInfo = display->GetDisplayInfo();
CHECK_AND_RETURN_LOG(displayInfo != nullptr, "displayInfo is nullptr");
int32_t width = displayInfo->GetWidth();
int32_t height = displayInfo->GetHeight();
property.windowProperty.startX = 0;
property.windowProperty.startY = 0;
property.windowProperty.width = static_cast<uint32_t>(width);
property.windowProperty.height = static_cast<uint32_t>(height);
SLOGI("get the displayInfo width %{public}d, height %{public}d", width, height);
}
}
} // namespace OHOS::AVSession