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