1 /*
2 * Copyright (c) 2023 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 "bundle_resource_callback.h"
17
18 #include <fstream>
19
20 #include "account_helper.h"
21 #include "bundle_constants.h"
22 #include "bundle_parser.h"
23 #include "bundle_resource_constants.h"
24 #include "bundle_resource_manager.h"
25 #ifdef GLOBAL_RESMGR_ENABLE
26 #include "resource_manager.h"
27 #endif
28 namespace OHOS {
29 namespace AppExecFwk {
30 std::mutex BundleResourceCallback::userFileMutex_;
31
OnUserIdSwitched(const int32_t oldUserId,const int32_t userId,const uint32_t type)32 bool BundleResourceCallback::OnUserIdSwitched(const int32_t oldUserId, const int32_t userId, const uint32_t type)
33 {
34 APP_LOGI("start, oldUserId:%{public}d to newUserId:%{public}d no need to process", oldUserId, userId);
35 return true;
36 }
37
OnSystemColorModeChanged(const std::string & colorMode,const uint32_t type)38 bool BundleResourceCallback::OnSystemColorModeChanged(const std::string &colorMode, const uint32_t type)
39 {
40 APP_LOGI("start, colorMode: %{public}s", colorMode.c_str());
41 if (colorMode == BundleSystemState::GetInstance().GetSystemColorMode()) {
42 APP_LOGD("colorMode: %{public}s no change", colorMode.c_str());
43 return true;
44 }
45 APP_LOGI("end, colorMode: %{public}s", colorMode.c_str());
46 return true;
47 }
48
OnSystemLanguageChange(const std::string & language,const uint32_t type)49 bool BundleResourceCallback::OnSystemLanguageChange(const std::string &language, const uint32_t type)
50 {
51 APP_LOGI("start, language %{public}s", language.c_str());
52 if (language == BundleSystemState::GetInstance().GetSystemLanguage()) {
53 APP_LOGD("current language is %{public}s no change", language.c_str());
54 return true;
55 }
56 int32_t currentUserId = AccountHelper::GetCurrentActiveUserId();
57 if (currentUserId <= 0) {
58 currentUserId = Constants::START_USERID;
59 }
60 SetConfigInFile(language, "", -1, -1, type, currentUserId);
61 BundleSystemState::GetInstance().SetSystemLanguage(language);
62 // need delete all and reload all
63 auto manager = DelayedSingleton<BundleResourceManager>::GetInstance();
64 if (manager == nullptr) {
65 APP_LOGE("manager is nullptr");
66 return false;
67 }
68
69 if (!manager->AddAllResourceInfo(currentUserId, type)) {
70 APP_LOGE("AddAllResourceInfo currentUserId %{public}d failed", currentUserId);
71 return false;
72 }
73 DeleteConfigInFile(currentUserId, type);
74 APP_LOGI("end, language %{public}s", language.c_str());
75 return true;
76 }
77
OnApplicationThemeChanged(const std::string & theme,const int32_t themeId,const int32_t themeIcon,const uint32_t type)78 bool BundleResourceCallback::OnApplicationThemeChanged(const std::string &theme,
79 const int32_t themeId, const int32_t themeIcon, const uint32_t type)
80 {
81 APP_LOGI("start, theme:%{public}s, themeId:%{public}d", theme.c_str(), themeId);
82 if (theme.empty()) {
83 APP_LOGW("theme is empty, no need to change");
84 return false;
85 }
86
87 nlohmann::json jsonObject = nlohmann::json::parse(theme, nullptr, false);
88 if (jsonObject.is_discarded()) {
89 APP_LOGE("failed parse theme %{public}s", theme.c_str());
90 return false;
91 }
92 const auto &jsonObjectEnd = jsonObject.end();
93 int32_t parseResult = ERR_OK;
94 int32_t updateIcons = 0;
95 GetValueIfFindKey<int32_t>(jsonObject, jsonObjectEnd, "icons", updateIcons,
96 JsonType::NUMBER, false, parseResult, ArrayType::NOT_ARRAY);
97 if (updateIcons == 0) {
98 APP_LOGI("icons no need to change, return");
99 return false;
100 }
101 int32_t currentUserId = AccountHelper::GetCurrentActiveUserId();
102 if (currentUserId <= 0) {
103 currentUserId = Constants::START_USERID;
104 }
105 SetConfigInFile("", theme, themeId, themeIcon, type, currentUserId);
106 #ifdef GLOBAL_RESMGR_ENABLE
107 if (!SetThemeParamForThemeChanged(themeId, themeIcon)) {
108 APP_LOGE("set theme param failed, themeId %{public}d themeIcon %{public}d", themeId, themeIcon);
109 }
110 #endif
111
112 auto manager = DelayedSingleton<BundleResourceManager>::GetInstance();
113 if (manager == nullptr) {
114 APP_LOGE("manager is nullptr");
115 return false;
116 }
117
118 if (!manager->AddAllResourceInfo(currentUserId, type)) {
119 APP_LOGE("AddAllResourceInfo currentUserId %{public}d failed", currentUserId);
120 return false;
121 }
122 DeleteConfigInFile(currentUserId, type);
123 APP_LOGI("end, theme:%{public}s", theme.c_str());
124 return true;
125 }
126
OnOverlayStatusChanged(const std::string & bundleName,bool isEnabled,int32_t userId)127 bool BundleResourceCallback::OnOverlayStatusChanged(
128 const std::string &bundleName,
129 bool isEnabled,
130 int32_t userId)
131 {
132 APP_LOGI("start, bundleName:%{public}s, isEnabled:%{public}d, userId:%{public}d",
133 bundleName.c_str(), isEnabled, userId);
134 int32_t currentUserId = AccountHelper::GetCurrentActiveUserId();
135 if ((currentUserId > 0) && (userId != currentUserId)) {
136 APP_LOGW("userId:%{public}d current:%{public}d not same", currentUserId, userId);
137 return false;
138 }
139 auto manager = DelayedSingleton<BundleResourceManager>::GetInstance();
140 if (manager == nullptr) {
141 APP_LOGE("manager is nullptr");
142 return false;
143 }
144 std::string targetBundleName = bundleName;
145 manager->GetTargetBundleName(bundleName, targetBundleName);
146 APP_LOGI("bundleName:%{public}s, targetBundleName:%{public}s overlay changed", bundleName.c_str(),
147 targetBundleName.c_str());
148 if (!manager->AddResourceInfoByBundleNameWhenUpdate(targetBundleName, userId)) {
149 APP_LOGE("add resource failed %{public}s", targetBundleName.c_str());
150 return false;
151 }
152 APP_LOGI("end, targetBundleName:%{public}s, isEnabled:%{public}d, userId:%{public}d",
153 targetBundleName.c_str(), isEnabled, userId);
154 return true;
155 }
156
SetThemeParamForThemeChanged(const int32_t themeId,const int32_t themeIcon)157 bool BundleResourceCallback::SetThemeParamForThemeChanged(const int32_t themeId, const int32_t themeIcon)
158 {
159 if (themeId <= 0) {
160 return false;
161 }
162 #ifdef GLOBAL_RESMGR_ENABLE
163 auto resourcePtr = std::shared_ptr<Global::Resource::ResourceManager>(Global::Resource::CreateResourceManager());
164 if (resourcePtr == nullptr) {
165 APP_LOGE("resource is nullptr, themeId %{public}d themeIcon %{public}d", themeId, themeIcon);
166 return false;
167 }
168 int32_t currentUserId = AccountHelper::GetCurrentActiveUserId();
169 if (currentUserId <= 0) {
170 APP_LOGW("currentUserId get failed");
171 currentUserId = Constants::START_USERID;
172 }
173 resourcePtr->userId = currentUserId;
174 APP_LOGI("start set themeId %{public}d userId %{public}d themeIcon %{public}d",
175 themeId, currentUserId, themeIcon);
176 std::unique_ptr<Global::Resource::ResConfig> resConfig(Global::Resource::CreateResConfig());
177 if (resConfig == nullptr) {
178 APP_LOGE("resConfig is nullptr, themeId %{public}d themeIcon %{public}d", themeId, themeIcon);
179 return false;
180 }
181 resConfig->SetThemeId(themeId);
182 resConfig->SetThemeIcon(themeIcon > 0 ? true : false);
183 Global::Resource::RState ret = resourcePtr->UpdateResConfig(*resConfig); // no need to process ret
184 if (ret != Global::Resource::RState::SUCCESS) {
185 APP_LOGW("UpdateResConfig ret %{public}d, themeId %{public}d, themeIcon %{public}d",
186 static_cast<int32_t>(ret), themeId, themeIcon);
187 }
188 APP_LOGI("end set themeId %{public}d themeIcon %{public}d", themeId, themeIcon);
189 #endif
190 return true;
191 }
192
SetUserId(const int32_t userId)193 void BundleResourceCallback::SetUserId(const int32_t userId)
194 {
195 std::string path = std::string(BundleResourceConstants::BUNDLE_RESOURCE_RDB_PATH) +
196 std::string(BundleResourceConstants::USER_FILE_NAME);
197 nlohmann::json jsonBuf;
198 if (!BundleParser::ReadFileIntoJson(path, jsonBuf)) {
199 APP_LOGW("read user file failed, errno %{public}d", errno);
200 }
201 std::ofstream out(path, std::ios::out);
202 if (!out.is_open()) {
203 APP_LOGE("open user file failed, errno:%{public}d", errno);
204 return;
205 }
206 jsonBuf[BundleResourceConstants::USER] = userId;
207 out << jsonBuf.dump();
208 out.close();
209 }
210
DeleteConfigInFile(const int32_t userId,const uint32_t type)211 void BundleResourceCallback::DeleteConfigInFile(const int32_t userId, const uint32_t type)
212 {
213 std::string path = std::string(BundleResourceConstants::BUNDLE_RESOURCE_RDB_PATH) +
214 std::string(BundleResourceConstants::USER_FILE_NAME);
215 nlohmann::json jsonBuf;
216 std::lock_guard<std::mutex> lock(userFileMutex_);
217 if (!BundleParser::ReadFileIntoJson(path, jsonBuf)) {
218 APP_LOGW("read user file failed, errno %{public}d", errno);
219 return;
220 }
221 std::string key;
222 if (type == static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_LANGUE_CHANGE)) {
223 key = std::string(BundleResourceConstants::LANGUAGE) +
224 std::string(BundleResourceConstants::UNDER_LINE) + std::to_string(userId);
225 } else if (type == static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_THEME_CHANGE)) {
226 key = std::string(BundleResourceConstants::THEME) +
227 std::string(BundleResourceConstants::UNDER_LINE) + std::to_string(userId);
228 } else {
229 return;
230 }
231 auto it = jsonBuf.find(key);
232 if (it == jsonBuf.end()) {
233 return;
234 }
235 jsonBuf.erase(it);
236 std::ofstream out(path, std::ios::out);
237 if (!out.is_open()) {
238 APP_LOGE("open user file failed, errno:%{public}d", errno);
239 return;
240 }
241 out << jsonBuf.dump();
242 out.close();
243 APP_LOGI("-u %{public}d -t %{public}d delete config success.", userId, type);
244 }
245
SetConfigInFile(const std::string & language,const std::string & theme,const int32_t id,const int32_t themeIcon,const uint32_t type,const int32_t userId)246 void BundleResourceCallback::SetConfigInFile(const std::string &language, const std::string &theme,
247 const int32_t id, const int32_t themeIcon, const uint32_t type, const int32_t userId)
248 {
249 std::string path = std::string(BundleResourceConstants::BUNDLE_RESOURCE_RDB_PATH) +
250 std::string(BundleResourceConstants::USER_FILE_NAME);
251 nlohmann::json jsonBuf;
252 std::lock_guard<std::mutex> lock(userFileMutex_);
253 if (!BundleParser::ReadFileIntoJson(path, jsonBuf)) {
254 APP_LOGW("read user file failed, errno %{public}d", errno);
255 }
256 if (jsonBuf.is_discarded()) {
257 APP_LOGW("bad profile file %{public}s", path.c_str());
258 return;
259 }
260 FILE *out = fopen(path.c_str(), "w");
261 if (out == nullptr) {
262 APP_LOGE("fopen %{public}s failed", path.c_str());
263 return;
264 }
265 nlohmann::json config;
266 if (type == static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_LANGUE_CHANGE)) {
267 config[BundleResourceConstants::LANGUAGE] = language;
268 config[BundleResourceConstants::USER] = userId;
269 config[BundleResourceConstants::TYPE] = type;
270 std::string key = std::string(BundleResourceConstants::LANGUAGE) +
271 std::string(BundleResourceConstants::UNDER_LINE) + std::to_string(userId);
272 jsonBuf[key] = config;
273 } else if (type == static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_THEME_CHANGE)) {
274 config[BundleResourceConstants::THEME] = theme;
275 config[BundleResourceConstants::THEME_ID] = id;
276 config[BundleResourceConstants::THEME_ICON] = themeIcon;
277 config[BundleResourceConstants::USER] = userId;
278 config[BundleResourceConstants::TYPE] = type;
279 std::string key = std::string(BundleResourceConstants::THEME) +
280 std::string(BundleResourceConstants::UNDER_LINE) + std::to_string(userId);
281 jsonBuf[key] = config;
282 } else {
283 (void)fclose(out);
284 return;
285 }
286
287 if (fputs(jsonBuf.dump().c_str(), out) == EOF) {
288 APP_LOGE("fputs %{public}s failed", path.c_str());
289 (void)fclose(out);
290 return;
291 }
292 (void)fsync(fileno(out));
293 (void)fclose(out);
294 APP_LOGI("-u %{public}d -t %{public}d save config success.", userId, type);
295 }
296 } // AppExecFwk
297 } // OHOS
298