• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ability_auto_startup_data_manager.h"
17 
18 #include <algorithm>
19 #include <unistd.h>
20 
21 #include "errors.h"
22 #include "hilog_wrapper.h"
23 #include "nlohmann/json.hpp"
24 #include "types.h"
25 
26 namespace OHOS {
27 namespace AbilityRuntime {
28 namespace {
29 constexpr int32_t CHECK_INTERVAL = 100000; // 100ms
30 constexpr int32_t MAX_TIMES = 5;           // 5 * 100ms = 500ms
31 constexpr const char *AUTO_STARTUP_STORAGE_DIR = "/data/service/el1/public/database/auto_startup_service";
32 const std::string JSON_KEY_BUNDLE_NAME = "bundleName";
33 const std::string JSON_KEY_ABILITY_NAME = "abilityName";
34 const std::string JSON_KEY_MODULE_NAME = "moduleName";
35 const std::string JSON_KEY_IS_AUTO_STARTUP = "isAutoStartup";
36 const std::string JSON_KEY_IS_EDM_FORCE = "isEdmForce";
37 const std::string JSON_KEY_TYPE_NAME = "abilityTypeName";
38 } // namespace
39 const DistributedKv::AppId AbilityAutoStartupDataManager::APP_ID = { "auto_startup_storage" };
40 const DistributedKv::StoreId AbilityAutoStartupDataManager::STORE_ID = { "auto_startup_infos" };
AbilityAutoStartupDataManager()41 AbilityAutoStartupDataManager::AbilityAutoStartupDataManager() {}
42 
~AbilityAutoStartupDataManager()43 AbilityAutoStartupDataManager::~AbilityAutoStartupDataManager()
44 {
45     if (kvStorePtr_ != nullptr) {
46         dataManager_.CloseKvStore(APP_ID, kvStorePtr_);
47     }
48 }
49 
GetKvStore()50 DistributedKv::Status AbilityAutoStartupDataManager::GetKvStore()
51 {
52     DistributedKv::Options options = { .createIfMissing = true,
53         .encrypt = false,
54         .autoSync = true,
55         .syncable = false,
56         .securityLevel = DistributedKv::SecurityLevel::S2,
57         .area = DistributedKv::EL1,
58         .kvStoreType = DistributedKv::KvStoreType::SINGLE_VERSION,
59         .baseDir = AUTO_STARTUP_STORAGE_DIR };
60 
61     DistributedKv::Status status = dataManager_.GetSingleKvStore(options, APP_ID, STORE_ID, kvStorePtr_);
62     if (status != DistributedKv::Status::SUCCESS) {
63         HILOG_ERROR("Return error: %{public}d.", status);
64         return status;
65     }
66 
67     HILOG_DEBUG("Get kvStore success.");
68     return status;
69 }
70 
CheckKvStore()71 bool AbilityAutoStartupDataManager::CheckKvStore()
72 {
73     if (kvStorePtr_ != nullptr) {
74         return true;
75     }
76     int32_t tryTimes = MAX_TIMES;
77     while (tryTimes > 0) {
78         DistributedKv::Status status = GetKvStore();
79         if (status == DistributedKv::Status::SUCCESS && kvStorePtr_ != nullptr) {
80             return true;
81         }
82         HILOG_DEBUG("Try times: %{public}d.", tryTimes);
83         usleep(CHECK_INTERVAL);
84         tryTimes--;
85     }
86     return kvStorePtr_ != nullptr;
87 }
88 
InsertAutoStartupData(const AutoStartupInfo & info,bool isAutoStartup,bool isEdmForce)89 int32_t AbilityAutoStartupDataManager::InsertAutoStartupData(
90     const AutoStartupInfo &info, bool isAutoStartup, bool isEdmForce)
91 {
92     if (info.bundleName.empty() || info.abilityName.empty()) {
93         HILOG_ERROR("Invalid value.");
94         return ERR_INVALID_VALUE;
95     }
96 
97     HILOG_DEBUG("bundleName: %{public}s, moduleName: %{public}s, abilityName: %{public}s.", info.bundleName.c_str(),
98         info.moduleName.c_str(), info.abilityName.c_str());
99     {
100         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
101         if (!CheckKvStore()) {
102             HILOG_ERROR("kvStore is nullptr.");
103             return ERR_NO_INIT;
104         }
105     }
106 
107     DistributedKv::Key key = ConvertAutoStartupDataToKey(info);
108     DistributedKv::Value value = ConvertAutoStartupStatusToValue(isAutoStartup, isEdmForce, info.abilityTypeName);
109     DistributedKv::Status status;
110     {
111         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
112         status = kvStorePtr_->Put(key, value);
113     }
114 
115     if (status != DistributedKv::Status::SUCCESS) {
116         HILOG_ERROR("Insert data to kvStore error: %{public}d.", status);
117         return ERR_INVALID_OPERATION;
118     }
119     return ERR_OK;
120 }
121 
UpdateAutoStartupData(const AutoStartupInfo & info,bool isAutoStartup,bool isEdmForce)122 int32_t AbilityAutoStartupDataManager::UpdateAutoStartupData(
123     const AutoStartupInfo &info, bool isAutoStartup, bool isEdmForce)
124 {
125     if (info.bundleName.empty() || info.abilityName.empty()) {
126         HILOG_WARN("Invalid value!");
127         return ERR_INVALID_VALUE;
128     }
129 
130     HILOG_DEBUG("bundleName: %{public}s, moduleName: %{public}s, abilityName: %{public}s.", info.bundleName.c_str(),
131         info.moduleName.c_str(), info.abilityName.c_str());
132     {
133         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
134         if (!CheckKvStore()) {
135             HILOG_ERROR("kvStore is nullptr.");
136             return ERR_NO_INIT;
137         }
138     }
139 
140     DistributedKv::Key key = ConvertAutoStartupDataToKey(info);
141     DistributedKv::Status status;
142     {
143         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
144         status = kvStorePtr_->Delete(key);
145     }
146     if (status != DistributedKv::Status::SUCCESS) {
147         HILOG_ERROR("Delete data from kvStore error: %{public}d.", status);
148         return ERR_INVALID_OPERATION;
149     }
150     DistributedKv::Value value = ConvertAutoStartupStatusToValue(isAutoStartup, isEdmForce, info.abilityTypeName);
151     {
152         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
153         status = kvStorePtr_->Put(key, value);
154     }
155     if (status != DistributedKv::Status::SUCCESS) {
156         HILOG_ERROR("Insert data to kvStore error: %{public}d.", status);
157         return ERR_INVALID_OPERATION;
158     }
159 
160     return ERR_OK;
161 }
162 
DeleteAutoStartupData(const AutoStartupInfo & info)163 int32_t AbilityAutoStartupDataManager::DeleteAutoStartupData(const AutoStartupInfo &info)
164 {
165     if (info.bundleName.empty() || info.abilityName.empty()) {
166         HILOG_WARN("Invalid value!");
167         return ERR_INVALID_VALUE;
168     }
169 
170     HILOG_DEBUG("bundleName: %{public}s, moduleName: %{public}s, abilityName: %{public}s.", info.bundleName.c_str(),
171         info.moduleName.c_str(), info.abilityName.c_str());
172     {
173         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
174         if (!CheckKvStore()) {
175             HILOG_ERROR("kvStore is nullptr.");
176             return ERR_NO_INIT;
177         }
178     }
179 
180     DistributedKv::Key key = ConvertAutoStartupDataToKey(info);
181     DistributedKv::Status status;
182     {
183         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
184         status = kvStorePtr_->Delete(key);
185     }
186 
187     if (status != DistributedKv::Status::SUCCESS) {
188         HILOG_ERROR("Delete data from kvStore error: %{public}d.", status);
189         return ERR_INVALID_OPERATION;
190     }
191     return ERR_OK;
192 }
193 
DeleteAutoStartupData(const std::string & bundleName)194 int32_t AbilityAutoStartupDataManager::DeleteAutoStartupData(const std::string &bundleName)
195 {
196     if (bundleName.empty()) {
197         HILOG_WARN("Invalid value!");
198         return ERR_INVALID_VALUE;
199     }
200 
201     HILOG_DEBUG("bundleName: %{public}s.", bundleName.c_str());
202     {
203         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
204         if (!CheckKvStore()) {
205             HILOG_ERROR("kvStore is nullptr.");
206             return ERR_NO_INIT;
207         }
208     }
209 
210     std::vector<DistributedKv::Entry> allEntries;
211     DistributedKv::Status status = kvStorePtr_->GetEntries(nullptr, allEntries);
212     if (status != DistributedKv::Status::SUCCESS) {
213         HILOG_ERROR("Get entries error: %{public}d.", status);
214         return ERR_INVALID_OPERATION;
215     }
216 
217     for (const auto &item : allEntries) {
218         if (IsEqual(item.key, bundleName)) {
219             {
220                 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
221                 status = kvStorePtr_->Delete(item.key);
222             }
223             if (status != DistributedKv::Status::SUCCESS) {
224                 HILOG_ERROR("Delete data from kvStore error: %{public}d.", status);
225                 return ERR_INVALID_OPERATION;
226             }
227         }
228     }
229 
230     return ERR_OK;
231 }
232 
QueryAutoStartupData(const AutoStartupInfo & info)233 AutoStartupStatus AbilityAutoStartupDataManager::QueryAutoStartupData(const AutoStartupInfo &info)
234 {
235     AutoStartupStatus asustatus;
236     if (info.bundleName.empty() || info.abilityName.empty()) {
237         HILOG_WARN("Invalid value!");
238         asustatus.code = ERR_INVALID_VALUE;
239         return asustatus;
240     }
241 
242     HILOG_DEBUG("bundleName: %{public}s, moduleName: %{public}s, abilityName: %{public}s.", info.bundleName.c_str(),
243         info.moduleName.c_str(), info.abilityName.c_str());
244     {
245         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
246         if (!CheckKvStore()) {
247             HILOG_ERROR("kvStore is nullptr.");
248             asustatus.code = ERR_NO_INIT;
249             return asustatus;
250         }
251     }
252 
253     std::vector<DistributedKv::Entry> allEntries;
254     DistributedKv::Status status = kvStorePtr_->GetEntries(nullptr, allEntries);
255     if (status != DistributedKv::Status::SUCCESS) {
256         HILOG_ERROR("Get entries error: %{public}d.", status);
257         asustatus.code = ERR_INVALID_OPERATION;
258         return asustatus;
259     }
260 
261     asustatus.code = ERR_NAME_NOT_FOUND;
262     for (const auto &item : allEntries) {
263         if (IsEqual(item.key, info)) {
264             ConvertAutoStartupStatusFromValue(item.value, asustatus.isAutoStartup, asustatus.isEdmForce);
265             asustatus.code = ERR_OK;
266         }
267     }
268 
269     return asustatus;
270 }
271 
QueryAllAutoStartupApplications(std::vector<AutoStartupInfo> & infoList)272 int32_t AbilityAutoStartupDataManager::QueryAllAutoStartupApplications(std::vector<AutoStartupInfo> &infoList)
273 {
274     HILOG_DEBUG("Called.");
275     {
276         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
277         if (!CheckKvStore()) {
278             HILOG_ERROR("kvStore is nullptr.");
279             return ERR_NO_INIT;
280         }
281     }
282 
283     std::vector<DistributedKv::Entry> allEntries;
284     DistributedKv::Status status = kvStorePtr_->GetEntries(nullptr, allEntries);
285     if (status != DistributedKv::Status::SUCCESS) {
286         HILOG_ERROR("Get entries error: %{public}d.", status);
287         return ERR_INVALID_OPERATION;
288     }
289 
290     for (const auto &item : allEntries) {
291         bool isAutoStartup, isEdmForce;
292         ConvertAutoStartupStatusFromValue(item.value, isAutoStartup, isEdmForce);
293         if (isAutoStartup) {
294             infoList.emplace_back(ConvertAutoStartupInfoFromKeyAndValue(item.key, item.value));
295         }
296     }
297     HILOG_DEBUG("InfoList.size: %{public}zu.", infoList.size());
298     return ERR_OK;
299 }
300 
GetCurrentAppAutoStartupData(const std::string & bundleName,std::vector<AutoStartupInfo> & infoList)301 int32_t AbilityAutoStartupDataManager::GetCurrentAppAutoStartupData(
302     const std::string &bundleName, std::vector<AutoStartupInfo> &infoList)
303 {
304     HILOG_DEBUG("Called.");
305     {
306         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
307         if (!CheckKvStore()) {
308             HILOG_ERROR("kvStore is nullptr.");
309             return ERR_NO_INIT;
310         }
311     }
312 
313     std::vector<DistributedKv::Entry> allEntries;
314     DistributedKv::Status status = kvStorePtr_->GetEntries(nullptr, allEntries);
315     if (status != DistributedKv::Status::SUCCESS) {
316         HILOG_ERROR("Get entries error: %{public}d.", status);
317         return ERR_INVALID_OPERATION;
318     }
319 
320     for (const auto &item : allEntries) {
321         if (IsEqual(item.key, bundleName)) {
322             infoList.emplace_back(ConvertAutoStartupInfoFromKeyAndValue(item.key, item.value));
323         }
324     }
325     HILOG_DEBUG("InfoList.size: %{public}zu.", infoList.size());
326     return ERR_OK;
327 }
328 
ConvertAutoStartupStatusToValue(bool isAutoStartup,bool isEdmForce,const std::string & abilityTypeName)329 DistributedKv::Value AbilityAutoStartupDataManager::ConvertAutoStartupStatusToValue(
330     bool isAutoStartup, bool isEdmForce, const std::string &abilityTypeName)
331 {
332     nlohmann::json jsonObject = nlohmann::json {
333         { JSON_KEY_IS_AUTO_STARTUP, isAutoStartup },
334         { JSON_KEY_IS_EDM_FORCE, isEdmForce },
335         { JSON_KEY_TYPE_NAME, abilityTypeName },
336     };
337     DistributedKv::Value value(jsonObject.dump());
338     HILOG_DEBUG("value: %{public}s.", value.ToString().c_str());
339     return value;
340 }
341 
ConvertAutoStartupStatusFromValue(const DistributedKv::Value & value,bool & isAutoStartup,bool & isEdmForce)342 void AbilityAutoStartupDataManager::ConvertAutoStartupStatusFromValue(
343     const DistributedKv::Value &value, bool &isAutoStartup, bool &isEdmForce)
344 {
345     nlohmann::json jsonObject = nlohmann::json::parse(value.ToString(), nullptr, false);
346     if (jsonObject.is_discarded()) {
347         HILOG_ERROR("Failed to parse json string.");
348         return;
349     }
350     if (jsonObject.contains(JSON_KEY_IS_AUTO_STARTUP) && jsonObject[JSON_KEY_IS_AUTO_STARTUP].is_boolean()) {
351         isAutoStartup = jsonObject.at(JSON_KEY_IS_AUTO_STARTUP).get<bool>();
352     }
353     if (jsonObject.contains(JSON_KEY_IS_EDM_FORCE) && jsonObject[JSON_KEY_IS_EDM_FORCE].is_boolean()) {
354         isEdmForce = jsonObject.at(JSON_KEY_IS_EDM_FORCE).get<bool>();
355     }
356 }
357 
ConvertAutoStartupDataToKey(const AutoStartupInfo & info)358 DistributedKv::Key AbilityAutoStartupDataManager::ConvertAutoStartupDataToKey(const AutoStartupInfo &info)
359 {
360     nlohmann::json jsonObject = nlohmann::json {
361         { JSON_KEY_BUNDLE_NAME, info.bundleName },
362         { JSON_KEY_MODULE_NAME, info.moduleName },
363         { JSON_KEY_ABILITY_NAME, info.abilityName },
364     };
365     DistributedKv::Key key(jsonObject.dump());
366     HILOG_DEBUG("key: %{public}s.", key.ToString().c_str());
367     return key;
368 }
369 
ConvertAutoStartupInfoFromKeyAndValue(const DistributedKv::Key & key,const DistributedKv::Value & value)370 AutoStartupInfo AbilityAutoStartupDataManager::ConvertAutoStartupInfoFromKeyAndValue(
371     const DistributedKv::Key &key, const DistributedKv::Value &value)
372 {
373     AutoStartupInfo info;
374     nlohmann::json jsonObject = nlohmann::json::parse(key.ToString(), nullptr, false);
375     if (jsonObject.is_discarded()) {
376         HILOG_ERROR("Failed to parse jsonObject.");
377         return info;
378     }
379 
380     if (jsonObject.contains(JSON_KEY_BUNDLE_NAME) && jsonObject[JSON_KEY_BUNDLE_NAME].is_string()) {
381         info.bundleName = jsonObject.at(JSON_KEY_BUNDLE_NAME).get<std::string>();
382     }
383 
384     if (jsonObject.contains(JSON_KEY_MODULE_NAME) && jsonObject[JSON_KEY_MODULE_NAME].is_string()) {
385         info.moduleName = jsonObject.at(JSON_KEY_MODULE_NAME).get<std::string>();
386     }
387 
388     if (jsonObject.contains(JSON_KEY_ABILITY_NAME) && jsonObject[JSON_KEY_ABILITY_NAME].is_string()) {
389         info.abilityName = jsonObject.at(JSON_KEY_ABILITY_NAME).get<std::string>();
390     }
391 
392     nlohmann::json jsonValueObject = nlohmann::json::parse(value.ToString(), nullptr, false);
393     if (jsonValueObject.is_discarded()) {
394         HILOG_ERROR("Failed to parse jsonValueObject.");
395         return info;
396     }
397 
398     if (jsonValueObject.contains(JSON_KEY_TYPE_NAME) && jsonValueObject[JSON_KEY_TYPE_NAME].is_string()) {
399         info.abilityTypeName = jsonValueObject.at(JSON_KEY_TYPE_NAME).get<std::string>();
400     }
401 
402     return info;
403 }
404 
IsEqual(const DistributedKv::Key & key,const AutoStartupInfo & info)405 bool AbilityAutoStartupDataManager::IsEqual(const DistributedKv::Key &key, const AutoStartupInfo &info)
406 {
407     nlohmann::json jsonObject = nlohmann::json::parse(key.ToString(), nullptr, false);
408     if (jsonObject.is_discarded()) {
409         HILOG_ERROR("Failed to parse json string.");
410         return false;
411     }
412 
413     if (jsonObject.contains(JSON_KEY_BUNDLE_NAME) && jsonObject[JSON_KEY_BUNDLE_NAME].is_string()) {
414         if (info.bundleName != jsonObject.at(JSON_KEY_BUNDLE_NAME).get<std::string>()) {
415             return false;
416         }
417     }
418 
419     if (jsonObject.contains(JSON_KEY_ABILITY_NAME) && jsonObject[JSON_KEY_ABILITY_NAME].is_string()) {
420         if (info.abilityName != jsonObject.at(JSON_KEY_ABILITY_NAME).get<std::string>()) {
421             return false;
422         }
423     }
424 
425     if (jsonObject.contains(JSON_KEY_MODULE_NAME) && jsonObject[JSON_KEY_MODULE_NAME].is_string()) {
426         std::string moduleName = jsonObject.at(JSON_KEY_MODULE_NAME).get<std::string>();
427         if (!moduleName.empty() && info.moduleName != moduleName) {
428             return false;
429         }
430     }
431     return true;
432 }
433 
IsEqual(const DistributedKv::Key & key,const std::string & bundleName)434 bool AbilityAutoStartupDataManager::IsEqual(const DistributedKv::Key &key, const std::string &bundleName)
435 {
436     nlohmann::json jsonObject = nlohmann::json::parse(key.ToString(), nullptr, false);
437     if (jsonObject.is_discarded()) {
438         HILOG_ERROR("Failed to parse json string.");
439         return false;
440     }
441 
442     if (jsonObject.contains(JSON_KEY_BUNDLE_NAME) && jsonObject[JSON_KEY_BUNDLE_NAME].is_string()) {
443         if (bundleName == jsonObject.at(JSON_KEY_BUNDLE_NAME).get<std::string>()) {
444             return true;
445         }
446     }
447     return false;
448 }
449 } // namespace AbilityRuntime
450 } // namespace OHOS
451