1 /*
2 * Copyright (C) 2022-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 #include "dev_profile.h"
16
17 #include <cstring>
18 #include <thread>
19
20 #include "dev_manager.h"
21 #include "device_manager.h"
22 #include "distributed_device_profile_client.h"
23 #include "distributed_module_config.h"
24 #include "nlohmann/json.hpp"
25 #include "para_handle.h"
26 #include "pasteboard_hilog.h"
27 #include "service_characteristic_profile.h"
28 #include "subscribe_info.h"
29 namespace OHOS {
30 namespace MiscServices {
31 using namespace OHOS::DeviceProfile;
32 using namespace OHOS::DistributedHardware;
33 constexpr const int32_t HANDLE_OK = 0;
34 constexpr const uint32_t NOT_SUPPORT = 0;
35 constexpr const uint32_t SUPPORT = 1;
36 constexpr const uint32_t FIRST_VERSION = 4;
37 constexpr const char *SERVICE_ID = "pasteboardService";
38 constexpr const char *CHARACTER_ID = "supportDistributedPasteboard";
39 constexpr const char *VERSION_ID = "PasteboardVersionId";
40
OnSyncCompleted(const SyncResult & syncResults)41 void DevProfile::PasteboardProfileEventCallback::OnSyncCompleted(const SyncResult &syncResults)
42 {
43 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "OnSyncCompleted.");
44 }
45
OnProfileChanged(const ProfileChangeNotification & changeNotification)46 void DevProfile::PasteboardProfileEventCallback::OnProfileChanged(const ProfileChangeNotification &changeNotification)
47 {
48 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "OnProfileChanged start.");
49 DistributedModuleConfig::Notify();
50 }
51
DevProfile()52 DevProfile::DevProfile()
53 {
54 }
55
GetInstance()56 DevProfile &DevProfile::GetInstance()
57 {
58 static DevProfile instance;
59 return instance;
60 }
61
Init()62 void DevProfile::Init()
63 {
64 ParaHandle::GetInstance().WatchEnabledStatus(ParameterChange);
65 }
66
OnReady()67 void DevProfile::OnReady()
68 {
69 auto status = ParaHandle::GetInstance().GetEnabledStatus();
70 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "status = %{public}s.", status.c_str());
71 PutEnabledStatus(status);
72 }
73
ParameterChange(const char * key,const char * value,void * context)74 void DevProfile::ParameterChange(const char *key, const char *value, void *context)
75 {
76 auto enabledKey = ParaHandle::DISTRIBUTED_PASTEBOARD_ENABLED_KEY;
77 if (strncmp(key, enabledKey, strlen(enabledKey)) != 0) {
78 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "key is error.");
79 return;
80 }
81 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "ParameterChange, key = %{public}s, value = %{public}s.", key, value);
82 DevProfile::GetInstance().PutEnabledStatus(value);
83 DistributedModuleConfig::Notify();
84 }
85
PutEnabledStatus(const std::string & enabledStatus)86 void DevProfile::PutEnabledStatus(const std::string &enabledStatus)
87 {
88 ServiceCharacteristicProfile profile;
89 profile.SetServiceId(SERVICE_ID);
90 profile.SetServiceType(SERVICE_ID);
91 nlohmann::json jsonObject;
92 jsonObject[CHARACTER_ID] = NOT_SUPPORT;
93 localEnable_ = false;
94 if (enabledStatus == "true") {
95 jsonObject[CHARACTER_ID] = SUPPORT;
96 localEnable_ = true;
97 }
98 jsonObject[VERSION_ID] = FIRST_VERSION;
99 profile.SetCharacteristicProfileJson(jsonObject.dump());
100 int32_t errNo = DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile);
101 if (errNo != HANDLE_OK) {
102 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "PutDeviceProfile failed, %{public}d", errNo);
103 return;
104 }
105 SyncEnabledStatus();
106 }
107
GetEnabledStatus(const std::string & deviceId,std::string & enabledStatus)108 void DevProfile::GetEnabledStatus(const std::string &deviceId, std::string &enabledStatus)
109 {
110 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetEnabledStatus start.");
111 ServiceCharacteristicProfile profile;
112 int32_t ret = DistributedDeviceProfileClient::GetInstance().GetDeviceProfile(deviceId, SERVICE_ID, profile);
113 if (ret != HANDLE_OK) {
114 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "GetDeviceProfile failed, %{public}.5s.", deviceId.c_str());
115 return;
116 }
117 const auto &jsonData = profile.GetCharacteristicProfileJson();
118 nlohmann::json jsonObject = nlohmann::json::parse(jsonData, nullptr, false);
119 if (jsonObject.is_discarded()) {
120 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "json parse failed.");
121 return;
122 }
123
124 enabledStatus = "false";
125 if (jsonObject[CHARACTER_ID] == SUPPORT) {
126 enabledStatus = "true";
127 }
128 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "GetEnabledStatus success %{public}s.", enabledStatus.c_str());
129 }
130
GetRemoteDeviceVersion(const std::string & deviceId,uint32_t & versionId)131 void DevProfile::GetRemoteDeviceVersion(const std::string &deviceId, uint32_t &versionId)
132 {
133 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetRemoteDeviceVersion start.");
134 ServiceCharacteristicProfile profile;
135 int32_t ret = DistributedDeviceProfileClient::GetInstance().GetDeviceProfile(deviceId, SERVICE_ID, profile);
136 if (ret != HANDLE_OK) {
137 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "GetDeviceProfile failed, %{public}.5s.", deviceId.c_str());
138 return;
139 }
140 const auto &jsonData = profile.GetCharacteristicProfileJson();
141 nlohmann::json jsonObject = nlohmann::json::parse(jsonData, nullptr, false);
142 if (jsonObject.is_discarded()) {
143 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "json parse failed.");
144 return;
145 }
146 if (jsonObject.contains(VERSION_ID) && jsonObject[VERSION_ID] == FIRST_VERSION) {
147 versionId = jsonObject[VERSION_ID];
148 }
149 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetRemoteDeviceVersion success, versionId = %{public}d.", versionId);
150 }
151
SubscribeProfileEvent(const std::string & deviceId)152 void DevProfile::SubscribeProfileEvent(const std::string &deviceId)
153 {
154 if (deviceId.empty()) {
155 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "deviceId is empty.");
156 return;
157 }
158 std::lock_guard<std::mutex> mutexLock(callbackMutex_);
159 if (callback_.find(deviceId) != callback_.end()) {
160 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "deviceId = %{public}.5s already exists.", deviceId.c_str());
161 return;
162 }
163 auto profileCallback = std::make_shared<PasteboardProfileEventCallback>();
164 callback_[deviceId] = profileCallback;
165 std::list<std::string> serviceIds = { SERVICE_ID };
166 ExtraInfo extraInfo;
167 extraInfo["deviceId"] = deviceId;
168 extraInfo["serviceIds"] = serviceIds;
169
170 SubscribeInfo subscribeInfo;
171 subscribeInfo.profileEvent = ProfileEvent::EVENT_PROFILE_CHANGED;
172 subscribeInfo.extraInfo = std::move(extraInfo);
173 int32_t errCode =
174 DistributedDeviceProfileClient::GetInstance().SubscribeProfileEvent(subscribeInfo, profileCallback);
175 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "SubscribeProfileEvent result, errCode = %{public}d.", errCode);
176 }
177
UnSubscribeProfileEvent(const std::string & deviceId)178 void DevProfile::UnSubscribeProfileEvent(const std::string &deviceId)
179 {
180 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start, deviceId = %{public}.5s", deviceId.c_str());
181 ProfileEvent profileEvent = EVENT_PROFILE_CHANGED;
182 std::lock_guard<std::mutex> mutexLock(callbackMutex_);
183 auto it = callback_.find(deviceId);
184 if (it == callback_.end()) {
185 return;
186 }
187 int32_t errCode = DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvent(profileEvent, it->second);
188 callback_.erase(it);
189 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "UnsubscribeProfileEvent result, errCode = %{public}d.", errCode);
190 }
191
SyncEnabledStatus()192 void DevProfile::SyncEnabledStatus()
193 {
194 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "SyncEnabledStatus start.");
195 SyncOptions syncOptions;
196 auto deviceIds = DevManager::GetInstance().GetNetworkIds();
197 if (deviceIds.empty()) {
198 return;
199 }
200 for (auto &id : deviceIds) {
201 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "id = %{public}.5s.", id.c_str());
202 syncOptions.AddDevice(id);
203 }
204 syncOptions.SetSyncMode(SyncMode::PUSH_PULL);
205 auto syncCallback = std::make_shared<PasteboardProfileEventCallback>();
206 int32_t errCode = DistributedDeviceProfileClient::GetInstance().SyncDeviceProfile(syncOptions, syncCallback);
207 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "SyncEnabledStatus, ret = %{public}d.", errCode);
208 }
209
UnsubscribeAllProfileEvents()210 void DevProfile::UnsubscribeAllProfileEvents()
211 {
212 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "UnsubscribeAllProfileEvents start.");
213 std::lock_guard<std::mutex> mutexLock(callbackMutex_);
214 for (auto it = callback_.begin(); it != callback_.end(); ++it) {
215 ProfileEvent profileEvent = EVENT_PROFILE_CHANGED;
216 int32_t errCode =
217 DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvent(profileEvent, it->second);
218 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "errCode = %{public}d.", errCode);
219 it = callback_.erase(it);
220 }
221 }
222
GetLocalEnable()223 bool DevProfile::GetLocalEnable()
224 {
225 return localEnable_;
226 }
227
228 } // namespace MiscServices
229 } // namespace OHOS
230