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