1 /*
2 * Copyright (c) 2023 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_adapter.h"
17
18 #include <algorithm>
19 #include <mutex>
20
21 #include "distributed_device_profile_client.h"
22 #include "service_characteristic_profile.h"
23 #include "sync_options.h"
24
25 #include "cooperate_util.h"
26 #include "devicestatus_define.h"
27 #include "json_parser.h"
28
29 namespace OHOS {
30 namespace Msdp {
31 namespace DeviceStatus {
32 using namespace OHOS::DeviceProfile;
33 namespace {
34 constexpr OHOS::HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "DeviceProfileAdapter" };
35 const std::string SERVICE_ID { "deviceStatus" };
36 } // namespace
37
DeviceProfileAdapter()38 DeviceProfileAdapter::DeviceProfileAdapter() {}
39
~DeviceProfileAdapter()40 DeviceProfileAdapter::~DeviceProfileAdapter()
41 {
42 std::lock_guard<std::mutex> guard(adapterLock_);
43 profileEventCallbacks_.clear();
44 callbacks_.clear();
45 }
46
UpdateCrossingSwitchState(bool state,const std::vector<std::string> & deviceIds)47 int32_t DeviceProfileAdapter::UpdateCrossingSwitchState(bool state, const std::vector<std::string> &deviceIds)
48 {
49 CALL_INFO_TRACE;
50 const std::string SERVICE_TYPE = "deviceStatus";
51 ServiceCharacteristicProfile profile;
52 profile.SetServiceId(SERVICE_ID);
53 profile.SetServiceType(SERVICE_TYPE);
54 cJSON *data = cJSON_CreateObject();
55 CHKPR(data, RET_ERR);
56 cJSON_AddItemToObject(data, characteristicsName_.c_str(), cJSON_CreateNumber(state));
57 char *smsg = cJSON_Print(data);
58 cJSON_Delete(data);
59 profile.SetCharacteristicProfileJson(smsg);
60 cJSON_free(smsg);
61
62 int32_t ret = DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile);
63 if (ret != 0) {
64 FI_HILOGE("Put device profile failed, ret:%{public}d", ret);
65 return ret;
66 }
67 SyncOptions syncOptions;
68 std::for_each(deviceIds.begin(), deviceIds.end(),
69 [&syncOptions](auto &networkId) {
70 syncOptions.AddDevice(networkId);
71 FI_HILOGD("Add device success");
72 });
73 auto syncCallback = std::make_shared<DeviceProfileAdapter::ProfileEventCallbackImpl>();
74 ret =
75 DistributedDeviceProfileClient::GetInstance().SyncDeviceProfile(syncOptions, syncCallback);
76 if (ret != 0) {
77 FI_HILOGE("Sync device profile failed");
78 }
79 return ret;
80 }
81
UpdateCrossingSwitchState(bool state)82 int32_t DeviceProfileAdapter::UpdateCrossingSwitchState(bool state)
83 {
84 CALL_INFO_TRACE;
85 const std::string SERVICE_TYPE = "deviceStatus";
86 ServiceCharacteristicProfile profile;
87 profile.SetServiceId(SERVICE_ID);
88 profile.SetServiceType(SERVICE_TYPE);
89 cJSON *data = cJSON_CreateObject();
90 CHKPR(data, RET_ERR);
91 cJSON_AddItemToObject(data, characteristicsName_.c_str(), cJSON_CreateNumber(state));
92 char *smsg = cJSON_Print(data);
93 cJSON_Delete(data);
94 profile.SetCharacteristicProfileJson(smsg);
95 cJSON_free(smsg);
96
97 return DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile);
98 }
99
GetCrossingSwitchState(const std::string & networkId)100 bool DeviceProfileAdapter::GetCrossingSwitchState(const std::string &networkId)
101 {
102 CALL_INFO_TRACE;
103 ServiceCharacteristicProfile profile;
104 DistributedDeviceProfileClient::GetInstance().GetDeviceProfile(networkId, SERVICE_ID, profile);
105 std::string jsonData = profile.GetCharacteristicProfileJson();
106 JsonParser parser;
107 parser.json = cJSON_Parse(jsonData.c_str());
108 if (!cJSON_IsObject(parser.json)) {
109 FI_HILOGE("parser json is not object");
110 return false;
111 }
112 cJSON* state = cJSON_GetObjectItemCaseSensitive(parser.json, characteristicsName_.c_str());
113 if (!cJSON_IsNumber(state)) {
114 FI_HILOGE("state is not number type");
115 return false;
116 }
117 return (static_cast<bool>(state->valueint));
118 }
119
RegisterCrossingStateListener(const std::string & networkId,DPCallback callback)120 int32_t DeviceProfileAdapter::RegisterCrossingStateListener(const std::string &networkId, DPCallback callback)
121 {
122 CHKPR(callback, RET_ERR);
123 if (networkId.empty()) {
124 FI_HILOGE("networkId is nullptr");
125 return RET_ERR;
126 }
127 std::lock_guard<std::mutex> guard(adapterLock_);
128 auto callbackIter = callbacks_.find(networkId);
129 if (callbackIter != callbacks_.end()) {
130 callbackIter->second = callback;
131 FI_HILOGW("Callback is updated");
132 return RET_OK;
133 }
134 callbacks_[networkId] = callback;
135 FI_HILOGI("Register crossing state listener success");
136 int32_t ret = RegisterProfileListener(networkId);
137 if (ret != RET_OK) {
138 FI_HILOGE("Register profile listener failed");
139 }
140 return ret;
141 }
142
UnregisterCrossingStateListener(const std::string & networkId)143 int32_t DeviceProfileAdapter::UnregisterCrossingStateListener(const std::string &networkId)
144 {
145 CALL_INFO_TRACE;
146 if (networkId.empty()) {
147 FI_HILOGE("networkId is empty");
148 return RET_ERR;
149 }
150 std::lock_guard<std::mutex> guard(adapterLock_);
151 auto it = profileEventCallbacks_.find(networkId);
152 if (it != profileEventCallbacks_.end()) {
153 std::list<ProfileEvent> profileEvents;
154 profileEvents.emplace_back(ProfileEvent::EVENT_PROFILE_CHANGED);
155 std::list<ProfileEvent> failedEvents;
156 DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvents(profileEvents,
157 it->second, failedEvents);
158 profileEventCallbacks_.erase(it);
159 }
160 auto callbackIter = callbacks_.find(networkId);
161 if (callbackIter == callbacks_.end()) {
162 FI_HILOGW("This device has no callback");
163 return RET_OK;
164 }
165 callbacks_.erase(callbackIter);
166 return RET_OK;
167 }
168
RegisterProfileListener(const std::string & networkId)169 int32_t DeviceProfileAdapter::RegisterProfileListener(const std::string &networkId)
170 {
171 CALL_INFO_TRACE;
172 std::list<std::string> serviceIdList;
173 serviceIdList.emplace_back(SERVICE_ID);
174 ExtraInfo extraInfo;
175 extraInfo["deviceId"] = networkId;
176 extraInfo["serviceIds"] = serviceIdList;
177 SubscribeInfo changeEventInfo;
178 changeEventInfo.profileEvent = ProfileEvent::EVENT_PROFILE_CHANGED;
179 changeEventInfo.extraInfo = std::move(extraInfo);
180 std::list<SubscribeInfo> subscribeInfos;
181 subscribeInfos.emplace_back(changeEventInfo);
182 SubscribeInfo syncEventInfo;
183 syncEventInfo.profileEvent = ProfileEvent::EVENT_SYNC_COMPLETED;
184 subscribeInfos.emplace_back(syncEventInfo);
185 std::list<ProfileEvent> failedEvents;
186 auto it = profileEventCallbacks_.find(networkId);
187 if (it == profileEventCallbacks_.end() || it->second == nullptr) {
188 profileEventCallbacks_[networkId] = std::make_shared<DeviceProfileAdapter::ProfileEventCallbackImpl>();
189 }
190 return DistributedDeviceProfileClient::GetInstance().SubscribeProfileEvents(
191 subscribeInfos, profileEventCallbacks_[networkId], failedEvents);
192 }
193
OnProfileChanged(const std::string & networkId)194 void DeviceProfileAdapter::OnProfileChanged(const std::string &networkId)
195 {
196 std::lock_guard<std::mutex> guard(adapterLock_);
197 auto it = callbacks_.find(networkId);
198 if (it == callbacks_.end()) {
199 FI_HILOGW("The device has no callback");
200 return;
201 }
202 if (it->second != nullptr) {
203 auto state = GetCrossingSwitchState(networkId);
204 it->second(networkId, state);
205 } else {
206 callbacks_.erase(it);
207 }
208 }
209
OnProfileChanged(const ProfileChangeNotification & changeNotification)210 void DeviceProfileAdapter::ProfileEventCallbackImpl::OnProfileChanged(
211 const ProfileChangeNotification &changeNotification)
212 {
213 CALL_INFO_TRACE;
214 std::string networkId = changeNotification.GetDeviceId();
215 DP_ADAPTER->OnProfileChanged(networkId);
216 }
217
OnSyncCompleted(const DeviceProfile::SyncResult & syncResults)218 void DeviceProfileAdapter::ProfileEventCallbackImpl::OnSyncCompleted(const DeviceProfile::SyncResult &syncResults)
219 {
220 std::for_each(syncResults.begin(), syncResults.end(), [](const auto &syncResult) {
221 FI_HILOGD("Sync result:%{public}d", syncResult.second);
222 });
223 }
224 } // namespace DeviceStatus
225 } // namespace Msdp
226 } // namespace OHOS
227