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