* Copyright (c) 2026-2026 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 "float_view_controller.h"
#include <set>
#include <map>
#include "float_view_manager.h"
#include "float_window_manager.h"
#include "floating_ball_manager.h"
#include "picture_in_picture_manager.h"
#include "window_manager_hilog.h"
#include "singleton_container.h"
#include "window_adapter.h"
namespace OHOS {
namespace Rosen {
namespace {
const std::string FV_WINDOW_NAME = "float_view_window";
const std::set<FvWindowState> STATE_WITH_WINDOW = {
FvWindowState::FV_STATE_STARTED,
FvWindowState::FV_STATE_HIDDEN,
FvWindowState::FV_STATE_IN_SIDEBAR,
FvWindowState::FV_STATE_IN_FLOATING_BALL,
};
const std::map<FvWindowState, FloatViewState> STATE_TO_STATE = {
{FvWindowState::FV_STATE_STARTED, FloatViewState::FV_STARTED},
{FvWindowState::FV_STATE_HIDDEN, FloatViewState::FV_HIDDEN},
{FvWindowState::FV_STATE_STOPPED, FloatViewState::FV_STOPPED},
{FvWindowState::FV_STATE_IN_SIDEBAR, FloatViewState::FV_IN_SIDEBAR},
{FvWindowState::FV_STATE_IN_FLOATING_BALL, FloatViewState::FV_IN_FLOATING_BALL},
};
}
FloatViewController::FloatViewController(const FvOption &option, napi_env env)
: weakRef_(this), option_(option), env_(env), type_(APIType::NAPI)
{
curState_ = FvWindowState::FV_STATE_UNDEFINED;
id_ = FloatWindowManager::GetControllerId();
SetPackageNameFromContext();
TLOGI(WmsLogTag::WMS_SYSTEM, "FloatViewController created, id: %{public}s", id_.c_str());
}
FloatViewController::FloatViewController(const FvOption &option, ani_env* env)
: weakRef_(this), option_(option), type_(APIType::ANI)
{
if (env && (env->GetVM(&vm_) != ANI_OK || !vm_)) {
TLOGE(WmsLogTag::WMS_SYSTEM, "FloatViewController for ani get vm failed");
}
curState_ = FvWindowState::FV_STATE_UNDEFINED;
id_ = FloatWindowManager::GetControllerId();
SetPackageNameFromContext();
TLOGI(WmsLogTag::WMS_SYSTEM, "FloatViewController created, id: %{public}s", id_.c_str());
}
FloatViewController::~FloatViewController()
{
TLOGI(WmsLogTag::WMS_SYSTEM, "FloatViewController release, id: %{public}s", id_.c_str());
option_.ClearAniReference(GetEnv());
}
void FloatViewController::UpdateMainWindow(const sptr<Window>& mainWindow)
{
if (mainWindow == nullptr) {
return;
}
mainWindow_ = mainWindow;
mainWindowId_ = mainWindow_->GetWindowId();
}
uint32_t FloatViewController::GetMainWindowId() const
{
return mainWindowId_;
}
FvWindowState FloatViewController::GetCurState()
{
std::lock_guard<std::mutex> lock(controllerMutex_);
return curState_;
}
FloatViewTemplate FloatViewController::GetTemplateType() const
{
return static_cast<FloatViewTemplate>(option_.GetTemplate());
}
void FloatViewController::ChangeState(const FvWindowState &newState)
{
std::lock_guard<std::mutex> lock(controllerMutex_);
TLOGI(WmsLogTag::WMS_SYSTEM, "change state from %{public}u to %{public}u, window: %{public}u, id: %{public}s",
curState_, newState, (window_ == nullptr) ? INVALID_WINDOW_ID : window_->GetWindowId(), id_.c_str());
curState_ = newState;
auto it = STATE_TO_STATE.find(newState);
if (it != STATE_TO_STATE.end()) {
OnStateChange(it->second);
}
}
bool FloatViewController::IsStateWithWindow(FvWindowState state)
{
if (STATE_WITH_WINDOW.find(state) != STATE_WITH_WINDOW.end()) {
return true;
}
return false;
}
void FloatViewController::SetBindState(bool isBind)
{
TLOGI(WmsLogTag::WMS_SYSTEM, "FloatViewController SetBindState %{public}d, id: %{public}s", isBind, id_.c_str());
std::lock_guard<std::mutex> lock(controllerMutex_);
bindState_ = isBind;
}
bool FloatViewController::IsBind()
{
std::lock_guard<std::mutex> lock(controllerMutex_);
return bindState_;
}
void FloatViewController::SetBindWindowId(uint32_t windowId)
{
TLOGI(WmsLogTag::WMS_SYSTEM, "FloatViewController SetBindWindowId %{public}d, id: %{public}s", windowId,
id_.c_str());
std::lock_guard<std::mutex> lock(controllerMutex_);
bindWindowId_ = windowId;
}
void FloatViewController::SetShowWhenCreate(bool showWhenCreate)
{
TLOGI(WmsLogTag::WMS_SYSTEM, "FloatViewController SetShowWhenCreate %{public}d, id: %{public}s", showWhenCreate,
id_.c_str());
std::lock_guard<std::mutex> lock(controllerMutex_);
option_.SetShowWhenCreate(showWhenCreate);
if (window_ == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "SetShowWhenCreate failed, window is null, id: %{public}s", id_.c_str());
return;
}
window_->UpdateFloatShowWhenCreate(showWhenCreate);
}
WMError FloatViewController::StartFloatView()
{
TLOGI(WmsLogTag::WMS_SYSTEM, "StartFloatView called, bindState_ %{public}d, id: %{public}s", bindState_,
id_.c_str());
if (IsBind()) {
return FloatWindowManager::StartBindFloatView(weakRef_);
}
return StartFloatViewSingle();
}
WMError FloatViewController::StartFloatViewSingle(bool showWhenCreate)
{
Rect rect = option_.GetRect();
FvStartEventParams params;
FillBaseEventParams(params);
params.width = rect.width_;
params.height = rect.height_;
params.visibleInApp = option_.GetVisibilityInApp();
params.isLoadUi = option_.IsUIPathValid();
auto errorCode = PrepareStartFloatView(showWhenCreate);
if (errorCode != WMError::WM_OK) {
params.errorReason = "PrepareStartFloatView failed";
} else {
errorCode = StartFloatViewInner();
if (errorCode != WMError::WM_OK) {
curState_ = FvWindowState::FV_STATE_ERROR;
OnStateChange(FloatViewState::FV_ERROR);
FloatViewManager::RemoveActiveController(weakRef_);
params.errorReason = "StartFloatViewInner failed";
}
}
SingletonContainer::Get<FloatingViewReporter>().ReportStartEvent(params);
return errorCode;
}
WMError FloatViewController::PrepareStartFloatView(bool showWhenCreate)
{
std::lock_guard<std::mutex> lock(controllerMutex_);
if (FloatViewManager::HasActiveController() && !FloatViewManager::IsActiveController(weakRef_)) {
TLOGI(WmsLogTag::WMS_SYSTEM, "StartFloatView abort");
return WMError::WM_ERROR_FV_START_FAILED;
}
if (curState_ == FvWindowState::FV_STATE_STARTING || IsStateWithWindow(curState_)) {
TLOGW(WmsLogTag::WMS_SYSTEM, "fvWindow state is: %{public}u, id: %{public}u, mainWindow: %{public}u",
curState_, (window_ == nullptr) ? INVALID_WINDOW_ID : window_->GetWindowId(), mainWindowId_);
return WMError::WM_ERROR_FV_REPEAT_OPERATION;
}
if (curState_ == FvWindowState::FV_STATE_STOPPING) {
TLOGW(WmsLogTag::WMS_SYSTEM, "fvWindow state is: %{public}u, id: %{public}u, mainWindow: %{public}u",
curState_, (window_ == nullptr) ? INVALID_WINDOW_ID : window_->GetWindowId(), mainWindowId_);
return WMError::WM_ERROR_FV_INVALID_STATE;
}
curState_ = FvWindowState::FV_STATE_STARTING;
FloatViewManager::SetActiveController(weakRef_);
option_.SetShowWhenCreate(showWhenCreate);
return WMError::WM_OK;
}
WMError FloatViewController::StartFloatViewInner()
{
{
std::lock_guard<std::mutex> lock(controllerMutex_);
WMError errCode = CreateFloatViewWindow();
if (errCode != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_SYSTEM, "Create fv window failed, err: %{public}u", errCode);
return errCode;
}
errCode = SetFloatViewContext();
if (errCode != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_SYSTEM, "Set fv window content failed, err: %{public}u", errCode);
return errCode;
}
}
auto errCode = window_->Show(0, false);
if (errCode != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_SYSTEM, "Show fv window failed, err: %{public}u", errCode);
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (mainWindow_ != nullptr) {
mainWindowLifeCycleListener_ = sptr<FloatViewController::WindowLifeCycleListener>::MakeSptr(mainWindowId_);
mainWindow_->RegisterLifeCycleListener(mainWindowLifeCycleListener_);
}
return WMError::WM_OK;
}
WMError FloatViewController::CreateFloatViewWindow()
{
auto contextPtr = option_.GetContext();
if (contextPtr == nullptr || mainWindow_ == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "Create fv failed, invalid fvOption or mainWindow");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto mainWindowState = mainWindow_->GetWindowState();
TLOGI(WmsLogTag::WMS_SYSTEM, "Main window state: %{public}u", mainWindowState);
if (mainWindowState != WindowState::STATE_SHOWN) {
TLOGW(WmsLogTag::WMS_SYSTEM, "Main window is not in foreground, state: %{public}u", mainWindowState);
return WMError::WM_ERROR_FV_START_FAILED;
}
auto windowOption = sptr<WindowOption>::MakeSptr();
windowOption->SetWindowName(FV_WINDOW_NAME);
windowOption->SetWindowType(WindowType::WINDOW_TYPE_FV);
windowOption->SetWindowMode(WindowMode::WINDOW_MODE_FV);
if (option_.IsRectValid()) {
windowOption->SetWindowRect(option_.GetRect());
}
FloatViewTemplateInfo fvTemplateInfo;
option_.GetFvTemplateInfo(fvTemplateInfo);
fvTemplateInfo.isBind_ = bindState_;
fvTemplateInfo.bindWindowId_ = bindWindowId_;
fvTemplateInfo.id_ = id_;
WMError errCode = WMError::WM_OK;
auto context = static_cast<std::weak_ptr<AbilityRuntime::Context>*>(contextPtr);
if (context == nullptr) {
TLOGW(WmsLogTag::WMS_SYSTEM, "Context is invalid when create window");
return WMError::WM_ERROR_INVALID_WINDOW;
}
sptr<Window> window = FloatWindowManager::CreateFvWindow(windowOption, fvTemplateInfo, context->lock(), errCode,
weakRef_);
if (window == nullptr || errCode != WMError::WM_OK) {
TLOGW(WmsLogTag::WMS_SYSTEM, "Window create failed, reason: %{public}d", errCode);
return errCode == WMError::WM_ERROR_FLOAT_CONFLICT_WITH_OTHERS ? errCode : WMError::WM_ERROR_SYSTEM_ABNORMALLY;
}
window_ = window;
FloatViewManager::AddController(window_->GetWindowId(), weakRef_);
return WMError::WM_OK;
}
WMError FloatViewController::SetFloatViewContext()
{
if (window_ != nullptr && option_.IsUIPathValid()) {
return SetUIContextInner(option_.isLoadUIByName);
}
return WMError::WM_OK;
}
void FloatViewController::WindowLifeCycleListener::AfterDestroyed()
{
TLOGI(WmsLogTag::WMS_SYSTEM, "float view AfterDestroyed");
FloatViewManager::DoActionCloseByMainWindow(mainWindowId_, "AppMainWindowStop");
}
WMError FloatViewController::StopFloatViewFromClient()
{
TLOGI(WmsLogTag::WMS_SYSTEM, "StopFloatViewFromClient called, bindState_ %{public}d, id: %{public}s", bindState_,
id_.c_str());
if (IsBind()) {
return FloatWindowManager::StopBindFloatView(weakRef_);
}
return StopFloatViewFromClientSingle();
}
WMError FloatViewController::StopFloatViewFromClientSingle(bool isForceStop)
{
{
std::lock_guard<std::mutex> lock(controllerMutex_);
TLOGI(WmsLogTag::WMS_SYSTEM, "StopFloatViewFromClient");
if (curState_ == FvWindowState::FV_STATE_STOPPING ||
curState_ == FvWindowState::FV_STATE_STOPPED) {
TLOGE(WmsLogTag::WMS_SYSTEM, "Repeat stop request, curState: %{public}u", curState_);
return WMError::WM_ERROR_FV_REPEAT_OPERATION;
}
if (!isForceStop) {
if (curState_ == FvWindowState::FV_STATE_UNDEFINED ||
curState_ == FvWindowState::FV_STATE_STARTING) {
TLOGE(WmsLogTag::WMS_SYSTEM, "float view not started: curState:%{public}u", curState_);
return WMError::WM_ERROR_FV_INVALID_STATE;
}
}
if (window_ == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "window is nullptr when stop fv");
return WMError::WM_ERROR_INVALID_WINDOW;
}
stopFromClient_ = true;
curState_ = FvWindowState::FV_STATE_STOPPING;
}
window_->NotifyPrepareCloseFloatView();
return WMError::WM_OK;
}
WMError FloatViewController::StopFloatView(const std::string& reason)
{
{
std::lock_guard<std::mutex> lock(controllerMutex_);
TLOGI(WmsLogTag::WMS_SYSTEM, "StopFloatView in, id: %{public}s, reason: %{public}s", id_.c_str(),
reason.c_str());
if ((!stopFromClient_ && curState_ == FvWindowState::FV_STATE_STOPPING) ||
curState_ == FvWindowState::FV_STATE_STOPPED) {
TLOGE(WmsLogTag::WMS_SYSTEM, "Repeat stop request, curState: %{public}u", curState_);
return WMError::WM_ERROR_FV_REPEAT_OPERATION;
}
if (window_ == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "window is nullptr when stop fv");
return WMError::WM_ERROR_INVALID_WINDOW;
}
curState_ = FvWindowState::FV_STATE_STOPPING;
}
return DestroyFloatViewWindow(reason);
}
WMError FloatViewController::RestoreMainWindow(const std::shared_ptr<AAFwk::WantParams>& wantParams)
{
FvRestoreEventParams params;
FillBaseEventParams(params);
WMError errorCode = WMError::WM_OK;
{
std::lock_guard<std::mutex> lock(controllerMutex_);
if (curState_ != FvWindowState::FV_STATE_STARTED) {
TLOGE(WmsLogTag::WMS_SYSTEM, "float view is not created, curState: %{public}u", curState_);
params.errorReason = "float view is not created";
errorCode = WMError::WM_ERROR_FV_INVALID_STATE;
} else if (window_ == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "window is nullptr");
params.errorReason = "window is nullptr";
errorCode = WMError::WM_ERROR_INVALID_WINDOW;
} else {
errorCode = window_->RestoreFloatViewMainWindow(wantParams);
if (errorCode != WMError::WM_OK) {
params.errorReason = "RestoreFloatViewMainWindow failed";
}
}
}
SingletonContainer::Get<FloatingViewReporter>().ReportRestoreEvent(params);
return errorCode;
}
WMError FloatViewController::DestroyFloatViewWindow(const std::string& reason)
{
TLOGI(WmsLogTag::WMS_SYSTEM, "called, id: %{public}s", id_.c_str());
if (window_ == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "window is nullptr when destroy fv");
return WMError::WM_ERROR_INVALID_WINDOW;
}
WMError ret = FloatWindowManager::DestroyFloatWindow(window_);
if (ret != WMError::WM_OK) {
curState_ = FvWindowState::FV_STATE_ERROR;
OnStateChange(FloatViewState::FV_ERROR);
TLOGE(WmsLogTag::WMS_SYSTEM, "window destroy failed, err:%{public}u", ret);
return WMError::WM_ERROR_SYSTEM_ABNORMALLY;
}
curState_ = FvWindowState::FV_STATE_STOPPED;
OnStateChange(FloatViewState::FV_STOPPED, reason);
FloatViewManager::RemoveActiveController(weakRef_);
if (mainWindow_ != nullptr) {
mainWindow_->UnregisterLifeCycleListener(mainWindowLifeCycleListener_);
mainWindowLifeCycleListener_ = nullptr;
}
FloatViewManager::RemoveController(window_->GetWindowId());
window_ = nullptr;
stopFromClient_ = false;
bindWindowId_ = INVALID_WINDOW_ID;
return WMError::WM_OK;
}
WMError FloatViewController::SetUIContext(const std::string &contextUrl,
const std::shared_ptr<NativeReference>& contentStorage, bool isLoadByName)
{
TLOGI(WmsLogTag::WMS_SYSTEM, "napi SetUIContext called");
if (type_ != APIType::NAPI) {
TLOGE(WmsLogTag::WMS_SYSTEM, "napi controller called by ani");
return WMError::WM_ERROR_INVALID_WINDOW;
}
std::lock_guard<std::mutex> lock(controllerMutex_);
option_.SetUIPath(contextUrl);
option_.SetStorage(contentStorage);
option_.isLoadUIByName = isLoadByName;
return SetUIContextInner(isLoadByName);
}
WMError FloatViewController::SetUIContext(const std::string &contextUrl,
const ani_ref& contentStorage, bool isLoadByName)
{
TLOGI(WmsLogTag::WMS_SYSTEM, "ani SetUIContext called");
if (type_ != APIType::ANI) {
TLOGE(WmsLogTag::WMS_SYSTEM, "ani controller called by napi");
return WMError::WM_ERROR_INVALID_WINDOW;
}
std::lock_guard<std::mutex> lock(controllerMutex_);
option_.SetUIPath(contextUrl);
option_.SetStorage(GetEnv(), contentStorage);
option_.isLoadUIByName = isLoadByName;
return SetUIContextInner(isLoadByName);
}
WMError FloatViewController::SetUIContextInner(bool isLoadByName)
{
FvSetUIContentEventParams params;
FillBaseEventParams(params);
WMError errorCode = WMError::WM_OK;
if (window_ == nullptr) {
if (IsStateWithWindow(curState_)) {
TLOGE(WmsLogTag::WMS_SYSTEM, "window is nullptr when SetUIContext");
params.errorReason = "window is nullptr when SetUIContext";
SingletonContainer::Get<FloatingViewReporter>().ReportSetUIContentEvent(params);
return WMError::WM_ERROR_INVALID_WINDOW;
}
return WMError::WM_OK;
}
if (type_ == APIType::NAPI) {
errorCode = SetUIContextNAPI(isLoadByName, params);
} else if (type_ == APIType::ANI) {
errorCode = SetUIContextANI(isLoadByName, params);
}
SingletonContainer::Get<FloatingViewReporter>().ReportSetUIContentEvent(params);
return errorCode;
}
WMError FloatViewController::SetUIContextNAPI(bool isLoadByName, FvSetUIContentEventParams& params)
{
WMError errorCode = WMError::WM_OK;
napi_value storage = nullptr;
auto contentStorage = option_.GetStorage();
auto contentUrl = option_.GetUIPath();
if (contentStorage != nullptr) {
storage = contentStorage->GetNapiValue();
TLOGI(WmsLogTag::WMS_SYSTEM, "Set UI Context with localStorage");
}
napi_env env = static_cast<napi_env>(env_);
WMError errCode;
if (isLoadByName) {
errCode = window_->NapiSetUIContentByName(contentUrl, env, storage);
} else {
errCode = window_->NapiSetUIContent(contentUrl, env, storage, BackupAndRestoreType::NONE);
}
if (errCode != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_SYSTEM, "Set fv window content failed, err: %{public}u", errCode);
params.errorReason = "NapiSetUIContent failed";
errorCode = WMError::WM_ERROR_INVALID_WINDOW;
}
return errorCode;
}
WMError FloatViewController::SetUIContextANI(bool isLoadByName, FvSetUIContentEventParams& params)
{
WMError errorCode = WMError::WM_OK;
auto contentUrl = option_.GetUIPath();
ani_ref storage = option_.GetAniStorage();
ani_env* env = GetEnv();
if (env == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "get env failed");
params.errorReason = "get ani env failed";
errorCode = WMError::WM_ERROR_INVALID_WINDOW;
} else {
WMError errCode;
if (isLoadByName) {
errCode = window_->AniSetUIContentByName(contentUrl, env, static_cast<ani_object>(storage));
} else {
errCode = window_->AniSetUIContent(contentUrl, env, static_cast<ani_object>(storage),
BackupAndRestoreType::NONE);
}
if (errCode != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_SYSTEM, "Set fv window content failed, err: %{public}u", errCode);
params.errorReason = "AniSetUIContent failed";
errorCode = WMError::WM_ERROR_INVALID_WINDOW;
}
}
return errorCode;
}
ani_env* FloatViewController::GetEnv() const
{
if (!vm_) {
return nullptr;
}
if (type_ != APIType::ANI) {
return nullptr;
}
ani_env* env_ = nullptr;
ani_status ret = vm_->GetEnv(ANI_VERSION_1, &env_);
if (ret != ANI_OK || !env_) {
TLOGE(WmsLogTag::WMS_PIP, "FloatViewController Get Env failed ret:%{public}u", ret);
}
return env_;
}
WMError FloatViewController::SetVisibilityInApp(bool visibleInApp)
{
TLOGI(WmsLogTag::WMS_SYSTEM, "SetVisibilityInApp called");
std::lock_guard<std::mutex> lock(controllerMutex_);
option_.SetVisibilityInApp(visibleInApp);
FvSetVisibilityEventParams params;
FillBaseEventParams(params);
params.visibleInApp = visibleInApp;
WMError errorCode = WMError::WM_OK;
if (window_ == nullptr) {
if (IsStateWithWindow(curState_)) {
TLOGE(WmsLogTag::WMS_SYSTEM, "window is nullptr when SetVisibilityInApp");
params.errorReason = "window is nullptr when SetVisibilityInApp";
errorCode = WMError::WM_ERROR_INVALID_WINDOW;
} else {
TLOGI(WmsLogTag::WMS_SYSTEM, "SetVisibilityInApp when window not created, save info");
}
SingletonContainer::Get<FloatingViewReporter>().ReportSetVisibilityEvent(params);
return errorCode;
}
FloatViewTemplateInfo fvTemplateInfo;
option_.GetFvTemplateInfo(fvTemplateInfo);
fvTemplateInfo.id_ = id_;
fvTemplateInfo.isBind_ = bindState_;
errorCode = window_->UpdateFloatView(fvTemplateInfo);
if (errorCode != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_SYSTEM, "Update float view failed when set visibility in app, err: %{public}u", errorCode);
params.errorReason = "Update float view failed when set visibility in app";
errorCode = WMError::WM_ERROR_SYSTEM_ABNORMALLY;
}
SingletonContainer::Get<FloatingViewReporter>().ReportSetVisibilityEvent(params);
return errorCode;
}
WMError FloatViewController::SetWindowSize(const Rect &rect)
{
TLOGI(WmsLogTag::WMS_SYSTEM, "SetWindowSize called");
std::lock_guard<std::mutex> lock(controllerMutex_);
option_.SetRect(rect);
FvSetSizeEventParams params;
FillBaseEventParams(params);
params.width = rect.width_;
params.height = rect.height_;
WMError errorCode = UpdateFloatView();
if (errorCode != WMError::WM_OK) {
params.errorReason = "UpdateFloatView failed";
}
SingletonContainer::Get<FloatingViewReporter>().ReportSetSizeEvent(params);
return errorCode;
}
WMError FloatViewController::SetTemplateTypeAndSize(const std::shared_ptr<TemplateProperty>& templateProperty)
{
TLOGI(WmsLogTag::WMS_SYSTEM, "SetTemplateType called");
std::lock_guard<std::mutex> lock(controllerMutex_);
option_.SetTemplate(templateProperty->templateType);
Rect rect {0, 0, static_cast<uint32_t>(templateProperty->width), static_cast<uint32_t>(templateProperty->height)};
option_.SetRect(rect);
FvSetSizeEventParams params;
FillBaseEventParams(params);
params.width = rect.width_;
params.height = rect.height_;
WMError errorCode = UpdateFloatView();
if (errorCode != WMError::WM_OK) {
params.errorReason = "UpdateFloatView failed";
}
SingletonContainer::Get<FloatingViewReporter>().ReportSetSizeEvent(params);
return errorCode;
}
WMError FloatViewController::UpdateFloatView()
{
if (window_ == nullptr) {
if (IsStateWithWindow(curState_)) {
TLOGE(WmsLogTag::WMS_SYSTEM, "window is nullptr when change float view template info");
return WMError::WM_ERROR_INVALID_WINDOW;
}
TLOGI(WmsLogTag::WMS_SYSTEM, "change float view template info when window not created, save info");
return WMError::WM_OK;
}
FloatViewTemplateInfo fvTemplateInfo;
option_.GetFvTemplateInfo(fvTemplateInfo);
fvTemplateInfo.id_ = id_;
fvTemplateInfo.isBind_ = bindState_;
auto errCode = window_->UpdateFloatView(fvTemplateInfo);
if (errCode != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_SYSTEM, "Update float view failed when change float view, err: %{public}u", errCode);
return WMError::WM_ERROR_SYSTEM_ABNORMALLY;
}
return WMError::WM_OK;
}
void FloatViewController::SyncWindowInfo(uint32_t windowId, const FloatViewWindowInfo& windowInfo,
const std::string& reason)
{
TLOGI(WmsLogTag::WMS_SYSTEM, "SyncWindowInfo called, id: %{public}s, reason: %{public}s", id_.c_str(),
reason.c_str());
{
std::lock_guard<std::mutex> lock(controllerMutex_);
if (window_ == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "window is nullptr when SyncWindowInfo");
return;
}
if (window_->GetWindowId() != windowId) {
TLOGE(WmsLogTag::WMS_SYSTEM, "window id is not matched when SyncWindowInfo, "
"windowId: %{public}u, infoWindowId: %{public}u", window_->GetWindowId(), windowId);
return;
}
windowInfo_ = windowInfo;
option_.SetRect(windowInfo_.windowRect_);
}
OnRectChange(windowInfo.windowRect_, windowInfo.scale_, reason);
}
void FloatViewController::SyncLimits(uint32_t windowId, const std::map<uint32_t, FloatViewLimits>& fvLimits)
{
TLOGI(WmsLogTag::WMS_SYSTEM, "SyncLimits called, id: %{public}s", id_.c_str());
FloatViewLimits limits;
{
std::lock_guard<std::mutex> lock(controllerMutex_);
if (window_ == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "window is nullptr when SyncLimits");
return;
}
if (window_->GetWindowId() != windowId) {
TLOGE(WmsLogTag::WMS_SYSTEM, "window id is not matched when SyncLimits, "
"windowId: %{public}u, infoWindowId: %{public}u", window_->GetWindowId(), windowId);
return;
}
auto it = fvLimits.find(option_.GetTemplate());
if (it == fvLimits.end()) {
TLOGE(WmsLogTag::WMS_SYSTEM, "template dont have limit.");
return;
}
limits = it->second;
}
OnLimitsChange(limits);
}
FloatViewWindowInfo FloatViewController::GetWindowInfo() const
{
TLOGI(WmsLogTag::WMS_SYSTEM, "GetWindowInfo called, id: %{public}s", id_.c_str());
return windowInfo_;
}
sptr<Window> FloatViewController::GetWindow() const
{
return window_;
}
void FloatViewController::OnStateChange(const FloatViewState& state, std::string stopReason)
{
std::vector<sptr<IFvStateChangeObserver>> listeners;
{
std::lock_guard<std::mutex> lock(listenerMutex_);
listeners.assign(stateChangeObservers_.begin(), stateChangeObservers_.end());
}
for (auto& listener : listeners) {
if (listener == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "state change listener is nullptr");
continue;
}
listener->OnStateChange(state, stopReason);
}
}
void FloatViewController::OnRectChange(const Rect& window, double scale, const std::string& reason)
{
std::vector<sptr<IFvRectChangeObserver>> listeners;
{
std::lock_guard<std::mutex> lock(listenerMutex_);
listeners.assign(rectChangeObservers_.begin(), rectChangeObservers_.end());
}
for (auto& listener : listeners) {
if (listener == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "rectangle change listener is nullptr");
continue;
}
listener->OnRectangleChange(window, scale, reason);
}
}
void FloatViewController::OnLimitsChange(const FloatViewLimits& limits)
{
std::vector<sptr<IFvLimitsChangeObserver>> listeners;
{
std::lock_guard<std::mutex> lock(listenerMutex_);
listeners.assign(limitsChangeObservers_.begin(), limitsChangeObservers_.end());
}
for (auto& listener : listeners) {
if (listener == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "limits change listener is nullptr");
continue;
}
listener->OnLimitsChange(limits);
}
}
WMError FloatViewController::RegisterStateChangeListener(const sptr<IFvStateChangeObserver>& listener)
{
return RegisterListener(stateChangeObservers_, listener);
}
WMError FloatViewController::UnregisterStateChangeListener(const sptr<IFvStateChangeObserver>& listener)
{
return UnRegisterListener(stateChangeObservers_, listener);
}
WMError FloatViewController::RegisterRectChangeListener(const sptr<IFvRectChangeObserver>& listener)
{
return RegisterListener(rectChangeObservers_, listener);
}
WMError FloatViewController::UnregisterRectChangeListener(const sptr<IFvRectChangeObserver>& listener)
{
return UnRegisterListener(rectChangeObservers_, listener);
}
WMError FloatViewController::RegisterLimitsChangeListener(const sptr<IFvLimitsChangeObserver>& listener)
{
return RegisterListener(limitsChangeObservers_, listener);
}
WMError FloatViewController::UnregisterLimitsChangeListener(const sptr<IFvLimitsChangeObserver>& listener)
{
return UnRegisterListener(limitsChangeObservers_, listener);
}
template<typename T>
WMError FloatViewController::RegisterListener(std::vector<sptr<T>>& holder, const sptr<T>& listener)
{
std::lock_guard<std::mutex> lock(listenerMutex_);
if (listener == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "listener is nullptr");
return WMError::WM_ERROR_INVALID_OPERATION;
}
if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
TLOGE(WmsLogTag::WMS_SYSTEM, "Listener already registered");
return WMError::WM_ERROR_FV_REPEAT_OPERATION;
}
holder.emplace_back(listener);
return WMError::WM_OK;
}
template<typename T>
WMError FloatViewController::UnRegisterListener(std::vector<sptr<T>>& holder, const sptr<T>& listener)
{
std::lock_guard<std::mutex> lock(listenerMutex_);
if (listener == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "listener could not be null");
return WMError::WM_ERROR_INVALID_OPERATION;
}
holder.erase(std::remove_if(holder.begin(), holder.end(),
[listener](const sptr<T>& registeredListener) {
return registeredListener == listener;
}), holder.end());
return WMError::WM_OK;
}
void FloatViewController::SetPackageNameFromContext()
{
auto contextPtr = option_.GetContext();
auto context = static_cast<std::weak_ptr<AbilityRuntime::Context>*>(contextPtr);
if (context == nullptr) {
return;
}
const std::shared_ptr<AbilityRuntime::Context>& abilityContext = context->lock();
if (abilityContext == nullptr || abilityContext->GetApplicationInfo() == nullptr) {
return;
}
SingletonContainer::Get<FloatingViewReporter>().SetCurrentPackageName(
abilityContext->GetApplicationInfo()->name);
}
void FloatViewController::FillBaseEventParams(FvBaseEventParams& base) const
{
base.controllerId = id_;
base.templateType = option_.GetTemplate();
base.bindFloatingBall = bindState_;
}
}
}