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 "rdb/starting_window_rdb_manager.h"
17
18 #include <hitrace_meter.h>
19
20 #include "ability_info.h"
21 #include "rdb/scope_guard.h"
22 #include "resource_manager.h"
23 #include "window_manager_hilog.h"
24
25 namespace OHOS {
26 namespace Rosen {
27 namespace {
28 const std::string DB_PRIMARY_KEY = "ID";
29 const std::string DB_BUNDLE_NAME = "BUNDLE_NAME";
30 const std::string DB_MODULE_NAME = "MODULE_NAME";
31 const std::string DB_ABILITY_NAME = "ABILITY_NAME";
32 const std::string DB_DARK_MODE = "DARK_MODE";
33 const std::string DB_BACKGROUND_COLOR_EARLY_VERSION = "BACKGROUND_COLOR_EARLY_VERSION";
34 const std::string DB_ICON_PATH_EARLY_VERSION = "ICON_PATH_EARLY_VERSION";
35 const std::string DB_CONFIG_FILE_ENABLED = "CONFIG_FILE_ENABLED";
36 const std::string DB_BACKGROUND_COLOR = "BACKGROUND_COLOR";
37 const std::string DB_ICON_PATH = "ICON_PATH";
38 const std::string DB_ILLUSTRATION_PATH = "ILLUSTRATION_PATH";
39 const std::string DB_BRANDING_PATH = "BRANDING_PATH";
40 const std::string DB_BACKGROUND_IMAGE_PATH = "BACKGROUND_IMAGE_PATH";
41 const std::string DB_BACKGROUND_IMAGE_FIT = "BACKGROUND_IMAGE_FIT";
42 const std::string DB_STARTWINDOW_TYPE = "STARTWINDOW_TYPE";
43 constexpr int32_t DB_PRIMARY_KEY_INDEX = 0;
44 constexpr int32_t DB_BUNDLE_NAME_INDEX = 1;
45 constexpr int32_t DB_MODULE_NAME_INDEX = 2;
46 constexpr int32_t DB_ABILITY_NAME_INDEX = 3;
47 constexpr int32_t DB_DARK_MODE_INDEX = 4;
48 constexpr int32_t DB_BACKGROUND_COLOR_EARLY_VERSION_INDEX = 5;
49 constexpr int32_t DB_ICON_PATH_EARLY_VERSION_INDEX = 6;
50 constexpr int32_t DB_CONFIG_FILE_ENABLED_INDEX = 7;
51 constexpr int32_t DB_BACKGROUND_COLOR_INDEX = 8;
52 constexpr int32_t DB_ICON_PATH_INDEX = 9;
53 constexpr int32_t DB_ILLUSTRATION_PATH_INDEX = 10;
54 constexpr int32_t DB_BRANDING_PATH_INDEX = 11;
55 constexpr int32_t DB_BACKGROUND_IMAGE_PATH_INDEX = 12;
56 constexpr int32_t DB_BACKGROUND_IMAGE_FIT_INDEX = 13;
57 constexpr int32_t DB_STARTWINDOW_TYPE_INDEX = 14;
58 constexpr const char* PROFILE_PREFIX = "$profile:";
59 constexpr uint16_t MAX_JSON_STRING_LENGTH = 4096;
60 constexpr int32_t DEFAULT_ROW_COUNT = -1;
61
BuildValuesBucket(const StartingWindowRdbItemKey & key,const StartingWindowInfo & value)62 NativeRdb::ValuesBucket BuildValuesBucket(const StartingWindowRdbItemKey& key, const StartingWindowInfo& value)
63 {
64 NativeRdb::ValuesBucket valuesBucket;
65 valuesBucket.PutString(DB_BUNDLE_NAME, key.bundleName);
66 valuesBucket.PutString(DB_MODULE_NAME, key.moduleName);
67 valuesBucket.PutString(DB_ABILITY_NAME, key.abilityName);
68 valuesBucket.PutBool(DB_DARK_MODE, key.darkMode);
69 valuesBucket.PutInt(DB_BACKGROUND_COLOR_EARLY_VERSION, value.backgroundColorEarlyVersion_);
70 valuesBucket.PutString(DB_ICON_PATH_EARLY_VERSION, value.iconPathEarlyVersion_);
71 valuesBucket.PutBool(DB_CONFIG_FILE_ENABLED, value.configFileEnabled_);
72 valuesBucket.PutInt(DB_BACKGROUND_COLOR, value.backgroundColor_);
73 valuesBucket.PutString(DB_ICON_PATH, value.iconPath_);
74 valuesBucket.PutString(DB_ILLUSTRATION_PATH, value.illustrationPath_);
75 valuesBucket.PutString(DB_BRANDING_PATH, value.brandingPath_);
76 valuesBucket.PutString(DB_BACKGROUND_IMAGE_PATH, value.backgroundImagePath_);
77 valuesBucket.PutString(DB_BACKGROUND_IMAGE_FIT, value.backgroundImageFit_);
78 valuesBucket.PutString(DB_STARTWINDOW_TYPE, value.startWindowType_);
79 return valuesBucket;
80 }
81
BuildPredicates(const std::string tableName,const StartingWindowRdbItemKey & key)82 NativeRdb::AbsRdbPredicates BuildPredicates(const std::string tableName, const StartingWindowRdbItemKey& key)
83 {
84 NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
85 absRdbPredicates.EqualTo(DB_BUNDLE_NAME, key.bundleName)->And()->
86 EqualTo(DB_MODULE_NAME, key.moduleName)->And()->
87 EqualTo(DB_ABILITY_NAME, key.abilityName)->And()->
88 EqualTo(DB_DARK_MODE, key.darkMode);
89 return absRdbPredicates;
90 }
91
CheckRdbResult(int resCode)92 bool CheckRdbResult(int resCode)
93 {
94 if (resCode != NativeRdb::E_OK) {
95 TLOGE(WmsLogTag::WMS_PATTERN, "rdb failed, ret:%{public}d", resCode);
96 return false;
97 }
98 return true;
99 }
100 } // namespace
101
StartingWindowRdbManager(const WmsRdbConfig & wmsRdbConfig)102 StartingWindowRdbManager::StartingWindowRdbManager(const WmsRdbConfig& wmsRdbConfig)
103 : wmsRdbConfig_(wmsRdbConfig)
104 {
105 std::string uniqueConstraint = std::string("CONSTRAINT uniqueConstraint UNIQUE (" +
106 DB_BUNDLE_NAME + ", " + DB_MODULE_NAME + ", " + DB_ABILITY_NAME + ", " + DB_DARK_MODE + ")");
107 wmsRdbConfig_.createTableSql = std::string("CREATE TABLE IF NOT EXISTS " + wmsRdbConfig_.tableName +
108 "(" + DB_PRIMARY_KEY + " INTEGER PRIMARY KEY AUTOINCREMENT, " + DB_BUNDLE_NAME + " TEXT NOT NULL, " +
109 DB_MODULE_NAME + " TEXT NOT NULL, " + DB_ABILITY_NAME + " TEXT NOT NULL, " + DB_DARK_MODE + " BOOLEAN, " +
110 DB_BACKGROUND_COLOR_EARLY_VERSION + " INTEGER, " + DB_ICON_PATH_EARLY_VERSION + " TEXT, " +
111 DB_CONFIG_FILE_ENABLED + " BOOLEAN, " + DB_BACKGROUND_COLOR + " INTEGER, " + DB_ICON_PATH + " TEXT, " +
112 DB_ILLUSTRATION_PATH + " TEXT, " + DB_BRANDING_PATH + " TEXT, " +
113 DB_BACKGROUND_IMAGE_PATH + " TEXT, " + DB_BACKGROUND_IMAGE_FIT + " TEXT, " +
114 DB_STARTWINDOW_TYPE + " TEXT, " + uniqueConstraint + ");");
115 }
116
~StartingWindowRdbManager()117 StartingWindowRdbManager::~StartingWindowRdbManager()
118 {
119 ClearRdbStore();
120 }
121
ClearRdbStore()122 void StartingWindowRdbManager::ClearRdbStore()
123 {
124 std::lock_guard<std::mutex> lock(rdbMutex_);
125 rdbStore_ = nullptr;
126 }
127
GetRdbStore()128 std::shared_ptr<NativeRdb::RdbStore> StartingWindowRdbManager::GetRdbStore()
129 {
130 std::lock_guard<std::mutex> lock(rdbMutex_);
131 if (rdbStore_ != nullptr) {
132 return rdbStore_;
133 }
134 NativeRdb::RdbStoreConfig rdbStoreConfig(wmsRdbConfig_.dbPath + wmsRdbConfig_.dbName);
135 rdbStoreConfig.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
136 int32_t resCode = NativeRdb::E_OK;
137 WmsRdbOpenCallback wmsCallback(wmsRdbConfig_);
138 rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(
139 rdbStoreConfig, wmsRdbConfig_.version, wmsCallback, resCode);
140 TLOGI(WmsLogTag::WMS_PATTERN, "resCode: %{public}d, version: %{public}d",
141 resCode, wmsRdbConfig_.version);
142 return rdbStore_;
143 }
144
Init()145 bool StartingWindowRdbManager::Init()
146 {
147 auto rdbStore = GetRdbStore();
148 if (rdbStore == nullptr) {
149 TLOGE(WmsLogTag::WMS_PATTERN, "failed");
150 return false;
151 }
152 return true;
153 }
154
InsertData(const StartingWindowRdbItemKey & key,const StartingWindowInfo & value)155 bool StartingWindowRdbManager::InsertData(const StartingWindowRdbItemKey& key, const StartingWindowInfo& value)
156 {
157 auto rdbStore = GetRdbStore();
158 if (rdbStore == nullptr) {
159 TLOGE(WmsLogTag::WMS_PATTERN, "RdbStore is null");
160 return false;
161 }
162 int64_t rowId = -1;
163 auto valuesBucket = BuildValuesBucket(key, value);
164 auto ret = rdbStore->InsertWithConflictResolution(
165 rowId, wmsRdbConfig_.tableName, valuesBucket, NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
166 return CheckRdbResult(ret);
167 }
168
BatchInsert(int64_t & outInsertNum,const std::vector<std::pair<StartingWindowRdbItemKey,StartingWindowInfo>> & inputValues)169 bool StartingWindowRdbManager::BatchInsert(int64_t& outInsertNum,
170 const std::vector<std::pair<StartingWindowRdbItemKey, StartingWindowInfo>>& inputValues)
171 {
172 auto rdbStore = GetRdbStore();
173 if (rdbStore == nullptr) {
174 TLOGE(WmsLogTag::WMS_PATTERN, "RdbStore is null");
175 return false;
176 }
177 std::vector<NativeRdb::ValuesBucket> valuesBuckets;
178 for (const auto& pair : inputValues) {
179 auto valuesBucket = BuildValuesBucket(pair.first, pair.second);
180 valuesBuckets.emplace_back(valuesBucket);
181 }
182 auto ret = rdbStore->BatchInsert(outInsertNum, wmsRdbConfig_.tableName, valuesBuckets);
183 return CheckRdbResult(ret);
184 }
185
DeleteDataByBundleName(const std::string & bundleName)186 bool StartingWindowRdbManager::DeleteDataByBundleName(const std::string& bundleName)
187 {
188 auto rdbStore = GetRdbStore();
189 if (rdbStore == nullptr) {
190 TLOGE(WmsLogTag::WMS_PATTERN, "RdbStore is null");
191 return false;
192 }
193 int32_t deletedRows = DEFAULT_ROW_COUNT;
194 NativeRdb::AbsRdbPredicates absRdbPredicates(wmsRdbConfig_.tableName);
195 absRdbPredicates.EqualTo(DB_BUNDLE_NAME, bundleName);
196 auto ret = rdbStore->Delete(deletedRows, absRdbPredicates);
197 return CheckRdbResult(ret);
198 }
199
DeleteAllData()200 bool StartingWindowRdbManager::DeleteAllData()
201 {
202 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ssm:DeleteAllData");
203 auto rdbStore = GetRdbStore();
204 if (rdbStore == nullptr) {
205 TLOGE(WmsLogTag::WMS_PATTERN, "RdbStore is null");
206 return false;
207 }
208 int32_t deletedRows = DEFAULT_ROW_COUNT;
209 NativeRdb::AbsRdbPredicates absRdbPredicates(wmsRdbConfig_.tableName);
210 auto ret = rdbStore->Delete(deletedRows, absRdbPredicates);
211 return CheckRdbResult(ret);
212 }
213
QueryData(const StartingWindowRdbItemKey & key,StartingWindowInfo & value)214 bool StartingWindowRdbManager::QueryData(const StartingWindowRdbItemKey& key, StartingWindowInfo& value)
215 {
216 auto rdbStore = GetRdbStore();
217 if (rdbStore == nullptr) {
218 TLOGE(WmsLogTag::WMS_PATTERN, "RdbStore is null");
219 return false;
220 }
221 auto absRdbPredicates = BuildPredicates(wmsRdbConfig_.tableName, key);
222 auto absSharedResultSet = rdbStore->QueryByStep(absRdbPredicates, std::vector<std::string>());
223 if (absSharedResultSet == nullptr) {
224 TLOGE(WmsLogTag::WMS_PATTERN, "absSharedResultSet failed");
225 return false;
226 }
227 ScopeGuard stateGuard([&] { absSharedResultSet->Close(); });
228 auto ret = absSharedResultSet->GoToFirstRow();
229 if (ret != NativeRdb::E_OK) {
230 TLOGE(WmsLogTag::WMS_PATTERN, "GoToFirstRow failed, ret:%{public}d", ret);
231 return false;
232 }
233 int backgroundColorEarlyVersion = 0;
234 int backgroundColor = 0;
235 int configFileEnabled = 0;
236 if (!CheckRdbResult(absSharedResultSet->GetInt(
237 DB_BACKGROUND_COLOR_EARLY_VERSION_INDEX, backgroundColorEarlyVersion)) ||
238 !CheckRdbResult(absSharedResultSet->GetString(
239 DB_ICON_PATH_EARLY_VERSION_INDEX, value.iconPathEarlyVersion_)) ||
240 !CheckRdbResult(absSharedResultSet->GetInt(DB_BACKGROUND_COLOR_INDEX, backgroundColor)) ||
241 !CheckRdbResult(absSharedResultSet->GetString(DB_ICON_PATH_INDEX, value.iconPath_)) ||
242 !CheckRdbResult(absSharedResultSet->GetInt(DB_CONFIG_FILE_ENABLED_INDEX, configFileEnabled)) ||
243 !CheckRdbResult(absSharedResultSet->GetString(DB_ILLUSTRATION_PATH_INDEX, value.illustrationPath_)) ||
244 !CheckRdbResult(absSharedResultSet->GetString(DB_BRANDING_PATH_INDEX, value.brandingPath_)) ||
245 !CheckRdbResult(absSharedResultSet->GetString(DB_BACKGROUND_IMAGE_PATH_INDEX, value.backgroundImagePath_)) ||
246 !CheckRdbResult(absSharedResultSet->GetString(DB_BACKGROUND_IMAGE_FIT_INDEX, value.backgroundImageFit_)) ||
247 !CheckRdbResult(absSharedResultSet->GetString(DB_STARTWINDOW_TYPE_INDEX, value.startWindowType_))) {
248 return false;
249 }
250 value.backgroundColorEarlyVersion_ = static_cast<uint32_t>(backgroundColorEarlyVersion);
251 value.backgroundColor_ = static_cast<uint32_t>(backgroundColor);
252 value.configFileEnabled_ = configFileEnabled;
253 return true;
254 }
255
GetStartWindowValFromProfile(const AppExecFwk::AbilityInfo & abilityInfo,const std::shared_ptr<Global::Resource::ResourceManager> & resourceMgr,const std::string & key,const std::string & defaultVal)256 std::string StartingWindowRdbManager::GetStartWindowValFromProfile(const AppExecFwk::AbilityInfo& abilityInfo,
257 const std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr,
258 const std::string& key, const std::string& defaultVal)
259 {
260 auto pos = abilityInfo.startWindow.find(PROFILE_PREFIX);
261 if (pos == std::string::npos) {
262 TLOGD(WmsLogTag::WMS_PATTERN, "invalid profile");
263 return defaultVal;
264 }
265 std::string startWindowName = abilityInfo.startWindow.substr(pos + strlen(PROFILE_PREFIX));
266 std::unique_ptr<uint8_t[]> fileContentPtr = nullptr;
267 size_t len = 0;
268 if (resourceMgr->GetProfileDataByName(startWindowName.c_str(), len, fileContentPtr) !=
269 Global::Resource::RState::SUCCESS) {
270 TLOGE(WmsLogTag::WMS_PATTERN, "getProfileData failed");
271 return defaultVal;
272 }
273 if (fileContentPtr == nullptr || len == 0) {
274 TLOGE(WmsLogTag::WMS_PATTERN, "invalid data");
275 return defaultVal;
276 }
277 std::string rawData(fileContentPtr.get(), fileContentPtr.get() + len);
278 if (!nlohmann::json::accept(rawData)) {
279 TLOGE(WmsLogTag::WMS_PATTERN, "rawData failed");
280 return defaultVal;
281 }
282 nlohmann::json profileJson = nlohmann::json::parse(rawData);
283 if (profileJson.is_discarded()) {
284 TLOGE(WmsLogTag::WMS_PATTERN, "bad profile file");
285 return defaultVal;
286 }
287 if (profileJson.find(key) == profileJson.end()) {
288 TLOGE(WmsLogTag::WMS_PATTERN, "the default value is %{public}s", defaultVal.c_str());
289 return defaultVal;
290 }
291 if (!profileJson.at(key).is_string()) {
292 TLOGE(WmsLogTag::WMS_PATTERN, "the default value is not string");
293 return defaultVal;
294 }
295 std::string res = profileJson.at(key).get<std::string>();
296 if (res.empty() || res.length() > MAX_JSON_STRING_LENGTH) {
297 TLOGE(WmsLogTag::WMS_PATTERN, "exceeding the maximum string length");
298 return defaultVal;
299 }
300 TLOGI(WmsLogTag::WMS_PATTERN, "startWindowType: %{public}s", res.c_str());
301 return res;
302 }
303 } // namespace Rosen
304 } // namespace OHOS