• 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 <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