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