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