• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 "preinstall_data_storage.h"
17 
18 #include <unistd.h>
19 #include "app_log_wrapper.h"
20 #include "bundle_util.h"
21 
22 using namespace OHOS::DistributedKv;
23 
24 namespace OHOS {
25 namespace AppExecFwk {
26 namespace {
27 const int32_t MAX_TIMES = 600;             // 1 min
28 const int32_t SLEEP_INTERVAL = 100 * 1000;  // 100ms
29 }  // namespace
30 
PreInstallDataStorage()31 PreInstallDataStorage::PreInstallDataStorage()
32 {
33     APP_LOGD("PreInstall instance is created");
34     TryTwice([this] { return GetKvStore(); });
35 }
36 
~PreInstallDataStorage()37 PreInstallDataStorage::~PreInstallDataStorage()
38 {
39     APP_LOGD("PreInstall instance is destroyed");
40     dataManager_.CloseKvStore(appId_, kvStorePtr_);
41 }
42 
GetKvStore()43 Status PreInstallDataStorage::GetKvStore()
44 {
45     Options options = {
46         .createIfMissing = true,
47         .encrypt = false,
48         .autoSync = false,
49         .kvStoreType = KvStoreType::SINGLE_VERSION
50     };
51 
52     Status status = dataManager_.GetSingleKvStore(options, appId_, storeId_, kvStorePtr_);
53     if (status != Status::SUCCESS) {
54         APP_LOGE("usage get kvStore error: %{public}d", status);
55     } else {
56         APP_LOGD("usage get kvStore success");
57     }
58     return status;
59 }
60 
TryTwice(const std::function<Status ()> & func) const61 void PreInstallDataStorage::TryTwice(const std::function<Status()> &func) const
62 {
63     Status status = func();
64     if (status == Status::IPC_ERROR) {
65         status = func();
66         APP_LOGW("distribute database ipc error and try to call again, result = %{public}d", status);
67     }
68 }
69 
CheckKvStore()70 bool PreInstallDataStorage::CheckKvStore()
71 {
72     if (kvStorePtr_ != nullptr) {
73         return true;
74     }
75     int32_t tryTimes = MAX_TIMES;
76     while (tryTimes > 0) {
77         Status status = GetKvStore();
78         if (status == Status::SUCCESS && kvStorePtr_ != nullptr) {
79             return true;
80         }
81         APP_LOGD("usage CheckKvStore, Times: %{public}d", tryTimes);
82         usleep(SLEEP_INTERVAL);
83         tryTimes--;
84     }
85     return kvStorePtr_ != nullptr;
86 }
87 
ResetKvStore()88 bool PreInstallDataStorage::ResetKvStore()
89 {
90     std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
91     kvStorePtr_ = nullptr;
92     Status status = GetKvStore();
93     if (status == Status::SUCCESS && kvStorePtr_ != nullptr) {
94         return true;
95     }
96     APP_LOGW("usage reset failed");
97     return false;
98 }
99 
SaveEntries(const std::vector<Entry> & allEntries,std::vector<PreInstallBundleInfo> & preInstallBundleInfos)100 void PreInstallDataStorage::SaveEntries(
101     const std::vector<Entry> &allEntries, std::vector<PreInstallBundleInfo> &preInstallBundleInfos)
102 {
103     APP_LOGD("PreInstall SaveEntries start.");
104     std::map<std::string, PreInstallBundleInfo> updateInfos;
105     for (const auto &item : allEntries) {
106         PreInstallBundleInfo preInstallBundleInfo;
107         nlohmann::json jsonObject = nlohmann::json::parse(item.value.ToString(), nullptr, false);
108         if (jsonObject.is_discarded()) {
109             APP_LOGE("jsonObject is discarded error key: %{public}s", item.key.ToString().c_str());
110             // it's an bad json, delete it
111             {
112                 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
113                 kvStorePtr_->Delete(item.key);
114             }
115             continue;
116         }
117 
118         if (preInstallBundleInfo.FromJson(jsonObject) != ERR_OK) {
119             APP_LOGE("error key: %{private}s", item.key.ToString().c_str());
120             // it's an error value, delete it
121             {
122                 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
123                 kvStorePtr_->Delete(item.key);
124             }
125             continue;
126         }
127         preInstallBundleInfos.emplace_back(preInstallBundleInfo);
128         // database update
129         std::string key = item.key.ToString();
130         if (key != preInstallBundleInfo.GetBundleName()) {
131             updateInfos.emplace(key, preInstallBundleInfo);
132         }
133     }
134     if (updateInfos.size() > 0) {
135         UpdateDataBase(updateInfos);
136     }
137     APP_LOGD("PreInstall SaveEntries end");
138 }
139 
LoadAllPreInstallBundleInfos(std::vector<PreInstallBundleInfo> & preInstallBundleInfos)140 bool PreInstallDataStorage::LoadAllPreInstallBundleInfos(std::vector<PreInstallBundleInfo> &preInstallBundleInfos)
141 {
142     APP_LOGD("load all preInstallBundleInfo data to vector start.");
143     {
144         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
145         if (!CheckKvStore()) {
146             APP_LOGE("kvStore is nullptr");
147             return false;
148         }
149     }
150 
151     Status status;
152     std::vector<Entry> allEntries;
153     TryTwice([this, &status, &allEntries] {
154         status = GetEntries(allEntries);
155         return status;
156     });
157 
158     if (status != Status::SUCCESS) {
159         APP_LOGE("get entries error: %{public}d", status);
160         // KEY_NOT_FOUND means no data in database, no need to report.
161         if (status != Status::KEY_NOT_FOUND) {
162             const std::string interfaceName = "KvStoreSnapshot::GetEntries()";
163         }
164         return false;
165     }
166 
167     SaveEntries(allEntries, preInstallBundleInfos);
168     return true;
169 }
170 
GetEntries(std::vector<Entry> & allEntries) const171 Status PreInstallDataStorage::GetEntries(std::vector<Entry> &allEntries) const
172 {
173     Status status = Status::ERROR;
174     Key token;
175     // if prefix is empty, get all entries.
176     Key allEntryKeyPrefix("");
177     if (kvStorePtr_) {
178         // sync call GetEntries, the callback will be trigger at once
179         status = kvStorePtr_->GetEntries(allEntryKeyPrefix, allEntries);
180     }
181     APP_LOGD("get all entries status: %{public}d", status);
182     return status;
183 }
184 
SavePreInstallStorageBundleInfo(const PreInstallBundleInfo & preInstallBundleInfo)185 bool PreInstallDataStorage::SavePreInstallStorageBundleInfo(const PreInstallBundleInfo &preInstallBundleInfo)
186 {
187     APP_LOGD("save PreInstall bundle data.");
188     {
189         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
190         if (!CheckKvStore()) {
191             APP_LOGE("kvStore is nullptr");
192             return false;
193         }
194     }
195     std::string keyInfo = preInstallBundleInfo.GetBundleName();
196     std::string valueInfo = preInstallBundleInfo.ToString();
197     Key key(keyInfo);
198     Value value(valueInfo);
199     APP_LOGD("save PreInstallStorageBundleInfo, key: %{public}s value: %{public}s.",
200         keyInfo.c_str(), valueInfo.c_str());
201     Status status;
202     {
203         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
204         status = kvStorePtr_->Put(key, value);
205         if (status == Status::IPC_ERROR) {
206             status = kvStorePtr_->Put(key, value);
207             APP_LOGD("distribute database ipc error and try to call again, result = %{public}d", status);
208         }
209     }
210 
211     if (status != Status::SUCCESS) {
212         APP_LOGD("put valLocalAbilityManager::InitializeSaProfilesue to kvStore error: %{public}d", status);
213         return false;
214     }
215     APP_LOGD("put value to kvStore success when save PreInstall bundle data.");
216     return true;
217 }
218 
DeletePreInstallStorageBundleInfo(const PreInstallBundleInfo & preInstallBundleInfo)219 bool PreInstallDataStorage::DeletePreInstallStorageBundleInfo(const PreInstallBundleInfo &preInstallBundleInfo)
220 {
221     APP_LOGD("delete PreInstall bundle data");
222     {
223         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
224         if (!CheckKvStore()) {
225             APP_LOGE("kvStore is nullptr");
226             return false;
227         }
228     }
229     std::string keyInfo = preInstallBundleInfo.GetBundleName();
230     Key key(keyInfo);
231     APP_LOGD("delete PreInstallStorageBundleInfo, key: %{public}s", keyInfo.c_str());
232     Status status;
233 
234     {
235         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
236         status = kvStorePtr_->Delete(key);
237         if (status == Status::IPC_ERROR) {
238             status = kvStorePtr_->Delete(key);
239             APP_LOGW("distribute database ipc error and try to call again, result = %{public}d", status);
240         }
241     }
242 
243     if (status != Status::SUCCESS) {
244         APP_LOGE("delete key error: %{public}d", status);
245         return false;
246     } else {
247         APP_LOGD("delete value to kvStore success");
248     }
249     return true;
250 }
251 
UpdateDataBase(std::map<std::string,PreInstallBundleInfo> & infos)252 void PreInstallDataStorage::UpdateDataBase(std::map<std::string, PreInstallBundleInfo>& infos)
253 {
254     APP_LOGD("begin to update preInstall database.");
255     for (const auto& item : infos) {
256         if (SavePreInstallStorageBundleInfo(item.second)) {
257             DeleteOldBundleInfo(item.first);
258         }
259     }
260     APP_LOGD("update preInstall database done.");
261 }
262 
DeleteOldBundleInfo(const std::string & oldKey)263 void PreInstallDataStorage::DeleteOldBundleInfo(const std::string& oldKey)
264 {
265     APP_LOGD("begin to delete old preInstall bundleInfo");
266     std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
267     if (!CheckKvStore()) {
268         APP_LOGE("kvStore is nullptr");
269         return;
270     }
271     Key key(oldKey);
272     Status status = kvStorePtr_->Delete(key);
273     if (status == Status::IPC_ERROR) {
274         status = kvStorePtr_->Delete(key);
275         APP_LOGW("distribute database ipc error and try to call again, result = %{public}d", status);
276     }
277     if (status != Status::SUCCESS) {
278         APP_LOGE("delete old bundleInfo failed: %{public}d", status);
279         return;
280     }
281     APP_LOGD("delete old preInstall bundleInfo success");
282 }
283 }  // namespace AppExecFwk
284 }  // namespace OHOS
285