• 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_LOGI("PreInstall instance is created");
34     TryTwice([this] { return GetKvStore(); });
35 }
36 
~PreInstallDataStorage()37 PreInstallDataStorage::~PreInstallDataStorage()
38 {
39     APP_LOGI("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_LOGI("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     for (const auto &item : allEntries) {
105         std::string bundleName;
106         std::string deviceId;
107         PreInstallBundleInfo preInstallBundleInfo;
108         if (!BundleUtil::KeyToDeviceAndName(item.key.ToString(), deviceId, bundleName)) {
109             APP_LOGE("SaveEntries error key: %{public}s", item.key.ToString().c_str());
110             // it's an error key, delete it
111             {
112                 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
113                 kvStorePtr_->Delete(item.key);
114             }
115             continue;
116         }
117 
118         nlohmann::json jsonObject = nlohmann::json::parse(item.value.ToString(), nullptr, false);
119         if (jsonObject.is_discarded()) {
120             APP_LOGE("jsonObject is discarded error key: %{public}s", item.key.ToString().c_str());
121             // it's an bad json, delete it
122             {
123                 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
124                 kvStorePtr_->Delete(item.key);
125             }
126             continue;
127         }
128 
129         if (preInstallBundleInfo.FromJson(jsonObject) != ERR_OK) {
130             APP_LOGE("error key: %{private}s", item.key.ToString().c_str());
131             // it's an error value, delete it
132             {
133                 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
134                 kvStorePtr_->Delete(item.key);
135             }
136             continue;
137         }
138 
139         preInstallBundleInfos.emplace_back(preInstallBundleInfo);
140     }
141     APP_LOGD("PreInstall SaveEntries end");
142 }
143 
LoadAllPreInstallBundleInfos(std::vector<PreInstallBundleInfo> & preInstallBundleInfos)144 bool PreInstallDataStorage::LoadAllPreInstallBundleInfos(
145     std::vector<PreInstallBundleInfo> &preInstallBundleInfos)
146 {
147     APP_LOGI("load all preInstallBundleInfo data to vector start.");
148     {
149         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
150         if (!CheckKvStore()) {
151             APP_LOGE("kvStore is nullptr");
152             return false;
153         }
154     }
155 
156     Status status;
157     std::vector<Entry> allEntries;
158     TryTwice([this, &status, &allEntries] {
159         status = GetEntries(allEntries);
160         return status;
161     });
162 
163     if (status != Status::SUCCESS) {
164         APP_LOGE("get entries error: %{public}d", status);
165         // KEY_NOT_FOUND means no data in database, no need to report.
166         if (status != Status::KEY_NOT_FOUND) {
167             const std::string interfaceName = "KvStoreSnapshot::GetEntries()";
168         }
169         return false;
170     }
171 
172     SaveEntries(allEntries, preInstallBundleInfos);
173     return true;
174 }
175 
GetEntries(std::vector<Entry> & allEntries) const176 Status PreInstallDataStorage::GetEntries(std::vector<Entry> &allEntries) const
177 {
178     Status status = Status::ERROR;
179     Key token;
180     // if prefix is empty, get all entries.
181     Key allEntryKeyPrefix("");
182     if (kvStorePtr_) {
183         // sync call GetEntries, the callback will be trigger at once
184         status = kvStorePtr_->GetEntries(allEntryKeyPrefix, allEntries);
185     }
186     APP_LOGI("get all entries status: %{public}d", status);
187     return status;
188 }
189 
SavePreInstallStorageBundleInfo(const std::string & deviceId,const PreInstallBundleInfo & preInstallBundleInfo)190 bool PreInstallDataStorage::SavePreInstallStorageBundleInfo(
191     const std::string &deviceId, const PreInstallBundleInfo &preInstallBundleInfo)
192 {
193     APP_LOGI("save PreInstall bundle data.");
194     {
195         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
196         if (!CheckKvStore()) {
197             APP_LOGE("kvStore is nullptr");
198             return false;
199         }
200     }
201 
202     std::string keyOfData;
203     BundleUtil::DeviceAndNameToKey(deviceId, preInstallBundleInfo.GetBundleName(), keyOfData);
204     Key key(keyOfData);
205     Value value(preInstallBundleInfo.ToString());
206     APP_LOGI("save PreInstallStorageBundleInfo, key: %{public}s value: %{public}s.",
207         keyOfData.c_str(), preInstallBundleInfo.ToString().c_str());
208     Status status;
209     {
210         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
211         status = kvStorePtr_->Put(key, value);
212         if (status == Status::IPC_ERROR) {
213             status = kvStorePtr_->Put(key, value);
214             APP_LOGI("distribute database ipc error and try to call again, result = %{public}d", status);
215         }
216     }
217 
218     if (status != Status::SUCCESS) {
219         const std::string interfaceName = "kvStorePtr::Put()";
220         APP_LOGI("put valLocalAbilityManager::InitializeSaProfilesue to kvStore error: %{public}d", status);
221         return false;
222     }
223     APP_LOGI("put value to kvStore success when save PreInstall bundle data.");
224     return true;
225 }
226 
GetPreInstallStorageBundleInfo(const std::string & deviceId,PreInstallBundleInfo & preInstallBundleInfo)227 bool PreInstallDataStorage::GetPreInstallStorageBundleInfo(
228     const std::string &deviceId, PreInstallBundleInfo &preInstallBundleInfo)
229 {
230     APP_LOGI("Get PreInstall bundle data start.");
231     {
232         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
233         if (!CheckKvStore()) {
234             APP_LOGE("kvStore is nullptr");
235             return false;
236         }
237     }
238     std::string keyOfData;
239     BundleUtil::DeviceAndNameToKey(deviceId, preInstallBundleInfo.GetBundleName(), keyOfData);
240     APP_LOGI("Get PreInstall bundle data when key is: %{public}s ", keyOfData.c_str());
241     Key key(keyOfData);
242     Value value;
243     Status status;
244 
245     {
246         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
247         status = kvStorePtr_->Get(key, value);
248         if (status == Status::IPC_ERROR) {
249             status = kvStorePtr_->Get(key, value);
250             APP_LOGI("distribute database ipc error and try to call again, result = %{public}d", status);
251         }
252     }
253 
254     if (status != Status::SUCCESS) {
255         APP_LOGE("Get key error: %{public}d", status);
256         return false;
257     }
258 
259     nlohmann::json jsonObject = nlohmann::json::parse(value.ToString(), nullptr, false);
260     if (jsonObject.is_discarded()) {
261         APP_LOGE("error key: %{private}s", key.ToString().c_str());
262         // it's an bad json, delete it
263         {
264             std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
265             kvStorePtr_->Delete(key);
266         }
267         return false;
268     }
269 
270     if (preInstallBundleInfo.FromJson(jsonObject) != ERR_OK) {
271         APP_LOGE("error key: %{private}s", key.ToString().c_str());
272         // it's an error value, delete it
273         {
274             std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
275             kvStorePtr_->Delete(key);
276         }
277         return false;
278     }
279 
280     APP_LOGI("Get value success when Get PreInstall bundle data.");
281     return true;
282 }
283 
DeletePreInstallStorageBundleInfo(const std::string & deviceId,const PreInstallBundleInfo & preInstallBundleInfo)284 bool PreInstallDataStorage::DeletePreInstallStorageBundleInfo(
285     const std::string &deviceId, const PreInstallBundleInfo &preInstallBundleInfo)
286 {
287     APP_LOGI("delete PreInstall bundle data");
288     {
289         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
290         if (!CheckKvStore()) {
291             APP_LOGE("kvStore is nullptr");
292             return false;
293         }
294     }
295     std::string keyOfData;
296     BundleUtil::DeviceAndNameToKey(deviceId, preInstallBundleInfo.GetBundleName(), keyOfData);
297     Key key(keyOfData);
298     Status status;
299 
300     {
301         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
302         status = kvStorePtr_->Delete(key);
303         if (status == Status::IPC_ERROR) {
304             status = kvStorePtr_->Delete(key);
305             APP_LOGW("distribute database ipc error and try to call again, result = %{public}d", status);
306         }
307     }
308 
309     if (status != Status::SUCCESS) {
310         const std::string interfaceName = "kvStorePtr::Delete()";
311         APP_LOGE("delete key error: %{public}d", status);
312         return false;
313     } else {
314         APP_LOGI("delete value to kvStore success");
315     }
316     return true;
317 }
318 }  // namespace AppExecFwk
319 }  // namespace OHOS
320