1e0dac50fSopenharmony_ci/* 2e0dac50fSopenharmony_ci * Copyright (c) 2023-2023 Huawei Device Co., Ltd. 3e0dac50fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4e0dac50fSopenharmony_ci * you may not use this file except in compliance with the License. 5e0dac50fSopenharmony_ci * You may obtain a copy of the License at 6e0dac50fSopenharmony_ci * 7e0dac50fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8e0dac50fSopenharmony_ci * 9e0dac50fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10e0dac50fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11e0dac50fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e0dac50fSopenharmony_ci * See the License for the specific language governing permissions and 13e0dac50fSopenharmony_ci * limitations under the License. 14e0dac50fSopenharmony_ci */ 15e0dac50fSopenharmony_ci 16e0dac50fSopenharmony_ci#include "picture_in_picture_controller.h" 17e0dac50fSopenharmony_ci 18e0dac50fSopenharmony_ci#include <event_handler.h> 19e0dac50fSopenharmony_ci#include <refbase.h> 20e0dac50fSopenharmony_ci#include <power_mgr_client.h> 21e0dac50fSopenharmony_ci#include <transaction/rs_sync_transaction_controller.h> 22e0dac50fSopenharmony_ci#include "picture_in_picture_manager.h" 23e0dac50fSopenharmony_ci#include "picture_in_picture_option.h" 24e0dac50fSopenharmony_ci#include "window_manager_hilog.h" 25e0dac50fSopenharmony_ci#include "window_option.h" 26e0dac50fSopenharmony_ci#include "window.h" 27e0dac50fSopenharmony_ci#include "wm_common.h" 28e0dac50fSopenharmony_ci#include "singleton_container.h" 29e0dac50fSopenharmony_ci#include "datashare_predicates.h" 30e0dac50fSopenharmony_ci#include "datashare_result_set.h" 31e0dac50fSopenharmony_ci#include "datashare_helper.h" 32e0dac50fSopenharmony_ci#include "iservice_registry.h" 33e0dac50fSopenharmony_ci#include "result_set.h" 34e0dac50fSopenharmony_ci#include "system_ability_definition.h" 35e0dac50fSopenharmony_ci#include "uri.h" 36e0dac50fSopenharmony_ci 37e0dac50fSopenharmony_cinamespace OHOS { 38e0dac50fSopenharmony_cinamespace Rosen { 39e0dac50fSopenharmony_cinamespace { 40e0dac50fSopenharmony_ci constexpr int32_t PIP_DESTROY_TIMEOUT = 600; 41e0dac50fSopenharmony_ci constexpr int32_t PIP_SUCCESS = 1; 42e0dac50fSopenharmony_ci constexpr int32_t FAILED = 0; 43e0dac50fSopenharmony_ci constexpr uint32_t PIP_LOW_PRIORITY = 0; 44e0dac50fSopenharmony_ci constexpr uint32_t PIP_HIGH_PRIORITY = 1; 45e0dac50fSopenharmony_ci const std::string PIP_CONTENT_PATH = "/system/etc/window/resources/pip_content.abc"; 46e0dac50fSopenharmony_ci const std::string DESTROY_TIMEOUT_TASK = "PipDestroyTimeout"; 47e0dac50fSopenharmony_ci const int DEFAULT_ASPECT_RATIO[] = {16, 9}; 48e0dac50fSopenharmony_ci} 49e0dac50fSopenharmony_ci 50e0dac50fSopenharmony_ciuint32_t PictureInPictureController::GetPipPriority(uint32_t pipTemplateType) 51e0dac50fSopenharmony_ci{ 52e0dac50fSopenharmony_ci if (pipTemplateType >= static_cast<uint32_t>(PiPTemplateType::END)) { 53e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "param invalid, pipTemplateType is %{public}d", pipTemplateType); 54e0dac50fSopenharmony_ci return PIP_LOW_PRIORITY; 55e0dac50fSopenharmony_ci } 56e0dac50fSopenharmony_ci if (pipTemplateType == static_cast<uint32_t>(PiPTemplateType::VIDEO_PLAY) || 57e0dac50fSopenharmony_ci pipTemplateType == static_cast<uint32_t>(PiPTemplateType::VIDEO_LIVE)) { 58e0dac50fSopenharmony_ci return PIP_LOW_PRIORITY; 59e0dac50fSopenharmony_ci } else { 60e0dac50fSopenharmony_ci return PIP_HIGH_PRIORITY; 61e0dac50fSopenharmony_ci } 62e0dac50fSopenharmony_ci} 63e0dac50fSopenharmony_ci 64e0dac50fSopenharmony_ciPictureInPictureController::PictureInPictureController(sptr<PipOption> pipOption, sptr<Window> mainWindow, 65e0dac50fSopenharmony_ci uint32_t windowId, napi_env env) 66e0dac50fSopenharmony_ci : weakRef_(this), pipOption_(pipOption), mainWindow_(mainWindow), mainWindowId_(windowId), env_(env) 67e0dac50fSopenharmony_ci{ 68e0dac50fSopenharmony_ci this->handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner()); 69e0dac50fSopenharmony_ci curState_ = PiPWindowState::STATE_UNDEFINED; 70e0dac50fSopenharmony_ci} 71e0dac50fSopenharmony_ci 72e0dac50fSopenharmony_ciPictureInPictureController::~PictureInPictureController() 73e0dac50fSopenharmony_ci{ 74e0dac50fSopenharmony_ci PictureInPictureManager::DetachAutoStartController(handleId_, weakRef_); 75e0dac50fSopenharmony_ci} 76e0dac50fSopenharmony_ci 77e0dac50fSopenharmony_ciWMError PictureInPictureController::CreatePictureInPictureWindow(StartPipType startType) 78e0dac50fSopenharmony_ci{ 79e0dac50fSopenharmony_ci if (pipOption_ == nullptr || pipOption_->GetContext() == nullptr) { 80e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "Create pip failed, invalid pipOption"); 81e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_CREATE_FAILED; 82e0dac50fSopenharmony_ci } 83e0dac50fSopenharmony_ci mainWindowXComponentController_ = pipOption_->GetXComponentController(); 84e0dac50fSopenharmony_ci if ((mainWindowXComponentController_ == nullptr && !IsTypeNodeEnabled()) || mainWindow_ == nullptr) { 85e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "mainWindowXComponentController or mainWindow is nullptr"); 86e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_CREATE_FAILED; 87e0dac50fSopenharmony_ci } 88e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "mainWindow:%{public}u, mainWindowState:%{public}u", 89e0dac50fSopenharmony_ci mainWindowId_, mainWindow_->GetWindowState()); 90e0dac50fSopenharmony_ci mainWindowLifeCycleListener_ = sptr<PictureInPictureController::WindowLifeCycleListener>::MakeSptr(); 91e0dac50fSopenharmony_ci mainWindow_->RegisterLifeCycleListener(mainWindowLifeCycleListener_); 92e0dac50fSopenharmony_ci if (startType != StartPipType::AUTO_START && mainWindow_->GetWindowState() != WindowState::STATE_SHOWN) { 93e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "mainWindow is not shown. create failed."); 94e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_CREATE_FAILED; 95e0dac50fSopenharmony_ci } 96e0dac50fSopenharmony_ci UpdateWinRectByComponent(); 97e0dac50fSopenharmony_ci auto windowOption = sptr<WindowOption>::MakeSptr(); 98e0dac50fSopenharmony_ci windowOption->SetWindowName(PIP_WINDOW_NAME); 99e0dac50fSopenharmony_ci windowOption->SetWindowType(WindowType::WINDOW_TYPE_PIP); 100e0dac50fSopenharmony_ci windowOption->SetWindowMode(WindowMode::WINDOW_MODE_PIP); 101e0dac50fSopenharmony_ci windowOption->SetWindowRect(windowRect_); 102e0dac50fSopenharmony_ci windowOption->SetKeepScreenOn(true); 103e0dac50fSopenharmony_ci windowOption->SetTouchable(false); 104e0dac50fSopenharmony_ci WMError errCode = WMError::WM_OK; 105e0dac50fSopenharmony_ci PiPTemplateInfo pipTemplateInfo; 106e0dac50fSopenharmony_ci pipTemplateInfo.pipTemplateType = pipOption_->GetPipTemplate(); 107e0dac50fSopenharmony_ci pipTemplateInfo.controlGroup = pipOption_->GetControlGroup(); 108e0dac50fSopenharmony_ci pipTemplateInfo.priority = GetPipPriority(pipOption_->GetPipTemplate()); 109e0dac50fSopenharmony_ci pipTemplateInfo.pipControlStatusInfoList = pipOption_->GetControlStatus(); 110e0dac50fSopenharmony_ci pipTemplateInfo.pipControlEnableInfoList = pipOption_->GetControlEnable(); 111e0dac50fSopenharmony_ci auto context = static_cast<std::weak_ptr<AbilityRuntime::Context>*>(pipOption_->GetContext()); 112e0dac50fSopenharmony_ci const std::shared_ptr<AbilityRuntime::Context>& abilityContext = context->lock(); 113e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().SetCurrentPackageName(abilityContext->GetApplicationInfo()->name); 114e0dac50fSopenharmony_ci sptr<Window> window = Window::CreatePiP(windowOption, pipTemplateInfo, context->lock(), errCode); 115e0dac50fSopenharmony_ci if (window == nullptr || errCode != WMError::WM_OK) { 116e0dac50fSopenharmony_ci TLOGW(WmsLogTag::WMS_PIP, "Window create failed, reason: %{public}d", errCode); 117e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_CREATE_FAILED; 118e0dac50fSopenharmony_ci } 119e0dac50fSopenharmony_ci window_ = window; 120e0dac50fSopenharmony_ci window_->UpdatePiPRect(windowRect_, WindowSizeChangeReason::PIP_START); 121e0dac50fSopenharmony_ci PictureInPictureManager::PutPipControllerInfo(window_->GetWindowId(), this); 122e0dac50fSopenharmony_ci return WMError::WM_OK; 123e0dac50fSopenharmony_ci} 124e0dac50fSopenharmony_ci 125e0dac50fSopenharmony_ciWMError PictureInPictureController::ShowPictureInPictureWindow(StartPipType startType) 126e0dac50fSopenharmony_ci{ 127e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "startType:%{public}u", startType); 128e0dac50fSopenharmony_ci if (pipOption_ == nullptr) { 129e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "Get PictureInPicture option failed"); 130e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_CREATE_FAILED; 131e0dac50fSopenharmony_ci } 132e0dac50fSopenharmony_ci if (window_ == nullptr) { 133e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "window is null when show pip"); 134e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPStartWindow(static_cast<int32_t>(startType), 135e0dac50fSopenharmony_ci pipOption_->GetPipTemplate(), FAILED, "window is nullptr"); 136e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_STATE_ABNORMALLY; 137e0dac50fSopenharmony_ci } 138e0dac50fSopenharmony_ci for (auto& listener : pipLifeCycleListeners_) { 139e0dac50fSopenharmony_ci listener->OnPreparePictureInPictureStart(); 140e0dac50fSopenharmony_ci } 141e0dac50fSopenharmony_ci window_->SetUIContentByAbc(PIP_CONTENT_PATH, env_, nullptr, nullptr); 142e0dac50fSopenharmony_ci WMError errCode = window_->Show(0, false); 143e0dac50fSopenharmony_ci if (errCode != WMError::WM_OK) { 144e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "window show failed, err: %{public}u", errCode); 145e0dac50fSopenharmony_ci for (auto& listener : pipLifeCycleListeners_) { 146e0dac50fSopenharmony_ci listener->OnPictureInPictureOperationError(static_cast<int32_t>(errCode)); 147e0dac50fSopenharmony_ci } 148e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPStartWindow(static_cast<int32_t>(startType), 149e0dac50fSopenharmony_ci pipOption_->GetPipTemplate(), FAILED, "window show failed"); 150e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_INTERNAL_ERROR; 151e0dac50fSopenharmony_ci } 152e0dac50fSopenharmony_ci uint32_t requestWidth = 0; 153e0dac50fSopenharmony_ci uint32_t requestHeight = 0; 154e0dac50fSopenharmony_ci pipOption_->GetContentSize(requestWidth, requestHeight); 155e0dac50fSopenharmony_ci WindowSizeChangeReason reason = WindowSizeChangeReason::PIP_SHOW; 156e0dac50fSopenharmony_ci if (startType == StartPipType::AUTO_START) { 157e0dac50fSopenharmony_ci reason = WindowSizeChangeReason::PIP_AUTO_START; 158e0dac50fSopenharmony_ci } 159e0dac50fSopenharmony_ci if (requestWidth > 0 && requestHeight > 0) { 160e0dac50fSopenharmony_ci Rect requestRect = {0, 0, requestWidth, requestHeight}; 161e0dac50fSopenharmony_ci window_->UpdatePiPRect(requestRect, reason); 162e0dac50fSopenharmony_ci } else { 163e0dac50fSopenharmony_ci window_->UpdatePiPRect(windowRect_, reason); 164e0dac50fSopenharmony_ci } 165e0dac50fSopenharmony_ci PictureInPictureManager::SetActiveController(this); 166e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPStartWindow(static_cast<int32_t>(startType), 167e0dac50fSopenharmony_ci pipOption_->GetPipTemplate(), PIP_SUCCESS, "show pip success"); 168e0dac50fSopenharmony_ci isStoppedFromClient_ = false; 169e0dac50fSopenharmony_ci return WMError::WM_OK; 170e0dac50fSopenharmony_ci} 171e0dac50fSopenharmony_ci 172e0dac50fSopenharmony_ciWMError PictureInPictureController::StartPictureInPicture(StartPipType startType) 173e0dac50fSopenharmony_ci{ 174e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "called"); 175e0dac50fSopenharmony_ci if (pipOption_ == nullptr || pipOption_->GetContext() == nullptr) { 176e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "pipOption is null or Get PictureInPictureOption failed"); 177e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_CREATE_FAILED; 178e0dac50fSopenharmony_ci } 179e0dac50fSopenharmony_ci if (curState_ == PiPWindowState::STATE_STARTING || curState_ == PiPWindowState::STATE_STARTED) { 180e0dac50fSopenharmony_ci TLOGW(WmsLogTag::WMS_PIP, "pipWindow is starting, state: %{public}u, id: %{public}u, mainWindow: %{public}u", 181e0dac50fSopenharmony_ci curState_, (window_ == nullptr) ? INVALID_WINDOW_ID : window_->GetWindowId(), mainWindowId_); 182e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPStartWindow(static_cast<int32_t>(startType), 183e0dac50fSopenharmony_ci pipOption_->GetPipTemplate(), FAILED, "Pip window is starting"); 184e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_REPEAT_OPERATION; 185e0dac50fSopenharmony_ci } 186e0dac50fSopenharmony_ci if (!IsPullPiPAndHandleNavigation()) { 187e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "Navigation operate failed"); 188e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_CREATE_FAILED; 189e0dac50fSopenharmony_ci } 190e0dac50fSopenharmony_ci curState_ = PiPWindowState::STATE_STARTING; 191e0dac50fSopenharmony_ci if (PictureInPictureManager::HasActiveController() && !PictureInPictureManager::IsActiveController(weakRef_)) { 192e0dac50fSopenharmony_ci // if current controller is not the active one, but belongs to the same mainWindow, reserve pipWindow 193e0dac50fSopenharmony_ci if (PictureInPictureManager::IsAttachedToSameWindow(mainWindowId_)) { 194e0dac50fSopenharmony_ci window_ = PictureInPictureManager::GetCurrentWindow(); 195e0dac50fSopenharmony_ci if (window_ == nullptr) { 196e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "Reuse pipWindow failed"); 197e0dac50fSopenharmony_ci curState_ = PiPWindowState::STATE_UNDEFINED; 198e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_CREATE_FAILED; 199e0dac50fSopenharmony_ci } 200e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "Reuse pipWindow: %{public}u as attached to the same mainWindow: %{public}u", 201e0dac50fSopenharmony_ci window_->GetWindowId(), mainWindowId_); 202e0dac50fSopenharmony_ci PictureInPictureManager::DoClose(false, false); 203e0dac50fSopenharmony_ci mainWindowXComponentController_ = IsTypeNodeEnabled() ? nullptr : pipOption_->GetXComponentController(); 204e0dac50fSopenharmony_ci UpdateWinRectByComponent(); 205e0dac50fSopenharmony_ci UpdateContentSize(windowRect_.width_, windowRect_.height_); 206e0dac50fSopenharmony_ci PictureInPictureManager::PutPipControllerInfo(window_->GetWindowId(), this); 207e0dac50fSopenharmony_ci WMError err = ShowPictureInPictureWindow(startType); 208e0dac50fSopenharmony_ci if (err != WMError::WM_OK) { 209e0dac50fSopenharmony_ci curState_ = PiPWindowState::STATE_UNDEFINED; 210e0dac50fSopenharmony_ci } else { 211e0dac50fSopenharmony_ci curState_ = PiPWindowState::STATE_STARTED; 212e0dac50fSopenharmony_ci } 213e0dac50fSopenharmony_ci return err; 214e0dac50fSopenharmony_ci } 215e0dac50fSopenharmony_ci // otherwise, stop the previous one 216e0dac50fSopenharmony_ci PictureInPictureManager::DoClose(true, true); 217e0dac50fSopenharmony_ci } 218e0dac50fSopenharmony_ci return StartPictureInPictureInner(startType); 219e0dac50fSopenharmony_ci} 220e0dac50fSopenharmony_ci 221e0dac50fSopenharmony_ciWMError PictureInPictureController::StartPictureInPictureInner(StartPipType startType) 222e0dac50fSopenharmony_ci{ 223e0dac50fSopenharmony_ci WMError errCode = CreatePictureInPictureWindow(startType); 224e0dac50fSopenharmony_ci if (errCode != WMError::WM_OK) { 225e0dac50fSopenharmony_ci curState_ = PiPWindowState::STATE_UNDEFINED; 226e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "Create pip window failed, err: %{public}u", errCode); 227e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPStartWindow(static_cast<int32_t>(startType), 228e0dac50fSopenharmony_ci pipOption_->GetPipTemplate(), FAILED, "Create pip window failed"); 229e0dac50fSopenharmony_ci return errCode; 230e0dac50fSopenharmony_ci } 231e0dac50fSopenharmony_ci StartPipType type = startType; 232e0dac50fSopenharmony_ci if (IsTypeNodeEnabled() && startType != StartPipType::AUTO_START) { 233e0dac50fSopenharmony_ci type = StartPipType::AUTO_START; 234e0dac50fSopenharmony_ci } 235e0dac50fSopenharmony_ci errCode = ShowPictureInPictureWindow(type); 236e0dac50fSopenharmony_ci if (errCode != WMError::WM_OK) { 237e0dac50fSopenharmony_ci curState_ = PiPWindowState::STATE_UNDEFINED; 238e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "Show pip window failed, err: %{public}u", errCode); 239e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPStartWindow(static_cast<int32_t>(type), 240e0dac50fSopenharmony_ci pipOption_->GetPipTemplate(), FAILED, "Show pip window failed"); 241e0dac50fSopenharmony_ci return errCode; 242e0dac50fSopenharmony_ci } 243e0dac50fSopenharmony_ci curState_ = PiPWindowState::STATE_STARTED; 244e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPStartWindow(static_cast<int32_t>(type), 245e0dac50fSopenharmony_ci pipOption_->GetPipTemplate(), PIP_SUCCESS, "start pip success"); 246e0dac50fSopenharmony_ci return WMError::WM_OK; 247e0dac50fSopenharmony_ci} 248e0dac50fSopenharmony_ci 249e0dac50fSopenharmony_ciWMError PictureInPictureController::StopPictureInPictureFromClient() 250e0dac50fSopenharmony_ci{ 251e0dac50fSopenharmony_ci if (!window_) { 252e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "window is null"); 253e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPStopWindow(static_cast<int32_t>(StopPipType::USER_STOP), 254e0dac50fSopenharmony_ci pipOption_->GetPipTemplate(), FAILED, "window is null"); 255e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_STATE_ABNORMALLY; 256e0dac50fSopenharmony_ci } 257e0dac50fSopenharmony_ci if (curState_ == PiPWindowState::STATE_STOPPING || curState_ == PiPWindowState::STATE_STOPPED || 258e0dac50fSopenharmony_ci curState_ == PiPWindowState::STATE_RESTORING) { 259e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "Repeat stop request, curState: %{public}u", curState_); 260e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPStopWindow(static_cast<int32_t>(StopPipType::USER_STOP), 261e0dac50fSopenharmony_ci pipOption_->GetPipTemplate(), FAILED, "Repeat stop request"); 262e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_REPEAT_OPERATION; 263e0dac50fSopenharmony_ci } 264e0dac50fSopenharmony_ci isStoppedFromClient_ = true; 265e0dac50fSopenharmony_ci WMError res = window_->NotifyPrepareClosePiPWindow(); 266e0dac50fSopenharmony_ci if (res != WMError::WM_OK) { 267e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPStopWindow(static_cast<int32_t>(StopPipType::USER_STOP), 268e0dac50fSopenharmony_ci pipOption_->GetPipTemplate(), FAILED, "window destroy failed"); 269e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_DESTROY_FAILED; 270e0dac50fSopenharmony_ci } 271e0dac50fSopenharmony_ci curState_ = PiPWindowState::STATE_STOPPING; 272e0dac50fSopenharmony_ci return res; 273e0dac50fSopenharmony_ci} 274e0dac50fSopenharmony_ci 275e0dac50fSopenharmony_ciWMError PictureInPictureController::StopPictureInPicture(bool destroyWindow, StopPipType stopPipType, bool withAnim) 276e0dac50fSopenharmony_ci{ 277e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "destroyWindow: %{public}u anim: %{public}d", destroyWindow, withAnim); 278e0dac50fSopenharmony_ci if ((!isStoppedFromClient_ && curState_ == PiPWindowState::STATE_STOPPING) || 279e0dac50fSopenharmony_ci curState_ == PiPWindowState::STATE_STOPPED) { 280e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "Repeat stop request, curState: %{public}u", curState_); 281e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPStopWindow(static_cast<int32_t>(stopPipType), 282e0dac50fSopenharmony_ci pipOption_->GetPipTemplate(), FAILED, "Repeat stop request"); 283e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_REPEAT_OPERATION; 284e0dac50fSopenharmony_ci } 285e0dac50fSopenharmony_ci if (window_ == nullptr) { 286e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "window is nullptr when stop pip"); 287e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPStopWindow(static_cast<int32_t>(stopPipType), 288e0dac50fSopenharmony_ci pipOption_->GetPipTemplate(), FAILED, "window_ is nullptr"); 289e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_STATE_ABNORMALLY; 290e0dac50fSopenharmony_ci } 291e0dac50fSopenharmony_ci curState_ = PiPWindowState::STATE_STOPPING; 292e0dac50fSopenharmony_ci for (auto& listener : pipLifeCycleListeners_) { 293e0dac50fSopenharmony_ci listener->OnPreparePictureInPictureStop(); 294e0dac50fSopenharmony_ci } 295e0dac50fSopenharmony_ci if (!destroyWindow) { 296e0dac50fSopenharmony_ci ResetExtController(); 297e0dac50fSopenharmony_ci curState_ = PiPWindowState::STATE_STOPPED; 298e0dac50fSopenharmony_ci for (auto& listener : pipLifeCycleListeners_) { 299e0dac50fSopenharmony_ci listener->OnPictureInPictureStop(); 300e0dac50fSopenharmony_ci } 301e0dac50fSopenharmony_ci PictureInPictureManager::RemoveActiveController(weakRef_); 302e0dac50fSopenharmony_ci PictureInPictureManager::RemovePipControllerInfo(window_->GetWindowId()); 303e0dac50fSopenharmony_ci return WMError::WM_OK; 304e0dac50fSopenharmony_ci } 305e0dac50fSopenharmony_ci return StopPictureInPictureInner(stopPipType, withAnim); 306e0dac50fSopenharmony_ci} 307e0dac50fSopenharmony_ci 308e0dac50fSopenharmony_ciWMError PictureInPictureController::StopPictureInPictureInner(StopPipType stopType, bool withAnim) 309e0dac50fSopenharmony_ci{ 310e0dac50fSopenharmony_ci uint32_t templateType = 0; 311e0dac50fSopenharmony_ci if (pipOption_ != nullptr) { 312e0dac50fSopenharmony_ci templateType = pipOption_->GetPipTemplate(); 313e0dac50fSopenharmony_ci } 314e0dac50fSopenharmony_ci if (window_ == nullptr) { 315e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "window is nullptr in stop pip inner"); 316e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPStopWindow(static_cast<int32_t>(stopType), 317e0dac50fSopenharmony_ci templateType, FAILED, "pipController is null"); 318e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_INTERNAL_ERROR; 319e0dac50fSopenharmony_ci } 320e0dac50fSopenharmony_ci auto syncTransactionController = RSSyncTransactionController::GetInstance(); 321e0dac50fSopenharmony_ci if (syncTransactionController) { 322e0dac50fSopenharmony_ci syncTransactionController->OpenSyncTransaction(); 323e0dac50fSopenharmony_ci } 324e0dac50fSopenharmony_ci ResetExtController(); 325e0dac50fSopenharmony_ci if (!withAnim) { 326e0dac50fSopenharmony_ci DestroyPictureInPictureWindow(); 327e0dac50fSopenharmony_ci } else { 328e0dac50fSopenharmony_ci // handle destroy timeout 329e0dac50fSopenharmony_ci if (handler_ == nullptr) { 330e0dac50fSopenharmony_ci handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner()); 331e0dac50fSopenharmony_ci } 332e0dac50fSopenharmony_ci auto timeoutTask = [weakThis = wptr(this)]() { 333e0dac50fSopenharmony_ci auto pipController = weakThis.promote(); 334e0dac50fSopenharmony_ci if (pipController == nullptr) { 335e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "execute destroy timeout task failed, pipController is null"); 336e0dac50fSopenharmony_ci return; 337e0dac50fSopenharmony_ci } 338e0dac50fSopenharmony_ci if (pipController->curState_ == PiPWindowState::STATE_STOPPED) { 339e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "pip window already destroyed"); 340e0dac50fSopenharmony_ci return; 341e0dac50fSopenharmony_ci } 342e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "DestroyPictureInPictureWindow timeout"); 343e0dac50fSopenharmony_ci pipController->DestroyPictureInPictureWindow(); 344e0dac50fSopenharmony_ci }; 345e0dac50fSopenharmony_ci handler_->PostTask(std::move(timeoutTask), DESTROY_TIMEOUT_TASK, PIP_DESTROY_TIMEOUT); 346e0dac50fSopenharmony_ci } 347e0dac50fSopenharmony_ci if (syncTransactionController) { 348e0dac50fSopenharmony_ci syncTransactionController->CloseSyncTransaction(); 349e0dac50fSopenharmony_ci } 350e0dac50fSopenharmony_ci 351e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPStopWindow(static_cast<int32_t>(stopType), 352e0dac50fSopenharmony_ci templateType, PIP_SUCCESS, "pip window stop success"); 353e0dac50fSopenharmony_ci return WMError::WM_OK; 354e0dac50fSopenharmony_ci} 355e0dac50fSopenharmony_ci 356e0dac50fSopenharmony_ciWMError PictureInPictureController::DestroyPictureInPictureWindow() 357e0dac50fSopenharmony_ci{ 358e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "called"); 359e0dac50fSopenharmony_ci handler_->RemoveTask(DESTROY_TIMEOUT_TASK); 360e0dac50fSopenharmony_ci if (window_ == nullptr) { 361e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "window is nullptr when destroy pip"); 362e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_INTERNAL_ERROR; 363e0dac50fSopenharmony_ci } 364e0dac50fSopenharmony_ci WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(window_->Destroy()); 365e0dac50fSopenharmony_ci if (ret != WmErrorCode::WM_OK) { 366e0dac50fSopenharmony_ci curState_ = PiPWindowState::STATE_UNDEFINED; 367e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "window destroy failed, err:%{public}u", ret); 368e0dac50fSopenharmony_ci for (auto& listener : pipLifeCycleListeners_) { 369e0dac50fSopenharmony_ci listener->OnPictureInPictureOperationError(static_cast<int32_t>(ret)); 370e0dac50fSopenharmony_ci } 371e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_DESTROY_FAILED; 372e0dac50fSopenharmony_ci } 373e0dac50fSopenharmony_ci PictureInPictureManager::RemoveActiveController(this); 374e0dac50fSopenharmony_ci PictureInPictureManager::RemovePipControllerInfo(window_->GetWindowId()); 375e0dac50fSopenharmony_ci window_ = nullptr; 376e0dac50fSopenharmony_ci 377e0dac50fSopenharmony_ci for (auto& listener : pipLifeCycleListeners_) { 378e0dac50fSopenharmony_ci listener->OnPictureInPictureStop(); 379e0dac50fSopenharmony_ci } 380e0dac50fSopenharmony_ci curState_ = PiPWindowState::STATE_STOPPED; 381e0dac50fSopenharmony_ci std::string navId = pipOption_ == nullptr ? "" : pipOption_->GetNavigationId(); 382e0dac50fSopenharmony_ci if (!navId.empty() && mainWindow_ && !IsTypeNodeEnabled()) { 383e0dac50fSopenharmony_ci auto navController = NavigationController::GetNavigationController(mainWindow_->GetUIContent(), navId); 384e0dac50fSopenharmony_ci if (navController) { 385e0dac50fSopenharmony_ci navController->DeletePIPMode(handleId_); 386e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "Delete pip mode id: %{public}d", handleId_); 387e0dac50fSopenharmony_ci } 388e0dac50fSopenharmony_ci } 389e0dac50fSopenharmony_ci if (mainWindow_ != nullptr) { 390e0dac50fSopenharmony_ci mainWindow_->UnregisterLifeCycleListener(mainWindowLifeCycleListener_); 391e0dac50fSopenharmony_ci } 392e0dac50fSopenharmony_ci mainWindowLifeCycleListener_ = nullptr; 393e0dac50fSopenharmony_ci return WMError::WM_OK; 394e0dac50fSopenharmony_ci} 395e0dac50fSopenharmony_ci 396e0dac50fSopenharmony_cisptr<Window> PictureInPictureController::GetPipWindow() const 397e0dac50fSopenharmony_ci{ 398e0dac50fSopenharmony_ci return window_; 399e0dac50fSopenharmony_ci} 400e0dac50fSopenharmony_ci 401e0dac50fSopenharmony_ciuint32_t PictureInPictureController::GetMainWindowId() 402e0dac50fSopenharmony_ci{ 403e0dac50fSopenharmony_ci return mainWindowId_; 404e0dac50fSopenharmony_ci} 405e0dac50fSopenharmony_ci 406e0dac50fSopenharmony_civoid PictureInPictureController::SetPipWindow(sptr<Window> window) 407e0dac50fSopenharmony_ci{ 408e0dac50fSopenharmony_ci window_ = window; 409e0dac50fSopenharmony_ci} 410e0dac50fSopenharmony_ci 411e0dac50fSopenharmony_civoid PictureInPictureController::SetAutoStartEnabled(bool enable) 412e0dac50fSopenharmony_ci{ 413e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "enable: %{public}u, mainWindow: %{public}u", enable, mainWindowId_); 414e0dac50fSopenharmony_ci isAutoStartEnabled_ = enable; 415e0dac50fSopenharmony_ci if (mainWindow_ == nullptr) { 416e0dac50fSopenharmony_ci return; 417e0dac50fSopenharmony_ci } 418e0dac50fSopenharmony_ci mainWindow_->SetAutoStartPiP(enable); 419e0dac50fSopenharmony_ci if (isAutoStartEnabled_) { 420e0dac50fSopenharmony_ci // cache navigation here as we cannot get containerId while BG 421e0dac50fSopenharmony_ci if (!IsPullPiPAndHandleNavigation()) { 422e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "Navigation operate failed"); 423e0dac50fSopenharmony_ci return; 424e0dac50fSopenharmony_ci } 425e0dac50fSopenharmony_ci PictureInPictureManager::AttachAutoStartController(handleId_, weakRef_); 426e0dac50fSopenharmony_ci } else { 427e0dac50fSopenharmony_ci PictureInPictureManager::DetachAutoStartController(handleId_, weakRef_); 428e0dac50fSopenharmony_ci if (IsTypeNodeEnabled()) { 429e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "typeNode enabled"); 430e0dac50fSopenharmony_ci return; 431e0dac50fSopenharmony_ci } 432e0dac50fSopenharmony_ci if (!pipOption_) { 433e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "pipOption is null"); 434e0dac50fSopenharmony_ci return; 435e0dac50fSopenharmony_ci } 436e0dac50fSopenharmony_ci std::string navId = pipOption_->GetNavigationId(); 437e0dac50fSopenharmony_ci if (!navId.empty()) { 438e0dac50fSopenharmony_ci auto navController = NavigationController::GetNavigationController(mainWindow_->GetUIContent(), navId); 439e0dac50fSopenharmony_ci if (navController) { 440e0dac50fSopenharmony_ci navController->DeletePIPMode(handleId_); 441e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "Delete pip mode id: %{public}d", handleId_); 442e0dac50fSopenharmony_ci } 443e0dac50fSopenharmony_ci } 444e0dac50fSopenharmony_ci } 445e0dac50fSopenharmony_ci} 446e0dac50fSopenharmony_ci 447e0dac50fSopenharmony_civoid PictureInPictureController::IsAutoStartEnabled(bool& enable) const 448e0dac50fSopenharmony_ci{ 449e0dac50fSopenharmony_ci enable = isAutoStartEnabled_; 450e0dac50fSopenharmony_ci} 451e0dac50fSopenharmony_ci 452e0dac50fSopenharmony_ciPiPWindowState PictureInPictureController::GetControllerState() 453e0dac50fSopenharmony_ci{ 454e0dac50fSopenharmony_ci return curState_; 455e0dac50fSopenharmony_ci} 456e0dac50fSopenharmony_ci 457e0dac50fSopenharmony_civoid PictureInPictureController::UpdateContentSize(int32_t width, int32_t height) 458e0dac50fSopenharmony_ci{ 459e0dac50fSopenharmony_ci if (width <= 0 || height <= 0) { 460e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "invalid size"); 461e0dac50fSopenharmony_ci return; 462e0dac50fSopenharmony_ci } 463e0dac50fSopenharmony_ci pipOption_->SetContentSize(static_cast<uint32_t>(width), static_cast<uint32_t>(height)); 464e0dac50fSopenharmony_ci if (curState_ != PiPWindowState::STATE_STARTED) { 465e0dac50fSopenharmony_ci TLOGD(WmsLogTag::WMS_PIP, "UpdateContentSize is disabled when state: %{public}u", curState_); 466e0dac50fSopenharmony_ci return; 467e0dac50fSopenharmony_ci } 468e0dac50fSopenharmony_ci if (window_ == nullptr) { 469e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "pipWindow not exist"); 470e0dac50fSopenharmony_ci return; 471e0dac50fSopenharmony_ci } 472e0dac50fSopenharmony_ci if (mainWindowXComponentController_ && !IsTypeNodeEnabled()) { 473e0dac50fSopenharmony_ci float posX = 0; 474e0dac50fSopenharmony_ci float posY = 0; 475e0dac50fSopenharmony_ci float newWidth = 0; 476e0dac50fSopenharmony_ci float newHeight = 0; 477e0dac50fSopenharmony_ci mainWindowXComponentController_->GetGlobalPosition(posX, posY); 478e0dac50fSopenharmony_ci mainWindowXComponentController_->GetSize(newWidth, newHeight); 479e0dac50fSopenharmony_ci bool isSizeChange = IsContentSizeChanged(newWidth, newHeight, posX, posY); 480e0dac50fSopenharmony_ci if (isSizeChange) { 481e0dac50fSopenharmony_ci Rect r = {static_cast<int32_t>(posX), static_cast<int32_t>(posY), 482e0dac50fSopenharmony_ci static_cast<uint32_t>(newWidth), static_cast<uint32_t>(newHeight)}; 483e0dac50fSopenharmony_ci window_->UpdatePiPRect(r, WindowSizeChangeReason::TRANSFORM); 484e0dac50fSopenharmony_ci } 485e0dac50fSopenharmony_ci } 486e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "UpdateContentSize window: %{public}u width:%{public}u height:%{public}u", 487e0dac50fSopenharmony_ci window_->GetWindowId(), width, height); 488e0dac50fSopenharmony_ci Rect rect = {0, 0, width, height}; 489e0dac50fSopenharmony_ci window_->UpdatePiPRect(rect, WindowSizeChangeReason::PIP_RATIO_CHANGE); 490e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPRatio(width, height); 491e0dac50fSopenharmony_ci} 492e0dac50fSopenharmony_ci 493e0dac50fSopenharmony_ci 494e0dac50fSopenharmony_civoid PictureInPictureController::UpdatePiPControlStatus(PiPControlType controlType, PiPControlStatus status) 495e0dac50fSopenharmony_ci{ 496e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "controlType:%{public}u, status:%{public}d", controlType, status); 497e0dac50fSopenharmony_ci if (static_cast<int32_t>(status) < -1) { 498e0dac50fSopenharmony_ci pipOption_->SetPiPControlEnabled(controlType, status); 499e0dac50fSopenharmony_ci } else { 500e0dac50fSopenharmony_ci pipOption_->SetPiPControlStatus(controlType, status); 501e0dac50fSopenharmony_ci } 502e0dac50fSopenharmony_ci if (window_ == nullptr) { 503e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "pipWindow not exist"); 504e0dac50fSopenharmony_ci return; 505e0dac50fSopenharmony_ci } 506e0dac50fSopenharmony_ci window_->UpdatePiPControlStatus(controlType, status); 507e0dac50fSopenharmony_ci} 508e0dac50fSopenharmony_ci 509e0dac50fSopenharmony_cibool PictureInPictureController::IsContentSizeChanged(float width, float height, float posX, float posY) 510e0dac50fSopenharmony_ci{ 511e0dac50fSopenharmony_ci return windowRect_.width_ != static_cast<uint32_t>(width) || 512e0dac50fSopenharmony_ci windowRect_.height_ != static_cast<uint32_t>(height) || 513e0dac50fSopenharmony_ci windowRect_.posX_ != static_cast<int32_t>(posX) || windowRect_.posY_ != static_cast<int32_t>(posY); 514e0dac50fSopenharmony_ci} 515e0dac50fSopenharmony_ci 516e0dac50fSopenharmony_civoid PictureInPictureController::WindowLifeCycleListener::AfterDestroyed() 517e0dac50fSopenharmony_ci{ 518e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "stop picture_in_picture when attached window destroy"); 519e0dac50fSopenharmony_ci PictureInPictureManager::DoClose(true, true); 520e0dac50fSopenharmony_ci} 521e0dac50fSopenharmony_ci 522e0dac50fSopenharmony_civoid PictureInPictureController::DoActionEvent(const std::string& actionName, int32_t status) 523e0dac50fSopenharmony_ci{ 524e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "actionName: %{public}s", actionName.c_str()); 525e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPActionEvent(pipOption_->GetPipTemplate(), actionName); 526e0dac50fSopenharmony_ci for (auto& listener : pipActionObservers_) { 527e0dac50fSopenharmony_ci listener->OnActionEvent(actionName, status); 528e0dac50fSopenharmony_ci } 529e0dac50fSopenharmony_ci if (CONTROL_TYPE_MAP.find(actionName) != CONTROL_TYPE_MAP.end()) { 530e0dac50fSopenharmony_ci pipOption_->SetPiPControlStatus(CONTROL_TYPE_MAP[actionName], static_cast<PiPControlStatus>(status)); 531e0dac50fSopenharmony_ci } 532e0dac50fSopenharmony_ci} 533e0dac50fSopenharmony_ci 534e0dac50fSopenharmony_civoid PictureInPictureController::PreRestorePictureInPicture() 535e0dac50fSopenharmony_ci{ 536e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "called"); 537e0dac50fSopenharmony_ci curState_ = PiPWindowState::STATE_RESTORING; 538e0dac50fSopenharmony_ci for (auto& listener : pipLifeCycleListeners_) { 539e0dac50fSopenharmony_ci listener->OnRestoreUserInterface(); 540e0dac50fSopenharmony_ci } 541e0dac50fSopenharmony_ci} 542e0dac50fSopenharmony_ci 543e0dac50fSopenharmony_civoid PictureInPictureController::DoControlEvent(PiPControlType controlType, PiPControlStatus status) 544e0dac50fSopenharmony_ci{ 545e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "controlType:%{public}u, enabled:%{public}d", controlType, status); 546e0dac50fSopenharmony_ci if (pipOption_ == nullptr) { 547e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "pipOption_ is nullptr"); 548e0dac50fSopenharmony_ci return; 549e0dac50fSopenharmony_ci } 550e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPControlEvent(pipOption_->GetPipTemplate(), controlType); 551e0dac50fSopenharmony_ci for (auto& listener : pipControlObservers_) { 552e0dac50fSopenharmony_ci listener->OnControlEvent(controlType, status); 553e0dac50fSopenharmony_ci } 554e0dac50fSopenharmony_ci pipOption_->SetPiPControlStatus(controlType, status); 555e0dac50fSopenharmony_ci} 556e0dac50fSopenharmony_ci 557e0dac50fSopenharmony_civoid PictureInPictureController::RestorePictureInPictureWindow() 558e0dac50fSopenharmony_ci{ 559e0dac50fSopenharmony_ci StopPictureInPicture(true, StopPipType::NULL_STOP, true); 560e0dac50fSopenharmony_ci SingletonContainer::Get<PiPReporter>().ReportPiPRestore(); 561e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "restore pip main window finished"); 562e0dac50fSopenharmony_ci} 563e0dac50fSopenharmony_ci 564e0dac50fSopenharmony_civoid PictureInPictureController::PrepareSource() 565e0dac50fSopenharmony_ci{ 566e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "in"); 567e0dac50fSopenharmony_ci if (IsTypeNodeEnabled()) { 568e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "typeNode enabled"); 569e0dac50fSopenharmony_ci return; 570e0dac50fSopenharmony_ci } 571e0dac50fSopenharmony_ci if (mainWindow_ == nullptr) { 572e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "mainWindow is nullptr"); 573e0dac50fSopenharmony_ci return; 574e0dac50fSopenharmony_ci } 575e0dac50fSopenharmony_ci std::string navId = pipOption_->GetNavigationId(); 576e0dac50fSopenharmony_ci if (navId != "") { 577e0dac50fSopenharmony_ci auto navController = NavigationController::GetNavigationController(mainWindow_->GetUIContent(), navId); 578e0dac50fSopenharmony_ci if (navController) { 579e0dac50fSopenharmony_ci navController->PushInPIP(handleId_); 580e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "Push in pip handleId: %{public}d", handleId_); 581e0dac50fSopenharmony_ci } else { 582e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "navController is nullptr"); 583e0dac50fSopenharmony_ci } 584e0dac50fSopenharmony_ci } 585e0dac50fSopenharmony_ci} 586e0dac50fSopenharmony_ci 587e0dac50fSopenharmony_civoid PictureInPictureController::LocateSource() 588e0dac50fSopenharmony_ci{ 589e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "in"); 590e0dac50fSopenharmony_ci if (window_ == nullptr) { 591e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "window is nullptr"); 592e0dac50fSopenharmony_ci return; 593e0dac50fSopenharmony_ci } 594e0dac50fSopenharmony_ci window_->SetTransparent(true); 595e0dac50fSopenharmony_ci UpdatePiPSourceRect(); 596e0dac50fSopenharmony_ci} 597e0dac50fSopenharmony_ci 598e0dac50fSopenharmony_civoid PictureInPictureController::UpdateWinRectByComponent() 599e0dac50fSopenharmony_ci{ 600e0dac50fSopenharmony_ci if (IsTypeNodeEnabled()) { 601e0dac50fSopenharmony_ci uint32_t contentWidth = 0; 602e0dac50fSopenharmony_ci uint32_t contentHeight = 0; 603e0dac50fSopenharmony_ci pipOption_->GetContentSize(contentWidth, contentHeight); 604e0dac50fSopenharmony_ci if (contentWidth == 0 || contentHeight == 0) { 605e0dac50fSopenharmony_ci contentWidth = DEFAULT_ASPECT_RATIO[0]; 606e0dac50fSopenharmony_ci contentHeight = DEFAULT_ASPECT_RATIO[1]; 607e0dac50fSopenharmony_ci } 608e0dac50fSopenharmony_ci windowRect_.posX_ = 0; 609e0dac50fSopenharmony_ci windowRect_.posY_ = 0; 610e0dac50fSopenharmony_ci windowRect_.width_ = contentWidth; 611e0dac50fSopenharmony_ci windowRect_.height_ = contentHeight; 612e0dac50fSopenharmony_ci return; 613e0dac50fSopenharmony_ci } 614e0dac50fSopenharmony_ci if (!mainWindowXComponentController_) { 615e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "main window xComponent not set"); 616e0dac50fSopenharmony_ci return; 617e0dac50fSopenharmony_ci } 618e0dac50fSopenharmony_ci float posX = 0; 619e0dac50fSopenharmony_ci float posY = 0; 620e0dac50fSopenharmony_ci float width = 0; 621e0dac50fSopenharmony_ci float height = 0; 622e0dac50fSopenharmony_ci mainWindowXComponentController_->GetGlobalPosition(posX, posY); 623e0dac50fSopenharmony_ci mainWindowXComponentController_->GetSize(width, height); 624e0dac50fSopenharmony_ci windowRect_.width_ = static_cast<uint32_t>(width); 625e0dac50fSopenharmony_ci windowRect_.height_ = static_cast<uint32_t>(height); 626e0dac50fSopenharmony_ci if (windowRect_.width_ == 0 || windowRect_.height_ == 0) { 627e0dac50fSopenharmony_ci uint32_t contentWidth = 0; 628e0dac50fSopenharmony_ci uint32_t contentHeight = 0; 629e0dac50fSopenharmony_ci pipOption_->GetContentSize(contentWidth, contentHeight); 630e0dac50fSopenharmony_ci windowRect_.width_ = contentWidth; 631e0dac50fSopenharmony_ci windowRect_.height_ = contentHeight; 632e0dac50fSopenharmony_ci } 633e0dac50fSopenharmony_ci windowRect_.posX_ = static_cast<int32_t>(posX); 634e0dac50fSopenharmony_ci windowRect_.posY_ = static_cast<int32_t>(posY); 635e0dac50fSopenharmony_ci TLOGD(WmsLogTag::WMS_PIP, "position width: %{public}u, height: %{public}u, posX: %{public}d, posY: %{public}d", 636e0dac50fSopenharmony_ci windowRect_.width_, windowRect_.height_, windowRect_.posX_, windowRect_.posY_); 637e0dac50fSopenharmony_ci} 638e0dac50fSopenharmony_ci 639e0dac50fSopenharmony_civoid PictureInPictureController::UpdatePiPSourceRect() const 640e0dac50fSopenharmony_ci{ 641e0dac50fSopenharmony_ci if (IsTypeNodeEnabled() && window_ != nullptr) { 642e0dac50fSopenharmony_ci Rect rect = {0, 0, 0, 0}; 643e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "use typeNode, unable to locate source rect"); 644e0dac50fSopenharmony_ci window_->UpdatePiPRect(rect, WindowSizeChangeReason::PIP_RESTORE); 645e0dac50fSopenharmony_ci return; 646e0dac50fSopenharmony_ci } 647e0dac50fSopenharmony_ci if (mainWindowXComponentController_ == nullptr || window_ == nullptr) { 648e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "xcomponent controller not valid"); 649e0dac50fSopenharmony_ci return; 650e0dac50fSopenharmony_ci } 651e0dac50fSopenharmony_ci float posX = 0; 652e0dac50fSopenharmony_ci float posY = 0; 653e0dac50fSopenharmony_ci float width = 0; 654e0dac50fSopenharmony_ci float height = 0; 655e0dac50fSopenharmony_ci mainWindowXComponentController_->GetGlobalPosition(posX, posY); 656e0dac50fSopenharmony_ci mainWindowXComponentController_->GetSize(width, height); 657e0dac50fSopenharmony_ci Rect rect = { posX, posY, width, height }; 658e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "result rect: [%{public}d, %{public}d, %{public}u, %{public}u]", 659e0dac50fSopenharmony_ci rect.posX_, rect.posY_, rect.width_, rect.height_); 660e0dac50fSopenharmony_ci window_->UpdatePiPRect(rect, WindowSizeChangeReason::PIP_RESTORE); 661e0dac50fSopenharmony_ci} 662e0dac50fSopenharmony_ci 663e0dac50fSopenharmony_civoid PictureInPictureController::ResetExtController() 664e0dac50fSopenharmony_ci{ 665e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "called"); 666e0dac50fSopenharmony_ci if (IsTypeNodeEnabled()) { 667e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "skip resetExtController as nodeController enabled"); 668e0dac50fSopenharmony_ci return; 669e0dac50fSopenharmony_ci } 670e0dac50fSopenharmony_ci if (mainWindowXComponentController_ == nullptr || pipXComponentController_ == nullptr) { 671e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "error when resetExtController, one of the xComponentController is null"); 672e0dac50fSopenharmony_ci return; 673e0dac50fSopenharmony_ci } 674e0dac50fSopenharmony_ci XComponentControllerErrorCode errorCode = 675e0dac50fSopenharmony_ci mainWindowXComponentController_->ResetExtController(pipXComponentController_); 676e0dac50fSopenharmony_ci if (errorCode != XComponentControllerErrorCode::XCOMPONENT_CONTROLLER_NO_ERROR) { 677e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "swap xComponent failed, errorCode: %{public}u", errorCode); 678e0dac50fSopenharmony_ci } 679e0dac50fSopenharmony_ci} 680e0dac50fSopenharmony_ci 681e0dac50fSopenharmony_ciWMError PictureInPictureController::SetXComponentController(std::shared_ptr<XComponentController> xComponentController) 682e0dac50fSopenharmony_ci{ 683e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "called"); 684e0dac50fSopenharmony_ci if (IsTypeNodeEnabled()) { 685e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "skip as nodeController enabled"); 686e0dac50fSopenharmony_ci return WMError::WM_OK; 687e0dac50fSopenharmony_ci } 688e0dac50fSopenharmony_ci pipXComponentController_ = xComponentController; 689e0dac50fSopenharmony_ci if (window_ == nullptr) { 690e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "window is nullptr when set XComponentController"); 691e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_STATE_ABNORMALLY; 692e0dac50fSopenharmony_ci } 693e0dac50fSopenharmony_ci if (mainWindowXComponentController_ == nullptr || pipXComponentController_ == nullptr) { 694e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "error when setXController, one of the xComponentController is null"); 695e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_STATE_ABNORMALLY; 696e0dac50fSopenharmony_ci } 697e0dac50fSopenharmony_ci XComponentControllerErrorCode errorCode = 698e0dac50fSopenharmony_ci mainWindowXComponentController_->SetExtController(pipXComponentController_); 699e0dac50fSopenharmony_ci if (errorCode != XComponentControllerErrorCode::XCOMPONENT_CONTROLLER_NO_ERROR) { 700e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "swap xComponent failed, errorCode: %{public}u", errorCode); 701e0dac50fSopenharmony_ci return WMError::WM_ERROR_PIP_INTERNAL_ERROR; 702e0dac50fSopenharmony_ci } 703e0dac50fSopenharmony_ci OnPictureInPictureStart(); 704e0dac50fSopenharmony_ci return WMError::WM_OK; 705e0dac50fSopenharmony_ci} 706e0dac50fSopenharmony_ci 707e0dac50fSopenharmony_civoid PictureInPictureController::OnPictureInPictureStart() 708e0dac50fSopenharmony_ci{ 709e0dac50fSopenharmony_ci for (auto& listener : pipLifeCycleListeners_) { 710e0dac50fSopenharmony_ci listener->OnPictureInPictureStart(); 711e0dac50fSopenharmony_ci } 712e0dac50fSopenharmony_ci} 713e0dac50fSopenharmony_ci 714e0dac50fSopenharmony_cibool PictureInPictureController::IsTypeNodeEnabled() const 715e0dac50fSopenharmony_ci{ 716e0dac50fSopenharmony_ci return pipOption_ != nullptr ? pipOption_->IsTypeNodeEnabled() : false; 717e0dac50fSopenharmony_ci} 718e0dac50fSopenharmony_ci 719e0dac50fSopenharmony_ciWMError PictureInPictureController::RegisterPiPLifecycle(const sptr<IPiPLifeCycle>& listener) 720e0dac50fSopenharmony_ci{ 721e0dac50fSopenharmony_ci return RegisterListener(pipLifeCycleListeners_, listener); 722e0dac50fSopenharmony_ci} 723e0dac50fSopenharmony_ci 724e0dac50fSopenharmony_ciWMError PictureInPictureController::RegisterPiPActionObserver(const sptr<IPiPActionObserver>& listener) 725e0dac50fSopenharmony_ci{ 726e0dac50fSopenharmony_ci return RegisterListener(pipActionObservers_, listener); 727e0dac50fSopenharmony_ci} 728e0dac50fSopenharmony_ci 729e0dac50fSopenharmony_ciWMError PictureInPictureController::RegisterPiPControlObserver(const sptr<IPiPControlObserver>& listener) 730e0dac50fSopenharmony_ci{ 731e0dac50fSopenharmony_ci return RegisterListener(pipControlObservers_, listener); 732e0dac50fSopenharmony_ci} 733e0dac50fSopenharmony_ci 734e0dac50fSopenharmony_ciWMError PictureInPictureController::UnregisterPiPLifecycle(const sptr<IPiPLifeCycle>& listener) 735e0dac50fSopenharmony_ci{ 736e0dac50fSopenharmony_ci return UnregisterListener(pipLifeCycleListeners_, listener); 737e0dac50fSopenharmony_ci} 738e0dac50fSopenharmony_ci 739e0dac50fSopenharmony_ciWMError PictureInPictureController::UnregisterPiPActionObserver(const sptr<IPiPActionObserver>& listener) 740e0dac50fSopenharmony_ci{ 741e0dac50fSopenharmony_ci return UnregisterListener(pipActionObservers_, listener); 742e0dac50fSopenharmony_ci} 743e0dac50fSopenharmony_ci 744e0dac50fSopenharmony_ciWMError PictureInPictureController::UnregisterPiPControlObserver(const sptr<IPiPControlObserver>& listener) 745e0dac50fSopenharmony_ci{ 746e0dac50fSopenharmony_ci return UnregisterListener(pipControlObservers_, listener); 747e0dac50fSopenharmony_ci} 748e0dac50fSopenharmony_ci 749e0dac50fSopenharmony_citemplate<typename T> 750e0dac50fSopenharmony_ciWMError PictureInPictureController::RegisterListener(std::vector<sptr<T>>& holder, const sptr<T>& listener) 751e0dac50fSopenharmony_ci{ 752e0dac50fSopenharmony_ci if (listener == nullptr) { 753e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "listener is nullptr"); 754e0dac50fSopenharmony_ci return WMError::WM_ERROR_NULLPTR; 755e0dac50fSopenharmony_ci } 756e0dac50fSopenharmony_ci if (std::find(holder.begin(), holder.end(), listener) != holder.end()) { 757e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "Listener already registered"); 758e0dac50fSopenharmony_ci return WMError::WM_OK; 759e0dac50fSopenharmony_ci } 760e0dac50fSopenharmony_ci holder.emplace_back(listener); 761e0dac50fSopenharmony_ci return WMError::WM_OK; 762e0dac50fSopenharmony_ci} 763e0dac50fSopenharmony_ci 764e0dac50fSopenharmony_citemplate<typename T> 765e0dac50fSopenharmony_ciWMError PictureInPictureController::UnregisterListener(std::vector<sptr<T>>& holder, const sptr<T>& listener) 766e0dac50fSopenharmony_ci{ 767e0dac50fSopenharmony_ci if (listener == nullptr) { 768e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "listener could not be null"); 769e0dac50fSopenharmony_ci return WMError::WM_ERROR_NULLPTR; 770e0dac50fSopenharmony_ci } 771e0dac50fSopenharmony_ci holder.erase(std::remove_if(holder.begin(), holder.end(), 772e0dac50fSopenharmony_ci [listener](const sptr<T>& registeredListener) { 773e0dac50fSopenharmony_ci return registeredListener == listener; 774e0dac50fSopenharmony_ci }), holder.end()); 775e0dac50fSopenharmony_ci return WMError::WM_OK; 776e0dac50fSopenharmony_ci} 777e0dac50fSopenharmony_ci 778e0dac50fSopenharmony_cibool PictureInPictureController::IsPullPiPAndHandleNavigation() 779e0dac50fSopenharmony_ci{ 780e0dac50fSopenharmony_ci if (IsTypeNodeEnabled()) { 781e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "App use typeNode"); 782e0dac50fSopenharmony_ci return true; 783e0dac50fSopenharmony_ci } 784e0dac50fSopenharmony_ci if (pipOption_->GetNavigationId() == "") { 785e0dac50fSopenharmony_ci TLOGI(WmsLogTag::WMS_PIP, "App not use navigation"); 786e0dac50fSopenharmony_ci return true; 787e0dac50fSopenharmony_ci } 788e0dac50fSopenharmony_ci if (mainWindow_ == nullptr) { 789e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "Main window init error"); 790e0dac50fSopenharmony_ci return false; 791e0dac50fSopenharmony_ci } 792e0dac50fSopenharmony_ci std::string navId = pipOption_->GetNavigationId(); 793e0dac50fSopenharmony_ci auto navController = NavigationController::GetNavigationController(mainWindow_->GetUIContent(), navId); 794e0dac50fSopenharmony_ci if (navController) { 795e0dac50fSopenharmony_ci if (navController->IsNavDestinationInTopStack()) { 796e0dac50fSopenharmony_ci handleId_ = navController->GetTopHandle(); 797e0dac50fSopenharmony_ci if (handleId_ != -1) { 798e0dac50fSopenharmony_ci TLOGD(WmsLogTag::WMS_PIP, "Top handle id : %{public}d", handleId_); 799e0dac50fSopenharmony_ci navController->SetInPIPMode(handleId_); 800e0dac50fSopenharmony_ci return true; 801e0dac50fSopenharmony_ci } else { 802e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "Get top handle error"); 803e0dac50fSopenharmony_ci return false; 804e0dac50fSopenharmony_ci } 805e0dac50fSopenharmony_ci } else { 806e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "Top is not navDestination"); 807e0dac50fSopenharmony_ci return false; 808e0dac50fSopenharmony_ci } 809e0dac50fSopenharmony_ci } else { 810e0dac50fSopenharmony_ci TLOGE(WmsLogTag::WMS_PIP, "Get navController error"); 811e0dac50fSopenharmony_ci } 812e0dac50fSopenharmony_ci return false; 813e0dac50fSopenharmony_ci} 814e0dac50fSopenharmony_ci 815e0dac50fSopenharmony_cistd::string PictureInPictureController::GetPiPNavigationId() 816e0dac50fSopenharmony_ci{ 817e0dac50fSopenharmony_ci return (pipOption_ != nullptr && !IsTypeNodeEnabled()) ? pipOption_->GetNavigationId() : ""; 818e0dac50fSopenharmony_ci} 819e0dac50fSopenharmony_ci 820e0dac50fSopenharmony_cinapi_ref PictureInPictureController::GetCustomNodeController() 821e0dac50fSopenharmony_ci{ 822e0dac50fSopenharmony_ci return pipOption_ == nullptr ? nullptr : pipOption_->GetNodeControllerRef(); 823e0dac50fSopenharmony_ci} 824e0dac50fSopenharmony_ci 825e0dac50fSopenharmony_cinapi_ref PictureInPictureController::GetTypeNode() const 826e0dac50fSopenharmony_ci{ 827e0dac50fSopenharmony_ci return pipOption_ == nullptr ? nullptr : pipOption_->GetTypeNodeRef(); 828e0dac50fSopenharmony_ci} 829e0dac50fSopenharmony_ci} // namespace Rosen 830e0dac50fSopenharmony_ci} // namespace OHOS