• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025-2025 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 "floating_ball_controller.h"
17 
18 #include <refbase.h>
19 #include <transaction/rs_sync_transaction_controller.h>
20 #include "parameters.h"
21 #include "singleton_container.h"
22 #include "window_adapter.h"
23 #include "window_manager_hilog.h"
24 #include "window_option.h"
25 #include "floating_ball_manager.h"
26 
27 namespace OHOS {
28 namespace Rosen {
29 
30 namespace {
31 const std::string FB_WINDOW_NAME = "fb_window";
32 }
33 
FloatingBallController(const sptr<Window> & mainWindow,const uint32_t & windowId,void * contextPtr)34 FloatingBallController::FloatingBallController(const sptr<Window>& mainWindow,
35     const uint32_t& windowId, void* contextPtr)
36     : weakRef_(this), mainWindow_(mainWindow), mainWindowId_(windowId), contextPtr_(contextPtr)
37 {
38     curState_ = FbWindowState::STATE_UNDEFINED;
39     auto context = static_cast<std::weak_ptr<AbilityRuntime::Context>*>(contextPtr_);
40     if (context == nullptr) {
41         return;
42     }
43     const std::shared_ptr<AbilityRuntime::Context>& abilityContext = context->lock();
44     if ((abilityContext == nullptr) || (abilityContext->GetApplicationInfo() == nullptr)) {
45         return;
46     }
47     SingletonContainer::Get<FloatingballReporter>().SetCurrentPackageName(abilityContext->GetApplicationInfo()->name);
48 }
49 
~FloatingBallController()50 FloatingBallController::~FloatingBallController()
51 {
52     TLOGI(WmsLogTag::WMS_SYSTEM, "FloatingBallController release");
53 }
54 
55 // LCOV_EXCL_START
GetControllerState() const56 FbWindowState FloatingBallController::GetControllerState() const
57 {
58     return curState_;
59 }
60 
UpdateMainWindow(const sptr<Window> & mainWindow)61 void FloatingBallController::UpdateMainWindow(const sptr<Window>& mainWindow)
62 {
63     if (mainWindow == nullptr) {
64         return;
65     }
66     mainWindow_ = mainWindow;
67     mainWindowId_ = mainWindow->GetWindowId();
68 }
69 // LCOV_EXCL_STOP
70 
UpdateFloatingBall(sptr<FbOption> & option)71 WMError FloatingBallController::UpdateFloatingBall(sptr<FbOption>& option)
72 {
73     TLOGI(WmsLogTag::WMS_SYSTEM, "UpdateFloatingBall");
74     if (curState_ != FbWindowState::STATE_STARTED) {
75         TLOGE(WmsLogTag::WMS_SYSTEM, "cur state is not started, can not update");
76         SingletonContainer::Get<FloatingballReporter>().ReportFbUpdateContent(templateType_,
77             "cur state is not started, can not update");
78         return WMError::WM_ERROR_FB_INVALID_STATE;
79     }
80     if (option == nullptr || window_ == nullptr) {
81         TLOGE(WmsLogTag::WMS_SYSTEM, "option or window is nullptr");
82         SingletonContainer::Get<FloatingballReporter>().ReportFbUpdateContent(templateType_,
83             "option or window is nullptr");
84         return WMError::WM_ERROR_FB_STATE_ABNORMALLY;
85     }
86     FloatingBallTemplateBaseInfo fbTemplateBaseInfo;
87     option->GetFbTemplateBaseInfo(fbTemplateBaseInfo);
88     auto errCode = window_->UpdateFloatingBall(fbTemplateBaseInfo, option->GetIcon());
89     std::ostringstream ss;
90     errCode == WMError::WM_OK ? (ss << "") : (ss << "Update floating ball window session failed, errCode:"
91         << static_cast<uint32_t>(errCode));
92     SingletonContainer::Get<FloatingballReporter>().ReportFbUpdateContent(templateType_, ss.str());
93     return errCode;
94 }
95 
StartFloatingBall(sptr<FbOption> & option)96 WMError FloatingBallController::StartFloatingBall(sptr<FbOption>& option)
97 {
98     {
99         std::lock_guard<std::mutex> lock(controllerMutex_);
100         if (FloatingBallManager::HasActiveController() && !FloatingBallManager::IsActiveController(this)) {
101             TLOGI(WmsLogTag::WMS_SYSTEM, "OnStartFloatingBall abort");
102             return WMError::WM_ERROR_FB_REPEAT_CONTROLLER;
103         }
104         TLOGI(WmsLogTag::WMS_SYSTEM, "called");
105         if (option == nullptr) {
106             TLOGE(WmsLogTag::WMS_SYSTEM, "fbOption is null");
107             return WMError::WM_ERROR_FB_STATE_ABNORMALLY;
108         }
109         templateType_ = option->GetTemplate();
110         if (curState_ == FbWindowState::STATE_STARTING || curState_ == FbWindowState::STATE_STARTED) {
111             TLOGW(WmsLogTag::WMS_SYSTEM, "fbWindow state is: %{public}u, id: %{public}u, mainWindow: %{public}u",
112                 curState_, (window_ == nullptr) ? INVALID_WINDOW_ID : window_->GetWindowId(), mainWindowId_);
113             SingletonContainer::Get<FloatingballReporter>().ReportFbStart(templateType_,
114                 "fbWindow state is starting or started");
115             return WMError::WM_ERROR_FB_REPEAT_OPERATION;
116         }
117         if (curState_ == FbWindowState::STATE_STOPPING) {
118             TLOGW(WmsLogTag::WMS_SYSTEM, "fbWindow state is: %{public}u, id: %{public}u, mainWindow: %{public}u",
119                 curState_, (window_ == nullptr) ? INVALID_WINDOW_ID : window_->GetWindowId(), mainWindowId_);
120             SingletonContainer::Get<FloatingballReporter>().ReportFbStart(templateType_, "fbWindow state is stopping");
121             return WMError::WM_ERROR_FB_INVALID_STATE;
122         }
123         curState_ = FbWindowState::STATE_STARTING;
124         FloatingBallManager::SetActiveController(this);
125     }
126     auto errorCode = StartFloatingBallInner(option);
127     if (errorCode != WMError::WM_OK) {
128         curState_ = FbWindowState::STATE_UNDEFINED;
129         FloatingBallManager::RemoveActiveController(this);
130     }
131     return errorCode;
132 }
133 
StartFloatingBallInner(const sptr<FbOption> & option)134 WMError FloatingBallController::StartFloatingBallInner(const sptr<FbOption>& option)
135 {
136     WMError errCode = CreateFloatingBallWindow(option);
137     if (errCode != WMError::WM_OK) {
138         TLOGE(WmsLogTag::WMS_SYSTEM, "Create fb window failed, err: %{public}u", errCode);
139         return errCode;
140     }
141     // LCOV_EXCL_START
142     errCode = window_->Show(0, false);
143     if (errCode != WMError::WM_OK) {
144         TLOGE(WmsLogTag::WMS_SYSTEM, "Show fb window failed, err: %{public}u", errCode);
145         (void)window_->Destroy();
146         return WMError::WM_ERROR_FB_STATE_ABNORMALLY;
147     }
148     mainWindowLifeCycleListener_ = sptr<FloatingBallController::WindowLifeCycleListener>::MakeSptr();
149     mainWindow_->RegisterLifeCycleListener(mainWindowLifeCycleListener_);
150     curState_ = FbWindowState::STATE_STARTED;
151     SingletonContainer::Get<FloatingballReporter>().ReportFbStart(templateType_, "");
152     OnFloatingBallStart();
153     return WMError::WM_OK;
154     // LCOV_EXCL_STOP
155 }
156 
AfterDestroyed()157 void FloatingBallController::WindowLifeCycleListener::AfterDestroyed()
158 {
159     TLOGI(WmsLogTag::WMS_SYSTEM, "fb AfterDestroyed");
160     FloatingBallManager::DoDestroy();
161 }
162 
CreateFloatingBallWindow(const sptr<FbOption> & option)163 WMError FloatingBallController::CreateFloatingBallWindow(const sptr<FbOption>& option)
164 {
165     if (option == nullptr || contextPtr_ == nullptr || mainWindow_ == nullptr) {
166         TLOGE(WmsLogTag::WMS_SYSTEM, "Create fb failed, invalid fbOption");
167         return WMError::WM_ERROR_FB_STATE_ABNORMALLY;
168     }
169     // LCOV_EXCL_START
170     auto uid = getuid();
171     auto mainWindowState = mainWindow_->GetWindowState();
172     TLOGI(WmsLogTag::WMS_SYSTEM, "mainWindow:%{public}u, mainWindowState:%{public}u, uid %{public}d",
173         mainWindowId_, mainWindowState, uid);
174     if (mainWindowState != WindowState::STATE_SHOWN) {
175         TLOGE(WmsLogTag::WMS_SYSTEM, "mainWindow:%{public}u is not shown", mainWindowId_);
176         return WMError::WM_ERROR_FB_CREATE_FAILED;
177     }
178     auto windowOption = sptr<WindowOption>::MakeSptr();
179     windowOption->SetWindowName(FB_WINDOW_NAME + "_" + std::to_string(uid));
180     windowOption->SetWindowType(WindowType::WINDOW_TYPE_FB);
181     windowOption->SetWindowMode(WindowMode::WINDOW_MODE_FB);
182     windowOption->SetTouchable(false);
183     FloatingBallTemplateBaseInfo fbTemplateBaseInfo;
184     option->GetFbTemplateBaseInfo(fbTemplateBaseInfo);
185     WMError errCode = WMError::WM_OK;
186     auto context = static_cast<std::weak_ptr<AbilityRuntime::Context>*>(contextPtr_);
187     sptr<Window> window = Window::CreateFb(windowOption, fbTemplateBaseInfo, option->GetIcon(),
188         context->lock(), errCode);
189     if (window == nullptr || errCode != WMError::WM_OK) {
190         TLOGW(WmsLogTag::WMS_SYSTEM, "Window create failed, reason: %{public}d", errCode);
191         return WMError::WM_ERROR_FB_CREATE_FAILED;
192     }
193     window_ = window;
194     return WMError::WM_OK;
195     // LCOV_EXCL_STOP
196 }
197 
198 // LCOV_EXCL_START
StopFloatingBallFromClient()199 WMError FloatingBallController::StopFloatingBallFromClient()
200 {
201     {
202         std::lock_guard<std::mutex> lock(controllerMutex_);
203         TLOGI(WmsLogTag::WMS_SYSTEM, "StopFloatingBallFromClient");
204         if (curState_ == FbWindowState::STATE_STOPPING ||
205             curState_ == FbWindowState::STATE_STOPPED) {
206             TLOGE(WmsLogTag::WMS_SYSTEM, "Repeat stop request, curState: %{public}u", curState_);
207             return WMError::WM_ERROR_FB_REPEAT_OPERATION;
208         }
209         if (window_ == nullptr) {
210             TLOGE(WmsLogTag::WMS_SYSTEM, "window is nullptr when stop fb");
211             return WMError::WM_ERROR_FB_STATE_ABNORMALLY;
212         }
213         stopFromClient_ = true;
214         curState_ = FbWindowState::STATE_STOPPING;
215     }
216     window_->NotifyPrepareCloseFloatingBall();
217     return WMError::WM_OK;
218 }
219 
StopFloatingBall()220 WMError FloatingBallController::StopFloatingBall()
221 {
222     {
223         std::lock_guard<std::mutex> lock(controllerMutex_);
224         TLOGI(WmsLogTag::WMS_SYSTEM, "StopFloatingBall in");
225         if ((!stopFromClient_ && curState_ == FbWindowState::STATE_STOPPING) ||
226             curState_ == FbWindowState::STATE_STOPPED) {
227             TLOGE(WmsLogTag::WMS_SYSTEM, "Repeat stop request, curState: %{public}u", curState_);
228             SingletonContainer::Get<FloatingballReporter>().ReportFbRemove(templateType_,
229                 "Repeat stop request, curState: stopping or stopped");
230             return WMError::WM_ERROR_FB_REPEAT_OPERATION;
231         }
232         if (window_ == nullptr) {
233             TLOGE(WmsLogTag::WMS_SYSTEM, "window is nullptr when stop fb");
234             return WMError::WM_ERROR_FB_STATE_ABNORMALLY;
235         }
236         curState_ = FbWindowState::STATE_STOPPING;
237     }
238     SingletonContainer::Get<FloatingballReporter>().ReportFbRemove(templateType_, "");
239     return DestroyFloatingBallWindow();
240 }
241 // LCOV_EXCL_STOP
242 
DestroyFloatingBallWindow()243 WMError FloatingBallController::DestroyFloatingBallWindow()
244 {
245     TLOGI(WmsLogTag::WMS_SYSTEM, "called");
246     if (window_ == nullptr) {
247         TLOGE(WmsLogTag::WMS_SYSTEM, "window is nullptr when destroy fb");
248         return WMError::WM_ERROR_FB_INTERNAL_ERROR;
249     }
250     // LCOV_EXCL_START
251     WMError ret = window_->Destroy();
252     if (ret != WMError::WM_OK) {
253         curState_ = FbWindowState::STATE_UNDEFINED;
254         TLOGE(WmsLogTag::WMS_SYSTEM, "window destroy failed, err:%{public}u", ret);
255         return WMError::WM_ERROR_FB_INTERNAL_ERROR;
256     }
257     curState_ = FbWindowState::STATE_STOPPED;
258     OnFloatingBallStop();
259     FloatingBallManager::RemoveActiveController(weakRef_);
260     if (mainWindow_ != nullptr) {
261         mainWindow_->UnregisterLifeCycleListener(mainWindowLifeCycleListener_);
262     }
263     window_ = nullptr;
264     stopFromClient_ = false;
265     return WMError::WM_OK;
266     // LCOV_EXCL_STOP
267 }
268 
GetFbWindow() const269 sptr<Window> FloatingBallController::GetFbWindow() const
270 {
271     return window_;
272 }
273 
RestoreMainWindow(const std::shared_ptr<AAFwk::Want> & want)274 WMError FloatingBallController::RestoreMainWindow(const std::shared_ptr<AAFwk::Want>& want)
275 {
276     TLOGI(WmsLogTag::WMS_SYSTEM, "restoreMainWindow");
277     if (curState_ != FbWindowState::STATE_STARTED) {
278         TLOGE(WmsLogTag::WMS_SYSTEM, "state is not started when restore main window");
279         SingletonContainer::Get<FloatingballReporter>().ReportFbRestoreMainWindow(templateType_,
280             "state is not started when restore main window");
281         return WMError::WM_ERROR_FB_INVALID_STATE;
282     }
283     if (window_ == nullptr) {
284         TLOGE(WmsLogTag::WMS_SYSTEM, "window is null when restoreMainWindow");
285         SingletonContainer::Get<FloatingballReporter>().ReportFbRestoreMainWindow(templateType_,
286             "window is null when restoreMainWindow");
287         return WMError::WM_ERROR_FB_STATE_ABNORMALLY;
288     }
289     SingletonContainer::Get<FloatingballReporter>().ReportFbRestoreMainWindow(templateType_, "");
290     return window_->RestoreFbMainWindow(want);
291 }
292 
293 // LCOV_EXCL_START
OnFloatingBallClick()294 void FloatingBallController::OnFloatingBallClick()
295 {
296     auto fbClickObservers = fbClickObservers_;
297     for (auto& listener : fbClickObservers) {
298         if (listener == nullptr) {
299             TLOGE(WmsLogTag::WMS_SYSTEM, "one click observer is nullptr");
300             continue;
301         }
302         listener->OnClickEvent();
303     }
304 }
305 
OnFloatingBallStart()306 void FloatingBallController::OnFloatingBallStart()
307 {
308     auto fbLifeCycleListeners = fbLifeCycleListeners_;
309     for (auto& listener : fbLifeCycleListeners) {
310         if (listener == nullptr) {
311             TLOGE(WmsLogTag::WMS_SYSTEM, "one lifecycle listener is nullptr");
312             continue;
313         }
314         listener->OnFloatingBallStart();
315     }
316 }
317 
OnFloatingBallStop()318 void FloatingBallController::OnFloatingBallStop()
319 {
320     auto fbLifeCycleListeners = fbLifeCycleListeners_;
321     for (auto& listener : fbLifeCycleListeners) {
322         if (listener == nullptr) {
323             TLOGE(WmsLogTag::WMS_SYSTEM, "one lifecycle listener is nullptr");
324             continue;
325         }
326         listener->OnFloatingBallStop();
327     }
328 }
329 // LCOV_EXCL_STOP
330 
RegisterFbLifecycle(const sptr<IFbLifeCycle> & listener)331 WMError FloatingBallController::RegisterFbLifecycle(const sptr<IFbLifeCycle>& listener)
332 {
333     return RegisterListener(fbLifeCycleListeners_, listener);
334 }
335 
RegisterFbClickObserver(const sptr<IFbClickObserver> & listener)336 WMError FloatingBallController::RegisterFbClickObserver(const sptr<IFbClickObserver>& listener)
337 {
338     return RegisterListener(fbClickObservers_, listener);
339 }
340 
UnRegisterFbLifecycle(const sptr<IFbLifeCycle> & listener)341 WMError FloatingBallController::UnRegisterFbLifecycle(const sptr<IFbLifeCycle>& listener)
342 {
343     return UnRegisterListener(fbLifeCycleListeners_, listener);
344 }
345 
UnRegisterFbClickObserver(const sptr<IFbClickObserver> & listener)346 WMError FloatingBallController::UnRegisterFbClickObserver(const sptr<IFbClickObserver>& listener)
347 {
348     return UnRegisterListener(fbClickObservers_, listener);
349 }
350 
351 template<typename T>
RegisterListener(std::vector<sptr<T>> & holder,const sptr<T> & listener)352 WMError FloatingBallController::RegisterListener(std::vector<sptr<T>>& holder, const sptr<T>& listener)
353 {
354     std::lock_guard<std::mutex> lock(listenerMutex_);
355     if (listener == nullptr) {
356         TLOGE(WmsLogTag::WMS_SYSTEM, "listener is nullptr");
357         return WMError::WM_ERROR_FB_INTERNAL_ERROR;
358     }
359     if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
360         TLOGE(WmsLogTag::WMS_SYSTEM, "Listener already registered");
361         return WMError::WM_OK;
362     }
363     holder.emplace_back(listener);
364     return WMError::WM_OK;
365 }
366 
367 template<typename T>
UnRegisterListener(std::vector<sptr<T>> & holder,const sptr<T> & listener)368 WMError FloatingBallController::UnRegisterListener(std::vector<sptr<T>>& holder, const sptr<T>& listener)
369 {
370     std::lock_guard<std::mutex> lock(listenerMutex_);
371     if (listener == nullptr) {
372         TLOGE(WmsLogTag::WMS_SYSTEM, "listener could not be null");
373         return WMError::WM_ERROR_FB_INTERNAL_ERROR;
374     }
375     holder.erase(std::remove_if(holder.begin(), holder.end(),
376         [listener](const sptr<T>& registeredListener) {
377             return registeredListener == listener;
378         }), holder.end());
379     return WMError::WM_OK;
380 }
381 
382 // LCOV_EXCL_START
GetFloatingBallWindowInfo(uint32_t & windowId)383 WMError FloatingBallController::GetFloatingBallWindowInfo(uint32_t& windowId)
384 {
385     if (curState_ != FbWindowState::STATE_STARTED) {
386         return WMError::WM_ERROR_FB_INVALID_STATE;
387     }
388     if (window_ == nullptr) {
389         TLOGE(WmsLogTag::WMS_SYSTEM, "window is null");
390         return WMError::WM_ERROR_FB_STATE_ABNORMALLY;
391     }
392     return window_->GetFloatingBallWindowId(windowId);
393 }
394 // LCOV_EXCL_STOP
395 
396 } // namespace Rosen
397 } // namespace OHOS