• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "distributed_data_storage.h"
17 
18 #include <unistd.h>
19 
20 #include "account_manager_helper.h"
21 #include "app_log_wrapper.h"
22 #include "distributed_bms.h"
23 #include "parameter.h"
24 
25 using namespace OHOS::DistributedKv;
26 
27 namespace OHOS {
28 namespace AppExecFwk {
29 namespace {
30 const std::string BMS_KV_BASE_DIR = "/data/service/el1/public/database/";
31 const int32_t EL1 = 1;
32 const int32_t MAX_TIMES = 600;              // 1min
33 const int32_t SLEEP_INTERVAL = 100 * 1000;  // 100ms
34 const int32_t FLAGS = BundleFlag::GET_BUNDLE_WITH_ABILITIES |
35                       ApplicationFlag::GET_APPLICATION_INFO_WITH_DISABLE |
36                       AbilityInfoFlag::GET_ABILITY_INFO_WITH_DISABLE;
37 const uint32_t DEVICE_UDID_LENGTH = 65;
38 }  // namespace
39 
40 std::shared_ptr<DistributedDataStorage> DistributedDataStorage::instance_ = nullptr;
41 std::recursive_mutex DistributedDataStorage::mutex_;
42 
GetInstance()43 std::shared_ptr<DistributedDataStorage> DistributedDataStorage::GetInstance()
44 {
45     if (instance_ == nullptr) {
46         std::lock_guard<std::recursive_mutex> lock_l(mutex_);
47         if (instance_ == nullptr) {
48             instance_ = std::make_shared<DistributedDataStorage>();
49         }
50     }
51     return instance_;
52 }
53 
DistributedDataStorage()54 DistributedDataStorage::DistributedDataStorage()
55 {
56     APP_LOGI("instance is created");
57     TryTwice([this] { return GetKvStore(); });
58 }
59 
~DistributedDataStorage()60 DistributedDataStorage::~DistributedDataStorage()
61 {
62     APP_LOGI("instance is destroyed");
63     dataManager_.CloseKvStore(appId_, storeId_);
64 }
65 
SaveStorageDistributeInfo(const std::string & bundleName,int32_t userId)66 void DistributedDataStorage::SaveStorageDistributeInfo(const std::string &bundleName, int32_t userId)
67 {
68     APP_LOGI("save DistributedBundleInfo data");
69     {
70         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
71         if (!CheckKvStore()) {
72             APP_LOGE("kvStore is nullptr");
73             return;
74         }
75     }
76     int32_t currentUserId = AccountManagerHelper::GetCurrentActiveUserId();
77     if (currentUserId == Constants::INVALID_USERID) {
78         currentUserId = Constants::START_USERID;
79     }
80     if (userId != currentUserId) {
81         APP_LOGW("install userid:%{public}d is not currentUserId:%{public}d", userId, currentUserId);
82         return;
83     }
84     auto bundleMgr = DelayedSingleton<DistributedBms>::GetInstance()->GetBundleMgr();
85     if (bundleMgr == nullptr) {
86         APP_LOGE("Get bundleMgr shared_ptr nullptr");
87         return;
88     }
89     BundleInfo bundleInfo;
90     bool ret = bundleMgr->GetBundleInfo(bundleName, FLAGS, bundleInfo, currentUserId);
91     if (!ret) {
92         APP_LOGW("GetBundleInfo:%{public}s  userid:%{public}d failed", bundleName.c_str(), currentUserId);
93         DeleteStorageDistributeInfo(bundleName, currentUserId);
94         return;
95     }
96     ret = InnerSaveStorageDistributeInfo(ConvertToDistributedBundleInfo(bundleInfo));
97     if (!ret) {
98         APP_LOGW("InnerSaveStorageDistributeInfo:%{public}s  failed", bundleName.c_str());
99     }
100 }
101 
InnerSaveStorageDistributeInfo(const DistributedBundleInfo & distributedBundleInfo)102 bool DistributedDataStorage::InnerSaveStorageDistributeInfo(const DistributedBundleInfo &distributedBundleInfo)
103 {
104     std::string udid;
105     bool ret = GetLocalUdid(udid);
106     if (!ret) {
107         APP_LOGE("GetLocalUdid error");
108         return false;
109     }
110     std::string keyOfData = DeviceAndNameToKey(udid, distributedBundleInfo.bundleName);
111     Key key(keyOfData);
112     Value value(distributedBundleInfo.ToString());
113     Status status = kvStorePtr_->Put(key, value);
114     if (status == Status::IPC_ERROR) {
115         status = kvStorePtr_->Put(key, value);
116         APP_LOGW("distribute database ipc error and try to call again, result = %{public}d", status);
117     }
118     if (status != Status::SUCCESS) {
119         APP_LOGE("put to kvStore error: %{public}d", status);
120         return false;
121     }
122     APP_LOGI("put value to kvStore success");
123     return true;
124 }
125 
DeleteStorageDistributeInfo(const std::string & bundleName,int32_t userId)126 void DistributedDataStorage::DeleteStorageDistributeInfo(const std::string &bundleName, int32_t userId)
127 {
128     APP_LOGI("delete DistributedBundleInfo");
129     {
130         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
131         if (!CheckKvStore()) {
132             APP_LOGE("kvStore is nullptr");
133             return;
134         }
135     }
136     int32_t currentUserId = AccountManagerHelper::GetCurrentActiveUserId();
137     if (userId != currentUserId) {
138         APP_LOGW("install userid:%{public}d is not currentUserId:%{public}d", userId, currentUserId);
139         return;
140     }
141     std::string udid;
142     bool ret = GetLocalUdid(udid);
143     if (!ret) {
144         APP_LOGE("GetLocalUdid error");
145         return;
146     }
147     std::string keyOfData = DeviceAndNameToKey(udid, bundleName);
148     Key key(keyOfData);
149     Status status = kvStorePtr_->Delete(key);
150     if (status == Status::IPC_ERROR) {
151         status = kvStorePtr_->Delete(key);
152         APP_LOGW("distribute database ipc error and try to call again, result = %{public}d", status);
153     }
154     if (status != Status::SUCCESS) {
155         APP_LOGE("delete key error: %{public}d", status);
156         return;
157     }
158     APP_LOGI("delete value to kvStore success");
159 }
160 
GetStorageDistributeInfo(const std::string & networkId,const std::string & bundleName,DistributedBundleInfo & info)161 bool DistributedDataStorage::GetStorageDistributeInfo(const std::string &networkId,
162     const std::string &bundleName, DistributedBundleInfo &info)
163 {
164     APP_LOGI("get DistributedBundleInfo");
165     {
166         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
167         if (!CheckKvStore()) {
168             APP_LOGE("kvStore is nullptr");
169             return false;
170         }
171     }
172     std::string udid;
173     int32_t ret = GetUdidByNetworkId(networkId, udid);
174     if (ret != 0) {
175         APP_LOGI("can not get udid by networkId error:%{public}d", ret);
176         return false;
177     }
178     std::string keyOfData = DeviceAndNameToKey(udid, bundleName);
179     APP_LOGI("keyOfData: [%{public}s]", keyOfData.c_str());
180     Key key(keyOfData);
181     Value value;
182     Status status = kvStorePtr_->Get(key, value);
183     if (status == Status::IPC_ERROR) {
184         status = kvStorePtr_->Get(key, value);
185         APP_LOGW("distribute database ipc error and try to call again, result = %{public}d", status);
186     }
187     if (status == Status::SUCCESS) {
188         if (!info.FromJsonString(value.ToString())) {
189             APP_LOGE("it's an error value");
190             kvStorePtr_->Delete(key);
191             return false;
192         }
193         return true;
194     }
195     APP_LOGE("get value status: %{public}d", status);
196     return false;
197 }
198 
DeviceAndNameToKey(const std::string & udid,const std::string & bundleName) const199 std::string DistributedDataStorage::DeviceAndNameToKey(
200     const std::string &udid, const std::string &bundleName) const
201 {
202     std::string key = udid + Constants::FILE_UNDERLINE + bundleName;
203     return key;
204 }
205 
CheckKvStore()206 bool DistributedDataStorage::CheckKvStore()
207 {
208     if (kvStorePtr_ != nullptr) {
209         return true;
210     }
211     int32_t tryTimes = MAX_TIMES;
212     while (tryTimes > 0) {
213         Status status = GetKvStore();
214         if (status == Status::SUCCESS && kvStorePtr_ != nullptr) {
215             return true;
216         }
217         APP_LOGI("CheckKvStore, Times: %{public}d", tryTimes);
218         usleep(SLEEP_INTERVAL);
219         tryTimes--;
220     }
221     return kvStorePtr_ != nullptr;
222 }
223 
GetKvStore()224 Status DistributedDataStorage::GetKvStore()
225 {
226     Options options = {
227         .createIfMissing = true,
228         .encrypt = false,
229         .autoSync = true,
230         .securityLevel = SecurityLevel::S1,
231         .kvStoreType = KvStoreType::SINGLE_VERSION,
232         .area = EL1,
233         .baseDir = BMS_KV_BASE_DIR + appId_.appId
234     };
235     Status status = dataManager_.GetSingleKvStore(options, appId_, storeId_, kvStorePtr_);
236     if (status != Status::SUCCESS) {
237         APP_LOGE("return error: %{public}d", status);
238     } else {
239         APP_LOGI("get kvStore success");
240     }
241     return status;
242 }
243 
TryTwice(const std::function<Status ()> & func) const244 void DistributedDataStorage::TryTwice(const std::function<Status()> &func) const
245 {
246     Status status = func();
247     if (status == Status::IPC_ERROR) {
248         status = func();
249         APP_LOGW("distribute database ipc error and try to call again, result = %{public}d", status);
250     }
251 }
252 
GetLocalUdid(std::string & udid)253 bool DistributedDataStorage::GetLocalUdid(std::string &udid)
254 {
255     char innerUdid[DEVICE_UDID_LENGTH] = {0};
256     int ret = GetDevUdid(innerUdid, DEVICE_UDID_LENGTH);
257     if (ret != 0) {
258         APP_LOGI("GetDevUdid failed ,ret:%{public}d", ret);
259         return false;
260     }
261     udid = std::string(innerUdid);
262     return true;
263 }
264 
GetUdidByNetworkId(const std::string & networkId,std::string & udid)265 int32_t DistributedDataStorage::GetUdidByNetworkId(const std::string &networkId, std::string &udid)
266 {
267     auto bundleMgr = DelayedSingleton<DistributedBms>::GetInstance()->GetBundleMgr();
268     if (bundleMgr == nullptr) {
269         APP_LOGE("Get bundleMgr shared_ptr nullptr");
270         return -1;
271     }
272     return bundleMgr->GetUdidByNetworkId(networkId, udid);
273 }
274 
ConvertToDistributedBundleInfo(const BundleInfo & bundleInfo)275 DistributedBundleInfo DistributedDataStorage::ConvertToDistributedBundleInfo(const BundleInfo &bundleInfo)
276 {
277     DistributedBundleInfo distributedBundleInfo;
278     distributedBundleInfo.bundleName = bundleInfo.name;
279     distributedBundleInfo.versionCode = bundleInfo.versionCode;
280     distributedBundleInfo.compatibleVersionCode = bundleInfo.compatibleVersion;
281     distributedBundleInfo.versionName = bundleInfo.versionName;
282     distributedBundleInfo.minCompatibleVersion = bundleInfo.minCompatibleVersionCode;
283     distributedBundleInfo.targetVersionCode = bundleInfo.targetVersion;
284     distributedBundleInfo.appId = bundleInfo.appId;
285     std::map<std::string, std::vector<DistributedAbilityInfo>> moduleAbilityInfos;
286     for (const auto &abilityInfo : bundleInfo.abilityInfos) {
287         DistributedAbilityInfo distributedAbilityInfo;
288         distributedAbilityInfo.abilityName = abilityInfo.name;
289         distributedAbilityInfo.permissions = abilityInfo.permissions;
290         distributedAbilityInfo.type = abilityInfo.type;
291         distributedAbilityInfo.enabled = abilityInfo.enabled;
292         auto infoItem = moduleAbilityInfos.find(abilityInfo.moduleName);
293         if (infoItem == moduleAbilityInfos.end()) {
294             std::vector<DistributedAbilityInfo> distributedAbilityInfos;
295             distributedAbilityInfos.emplace_back(distributedAbilityInfo);
296             moduleAbilityInfos.emplace(abilityInfo.moduleName, distributedAbilityInfos);
297         } else {
298             moduleAbilityInfos[abilityInfo.moduleName].emplace_back(distributedAbilityInfo);
299         }
300     }
301     for (const auto& moduleAbilityInfo : moduleAbilityInfos) {
302         DistributedModuleInfo distributedModuleInfo;
303         distributedModuleInfo.moduleName = moduleAbilityInfo.first;
304         distributedModuleInfo.abilities = moduleAbilityInfo.second;
305         distributedBundleInfo.moduleInfos.emplace_back(distributedModuleInfo);
306     }
307     distributedBundleInfo.enabled = bundleInfo.applicationInfo.enabled;
308     return distributedBundleInfo;
309 }
310 
UpdateDistributedData(int32_t userId)311 void DistributedDataStorage::UpdateDistributedData(int32_t userId)
312 {
313     APP_LOGI("UpdateDistributedData");
314     if (kvStorePtr_ == nullptr) {
315         APP_LOGE("kvStorePtr_ is null");
316         return;
317     }
318     std::string udid;
319     if (!GetLocalUdid(udid)) {
320         APP_LOGE("GetLocalUdid failed");
321         return;
322     }
323     Key allEntryKeyPrefix("");
324     std::vector<Entry> allEntries;
325     Status status = kvStorePtr_->GetEntries(allEntryKeyPrefix, allEntries);
326     if (status != Status::SUCCESS) {
327         APP_LOGE("dataManager_ GetEntries error: %{public}d", status);
328         return;
329     }
330     for (auto entry : allEntries) {
331         std::string key = entry.key.ToString();
332         if (key.find(udid) == std::string::npos) {
333             continue;
334         }
335         status = kvStorePtr_->Delete(entry.key);
336         if (status != Status::SUCCESS) {
337             APP_LOGE("Delete key:%{public}s failed", key.c_str());
338         }
339     }
340     auto bundleMgr = DelayedSingleton<DistributedBms>::GetInstance()->GetBundleMgr();
341     if (bundleMgr == nullptr) {
342         APP_LOGE("Get bundleMgr shared_ptr nullptr");
343         return;
344     }
345     std::vector<BundleInfo> bundleInfos;
346     if (!bundleMgr->GetBundleInfos(FLAGS, bundleInfos, userId)) {
347         APP_LOGE("get bundleInfos failed");
348         return;
349     }
350     for (auto bundleInfo : bundleInfos) {
351         if (bundleInfo.singleton) {
352             continue;
353         }
354         if (!InnerSaveStorageDistributeInfo(ConvertToDistributedBundleInfo(bundleInfo))) {
355             APP_LOGW("UpdateDistributedData SaveStorageDistributeInfo:%{public}s failed", bundleInfo.name.c_str());
356         }
357     }
358 }
359 }  // namespace AppExecFwk
360 }  // namespace OHOS