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_manager.h"
17 
18 #include <refbase.h>
19 #include "picture_in_picture_controller.h"
20 #include "window.h"
21 #include "window_manager_hilog.h"
22 #include "window_scene_session_impl.h"
23 #include "wm_common.h"
24 #include "scene_board_judgement.h"
25 
26 namespace OHOS {
27 namespace Rosen {
28 namespace {
29 const std::string ACTION_CLOSE = "close";
30 const std::string ACTION_PRE_RESTORE = "pre_restore";
31 const std::string ACTION_RESTORE = "restore";
32 const std::string ACTION_DESTROY = "destroy";
33 const std::string ACTION_PREPARE_SOURCE = "prepare_source";
34 const std::string ACTION_LOCATE_SOURCE = "locate_source";
35 const std::string ACTION_BACKGROUND_AUTO_START = "background_auto_start";
36 
37 const std::map<std::string, std::function<void()>> PIP_ACTION_MAP {
38     {ACTION_CLOSE, PictureInPictureManager::DoActionClose},
39     {ACTION_PRE_RESTORE, PictureInPictureManager::DoPreRestore},
40     {ACTION_RESTORE, PictureInPictureManager::DoRestore},
41     {ACTION_PREPARE_SOURCE, PictureInPictureManager::DoPrepareSource},
42     {ACTION_LOCATE_SOURCE, PictureInPictureManager::DoLocateSource},
43     {ACTION_DESTROY, PictureInPictureManager::DoDestroy},
44     {ACTION_BACKGROUND_AUTO_START, PictureInPictureManager::AutoStartPipWindow},
45 };
46 }
47 
48 sptr<PictureInPictureController> PictureInPictureManager::activeController_ = nullptr;
49 wptr<PictureInPictureController> PictureInPictureManager::autoStartController_ = nullptr;
50 std::map<int32_t, wptr<PictureInPictureController>> PictureInPictureManager::autoStartControllerMap_ = {};
51 std::map<int32_t, sptr<PictureInPictureController>> PictureInPictureManager::windowToControllerMap_ = {};
52 std::shared_ptr<NativeReference> PictureInPictureManager::innerCallbackRef_ = nullptr;
53 
PictureInPictureManager()54 PictureInPictureManager::PictureInPictureManager()
55 {
56 }
57 
~PictureInPictureManager()58 PictureInPictureManager::~PictureInPictureManager()
59 {
60 }
61 
IsSupportPiP()62 bool PictureInPictureManager::IsSupportPiP()
63 {
64     return SceneBoardJudgement::IsSceneBoardEnabled();
65 }
66 
ShouldAbortPipStart()67 bool PictureInPictureManager::ShouldAbortPipStart()
68 {
69     return activeController_ != nullptr && activeController_->GetControllerState() == PiPWindowState::STATE_STARTING;
70 }
71 
PutPipControllerInfo(int32_t windowId, sptr<PictureInPictureController> pipController)72 void PictureInPictureManager::PutPipControllerInfo(int32_t windowId, sptr<PictureInPictureController> pipController)
73 {
74     TLOGI(WmsLogTag::WMS_PIP, "windowId %{public}u", windowId);
75     windowToControllerMap_.insert(std::make_pair(windowId, pipController));
76 }
77 
RemovePipControllerInfo(int32_t windowId)78 void PictureInPictureManager::RemovePipControllerInfo(int32_t windowId)
79 {
80     TLOGI(WmsLogTag::WMS_PIP, "windowId %{public}u", windowId);
81     windowToControllerMap_.erase(windowId);
82 }
83 
GetPipControllerInfo(int32_t windowId)84 sptr<PictureInPictureController> PictureInPictureManager::GetPipControllerInfo(int32_t windowId)
85 {
86     if (windowToControllerMap_.empty() || windowToControllerMap_.find(windowId) == windowToControllerMap_.end()) {
87         TLOGE(WmsLogTag::WMS_PIP, "error, windowId: %{public}d not registered!", windowId);
88         return nullptr;
89     }
90     TLOGI(WmsLogTag::WMS_PIP, "windowId: %{public}d", windowId);
91     return windowToControllerMap_[windowId];
92 }
93 
HasActiveController()94 bool PictureInPictureManager::HasActiveController()
95 {
96     return activeController_ != nullptr;
97 }
98 
IsActiveController(wptr<PictureInPictureController> pipController)99 bool PictureInPictureManager::IsActiveController(wptr<PictureInPictureController> pipController)
100 {
101     if (!HasActiveController()) {
102         return false;
103     }
104     bool res = pipController.GetRefPtr() == activeController_.GetRefPtr();
105     TLOGD(WmsLogTag::WMS_PIP, "res: %{public}u", res);
106     return res;
107 }
108 
SetActiveController(sptr<PictureInPictureController> pipController)109 void PictureInPictureManager::SetActiveController(sptr<PictureInPictureController> pipController)
110 {
111     TLOGD(WmsLogTag::WMS_PIP, "in");
112     activeController_ = pipController;
113 }
114 
RemoveActiveController(wptr<PictureInPictureController> pipController)115 void PictureInPictureManager::RemoveActiveController(wptr<PictureInPictureController> pipController)
116 {
117     TLOGD(WmsLogTag::WMS_PIP, "in");
118     if (HasActiveController() && pipController.GetRefPtr() == activeController_.GetRefPtr()) {
119         activeController_ = nullptr;
120     }
121 }
122 
AttachAutoStartController(int32_t handleId, wptr<PictureInPictureController> pipController)123 void PictureInPictureManager::AttachAutoStartController(int32_t handleId,
124     wptr<PictureInPictureController> pipController)
125 {
126     TLOGD(WmsLogTag::WMS_PIP, "handleId: %{public}u", handleId);
127     if (pipController == nullptr) {
128         return;
129     }
130     autoStartController_ = pipController;
131     autoStartControllerMap_[handleId] = pipController;
132 }
133 
DetachAutoStartController(int32_t handleId, wptr<PictureInPictureController> pipController)134 void PictureInPictureManager::DetachAutoStartController(int32_t handleId,
135     wptr<PictureInPictureController> pipController)
136 {
137     TLOGD(WmsLogTag::WMS_PIP, "handleId: %{public}u", handleId);
138     autoStartControllerMap_.erase(handleId);
139     if (autoStartController_ == nullptr) {
140         return;
141     }
142     if (pipController != nullptr &&
143         pipController.GetRefPtr() != autoStartController_.GetRefPtr()) {
144         TLOGE(WmsLogTag::WMS_PIP, "not same pip controller or no active pip controller");
145         return;
146     }
147     autoStartController_ = nullptr;
148 }
149 
IsAttachedToSameWindow(uint32_t windowId)150 bool PictureInPictureManager::IsAttachedToSameWindow(uint32_t windowId)
151 {
152     TLOGI(WmsLogTag::WMS_PIP, "windowId: %{public}u", windowId);
153     if (!HasActiveController()) {
154         return false;
155     }
156     return activeController_->GetMainWindowId() == windowId;
157 }
158 
GetCurrentWindow()159 sptr<Window> PictureInPictureManager::GetCurrentWindow()
160 {
161     if (!HasActiveController()) {
162         return nullptr;
163     }
164     return activeController_->GetPipWindow();
165 }
166 
DoPreRestore()167 void PictureInPictureManager::DoPreRestore()
168 {
169     TLOGI(WmsLogTag::WMS_PIP, "in");
170     if (!HasActiveController()) {
171         return;
172     }
173     activeController_->PreRestorePictureInPicture();
174 }
175 
DoRestore()176 void PictureInPictureManager::DoRestore()
177 {
178     TLOGI(WmsLogTag::WMS_PIP, "in");
179     if (!HasActiveController()) {
180         return;
181     }
182     activeController_->RestorePictureInPictureWindow();
183 }
184 
DoPrepareSource()185 void PictureInPictureManager::DoPrepareSource()
186 {
187     TLOGI(WmsLogTag::WMS_PIP, "in");
188     if (!HasActiveController()) {
189         return;
190     }
191     activeController_->PrepareSource();
192 }
193 
DoLocateSource()194 void PictureInPictureManager::DoLocateSource()
195 {
196     TLOGI(WmsLogTag::WMS_PIP, "in");
197     if (!HasActiveController()) {
198         return;
199     }
200     activeController_->LocateSource();
201 }
202 
DoClose(bool destroyWindow, bool byPriority)203 void PictureInPictureManager::DoClose(bool destroyWindow, bool byPriority)
204 {
205     TLOGI(WmsLogTag::WMS_PIP, "in");
206     if (!HasActiveController()) {
207         return;
208     }
209     StopPipType currentStopType = StopPipType::NULL_STOP;
210     if (!byPriority) {
211         currentStopType = StopPipType::USER_STOP;
212     } else {
213         currentStopType = StopPipType::OTHER_PACKAGE_STOP;
214     }
215     activeController_->StopPictureInPicture(destroyWindow, currentStopType, !byPriority);
216 }
217 
DoActionClose()218 void PictureInPictureManager::DoActionClose()
219 {
220     TLOGI(WmsLogTag::WMS_PIP, "in");
221     DoClose(true, false);
222 }
223 
DoDestroy()224 void PictureInPictureManager::DoDestroy()
225 {
226     TLOGI(WmsLogTag::WMS_PIP, "in");
227     if (!HasActiveController()) {
228         return;
229     }
230     activeController_->DestroyPictureInPictureWindow();
231 }
232 
DoActionEvent(const std::string& actionName, int32_t status)233 void PictureInPictureManager::DoActionEvent(const std::string& actionName, int32_t status)
234 {
235     TLOGI(WmsLogTag::WMS_PIP, "in");
236     auto func = PIP_ACTION_MAP.find(actionName);
237     if (func == PIP_ACTION_MAP.end()) {
238         TLOGI(WmsLogTag::WMS_PIP, "through pass");
239         if (HasActiveController()) {
240             activeController_->DoActionEvent(actionName, status);
241         }
242         return;
243     }
244     func->second();
245 }
246 
DoControlEvent(PiPControlType controlType, PiPControlStatus status)247 void PictureInPictureManager::DoControlEvent(PiPControlType controlType, PiPControlStatus status)
248 {
249     TLOGI(WmsLogTag::WMS_PIP, "controlType:%{public}u, enabled:%{public}d", controlType, status);
250     if (!HasActiveController()) {
251         return;
252     }
253     activeController_->DoControlEvent(controlType, status);
254 }
255 
AutoStartPipWindow()256 void PictureInPictureManager::AutoStartPipWindow()
257 {
258     TLOGI(WmsLogTag::WMS_PIP, "in");
259     if (autoStartController_ == nullptr) {
260         TLOGE(WmsLogTag::WMS_PIP, "autoStartController is null");
261         return;
262     }
263     if (autoStartController_->GetPiPNavigationId().empty() || autoStartController_->IsTypeNodeEnabled()) {
264         TLOGI(WmsLogTag::WMS_PIP, "No use navigation for auto start");
265         autoStartController_->StartPictureInPicture(StartPipType::AUTO_START);
266         return;
267     }
268     sptr<WindowSessionImpl> mainWindow = WindowSceneSessionImpl::GetMainWindowWithId(
269         autoStartController_->GetMainWindowId());
270     if (mainWindow) {
271         auto navController = NavigationController::GetNavigationController(mainWindow->GetUIContent(),
272             autoStartController_->GetPiPNavigationId());
273         if (!navController) {
274             TLOGE(WmsLogTag::WMS_PIP, "navController is nullptr");
275             return;
276         }
277         if (navController->IsNavDestinationInTopStack()) {
278             int handleId = navController->GetTopHandle();
279             if (autoStartControllerMap_.empty() ||
280                 autoStartControllerMap_.find(handleId) == autoStartControllerMap_.end()) {
281                 TLOGE(WmsLogTag::WMS_PIP, "GetNavController info error, %{public}d not registered", handleId);
282                 return;
283             }
284             auto pipController = autoStartControllerMap_[handleId];
285             pipController->StartPictureInPicture(StartPipType::AUTO_START);
286         } else {
287             TLOGE(WmsLogTag::WMS_PIP, "Top is not navDestination");
288         }
289     }
290 }
291 }
292 }
293