1 /*
2  * Copyright (c) 2021-2024 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 "device_profile_storage_manager.h"
17 
18 #include <chrono>
19 #include <thread>
20 
21 #include "device_profile_errors.h"
22 #include "device_profile_log.h"
23 #include "device_profile_utils.h"
24 #include "dp_device_manager.h"
25 #include "dp_radar_helper.h"
26 #include "hisysevent.h"
27 #include "hitrace_meter.h"
28 #include "sync_coordinator.h"
29 
30 #include "ipc_object_proxy.h"
31 #include "ipc_skeleton.h"
32 #include "iservice_registry.h"
33 #include "subscribe_info.h"
34 #include "subscribe_manager.h"
35 #include "system_ability_definition.h"
36 
37 namespace OHOS {
38 namespace DeviceProfile {
39 using namespace OHOS::HiviewDFX;
40 using namespace std::chrono_literals;
41 using namespace OHOS::DistributedKv;
42 
43 namespace {
44 const std::string TAG = "DeviceProfileStorageManager";
45 
46 const std::string SERVICE_TYPE = "type";
47 const std::string SERVICES = "services";
48 const std::string DP_SYNC_FAILED = "DP_SYNC_FAILED";
49 const std::string DP_SYNC_EVENT = "DP_SYNC_EVENT";
50 const std::string FAULT_CODE_KEY = "FAULT_CODE";
51 const std::string DP_DEVICE_PUT_TRACE = "DP_DEVICE_PUT";
52 const std::string DP_DEVICE_GET_TRACE = "DP_DEVICE_GET";
53 const std::string DP_DEVICE_DELETE_TRACE = "DP_DEVICE_DELETE";
54 const std::string DP_DEVICE_SYNC_TRACE = "DP_DEVICE_SYNC";
55 constexpr int32_t RETRY_TIMES_WAIT_KV_DATA = 600;
56 constexpr int32_t FIX_TASK_ID = 0;
57 constexpr int32_t DELAY_TIME_MS = 100;
58 constexpr int32_t INDENT = -1;
59 const char INDENT_CHAR = ' ';
60 }
61 
62 IMPLEMENT_SINGLE_INSTANCE(DeviceProfileStorageManager);
63 
Init()64 bool DeviceProfileStorageManager::Init()
65 {
66     std::lock_guard<std::mutex> lock(initLock_);
67     if (!inited_) {
68         if (!SyncCoordinator::GetInstance().Init()) {
69             HILOGE("SyncCoordinator init failed");
70             return false;
71         }
72         DpDeviceManager::GetInstance().GetLocalDeviceUdid(localUdid_);
73         if (localUdid_.empty()) {
74             HILOGE("get local udid failed");
75             return false;
76         }
77         onlineSyncTbl_ = std::make_shared<OnlineSyncTable>();
78         kvStoreDeathRecipientDp_ = sptr<IRemoteObject::DeathRecipient>(new KvStoreDeathRecipientDp());
79         auto runner = AppExecFwk::EventRunner::Create("dpstorage");
80         storageHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
81         if (storageHandler_ == nullptr) {
82             return false;
83         }
84         inited_ = true;
85     }
86 
87     bool isKvServiceLoad = WaitKvDataService();
88     if (!isKvServiceLoad) {
89         HILOGE("WaitKvDataService fail!");
90         std::lock_guard<std::mutex> autoLock(serviceLock_);
91         profileItems_.clear();
92         kvDataServiceFailed_ = true;
93         return false;
94     }
95     HILOGI("WaitKvDataService success!");
96     auto callback = std::bind(&DeviceProfileStorageManager::OnKvStoreInitDone, this);
97     onlineSyncTbl_->RegisterKvStoreInitCallback(callback);
98     onlineSyncTbl_->Init();
99 
100     HILOGI("init succeeded");
101     return true;
102 }
103 
WaitKvDataService()104 bool DeviceProfileStorageManager::WaitKvDataService()
105 {
106     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
107     if (samgrProxy == nullptr) {
108         HILOGE("get samgrProxy failed");
109         return false;
110     }
111     int32_t retryTimes = RETRY_TIMES_WAIT_KV_DATA;
112     do {
113         auto kvDataSvr = samgrProxy->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID);
114         if (kvDataSvr != nullptr) {
115             IPCObjectProxy* proxy = reinterpret_cast<IPCObjectProxy*>(kvDataSvr.GetRefPtr());
116             if (proxy != nullptr && !proxy->IsObjectDead()) {
117                 HILOGI("get service succeed");
118                 proxy->AddDeathRecipient(kvStoreDeathRecipientDp_);
119                 return true;
120             }
121         }
122         HILOGD("waiting for service...");
123         std::this_thread::sleep_for(std::chrono::milliseconds(DELAY_TIME_MS));
124         if (--retryTimes <= 0) {
125             HILOGE("waiting service timeout(60)s");
126             return false;
127         }
128     } while (true);
129     return false;
130 }
131 
GenerateKey(const std::string & udid,const std::string & key,KeyType keyType)132 std::string DeviceProfileStorageManager::GenerateKey(const std::string& udid,
133     const std::string& key, KeyType keyType)
134 {
135     std::string tmp;
136     tmp.append(udid).append("/").append(std::to_string(static_cast<int8_t>(keyType))).append("/").append(key);
137     return tmp;
138 }
139 
PutDeviceProfile(const ServiceCharacteristicProfile & profile)140 int32_t DeviceProfileStorageManager::PutDeviceProfile(const ServiceCharacteristicProfile& profile)
141 {
142     HITRACE_METER_NAME(HITRACE_TAG_DEVICE_PROFILE, DP_DEVICE_PUT_TRACE);
143     if (onlineSyncTbl_ == nullptr) {
144         HILOGE("onlineSyncTbl is nullptr!");
145         return ERR_DP_INIT_DB_FAILED;
146     }
147     if (kvDataServiceFailed_ || onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_FAILED) {
148         HILOGE("kvstore init failed");
149         return ERR_DP_INIT_DB_FAILED;
150     }
151 
152     std::vector<std::string> keys;
153     std::vector<std::string> values;
154     std::string serviceId = profile.GetServiceId();
155     keys.emplace_back(GenerateKey(localUdid_, serviceId, KeyType::SERVICE));
156     values.emplace_back(profile.GetCharacteristicProfileJson());
157     std::unique_lock<std::mutex> autoLock(serviceLock_);
158     if (servicesJson_[serviceId] == nullptr) {
159         nlohmann::json j;
160         j[SERVICE_TYPE] = profile.GetServiceType();
161         servicesJson_[serviceId] = j;
162         keys.emplace_back(GenerateKey(localUdid_, SERVICES, KeyType::SERVICE_LIST));
163         values.emplace_back(servicesJson_.dump(INDENT, INDENT_CHAR, false, nlohmann::json::error_handler_t::ignore));
164     }
165 
166     int32_t errCode = ERR_OK;
167     if (onlineSyncTbl_ != nullptr && onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_SUCCEED) {
168         autoLock.unlock();
169         if (keys.size() > 1) {
170             errCode = onlineSyncTbl_->PutDeviceProfileBatch(keys, values);
171         } else {
172             errCode = onlineSyncTbl_->PutDeviceProfile(keys[0], values[0]);
173         }
174     } else {
175         for (size_t i = 0; i < keys.size(); i++) {
176             profileItems_[keys[i]] = values[i];
177         }
178     }
179     struct RadarInfo info = {
180         .funcName = "PutDeviceProfile",
181         .stageRes = (errCode == ERR_OK) ?
182             static_cast<int32_t>(StageRes::STAGE_SUCC) : static_cast<int32_t>(StageRes::STAGE_FAIL),
183         .toCallPkg = kvNAME,
184         .hostName = DpRadarHelper::GetInstance().GetHostNameByServiceId(serviceId),
185         .localUdid = localUdid_,
186         .errCode = ERR_DP_ADD_DATA_FAILED,
187     };
188     if (!DpRadarHelper::GetInstance().ReportAddData(info)) {
189         HILOGE("ReportAddData failed");
190     }
191     return errCode;
192 }
193 
GetDeviceProfile(const std::string & udid,const std::string & serviceId,ServiceCharacteristicProfile & profile)194 int32_t DeviceProfileStorageManager::GetDeviceProfile(const std::string& udid,
195     const std::string& serviceId, ServiceCharacteristicProfile& profile)
196 {
197     HITRACE_METER_NAME(HITRACE_TAG_DEVICE_PROFILE, DP_DEVICE_GET_TRACE);
198     if (onlineSyncTbl_ == nullptr) {
199         HILOGE("onlineSyncTbl is nullptr!");
200         return ERR_DP_INIT_DB_FAILED;
201     }
202     if (onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_FAILED) {
203         HILOGE("kvstore init failed");
204         return ERR_DP_INIT_DB_FAILED;
205     }
206 
207     std::string key;
208     std::string value;
209     int32_t result = ERR_OK;
210     if (udid.empty()) {
211         key = GenerateKey(localUdid_, serviceId, KeyType::SERVICE);
212         SetServiceType(udid, serviceId, profile);
213     } else {
214         std::string queryUdid;
215         if (!DpDeviceManager::GetInstance().TransformDeviceId(udid, queryUdid,
216             DeviceIdType::UDID)) {
217             HILOGE("transform to networkid failed");
218             return ERR_DP_INVALID_PARAMS;
219         }
220         key = GenerateKey(queryUdid, serviceId, KeyType::SERVICE);
221         SetServiceType(queryUdid, serviceId, profile);
222     }
223     std::unique_lock<std::mutex> autoLock(serviceLock_);
224     auto itItem = profileItems_.find(key);
225     if (itItem != profileItems_.end()) {
226         value = profileItems_[key];
227     } else {
228         autoLock.unlock();
229         result = onlineSyncTbl_->GetDeviceProfile(udid, key, value);
230     }
231     struct RadarInfo info = {
232         .funcName = "GetDeviceProfile",
233         .stageRes = (result == ERR_OK) ?
234             static_cast<int32_t>(StageRes::STAGE_SUCC) : static_cast<int32_t>(StageRes::STAGE_FAIL),
235         .toCallPkg = kvNAME,
236         .hostName = DpRadarHelper::GetInstance().GetHostNameByServiceId(serviceId),
237         .localUdid = localUdid_,
238         .errCode = ERR_DP_GET_DATA_FAILED,
239     };
240     if (!DpRadarHelper::GetInstance().ReportGetData(info)) {
241         HILOGE("ReportGetData failed");
242     }
243     profile.SetServiceId(serviceId);
244     profile.SetCharacteristicProfileJson(value);
245     return result;
246 }
247 
SetServiceType(const std::string & udid,const std::string & serviceId,ServiceCharacteristicProfile & profile)248 void DeviceProfileStorageManager::SetServiceType(const std::string& udid,
249     const std::string& serviceId, ServiceCharacteristicProfile& profile)
250 {
251     std::unique_lock<std::mutex> autoLock(serviceLock_);
252     if (udid.empty()) {
253         auto jsonData = servicesJson_[serviceId];
254         if (jsonData != nullptr) {
255             profile.SetServiceType(jsonData[SERVICE_TYPE]);
256         }
257         return;
258     }
259 
260     std::string value;
261     std::string key = GenerateKey(udid, SERVICES, KeyType::SERVICE_LIST);
262     int32_t result = onlineSyncTbl_->GetDeviceProfile(key, value);
263     if (result != ERR_OK) {
264         HILOGE("get service type failed");
265         return;
266     }
267     auto jsonData = nlohmann::json::parse(value, nullptr, false);
268     if (jsonData.is_discarded()) {
269         HILOGE("parse error");
270         return;
271     }
272     auto typeData = jsonData[serviceId];
273     if (typeData != nullptr && typeData[SERVICE_TYPE] != nullptr) {
274         profile.SetServiceType(typeData[SERVICE_TYPE]);
275     }
276 }
277 
DeleteDeviceProfile(const std::string & serviceId)278 int32_t DeviceProfileStorageManager::DeleteDeviceProfile(const std::string& serviceId)
279 {
280     HITRACE_METER_NAME(HITRACE_TAG_DEVICE_PROFILE, DP_DEVICE_DELETE_TRACE);
281     if (onlineSyncTbl_ == nullptr) {
282         HILOGE("onlineSyncTbl_ is null");
283         return ERR_DP_INVALID_PARAMS;
284     }
285     if (onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_FAILED) {
286         HILOGE("kvstore init failed");
287         return ERR_DP_INIT_DB_FAILED;
288     }
289     std::unique_lock<std::mutex> autoLock(serviceLock_);
290     if (servicesJson_[serviceId] == nullptr) {
291         HILOGW("can't find service %{public}s", serviceId.c_str());
292         return ERR_DP_INVALID_PARAMS;
293     }
294     nlohmann::json original = servicesJson_[serviceId];
295     servicesJson_.erase(serviceId);
296     std::string servicesKey = GenerateKey(localUdid_, SERVICES, KeyType::SERVICE_LIST);
297     std::string servicesValue = servicesJson_.dump();
298     int32_t errCode = ERR_OK;
299     std::string serviceKey = GenerateKey(localUdid_, serviceId, KeyType::SERVICE);
300     struct RadarInfo info = {
301         .funcName = "DeleteDeviceProfile",
302         .toCallPkg = kvNAME,
303         .hostName = DpRadarHelper::GetInstance().GetHostNameByServiceId(serviceId),
304         .localUdid = localUdid_,
305     };
306     if (onlineSyncTbl_ != nullptr && onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_SUCCEED) {
307         errCode = onlineSyncTbl_->DeleteDeviceProfile(serviceKey);
308         if (errCode != ERR_OK) {
309             servicesJson_[serviceId] = std::move(original);
310             return errCode;
311         }
312         errCode = onlineSyncTbl_->PutDeviceProfile(servicesKey, servicesValue);
313         info.stageRes = (errCode == ERR_OK) ?
314             static_cast<int32_t>(StageRes::STAGE_SUCC) : static_cast<int32_t>(StageRes::STAGE_FAIL);
315         info.errCode = ERR_DP_DELETE_DATA_FAILED;
316         if (errCode != ERR_OK) {
317             HILOGW("update services failed, errorCode = %{public}d", errCode);
318         }
319     } else {
320         info.stageRes = static_cast<int32_t>(StageRes::STAGE_SUCC);
321         profileItems_.erase(serviceKey);
322         profileItems_[servicesKey] = std::move(servicesValue);
323     }
324     if (!DpRadarHelper::GetInstance().ReportDeleteData(info)) {
325         HILOGE("ReportDeleteData failed");
326     }
327     return errCode;
328 }
329 
RemoveUnBoundDeviceProfile(const std::string & udid)330 int32_t DeviceProfileStorageManager::RemoveUnBoundDeviceProfile(const std::string& udid)
331 {
332     if (onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_FAILED) {
333         HILOGE("kvstore init failed");
334         return ERR_DP_INIT_DB_FAILED;
335     }
336 
337     std::unique_lock<std::mutex> autoLock(serviceLock_);
338     if (onlineSyncTbl_->GetInitStatus() != StorageInitStatus::INIT_SUCCEED) {
339         HILOGE("kvstore not init");
340         return ERR_DP_NOT_INIT_DB;
341     }
342 
343     int32_t errCode = ERR_OK;
344     std::string networkId;
345     if (!DpDeviceManager::GetInstance().TransformDeviceId(udid, networkId, DeviceIdType::NETWORKID)) {
346         HILOGE("udid transform to networkid failed, udid = %{public}s",
347             DeviceProfileUtils::AnonymizeDeviceId(udid).c_str());
348         return ERR_DP_GET_NETWORKID_FAILED;
349     }
350 
351     errCode = onlineSyncTbl_->RemoveDeviceData(networkId);
352     return errCode;
353 }
354 
RemoveRemoteDeviceProfile()355 int32_t DeviceProfileStorageManager::RemoveRemoteDeviceProfile()
356 {
357     if (onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_FAILED) {
358         HILOGE("kvstore init failed");
359         return ERR_DP_INIT_DB_FAILED;
360     }
361 
362     if (onlineSyncTbl_->GetInitStatus() != StorageInitStatus::INIT_SUCCEED) {
363         HILOGE("kvstore not init");
364         return ERR_DP_NOT_INIT_DB;
365     }
366     int errCode = onlineSyncTbl_->RemoveDeviceData("");
367     return errCode;
368 }
369 
SyncDeviceProfile(const SyncOptions & syncOptions,const sptr<IRemoteObject> & profileEventNotifier)370 int32_t DeviceProfileStorageManager::SyncDeviceProfile(const SyncOptions& syncOptions,
371     const sptr<IRemoteObject>& profileEventNotifier)
372 {
373     if (onlineSyncTbl_ == nullptr || onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_FAILED) {
374         HILOGE("kvstore init failed");
375         return ERR_DP_INIT_DB_FAILED;
376     }
377     if (!CheckSyncOption(syncOptions)) {
378         HILOGW("device list has offline device");
379         return ERR_DP_INVALID_PARAMS;
380     }
381     int32_t result = NotifySyncStart(profileEventNotifier);
382     if (result != ERR_OK) {
383         return result;
384     }
385     StartAsyncTrace(HITRACE_TAG_DEVICE_PROFILE, DP_DEVICE_SYNC_TRACE, FIX_TASK_ID);
386     auto syncTask = [syncOptions, this]() {
387         HILOGI("start sync");
388         ReportBehaviorEvent(DP_SYNC_EVENT);
389         auto devicesList = syncOptions.GetDeviceList();
390         if (devicesList.empty()) {
391             DpDeviceManager::GetInstance().GetDeviceIdList(devicesList);
392         }
393         SyncCoordinator::GetInstance().SetSyncTrigger(false);
394         std::vector<std::string> devicesVector(std::vector<std::string> { devicesList.begin(), devicesList.end() });
395         int32_t result = onlineSyncTbl_->SyncDeviceProfile(devicesVector, syncOptions.GetSyncMode());
396         struct RadarInfo info = {
397             .stageRes = (result == ERR_OK) ?
398                 static_cast<int32_t>(StageRes::STAGE_IDLE) : static_cast<int32_t>(StageRes::STAGE_FAIL),
399             .bizState = (result == ERR_OK) ?
400                 static_cast<int32_t>(BizState::BIZ_STATE_START) : static_cast<int32_t>(BizState::BIZ_STATE_END),
401             .peerUdid = DpRadarHelper::GetInstance().GetStringUdidList(devicesList),
402             .errCode = ERR_DP_SYNC_DATA_FAILED,
403         };
404         if (!DpRadarHelper::GetInstance().ReportSyncData(info)) {
405             HILOGE("ReportSyncData failed");
406         }
407         if (result != ERR_OK) {
408             ReportFaultEvent(DP_SYNC_FAILED, FAULT_CODE_KEY, result);
409             HILOGE("sync failed result : %{public}d", result);
410             NotifySyncCompleted();
411             return;
412         }
413     };
414     if (!SyncCoordinator::GetInstance().DispatchSyncTask(syncTask)) {
415         HILOGE("post sync task failed");
416         NotifySyncCompleted();
417         return ERR_DP_POST_TASK_FAILED;
418     }
419     return ERR_OK;
420 }
421 
NotifySyncStart(const sptr<IRemoteObject> & profileEventNotifier)422 int32_t DeviceProfileStorageManager::NotifySyncStart(const sptr<IRemoteObject>& profileEventNotifier)
423 {
424     {
425         std::lock_guard<std::mutex> autoLock(profileSyncLock_);
426         syncEventNotifier_ = profileEventNotifier;
427     }
428 
429     SubscribeInfo subscribeInfo;
430     subscribeInfo.profileEvent = ProfileEvent::EVENT_SYNC_COMPLETED;
431     std::list<SubscribeInfo> subscribeInfos;
432     subscribeInfos.emplace_back(subscribeInfo);
433     std::list<ProfileEvent> failedEvents;
434     if (SubscribeManager::GetInstance().SubscribeProfileEvents(
435         subscribeInfos, profileEventNotifier, failedEvents) != ERR_OK) {
436         HILOGE("subscribe sync event failed");
437         SyncCoordinator::GetInstance().ReleaseSync();
438         std::lock_guard<std::mutex> autoLock(profileSyncLock_);
439         syncEventNotifier_ = nullptr;
440         return ERR_DP_SUBSCRIBE_FAILED;
441     }
442     return ERR_OK;
443 }
444 
NotifySyncCompleted()445 void DeviceProfileStorageManager::NotifySyncCompleted()
446 {
447     HILOGI("called");
448     SyncCoordinator::GetInstance().ReleaseSync();
449     FinishAsyncTrace(HITRACE_TAG_DEVICE_PROFILE, DP_DEVICE_SYNC_TRACE, FIX_TASK_ID);
450     std::lock_guard<std::mutex> autoLock(profileSyncLock_);
451     std::list<ProfileEvent> profileEvents;
452     profileEvents.emplace_back(ProfileEvent::EVENT_SYNC_COMPLETED);
453     std::list<ProfileEvent> failedEvents;
454     int32_t ret = SubscribeManager::GetInstance().UnsubscribeProfileEvents(
455         profileEvents, syncEventNotifier_, failedEvents);
456     if (ret != ERR_OK) {
457         HILOGW("unsubscribe sync event failed");
458     }
459     syncEventNotifier_ = nullptr;
460 }
461 
NotifySubscriberDied(const sptr<IRemoteObject> & profileEventNotifier)462 void DeviceProfileStorageManager::NotifySubscriberDied(const sptr<IRemoteObject>& profileEventNotifier)
463 {
464     HILOGI("called");
465     std::lock_guard<std::mutex> autoLock(profileSyncLock_);
466     if (profileEventNotifier != syncEventNotifier_) {
467         return;
468     }
469 
470     SyncCoordinator::GetInstance().ReleaseSync();
471     syncEventNotifier_ = nullptr;
472 }
473 
CheckSyncOption(const SyncOptions & syncOptions)474 bool DeviceProfileStorageManager::CheckSyncOption(const SyncOptions& syncOptions)
475 {
476     std::list<std::shared_ptr<DeviceInfo>> onlineDevices;
477     DpDeviceManager::GetInstance().GetDeviceList(onlineDevices);
478     std::list<std::string> onlineDeviceIds;
479     for (const auto& onlineDevice : onlineDevices) {
480         onlineDeviceIds.emplace_back(onlineDevice->GetNetworkId());
481     }
482 
483     // check whether deviceId is online
484     auto syncDeviceIds = syncOptions.GetDeviceList();
485     for (const auto& syncDeviceId : syncDeviceIds) {
486         auto iter = find(onlineDeviceIds.begin(), onlineDeviceIds.end(), syncDeviceId);
487         if (iter == onlineDeviceIds.end()) {
488             HILOGE("deviceId: %{public}s is not online", DeviceProfileUtils::AnonymizeDeviceId(syncDeviceId).c_str());
489             return false;
490         }
491     }
492     return true;
493 }
494 
RestoreServiceItemLocked(const std::string & value)495 void DeviceProfileStorageManager::RestoreServiceItemLocked(const std::string& value)
496 {
497     auto restoreItems = nlohmann::json::parse(value, nullptr, false);
498     if (restoreItems.is_discarded()) {
499         HILOGE("parse error");
500         return;
501     }
502     for (const auto& [key, value] : servicesJson_.items()) {
503         restoreItems[key] = value;
504     }
505     servicesJson_ = std::move(restoreItems);
506 }
507 
FlushProfileItems()508 void DeviceProfileStorageManager::FlushProfileItems()
509 {
510     std::string services;
511     std::string servicesKey = GenerateKey(localUdid_, SERVICES, KeyType::SERVICE_LIST);
512     int32_t errCode = onlineSyncTbl_->GetDeviceProfile(servicesKey, services);
513     std::unique_lock<std::mutex> autoLock(serviceLock_);
514     if (errCode == ERR_OK) {
515         RestoreServiceItemLocked(services);
516     }
517 
518     std::vector<std::string> keys;
519     std::vector<std::string> values;
520     size_t itemSize = profileItems_.size();
521     HILOGI("profile item size = %{public}zu", itemSize);
522     if (itemSize == 0) {
523         return;
524     }
525     keys.reserve(itemSize);
526     values.reserve(itemSize);
527     // update service list to avoid overwriting the value in db storage
528     profileItems_[servicesKey] = servicesJson_.dump();
529     for (const auto& [key, value] : profileItems_) {
530         keys.emplace_back(key);
531         values.emplace_back(value);
532     }
533     profileItems_.clear();
534     autoLock.unlock();
535 
536     errCode = onlineSyncTbl_->PutDeviceProfileBatch(keys, values);
537     if (errCode != ERR_OK) {
538         HILOGE("put failed, errCode = %{public}d", errCode);
539     }
540 }
541 
RegisterCallbacks()542 void DeviceProfileStorageManager::RegisterCallbacks()
543 {
544     HILOGI("called");
545     int32_t errCode = ERR_OK;
546     if (kvStoreObserver_ != nullptr) {
547         errCode = onlineSyncTbl_->SubscribeKvStore(kvStoreObserver_);
548         HILOGI("SubscribeKvStore errCode = %{public}d", errCode);
549     }
550     if (kvStoreSyncCallback_ != nullptr) {
551         errCode = onlineSyncTbl_->RegisterSyncCallback(kvStoreSyncCallback_);
552         HILOGI("RegisterSyncCallback errCode = %{public}d", errCode);
553     }
554 }
555 
OnKvStoreInitDone()556 void DeviceProfileStorageManager::OnKvStoreInitDone()
557 {
558     RegisterCallbacks();
559     FlushProfileItems();
560 }
561 
SubscribeKvStore(const std::shared_ptr<KvStoreObserver> & observer)562 int32_t DeviceProfileStorageManager::SubscribeKvStore(const std::shared_ptr<KvStoreObserver>& observer)
563 {
564     std::lock_guard<std::mutex> autoLock(callbackLock_);
565     kvStoreObserver_ = observer;
566     if (onlineSyncTbl_ != nullptr && onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_SUCCEED) {
567         return onlineSyncTbl_->SubscribeKvStore(observer);
568     }
569     return ERR_OK;
570 }
571 
UnSubscribeKvStore(const std::shared_ptr<KvStoreObserver> & observer)572 int32_t DeviceProfileStorageManager::UnSubscribeKvStore(const std::shared_ptr<KvStoreObserver>& observer)
573 {
574     std::lock_guard<std::mutex> autoLock(callbackLock_);
575     kvStoreObserver_ = nullptr;
576     return onlineSyncTbl_->UnSubscribeKvStore(observer);
577 }
578 
RegisterSyncCallback(const std::shared_ptr<KvStoreSyncCallback> & sycnCb)579 int32_t DeviceProfileStorageManager::RegisterSyncCallback(const std::shared_ptr<KvStoreSyncCallback>& sycnCb)
580 {
581     std::lock_guard<std::mutex> autoLock(callbackLock_);
582     kvStoreSyncCallback_ = sycnCb;
583     if (onlineSyncTbl_ != nullptr && onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_SUCCEED) {
584         return onlineSyncTbl_->RegisterSyncCallback(sycnCb);
585     }
586     return ERR_OK;
587 }
588 
UnRegisterSyncCallback()589 int32_t DeviceProfileStorageManager::UnRegisterSyncCallback()
590 {
591     std::lock_guard<std::mutex> autoLock(callbackLock_);
592     kvStoreSyncCallback_ = nullptr;
593     return onlineSyncTbl_->UnRegisterSyncCallback();
594 }
595 
ReportBehaviorEvent(const std::string & event)596 void DeviceProfileStorageManager::ReportBehaviorEvent(const std::string& event)
597 {
598     int ret = HiSysEventWrite(HiSysEvent::Domain::DEVICE_PROFILE, event, HiSysEvent::EventType::BEHAVIOR);
599     if (ret != 0) {
600         HILOGE("hisysevent write failed! ret %{public}d.", ret);
601     }
602 }
603 
ReportFaultEvent(const std::string & event,const std::string & key,const int32_t result)604 void DeviceProfileStorageManager::ReportFaultEvent(const std::string& event,
605     const std::string& key, const int32_t result)
606 {
607     int ret = HiSysEventWrite(HiSysEvent::Domain::DEVICE_PROFILE, event, HiSysEvent::EventType::FAULT, key, result);
608     if (ret != 0) {
609         HILOGE("hisysevent write failed! ret %{public}d.", ret);
610     }
611 }
612 
DumpLocalProfile(std::string & result)613 void DeviceProfileStorageManager::DumpLocalProfile(std::string& result)
614 {
615     for (const auto& [key, value] : servicesJson_.items()) {
616         result.append("key:");
617         result.append(key);
618         result.append(" value:");
619         result.append(value.dump());
620         result.append("\n");
621     }
622 }
623 } // namespace DeviceProfile
624 } // namespace OHOS
625