1 /*
2  * Copyright (c) 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 <mutex>
17 #include <memory>
18 #include <algorithm>
19 #include <dlfcn.h>
20 #include <vector>
21 
22 #include "static_profile_manager.h"
23 
24 #include "distributed_device_profile_errors.h"
25 #include "distributed_device_profile_log.h"
26 #include "event_handler_factory.h"
27 #include "kv_data_change_listener.h"
28 #include "kv_store_death_recipient.h"
29 #include "kv_sync_completed_listener.h"
30 #include "kv_adapter.h"
31 #include "profile_cache.h"
32 #include "profile_control_utils.h"
33 #include "profile_utils.h"
34 #include "permission_manager.h"
35 #include "static_capability_loader.h"
36 
37 namespace OHOS {
38 namespace DistributedDeviceProfile {
39 IMPLEMENT_SINGLE_INSTANCE(StaticProfileManager);
40 namespace {
41     const std::string TAG = "StaticProfileManager";
42     const std::string APP_ID = "distributed_device_profile_service";
43     const std::string STORE_ID = "dp_kv_static_store";
44 }
45 
Init()46 int32_t StaticProfileManager::Init()
47 {
48     HILOGI("call!");
49     int32_t initResult = DP_MANAGER_INIT_FAIL;
50     {
51         std::lock_guard<std::mutex> lock(staticStoreMutex_);
52         staticProfileStore_ = std::make_shared<KVAdapter>(APP_ID, STORE_ID,
53             std::make_shared<KvDataChangeListener>(STORE_ID),
54             std::make_shared<KvSyncCompletedListener>(STORE_ID), std::make_shared<KvDeathRecipient>(STORE_ID),
55             DistributedKv::TYPE_STATICS);
56         initResult = staticProfileStore_->Init();
57     }
58     HILOGI("Init finish, res: %{public}d", initResult);
59     return initResult;
60 }
61 
UnInit()62 int32_t StaticProfileManager::UnInit()
63 {
64     HILOGI("call!");
65     {
66         std::lock_guard<std::mutex> lock(staticStoreMutex_);
67         if (staticProfileStore_ == nullptr) {
68             HILOGE("staticProfileStore_ is nullptr!");
69             return DP_NULLPTR;
70         }
71         staticProfileStore_->UnInit();
72         staticProfileStore_ = nullptr;
73     }
74     return DP_SUCCESS;
75 }
76 
ReInit()77 int32_t StaticProfileManager::ReInit()
78 {
79     HILOGI("call!");
80     UnInit();
81     return Init();
82 }
83 
PutCharacteristicProfile(const CharacteristicProfile & charProfile)84 int32_t StaticProfileManager::PutCharacteristicProfile(const CharacteristicProfile& charProfile)
85 {
86     HILOGD("call!");
87     int32_t putResult = DP_PUT_CHARACTERISTIC_CACHE_ERR;
88     {
89         std::lock_guard<std::mutex> lock(staticStoreMutex_);
90         putResult = ProfileControlUtils::PutCharacteristicProfile(staticProfileStore_, charProfile);
91     }
92     HILOGI("PutCharacteristicProfile result: %{public}d!", putResult);
93     return putResult;
94 }
95 
GetCharacteristicProfile(const std::string & deviceId,const std::string & serviceName,const std::string & characteristicKey,CharacteristicProfile & charProfile)96 int32_t StaticProfileManager::GetCharacteristicProfile(const std::string& deviceId, const std::string& serviceName,
97     const std::string& characteristicKey, CharacteristicProfile& charProfile)
98 {
99     HILOGD("call!");
100     if (!ProfileUtils::IsKeyValid(deviceId) || !ProfileUtils::IsKeyValid(serviceName) ||
101         !ProfileUtils::IsKeyValid(characteristicKey)) {
102         HILOGE("Params are invalid!");
103         return DP_INVALID_PARAMS;
104     }
105     HILOGD("deviceId: %{public}s, serviceName: %{public}s, charKey: %{public}s!",
106         ProfileUtils::GetAnonyString(deviceId).c_str(), serviceName.c_str(), characteristicKey.c_str());
107     if (ProfileCache::GetInstance().GetStaticCharacteristicProfile(deviceId, serviceName, characteristicKey,
108         charProfile) == DP_SUCCESS) {
109         HILOGI("profile: %{public}s!", charProfile.dump().c_str());
110         return DP_SUCCESS;
111     }
112     CharacteristicProfile staticCapabilityProfile;
113     int32_t getResult = DP_GET_KV_DB_FAIL;
114     {
115         std::lock_guard<std::mutex> lock(staticStoreMutex_);
116         getResult = ProfileControlUtils::GetCharacteristicProfile(staticProfileStore_, deviceId,
117             STATIC_CAPABILITY_SVR_ID, STATIC_CAPABILITY_CHAR_ID, staticCapabilityProfile);
118     }
119     if (getResult != DP_SUCCESS) {
120         HILOGE("GetCharacteristicProfile fail, reason: %{public}d!", getResult);
121         return getResult;
122     }
123     HILOGI("profile : %{public}s", staticCapabilityProfile.dump().c_str());
124     std::unordered_map<std::string, CharacteristicProfile> staticInfoProfiles;
125     int generateProfileResult = GenerateStaticInfoProfile(staticCapabilityProfile, staticInfoProfiles);
126     if (generateProfileResult != DP_SUCCESS) {
127         HILOGE("GenerateStaticInfoProfile fail, reason: %{public}d!", generateProfileResult);
128         return generateProfileResult;
129     }
130     std::string charProfileKey = ProfileUtils::GenerateCharProfileKey(deviceId, serviceName, characteristicKey);
131     if (staticInfoProfiles.find(charProfileKey) == staticInfoProfiles.end()) {
132         HILOGE("charKey not exist, deviceId: %{public}s, serviceName: %{public}s, characteristicKey: %{public}s",
133             ProfileUtils::GetAnonyString(deviceId).c_str(), serviceName.c_str(), characteristicKey.c_str());
134         return DP_NOT_FOUND_FAIL;
135     }
136     charProfile = staticInfoProfiles[charProfileKey];
137     ProfileCache::GetInstance().AddStaticCharProfileBatch(staticInfoProfiles);
138     return DP_SUCCESS;
139 }
140 
GetAllCharacteristicProfile(std::vector<CharacteristicProfile> & staticCapabilityProfiles)141 int32_t StaticProfileManager::GetAllCharacteristicProfile(
142     std::vector<CharacteristicProfile>& staticCapabilityProfiles)
143 {
144     HILOGD("call!");
145     int32_t getAllResult = DP_GET_KV_DB_FAIL;
146     {
147         std::lock_guard<std::mutex> lock(staticStoreMutex_);
148         getAllResult = ProfileControlUtils::GetAllCharacteristicProfile(staticProfileStore_, staticCapabilityProfiles);
149     }
150     if (getAllResult != DP_SUCCESS) {
151         HILOGE("GetAllCharacteristicProfile fail, reason: %{public}d!", getAllResult);
152         return getAllResult;
153     }
154     return DP_SUCCESS;
155 }
156 
GenerateStaticInfoProfile(const CharacteristicProfile & staticCapabilityProfile,std::unordered_map<std::string,CharacteristicProfile> & staticInfoProfiles)157 int32_t StaticProfileManager::GenerateStaticInfoProfile(const CharacteristicProfile& staticCapabilityProfile,
158     std::unordered_map<std::string, CharacteristicProfile>& staticInfoProfiles)
159 {
160     HILOGD("call!");
161     std::string charValue = staticCapabilityProfile.GetCharacteristicValue();
162     cJSON* charValueJson = cJSON_Parse(charValue.c_str());
163     if (!cJSON_IsObject(charValueJson)) {
164         HILOGE("cJSON_Parse fail! charValue : %{public}s", ProfileUtils::GetAnonyString(charValue).c_str());
165         cJSON_Delete(charValueJson);
166         return DP_PARSE_STATIC_CAP_FAIL;
167     }
168     cJSON* staticCapabilityVersionItem = cJSON_GetObjectItemCaseSensitive(charValueJson,
169         STATIC_CAPABILITY_VERSION.c_str());
170     if (!cJSON_IsString(staticCapabilityVersionItem) || (staticCapabilityVersionItem->valuestring == NULL)) {
171         HILOGE("staticCapabilityVersion is invalid!");
172         cJSON_Delete(charValueJson);
173         return DP_PARSE_STATIC_CAP_FAIL;
174     }
175     std::string staticCapabilityVersion = staticCapabilityVersionItem->valuestring;
176     cJSON* staticCapabilityValueItem = cJSON_GetObjectItemCaseSensitive(charValueJson, STATIC_CAPABILITY_VALUE.c_str());
177     if (!cJSON_IsString(staticCapabilityValueItem) || (staticCapabilityValueItem->valuestring == NULL)) {
178         HILOGE("staticCapabilityValue is invalid!");
179         cJSON_Delete(charValueJson);
180         return DP_PARSE_STATIC_CAP_FAIL;
181     }
182     std::string staticCapabilityValue = staticCapabilityValueItem->valuestring;
183     cJSON_Delete(charValueJson);
184     StaticCapabilityLoader::GetInstance().LoadStaticProfiles(staticCapabilityProfile.GetDeviceId(),
185         staticCapabilityValue, staticCapabilityVersion, staticInfoProfiles);
186     return DP_SUCCESS;
187 }
188 
E2ESyncStaticProfile(const DistributedHardware::DmDeviceInfo deviceInfo)189 void StaticProfileManager::E2ESyncStaticProfile(const DistributedHardware::DmDeviceInfo deviceInfo)
190 {
191     HILOGD("call!");
192     auto task = [this, deviceInfo]() {
193         std::string remoteNetworkId = deviceInfo.networkId;
194         HILOGD("networkId:%{public}s", ProfileUtils::GetAnonyString(remoteNetworkId).c_str());
195         if (remoteNetworkId.empty()) {
196             HILOGE("networkId or extraData is empty!");
197             return;
198         }
199         if (!ProfileUtils::IsOHBasedDevice(deviceInfo.extraData)) {
200             HILOGI("device is not ohbase. remoteNetworkId=%{public}s",
201                 ProfileUtils::GetAnonyString(remoteNetworkId).c_str());
202             return;
203         }
204         std::lock_guard<std::mutex> lock(staticStoreMutex_);
205         if (staticProfileStore_ == nullptr) {
206             HILOGE("staticProfileStore is nullptr");
207             return;
208         }
209         int32_t syncResult = staticProfileStore_->Sync({remoteNetworkId}, SyncMode::PUSH_PULL);
210         if (syncResult != DP_SUCCESS) {
211             HILOGE("E2ESyncStaticProfile fail, res: %{public}d!", syncResult);
212             return;
213         }
214         HILOGI("E2ESyncStaticProfile success!");
215     };
216     auto handler = EventHandlerFactory::GetInstance().GetEventHandler();
217     if (handler == nullptr || !handler->PostTask(task)) {
218         HILOGE("Post E2ESyncStaticProfile task fail!");
219         return;
220     }
221 }
222 } // namespace DistributedDeviceProfile
223 } // namespace OHOS
224