1 /*
2 * Copyright (c) 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 "dark_mode_temp_state_manager.h"
17
18 #include <ctime>
19 #include <sys/time.h>
20 #include <cinttypes>
21 #include "dark_mode_manager.h"
22 #include "parameter_wrap.h"
23 #include "ui_appearance_log.h"
24
25 namespace OHOS::ArkUi::UiAppearance {
26 namespace {
27 static const std::string TEMPORARY_COLOR_MODE_PARAM_STRING = "persist.uiAppearance.dark_mode_temp_state_flag.";
28 static const std::string TEMPORARY_STATE_START_TIME_PARAM_STRING =
29 "persist.uiAppearance.dark_mode_temp_state_start_time.";
30 static const std::string TEMPORARY_STATE_END_TIME_PARAM_STRING = "persist.uiAppearance.dark_mode_temp_state_end_time.";
31 static const std::string TEMPORARY_COLOR_MODE_TEMPORARY_STRING = "1";
32 static const std::string TEMPORARY_COLOR_MODE_NORMAL_STRING = "0";
33 constexpr int32_t DAY_TO_MINUTE = 24 * 60;
34 constexpr int32_t HOUR_TO_MINUTE = 60;
35 constexpr int32_t MINUTE_TO_SECOND = 60;
36 } // namespace
37
InitData(const int32_t userId)38 void TemporaryColorModeManager::InitData(const int32_t userId)
39 {
40 TempColorModeInfo info;
41 std::string temporaryColorModeValue = TEMPORARY_COLOR_MODE_NORMAL_STRING;
42 GetParameterWrap(TemporaryColorModeAssignUser(userId), temporaryColorModeValue);
43 info.tempColorMode = temporaryColorModeValue == TEMPORARY_COLOR_MODE_NORMAL_STRING
44 ? TempColorModeType::ColorModeNormal
45 : TempColorModeType::ColorModeTemp;
46 if (info.tempColorMode == TempColorModeType::ColorModeTemp) {
47 std::string startTime = "0";
48 GetParameterWrap(TemporaryStateStartTimeAssignUser(userId), startTime);
49 info.keepTemporaryStateStartTime = atoll(startTime.c_str());
50
51 std::string endTime = "0";
52 GetParameterWrap(TemporaryStateEndTimeAssignUser(userId), endTime);
53 info.keepTemporaryStateEndTime = atoll(endTime.c_str());
54 }
55 {
56 std::lock_guard guard(multiUserTempColorModeMapMutex_);
57 multiUserTempColorModeMap_[userId] = info;
58 }
59 LOGI("init temp colormode info userId:%{public}d, tempColorMode:%{public}d, keepStartTime:%{public}" PRId64
60 ", keepEndTime:%{public}" PRId64,
61 userId, static_cast<int32_t>(info.tempColorMode), info.keepTemporaryStateStartTime,
62 info.keepTemporaryStateEndTime);
63 }
64
IsColorModeTemporary(const int32_t userId)65 bool TemporaryColorModeManager::IsColorModeTemporary(const int32_t userId)
66 {
67 std::lock_guard guard(multiUserTempColorModeMapMutex_);
68 auto it = multiUserTempColorModeMap_.find(userId);
69 if (it != multiUserTempColorModeMap_.end()) {
70 return it->second.tempColorMode == TempColorModeType::ColorModeTemp;
71 }
72 return false;
73 }
IsColorModeNormal(const int32_t userId)74 bool TemporaryColorModeManager::IsColorModeNormal(const int32_t userId)
75 {
76 std::lock_guard guard(multiUserTempColorModeMapMutex_);
77 auto it = multiUserTempColorModeMap_.find(userId);
78 if (it != multiUserTempColorModeMap_.end()) {
79 return it->second.tempColorMode == TempColorModeType::ColorModeNormal;
80 }
81 return true;
82 }
SetColorModeTemporary(const int32_t userId)83 bool TemporaryColorModeManager::SetColorModeTemporary(const int32_t userId)
84 {
85 {
86 std::lock_guard guard(multiUserTempColorModeMapMutex_);
87 multiUserTempColorModeMap_[userId].tempColorMode = TempColorModeType::ColorModeTemp;
88 int32_t settingStartTime = 0;
89 int32_t settingEndTime = 0;
90 auto res = DarkModeManager::GetInstance().GetSettingTime(userId, settingStartTime, settingEndTime);
91 if (res == false) {
92 LOGE("GetSettingTime faild userId: %{public}d", userId);
93 return false;
94 }
95 GetTempColorModeTimeInfo(settingStartTime, settingEndTime,
96 multiUserTempColorModeMap_[userId].keepTemporaryStateStartTime,
97 multiUserTempColorModeMap_[userId].keepTemporaryStateEndTime);
98 }
99 SaveTempColorModeInfo(userId);
100 return true;
101 }
SetColorModeNormal(const int32_t userId)102 bool TemporaryColorModeManager::SetColorModeNormal(const int32_t userId)
103 {
104 {
105 std::lock_guard guard(multiUserTempColorModeMapMutex_);
106 multiUserTempColorModeMap_[userId].tempColorMode = TempColorModeType::ColorModeNormal;
107 multiUserTempColorModeMap_[userId].keepTemporaryStateStartTime = 0;
108 multiUserTempColorModeMap_[userId].keepTemporaryStateEndTime = 0;
109 }
110 SaveTempColorModeInfo(userId);
111 return true;
112 }
113
CheckTemporaryStateEffective(const int32_t userId)114 bool TemporaryColorModeManager::CheckTemporaryStateEffective(const int32_t userId)
115 {
116 auto checkTempStateNoTimeout = [](const int64_t startTime, const int64_t endTime) {
117 std::time_t timestampNow = std::time(nullptr);
118 if (timestampNow == static_cast<std::time_t>(-1)) {
119 LOGE("fail to get timestamp");
120 return false;
121 }
122 if (startTime < timestampNow && timestampNow < endTime) {
123 return true;
124 }
125 return false;
126 };
127
128 std::lock_guard guard(multiUserTempColorModeMapMutex_);
129 auto it = multiUserTempColorModeMap_.find(userId);
130 if (it != multiUserTempColorModeMap_.end()) {
131 if (it->second.tempColorMode == TempColorModeType::ColorModeTemp &&
132 checkTempStateNoTimeout(it->second.keepTemporaryStateStartTime, it->second.keepTemporaryStateEndTime)) {
133 return true;
134 }
135 }
136 return false;
137 }
138
TemporaryColorModeAssignUser(const int32_t userId)139 std::string TemporaryColorModeManager::TemporaryColorModeAssignUser(const int32_t userId)
140 {
141 return TEMPORARY_COLOR_MODE_PARAM_STRING + std::to_string(userId);
142 }
143
TemporaryStateStartTimeAssignUser(const int32_t userId)144 std::string TemporaryColorModeManager::TemporaryStateStartTimeAssignUser(const int32_t userId)
145 {
146 return TEMPORARY_STATE_START_TIME_PARAM_STRING + std::to_string(userId);
147 }
148
TemporaryStateEndTimeAssignUser(const int32_t userId)149 std::string TemporaryColorModeManager::TemporaryStateEndTimeAssignUser(const int32_t userId)
150 {
151 return TEMPORARY_STATE_END_TIME_PARAM_STRING + std::to_string(userId);
152 }
153
GetTempColorModeTimeInfo(const int32_t settingStartTime,const int32_t settingEndTime,int64_t & tempStateStartTime,int64_t & tempStateEndTime)154 void TemporaryColorModeManager::GetTempColorModeTimeInfo(const int32_t settingStartTime,
155 const int32_t settingEndTime, int64_t& tempStateStartTime, int64_t& tempStateEndTime)
156 {
157 auto calcEndTimestamp = [](const int32_t secondOffset, int64_t& endTimeStamp) {
158 std::time_t timestamp = std::time(nullptr);
159 if (timestamp == static_cast<std::time_t>(-1)) {
160 LOGE("fail to get timestamp");
161 return false;
162 }
163 std::tm* nowTime = std::localtime(×tamp);
164 if (nowTime != nullptr) {
165 nowTime->tm_hour = 0;
166 nowTime->tm_min = 0;
167 nowTime->tm_sec = 0;
168 }
169 std::time_t midnightTime = std::mktime(nowTime);
170 endTimeStamp = midnightTime + secondOffset - 1;
171 return true;
172 };
173
174 tempStateStartTime = static_cast<int64_t>(std::time(nullptr));
175
176 if (settingEndTime > DAY_TO_MINUTE) {
177 if (AlarmTimerManager::IsWithinTimeInterval(settingStartTime, settingEndTime) == false) {
178 /*********************************************************************
179 for example settingStartTime=20, settingEndTime=8
180 ↓(setting)
181 xxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxx
182 0 8 20 24(0) 8 20 24
183 |-----------------------------------|
184 ************************************************************************/
185 calcEndTimestamp((settingEndTime * MINUTE_TO_SECOND), tempStateEndTime);
186 } else if (TemporaryColorModeManager::IsWithInPreInterval(settingStartTime, settingEndTime)) {
187 /*********************************************************************
188 for example settingStartTime=20, settingEndTime=8
189 ↓(setting)
190 xxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxx
191 0 8 20 24(0) 8 20 24
192 |-----------------|
193 ************************************************************************/
194 calcEndTimestamp((settingStartTime * MINUTE_TO_SECOND), tempStateEndTime);
195 } else {
196 /*********************************************************************
197 for example settingStartTime=20, settingEndTime=8
198 ↓(setting)
199 xxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxx
200 0 8 20 24(0) 8 20 24
201 |-------------------------------|
202 ************************************************************************/
203 calcEndTimestamp(((settingStartTime + DAY_TO_MINUTE) * MINUTE_TO_SECOND), tempStateEndTime);
204 }
205 } else {
206 if (AlarmTimerManager::IsWithinTimeInterval(settingStartTime, settingEndTime)) {
207 /*********************************************************************
208 for example settingStartTime=11, settingEndTime=16
209 ↓(setting)
210 xxxxxxxxxx xxxxxxxxxxxx
211 0 11 16 24(0) 11 16 24
212 |-----------------------------------|
213 ************************************************************************/
214 calcEndTimestamp(((settingStartTime + DAY_TO_MINUTE) * MINUTE_TO_SECOND), tempStateEndTime);
215 } else if (TemporaryColorModeManager::IsWithInPreInterval(settingStartTime, settingEndTime)) {
216 /*********************************************************************
217 for example settingStartTime=11, settingEndTime=16
218 ↓(setting)
219 xxxxxxxxxx xxxxxxxxxxxx
220 0 11 16 24(0) 11 16 24
221 |-------------|
222 ************************************************************************/
223 calcEndTimestamp((settingEndTime * MINUTE_TO_SECOND), tempStateEndTime);
224 } else {
225 /*********************************************************************
226 for example settingStartTime=11, settingEndTime=16
227 ↓(setting)
228 xxxxxxxxxx xxxxxxxxxxxx
229 0 11 16 24(0) 11 16 24
230 |-------------------------------------|
231 ************************************************************************/
232 calcEndTimestamp(((settingEndTime + DAY_TO_MINUTE) * MINUTE_TO_SECOND), tempStateEndTime);
233 }
234 }
235 }
236
IsWithInPreInterval(const int32_t startTime,const int32_t endTime)237 bool TemporaryColorModeManager::IsWithInPreInterval(const int32_t startTime, const int32_t endTime)
238 {
239 std::time_t timestamp = std::time(nullptr);
240 if (timestamp == static_cast<std::time_t>(-1)) {
241 LOGE("fail to get timestamp");
242 return false;
243 }
244 std::tm* nowTime = std::localtime(×tamp);
245 int32_t totalMinutes { 0 };
246 if (nowTime != nullptr) {
247 totalMinutes = static_cast<int32_t>(nowTime->tm_hour * HOUR_TO_MINUTE + nowTime->tm_min);
248 }
249
250 if (totalMinutes <= startTime) {
251 return true;
252 }
253 return false;
254 }
255
SaveTempColorModeInfo(const int32_t userId)256 void TemporaryColorModeManager::SaveTempColorModeInfo(const int32_t userId)
257 {
258 TempColorModeInfo info;
259 {
260 std::lock_guard guard(multiUserTempColorModeMapMutex_);
261 info = multiUserTempColorModeMap_[userId];
262 }
263 SetParameterWrap(TemporaryColorModeAssignUser(userId), info.tempColorMode == TempColorModeType::ColorModeNormal
264 ? TEMPORARY_COLOR_MODE_NORMAL_STRING
265 : TEMPORARY_COLOR_MODE_TEMPORARY_STRING);
266 LOGI("SaveTempColorModeInfo userId:%{public}d,colorMode:%{public}d", userId,
267 static_cast<int32_t>(info.tempColorMode));
268 if (info.tempColorMode == TempColorModeType::ColorModeTemp) {
269 SetParameterWrap(TemporaryStateStartTimeAssignUser(userId), std::to_string(info.keepTemporaryStateStartTime));
270 SetParameterWrap(TemporaryStateEndTimeAssignUser(userId), std::to_string(info.keepTemporaryStateEndTime));
271 LOGI("SaveTempColorModeInfo keepStartTime:%{public}" PRId64 ",keepEndTime:%{public}" PRId64,
272 info.keepTemporaryStateStartTime, info.keepTemporaryStateEndTime);
273 }
274 }
275
276 } // namespace OHOS::ArkUi::UiAppearance
277