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 #include "feature/bundle_distributed/form_distributed_mgr.h"
16
17 #include "fms_log_wrapper.h"
18 #include "form_mgr_errors.h"
19 #include "common/util/scope_guard.h"
20
21 namespace OHOS {
22 namespace AppExecFwk {
23 namespace {
24 const std::string DISTRIBUTED_FORM_BUNDLE_TABLE = "distributed_form_bundle_table";
25 constexpr int32_t KEY_INDEX = 0;
26 constexpr int32_t USERID_INDEX = 1;
27 constexpr int32_t ENTRYMODULE_INDEX = 2;
28 constexpr int32_t UIMODULE_INDEX = 3;
29 constexpr int32_t VALUE_INDEX = 4;
30 constexpr const char* KEY = "KEY"; // KEY = BUNDLENAME + USERID
31 constexpr const char* USERID = "USERID";
32 constexpr const char* ENTRYMODULE = "ENTRYMODULE";
33 constexpr const char* UIMODULE = "UIMODULE";
34 constexpr const char* VALUE = "VALUE";
35 }
36
FormDistributedMgr()37 FormDistributedMgr::FormDistributedMgr()
38 {
39 HILOG_INFO("Create");
40 }
41
~FormDistributedMgr()42 FormDistributedMgr::~FormDistributedMgr()
43 {
44 HILOG_INFO("Destroy");
45 }
46
47 const static std::map<std::string, std::string> tableExtraColumns_ = {
48 { USERID, "INTEGER" },
49 { ENTRYMODULE, "TEXT" },
50 { UIMODULE, "TEXT" },
51 { VALUE, "TEXT" },
52 };
53
Start()54 void FormDistributedMgr::Start()
55 {
56 HILOG_INFO("Start");
57 Init();
58 }
59
Init()60 bool FormDistributedMgr::Init()
61 {
62 FormRdbTableConfig formRdbTableConfig;
63 formRdbTableConfig.tableName = DISTRIBUTED_FORM_BUNDLE_TABLE;
64 formRdbTableConfig.createTableSql = "CREATE TABLE IF NOT EXISTS " + formRdbTableConfig.tableName
65 + " (KEY TEXT NOT NULL PRIMARY KEY, USERID INTEGER, ENTRYMODULE TEXT, UIMODULE TEXT, VALUE TEXT);";
66 if (FormRdbDataMgr::GetInstance().InitFormRdbTable(formRdbTableConfig) != ERR_OK) {
67 HILOG_ERROR("Form bundle distributed mgr init form rdb table fail");
68 return false;
69 }
70
71 AlterTableAddColumn();
72
73 LoadDataFromDb();
74
75 isInitialized_ = true;
76 HILOG_INFO("initialized");
77 return true;
78 }
79
IsBundleDistributed(const std::string & bundleName,int32_t userId)80 bool FormDistributedMgr::IsBundleDistributed(const std::string &bundleName, int32_t userId)
81 {
82 if (bundleName.empty() || userId == Constants::INVALID_USER_ID) {
83 HILOG_ERROR("invalid bundleName or userId, userId:%{public}d", userId);
84 return false;
85 }
86
87 if (!IsBundleDistributedInit()) {
88 HILOG_ERROR("distributed mgr init failed, get status error");
89 return false;
90 }
91
92 std::shared_lock<std::shared_mutex> lock(bundleDistributedMapMutex_);
93 auto iter = distributedBundleMap_.find(bundleName + std::to_string(userId));
94 return iter != distributedBundleMap_.end();
95 }
96
SetBundleDistributedStatus(const std::string & bundleName,bool isDistributed,const DistributedModule & distributedModule)97 void FormDistributedMgr::SetBundleDistributedStatus(
98 const std::string &bundleName, bool isDistributed, const DistributedModule &distributedModule)
99 {
100 if (bundleName.empty()) {
101 HILOG_ERROR("invalid bundleName");
102 return;
103 }
104
105 if (!isInitialized_ && !Init()) {
106 HILOG_ERROR("Form bundle distributed mgr not init");
107 return;
108 }
109
110 std::unique_lock<std::shared_mutex> lock(bundleDistributedMapMutex_);
111 HILOG_INFO("set bundle: %{public}s distributed status: %{public}d, userId:%{public}d",
112 bundleName.c_str(), isDistributed, distributedModule.userId);
113 std::string key = bundleName + std::to_string(distributedModule.userId);
114 auto iter = distributedBundleMap_.find(key);
115 if (isDistributed && distributedModule.userId != Constants::INVALID_USER_ID) {
116 distributedBundleMap_[key] = distributedModule;
117 SaveDataToDb(bundleName, distributedModule);
118 } else if (!isDistributed && iter != distributedBundleMap_.end()) {
119 distributedBundleMap_.erase(key);
120 DeleteDataInDb(bundleName, distributedModule.userId);
121 }
122 }
123
IsBundleDistributedInit()124 bool FormDistributedMgr::IsBundleDistributedInit()
125 {
126 std::unique_lock<std::shared_mutex> lock(bundleDistributedMapMutex_);
127 if (!isInitialized_ && !Init()) {
128 HILOG_ERROR("Form bundle distributed mgr not init");
129 return false;
130 }
131 return true;
132 }
133
AlterTableAddColumn()134 void FormDistributedMgr::AlterTableAddColumn()
135 {
136 static const std::vector<std::string> columns = { USERID, ENTRYMODULE, UIMODULE, VALUE };
137 std::string sql;
138 for (const auto &iter : columns) {
139 auto it = tableExtraColumns_.find(iter);
140 if (it == tableExtraColumns_.end()) {
141 return;
142 }
143 sql = "ALTER TABLE " + DISTRIBUTED_FORM_BUNDLE_TABLE + " ADD COLUMN " + it->first + " " + it->second;
144 FormRdbDataMgr::GetInstance().ExecuteSql(sql);
145 }
146 }
147
GetUiModuleName(const std::string & bundleName,int32_t userId)148 std::string FormDistributedMgr::GetUiModuleName(const std::string &bundleName, int32_t userId)
149 {
150 if (bundleName.empty() || userId == Constants::INVALID_USER_ID) {
151 HILOG_ERROR("invalid bundleName or userId, userId:%{public}d", userId);
152 return "";
153 }
154
155 if (!IsBundleDistributedInit()) {
156 HILOG_ERROR("distributed mgr init failed, get uiModuleName error");
157 return "";
158 }
159
160 std::shared_lock<std::shared_mutex> lock(bundleDistributedMapMutex_);
161 auto iter = distributedBundleMap_.find(bundleName + std::to_string(userId));
162 return iter != distributedBundleMap_.end() ? iter->second.uiModule : "";
163 }
164
LoadDataFromDb()165 void FormDistributedMgr::LoadDataFromDb()
166 {
167 NativeRdb::AbsRdbPredicates absRdbPredicates(DISTRIBUTED_FORM_BUNDLE_TABLE);
168 auto absSharedResultSet = FormRdbDataMgr::GetInstance().QueryData(absRdbPredicates);
169 if (absSharedResultSet == nullptr) {
170 HILOG_ERROR("get distributed db data failed");
171 return;
172 }
173
174 ScopeGuard stateGuard([absSharedResultSet] {
175 if (absSharedResultSet) {
176 absSharedResultSet->Close();
177 }
178 });
179 if (!absSharedResultSet->HasBlock()) {
180 HILOG_ERROR("absSharedResultSet has no block");
181 return;
182 }
183
184 int32_t ret = absSharedResultSet->GoToFirstRow();
185 if (ret == NativeRdb::E_OK) {
186 do {
187 std::string key;
188 ret += absSharedResultSet->GetString(KEY_INDEX, key);
189
190 DistributedModule distributedModule;
191 ret += absSharedResultSet->GetInt(USERID_INDEX, distributedModule.userId);
192 ret += absSharedResultSet->GetString(ENTRYMODULE_INDEX, distributedModule.entryModule);
193 ret += absSharedResultSet->GetString(UIMODULE_INDEX, distributedModule.uiModule);
194 ret += absSharedResultSet->GetString(VALUE_INDEX, distributedModule.extraValue);
195 if (ret != NativeRdb::E_OK) {
196 HILOG_ERROR("GetString field failed");
197 break;
198 }
199
200 distributedBundleMap_[key] = distributedModule;
201 } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
202 }
203 absSharedResultSet->Close();
204
205 HILOG_INFO("init distributed data size:%{public}zu", distributedBundleMap_.size());
206 }
207
SaveDataToDb(const std::string & bundleName,const DistributedModule & distributedModule)208 void FormDistributedMgr::SaveDataToDb(const std::string &bundleName, const DistributedModule &distributedModule)
209 {
210 NativeRdb::ValuesBucket valuesBucket;
211 valuesBucket.PutString(KEY, bundleName + std::to_string(distributedModule.userId));
212 valuesBucket.PutInt(USERID, distributedModule.userId);
213 valuesBucket.PutString(ENTRYMODULE, distributedModule.entryModule);
214 valuesBucket.PutString(UIMODULE, distributedModule.uiModule);
215 valuesBucket.PutString(VALUE, distributedModule.extraValue);
216 int64_t rowId;
217 bool ret = FormRdbDataMgr::GetInstance().InsertData(DISTRIBUTED_FORM_BUNDLE_TABLE, valuesBucket, rowId);
218 HILOG_INFO("insert data ret:%{public}d, bundleName:%{public}s, userId:%{public}d",
219 ret, bundleName.c_str(), distributedModule.userId);
220 }
221
DeleteDataInDb(const std::string & bundleName,int32_t userId)222 void FormDistributedMgr::DeleteDataInDb(const std::string &bundleName, int32_t userId)
223 {
224 NativeRdb::AbsRdbPredicates absRdbPredicates(DISTRIBUTED_FORM_BUNDLE_TABLE);
225 absRdbPredicates.EqualTo(KEY, bundleName + std::to_string(userId));
226 bool ret = FormRdbDataMgr::GetInstance().DeleteData(absRdbPredicates);
227 HILOG_INFO("deleta data ret:%{public}d, bundleName:%{public}s, userId:%{public}d", ret, bundleName.c_str(), userId);
228 }
229 } // namespace AppExecFwk
230 } // namespace OHOS