• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "dark_mode_manager.h"
17 
18 #include "setting_data_manager.h"
19 #include "ui_appearance_log.h"
20 
21 namespace OHOS::ArkUi::UiAppearance {
22 namespace {
23 const std::string SETTING_DARK_MODE_MODE = "settings.uiappearance.darkmode_mode";
24 const std::string SETTING_DARK_MODE_START_TIME = "settings.uiappearance.darkmode_starttime";
25 const std::string SETTING_DARK_MODE_END_TIME = "settings.uiappearance.darkmode_endtime";
26 const static int32_t USER100 = 100;
27 }
28 
GetInstance()29 DarkModeManager &DarkModeManager::GetInstance()
30 {
31     static DarkModeManager instance;
32     return instance;
33 }
34 
Initialize(const std::function<void (bool,int32_t)> & updateCallback)35 ErrCode DarkModeManager::Initialize(const std::function<void(bool, int32_t)>& updateCallback)
36 {
37     LoadSettingDataObserversCallback();
38     updateCallback_ = updateCallback;
39     return ERR_OK;
40 }
41 
LoadUserSettingData(const int32_t userId,const bool needUpdateCallback,bool & isDarkMode)42 ErrCode DarkModeManager::LoadUserSettingData(const int32_t userId, const bool needUpdateCallback, bool &isDarkMode)
43 {
44     SettingDataManager& manager = SettingDataManager::GetInstance();
45     int32_t darkMode = DARK_MODE_INVALID;
46     manager.GetInt32ValueStrictly(SETTING_DARK_MODE_MODE, darkMode, userId);
47     if (darkMode < DARK_MODE_INVALID || darkMode >= DARK_MODE_SIZE) {
48         LOGE("dark mode out of range: %{public}d, userId: %{public}d", darkMode, userId);
49         darkMode = DARK_MODE_INVALID;
50     }
51     int32_t startTime = -1;
52     manager.GetInt32ValueStrictly(SETTING_DARK_MODE_START_TIME, startTime, userId);
53     int32_t endTime = -1;
54     manager.GetInt32ValueStrictly(SETTING_DARK_MODE_END_TIME, endTime, userId);
55 
56     std::lock_guard lock(darkModeStatesMutex_);
57     DarkModeState& state = darkModeStates_[userId];
58     state.settingMode = static_cast<DarkModeMode>(darkMode);
59     state.settingStartTime = startTime;
60     state.settingEndTime = endTime;
61     LOGI("load user setting data, userId: %{public}d, mode: %{public}d, start: %{public}d, end : %{public}d",
62         userId, darkMode, startTime, endTime);
63     temporaryColorModeMgr_.InitData(userId);
64     if (temporaryColorModeMgr_.IsColorModeTemporary(userId) &&
65         temporaryColorModeMgr_.CheckTemporaryStateEffective(userId) == false) {
66         temporaryColorModeMgr_.SetColorModeNormal(userId);
67     }
68     screenSwitchOperatorMgr_.ResetScreenOffOperateInfo();
69     return OnStateChangeLocked(userId, needUpdateCallback, isDarkMode, false);
70 }
71 
NotifyDarkModeUpdate(const int32_t userId,const bool isDarkMode)72 void DarkModeManager::NotifyDarkModeUpdate(const int32_t userId, const bool isDarkMode)
73 {
74     SettingDataManager& manager = SettingDataManager::GetInstance();
75     std::lock_guard lock(darkModeStatesMutex_);
76     const DarkModeState& state = darkModeStates_[userId];
77     if (isDarkMode) {
78         if (state.settingMode == DARK_MODE_ALWAYS_LIGHT || state.settingMode == DARK_MODE_INVALID) {
79             LOGI("notify change to always dark, userId: %{public}d", userId);
80             manager.SetStringValue(SETTING_DARK_MODE_MODE, std::to_string(DARK_MODE_ALWAYS_DARK), userId);
81         } // else no need to change
82     } else {
83         if (state.settingMode == DARK_MODE_ALWAYS_DARK || state.settingMode == DARK_MODE_INVALID) {
84             LOGI("notify change to always light, userId: %{public}d", userId);
85             manager.SetStringValue(SETTING_DARK_MODE_MODE, std::to_string(DARK_MODE_ALWAYS_LIGHT), userId);
86         } // else no need to change
87     }
88 }
89 
ScreenOnCallback()90 void DarkModeManager::ScreenOnCallback()
91 {
92     screenSwitchOperatorMgr_.SetScreenOn();
93 }
94 
ScreenOffCallback()95 void DarkModeManager::ScreenOffCallback()
96 {
97     screenSwitchOperatorMgr_.SetScreenOff();
98     if (screenSwitchOperatorMgr_.HaveScreenOffOperate()) {
99         bool switchToDark = false;
100         int32_t userId = USER100;
101         screenSwitchOperatorMgr_.GetScreenOffOperateInfo(switchToDark, userId);
102         OnChangeDarkMode(
103             switchToDark == true ? DarkModeMode::DARK_MODE_ALWAYS_DARK : DarkModeMode::DARK_MODE_ALWAYS_LIGHT,
104             userId);
105         screenSwitchOperatorMgr_.ResetScreenOffOperateInfo();
106     }
107 }
108 
OnSwitchUser(const int32_t userId)109 ErrCode DarkModeManager::OnSwitchUser(const int32_t userId)
110 {
111     SettingDataManager& manager = SettingDataManager::GetInstance();
112     if (!manager.IsInitialized()) {
113         ErrCode code = manager.Initialize();
114         if (code != ERR_OK || manager.IsInitialized() == false) {
115             LOGE("setting data manager is not initialized");
116             return ERR_NO_INIT;
117         }
118     }
119 
120     if (userId <= INVALID_USER_ID) {
121         LOGE("invalid userId: %{public}d", userId);
122         return ERR_INVALID_OPERATION;
123     }
124 
125     std::lock_guard lock(settingDataObserversMutex_);
126     if (settingDataObserversUserId_ != INVALID_USER_ID) {
127         LOGI("clear timers and unregister observers for userId: %{public}d", settingDataObserversUserId_);
128         alarmTimerManager_.ClearTimerByUserId(settingDataObserversUserId_);
129         UnregisterSettingDataObserversLocked(settingDataObserversUserId_);
130         settingDataObserversUserId_ = INVALID_USER_ID;
131     }
132 
133     ErrCode code = RegisterSettingDataObserversLocked(userId);
134     settingDataObserversUserId_ = userId;
135     return code;
136 }
137 
DoSwitchTemporaryColorMode(const int32_t userId,bool isDarkMode)138 void DarkModeManager::DoSwitchTemporaryColorMode(const int32_t userId, bool isDarkMode)
139 {
140     if (IsDarkModeCustomAuto(userId)) {
141         screenSwitchOperatorMgr_.ResetScreenOffOperateInfo();
142         int32_t settingStartTime = 0;
143         int32_t settingEndTime = 0;
144         auto res = GetSettingTime(userId, settingStartTime, settingEndTime);
145         if (res == false) {
146             LOGE("GetSettingTime faild userId: %{public}d", userId);
147             return;
148         }
149         if ((AlarmTimerManager::IsWithinTimeInterval(settingStartTime, settingEndTime) && isDarkMode == true) ||
150             (!AlarmTimerManager::IsWithinTimeInterval(settingStartTime, settingEndTime) && isDarkMode == false)) {
151             temporaryColorModeMgr_.SetColorModeNormal(userId);
152         } else {
153             temporaryColorModeMgr_.SetColorModeTemporary(userId);
154         }
155     }
156 }
157 
UpdateDarkModeSchedule(const DarkModeMode mode,const int32_t userId,const bool resetTempColorModeFlag)158 void DarkModeManager::UpdateDarkModeSchedule(
159     const DarkModeMode mode, const int32_t userId, const bool resetTempColorModeFlag)
160 {
161     screenSwitchOperatorMgr_.ResetScreenOffOperateInfo();
162     if (resetTempColorModeFlag == true) {
163         OnChangeDarkMode(mode, userId);
164         return;
165     }
166 
167     if (screenSwitchOperatorMgr_.IsScreenOff()) {
168         if (temporaryColorModeMgr_.IsColorModeNormal(userId) ||
169             temporaryColorModeMgr_.CheckTemporaryStateEffective(userId) == false) {
170             OnChangeDarkMode(mode, userId);
171         }
172         return;
173     }
174 
175     if (temporaryColorModeMgr_.IsColorModeNormal(userId) ||
176         temporaryColorModeMgr_.CheckTemporaryStateEffective(userId) == false) {
177         screenSwitchOperatorMgr_.SetScreenOffOperateInfo(mode == DARK_MODE_ALWAYS_DARK, userId);
178         LOGI("SetScreenOffOperateInfo userId:%{public}d operate:%{public}d", userId, static_cast<int32_t>(mode));
179     }
180 }
181 
RestartTimer()182 ErrCode DarkModeManager::RestartTimer()
183 {
184     std::lock_guard lock(darkModeStatesMutex_);
185     DarkModeMode mode = darkModeStates_[settingDataObserversUserId_].settingMode;
186     if (mode != DARK_MODE_CUSTOM_AUTO) {
187         LOGD("no need to restart timer.");
188         return ERR_OK;
189     }
190 
191     int32_t startTime = darkModeStates_[settingDataObserversUserId_].settingStartTime;
192     int32_t endTime = darkModeStates_[settingDataObserversUserId_].settingEndTime;
193     if (AlarmTimerManager::IsWithinTimeInterval(startTime, endTime)) {
194         UpdateDarkModeSchedule(DARK_MODE_ALWAYS_DARK, settingDataObserversUserId_, false);
195     } else {
196         UpdateDarkModeSchedule(DARK_MODE_ALWAYS_LIGHT, settingDataObserversUserId_, false);
197     }
198     return alarmTimerManager_.RestartAllTimer();
199 }
200 
IsDarkModeCustomAuto(const int32_t userId)201 bool DarkModeManager::IsDarkModeCustomAuto(const int32_t userId)
202 {
203     std::lock_guard lock(darkModeStatesMutex_);
204     return darkModeStates_[userId].settingMode == DARK_MODE_CUSTOM_AUTO;
205 }
206 
GetSettingTime(const int32_t userId,int32_t & settingStartTime,int32_t & settingEndTime)207 bool DarkModeManager::GetSettingTime(const int32_t userId, int32_t& settingStartTime, int32_t& settingEndTime)
208 {
209     std::lock_guard lock(darkModeStatesMutex_);
210     auto it = darkModeStates_.find(userId);
211     if (it != darkModeStates_.end()) {
212         settingStartTime = it->second.settingStartTime;
213         settingEndTime = it->second.settingEndTime;
214         return true;
215     }
216     return false;
217 }
218 
IsColorModeNormal(const int32_t userId)219 bool DarkModeManager::IsColorModeNormal(const int32_t userId)
220 {
221     return temporaryColorModeMgr_.IsColorModeNormal(userId);
222 }
223 
Dump()224 void DarkModeManager::Dump()
225 {
226     {
227         std::lock_guard observersGuard(settingDataObserversMutex_);
228         LOGD("settingData observers size: %{public}zu, userId: %{public}d",
229             settingDataObservers_.size(), settingDataObserversUserId_);
230     }
231 
232     std::lock_guard stateGuard(darkModeStatesMutex_);
233     LOGD("darkModeStates size: %{public}zu", darkModeStates_.size());
234     for (const auto& state : darkModeStates_) {
235         LOGD("userId: %{public}d, mode: %{public}d, start: %{public}d, end: %{public}d",
236             state.first, state.second.settingMode, state.second.settingStartTime, state.second.settingEndTime);
237     }
238 
239     alarmTimerManager_.Dump();
240 }
241 
LoadSettingDataObserversCallback()242 void DarkModeManager::LoadSettingDataObserversCallback()
243 {
244     std::lock_guard lock(settingDataObserversMutex_);
245     settingDataObservers_.clear();
246     settingDataObservers_.emplace_back(SETTING_DARK_MODE_MODE, [&](const std::string& key, int32_t userId) {
247         SettingDataDarkModeModeUpdateFunc(key, userId);
248     });
249     settingDataObservers_.emplace_back(SETTING_DARK_MODE_START_TIME, [&](const std::string& key, int32_t userId) {
250         SettingDataDarkModeStartTimeUpdateFunc(key, userId);
251     });
252     settingDataObservers_.emplace_back(SETTING_DARK_MODE_END_TIME, [&](const std::string& key, int32_t userId) {
253         SettingDataDarkModeEndTimeUpdateFunc(key, userId);
254     });
255 }
256 
RegisterSettingDataObserversLocked(const int32_t userId) const257 ErrCode DarkModeManager::RegisterSettingDataObserversLocked(const int32_t userId) const
258 {
259     SettingDataManager& manager = SettingDataManager::GetInstance();
260     size_t count = 0;
261     for (const auto& observer : settingDataObservers_) {
262         if (manager.RegisterObserver(observer.first, observer.second, userId) != ERR_OK) {
263             count++;
264         }
265     }
266     if (count != 0) {
267         LOGE("setting data observers are not all initialized");
268         return ERR_NO_INIT;
269     }
270     LOGD("setting data observers are all initialized");
271     return ERR_OK;
272 }
273 
UnregisterSettingDataObserversLocked(const int32_t userId) const274 void DarkModeManager::UnregisterSettingDataObserversLocked(const int32_t userId) const
275 {
276     SettingDataManager& manager = SettingDataManager::GetInstance();
277     for (const auto& observer : settingDataObservers_) {
278         manager.UnregisterObserver(observer.first, userId);
279     }
280 }
281 
SettingDataDarkModeModeUpdateFunc(const std::string & key,const int32_t userId)282 void DarkModeManager::SettingDataDarkModeModeUpdateFunc(const std::string& key, const int32_t userId)
283 {
284     SettingDataManager& manager = SettingDataManager::GetInstance();
285     int32_t value = DARK_MODE_INVALID;
286     ErrCode code = manager.GetInt32ValueStrictly(key, value, userId);
287     if (code != ERR_OK) {
288         LOGE("get dark mode value failed, key: %{public}s, userId: %{public}d, code: %{public}d, set to default",
289             key.c_str(), userId, code);
290         value = DARK_MODE_INVALID;
291     }
292     if (value < DARK_MODE_INVALID || value >= DARK_MODE_SIZE) {
293         LOGE("dark mode value is invalid, key: %{public}s, userId: %{public}d, value: %{public}d, set to default",
294             key.c_str(), userId, value);
295         value = DARK_MODE_INVALID;
296     }
297 
298     auto mode = static_cast<DarkModeMode>(value);
299     std::lock_guard lock(darkModeStatesMutex_);
300     LOGI("dark mode change, key: %{public}s, userId: %{public}d, from %{public}d to %{public}d",
301         key.c_str(), userId, darkModeStates_[userId].settingMode, value);
302     darkModeStates_[userId].settingMode = mode;
303     bool isDarkMode = false;
304     OnStateChangeLocked(userId, true, isDarkMode, true);
305 }
306 
SettingDataDarkModeStartTimeUpdateFunc(const std::string & key,const int32_t userId)307 void DarkModeManager::SettingDataDarkModeStartTimeUpdateFunc(const std::string& key, const int32_t userId)
308 {
309     SettingDataManager& manager = SettingDataManager::GetInstance();
310     int32_t value = -1;
311     manager.GetInt32ValueStrictly(key, value, userId);
312     std::lock_guard lock(darkModeStatesMutex_);
313     LOGI("dark mode start time change, key: %{public}s, userId: %{public}d, from %{public}d to %{public}d",
314         key.c_str(), userId, darkModeStates_[userId].settingStartTime, value);
315     darkModeStates_[userId].settingStartTime = value;
316     bool isDarkMode = false;
317     OnStateChangeLocked(userId, true, isDarkMode, true);
318 }
319 
SettingDataDarkModeEndTimeUpdateFunc(const std::string & key,const int32_t userId)320 void DarkModeManager::SettingDataDarkModeEndTimeUpdateFunc(const std::string& key, const int32_t userId)
321 {
322     SettingDataManager& manager = SettingDataManager::GetInstance();
323     int32_t value = -1;
324     manager.GetInt32ValueStrictly(key, value, userId);
325     std::lock_guard lock(darkModeStatesMutex_);
326     LOGI("dark mode end time change, key: %{public}s, userId: %{public}d, from %{public}d to %{public}d",
327         key.c_str(), userId, darkModeStates_[userId].settingEndTime, value);
328     darkModeStates_[userId].settingEndTime = value;
329     bool isDarkMode = false;
330     OnStateChangeLocked(userId, true, isDarkMode, true);
331 }
332 
OnStateChangeLocked(const int32_t userId,const bool needUpdateCallback,bool & isDarkMode,const bool resetTempColorModeFlag)333 ErrCode DarkModeManager::OnStateChangeLocked(
334     const int32_t userId, const bool needUpdateCallback, bool& isDarkMode, const bool resetTempColorModeFlag)
335 {
336     ErrCode code = ERR_OK;
337     DarkModeState& state = darkModeStates_[userId];
338     switch (state.settingMode) {
339         case DARK_MODE_ALWAYS_LIGHT:
340         case DARK_MODE_ALWAYS_DARK:
341             code = OnStateChangeToAllDayMode(
342                 userId, state.settingMode, needUpdateCallback, isDarkMode, resetTempColorModeFlag);
343             break;
344         case DARK_MODE_CUSTOM_AUTO:
345             code = OnStateChangeToCustomAutoMode(userId, state, needUpdateCallback, isDarkMode, resetTempColorModeFlag);
346             break;
347         default:
348             // do nothing
349             code = ERR_INVALID_OPERATION;
350             break;
351     }
352     return code;
353 }
354 
OnStateChangeToAllDayMode(const int32_t userId,const DarkModeMode darkMode,const bool needUpdateCallback,bool & isDarkMode,const bool resetTempColorModeFlag)355 ErrCode DarkModeManager::OnStateChangeToAllDayMode(const int32_t userId, const DarkModeMode darkMode,
356     const bool needUpdateCallback, bool& isDarkMode, const bool resetTempColorModeFlag)
357 {
358     alarmTimerManager_.ClearTimerByUserId(userId);
359     isDarkMode = darkMode == DARK_MODE_ALWAYS_DARK;
360     if (needUpdateCallback) {
361         UpdateDarkModeSchedule(darkMode, userId, resetTempColorModeFlag);
362     }
363     return ERR_OK;
364 }
365 
OnStateChangeToCustomAutoMode(const int32_t userId,const DarkModeState & state,const bool needUpdateCallback,bool & isDarkMode,const bool resetTempColorModeFlag)366 ErrCode DarkModeManager::OnStateChangeToCustomAutoMode(const int32_t userId, const DarkModeState& state,
367     const bool needUpdateCallback, bool& isDarkMode, const bool resetTempColorModeFlag)
368 {
369     ErrCode code = CreateOrUpdateTimers(state.settingStartTime, state.settingEndTime, userId);
370     if (code != ERR_OK) {
371         alarmTimerManager_.ClearTimerByUserId(userId);
372         return code;
373     }
374     DarkModeMode mode = DARK_MODE_INVALID;
375     if (AlarmTimerManager::IsWithinTimeInterval(state.settingStartTime, state.settingEndTime)) {
376         isDarkMode = true;
377         mode = DARK_MODE_ALWAYS_DARK;
378     } else {
379         isDarkMode = false;
380         mode = DARK_MODE_ALWAYS_LIGHT;
381     }
382 
383     if (needUpdateCallback) {
384         UpdateDarkModeSchedule(mode, userId, resetTempColorModeFlag);
385     }
386     return ERR_OK;
387 }
388 
OnChangeDarkMode(const DarkModeMode mode,const int32_t userId)389 void DarkModeManager::OnChangeDarkMode(const DarkModeMode mode, const int32_t userId)
390 {
391     if (!updateCallback_) {
392         LOGE("no update callback, mode: %{public}d, userId: %{public}d", mode, userId);
393         return;
394     }
395     updateCallback_(mode == DARK_MODE_ALWAYS_DARK, userId);
396     if (temporaryColorModeMgr_.IsColorModeTemporary(userId)) {
397         temporaryColorModeMgr_.SetColorModeNormal(userId);
398     }
399 }
400 
CreateOrUpdateTimers(int32_t startTime,int32_t endTime,int32_t userId)401 ErrCode DarkModeManager::CreateOrUpdateTimers(int32_t startTime, int32_t endTime, int32_t userId)
402 {
403     auto callbackSetDark = [startTime, endTime, userId]() {
404         LOGI("timer callback, startTime: %{public}d, endTime: %{public}d, userId: %{public}d",
405             startTime, endTime, userId);
406         ErrCode code = GetInstance().CheckTimerCallbackParams(startTime, endTime, userId);
407         if (code != ERR_OK) {
408             LOGE("timer callback, params check failed: %{public}d", code);
409             return;
410         }
411         GetInstance().UpdateDarkModeSchedule(DARK_MODE_ALWAYS_DARK, userId, false);
412     };
413 
414     auto callbackSetLight = [startTime, endTime, userId]() {
415         LOGI("timer callback, startTime: %{public}d, endTime: %{public}d, userId: %{public}d",
416             startTime, endTime, userId);
417         ErrCode code = GetInstance().CheckTimerCallbackParams(startTime, endTime, userId);
418         if (code != ERR_OK) {
419             LOGE("timer callback, params check failed: %{public}d", code);
420             return;
421         }
422         GetInstance().UpdateDarkModeSchedule(DARK_MODE_ALWAYS_LIGHT, userId, false);
423     };
424 
425     return alarmTimerManager_.SetScheduleTime(startTime, endTime, userId, callbackSetDark, callbackSetLight);
426 }
427 
CheckTimerCallbackParams(const int32_t startTime,const int32_t endTime,const int32_t userId)428 ErrCode DarkModeManager::CheckTimerCallbackParams(const int32_t startTime, const int32_t endTime, const int32_t userId)
429 {
430     std::lock_guard lock(darkModeStatesMutex_);
431     DarkModeState& state = darkModeStates_[userId];
432     if (state.settingMode != DARK_MODE_CUSTOM_AUTO) {
433         LOGE("timer callback, param wrong, setting mode: %{public}d", state.settingMode);
434         return ERR_INVALID_OPERATION;
435     }
436     if (state.settingStartTime != startTime) {
437         LOGE("timer callback, param wrong, startTime: %{public}d, setting: %{public}d",
438             startTime, state.settingStartTime);
439         return ERR_INVALID_OPERATION;
440     }
441     if (state.settingEndTime != endTime) {
442         LOGE("timer callback, param wrong, endTime: %{public}d, setting: %{public}d", endTime, state.settingEndTime);
443         return ERR_INVALID_OPERATION;
444     }
445     return ERR_OK;
446 }
447 } // namespace OHOS::ArkUi::UiAppearance
448