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 <event_handler.h>
19 #include <refbase.h>
20 #include <power_mgr_client.h>
21 #include "picture_in_picture_manager.h"
22 #include "picture_in_picture_option.h"
23 #include "window_manager_hilog.h"
24 #include "window_option.h"
25 #include "window.h"
26 #include "wm_common.h"
27 #include "singleton_container.h"
28
29 namespace OHOS {
30 namespace Rosen {
31 namespace {
32 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "PictureInPictureController"};
33 constexpr int32_t DELAY_ANIM = 500;
34 constexpr int32_t SUCCESS = 1;
35 constexpr int32_t FAILED = 0;
36 const std::string VIDEO_PAGE_PATH = "/system/etc/window/resources/pip_video.abc";
37 const std::string CALL_PAGE_PATH = "/system/etc/window/resources/pip_call.abc";
38 const std::string MEETING_PAGE_PATH = "/system/etc/window/resources/pip_meeting.abc";
39 const std::string LIVE_PAGE_PATH = "/system/etc/window/resources/pip_live.abc";
40 }
41
PictureInPictureController(sptr<PipOption> pipOption,sptr<Window> mainWindow,uint32_t windowId,napi_env env)42 PictureInPictureController::PictureInPictureController(sptr<PipOption> pipOption, sptr<Window> mainWindow,
43 uint32_t windowId, napi_env env)
44 : weakRef_(this), pipOption_(pipOption), mainWindow_(mainWindow), mainWindowId_(windowId), env_(env)
45 {
46 this->handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
47 curState_ = PipWindowState::STATE_UNDEFINED;
48 pipDisplayListener_ = new PictureInPictureController::PipDisplayListener(weakRef_);
49 }
50
~PictureInPictureController()51 PictureInPictureController::~PictureInPictureController()
52 {
53 PictureInPictureManager::DetachAutoStartController(handleId_, weakRef_);
54 }
55
CreatePictureInPictureWindow()56 WMError PictureInPictureController::CreatePictureInPictureWindow()
57 {
58 WLOGI("CreatePictureInPictureWindow is called, mainWindow:%{public}u", mainWindowId_);
59 sptr<PictureInPictureController> thisController = this;
60 if (pipOption_ == nullptr || pipOption_->GetContext() == nullptr) {
61 WLOGFE("Get PictureInPictureOption failed");
62 return WMError::WM_ERROR_PIP_CREATE_FAILED;
63 }
64 auto context = static_cast<std::weak_ptr<AbilityRuntime::Context>*>(pipOption_->GetContext());
65 const std::shared_ptr<AbilityRuntime::Context>& abilityContext = context->lock();
66 SingletonContainer::Get<PiPReporter>().SetCurrentPackageName(abilityContext->GetApplicationInfo()->name);
67 sptr<WindowOption> windowOption = new(std::nothrow) WindowOption();
68 if (windowOption == nullptr) {
69 WLOGFE("Get WindowOption failed");
70 return WMError::WM_ERROR_PIP_CREATE_FAILED;
71 }
72 mainWindowXComponentController_ = pipOption_->GetXComponentController();
73 if (mainWindowXComponentController_ == nullptr || mainWindow_ == nullptr) {
74 WLOGFE("mainWindowXComponentController or main window is nullptr");
75 return WMError::WM_ERROR_PIP_CREATE_FAILED;
76 }
77 UpdateXComponentPositionAndSize();
78 windowOption->SetWindowName(PIP_WINDOW_NAME);
79 windowOption->SetWindowType(WindowType::WINDOW_TYPE_PIP);
80 windowOption->SetWindowMode(WindowMode::WINDOW_MODE_PIP);
81 windowOption->SetWindowRect(windowRect_);
82 WMError errCode;
83 sptr<Window> window = Window::Create(windowOption->GetWindowName(), windowOption, context->lock(), errCode);
84 if (window == nullptr || errCode != WMError::WM_OK) {
85 WLOGFE("Window create failed, reason: %{public}d", errCode);
86 return WMError::WM_ERROR_PIP_CREATE_FAILED;
87 }
88 window_ = window;
89 PictureInPictureManager::PutPipControllerInfo(window_->GetWindowId(), thisController);
90 return WMError::WM_OK;
91 }
92
ShowPictureInPictureWindow(StartPipType startType)93 WMError PictureInPictureController::ShowPictureInPictureWindow(StartPipType startType)
94 {
95 WLOGD("ShowPictureInPictureWindow is called");
96 if (window_ == nullptr) {
97 WLOGFD("window_ is nullptr");
98 SingletonContainer::Get<PiPReporter>().ReportPiPStartWindow(static_cast<int32_t>(startType),
99 pipOption_->GetPipTemplate(), FAILED, "window_ is nullptr");
100 return WMError::WM_ERROR_PIP_STATE_ABNORMALLY;
101 }
102 if (pipLifeCycleListener_ != nullptr) {
103 pipLifeCycleListener_->OnPreparePictureInPictureStart();
104 }
105 if (pipOption_ == nullptr) {
106 WLOGFE("Get PictureInPicture option failed");
107 return WMError::WM_ERROR_PIP_CREATE_FAILED;
108 }
109 auto pipTemplateType = static_cast<PipTemplateType>(pipOption_->GetPipTemplate());
110 WLOGFI("mainWindow: %{public}u, pipWindow: %{public}u, template:%{public}u", mainWindowId_,
111 window_->GetWindowId(), pipTemplateType);
112 switch (pipTemplateType) {
113 default:
114 case PipTemplateType::VIDEO_PLAY:
115 window_->SetUIContentByAbc(VIDEO_PAGE_PATH, env_, nullptr, nullptr);
116 break;
117 case PipTemplateType::VIDEO_CALL:
118 window_->SetUIContentByAbc(CALL_PAGE_PATH, env_, nullptr, nullptr);
119 break;
120 case PipTemplateType::VIDEO_MEETING:
121 window_->SetUIContentByAbc(MEETING_PAGE_PATH, env_, nullptr, nullptr);
122 break;
123 case PipTemplateType::VIDEO_LIVE:
124 window_->SetUIContentByAbc(LIVE_PAGE_PATH, env_, nullptr, nullptr);
125 break;
126 }
127 WMError errCode = window_->Show(0, false);
128 if (errCode != WMError::WM_OK) {
129 WLOGFD("window_ show failed, err: %{public}u", errCode);
130 int32_t err = static_cast<int32_t>(errCode);
131 if (pipLifeCycleListener_ != nullptr) {
132 pipLifeCycleListener_->OnPictureInPictureOperationError(err);
133 }
134 SingletonContainer::Get<PiPReporter>().ReportPiPStartWindow(static_cast<int32_t>(startType),
135 pipOption_->GetPipTemplate(), FAILED, "window_ show failed");
136 return WMError::WM_ERROR_PIP_INTERNAL_ERROR;
137 }
138 PictureInPictureManager::SetActiveController(this);
139 SingletonContainer::Get<PiPReporter>().ReportPiPStartWindow(static_cast<int32_t>(startType),
140 pipOption_->GetPipTemplate(), SUCCESS, "show pip success");
141 return WMError::WM_OK;
142 }
143
StartPictureInPicture(StartPipType startType)144 WMError PictureInPictureController::StartPictureInPicture(StartPipType startType)
145 {
146 WLOGI("StartPictureInPicture called");
147 std::lock_guard<std::mutex> lock(mutex_);
148 if (curState_ == PipWindowState::STATE_STARTING || curState_ == PipWindowState::STATE_STARTED) {
149 WLOGFW("pip window is starting, state: %{public}u, pipWindow: %{public}u, mainWindow: %{public}u",
150 curState_, window_->GetWindowId(), mainWindowId_);
151 SingletonContainer::Get<PiPReporter>().ReportPiPStartWindow(static_cast<int32_t>(startType),
152 pipOption_->GetPipTemplate(), FAILED, "Pip window is starting");
153 return WMError::WM_ERROR_PIP_REPEAT_OPERATION;
154 }
155 if (pipOption_ == nullptr || pipOption_->GetContext() == nullptr) {
156 WLOGFE("Get PictureInPictureOption failed");
157 return WMError::WM_ERROR_PIP_CREATE_FAILED;
158 }
159 if (mainWindow_ == nullptr) {
160 WLOGFE("Init main window failed");
161 return WMError::WM_ERROR_PIP_CREATE_FAILED;
162 }
163 if (!IsPullPiPAndHandleNavigation()) {
164 WLOGFE("Navigation operate failed");
165 return WMError::WM_ERROR_PIP_CREATE_FAILED;
166 }
167 Rosen::DisplayManager::GetInstance().RegisterDisplayListener(pipDisplayListener_);
168 curState_ = PipWindowState::STATE_STARTING;
169 if (PictureInPictureManager::HasActiveController() && !PictureInPictureManager::IsActiveController(weakRef_)) {
170 // if current controller is not the active one, but belongs to the same mainWindow, reserve pipWindow
171 if (PictureInPictureManager::IsAttachedToSameWindow(mainWindowId_)) {
172 window_ = PictureInPictureManager::GetCurrentWindow();
173 WLOGFD("Reuse pipWindow: %{public}u as attached to the same mainWindow: %{public}u",
174 window_->GetWindowId(), mainWindowId_);
175 PictureInPictureManager::DoClose(false, false);
176 mainWindowXComponentController_ = pipOption_->GetXComponentController();
177 UpdateXComponentPositionAndSize();
178 UpdateContentSize(windowRect_.width_, windowRect_.height_);
179 PictureInPictureManager::PutPipControllerInfo(window_->GetWindowId(), this);
180 WMError err = ShowPictureInPictureWindow(startType);
181 if (err != WMError::WM_OK) {
182 curState_ = PipWindowState::STATE_UNDEFINED;
183 } else {
184 curState_ = PipWindowState::STATE_STARTED;
185 }
186 return err;
187 }
188 // otherwise, stop the previous one
189 PictureInPictureManager::DoClose(true, false);
190 }
191 return StartPictureInPictureInner(startType);
192 }
193
StartPictureInPictureInner(StartPipType startType)194 WMError PictureInPictureController::StartPictureInPictureInner(StartPipType startType)
195 {
196 WMError errCode = CreatePictureInPictureWindow();
197 if (errCode != WMError::WM_OK) {
198 curState_ = PipWindowState::STATE_UNDEFINED;
199 WLOGFE("Create pip window failed, err: %{public}u", errCode);
200 SingletonContainer::Get<PiPReporter>().ReportPiPStartWindow(static_cast<int32_t>(startType),
201 pipOption_->GetPipTemplate(), FAILED, "Create pip window failed");
202 return errCode;
203 }
204 errCode = ShowPictureInPictureWindow(startType);
205 if (errCode != WMError::WM_OK) {
206 curState_ = PipWindowState::STATE_UNDEFINED;
207 WLOGFE("Show pip window failed, err: %{public}u", errCode);
208 SingletonContainer::Get<PiPReporter>().ReportPiPStartWindow(static_cast<int32_t>(startType),
209 pipOption_->GetPipTemplate(), FAILED, "Show pip window failed");
210 return errCode;
211 }
212 curState_ = PipWindowState::STATE_STARTED;
213 SingletonContainer::Get<PiPReporter>().ReportPiPStartWindow(static_cast<int32_t>(startType),
214 pipOption_->GetPipTemplate(), SUCCESS, "start pip success");
215 return WMError::WM_OK;
216 }
217
StopPictureInPicture(bool destroyWindow,bool needAnim,StopPipType stopPipType)218 WMError PictureInPictureController::StopPictureInPicture(bool destroyWindow, bool needAnim, StopPipType stopPipType)
219 {
220 WLOGI("StopPictureInPicture is called, destroyWindow: %{public}u, needAnim: %{public}u", destroyWindow, needAnim);
221 std::lock_guard<std::mutex> lock(mutex_);
222 if (curState_ == PipWindowState::STATE_STOPPING || curState_ == PipWindowState::STATE_STOPPED) {
223 WLOGFE("Repeat stop request, curState: %{public}u", curState_);
224 SingletonContainer::Get<PiPReporter>().ReportPiPStopWindow(static_cast<int32_t>(stopPipType),
225 pipOption_->GetPipTemplate(), FAILED, "Repeat stop request");
226 return WMError::WM_ERROR_PIP_REPEAT_OPERATION;
227 }
228 if (window_ == nullptr) {
229 WLOGFE("window_ is nullptr");
230 SingletonContainer::Get<PiPReporter>().ReportPiPStopWindow(static_cast<int32_t>(stopPipType),
231 pipOption_->GetPipTemplate(), FAILED, "window_ is nullptr");
232 return WMError::WM_ERROR_PIP_STATE_ABNORMALLY;
233 }
234 curState_ = PipWindowState::STATE_STOPPING;
235 if (pipLifeCycleListener_ != nullptr) {
236 pipLifeCycleListener_->OnPreparePictureInPictureStop();
237 }
238 (void)Rosen::DisplayManager::GetInstance().UnregisterDisplayListener(pipDisplayListener_);
239 if (!destroyWindow) {
240 ResetExtController();
241 curState_ = PipWindowState::STATE_STOPPED;
242 if (pipLifeCycleListener_) {
243 pipLifeCycleListener_->OnPictureInPictureStop();
244 }
245 PictureInPictureManager::RemoveActiveController(weakRef_);
246 PictureInPictureManager::RemovePipControllerInfo(window_->GetWindowId());
247 return WMError::WM_OK;
248 }
249 return StopPictureInPictureInner(needAnim, stopPipType);
250 }
251
StopPictureInPictureInner(bool needAnim,StopPipType stopType)252 WMError PictureInPictureController::StopPictureInPictureInner(bool needAnim, StopPipType stopType)
253 {
254 window_->NotifyPrepareClosePiPWindow();
255 auto task = [weakThis = wptr(this), currentStopType = stopType, currentPipOption = pipOption_]() {
256 auto session = weakThis.promote();
257 if (!session || !session->window_) {
258 WLOGFE("session is null");
259 SingletonContainer::Get<PiPReporter>().ReportPiPStopWindow(static_cast<int32_t>(currentStopType),
260 currentPipOption->GetPipTemplate(), FAILED, "session is null");
261 return WMError::WM_ERROR_PIP_INTERNAL_ERROR;
262 }
263 session->ResetExtController();
264 WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(session->window_->Destroy());
265 if (ret != WmErrorCode::WM_OK) {
266 session->curState_ = PipWindowState::STATE_UNDEFINED;
267 WLOGFE("Window destroy failed");
268 int32_t err = static_cast<int32_t>(ret);
269 if (session->pipLifeCycleListener_ != nullptr) {
270 session->pipLifeCycleListener_->OnPictureInPictureOperationError(err);
271 }
272 SingletonContainer::Get<PiPReporter>().ReportPiPStopWindow(static_cast<int32_t>(currentStopType),
273 currentPipOption->GetPipTemplate(), FAILED, "Window destroy failed");
274 return WMError::WM_ERROR_PIP_DESTROY_FAILED;
275 }
276 if (session->pipLifeCycleListener_ != nullptr) {
277 session->pipLifeCycleListener_->OnPictureInPictureStop();
278 }
279 PictureInPictureManager::RemoveActiveController(session);
280 PictureInPictureManager::RemovePipControllerInfo(session->window_->GetWindowId());
281 session->window_ = nullptr;
282 session->curState_ = PipWindowState::STATE_STOPPED;
283 std::string navId = session->pipOption_->GetNavigationId();
284 if (navId != "" && session->mainWindow_) {
285 auto navController = NavigationController::GetNavigationController(
286 session->mainWindow_->GetUIContent(), navId);
287 if (navController) {
288 navController->DeletePIPMode(session->handleId_);
289 WLOGFI("Delete pip mode id: %{public}d", session->handleId_);
290 }
291 }
292 SingletonContainer::Get<PiPReporter>().ReportPiPStopWindow(static_cast<int32_t>(currentStopType),
293 currentPipOption->GetPipTemplate(), SUCCESS, "pip window stop success");
294 return WMError::WM_OK;
295 };
296 if (handler_ && needAnim) {
297 handler_->PostTask(task, "wms:StopPictureInPicture", DEFAULT_TIME_DELAY);
298 } else {
299 return task();
300 }
301 return WMError::WM_OK;
302 }
303
GetPipWindow()304 sptr<Window> PictureInPictureController::GetPipWindow()
305 {
306 return window_;
307 }
308
GetMainWindowId()309 uint32_t PictureInPictureController::GetMainWindowId()
310 {
311 return mainWindowId_;
312 }
313
SetPipWindow(sptr<Window> window)314 void PictureInPictureController::SetPipWindow(sptr<Window> window)
315 {
316 window_ = window;
317 }
318
SetAutoStartEnabled(bool enable)319 void PictureInPictureController::SetAutoStartEnabled(bool enable)
320 {
321 WLOGI("SetAutoStartEnabled called, enable: %{public}u, mainWindow: %{public}u", enable, mainWindowId_);
322 isAutoStartEnabled_ = enable;
323 if (isAutoStartEnabled_) {
324 if (mainWindow_ == nullptr) {
325 WLOGFE("Init main window failed");
326 return;
327 }
328 if (!IsPullPiPAndHandleNavigation()) {
329 WLOGFE("Navigation operate failed");
330 return;
331 }
332 PictureInPictureManager::AttachAutoStartController(handleId_, weakRef_);
333 } else {
334 PictureInPictureManager::DetachAutoStartController(handleId_, weakRef_);
335 }
336 }
337
IsAutoStartEnabled(bool & enable) const338 void PictureInPictureController::IsAutoStartEnabled(bool& enable) const
339 {
340 enable = isAutoStartEnabled_;
341 }
342
GetControllerState()343 PipWindowState PictureInPictureController::GetControllerState()
344 {
345 return curState_;
346 }
347
UpdateContentSize(int32_t width,int32_t height)348 void PictureInPictureController::UpdateContentSize(int32_t width, int32_t height)
349 {
350 if (width <= 0 || height <= 0) {
351 WLOGFE("invalid size");
352 return;
353 }
354 if (curState_ != PipWindowState::STATE_STARTED) {
355 WLOGFD("UpdateContentSize is disabled when state: %{public}u", curState_);
356 return;
357 }
358 if (window_ == nullptr) {
359 WLOGFE("pipWindow not exist");
360 return;
361 }
362 WLOGI("UpdateContentSize window: %{public}u width:%{public}u height:%{public}u",
363 window_->GetWindowId(), width, height);
364 window_->UpdatePiPRect(width, height, PiPRectUpdateReason::REASON_PIP_VIDEO_RATIO_CHANGE);
365 }
366
StartMove()367 void PictureInPictureController::StartMove()
368 {
369 if (window_ == nullptr) {
370 WLOGFE("pipWindow not exist");
371 return;
372 }
373 WLOGI("StartMove is called, window: %{public}u", window_->GetWindowId());
374 SingletonContainer::Get<PiPReporter>().ReportPiPMove();
375 window_->StartMove();
376 }
377
DoScale()378 void PictureInPictureController::DoScale()
379 {
380 if (window_ == nullptr) {
381 WLOGFE("PiPWindow is not exist");
382 return;
383 }
384 WLOGI("DoScale is called, window: %{public}u", window_->GetWindowId());
385 window_->UpdatePiPRect(0, 0, PiPRectUpdateReason::REASON_PIP_SCALE_CHANGE);
386 }
387
AfterBackground()388 void PictureInPictureController::PipMainWindowLifeCycleImpl::AfterBackground()
389 {
390 WLOGI("PipMainWindowLifeCycleImpl AfterBackground is called");
391 if (!PowerMgr::PowerMgrClient::GetInstance().IsScreenOn()) {
392 WLOGFI("disable auto start as screen is off");
393 return;
394 }
395 PictureInPictureManager::AutoStartPipWindow(navigationId_);
396 }
397
BackgroundFailed(int32_t type)398 void PictureInPictureController::PipMainWindowLifeCycleImpl::BackgroundFailed(int32_t type)
399 {
400 WLOGI("PipMainWindowLifeCycleImpl BackgroundFailed");
401 }
402
OnCreate(DisplayId displayId)403 void PictureInPictureController::PipDisplayListener::OnCreate(DisplayId displayId)
404 {
405 WLOGD("PipDisplayListener OnCreate");
406 }
407
OnDestroy(DisplayId displayId)408 void PictureInPictureController::PipDisplayListener::OnDestroy(DisplayId displayId)
409 {
410 WLOGD("PipDisplayListener OnDestroy");
411 }
412
OnChange(DisplayId displayId)413 void PictureInPictureController::PipDisplayListener::OnChange(DisplayId displayId)
414 {
415 if (displayId != DisplayManager::GetInstance().GetDefaultDisplay()->GetId()) {
416 return;
417 }
418 Rotation rotation = DisplayManager::GetInstance().GetDisplayById(displayId)->GetRotation();
419 if (((preRotation_ == Rotation::ROTATION_0 || preRotation_ == Rotation::ROTATION_180) &&
420 (rotation == Rotation::ROTATION_90 || rotation == Rotation::ROTATION_270)) ||
421 ((preRotation_ == Rotation::ROTATION_90 || preRotation_ == Rotation::ROTATION_270) &&
422 (rotation == Rotation::ROTATION_0 || rotation == Rotation::ROTATION_180))) {
423 WLOGFI("display rotation changed from %{public}d to %{public}d", static_cast<int32_t>(preRotation_),
424 static_cast<int32_t>(rotation));
425 preRotation_ = rotation;
426 if (pipController_ != nullptr && pipController_->GetPipWindow() != nullptr) {
427 pipController_->GetPipWindow()->UpdatePiPRect(pipController_->windowRect_.width_,
428 pipController_->windowRect_.height_, PiPRectUpdateReason::REASON_DISPLAY_ROTATION_CHANGE);
429 }
430 }
431 }
432
DoActionEvent(std::string & actionName)433 void PictureInPictureController::DoActionEvent(std::string& actionName)
434 {
435 WLOGFD("actionName: %{public}s", actionName.c_str());
436 if (pipActionObserver_ == nullptr) {
437 WLOGFE("pipActionObserver is not registered");
438 return;
439 }
440 SingletonContainer::Get<PiPReporter>().ReportPiPActionEvent(pipOption_->GetPipTemplate(), actionName);
441 pipActionObserver_->OnActionEvent(actionName);
442 }
443
RestorePictureInPictureWindow()444 void PictureInPictureController::RestorePictureInPictureWindow()
445 {
446 if (window_ == nullptr || mainWindow_ == nullptr) {
447 WLOGFE("window or main window is nullptr");
448 return;
449 }
450 WLOGFI("restore pipWindow %{public}u to [%{public}u, %{public}u, %{public}u, %{public}u]", window_->GetWindowId(),
451 windowRect_.posX_, windowRect_.posY_, windowRect_.width_, windowRect_.height_);
452 if (pipLifeCycleListener_) {
453 pipLifeCycleListener_->OnRestoreUserInterface();
454 }
455 window_->RecoveryPullPiPMainWindow(windowRect_);
456 std::string navId = pipOption_->GetNavigationId();
457 if (navId != "") {
458 auto navController = NavigationController::GetNavigationController(mainWindow_->GetUIContent(), navId);
459 if (navController) {
460 navController->PushInPIP(handleId_);
461 WLOGFI("Push in pip handleId: %{public}d", handleId_);
462 } else {
463 WLOGFE("navController is nullptr");
464 }
465 }
466 auto stopPipTask = [weakThis = wptr(this)]() {
467 auto session = weakThis.promote();
468 if (!session) {
469 WLOGFE("session is null");
470 return;
471 }
472 session->StopPictureInPicture(true, false, StopPipType::NULL_STOP);
473 };
474 if (handler_ == nullptr) {
475 WLOGFE("handler is nullptr");
476 return;
477 }
478 handler_->PostTask(stopPipTask, "wms:RestorePictureInPictureWindow", DELAY_ANIM);
479 SingletonContainer::Get<PiPReporter>().ReportPiPRestore();
480 WLOGFI("restore pip main window finished");
481 }
482
UpdateXComponentPositionAndSize()483 void PictureInPictureController::UpdateXComponentPositionAndSize()
484 {
485 float posX = 0;
486 float posY = 0;
487 float width = 0;
488 float height = 0;
489 mainWindowXComponentController_->GetGlobalPosition(posX, posY);
490 mainWindowXComponentController_->GetSize(width, height);
491 windowRect_.width_ = static_cast<uint32_t>(width);
492 windowRect_.height_ = static_cast<uint32_t>(height);
493 windowRect_.posX_ = static_cast<uint32_t>(posX);
494 windowRect_.posY_ = static_cast<uint32_t>(posY);
495
496 bool isFullScreen = mainWindow_->IsLayoutFullScreen();
497 if (!isFullScreen) {
498 // calculate status bar height as offset
499 WLOGFI("not full screen");
500 AvoidAreaType avoidAreaType = AvoidAreaType::TYPE_SYSTEM;
501 AvoidArea avoidArea;
502 mainWindow_->GetAvoidAreaByType(avoidAreaType, avoidArea);
503
504 uint32_t offset = avoidArea.topRect_.height_;
505 windowRect_.posY_ += offset;
506 WLOGFD("status bar height = %{public}d", offset);
507 }
508 WLOGFD("position width: %{public}u, height: %{public}u, posX: %{public}d, posY: %{public}d",
509 windowRect_.width_, windowRect_.height_, windowRect_.posX_, windowRect_.posY_);
510 }
511
ResetExtController()512 void PictureInPictureController::ResetExtController()
513 {
514 WLOGI("ResetExtController is called");
515 if (mainWindowXComponentController_ == nullptr || pipXComponentController_ == nullptr) {
516 WLOGFE("error when reset XComponentController");
517 return;
518 }
519 XComponentControllerErrorCode errorCode =
520 mainWindowXComponentController_->ResetExtController(pipXComponentController_);
521 if (errorCode != XComponentControllerErrorCode::XCOMPONENT_CONTROLLER_NO_ERROR) {
522 WLOGFE("swap xComponent failed, errorCode: %{public}u", errorCode);
523 }
524 }
525
SetXComponentController(std::shared_ptr<XComponentController> xComponentController)526 WMError PictureInPictureController::SetXComponentController(std::shared_ptr<XComponentController> xComponentController)
527 {
528 WLOGI("SetXComponentController is called");
529 pipXComponentController_ = xComponentController;
530 if (window_ == nullptr) {
531 WLOGFE("window_ is nullptr");
532 return WMError::WM_ERROR_PIP_STATE_ABNORMALLY;
533 }
534 if (mainWindowXComponentController_ == nullptr || pipXComponentController_ == nullptr) {
535 WLOGFE("window_ is nullptr");
536 return WMError::WM_ERROR_PIP_STATE_ABNORMALLY;
537 }
538 XComponentControllerErrorCode errorCode =
539 mainWindowXComponentController_->SetExtController(pipXComponentController_);
540 if (errorCode != XComponentControllerErrorCode::XCOMPONENT_CONTROLLER_NO_ERROR) {
541 WLOGFE("swap xComponent failed, errorCode: %{public}u", errorCode);
542 return WMError::WM_ERROR_PIP_INTERNAL_ERROR;
543 }
544 if (pipLifeCycleListener_ != nullptr) {
545 pipLifeCycleListener_->OnPictureInPictureStart();
546 }
547 return WMError::WM_OK;
548 }
549
SetPictureInPictureLifecycle(sptr<IPiPLifeCycle> listener)550 void PictureInPictureController::SetPictureInPictureLifecycle(sptr<IPiPLifeCycle> listener)
551 {
552 WLOGFD("SetPictureInPictureLifecycle is called");
553 pipLifeCycleListener_ = listener;
554 }
555
SetPictureInPictureActionObserver(sptr<IPiPActionObserver> listener)556 void PictureInPictureController::SetPictureInPictureActionObserver(sptr<IPiPActionObserver> listener)
557 {
558 WLOGFD("SetPictureInPictureActionObserver is called");
559 pipActionObserver_ = listener;
560 }
561
GetPictureInPictureLifecycle() const562 sptr<IPiPLifeCycle> PictureInPictureController::GetPictureInPictureLifecycle() const
563 {
564 return pipLifeCycleListener_;
565 }
566
GetPictureInPictureActionObserver() const567 sptr<IPiPActionObserver> PictureInPictureController::GetPictureInPictureActionObserver() const
568 {
569 return pipActionObserver_;
570 }
571
IsPullPiPAndHandleNavigation()572 bool PictureInPictureController::IsPullPiPAndHandleNavigation()
573 {
574 if (pipOption_->GetNavigationId() == "") {
575 WLOGFI("App not use navigation");
576 return true;
577 }
578 if (mainWindow_ == nullptr) {
579 WLOGFE("Main window init error");
580 return false;
581 }
582 std::string navId = pipOption_->GetNavigationId();
583 auto navController = NavigationController::GetNavigationController(mainWindow_->GetUIContent(), navId);
584 if (navController) {
585 if (navController->IsNavDestinationInTopStack()) {
586 handleId_ = navController->GetTopHandle();
587 if (handleId_ != -1) {
588 WLOGFD("Top handle id : %{public}d", handleId_);
589 navController->SetInPIPMode(handleId_);
590 return true;
591 } else {
592 WLOGFE("Get top handle error");
593 return false;
594 }
595 } else {
596 WLOGFE("Top is not navDestination");
597 return false;
598 }
599 } else {
600 WLOGFE("Get navController error");
601 }
602 return false;
603 }
604
GetPiPNavigationId()605 std::string PictureInPictureController::GetPiPNavigationId()
606 {
607 return pipOption_? pipOption_->GetNavigationId() : "";
608 }
609 } // namespace Rosen
610 } // namespace OHOS