1 /*
2  * Copyright (c) 2024 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 "account_manager.h"
17 
18 #include <securec.h>
19 #include <common_event_manager.h>
20 #include <common_event_support.h>
21 #ifdef SCREENLOCK_MANAGER_ENABLED
22 #include <screenlock_manager.h>
23 #endif // SCREENLOCK_MANAGER_ENABLED
24 #include <system_ability_definition.h>
25 
26 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
27 #include "display_event_monitor.h"
28 #endif // OHOS_BUILD_ENABLE_KEYBOARD
29 #include "setting_datashare.h"
30 #include "timer_manager.h"
31 
32 #undef MMI_LOG_DOMAIN
33 #define MMI_LOG_DOMAIN MMI_LOG_SERVER
34 #undef MMI_LOG_TAG
35 #define MMI_LOG_TAG "AccountManager"
36 
37 namespace OHOS {
38 namespace MMI {
39 namespace {
40 constexpr int32_t MAIN_ACCOUNT_ID { 100 };
41 constexpr int32_t REPEAT_ONCE { 1 };
42 constexpr int32_t REPEAT_COOLING_TIME { 1000 };
43 constexpr size_t DEFAULT_BUFFER_LENGTH { 512 };
44 const std::string ACC_SHORTCUT_ENABLED { "accessibility_shortcut_enabled" };
45 const std::string ACC_SHORTCUT_ENABLED_ON_LOCK_SCREEN { "accessibility_shortcut_enabled_on_lock_screen" };
46 const std::string ACC_SHORTCUT_TIMEOUT { "accessibility_shortcut_timeout" };
47 const std::string SECURE_SETTING_URI_PROXY {
48     "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE_%d?Proxy=true" };
49 }
50 
51 std::shared_ptr<AccountManager> AccountManager::instance_;
52 std::mutex AccountManager::mutex_;
53 
GetInstance()54 std::shared_ptr<AccountManager> AccountManager::GetInstance()
55 {
56     if (instance_ == nullptr) {
57         std::lock_guard<std::mutex> lock(mutex_);
58         if (instance_ == nullptr) {
59             instance_ = std::make_shared<AccountManager>();
60             instance_->Initialize();
61         }
62     }
63     return instance_;
64 }
65 
OnReceiveEvent(const EventFwk::CommonEventData &data)66 void AccountManager::CommonEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &data)
67 {
68     AccountManager::GetInstance()->OnCommonEvent(data);
69 }
70 
AccountSetting(int32_t accountId)71 AccountManager::AccountSetting::AccountSetting(int32_t accountId)
72     : accountId_(accountId)
73 {
74     InitializeSetting();
75 }
76 
~AccountSetting()77 AccountManager::AccountSetting::~AccountSetting()
78 {
79     if (timerId_ >= 0) {
80         TimerMgr->RemoveTimer(timerId_);
81     }
82     auto &setting = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID);
83     if (switchObserver_ != nullptr) {
84         setting.UnregisterObserver(switchObserver_);
85     }
86     if (onScreenLockedSwitchObserver_ != nullptr) {
87         setting.UnregisterObserver(onScreenLockedSwitchObserver_);
88     }
89     if (configObserver_ != nullptr) {
90         setting.UnregisterObserver(configObserver_);
91     }
92 }
93 
AccountSetting(const AccountSetting &other)94 AccountManager::AccountSetting::AccountSetting(const AccountSetting &other)
95     : accountId_(other.accountId_), accShortcutTimeout_(other.accShortcutTimeout_),
96       accShortcutEnabled_(other.accShortcutEnabled_),
97       accShortcutEnabledOnScreenLocked_(other.accShortcutEnabledOnScreenLocked_)
98 {}
99 
operator =(const AccountSetting &other)100 AccountManager::AccountSetting& AccountManager::AccountSetting::operator=(const AccountSetting &other)
101 {
102     accountId_ = other.accountId_;
103     accShortcutTimeout_ = other.accShortcutTimeout_;
104     accShortcutEnabled_ = other.accShortcutEnabled_;
105     accShortcutEnabledOnScreenLocked_ = other.accShortcutEnabledOnScreenLocked_;
106     return *this;
107 }
108 
AccShortcutTimeout(int32_t accountId, const std::string &key)109 void AccountManager::AccountSetting::AccShortcutTimeout(int32_t accountId, const std::string &key)
110 {
111     auto accountMgr = ACCOUNT_MGR;
112     std::lock_guard<std::mutex> guard { accountMgr->lock_ };
113     if (auto iter = accountMgr->accounts_.find(accountId); iter != accountMgr->accounts_.end()) {
114         iter->second->OnAccShortcutTimeoutChanged(key);
115     } else {
116         MMI_HILOGW("No account(%d)", accountId);
117     }
118 }
119 
AccShortcutEnabled(int32_t accountId, const std::string &key)120 void AccountManager::AccountSetting::AccShortcutEnabled(int32_t accountId, const std::string &key)
121 {
122     auto accountMgr = ACCOUNT_MGR;
123     std::lock_guard<std::mutex> guard { accountMgr->lock_ };
124     if (auto iter = accountMgr->accounts_.find(accountId); iter != accountMgr->accounts_.end()) {
125         iter->second->OnAccShortcutEnabled(key);
126     } else {
127         MMI_HILOGW("No account(%{public}d)", accountId);
128     }
129 }
130 
AccShortcutEnabledOnScreenLocked(int32_t accountId, const std::string &key)131 void AccountManager::AccountSetting::AccShortcutEnabledOnScreenLocked(int32_t accountId, const std::string &key)
132 {
133     auto accountMgr = ACCOUNT_MGR;
134     std::lock_guard<std::mutex> guard { accountMgr->lock_ };
135     if (auto iter = accountMgr->accounts_.find(accountId); iter != accountMgr->accounts_.end()) {
136         iter->second->OnAccShortcutEnabledOnScreenLocked(key);
137     } else {
138         MMI_HILOGW("No account(%{public}d)", accountId);
139     }
140 }
141 
RegisterSettingObserver( const std::string &key, SettingObserver::UpdateFunc onUpdate)142 sptr<SettingObserver> AccountManager::AccountSetting::RegisterSettingObserver(
143     const std::string &key, SettingObserver::UpdateFunc onUpdate)
144 {
145     char buf[DEFAULT_BUFFER_LENGTH] {};
146     if (sprintf_s(buf, sizeof(buf), SECURE_SETTING_URI_PROXY.c_str(), accountId_) < 0) {
147         MMI_HILOGE("Failed to format URI");
148         return nullptr;
149     }
150     MMI_HILOGI("[AccountSetting] Registering observer of '%{public}s' in %{public}s", key.c_str(), buf);
151     auto &settingHelper = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID);
152     sptr<SettingObserver> settingObserver = settingHelper.CreateObserver(key, onUpdate);
153     ErrCode ret = settingHelper.RegisterObserver(settingObserver, std::string(buf));
154     if (ret != ERR_OK) {
155         MMI_HILOGE("[AccountSetting] Failed to register '%{public}s' observer, error:%{public}d",
156             key.c_str(), ret);
157         return nullptr;
158     }
159     return settingObserver;
160 }
161 
InitializeSetting()162 void AccountManager::AccountSetting::InitializeSetting()
163 {
164     CALL_INFO_TRACE;
165     if (switchObserver_ == nullptr) {
166         switchObserver_ = RegisterSettingObserver(ACC_SHORTCUT_ENABLED,
167             [accountId = accountId_](const std::string &key) {
168                 AccountManager::AccountSetting::AccShortcutEnabled(accountId, key);
169             });
170     }
171     if (onScreenLockedSwitchObserver_ == nullptr) {
172         onScreenLockedSwitchObserver_ = RegisterSettingObserver(ACC_SHORTCUT_ENABLED_ON_LOCK_SCREEN,
173             [accountId = accountId_](const std::string &key) {
174                 AccountManager::AccountSetting::AccShortcutEnabledOnScreenLocked(accountId, key);
175             });
176     }
177     if (configObserver_ == nullptr) {
178         configObserver_ = RegisterSettingObserver(ACC_SHORTCUT_TIMEOUT,
179             [accountId = accountId_](const std::string &key) {
180                 AccountManager::AccountSetting::AccShortcutTimeout(accountId, key);
181             });
182     }
183     if ((switchObserver_ == nullptr) || (onScreenLockedSwitchObserver_ == nullptr) || (configObserver_ == nullptr)) {
184         timerId_ = TimerMgr->AddTimer(REPEAT_COOLING_TIME, REPEAT_ONCE, [this]() {
185             InitializeSetting();
186         });
187         if (timerId_ < 0) {
188             MMI_HILOGE("AddTimer fail, setting will not work");
189         }
190     } else {
191         timerId_ = -1;
192     }
193 }
194 
OnAccShortcutTimeoutChanged(const std::string &key)195 void AccountManager::AccountSetting::OnAccShortcutTimeoutChanged(const std::string &key)
196 {
197     MMI_HILOGI("[AccountSetting][%d] Setting '%s' has changed", GetAccountId(), key.c_str());
198     ReadLongPressTime();
199 }
200 
OnAccShortcutEnabled(const std::string &key)201 void AccountManager::AccountSetting::OnAccShortcutEnabled(const std::string &key)
202 {
203     MMI_HILOGI("[AccountSetting][%d] Setting '%s' has changed", GetAccountId(), key.c_str());
204     accShortcutEnabled_ = ReadSwitchStatus(key, accShortcutEnabled_);
205 }
206 
OnAccShortcutEnabledOnScreenLocked(const std::string &key)207 void AccountManager::AccountSetting::OnAccShortcutEnabledOnScreenLocked(const std::string &key)
208 {
209     MMI_HILOGI("[AccountSetting][%d] Setting '%{public}s' has changed", GetAccountId(), key.c_str());
210     accShortcutEnabledOnScreenLocked_ = ReadSwitchStatus(key, accShortcutEnabledOnScreenLocked_);
211 }
212 
ReadSwitchStatus(const std::string &key, bool currentSwitchStatus)213 bool AccountManager::AccountSetting::ReadSwitchStatus(const std::string &key, bool currentSwitchStatus)
214 {
215     if (accountId_ < 0) {
216         return false;
217     }
218     char buf[DEFAULT_BUFFER_LENGTH] {};
219     if (sprintf_s(buf, sizeof(buf), SECURE_SETTING_URI_PROXY.c_str(), accountId_) < 0) {
220         MMI_HILOGE("Failed to format URI");
221         return currentSwitchStatus;
222     }
223     bool switchOn = true;
224     auto ret = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID).GetBoolValue(
225         key, switchOn, std::string(buf));
226     if (ret != RET_OK) {
227         MMI_HILOGE("[AccountSetting] Failed to acquire '%{public}s', error:%{public}d", key.c_str(), ret);
228         return currentSwitchStatus;
229     }
230     MMI_HILOGI("[AccountSetting] '%{public}s' switch %{public}s", key.c_str(), switchOn ? "on" : "off");
231     return switchOn;
232 }
233 
ReadLongPressTime()234 void AccountManager::AccountSetting::ReadLongPressTime()
235 {
236     if (accountId_ < 0) {
237         return;
238     }
239     char buf[DEFAULT_BUFFER_LENGTH] {};
240     if (sprintf_s(buf, sizeof(buf), SECURE_SETTING_URI_PROXY.c_str(), accountId_) < 0) {
241         MMI_HILOGE("Failed to format URI");
242         return;
243     }
244     int32_t longPressTime {};
245     auto ret = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID).GetIntValue(
246         ACC_SHORTCUT_TIMEOUT, longPressTime, std::string(buf));
247     if (ret != RET_OK) {
248         MMI_HILOGE("[AccountSetting] Failed to acquire '%{public}s', error:%{public}d",
249             ACC_SHORTCUT_TIMEOUT.c_str(), ret);
250         return;
251     }
252     accShortcutTimeout_ = longPressTime;
253     MMI_HILOGI("[AccountSetting] '%{public}s' was set to %{public}d",
254         ACC_SHORTCUT_TIMEOUT.c_str(), accShortcutTimeout_);
255 }
256 
AccountManager()257 AccountManager::AccountManager()
258 {
259     handlers_ = {
260         {
261             EventFwk::CommonEventSupport::COMMON_EVENT_USER_ADDED,
262             [this](const EventFwk::CommonEventData &data) {
263                 OnAddUser(data);
264             },
265         }, {
266             EventFwk::CommonEventSupport::COMMON_EVENT_USER_REMOVED,
267             [this](const EventFwk::CommonEventData &data) {
268                 OnRemoveUser(data);
269             },
270         }, {
271             EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED,
272             [this](const EventFwk::CommonEventData &data) {
273                 OnSwitchUser(data);
274             },
275         }, {
276             EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_ON,
277             [this](const EventFwk::CommonEventData &data) {
278 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
279                 DISPLAY_MONITOR->SetScreenStatus(EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_ON);
280 #endif // OHOS_BUILD_ENABLE_KEYBOARD
281             },
282         }, {
283             EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF,
284             [this](const EventFwk::CommonEventData &data) {
285 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
286                 DISPLAY_MONITOR->SetScreenStatus(EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF);
287 #endif // OHOS_BUILD_ENABLE_KEYBOARD
288             },
289         }, {
290             EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_LOCKED,
291             [this](const EventFwk::CommonEventData &data) {
292 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
293                 DISPLAY_MONITOR->SetScreenLocked(true);
294 #endif // OHOS_BUILD_ENABLE_KEYBOARD
295             },
296         }, {
297             EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED,
298             [this](const EventFwk::CommonEventData &data) {
299 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
300                 DISPLAY_MONITOR->SetScreenLocked(false);
301 #endif // OHOS_BUILD_ENABLE_KEYBOARD
302             },
303         }
304     };
305 }
306 
~AccountManager()307 AccountManager::~AccountManager()
308 {
309     std::lock_guard<std::mutex> guard { lock_ };
310     UnsubscribeCommonEvent();
311     if (timerId_ >= 0) {
312         TimerMgr->RemoveTimer(timerId_);
313     }
314     accounts_.clear();
315 }
316 
Initialize()317 void AccountManager::Initialize()
318 {
319     MMI_HILOGI("Initialize account manager");
320     std::lock_guard<std::mutex> guard { lock_ };
321     SetupMainAccount();
322     SubscribeCommonEvent();
323 #ifdef SCREENLOCK_MANAGER_ENABLED
324     InitializeScreenLockStatus();
325 #endif // SCREENLOCK_MANAGER_ENABLED
326 }
327 
GetCurrentAccountSetting()328 AccountManager::AccountSetting AccountManager::GetCurrentAccountSetting()
329 {
330     std::lock_guard<std::mutex> guard { lock_ };
331     if (auto iter = accounts_.find(currentAccountId_); iter != accounts_.end()) {
332         return *iter->second;
333     }
334     auto [iter, _] = accounts_.emplace(currentAccountId_, std::make_unique<AccountSetting>(currentAccountId_));
335     return *iter->second;
336 }
337 
338 #ifdef SCREENLOCK_MANAGER_ENABLED
InitializeScreenLockStatus()339 void AccountManager::InitializeScreenLockStatus()
340 {
341     MMI_HILOGI("Initialize screen lock status");
342 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
343     auto screenLockPtr = ScreenLock::ScreenLockManager::GetInstance();
344     CHKPV(screenLockPtr);
345     DISPLAY_MONITOR->SetScreenLocked(screenLockPtr->IsScreenLocked());
346 #endif // OHOS_BUILD_ENABLE_KEYBOARD
347 }
348 #endif // SCREENLOCK_MANAGER_ENABLED
349 
SubscribeCommonEvent()350 void AccountManager::SubscribeCommonEvent()
351 {
352     CALL_INFO_TRACE;
353     EventFwk::MatchingSkills matchingSkills;
354 
355     for (auto &item : handlers_) {
356         MMI_HILOGD("Add event: %{public}s", item.first.c_str());
357         matchingSkills.AddEvent(item.first);
358     }
359     EventFwk::CommonEventSubscribeInfo subscribeInfo { matchingSkills };
360     subscriber_ = std::make_shared<CommonEventSubscriber>(subscribeInfo);
361 
362     if (EventFwk::CommonEventManager::SubscribeCommonEvent(subscriber_)) {
363         timerId_ = -1;
364         MMI_HILOGI("SubscribeCommonEvent succeed");
365         return;
366     }
367     subscriber_ = nullptr;
368     MMI_HILOGI("SubscribeCommonEvent fail, retry later");
369     timerId_ = TimerMgr->AddTimer(REPEAT_COOLING_TIME, REPEAT_ONCE, [this]() {
370         SubscribeCommonEvent();
371     });
372     if (timerId_ < 0) {
373         MMI_HILOGE("AddTimer fail, SubscribeCommonEvent fail");
374     }
375 }
376 
UnsubscribeCommonEvent()377 void AccountManager::UnsubscribeCommonEvent()
378 {
379     CALL_INFO_TRACE;
380     if (subscriber_ != nullptr) {
381         if (!EventFwk::CommonEventManager::UnSubscribeCommonEvent(subscriber_)) {
382             MMI_HILOGE("UnSubscribeCommonEvent fail");
383         }
384         subscriber_ = nullptr;
385     }
386 }
387 
SetupMainAccount()388 void AccountManager::SetupMainAccount()
389 {
390     MMI_HILOGI("Setup main account(%{public}d)", MAIN_ACCOUNT_ID);
391     currentAccountId_ = MAIN_ACCOUNT_ID;
392     auto [_, isNew] = accounts_.emplace(MAIN_ACCOUNT_ID, std::make_unique<AccountSetting>(MAIN_ACCOUNT_ID));
393     if (!isNew) {
394         MMI_HILOGW("Account(%{public}d) has existed", MAIN_ACCOUNT_ID);
395     }
396 }
397 
OnCommonEvent(const EventFwk::CommonEventData &data)398 void AccountManager::OnCommonEvent(const EventFwk::CommonEventData &data)
399 {
400     std::lock_guard<std::mutex> guard { lock_ };
401     std::string action = data.GetWant().GetAction();
402     MMI_HILOGI("Receive common event: %{public}s", action.c_str());
403     if (auto iter = handlers_.find(action); iter != handlers_.end()) {
404         iter->second(data);
405     } else {
406         MMI_HILOGW("Ignore event: %{public}s", action.c_str());
407     }
408 }
409 
OnAddUser(const EventFwk::CommonEventData &data)410 void AccountManager::OnAddUser(const EventFwk::CommonEventData &data)
411 {
412     int32_t accountId = data.GetCode();
413     MMI_HILOGI("Add account(%d)", accountId);
414     auto [_, isNew] = accounts_.emplace(accountId, std::make_unique<AccountSetting>(accountId));
415     if (!isNew) {
416         MMI_HILOGW("Account(%d) has existed", accountId);
417     }
418 }
419 
OnRemoveUser(const EventFwk::CommonEventData &data)420 void AccountManager::OnRemoveUser(const EventFwk::CommonEventData &data)
421 {
422     int32_t accountId = data.GetCode();
423     MMI_HILOGI("Remove account(%d)", accountId);
424     if (auto iter = accounts_.find(accountId); iter != accounts_.end()) {
425         accounts_.erase(iter);
426         MMI_HILOGI("Account(%d) has been removed", accountId);
427     } else {
428         MMI_HILOGW("No account(%d)", accountId);
429     }
430 }
431 
OnSwitchUser(const EventFwk::CommonEventData &data)432 void AccountManager::OnSwitchUser(const EventFwk::CommonEventData &data)
433 {
434     int32_t accountId = data.GetCode();
435     MMI_HILOGI("Switch to account(%d)", accountId);
436     if (currentAccountId_ != accountId) {
437         if (auto iter = accounts_.find(accountId); iter == accounts_.end()) {
438             accounts_.emplace(accountId, std::make_unique<AccountSetting>(accountId));
439         }
440         currentAccountId_ = accountId;
441         MMI_HILOGI("Switched to account(%d)", currentAccountId_);
442     }
443 }
444 } // namespace MMI
445 } // namespace OHOS
446