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