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