diff --git a/common/include/device_profile_errors.h b/common/include/device_profile_errors.h new file mode 100755 index 0000000000000000000000000000000000000000..ad00a33fddae088a8610b127422c076f79594183 --- /dev/null +++ b/common/include/device_profile_errors.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_ERRORS_H +#define OHOS_DEVICE_PROFILE_ERRORS_H + +#include "errors.h" + +namespace OHOS { +namespace DeviceProfile { +enum { + DEVICE_PROFILE_MODULE_DDP = 0, +}; + +constexpr ErrCode DEVICE_PROFILE_ERR_OFFSET = ErrCodeOffset(SUBSYS_DEVICEPROFILE, DEVICE_PROFILE_MODULE_DDP); + +enum { + // DEVICE_PROFILE_ERR_OFFSET(98566143) + ERR_DP_INVALID_PARAMS = 98566144, + ERR_DP_INTERFACE_CHECK_FAILED = 98566145, + ERR_DP_GET_LOCAL_UDID_FAILED = 98566146, + ERR_DP_GET_SERVICE_FAILED = 98566147, + ERR_DP_INIT_DB_FAILED = 98566148, + ERR_DP_NOT_SUBSCRIBED = 98566149, + ERR_DP_UNSUBSCRIBE_FAILED = 98566150, + ERR_DP_SUBSCRIBE_FAILED = 98566151, + ERR_DP_SUBSCRIBE_LIMIT_EXCEEDED = 98566152, + ERR_DP_POST_TASK_FAILED = 98566153, + ERR_DP_DEVICE_SYNC_BUSY = 98566154, +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_ERRORS_H diff --git a/common/include/device_profile_log.h b/common/include/device_profile_log.h new file mode 100755 index 0000000000000000000000000000000000000000..0148aaaef15e7a9788ce30c7f887bd4ff92bfd71 --- /dev/null +++ b/common/include/device_profile_log.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_LOG_H +#define OHOS_DEVICE_PROFILE_LOG_H + +#include "hilog/log.h" + +namespace OHOS { +namespace DeviceProfile { +static constexpr OHOS::HiviewDFX::HiLogLabel DP_LOG_LABEL = { + LOG_CORE, + 0xD001900, + "Device_Profile" +}; + +#ifdef HILOGF +#undef HILOGF +#endif +#ifdef HILOGE +#undef HILOGE +#endif +#ifdef HILOGW +#undef HILOGW +#endif +#ifdef HILOGI +#undef HILOGI +#endif +#ifdef HILOGD +#undef HILOGD +#endif + +#define DP_LOG(level, fmt, ...) \ + HiviewDFX::HiLog::level(DP_LOG_LABEL, "%{public}s::%{public}s " fmt, TAG.c_str(), __FUNCTION__, ##__VA_ARGS__) + +#define HILOGF(fmt, ...) DP_LOG(Fatal, fmt, ##__VA_ARGS__) +#define HILOGE(fmt, ...) DP_LOG(Error, fmt, ##__VA_ARGS__) +#define HILOGW(fmt, ...) DP_LOG(Warn, fmt, ##__VA_ARGS__) +#define HILOGI(fmt, ...) DP_LOG(Info, fmt, ##__VA_ARGS__) +#define HILOGD(fmt, ...) DP_LOG(Debug, fmt, ##__VA_ARGS__) +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DP_DATA_CHANGE_LISTENER_H diff --git a/common/include/device_profile_utils.h b/common/include/device_profile_utils.h new file mode 100755 index 0000000000000000000000000000000000000000..fd5e0c850aaad7ba0333ae7632f36827f6ec84b2 --- /dev/null +++ b/common/include/device_profile_utils.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_PROFILE_UTILS_H +#define OHOS_DEVICE_PROFILE_PROFILE_UTILS_H + +#include + +#include "parcel.h" +#include "profile_event.h" + +namespace OHOS { +namespace DeviceProfile { +class DeviceProfileUtils { +public: + static bool WriteProfileEvents(const std::list& profileEvents, Parcel& parcel); + static bool ReadProfileEvents(Parcel& parcel, std::list& profileEvents); + static std::string AnonymizeDeviceId(const std::string& deviceId); +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_PROFILE_UTILS_H diff --git a/common/include/parcel_helper.h b/common/include/parcel_helper.h new file mode 100755 index 0000000000000000000000000000000000000000..5e4dfd77b43e976c81255ba1fe6e170d4c8492c5 --- /dev/null +++ b/common/include/parcel_helper.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_PARCEL_HELPER_H +#define OHOS_DEVICE_PROFILE_PARCEL_HELPER_H + +#include "ipc_types.h" +#include "device_profile_log.h" + +namespace OHOS { +namespace DeviceProfile { +#define PARCEL_WRITE_HELPER(parcel, type, value) \ + do { \ + bool ret = parcel.Write##type((value)); \ + if (!ret) { \ + HILOGE("write value failed!"); \ + return ERR_FLATTEN_OBJECT; \ + } \ + } while (0) + +#define PARCEL_WRITE_HELPER_NORET(parcel, type, value) \ + do { \ + bool ret = parcel.Write##type((value)); \ + if (!ret) { \ + HILOGE("write value failed!"); \ + return; \ + } \ + } while (0) + +#define PARCEL_WRITE_HELPER_RET(parcel, type, value, failRet) \ + do { \ + bool ret = parcel.Write##type((value)); \ + if (!ret) { \ + HILOGE("write value failed!"); \ + return failRet; \ + } \ + } while (0) + +#define PARCEL_READ_HELPER(parcel, type, out) \ + do { \ + bool ret = parcel.Read##type((out)); \ + if (!ret) { \ + HILOGE("read value failed!"); \ + return ERR_FLATTEN_OBJECT; \ + } \ + } while (0) + +#define PARCEL_READ_HELPER_RET(parcel, type, out, failRet) \ + do { \ + bool ret = parcel.Read##type((out)); \ + if (!ret) { \ + HILOGE("read value failed!"); \ + return failRet; \ + } \ + } while (0) + +#define PARCEL_READ_HELPER_NORET(parcel, type, out) \ + do { \ + bool ret = parcel.Read##type((out)); \ + if (!ret) { \ + HILOGW("read value failed!"); \ + } \ + } while (0) + +#define PARCEL_WRITE_REPLY_NOERROR(reply, type, result) \ + do { \ + bool ret = reply.Write##type(result); \ + if (!ret) { \ + HILOGW("write reply failed!"); \ + } \ + return ERR_OK; \ + } while (0) + +#define PARCEL_TRANSACT_SYNC_RET_INT(remote, code, data, reply) \ + do { \ + MessageOption option; \ + int32_t errCode = remote->SendRequest(code, data, reply, option); \ + if (errCode != ERR_OK) { \ + HILOGE("transact failed, errCode = %{public}d", errCode); \ + return errCode; \ + } \ + HILOGI("transact succeeded"); \ + return ERR_OK; \ + } while (0) + +#define PARCEL_TRANSACT_SYNC_NORET(remote, code, data, reply) \ + do { \ + MessageOption option; \ + int32_t errCode = remote->SendRequest(code, data, reply, option); \ + if (errCode != ERR_OK) { \ + HILOGE("transact failed, errCode = %{public}d", errCode); \ + return; \ + } \ + HILOGI("transact succeeded"); \ + } while (0) +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_PARCEL_HELPER_H diff --git a/common/include/single_instance.h b/common/include/single_instance.h new file mode 100755 index 0000000000000000000000000000000000000000..017b5c27220d0643e7041d819210693a4ff3dca6 --- /dev/null +++ b/common/include/single_instance.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_SINGLE_INSTANCE_H +#define OHOS_DEVICE_PROFILE_SINGLE_INSTANCE_H + +namespace OHOS { +namespace DeviceProfile { +#define DECLARE_SINGLE_INSTANCE_BASE(className) \ +public: \ + static className& GetInstance(); \ +private: \ + className(const className&) = delete; \ + className& operator= (const className&) = delete; \ + className(className&&) = delete; \ + className& operator= (className&&) = delete; \ + +#define DECLARE_SINGLE_INSTANCE(className) \ + DECLARE_SINGLE_INSTANCE_BASE(className) \ +private: \ + className() = default; \ + ~className() = default; \ + +#define IMPLEMENT_SINGLE_INSTANCE(className) \ +className& className::GetInstance() \ +{ \ + static auto instance = new className(); \ + return *instance; \ +} +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_SINGLE_INSTANCE_H \ No newline at end of file diff --git a/common/src/device_profile_utils.cpp b/common/src/device_profile_utils.cpp new file mode 100755 index 0000000000000000000000000000000000000000..b19ee7813e9b77da74bc9380adc0e4a4ca8d7eb6 --- /dev/null +++ b/common/src/device_profile_utils.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "device_profile_utils.h" + +#include "parcel_helper.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "DeviceProfileUtils"; + +constexpr int32_t NON_ANONYMIZED_LENGTH = 6; +const std::string EMPTY_DEVICE_ID = ""; +} + +bool DeviceProfileUtils::WriteProfileEvents(const std::list& profileEvents, Parcel& parcel) +{ + size_t size = profileEvents.size(); + PARCEL_WRITE_HELPER(parcel, Uint32, static_cast(size)); + for (auto profileEvent : profileEvents) { + PARCEL_WRITE_HELPER(parcel, Uint32, static_cast(profileEvent)); + } + return true; +} + +bool DeviceProfileUtils::ReadProfileEvents(Parcel& parcel, std::list& profileEvents) +{ + uint32_t numEvents = parcel.ReadUint32(); + for (uint32_t i = 0; i < numEvents; i++) { + ProfileEvent profileEvent = static_cast(parcel.ReadUint32()); + if (profileEvent >= EVENT_PROFILE_END || profileEvent == EVENT_UNKNOWN) { + return false; + } + profileEvents.emplace_back(profileEvent); + } + return true; +} + +std::string DeviceProfileUtils::AnonymizeDeviceId(const std::string& deviceId) +{ + if (deviceId.length() < NON_ANONYMIZED_LENGTH) { + return EMPTY_DEVICE_ID; + } + std::string anonDeviceId = deviceId.substr(0, NON_ANONYMIZED_LENGTH); + anonDeviceId.append("******"); + return anonDeviceId; +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/core/BUILD.gn b/interfaces/innerkits/core/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..14a4cd670e129e2fa5d9c962d21a60ac46d1ea8a --- /dev/null +++ b/interfaces/innerkits/core/BUILD.gn @@ -0,0 +1,62 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//build/ohos_var.gni") + +device_profile_path = "//foundation/deviceprofile/device_profile_core" +device_profile_service = "${device_profile_path}/services/core" +distributed_datamgr_innerkits = + "//foundation/distributeddatamgr/distributeddatamgr/interfaces/innerkits" + +config("distributed_device_profile_client_config") { + visibility = [ ":*" ] + include_dirs = [ + "include", + "${device_profile_path}/common/include", + "${distributed_datamgr_innerkits}/distributeddata/include", + "//third_party/json/include", + ] +} + +ohos_shared_library("distributed_device_profile_client") { + install_enable = true + sources = [ + "${device_profile_path}/common/src/device_profile_utils.cpp", + "${device_profile_service}/src/profile_change_notification.cpp", + "${device_profile_service}/src/service_characteristic_profile.cpp", + "${device_profile_service}/src/subscribemanager/subscribe_info.cpp", + "${device_profile_service}/src/sync_options.cpp", + "src/distributed_device_profile_client.cpp", + "src/distributed_device_profile_proxy.cpp", + "src/profile_event_notifier_stub.cpp", + ] + + configs = [ ":distributed_device_profile_client_config" ] + + deps = [ + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//utils/native/base:utils", + ] + + public_deps = [ "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler" ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + part_name = "device_profile_core" + subsystem_name = "deviceprofile" +} diff --git a/interfaces/innerkits/core/include/distributed_device_profile_client.h b/interfaces/innerkits/core/include/distributed_device_profile_client.h new file mode 100755 index 0000000000000000000000000000000000000000..b86906083542ad0b7dae2a37c142bbfdcb94a45d --- /dev/null +++ b/interfaces/innerkits/core/include/distributed_device_profile_client.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DEVICE_PROFILE_CLIENT_H +#define OHOS_DISTRIBUTED_DEVICE_PROFILE_CLIENT_H + +#include "idistributed_device_profile.h" +#include "single_instance.h" +#include "iprofile_event_callback.h" +#include "profile_event_notifier_stub.h" +#include "profile_event.h" +#include "event_handler.h" +#include "iremote_object.h" + +namespace OHOS { +namespace DeviceProfile { +class DistributedDeviceProfileClient { + DECLARE_SINGLE_INSTANCE(DistributedDeviceProfileClient); + +public: + int32_t PutDeviceProfile(const ServiceCharacteristicProfile& profile); + int32_t GetDeviceProfile(const std::string& udid, const std::string& serviceId, + ServiceCharacteristicProfile& profile); + int32_t DeleteDeviceProfile(const std::string& serviceId); + int32_t SubscribeProfileEvent(const SubscribeInfo& subscribeInfo, + const std::shared_ptr& eventCb); + int32_t UnsubscribeProfileEvent(ProfileEvent profileEvent, + const std::shared_ptr& eventCb); + int32_t SubscribeProfileEvents(const std::list& subscribeInfos, + const std::shared_ptr& eventCb, + std::list& failedEvents); + int32_t UnsubscribeProfileEvents(const std::list& profileEvents, + const std::shared_ptr& eventCb, + std::list& failedEvents); + int32_t SyncDeviceProfile(const SyncOptions& syncOptions, + const std::shared_ptr& syncCb); + +private: + class DeviceProfileDeathRecipient : public IRemoteObject::DeathRecipient { + public: + void OnRemoteDied(const wptr& remote) override; + }; + + struct SubscribeRecord { + std::list subscribeInfos; + sptr notifier; + ProfileEvents profileEvents; + }; + + sptr GetDeviceProfileService(); + bool CheckProfileInvalidity(const ServiceCharacteristicProfile& profile); + void OnServiceDied(const sptr& remote); + void MergeSubscribeInfoLocked(std::list& subscribeInfos, + const std::list& newSubscribeInfos); + + std::mutex serviceLock_; + std::mutex subscribeLock_; + sptr dpProxy_; + sptr dpDeathRecipient_; + std::shared_ptr dpClientHandler_; + std::map, SubscribeRecord> subscribeRecords_; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DEVICE_PROFILE_CLIENT_H \ No newline at end of file diff --git a/interfaces/innerkits/core/include/distributed_device_profile_proxy.h b/interfaces/innerkits/core/include/distributed_device_profile_proxy.h new file mode 100755 index 0000000000000000000000000000000000000000..2b8f9c73055285276b139e77c909284a85bdc6f5 --- /dev/null +++ b/interfaces/innerkits/core/include/distributed_device_profile_proxy.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DEVICE_PROFILE_PROXY_H +#define OHOS_DISTRIBUTED_DEVICE_PROFILE_PROXY_H + +#include "idistributed_device_profile.h" +#include "iremote_proxy.h" +#include "profile_event.h" + +namespace OHOS { +namespace DeviceProfile { +class DistributedDeviceProfileProxy : public IRemoteProxy { +public: + explicit DistributedDeviceProfileProxy(const sptr& impl) + : IRemoteProxy(impl) {} + ~DistributedDeviceProfileProxy() = default; + + int32_t PutDeviceProfile(const ServiceCharacteristicProfile& profile) override; + int32_t GetDeviceProfile(const std::string& udid, const std::string& serviceId, + ServiceCharacteristicProfile& profile) override; + int32_t DeleteDeviceProfile(const std::string& serviceId) override; + int32_t SubscribeProfileEvents(const std::list& subscribeInfos, + const sptr& profileEventNotifier, + std::list& failedEvents) override; + int32_t UnsubscribeProfileEvents(const std::list& profileEvents, + const sptr& profileEventNotifier, + std::list& failedEvents) override; + int32_t SyncDeviceProfile(const SyncOptions& syncOptions, + const sptr& profileEventNotifier) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DEVICE_PROFILE_PROXY_H \ No newline at end of file diff --git a/interfaces/innerkits/core/include/idistributed_device_profile.h b/interfaces/innerkits/core/include/idistributed_device_profile.h new file mode 100755 index 0000000000000000000000000000000000000000..80b0e77f4b9dc1cea604e0ffe1bf4b6b0f8f1d9b --- /dev/null +++ b/interfaces/innerkits/core/include/idistributed_device_profile.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_I_DISTRIBUTED_DEVICE_PROFILE_H +#define OHOS_I_DISTRIBUTED_DEVICE_PROFILE_H + +#include + +#include "iremote_broker.h" +#include "service_characteristic_profile.h" +#include "iprofile_event_notifier.h" +#include "profile_event.h" +#include "subscribe_info.h" +#include "sync_options.h" + +namespace OHOS { +namespace DeviceProfile { +class IDistributedDeviceProfile : public IRemoteBroker { +public: + enum { + PUT_DEVICE_PROFILE = 1, + GET_DEVICE_PROFILE = 2, + DELETE_DEVICE_PROFILE = 3, + SUBSCRIBE_PROFILE_EVENT = 4, + UNSUBSCRIBE_PROFILE_EVENT = 5, + SYNC_DEVICE_PROFILE = 6 + }; + + virtual int32_t PutDeviceProfile(const ServiceCharacteristicProfile& profile) = 0; + virtual int32_t GetDeviceProfile(const std::string& udid, const std::string& serviceId, + ServiceCharacteristicProfile& profile) = 0; + virtual int32_t DeleteDeviceProfile(const std::string& serviceId) = 0; + virtual int32_t SubscribeProfileEvents(const std::list& subscribeInfos, + const sptr& profileEventNotifier, + std::list& failedEvents) = 0; + virtual int32_t UnsubscribeProfileEvents(const std::list& profileEvents, + const sptr& profileEventNotifier, + std::list& failedEvents) = 0; + virtual int32_t SyncDeviceProfile(const SyncOptions& syncOptions, + const sptr& profileEventNotifier) = 0; + + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DeviceProfile.IDistributedDeviceProfile"); +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_I_DISTRIBUTED_DEVICE_PROFILE_H \ No newline at end of file diff --git a/interfaces/innerkits/core/include/iprofile_event_callback.h b/interfaces/innerkits/core/include/iprofile_event_callback.h new file mode 100755 index 0000000000000000000000000000000000000000..cee1209f251a942917e63945e332a377e7400920 --- /dev/null +++ b/interfaces/innerkits/core/include/iprofile_event_callback.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_I_PROFILE_EVENT_CALLBACK_H +#define OHOS_DEVICE_PROFILE_I_PROFILE_EVENT_CALLBACK_H + +#include +#include "profile_change_notification.h" + +namespace OHOS { +namespace DeviceProfile { +enum SyncStatus { + SUCCEEDED = 0, + FAILED = 1 +}; + +using SyncResult = std::map; + +class IProfileEventCallback { +public: + IProfileEventCallback() = default; + virtual ~IProfileEventCallback() = default; + + virtual void OnSyncCompleted(const SyncResult& syncResults) {}; + virtual void OnProfileChanged(const ProfileChangeNotification& changeNotification) {}; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_I_PROFILE_EVENT_CALLBACK_H diff --git a/interfaces/innerkits/core/include/iprofile_event_notifier.h b/interfaces/innerkits/core/include/iprofile_event_notifier.h new file mode 100755 index 0000000000000000000000000000000000000000..98217f1db88b4e6fb3028f775b6cbdca6def4986 --- /dev/null +++ b/interfaces/innerkits/core/include/iprofile_event_notifier.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_I_PROFILE_EVENT_NOTIFIER_H +#define OHOS_DEVICE_PROFILE_I_PROFILE_EVENT_NOTIFIER_H + +#include +#include "iremote_broker.h" +#include "iprofile_event_callback.h" + +namespace OHOS { +namespace DeviceProfile { +using SyncResult = std::map; + +class IProfileEventNotifier : public IRemoteBroker, public IProfileEventCallback { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DeviceProfile.IProfileEventNotifier"); +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_I_PROFILE_EVENT_NOTIFIER_H diff --git a/interfaces/innerkits/core/include/profile_change_notification.h b/interfaces/innerkits/core/include/profile_change_notification.h new file mode 100755 index 0000000000000000000000000000000000000000..23f9e577fa447b4915a38bd400534cb82fe37c91 --- /dev/null +++ b/interfaces/innerkits/core/include/profile_change_notification.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_CHANGE_NOTIFICATION_H +#define OHOS_DEVICE_PROFILE_CHANGE_NOTIFICATION_H + +#include +#include + +#include "parcel.h" + +namespace OHOS { +namespace DeviceProfile { +enum ProfileChangeType : uint8_t { + UNKNOWN_CHANGE_TYPE = 0, + INSERTED = 1, + UPDATED = 2, + DELETED = 3 +}; + +using Service2Index = std::map; + +struct ProfileEntry { + template + ProfileEntry(T&& k, T&& val, ProfileChangeType type) + : key(std::forward(k)), value(std::forward(val)), changeType(type) {} + ProfileEntry() {} + ~ProfileEntry() = default; + + bool Marshalling(Parcel& parcel) const; + bool Unmarshalling(Parcel& parcel); + + std::string key; + std::string value; + ProfileChangeType changeType {ProfileChangeType::UNKNOWN_CHANGE_TYPE}; +}; + +class ProfileChangeNotification : public Parcelable { +public: + ProfileChangeNotification(std::vector& profileEntries, + std::string& networkId, bool isLocal) + : profileEntries_(std::move(profileEntries)), + deviceId_(std::move(networkId)), isLocal_(isLocal) {} + ProfileChangeNotification() {}; + ~ProfileChangeNotification() = default; + + const std::vector& GetProfileEntries() const; + const std::string& GetDeviceId() const; + bool IsLocal() const; + + bool Marshalling(Parcel& parcel) const override; + bool Unmarshalling(Parcel& parcel); + +private: + std::vector profileEntries_; + std::string deviceId_; + bool isLocal_ {false}; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_CHANGE_NOTIFICATION_H diff --git a/interfaces/innerkits/core/include/profile_event.h b/interfaces/innerkits/core/include/profile_event.h new file mode 100755 index 0000000000000000000000000000000000000000..742a8b45b0221580a97580be72f3a2f08ca4ee30 --- /dev/null +++ b/interfaces/innerkits/core/include/profile_event.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_PROFILE_EVENT_H +#define OHOS_DEVICE_PROFILE_PROFILE_EVENT_H + +#include + +namespace OHOS { +namespace DeviceProfile { +enum ProfileEvent : uint32_t { + EVENT_UNKNOWN = 0, + EVENT_SYNC_COMPLETED = 1, + EVENT_PROFILE_CHANGED = 2, + EVENT_PROFILE_END, +}; + +using ProfileEvents = std::bitset; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_PROFILE_EVENT_H \ No newline at end of file diff --git a/interfaces/innerkits/core/include/profile_event_notifier_stub.h b/interfaces/innerkits/core/include/profile_event_notifier_stub.h new file mode 100755 index 0000000000000000000000000000000000000000..ce6a6bcb9ba4e560797fd9b8f1714c39b59405fc --- /dev/null +++ b/interfaces/innerkits/core/include/profile_event_notifier_stub.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_I_PROFILE_SYNC_CALLBACK_STUB_H +#define OHOS_DEVICE_PROFILE_I_PROFILE_SYNC_CALLBACK_STUB_H + +#include "message_parcel.h" +#include "iremote_stub.h" +#include "iprofile_event_notifier.h" + +namespace OHOS { +namespace DeviceProfile { +class ProfileEventNotifierStub : public IRemoteStub { +public: + ProfileEventNotifierStub(const std::shared_ptr& profileEventCb) + : profileEventCb_(profileEventCb) {} + ~ProfileEventNotifierStub() = default; + + virtual int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, + MessageParcel& reply, MessageOption& option) override; + +private: + using Handler = int32_t(ProfileEventNotifierStub::*)(MessageParcel& data, MessageParcel& reply); + using HandlersMap = std::map; + + static HandlersMap InitHandlersMap(); + + int32_t OnSyncCompletedInner(MessageParcel& data, MessageParcel& reply); + int32_t OnProfileChangedInner(MessageParcel& data, MessageParcel& reply); + +private: + static const HandlersMap handlersMap_; + std::shared_ptr profileEventCb_; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_I_PROFILE_SYNC_CALLBACK_STUB_H \ No newline at end of file diff --git a/interfaces/innerkits/core/include/service_characteristic_profile.h b/interfaces/innerkits/core/include/service_characteristic_profile.h new file mode 100755 index 0000000000000000000000000000000000000000..009fc8db09fd2e5b670a35c091037d61f644c3e2 --- /dev/null +++ b/interfaces/innerkits/core/include/service_characteristic_profile.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_SERVICE_PROFILE_CHARACTERISTIC_PROFILE_H +#define OHOS_DEVICE_SERVICE_PROFILE_CHARACTERISTIC_PROFILE_H + +#include "parcel.h" + +namespace OHOS { +namespace DeviceProfile { +class ServiceCharacteristicProfile : public Parcelable { +public: + ServiceCharacteristicProfile() = default; + ~ServiceCharacteristicProfile() = default; + + void SetServiceId(const std::string& serviceId); + void SetServiceType(const std::string& serviceType); + void SetServiceProfileJson(const std::string& profileJson); + void SetCharacteristicProfileJson(const std::string& profileJson); + + const std::string& GetServiceId() const; + const std::string& GetServiceType() const; + const std::string& GetServiceProfileJson() const; + const std::string& GetCharacteristicProfileJson() const; + + bool Marshalling(Parcel& parcel) const override; + bool Unmarshalling(Parcel& parcel); + +private: + std::string serviceId_; + std::string serviceType_; + // reserved, not used currently + std::string serviceProfileJson_; + std::string characteristicProfileJson_; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_SERVICE_PROFILE_CHARACTERISTIC_PROFILE_H \ No newline at end of file diff --git a/interfaces/innerkits/core/include/subscribe_info.h b/interfaces/innerkits/core/include/subscribe_info.h new file mode 100755 index 0000000000000000000000000000000000000000..62f4a888ff3c672817cea8db7c969beea86eecba --- /dev/null +++ b/interfaces/innerkits/core/include/subscribe_info.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_SUBSCRIBE_INFO_H +#define OHOS_DEVICE_PROFILE_SUBSCRIBE_INFO_H + +#include "nlohmann/json.hpp" +#include "profile_event.h" +#include "parcel.h" + +namespace OHOS { +namespace DeviceProfile { +using ExtraInfo = nlohmann::json; + +struct SubscribeInfo : public Parcelable { + bool Marshalling(Parcel& parcel) const override; + bool Unmarshalling(Parcel& parcel); + + ProfileEvent profileEvent {ProfileEvent::EVENT_UNKNOWN}; + ExtraInfo extraInfo; + + bool operator!=(const SubscribeInfo& rhs) const; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_SUBSCRIBE_INFO_H \ No newline at end of file diff --git a/interfaces/innerkits/core/include/sync_options.h b/interfaces/innerkits/core/include/sync_options.h new file mode 100755 index 0000000000000000000000000000000000000000..5da0595799e996a38c2ca49860e3c86fb34aea2b --- /dev/null +++ b/interfaces/innerkits/core/include/sync_options.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_SYNC_OPERATION_H +#define OHOS_SYNC_OPERATION_H + +#include +#include "parcel.h" +#include "types.h" + +namespace OHOS { +namespace DeviceProfile { +class SyncOptions : public Parcelable { +public: + SyncOptions() = default; + ~SyncOptions() = default; + + const std::list& GetDeviceList() const; + DistributedKv::SyncMode GetSyncMode() const; + + void AddDevice(const std::string& deviceId); + void SetSyncMode(DistributedKv::SyncMode mode); + + bool Marshalling(Parcel& parcel) const override; + bool Unmarshalling(Parcel& parcel); + +private: + DistributedKv::SyncMode syncMode_ {DistributedKv::SyncMode::PUSH}; + std::list syncDevIds_; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_SYNC_OPERATION_H \ No newline at end of file diff --git a/interfaces/innerkits/core/src/distributed_device_profile_client.cpp b/interfaces/innerkits/core/src/distributed_device_profile_client.cpp new file mode 100755 index 0000000000000000000000000000000000000000..4ecaa981ab602e98892d136e189341930533f9e1 --- /dev/null +++ b/interfaces/innerkits/core/src/distributed_device_profile_client.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "distributed_device_profile_client.h" + +#include +#include +#include + +#include "device_profile_errors.h" +#include "device_profile_log.h" + +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" + +namespace OHOS { +namespace DeviceProfile { +using namespace std::chrono_literals; + +namespace { +const std::string TAG = "DistributedDeviceProfileClient"; +const std::string JSON_NULL = "null"; +constexpr int32_t RETRY_TIMES_GET_SERVICE = 5; +} + +IMPLEMENT_SINGLE_INSTANCE(DistributedDeviceProfileClient); + +int32_t DistributedDeviceProfileClient::PutDeviceProfile(const ServiceCharacteristicProfile& profile) +{ + if (CheckProfileInvalidity(profile)) { + return ERR_DP_INVALID_PARAMS; + } + + auto dps = GetDeviceProfileService(); + if (dps == nullptr) { + return ERR_DP_GET_SERVICE_FAILED; + } + return dps->PutDeviceProfile(profile); +} + +int32_t DistributedDeviceProfileClient::GetDeviceProfile(const std::string& udid, const std::string& serviceId, + ServiceCharacteristicProfile& profile) +{ + auto dps = GetDeviceProfileService(); + if (dps == nullptr) { + return ERR_DP_GET_SERVICE_FAILED; + } + return dps->GetDeviceProfile(udid, serviceId, profile); +} + +int32_t DistributedDeviceProfileClient::DeleteDeviceProfile(const std::string& serviceId) +{ + if (serviceId.empty()) { + return ERR_DP_INVALID_PARAMS; + } + + auto dps = GetDeviceProfileService(); + if (dps == nullptr) { + return ERR_DP_GET_SERVICE_FAILED; + } + return dps->DeleteDeviceProfile(serviceId); +} + +int32_t DistributedDeviceProfileClient::SubscribeProfileEvent(const SubscribeInfo& subscribeInfo, + const std::shared_ptr& eventCb) +{ + std::list subscribeInfos; + subscribeInfos.emplace_back(subscribeInfo); + std::list failedEvents; + return SubscribeProfileEvents(subscribeInfos, eventCb, failedEvents); +} + +int32_t DistributedDeviceProfileClient::SubscribeProfileEvents(const std::list& subscribeInfos, + const std::shared_ptr& eventCb, + std::list& failedEvents) +{ + if (subscribeInfos.empty() || eventCb == nullptr) { + return ERR_DP_INVALID_PARAMS; + } + + ProfileEvents subProfileEvents; + for (auto& subscribeInfo : subscribeInfos) { + subProfileEvents.set(static_cast(subscribeInfo.profileEvent)); + } + // duplicated profile event is disallowed + if (subProfileEvents.count() != subscribeInfos.size()) { + return ERR_DP_INVALID_PARAMS; + } + + std::unique_lock autoLock(subscribeLock_); + sptr notifier; + auto iter = subscribeRecords_.find(eventCb); + if (iter != subscribeRecords_.end()) { + notifier = iter->second.notifier; + } else { + notifier = sptr( + new (std::nothrow) ProfileEventNotifierStub(eventCb)); + } + autoLock.unlock(); + + auto dps = GetDeviceProfileService(); + if (dps == nullptr) { + return ERR_DP_GET_SERVICE_FAILED; + } + + failedEvents.clear(); + int32_t errCode = dps->SubscribeProfileEvents(subscribeInfos, notifier, failedEvents); + for (auto failedEvent : failedEvents) { + subProfileEvents.reset(static_cast(failedEvent)); + } + + autoLock.lock(); + iter = subscribeRecords_.find(eventCb); + if (iter != subscribeRecords_.end()) { + MergeSubscribeInfoLocked(iter->second.subscribeInfos, subscribeInfos); + iter->second.profileEvents |= subProfileEvents; + } else { + SubscribeRecord record {subscribeInfos, notifier, subProfileEvents}; + subscribeRecords_.emplace(eventCb, std::move(record)); + } + return errCode; +} + +int32_t DistributedDeviceProfileClient::UnsubscribeProfileEvent(ProfileEvent profileEvent, + const std::shared_ptr& eventCb) +{ + std::list profileEvents; + profileEvents.emplace_back(profileEvent); + std::list failedEvents; + return UnsubscribeProfileEvents(profileEvents, eventCb, failedEvents); +} + +int32_t DistributedDeviceProfileClient::UnsubscribeProfileEvents(const std::list& profileEvents, + const std::shared_ptr& eventCb, + std::list& failedEvents) +{ + if (profileEvents.empty() || eventCb == nullptr) { + return ERR_DP_INVALID_PARAMS; + } + + std::unique_lock autoLock(subscribeLock_); + ProfileEvents unsubProfileEvents; + for (auto profileEvent : profileEvents) { + unsubProfileEvents.set(static_cast(profileEvent)); + } + auto iter = subscribeRecords_.find(eventCb); + if (iter == subscribeRecords_.end()) { + return ERR_DP_NOT_SUBSCRIBED; + } + sptr notifier = iter->second.notifier; + autoLock.unlock(); + + auto dps = GetDeviceProfileService(); + if (dps == nullptr) { + return ERR_DP_GET_SERVICE_FAILED; + } + + failedEvents.clear(); + int32_t errCode = dps->UnsubscribeProfileEvents(profileEvents, notifier, failedEvents); + autoLock.lock(); + iter = subscribeRecords_.find(eventCb); + if (iter != subscribeRecords_.end()) { + for (auto failedEvent : failedEvents) { + unsubProfileEvents.reset(static_cast(failedEvent)); + } + auto& subProfileEvents = iter->second.profileEvents; + subProfileEvents &= ~unsubProfileEvents; + if (subProfileEvents.none()) { + subscribeRecords_.erase(iter); + } + } + return errCode; +} + +int32_t DistributedDeviceProfileClient::SyncDeviceProfile(const SyncOptions& syncOptions, + const std::shared_ptr& syncCb) +{ + auto dps = GetDeviceProfileService(); + if (dps == nullptr) { + return ERR_DP_GET_SERVICE_FAILED; + } + + sptr notifier = + sptr(new (std::nothrow) ProfileEventNotifierStub(syncCb)); + return dps->SyncDeviceProfile(syncOptions, notifier); +} + +sptr DistributedDeviceProfileClient::GetDeviceProfileService() +{ + std::lock_guard lock(serviceLock_); + if (dpProxy_ != nullptr) { + return dpProxy_; + } + + auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (samgrProxy == nullptr) { + HILOGE("get samgr failed"); + return nullptr; + } + auto object = samgrProxy->GetSystemAbility(DISTRIBUTED_DEVICE_PROFILE_SA_ID); + if (object == nullptr) { + HILOGE("get service failed"); + return nullptr; + } + HILOGI("get service succeeded"); + if (dpDeathRecipient_ == nullptr) { + dpDeathRecipient_ = sptr( + new (std::nothrow) DeviceProfileDeathRecipient); + } + object->AddDeathRecipient(dpDeathRecipient_); + dpProxy_ = iface_cast(object); + return dpProxy_; +} + +bool DistributedDeviceProfileClient::CheckProfileInvalidity(const ServiceCharacteristicProfile& profile) +{ + return profile.GetServiceId().empty() || + profile.GetServiceType().empty() || + profile.GetCharacteristicProfileJson().empty() || + profile.GetCharacteristicProfileJson() == JSON_NULL; +} + +void DistributedDeviceProfileClient::MergeSubscribeInfoLocked(std::list& subscribeInfos, + const std::list& newSubscribeInfos) +{ + for (const auto& newSubscribeInfo : newSubscribeInfos) { + auto iter = std::find_if(subscribeInfos.begin(), subscribeInfos.end(), + [&newSubscribeInfo](const auto& subscribeInfo) { + return subscribeInfo.profileEvent == newSubscribeInfo.profileEvent; + }); + if (iter != subscribeInfos.end()) { + subscribeInfos.emplace_back(newSubscribeInfo); + continue; + } + // override with the new suscribe info for same profile event + if (*iter != newSubscribeInfo) { + *iter = newSubscribeInfo; + } + } +} + +void DistributedDeviceProfileClient::OnServiceDied(const sptr& remote) +{ + HILOGI("called"); + { + std::lock_guard lock(serviceLock_); + dpProxy_ = nullptr; + } + + std::lock_guard lock(subscribeLock_); + if (dpClientHandler_ == nullptr) { + auto runner = AppExecFwk::EventRunner::Create("dpclient" + std::to_string(getpid())); + dpClientHandler_ = std::make_shared(runner); + } + + // try resubscribe when device profile service died + auto resubscribe = [this]() { + int32_t retryTimes = 0; + sptr dps; + do { + std::this_thread::sleep_for(500ms); + dps = GetDeviceProfileService(); + if (dps != nullptr) { + HILOGI("get service succeeded"); + break; + } + if (retryTimes++ == RETRY_TIMES_GET_SERVICE) { + HILOGE("get service timeout"); + return; + } + } while (true); + + std::list failedEvents; + std::lock_guard lock(subscribeLock_); + for (const auto& [_, subscribeRecord] : subscribeRecords_) { + int32_t errCode = dps->SubscribeProfileEvents(subscribeRecord.subscribeInfos, + subscribeRecord.notifier, failedEvents); + HILOGI("resubscribe result = %{public}d", errCode); + } + }; + if (dpClientHandler_ != nullptr && !dpClientHandler_->PostTask(resubscribe)) { + HILOGE("post task failed"); + } +} + +void DistributedDeviceProfileClient::DeviceProfileDeathRecipient::OnRemoteDied(const wptr& remote) +{ + DistributedDeviceProfileClient::GetInstance().OnServiceDied(remote.promote()); +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/core/src/distributed_device_profile_proxy.cpp b/interfaces/innerkits/core/src/distributed_device_profile_proxy.cpp new file mode 100755 index 0000000000000000000000000000000000000000..ef942bb3481b1a8260548aca2f2205f626390db7 --- /dev/null +++ b/interfaces/innerkits/core/src/distributed_device_profile_proxy.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "distributed_device_profile_proxy.h" + +#include "device_profile_log.h" +#include "device_profile_utils.h" +#include "parcel_helper.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "DistributedDeviceProfileProxy"; +} + +int32_t DistributedDeviceProfileProxy::PutDeviceProfile(const ServiceCharacteristicProfile& profile) +{ + sptr remote = Remote(); + MessageParcel data; + if (!data.WriteInterfaceToken(IDistributedDeviceProfile::GetDescriptor())) { + HILOGE("write interface token failed"); + return ERR_FLATTEN_OBJECT; + } + if (!profile.Marshalling(data)) { + HILOGE("marshall profile failed"); + return ERR_FLATTEN_OBJECT; + } + MessageParcel reply; + PARCEL_TRANSACT_SYNC_RET_INT(remote, PUT_DEVICE_PROFILE, data, reply); +} + +int32_t DistributedDeviceProfileProxy::GetDeviceProfile(const std::string& udid, const std::string& serviceId, + ServiceCharacteristicProfile& profile) +{ + sptr remote = Remote(); + MessageParcel data; + if (!data.WriteInterfaceToken(IDistributedDeviceProfile::GetDescriptor())) { + HILOGE("write interface token failed"); + return ERR_FLATTEN_OBJECT; + } + PARCEL_WRITE_HELPER(data, String, udid); + PARCEL_WRITE_HELPER(data, String, serviceId); + MessageParcel reply; + MessageOption option; + int32_t error = remote->SendRequest(GET_DEVICE_PROFILE, data, reply, option); + if (error != ERR_NONE) { + HILOGE("transact failed, error: %{public}d", error); + return error; + } + profile.Unmarshalling(reply); + return ERR_OK; +} + +int32_t DistributedDeviceProfileProxy::DeleteDeviceProfile(const std::string& serviceId) +{ + sptr remote = Remote(); + MessageParcel data; + if (!data.WriteInterfaceToken(IDistributedDeviceProfile::GetDescriptor())) { + HILOGE("write inteface token failed"); + return ERR_FLATTEN_OBJECT; + } + PARCEL_WRITE_HELPER(data, String, serviceId); + MessageParcel reply; + PARCEL_TRANSACT_SYNC_RET_INT(remote, DELETE_DEVICE_PROFILE, data, reply); +} + +int32_t DistributedDeviceProfileProxy::SubscribeProfileEvents( + const std::list& subscribeInfos, + const sptr& profileEventNotifier, + std::list& failedEvents) +{ + sptr remote = Remote(); + MessageParcel data; + if (!data.WriteInterfaceToken(IDistributedDeviceProfile::GetDescriptor())) { + HILOGE("write inteface token failed"); + return ERR_FLATTEN_OBJECT; + } + size_t size = subscribeInfos.size(); + PARCEL_WRITE_HELPER(data, Uint32, static_cast(size)); + for (const auto& subscribeInfo : subscribeInfos) { + if (!subscribeInfo.Marshalling(data)) { + HILOGE("marshall subscribe info failed"); + return ERR_FLATTEN_OBJECT; + } + } + PARCEL_WRITE_HELPER(data, RemoteObject, profileEventNotifier); + MessageParcel reply; + MessageOption option; + int32_t errCode = remote->SendRequest(SUBSCRIBE_PROFILE_EVENT, data, reply, option); + if (errCode != ERR_OK) { + HILOGE("transact failed, errCode = %{public}d", errCode); + if (!DeviceProfileUtils::ReadProfileEvents(reply, failedEvents)) { + HILOGW("read profile events failed"); + } + } + return errCode; +} + +int32_t DistributedDeviceProfileProxy::UnsubscribeProfileEvents( + const std::list& profileEvents, + const sptr& profileEventNotifier, + std::list& failedEvents) +{ + sptr remote = Remote(); + MessageParcel data; + if (!data.WriteInterfaceToken(IDistributedDeviceProfile::GetDescriptor())) { + HILOGE("write inteface token failed"); + return ERR_FLATTEN_OBJECT; + } + if (!DeviceProfileUtils::WriteProfileEvents(profileEvents, data)) { + return ERR_FLATTEN_OBJECT; + } + + PARCEL_WRITE_HELPER(data, RemoteObject, profileEventNotifier); + MessageParcel reply; + MessageOption option; + int32_t errCode = remote->SendRequest(UNSUBSCRIBE_PROFILE_EVENT, data, reply, option); + if (errCode != ERR_OK) { + HILOGE("transact failed, errCode = %{public}d", errCode); + if (!DeviceProfileUtils::ReadProfileEvents(reply, failedEvents)) { + HILOGW("read profile events failed"); + } + } + return errCode; +} + +int32_t DistributedDeviceProfileProxy::SyncDeviceProfile(const SyncOptions& syncOptions, + const sptr& profileEventNotifier) +{ + sptr remote = Remote(); + MessageParcel data; + if (!data.WriteInterfaceToken(IDistributedDeviceProfile::GetDescriptor())) { + HILOGE("write inteface token failed"); + return ERR_FLATTEN_OBJECT; + } + + if (!syncOptions.Marshalling(data)) { + HILOGE("marshall option failed"); + return ERR_FLATTEN_OBJECT; + } + + PARCEL_WRITE_HELPER(data, RemoteObject, profileEventNotifier); + MessageParcel reply; + PARCEL_TRANSACT_SYNC_RET_INT(remote, SYNC_DEVICE_PROFILE, data, reply); +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/core/src/profile_event_notifier_stub.cpp b/interfaces/innerkits/core/src/profile_event_notifier_stub.cpp new file mode 100755 index 0000000000000000000000000000000000000000..2960d637d153c27a8c147b840fb8179597c15310 --- /dev/null +++ b/interfaces/innerkits/core/src/profile_event_notifier_stub.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "profile_event_notifier_stub.h" + +#include "device_profile_errors.h" +#include "device_profile_log.h" +#include "profile_event.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "ProfileEventNotifierStub"; +} + +const ProfileEventNotifierStub::HandlersMap ProfileEventNotifierStub::handlersMap_ = + ProfileEventNotifierStub::InitHandlersMap(); + +ProfileEventNotifierStub::HandlersMap ProfileEventNotifierStub::InitHandlersMap() +{ + ProfileEventNotifierStub::HandlersMap m; + m[EVENT_SYNC_COMPLETED] = &ProfileEventNotifierStub::OnSyncCompletedInner; + m[EVENT_PROFILE_CHANGED] = &ProfileEventNotifierStub::OnProfileChangedInner; + return m; +} + +int32_t ProfileEventNotifierStub::OnRemoteRequest(uint32_t code, MessageParcel& data, + MessageParcel& reply, MessageOption& option) +{ + HILOGI("code = %{public}d", code); + std::u16string descriptor = ProfileEventNotifierStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + HILOGE("check descriptor failed"); + return ERR_DP_INTERFACE_CHECK_FAILED; + } + + auto iter = handlersMap_.find(code); + if (iter != handlersMap_.end()) { + if (auto handler = iter->second; handler != nullptr) { + return (this->*handler)(data, reply); + } + } + HILOGW("unknown request code, please check"); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +int32_t ProfileEventNotifierStub::OnSyncCompletedInner(MessageParcel& data, + [[maybe_unused]] MessageParcel& reply) +{ + int32_t size = data.ReadInt32(); + if (size <= 0) { + HILOGW("size %{public}d", size); + return ERR_DP_INVALID_PARAMS; + } + + SyncResult syncResults; + for (int32_t i = 0; i < size; i++) { + syncResults.emplace(data.ReadString(), static_cast(data.ReadInt32())); + } + if (profileEventCb_ != nullptr) { + profileEventCb_->OnSyncCompleted(syncResults); + } + return ERR_OK; +} + +int32_t ProfileEventNotifierStub::OnProfileChangedInner(MessageParcel& data, + [[maybe_unused]] MessageParcel& reply) +{ + ProfileChangeNotification changeNotification; + if (!changeNotification.Unmarshalling(data)) { + HILOGW("marshalling failed"); + return ERR_DP_INVALID_PARAMS; + } + profileEventCb_->OnProfileChanged(changeNotification); + return ERR_OK; +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/ohos.build b/ohos.build new file mode 100755 index 0000000000000000000000000000000000000000..84a0063c9d7cac789e4c995f828e6b8bc5e14932 --- /dev/null +++ b/ohos.build @@ -0,0 +1,34 @@ +{ + "parts": { + "device_profile_core": { + "variants": ["phone", "wearable"], + "inner_kits": [ + { + "header": { + "header_base": "//foundation/deviceprofile/device_profile_core/interfaces/innerkits/core/include", + "header_files": [ + "distributed_device_profile_client.h", + "distributed_device_profile_proxy.h", + "idistributed_device_profile.h", + "iprofile_event_callback.h", + "profile_change_notification.h", + "profile_event.h", + "service_characteristic_profile.h", + "subscribe_info.h" + ] + }, + "name": "//foundation/deviceprofile/device_profile_core/interfaces/innerkits/core:distributed_device_profile_client" + } + ], + "module_list": [ + "//foundation/deviceprofile/device_profile_core/sa_profile:dps_sa_profile", + "//foundation/deviceprofile/device_profile_core/services/core:distributed_device_profile" + ], + "system_kits": [], + "test_list": [ + "//foundation/deviceprofile/device_profile_core/services/core:unittest" + ] + } + }, + "subsystem": "deviceprofile" +} \ No newline at end of file diff --git a/sa_profile/6001.xml b/sa_profile/6001.xml new file mode 100755 index 0000000000000000000000000000000000000000..8b2a600a60bf7b2e5d293447db0a2fff3b60510e --- /dev/null +++ b/sa_profile/6001.xml @@ -0,0 +1,24 @@ + + + + distributedsched + + 6001 + libdistributed_device_profile.z.so + true + false + 1 + + \ No newline at end of file diff --git a/sa_profile/BUILD.gn b/sa_profile/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..4a55b45178d0b17bb15cb6e91fe2c53cef64c508 --- /dev/null +++ b/sa_profile/BUILD.gn @@ -0,0 +1,19 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos/sa_profile/sa_profile.gni") + +ohos_sa_profile("dps_sa_profile") { + sources = [ "6001.xml" ] + part_name = "device_profile_core" +} diff --git a/services/core/BUILD.gn b/services/core/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..8ae83922c2edab61dd6d02f3284fc2a59916ce20 --- /dev/null +++ b/services/core/BUILD.gn @@ -0,0 +1,96 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//build/ohos_var.gni") + +device_profile_path = "//foundation/deviceprofile/device_profile_core" +device_profile_innerkits = "${device_profile_path}/interfaces/innerkits" +distributed_datamgr_innerkits = + "//foundation/distributeddatamgr/distributeddatamgr/interfaces/innerkits" + +config("device_profile_core_config") { + visibility = [ ":*" ] + include_dirs = [ + "include", + "include/devicemanager", + "include/contentsensor", + "include/dbstorage", + "include/subscribemanager", + "${device_profile_path}/common/include", + "${device_profile_innerkits}/core/include", + "${distributed_datamgr_innerkits}/distributeddata/include", + "//third_party/json/include", + ] +} + +dp_common_sources = + [ "${device_profile_path}/common/src/device_profile_utils.cpp" ] + +ohos_shared_library("distributed_device_profile") { + install_enable = true + sources = [ + "src/contentsensor/content_collector.cpp", + "src/contentsensor/content_sensor_manager.cpp", + "src/contentsensor/device_info_collector.cpp", + "src/contentsensor/system_info_collector.cpp", + "src/dbstorage/device_profile_storage.cpp", + "src/dbstorage/device_profile_storage_manager.cpp", + "src/dbstorage/kvstore_death_recipient.cpp", + "src/dbstorage/online_sync_table.cpp", + "src/devicemanager/device_basic_info.cpp", + "src/devicemanager/device_manager.cpp", + "src/distributed_device_profile_service.cpp", + "src/distributed_device_profile_stub.cpp", + "src/profile_change_notification.cpp", + "src/service_characteristic_profile.cpp", + "src/subscribemanager/profile_change_handler.cpp", + "src/subscribemanager/profile_event_handler.cpp", + "src/subscribemanager/profile_event_handler_factory.cpp", + "src/subscribemanager/profile_event_notifier_proxy.cpp", + "src/subscribemanager/profile_sync_handler.cpp", + "src/subscribemanager/subscribe_info.cpp", + "src/subscribemanager/subscribe_info_checker.cpp", + "src/subscribemanager/subscribe_manager.cpp", + "src/subscribemanager/subscriber_death_recipient.cpp", + "src/sync_options.cpp", + ] + + sources += dp_common_sources + + configs = [ ":device_profile_core_config" ] + + deps = [ + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", + "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributeddatamgr/distributeddatamgr/interfaces/innerkits/distributeddata:distributeddata_inner", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//utils/native/base:utils", + ] + + external_deps = [ + "dsoftbus_standard:softbus_client", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + part_name = "device_profile_core" + subsystem_name = "deviceprofile" +} + +group("unittest") { + testonly = true + deps = [ "test:unittest" ] +} diff --git a/services/core/include/contentsensor/content_collector.h b/services/core/include/contentsensor/content_collector.h new file mode 100755 index 0000000000000000000000000000000000000000..6be780fcc036bd11b772f76c600d831a415a545b --- /dev/null +++ b/services/core/include/contentsensor/content_collector.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_CONTENT_COLLECTOR_H +#define OHOS_DEVICE_PROFILE_CONTENT_COLLECTOR_H + +#include "service_characteristic_profile.h" + +namespace OHOS { +namespace DeviceProfile { +class ContentCollector { +public: + ContentCollector() = default; + virtual ~ContentCollector() = default; + virtual void ConvertToProfileData(ServiceCharacteristicProfile& profile) = 0; + + void DoCollect(ServiceCharacteristicProfile& profileData); +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_CONTENT_COLLECTOR_H \ No newline at end of file diff --git a/services/core/include/contentsensor/content_sensor_manager.h b/services/core/include/contentsensor/content_sensor_manager.h new file mode 100755 index 0000000000000000000000000000000000000000..a07007c724db41c33efc5361271eabe6eff0ea23 --- /dev/null +++ b/services/core/include/contentsensor/content_sensor_manager.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_CONTENT_SENSOR_MANAGER_H +#define OHOS_DEVICE_PROFILE_CONTENT_SENSOR_MANAGER_H + +#include + +#include "content_collector.h" +#include "event_handler.h" +#include "single_instance.h" + +namespace OHOS { +namespace DeviceProfile { +class ContentSensorManager { + DECLARE_SINGLE_INSTANCE(ContentSensorManager); + +public: + bool Init(); + +private: + bool Collect(); + std::shared_ptr csCollectorHandler_; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_CONTENT_SENSOR_MANAGER_H \ No newline at end of file diff --git a/services/core/include/contentsensor/device_info_collector.h b/services/core/include/contentsensor/device_info_collector.h new file mode 100755 index 0000000000000000000000000000000000000000..3bf97656df1586e5a1286124db1d4a9c4cbed8a6 --- /dev/null +++ b/services/core/include/contentsensor/device_info_collector.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_DEVICE_INFO_TASK_H +#define OHOS_DEVICE_PROFILE_DEVICE_INFO_TASK_H + +#include + +#include "content_collector.h" +#include "service_characteristic_profile.h" + +namespace OHOS { +namespace DeviceProfile { +class DeviceInfoCollector : public ContentCollector { +public: + void ConvertToProfileData(ServiceCharacteristicProfile& profile) override; + +private: + std::string GetDeviceModel(); + std::string GetDeviceManufacturer(); + std::string GetDeviceSerial(); + std::string GetDeviceType(); + std::string GetDeviceName(); + std::string GetDeviceUdid(); + std::string GetDeviceProductId(); +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_DEVICE_INFO_TASK_H \ No newline at end of file diff --git a/services/core/include/contentsensor/system_info_collector.h b/services/core/include/contentsensor/system_info_collector.h new file mode 100755 index 0000000000000000000000000000000000000000..d65d6974502361a4d89c4042b7cf7636f7cddf99 --- /dev/null +++ b/services/core/include/contentsensor/system_info_collector.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_SYSTEM_INFO_COLLECTOR_H +#define OHOS_DEVICE_PROFILE_SYSTEM_INFO_COLLECTOR_H + +#include + +#include "content_collector.h" +#include "service_characteristic_profile.h" + +namespace OHOS { +namespace DeviceProfile { +class SystemInfoCollector : public ContentCollector { +public: + void ConvertToProfileData(ServiceCharacteristicProfile& profile) override; + +private: + int32_t GetOsType(); + std::string GetApiVersion(); + std::string GetOsVersion(); +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_SYSTEM_INFO_COLLECTOR_H \ No newline at end of file diff --git a/services/core/include/dbstorage/device_profile_storage.h b/services/core/include/dbstorage/device_profile_storage.h new file mode 100755 index 0000000000000000000000000000000000000000..3c9da4593560b1ecc95e625c85b4b7d743bd1e85 --- /dev/null +++ b/services/core/include/dbstorage/device_profile_storage.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DEVICE_PROFILE_STORAGE_H +#define OHOS_DISTRIBUTED_DEVICE_PROFILE_STORAGE_H + +#include +#include + +#include "distributed_kv_data_manager.h" +#include "event_handler.h" +#include "kvstore_observer.h" +#include "kvstore_sync_callback.h" + +namespace OHOS { +namespace DeviceProfile { +enum StorageInitStatus { + UNINITED = 1, + INIT_FAILED = 2, + INIT_SUCCEED = 3 +}; + +class DeviceProfileStorage { +public: + using KvStoreInitCallback = std::function; + + DeviceProfileStorage(const std::string& appId, const std::string& storeId); + virtual ~DeviceProfileStorage() = default; + + virtual void Init(); + virtual int32_t GetDeviceProfile(const std::string& key, std::string& value); + virtual int32_t DeleteDeviceProfile(const std::string& key); + virtual int32_t PutDeviceProfile(const std::string& key, const std::string& value); + virtual int32_t PutDeviceProfileBatch(const std::vector& keys, + const std::vector& values); + virtual int32_t SyncDeviceProfile(const std::vector& deviceIdList, + DistributedKv::SyncMode syncMode); + + void SetOptions(const DistributedKv::Options& options); + StorageInitStatus GetInitStatus(); + bool RegisterKvStoreInitCallback(const KvStoreInitCallback& callback); + int32_t SubscribeKvStore(const std::shared_ptr& observer); + int32_t UnSubscribeKvStore(const std::shared_ptr& observer); + int32_t RegisterSyncCallback(const std::shared_ptr& sycnCb); + int32_t UnRegisterSyncCallback(); + +private: + bool TryGetKvStore(); + bool InitKvStore(); + DistributedKv::Status GetKvStore(); + void DeleteKvStore(); + void SubscribeDeviceProfileKvStore(); + +private: + DistributedKv::Options options_; + DistributedKv::AppId appId_; + DistributedKv::StoreId storeId_; + DistributedKv::DistributedKvDataManager dataManager_; + + std::shared_ptr kvStorePtr_; + std::atomic initStatus_ {StorageInitStatus::UNINITED}; + KvStoreInitCallback kvStoreInitCallback_; + std::shared_mutex storageLock_; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DEVICE_PROFILE_STORAGE_H diff --git a/services/core/include/dbstorage/device_profile_storage_manager.h b/services/core/include/dbstorage/device_profile_storage_manager.h new file mode 100755 index 0000000000000000000000000000000000000000..64406479e8c5761304ee095ace193ed82f1f452f --- /dev/null +++ b/services/core/include/dbstorage/device_profile_storage_manager.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DEVICE_PROFILE_STORAGE_MANAGER_H +#define OHOS_DISTRIBUTED_DEVICE_PROFILE_STORAGE_MANAGER_H + +#include +#include + +#include "device_profile_storage.h" +#include "event_handler.h" +#include "kvstore_death_recipient.h" +#include "online_sync_table.h" +#include "service_characteristic_profile.h" +#include "single_instance.h" + +#include "device_manager.h" +#include "sync_options.h" + +#include "nlohmann/json.hpp" + +namespace OHOS { +namespace DeviceProfile { +enum KeyType { + UNKNOWN = -1, + SERVICE = 0, + SERVICE_LIST = 1, + DEVICE_INFO = 2 +}; + +class DeviceProfileStorageManager { + DECLARE_SINGLE_INSTANCE(DeviceProfileStorageManager); + friend class DeviceProfile::DeviceManager; + +public: + bool Init(); + void OnKvStoreInitDone(); + + int32_t PutDeviceProfile(const ServiceCharacteristicProfile& profile); + int32_t DeleteDeviceProfile(const std::string& serviceId); + int32_t GetDeviceProfile(const std::string& udid, const std::string& serviceId, + ServiceCharacteristicProfile& profile); + int32_t SyncDeviceProfile(const SyncOptions& syncOptions, + const sptr& profileEventNotifier); + + int32_t SubscribeKvStore(const std::shared_ptr& observer); + int32_t UnSubscribeKvStore(const std::shared_ptr& observer); + int32_t RegisterSyncCallback(const std::shared_ptr& sycnCb); + int32_t UnRegisterSyncCallback(); + void NotifySyncCompleted(); + void NotifySubscriberDied(const sptr& profileEventNotifier); + +private: + bool WaitKvDataService(); + void RestoreServiceItemLocked(const std::string& value); + void RegisterCallbacks(); + void FlushProfileItems(); + std::string GenerateKey(const std::string& udid, const std::string& key, KeyType keyType); + + void OnNodeOnline(const std::shared_ptr deviceBasicInfo); + bool CheckSyncOption(const SyncOptions& syncOptions); + int32_t NotifySyncStart(const sptr& profileEventNotifier); + void SetServiceType(const std::string& udid, const std::string& serviceId, ServiceCharacteristicProfile& profile); + +private: + std::mutex serviceLock_; + std::mutex callbackLock_; + nlohmann::json servicesJson_; + std::unique_ptr onlineSyncTbl_; + std::shared_ptr storageHandler_; + sptr kvStoreDeathRecipient_; + std::string localUdid_; + std::map profileItems_; + std::atomic kvDataServiceFailed_ {false}; + std::atomic inited_ {false}; + std::shared_ptr kvStoreObserver_; + std::shared_ptr kvStoreSyncCallback_; + std::mutex profileSyncLock_; + sptr syncEventNotifier_; + std::atomic isSync_ {false}; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DEVICE_PROFILE_STORAGE_MANAGER_H \ No newline at end of file diff --git a/services/core/include/dbstorage/kvstore_death_recipient.h b/services/core/include/dbstorage/kvstore_death_recipient.h new file mode 100755 index 0000000000000000000000000000000000000000..a8c8cec266335b266bbb74f5e19798abc4234a6c --- /dev/null +++ b/services/core/include/dbstorage/kvstore_death_recipient.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_KVSTORE_DEATH_RECIPIENT_H +#define OHOS_KVSTORE_DEATH_RECIPIENT_H + +#include "iremote_object.h" + +namespace OHOS { +namespace DeviceProfile { +class KvStoreDeathRecipient : public IRemoteObject::DeathRecipient { +public: + void OnRemoteDied(const wptr& remote) override; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_KVSTORE_DEATH_RECIPIENT_H \ No newline at end of file diff --git a/services/core/include/dbstorage/online_sync_table.h b/services/core/include/dbstorage/online_sync_table.h new file mode 100755 index 0000000000000000000000000000000000000000..b08c0659993376d1dd4a521ba5da2bcc2f3c7fc5 --- /dev/null +++ b/services/core/include/dbstorage/online_sync_table.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DEVICE_PROFILE_ONLINE_SYNC_TABLE_H +#define OHOS_DISTRIBUTED_DEVICE_PROFILE_ONLINE_SYNC_TABLE_H + +#include "device_profile_storage.h" + +namespace OHOS { +namespace DeviceProfile { +class OnlineSyncTable : public DeviceProfileStorage { +public: + OnlineSyncTable(); + ~OnlineSyncTable() = default; + + void Init() override; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DEVICE_PROFILE_ONLINE_SYNC_TABLE_H \ No newline at end of file diff --git a/services/core/include/devicemanager/device_basic_info.h b/services/core/include/devicemanager/device_basic_info.h new file mode 100755 index 0000000000000000000000000000000000000000..714c5bc714c0dab633da2560172c5307d190c98f --- /dev/null +++ b/services/core/include/devicemanager/device_basic_info.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_DEVICE_BASIC_INFO_H +#define OHOS_DEVICE_PROFILE_DEVICE_BASIC_INFO_H + +#include + +#include "parcel.h" + +namespace OHOS { +namespace DeviceProfile { +enum { + UNKNOWN_TYPE = 0x00, +}; + +class DeviceBasicInfo { +public: + DeviceBasicInfo(const std::string& deviceName, const std::string& deviceId, int32_t deviceType) + : deviceName_(deviceName), deviceId_(deviceId), deviceType_(deviceType) {} + ~DeviceBasicInfo() = default; + + const std::string& GetDeviceName() const; + const std::string& GetDeviceId() const; + int32_t GetDeviceType() const; + +private: + std::string deviceName_; + std::string deviceId_; + int32_t deviceType_ = UNKNOWN_TYPE; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_DEVICE_BASIC_INFO_H diff --git a/services/core/include/devicemanager/device_manager.h b/services/core/include/devicemanager/device_manager.h new file mode 100755 index 0000000000000000000000000000000000000000..27664fbd0d99ee9e59fc0bb09545bcff234e2181 --- /dev/null +++ b/services/core/include/devicemanager/device_manager.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_DEVICE_MANAGER_H +#define OHOS_DEVICE_PROFILE_DEVICE_MANAGER_H + +#include +#include +#include + +#include "event_handler.h" +#include "single_instance.h" +#include "device_basic_info.h" +#include "softbus_bus_center.h" + +namespace OHOS { +namespace DeviceProfile { +enum DeviceIdType : uint8_t { + NETWORKID = 0, + UDID = 1, + UUID = 2 +}; + +class DeviceManager { + DECLARE_SINGLE_INSTANCE(DeviceManager); +public: + bool Init(); + std::unique_ptr GetLocalBasicInfo(); + void GetLocalDeviceUdid(std::string& udid); + bool GetUdidByNetworkId(const std::string& networkId, std::string& udid); + bool GetUuidByNetworkId(const std::string& networkId, std::string& uuid); + void DisconnectSoftbus(); + bool ConnectSoftbus(); + bool TransformDeviceId(const std::string& fromDeviceId, std::string& toDeviceId, + DeviceIdType toType); + void GetDeviceIdList(std::list& deviceIdList); + void GetDeviceList(std::list>& deviceList); + +private: + static void OnNodeOnlineAdapter(NodeBasicInfo* info); + static void OnNodeOfflineAdapter(NodeBasicInfo* info); + static void OnNodeBasicInfoChangedAdapter(NodeBasicInfoType type, NodeBasicInfo* info); + + bool GetUuidOrUdidByNetworkId(const std::string& nodeId, NodeDeivceInfoKey keyType, + std::string& uuidOrUdid); + void OnNodeOnline(const std::shared_ptr deviceBasicInfo); + void OnNodeOffline(const std::string& deviceId); + void OnNodeBasicInfoChanged(const std::string& deviceId, NodeBasicInfoType type); + void AddLocalDeviceIds(); + void AddDeviceIds(const std::string& networkId); + void RemoveDeviceIds(const std::string& networkId); + void RecoverDevicesIfNeeded(); + +private: + INodeStateCb nodeStateCb_; + std::mutex deviceLock_; + std::shared_ptr devMgrHandler_; + std::map> remoteDeviceInfoMap_; + std::list> deviceIdsList_; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_DEVICE_MANAGER_H diff --git a/services/core/include/distributed_device_profile_service.h b/services/core/include/distributed_device_profile_service.h new file mode 100755 index 0000000000000000000000000000000000000000..b2856cbf26fd045fa31fb4aadd8c496ac1c84ecb --- /dev/null +++ b/services/core/include/distributed_device_profile_service.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DEVICE_PROFILE_SERVICE_H +#define OHOS_DISTRIBUTED_DEVICE_PROFILE_SERVICE_H + +#include "distributed_device_profile_stub.h" +#include "single_instance.h" + +#include "system_ability.h" + +namespace OHOS { +namespace DeviceProfile { +class DistributedDeviceProfileService : public SystemAbility, public DistributedDeviceProfileStub { + DECLARE_SYSTEM_ABILITY(DistributedDeviceProfileService); + DECLARE_SINGLE_INSTANCE_BASE(DistributedDeviceProfileService); + +public: + DistributedDeviceProfileService(); + ~DistributedDeviceProfileService() = default; + + int32_t PutDeviceProfile(const ServiceCharacteristicProfile& profile) override; + int32_t DeleteDeviceProfile(const std::string& serviceId) override; + int32_t GetDeviceProfile(const std::string& udid, const std::string& serviceId, + ServiceCharacteristicProfile& profile) override; + int32_t SubscribeProfileEvents(const std::list& subscribeInfos, + const sptr& profileEventNotifier, + std::list& failedEvents) override; + int32_t UnsubscribeProfileEvents(const std::list& profileEvents, + const sptr& profileEventNotifier, + std::list& failedEvents) override; + int32_t SyncDeviceProfile(const SyncOptions& syncOptions, + const sptr& profileEventNotifier) override; + +protected: + void OnStart() override; + void OnStop() override; + +private: + bool Init(); +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DEVICE_PROFILE_SERVICE_H \ No newline at end of file diff --git a/services/core/include/distributed_device_profile_stub.h b/services/core/include/distributed_device_profile_stub.h new file mode 100755 index 0000000000000000000000000000000000000000..3223b55818263df97f8eaecc602763a9be42e7a7 --- /dev/null +++ b/services/core/include/distributed_device_profile_stub.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DEVICE_PROFILE_STUB_H +#define OHOS_DISTRIBUTED_DEVICE_PROFILE_STUB_H + +#include "idistributed_device_profile.h" + +#include + +#include "iremote_stub.h" + +namespace OHOS { +namespace DeviceProfile { +class DistributedDeviceProfileStub : public IRemoteStub { +public: + DistributedDeviceProfileStub(); + ~DistributedDeviceProfileStub() = default; + + int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, + MessageOption& option) override; + + int32_t PutDeviceProfileInner(MessageParcel& data, MessageParcel& reply); + int32_t DeleteDeviceProfileInner(MessageParcel& data, MessageParcel& reply); + int32_t GetDeviceProfileInner(MessageParcel& data, MessageParcel& reply); + int32_t SubscribeProfileEventInner(MessageParcel& data, MessageParcel& reply); + int32_t UnsubscribeProfileEventInner(MessageParcel& data, MessageParcel& reply); + int32_t SyncDeviceProfileInner(MessageParcel& data, MessageParcel& reply); + +private: + using Func = int32_t(DistributedDeviceProfileStub::*)(MessageParcel& data, MessageParcel& reply); + + bool EnforceInterfaceToken(MessageParcel& data); + +private: + std::map funcsMap_; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DEVICE_PROFILE_STUB_H \ No newline at end of file diff --git a/services/core/include/subscribemanager/profile_change_handler.h b/services/core/include/subscribemanager/profile_change_handler.h new file mode 100755 index 0000000000000000000000000000000000000000..acd18a4135537e379c75231f5cd0e487ad3d3c3f --- /dev/null +++ b/services/core/include/subscribemanager/profile_change_handler.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DEVICE_PROFILE_PROFILE_CHANGE_HANDLER_H +#define OHOS_DISTRIBUTED_DEVICE_PROFILE_PROFILE_CHANGE_HANDLER_H + +#include + +#include "profile_change_notification.h" +#include "profile_event_handler.h" + +#include "kvstore_observer.h" + +namespace OHOS { +namespace DeviceProfile { +class ProfileChangeHandler : public std::enable_shared_from_this, + public ProfileEventHandler, + public DistributedKv::KvStoreObserver { +public: + explicit ProfileChangeHandler(const std::string& handlerName) + : ProfileEventHandler(handlerName) {} + ~ProfileChangeHandler() = default; + + void OnChange(const DistributedKv::ChangeNotification& changeNotification, + std::shared_ptr snapshot) override {}; + void OnChange(const DistributedKv::ChangeNotification& changeNotification) override; + +private: + int32_t Register() override; + int32_t Unregister() override; + + void ConvertEntry(const std::vector& entries, ProfileChangeType changeType, + std::vector& profileEntries, Service2Index& service2Index); + + void NotifyProfileChanged(const ProfileChangeNotification& changeNotification, + const Service2Index& service2Index); + void FilterChangedProfileLocked(const SubscribeInfo& subscribeInfo, + const ProfileChangeNotification& changeNotification, + const Service2Index& service2Index, FilterInfo& filterInfo); + void NotifyProfileChangedLocked(const ProfileChangeNotification& changeNotification, + const FilterInfo& filterInfo, + const sptr& profileEventNotifier); +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DEVICE_PROFILE_PROFILE_CHANGE_HANDLER_H diff --git a/services/core/include/subscribemanager/profile_event_handler.h b/services/core/include/subscribemanager/profile_event_handler.h new file mode 100755 index 0000000000000000000000000000000000000000..a787f6566af2f7baf2ea1c3c754a62bf439ff644 --- /dev/null +++ b/services/core/include/subscribemanager/profile_event_handler.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include + +#include "event_handler.h" +#include "iremote_object.h" + +#include "iprofile_event_notifier.h" +#include "profile_event.h" +#include "profile_change_notification.h" +#include "subscribe_info.h" +#include "single_instance.h" + +#ifndef OHOS_DEVICE_PROFILE_PROFILE_EVENT_HANDLER_H +#define OHOS_DEVICE_PROFILE_PROFILE_EVENT_HANDLER_H + +namespace OHOS { +namespace DeviceProfile { +struct FilterInfo { + bool filtered {false}; + std::unordered_set indexes; +}; + +class ProfileEventHandler { + friend class SubscriberDeathRecipient; +public: + explicit ProfileEventHandler(const std::string& handlerName) + : handlerName_(handlerName) {} + virtual ~ProfileEventHandler() = default; + + bool Init(); + bool IsRegistered() const; + + int32_t Subscribe(const SubscribeInfo& subscribeInfo, const sptr& profileEventNotifier); + int32_t Unsubscribe(const sptr& profileEventNotifier); + void OnSubscriberDied(const sptr& profileEventNotifier); + +protected: + std::atomic isRegistered_ {false}; + std::mutex notifierLock_; + std::map, SubscribeInfo> profileEventSubscribeInfos_; + std::string handlerName_; + std::shared_ptr eventHandler_; + +private: + virtual int32_t Register() = 0; + virtual int32_t Unregister() = 0; +}; +} // namespace DeviceProfile +} // namespace OHOS + +#endif // OHOS_DEVICE_PROFILE_I_PROFILE_EVENT_H diff --git a/services/core/include/subscribemanager/profile_event_handler_factory.h b/services/core/include/subscribemanager/profile_event_handler_factory.h new file mode 100755 index 0000000000000000000000000000000000000000..d4ac67f9d8abca88d612187f4ded98ea32c668d6 --- /dev/null +++ b/services/core/include/subscribemanager/profile_event_handler_factory.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_PROFILE_EVENT_HANDLER_FACTORY_H +#define OHOS_DEVICE_PROFILE_PROFILE_EVENT_HANDLER_FACTORY_H + +#include "profile_event.h" +#include "profile_event_handler.h" +#include "single_instance.h" + +namespace OHOS { +namespace DeviceProfile { +class ProfileEventHandlerFactory { + DECLARE_SINGLE_INSTANCE_BASE(ProfileEventHandlerFactory); + +public: + ProfileEventHandlerFactory(); + ~ProfileEventHandlerFactory() = default; + + std::shared_ptr GetHandler(ProfileEvent profileEvent); + +private: + using Handler = std::shared_ptr(ProfileEventHandlerFactory::*)(); + + std::shared_ptr GetProfileChangeHandlerInner(); + std::shared_ptr GetProfileSyncHandlerInner(); + +private: + std::map handlersMap_; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_PROFILE_EVENT_HANDLER_FACTORY_H diff --git a/services/core/include/subscribemanager/profile_event_notifier_proxy.h b/services/core/include/subscribemanager/profile_event_notifier_proxy.h new file mode 100755 index 0000000000000000000000000000000000000000..afcc3b6928b0bae57863c17e1c1d3aaaea1793ea --- /dev/null +++ b/services/core/include/subscribemanager/profile_event_notifier_proxy.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_I_PROFILE_SYNC_CALLBACK_PROXY_H +#define OHOS_DEVICE_PROFILE_I_PROFILE_SYNC_CALLBACK_PROXY_H + +#include "iprofile_event_notifier.h" +#include "iremote_proxy.h" + +namespace OHOS { +namespace DeviceProfile { +class ProfileEventNotifierProxy : public IRemoteProxy { +public: + explicit ProfileEventNotifierProxy(const sptr& impl); + ~ProfileEventNotifierProxy() = default; + + void OnSyncCompleted(const SyncResult& syncResults) override; + void OnProfileChanged(const ProfileChangeNotification& changeNotification) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace DeviceProfile +} // namespace OHOS + +#endif // OHOS_DEVICE_PROFILE_I_PROFILE_SYNC_CALLBACK_PROXY_H diff --git a/services/core/include/subscribemanager/profile_sync_handler.h b/services/core/include/subscribemanager/profile_sync_handler.h new file mode 100755 index 0000000000000000000000000000000000000000..3e17e77f38e07ba5e60d123bcc8abf15c063cbed --- /dev/null +++ b/services/core/include/subscribemanager/profile_sync_handler.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_PROFILE_SYNC_HANDLER_H +#define OHOS_DEVICE_PROFILE_PROFILE_SYNC_HANDLER_H + +#include + +#include "kvstore_sync_callback.h" +#include "profile_event_handler.h" + +namespace OHOS { +namespace DeviceProfile { +using namespace OHOS::DistributedKv; + +class ProfileSyncHandler : public std::enable_shared_from_this, + public ProfileEventHandler, + public DistributedKv::KvStoreSyncCallback { +public: + explicit ProfileSyncHandler(const std::string& handlerName) + : ProfileEventHandler(handlerName) {} + ~ProfileSyncHandler() = default; + + void SyncCompleted(const std::map& results) override; + +private: + int32_t Register() override; + int32_t Unregister() override; + + void NotifySyncCompleted(const SyncResult& syncResults); +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_PROFILE_SYNC_HANDLER_H diff --git a/services/core/include/subscribemanager/subscribe_info_checker.h b/services/core/include/subscribemanager/subscribe_info_checker.h new file mode 100755 index 0000000000000000000000000000000000000000..e78029facf66a2d926aaf766cad33de2414ab76c --- /dev/null +++ b/services/core/include/subscribemanager/subscribe_info_checker.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_SUBSCRIBE_INFO_CHECKER_H +#define OHOS_DEVICE_PROFILE_SUBSCRIBE_INFO_CHECKER_H + +#include + +#include "single_instance.h" +#include "subscribe_info.h" + +namespace OHOS { +namespace DeviceProfile { +class SubscribeInfoChecker { + DECLARE_SINGLE_INSTANCE_BASE(SubscribeInfoChecker); +public: + SubscribeInfoChecker(); + ~SubscribeInfoChecker() = default; + + bool Check(const std::list& subscribeInfos); + +private: + using Checker = bool(SubscribeInfoChecker::*)(const SubscribeInfo&); + + bool CheckSyncEventInner(const SubscribeInfo& subscribeInfo); + bool CheckProfileChangeInner(const SubscribeInfo& subscribeInfo); + +private: + std::map checkersMap_; +}; +} // namespace DeviceProfile +} // namespace OHOS + +#endif // OHOS_DEVICE_PROFILE_SUBSCRIBE_INFO_CHECKER_H diff --git a/services/core/include/subscribemanager/subscribe_manager.h b/services/core/include/subscribemanager/subscribe_manager.h new file mode 100755 index 0000000000000000000000000000000000000000..4e7e2a24b21c2e83960fabca946b2800feb72258 --- /dev/null +++ b/services/core/include/subscribemanager/subscribe_manager.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_SUBSCRIBE_MANAGER_H +#define OHOS_DEVICE_PROFILE_SUBSCRIBE_MANAGER_H + +#include +#include +#include +#include + +#include "iremote_object.h" +#include "single_instance.h" +#include "iprofile_event_notifier.h" +#include "profile_event.h" +#include "profile_change_notification.h" + +#include "profile_event_handler.h" +#include "subscribe_info.h" + +namespace OHOS { +namespace DeviceProfile { +class SubscribeManager { + DECLARE_SINGLE_INSTANCE(SubscribeManager); + +public: + bool Init(); + + int32_t SubscribeProfileEvents(const std::list& subscribeInfos, + const sptr& profileEventNotifier, + std::list& failedEvents); + int32_t UnsubscribeProfileEvents(const std::list& profileEvents, + const sptr& profileEventNotifier, + std::list& failedEvents); + + void OnSubscriberDied(const sptr& profileEventNotifier); + +private: + struct NotifierInfo { + int32_t callingUid; + ProfileEvents profileEvents; + }; + + void TryAddNotifierLocked(const sptr& profileEventNotifier, + const ProfileEvents& profileEvents); + void TryRemoveNotiferLocked(const sptr& profileEventNotifier, + const ProfileEvents& profileEvents); + void IncSubsOfUidLocked(int32_t uid); + void DecSubsOfUidLocked(int32_t uid); + bool CheckSubsOfUid(int32_t uid); + +private: + std::mutex handlerLock_; + std::map, NotifierInfo> notifiersMap_; + std::map> handlersMap_; + std::unordered_map uidSubsMap_; + sptr subscriberDeathRecipient_; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_SUBSCRIBE_MANAGER_H diff --git a/services/core/include/subscribemanager/subscriber_death_recipient.h b/services/core/include/subscribemanager/subscriber_death_recipient.h new file mode 100755 index 0000000000000000000000000000000000000000..249072c85ea64413c4e996ad5f0fbd98380d5b39 --- /dev/null +++ b/services/core/include/subscribemanager/subscriber_death_recipient.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_SUBSCRIBER_DEATH_RECIPIENT_H +#define OHOS_DEVICE_PROFILE_SUBSCRIBER_DEATH_RECIPIENT_H + +#include "iremote_object.h" + +namespace OHOS { +namespace DeviceProfile { +class SubscriberDeathRecipient : public IRemoteObject::DeathRecipient { +public: + SubscriberDeathRecipient() = default; + ~SubscriberDeathRecipient() = default; + + void OnRemoteDied(const wptr& remote) override; +}; +} // namespace DeviceProfile +} // namespace OHOS +#endif // OHOS_DEVICE_PROFILE_SUBSCRIBER_DEATH_RECIPIENT_H diff --git a/services/core/src/contentsensor/content_collector.cpp b/services/core/src/contentsensor/content_collector.cpp new file mode 100755 index 0000000000000000000000000000000000000000..cbac30a1a617c93db099fff98adcdcc2853519b5 --- /dev/null +++ b/services/core/src/contentsensor/content_collector.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "content_collector.h" + +#include "device_profile_log.h" +#include "device_profile_storage_manager.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "ContentCollector"; +} + +void ContentCollector::DoCollect(ServiceCharacteristicProfile& profileData) +{ + DeviceProfileStorageManager::GetInstance().PutDeviceProfile(profileData); +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/src/contentsensor/content_sensor_manager.cpp b/services/core/src/contentsensor/content_sensor_manager.cpp new file mode 100755 index 0000000000000000000000000000000000000000..b0e64d827683dc937b5f848da3417fe25106239a --- /dev/null +++ b/services/core/src/contentsensor/content_sensor_manager.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "content_sensor_manager.h" + +#include "device_info_collector.h" +#include "device_profile_log.h" +#include "system_info_collector.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "ContentSensorManager"; +} + +IMPLEMENT_SINGLE_INSTANCE(ContentSensorManager); + +bool ContentSensorManager::Init() +{ + auto runner = AppExecFwk::EventRunner::Create("csCollector"); + csCollectorHandler_ = std::make_shared(runner); + if (csCollectorHandler_ == nullptr) { + return false; + } + return Collect(); +} + +bool ContentSensorManager::Collect() +{ + auto csTask = []() { + HILOGI("ContentSensorManager Collect"); + std::list> taskList; + taskList.push_back(std::make_shared()); + taskList.push_back(std::make_shared()); + for (auto& task : taskList) { + ServiceCharacteristicProfile profileData; + task->ConvertToProfileData(profileData); + task->DoCollect(profileData); + } + }; + if (!csCollectorHandler_->PostTask(csTask)) { + HILOGE("post task failed"); + return false; + } + return true; +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/src/contentsensor/device_info_collector.cpp b/services/core/src/contentsensor/device_info_collector.cpp new file mode 100755 index 0000000000000000000000000000000000000000..13c4c6025a8787d61d5efb75bd4793d2c291f7a9 --- /dev/null +++ b/services/core/src/contentsensor/device_info_collector.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "device_info_collector.h" + +#include "device_profile_errors.h" +#include "device_profile_log.h" + +#include "nlohmann/json.hpp" +#include "parameter.h" +#include "parameters.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "DeviceInfoCollector"; + +const std::string SERVICE_ID = "device"; +const std::string SERVICE_TYPE = "device"; +const std::string EMPTY_PARAM = ""; +const std::string DEVICE_NAME = "deviceName"; +const std::string DEVICE_MODEL = "model"; +const std::string DEVICE_UDID = "udid"; +const std::string DEVICE_TYPE = "devType"; +const std::string DEVICE_MANU = "manu"; +const std::string DEVICE_PRODUCT_ID = "prodId"; +const std::string DEVICE_SN = "sn"; +const std::string DEVICE_NAME_PARAM = "ro.product.name"; +const std::string DEVICE_TYPE_PARAM = "ro.build.characteristics"; +constexpr int32_t DEVICE_UUID_LENGTH = 65; +} + +void DeviceInfoCollector::ConvertToProfileData(ServiceCharacteristicProfile& profile) +{ + profile.SetServiceId(SERVICE_ID); + profile.SetServiceType(SERVICE_TYPE); + nlohmann::json jsonData; + jsonData[DEVICE_NAME] = GetDeviceName(); + jsonData[DEVICE_MODEL] = GetDeviceModel(); + jsonData[DEVICE_UDID] = GetDeviceUdid(); + jsonData[DEVICE_TYPE] = GetDeviceType(); + jsonData[DEVICE_MANU] = GetDeviceManufacturer(); + jsonData[DEVICE_PRODUCT_ID] = GetDeviceProductId(); + jsonData[DEVICE_SN] = GetDeviceSerial(); + profile.SetCharacteristicProfileJson(jsonData.dump()); +} + +std::string DeviceInfoCollector::GetDeviceModel() +{ + return GetProductModel(); +} + +std::string DeviceInfoCollector::GetDeviceManufacturer() +{ + return GetManufacture(); +} + +std::string DeviceInfoCollector::GetDeviceSerial() +{ + return GetSerial(); +} + +std::string DeviceInfoCollector::GetDeviceType() +{ + return system::GetParameter(DEVICE_TYPE_PARAM, EMPTY_PARAM); +} + +std::string DeviceInfoCollector::GetDeviceName() +{ + std::string devName = system::GetParameter(DEVICE_NAME_PARAM, EMPTY_PARAM); + if (!devName.empty()) { + return devName; + } + return GetProductModel(); +} + +std::string DeviceInfoCollector::GetDeviceUdid() +{ + char localDeviceId[DEVICE_UUID_LENGTH] = {0}; + GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH); + return localDeviceId; +} + +std::string DeviceInfoCollector::GetDeviceProductId() +{ + return ""; +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/src/contentsensor/system_info_collector.cpp b/services/core/src/contentsensor/system_info_collector.cpp new file mode 100755 index 0000000000000000000000000000000000000000..04254b9fe99fc45c664f9dacb2df5835b259ba65 --- /dev/null +++ b/services/core/src/contentsensor/system_info_collector.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "system_info_collector.h" + +#include "device_profile_errors.h" +#include "device_profile_log.h" + +#include "nlohmann/json.hpp" +#include "parameters.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "SystemInfoCollector"; + +const std::string SERVICE_ID = "system"; +const std::string SERVICE_TYPE = "system"; +const std::string EMPTY_PARAM = ""; +const std::string SYSTEM_OS_TYPE = "type"; +const std::string DEVICE_OHOS_VERSION = "harmonyVersion"; +const std::string DEVICE_API_LEVEL = "harmonyApiLevel"; +const std::string SYSTEM_OS_TYPE_PARAM = "hw_sc.build.os.enable"; +const std::string DEVICE_API_LEVEL_PARAM = "hw_sc.build.os.apiversion"; +const std::string DEVICE_OHOS_VERSION_PARAM = "hw_sc.build.os.version"; +constexpr int32_t OHOS_TYPE = 11; +} + +void SystemInfoCollector::ConvertToProfileData(ServiceCharacteristicProfile& profile) +{ + profile.SetServiceId(SERVICE_ID); + profile.SetServiceType(SERVICE_TYPE); + nlohmann::json jsonData; + jsonData[SYSTEM_OS_TYPE] = GetOsType(); + jsonData[DEVICE_OHOS_VERSION] = GetOsVersion(); + jsonData[DEVICE_API_LEVEL] = GetApiVersion(); + profile.SetCharacteristicProfileJson(jsonData.dump()); +} + +int32_t SystemInfoCollector::GetOsType() +{ + return OHOS_TYPE; +} + +std::string SystemInfoCollector::GetApiVersion() +{ + return system::GetParameter(DEVICE_API_LEVEL_PARAM, EMPTY_PARAM); +} + +std::string SystemInfoCollector::GetOsVersion() +{ + return system::GetParameter(DEVICE_OHOS_VERSION_PARAM, EMPTY_PARAM); +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/src/dbstorage/device_profile_storage.cpp b/services/core/src/dbstorage/device_profile_storage.cpp new file mode 100755 index 0000000000000000000000000000000000000000..eb5908057f7f45d25db77d41e48e3e942c2b24c1 --- /dev/null +++ b/services/core/src/dbstorage/device_profile_storage.cpp @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "device_profile_storage.h" + +#include +#include + +#include "device_profile_errors.h" +#include "device_profile_log.h" +#include "device_profile_storage_manager.h" +#include "service_characteristic_profile.h" + +#include "datetime_ex.h" +#include "profile_change_handler.h" + +namespace OHOS { +namespace DeviceProfile { +using namespace OHOS::DistributedKv; +using namespace std::chrono_literals; + +namespace { +const std::string TAG = "DeviceProfileStorage"; + +constexpr int32_t RETRY_TIMES_GET_KVSTORE = 10; +} + +DeviceProfileStorage::DeviceProfileStorage(const std::string& appId, const std::string& storeId) +{ + appId_.appId = appId, + storeId_.storeId = storeId; +} + +void DeviceProfileStorage::SetOptions(const Options& options) +{ + options_ = options; +} + +bool DeviceProfileStorage::RegisterKvStoreInitCallback(const KvStoreInitCallback& callback) +{ + if (kvStoreInitCallback_ != nullptr) { + HILOGE("callback is not null"); + return false; + } + kvStoreInitCallback_ = callback; + return true; +} + +void DeviceProfileStorage::Init() +{ + int64_t begin = GetTickCount(); + std::unique_lock writeLock(storageLock_); + bool result = TryGetKvStore(); + writeLock.unlock(); + int64_t end = GetTickCount(); + HILOGI("TryGetKvStore %{public}s, spend %{public}" PRId64 " ms", + result ? "succeeded" : "failed", end - begin); + // must call callback before set init status + if (kvStoreInitCallback_ != nullptr) { + kvStoreInitCallback_(); + } + initStatus_ = StorageInitStatus::INIT_SUCCEED; +} + +int32_t DeviceProfileStorage::SubscribeKvStore(const std::shared_ptr& observer) +{ + HILOGD("called"); + if (kvStorePtr_ == nullptr || observer == nullptr) { + return ERR_DP_INVALID_PARAMS; + } + Status status = kvStorePtr_->SubscribeKvStore(SubscribeType::DEFAULT, observer); + HILOGI("status %{public}d", status); + return static_cast(status); +} + +int32_t DeviceProfileStorage::UnSubscribeKvStore(const std::shared_ptr& observer) +{ + HILOGD("called"); + if (kvStorePtr_ == nullptr || observer == nullptr) { + return ERR_DP_INVALID_PARAMS; + } + Status status = kvStorePtr_->UnSubscribeKvStore(SubscribeType::DEFAULT, observer); + HILOGI("status %{public}d", status); + return static_cast(status); +} + +int32_t DeviceProfileStorage::RegisterSyncCallback(const std::shared_ptr& sycnCb) +{ + HILOGD("called"); + if (kvStorePtr_ == nullptr || sycnCb == nullptr) { + return ERR_DP_INVALID_PARAMS; + } + Status status = kvStorePtr_->RegisterSyncCallback(sycnCb); + HILOGI("status %{public}d", status); + return static_cast(status); +} + +int32_t DeviceProfileStorage::UnRegisterSyncCallback() +{ + HILOGD("called"); + if (kvStorePtr_ == nullptr) { + return ERR_DP_INVALID_PARAMS; + } + Status status = kvStorePtr_->UnRegisterSyncCallback(); + HILOGI("status %{public}d", status); + return static_cast(status); +} + +StorageInitStatus DeviceProfileStorage::GetInitStatus() +{ + return initStatus_; +} + +bool DeviceProfileStorage::TryGetKvStore() +{ + int32_t retryTimes = 0; + while (retryTimes < RETRY_TIMES_GET_KVSTORE) { + if (GetKvStore() == Status::SUCCESS && kvStorePtr_ != nullptr) { + return true; + } + HILOGD("retry get kvstore..."); + std::this_thread::sleep_for(500ms); + retryTimes++; + } + if (kvStorePtr_ == nullptr) { + initStatus_ = StorageInitStatus::INIT_FAILED; + return false; + } + return true; +} + +Status DeviceProfileStorage::GetKvStore() +{ + HILOGD("called"); + Status status = dataManager_.GetSingleKvStore(options_, appId_, storeId_, kvStorePtr_); + if (status != Status::SUCCESS) { + HILOGI("get failed, error = %{public}d", status); + } else { + HILOGI("get succeeded"); + } + return status; +} + +void DeviceProfileStorage::DeleteKvStore() +{ + Status status = dataManager_.DeleteKvStore(appId_, storeId_); + if (status != Status::SUCCESS) { + HILOGE("delete failed, error = %{public}d", status); + } +} + +int32_t DeviceProfileStorage::GetDeviceProfile(const std::string& key, std::string& value) +{ + std::shared_lock readLock(storageLock_); + if (kvStorePtr_ == nullptr) { + HILOGE("null kvstore"); + return ERR_DP_INVALID_PARAMS; + } + + Key k(key); + Value v; + Status status = kvStorePtr_->Get(k, v); + if (status != Status::SUCCESS) { + HILOGE("get failed, %{public}d", status); + return static_cast(status); + } + value = v.ToString(); + HILOGI("get succeeded"); + return static_cast(status); +} + +int32_t DeviceProfileStorage::PutDeviceProfile(const std::string& key, const std::string& value) +{ + std::unique_lock writeLock(storageLock_); + if (kvStorePtr_ == nullptr) { + HILOGE("null kvstore"); + return ERR_DP_INVALID_PARAMS; + } + + Key k(key); + Value v(value); + Status status = kvStorePtr_->Put(k, v); + if (status != Status::SUCCESS) { + HILOGE("put failed, error = %{public}d", status); + } + return static_cast(status); +} + +int32_t DeviceProfileStorage::PutDeviceProfileBatch(const std::vector& keys, + const std::vector& values) +{ + std::unique_lock writeLock(storageLock_); + if (kvStorePtr_ == nullptr) { + HILOGE("null kvstore"); + return ERR_DP_INVALID_PARAMS; + } + + const size_t keySize = keys.size(); + const size_t valSize = values.size(); + HILOGI("keySize = %{public}zu, valSize = %{public}zu", keySize, valSize); + if (keySize != valSize) { + HILOGE("diff key-value size"); + return ERR_DP_INVALID_PARAMS; + } + + std::vector entries; + entries.reserve(keySize); + for (uint32_t i = 0; i < keySize; i++) { + Entry entry; + entry.key = keys[i]; + entry.value = values[i]; + entries.emplace_back(entry); + } + + Status status = kvStorePtr_->PutBatch(entries); + if (status != Status::SUCCESS) { + HILOGE("put batch failed, error = %{public}d", status); + } + return static_cast(status); +} + +int32_t DeviceProfileStorage::DeleteDeviceProfile(const std::string& key) +{ + std::unique_lock writeLock(storageLock_); + if (kvStorePtr_ == nullptr) { + return ERR_DP_INVALID_PARAMS; + } + Key k(key); + Status status = kvStorePtr_->Delete(k); + if (status != Status::SUCCESS) { + HILOGE("delete failed, error = %{public}d", status); + } + return static_cast(status); +} + +int32_t DeviceProfileStorage::SyncDeviceProfile(const std::vector& deviceIdList, + DistributedKv::SyncMode syncMode) +{ + std::unique_lock writeLock(storageLock_); + if (kvStorePtr_ == nullptr) { + return ERR_DP_INVALID_PARAMS; + } + Status status = kvStorePtr_->Sync(deviceIdList, syncMode); + if (status != Status::SUCCESS) { + HILOGE("sync failed, error = %{public}d", status); + } + return static_cast(status); +} +} // namespace DeviceProfile +} // namespace OHOS diff --git a/services/core/src/dbstorage/device_profile_storage_manager.cpp b/services/core/src/dbstorage/device_profile_storage_manager.cpp new file mode 100755 index 0000000000000000000000000000000000000000..90f94ee2cd8cea8e1437322670bad63455fd60e4 --- /dev/null +++ b/services/core/src/dbstorage/device_profile_storage_manager.cpp @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "device_profile_storage_manager.h" + +#include +#include + +#include "device_manager.h" +#include "device_profile_errors.h" +#include "device_profile_log.h" +#include "device_profile_utils.h" + +#include "ipc_object_proxy.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "subscribe_info.h" +#include "subscribe_manager.h" +#include "system_ability_definition.h" + +namespace OHOS { +namespace DeviceProfile { +using namespace std::chrono_literals; +using namespace OHOS::DistributedKv; + +namespace { +const std::string TAG = "DeviceProfileStorageManager"; + +const std::string SERVICE_TYPE = "type"; +const std::string SERVICES = "services"; +constexpr int32_t RETRY_TIMES_WAIT_KV_DATA = 30; +} + +IMPLEMENT_SINGLE_INSTANCE(DeviceProfileStorageManager); + +bool DeviceProfileStorageManager::Init() +{ + if (!inited_) { + DeviceManager::GetInstance().GetLocalDeviceUdid(localUdid_); + if (localUdid_.empty()) { + HILOGE("get local udid failed"); + return false; + } + onlineSyncTbl_ = std::make_unique(); + if (onlineSyncTbl_ == nullptr) { + return false; + } + + kvStoreDeathRecipient_ = sptr(new KvStoreDeathRecipient()); + auto runner = AppExecFwk::EventRunner::Create("dpstorage"); + storageHandler_ = std::make_shared(runner); + if (storageHandler_ == nullptr) { + return false; + } + inited_ = true; + } + + auto waitTask = [this]() { + if (!WaitKvDataService()) { + std::lock_guard autoLock(serviceLock_); + profileItems_.clear(); + kvDataServiceFailed_ = true; + return; + } + auto callback = std::bind(&DeviceProfileStorageManager::OnKvStoreInitDone, this); + onlineSyncTbl_->RegisterKvStoreInitCallback(callback); + onlineSyncTbl_->Init(); + }; + if (!storageHandler_->PostTask(waitTask)) { + HILOGE("post task failed"); + return false; + } + HILOGI("init succeeded"); + return true; +} + +bool DeviceProfileStorageManager::WaitKvDataService() +{ + auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (samgrProxy == nullptr) { + HILOGE("get samgrProxy failed"); + return false; + } + int32_t retryTimes = RETRY_TIMES_WAIT_KV_DATA; + do { + auto kvDataSvr = samgrProxy->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + if (kvDataSvr != nullptr) { + IPCObjectProxy* proxy = reinterpret_cast(kvDataSvr.GetRefPtr()); + if (proxy != nullptr && !proxy->IsObjectDead()) { + HILOGI("get service succeed"); + proxy->AddDeathRecipient(kvStoreDeathRecipient_); + return true; + } + } + HILOGD("waiting for service..."); + std::this_thread::sleep_for(1s); + if (--retryTimes <= 0) { + HILOGE("waiting service timeout(30)s"); + return false; + } + } while (true); + return false; +} + +std::string DeviceProfileStorageManager::GenerateKey(const std::string& udid, + const std::string& key, KeyType keyType) +{ + std::string tmp; + tmp.append(udid).append("/").append(std::to_string(keyType)).append("/").append(key); + return tmp; +} + +int32_t DeviceProfileStorageManager::PutDeviceProfile(const ServiceCharacteristicProfile& profile) +{ + if (kvDataServiceFailed_ || onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_FAILED) { + HILOGE("kvstore init failed"); + return ERR_DP_INIT_DB_FAILED; + } + + std::vector keys; + std::vector values; + std::string serviceId = profile.GetServiceId(); + keys.emplace_back(GenerateKey(localUdid_, serviceId, KeyType::SERVICE)); + values.emplace_back(profile.GetCharacteristicProfileJson()); + std::unique_lock autoLock(serviceLock_); + if (servicesJson_[serviceId] == nullptr) { + nlohmann::json j; + j[SERVICE_TYPE] = profile.GetServiceType(); + servicesJson_[serviceId] = j; + keys.emplace_back(GenerateKey(localUdid_, SERVICES, KeyType::SERVICE_LIST)); + values.emplace_back(servicesJson_.dump()); + } + + int32_t errCode = ERR_OK; + if (onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_SUCCEED) { + autoLock.unlock(); + if (keys.size() > 1) { + errCode = onlineSyncTbl_->PutDeviceProfileBatch(keys, values); + } else { + errCode = onlineSyncTbl_->PutDeviceProfile(keys[0], values[0]); + } + } else { + for (size_t i = 0; i < keys.size(); i++) { + profileItems_[keys[i]] = values[i]; + } + } + return errCode; +} + +int32_t DeviceProfileStorageManager::GetDeviceProfile(const std::string& udid, + const std::string& serviceId, ServiceCharacteristicProfile& profile) +{ + if (onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_FAILED) { + HILOGE("kvstore init failed"); + return ERR_DP_INIT_DB_FAILED; + } + + std::string key; + std::string value; + int32_t result = ERR_OK; + if (udid.empty()) { + key = GenerateKey(localUdid_, serviceId, KeyType::SERVICE); + SetServiceType(udid, serviceId, profile); + } else { + std::string queryUdid; + if (!DeviceManager::GetInstance().TransformDeviceId(udid, queryUdid, + DeviceIdType::UDID)) { + HILOGE("transform to networkid failed"); + return ERR_DP_INVALID_PARAMS; + } + key = GenerateKey(queryUdid, serviceId, KeyType::SERVICE); + SetServiceType(queryUdid, serviceId, profile); + } + std::unique_lock autoLock(serviceLock_); + auto itItem = profileItems_.find(key); + if (itItem != profileItems_.end()) { + value = profileItems_[key]; + } else { + autoLock.unlock(); + result = onlineSyncTbl_->GetDeviceProfile(key, value); + } + profile.SetServiceId(serviceId); + profile.SetCharacteristicProfileJson(value); + return result; +} + +void DeviceProfileStorageManager::SetServiceType(const std::string& udid, + const std::string& serviceId, ServiceCharacteristicProfile& profile) +{ + std::unique_lock autoLock(serviceLock_); + if (udid.empty()) { + auto jsonData = servicesJson_[serviceId]; + if (jsonData != nullptr) { + profile.SetServiceType(jsonData[SERVICE_TYPE]); + } + return; + } + + std::string value; + std::string key = GenerateKey(udid, SERVICES, KeyType::SERVICE_LIST); + int32_t result = onlineSyncTbl_->GetDeviceProfile(key, value); + if (result != ERR_OK) { + HILOGE("get service type failed"); + return; + } + auto jsonData = nlohmann::json::parse(value, nullptr, false); + if (jsonData.is_discarded()) { + HILOGE("parse error"); + return; + } + auto typeData = jsonData[serviceId]; + if (typeData != nullptr && typeData[SERVICE_TYPE] != nullptr) { + profile.SetServiceType(typeData[SERVICE_TYPE]); + } +} + +int32_t DeviceProfileStorageManager::DeleteDeviceProfile(const std::string& serviceId) +{ + if (onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_FAILED) { + HILOGE("kvstore init failed"); + return ERR_DP_INIT_DB_FAILED; + } + + std::unique_lock autoLock(serviceLock_); + if (servicesJson_[serviceId] == nullptr) { + HILOGW("can't find service %{public}s", serviceId.c_str()); + return ERR_DP_INVALID_PARAMS; + } + nlohmann::json original = servicesJson_[serviceId]; + servicesJson_.erase(serviceId); + std::string servicesKey = GenerateKey(localUdid_, SERVICES, KeyType::SERVICE_LIST); + std::string servicesValue = servicesJson_.dump(); + int32_t errCode = ERR_OK; + std::string serviceKey = GenerateKey(localUdid_, serviceId, KeyType::SERVICE); + if (onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_SUCCEED) { + errCode = onlineSyncTbl_->DeleteDeviceProfile(serviceKey); + if (errCode != ERR_OK) { + servicesJson_[serviceId] = std::move(original); + return errCode; + } + errCode = onlineSyncTbl_->PutDeviceProfile(servicesKey, servicesValue); + if (errCode != ERR_OK) { + HILOGW("update services failed, errorCode = %{public}d", errCode); + } + } else { + profileItems_.erase(serviceKey); + profileItems_[servicesKey] = std::move(servicesValue); + } + return errCode; +} + +int32_t DeviceProfileStorageManager::SyncDeviceProfile(const SyncOptions& syncOptions, + const sptr& profileEventNotifier) +{ + if (onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_FAILED) { + HILOGE("kvstore init failed"); + return ERR_DP_INIT_DB_FAILED; + } + + if (!CheckSyncOption(syncOptions)) { + HILOGW("device list has offline device"); + return ERR_DP_INVALID_PARAMS; + } + + int32_t result = NotifySyncStart(profileEventNotifier); + if (result != ERR_OK) { + return result; + } + + auto syncTask = [syncOptions, this]() { + HILOGI("start sync"); + if (onlineSyncTbl_ == nullptr) { + HILOGI("param init error"); + NotifySyncCompleted(); + return; + } + auto devicesList = syncOptions.GetDeviceList(); + if (devicesList.empty()) { + DeviceManager::GetInstance().GetDeviceIdList(devicesList); + } + std::vector devicesVector(std::vector { devicesList.begin(), devicesList.end() }); + int32_t result = onlineSyncTbl_->SyncDeviceProfile(devicesVector, syncOptions.GetSyncMode()); + if (result != ERR_OK) { + HILOGE("sync failed result : %{public}d", result); + NotifySyncCompleted(); + return; + } + }; + if (!storageHandler_->PostTask(syncTask)) { + HILOGE("post task failed"); + NotifySyncCompleted(); + return ERR_DP_POST_TASK_FAILED; + } + return ERR_OK; +} + +int32_t DeviceProfileStorageManager::NotifySyncStart(const sptr& profileEventNotifier) +{ + { + std::lock_guard autoLock(profileSyncLock_); + if (isSync_) { + HILOGW("sync busy"); + return ERR_DP_DEVICE_SYNC_BUSY; + } + isSync_ = true; + syncEventNotifier_ = profileEventNotifier; + } + + SubscribeInfo subscribeInfo; + subscribeInfo.profileEvent = ProfileEvent::EVENT_SYNC_COMPLETED; + std::list subscribeInfos; + subscribeInfos.emplace_back(subscribeInfo); + std::list failedEvents; + if (SubscribeManager::GetInstance().SubscribeProfileEvents( + subscribeInfos, profileEventNotifier, failedEvents) != ERR_OK) { + HILOGE("subscribe sync event failed"); + std::lock_guard autoLock(profileSyncLock_); + isSync_ = false; + syncEventNotifier_ = nullptr; + return ERR_DP_SUBSCRIBE_FAILED; + } + return ERR_OK; +} + +void DeviceProfileStorageManager::NotifySyncCompleted() +{ + HILOGI("called"); + std::list profileEvents; + profileEvents.emplace_back(ProfileEvent::EVENT_SYNC_COMPLETED); + std::list failedEvents; + std::lock_guard autoLock(profileSyncLock_); + int32_t ret = SubscribeManager::GetInstance().UnsubscribeProfileEvents( + profileEvents, syncEventNotifier_, failedEvents); + if (ret != ERR_OK) { + HILOGW("unsubscribe sync event failed"); + } + + isSync_ = false; + syncEventNotifier_ = nullptr; +} + +void DeviceProfileStorageManager::NotifySubscriberDied(const sptr& profileEventNotifier) +{ + HILOGI("called"); + std::lock_guard autoLock(profileSyncLock_); + if (profileEventNotifier != syncEventNotifier_) { + return; + } + + isSync_ = false; + syncEventNotifier_ = nullptr; +} + +bool DeviceProfileStorageManager::CheckSyncOption(const SyncOptions& syncOptions) +{ + std::list> onlineDevices; + DeviceManager::GetInstance().GetDeviceList(onlineDevices); + std::list onlineDeviceIds; + for (const auto& onlineDevice : onlineDevices) { + onlineDeviceIds.emplace_back(onlineDevice->GetDeviceId()); + } + + // check whether deviceId is online + auto syncDeviceIds = syncOptions.GetDeviceList(); + for (const auto& syncDeviceId : syncDeviceIds) { + auto iter = find(onlineDeviceIds.begin(), onlineDeviceIds.end(), syncDeviceId); + if (iter == onlineDeviceIds.end()) { + HILOGE("deviceId: %{public}s is not online", DeviceProfileUtils::AnonymizeDeviceId(syncDeviceId).c_str()); + return false; + } + } + return true; +} + +void DeviceProfileStorageManager::RestoreServiceItemLocked(const std::string& value) +{ + auto restoreItems = nlohmann::json::parse(value, nullptr, false); + if (restoreItems.is_discarded()) { + HILOGE("parse error"); + return; + } + for (const auto& [key, value] : servicesJson_.items()) { + restoreItems[key] = value; + } + servicesJson_ = std::move(restoreItems); +} + +void DeviceProfileStorageManager::FlushProfileItems() +{ + std::string services; + std::string servicesKey = GenerateKey(localUdid_, SERVICES, KeyType::SERVICE_LIST); + int32_t errCode = onlineSyncTbl_->GetDeviceProfile(servicesKey, services); + std::unique_lock autoLock(serviceLock_); + if (errCode == ERR_OK) { + RestoreServiceItemLocked(services); + } + + std::vector keys; + std::vector values; + size_t itemSize = profileItems_.size(); + HILOGI("profile item size = %{public}zu", itemSize); + if (itemSize == 0) { + return; + } + keys.reserve(itemSize); + values.reserve(itemSize); + // update service list to avoid overwriting the value in db storage + profileItems_[servicesKey] = servicesJson_.dump(); + for (const auto& [key, value] : profileItems_) { + keys.emplace_back(key); + values.emplace_back(value); + HILOGD("key = %{public}s, value = %{public}s", key.c_str(), value.c_str()); + } + profileItems_.clear(); + autoLock.unlock(); + + errCode = onlineSyncTbl_->PutDeviceProfileBatch(keys, values); + if (errCode != ERR_OK) { + HILOGE("put failed, errCode = %{public}d", errCode); + } +} + +void DeviceProfileStorageManager::RegisterCallbacks() +{ + HILOGI("called"); + int32_t errCode = ERR_OK; + if (kvStoreObserver_ != nullptr) { + errCode = onlineSyncTbl_->SubscribeKvStore(kvStoreObserver_); + HILOGI("SubscribeKvStore errCode = %{public}d", errCode); + } + if (kvStoreSyncCallback_ != nullptr) { + errCode = onlineSyncTbl_->RegisterSyncCallback(kvStoreSyncCallback_); + HILOGI("RegisterSyncCallback errCode = %{public}d", errCode); + } +} + +void DeviceProfileStorageManager::OnKvStoreInitDone() +{ + RegisterCallbacks(); + FlushProfileItems(); +} + +int32_t DeviceProfileStorageManager::SubscribeKvStore(const std::shared_ptr& observer) +{ + std::lock_guard autoLock(callbackLock_); + kvStoreObserver_ = observer; + if (onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_SUCCEED) { + return onlineSyncTbl_->SubscribeKvStore(observer); + } + return ERR_OK; +} + +int32_t DeviceProfileStorageManager::UnSubscribeKvStore(const std::shared_ptr& observer) +{ + std::lock_guard autoLock(callbackLock_); + kvStoreObserver_ = nullptr; + return onlineSyncTbl_->UnSubscribeKvStore(observer); +} + +int32_t DeviceProfileStorageManager::RegisterSyncCallback(const std::shared_ptr& sycnCb) +{ + std::lock_guard autoLock(callbackLock_); + kvStoreSyncCallback_ = sycnCb; + if (onlineSyncTbl_->GetInitStatus() == StorageInitStatus::INIT_SUCCEED) { + return onlineSyncTbl_->RegisterSyncCallback(sycnCb); + } + return ERR_OK; +} + +int32_t DeviceProfileStorageManager::UnRegisterSyncCallback() +{ + std::lock_guard autoLock(callbackLock_); + kvStoreSyncCallback_ = nullptr; + return onlineSyncTbl_->UnRegisterSyncCallback(); +} + +void DeviceProfileStorageManager::OnNodeOnline(const std::shared_ptr deviceBasicInfo) +{ + HILOGI("called"); + std::vector onlineDevice = { deviceBasicInfo->GetDeviceId() }; + int32_t errCode = onlineSyncTbl_->SyncDeviceProfile(onlineDevice, SyncMode::PUSH); + if (errCode != ERR_OK) { + HILOGE("online sync errCode = %{public}d", errCode); + } +} +} // namespace DeviceProfile +} // namespace OHOS diff --git a/services/core/src/dbstorage/kvstore_death_recipient.cpp b/services/core/src/dbstorage/kvstore_death_recipient.cpp new file mode 100755 index 0000000000000000000000000000000000000000..f40f8a877b4462b9e8e39d67c9ea36526cb7f344 --- /dev/null +++ b/services/core/src/dbstorage/kvstore_death_recipient.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kvstore_death_recipient.h" + +#include "device_profile_log.h" +#include "device_profile_storage_manager.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "KvStoreDeathRecipient"; +} + +void KvStoreDeathRecipient::OnRemoteDied(const wptr& remote) +{ + HILOGI("called"); + DeviceProfileStorageManager::GetInstance().Init(); +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/src/dbstorage/online_sync_table.cpp b/services/core/src/dbstorage/online_sync_table.cpp new file mode 100755 index 0000000000000000000000000000000000000000..5a7bf456a5cb6af36277185d9ec3ff0d2d4725dc --- /dev/null +++ b/services/core/src/dbstorage/online_sync_table.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "online_sync_table.h" + +#include "device_profile_log.h" + +namespace OHOS { +namespace DeviceProfile { +using namespace OHOS::DistributedKv; + +namespace { +const std::string TAG = "OnlineSyncTable"; + +const std::string APP_ID = "distributed_device_profile_service"; +const std::string STORE_ID = "online_sync_storage"; +} + +OnlineSyncTable::OnlineSyncTable() : DeviceProfileStorage(APP_ID, STORE_ID) +{ +} + +void OnlineSyncTable::Init() +{ + HILOGD("called"); + Options options = { + .createIfMissing = true, + .encrypt = false, + .autoSync = false, + .kvStoreType = KvStoreType::SINGLE_VERSION, + }; + SetOptions(options); + DeviceProfileStorage::Init(); +} +} // namespace DeviceProfile +} // namespace OHOS diff --git a/services/core/src/devicemanager/device_basic_info.cpp b/services/core/src/devicemanager/device_basic_info.cpp new file mode 100755 index 0000000000000000000000000000000000000000..a369bf28cd116fe936bc13dd5d9e0a5889fa4bc3 --- /dev/null +++ b/services/core/src/devicemanager/device_basic_info.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "device_basic_info.h" + +namespace OHOS { +namespace DeviceProfile { +const std::string& DeviceBasicInfo::GetDeviceName() const +{ + return deviceName_; +} + +const std::string& DeviceBasicInfo::GetDeviceId() const +{ + return deviceId_; +} + +int32_t DeviceBasicInfo::GetDeviceType() const +{ + return deviceType_; +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/src/devicemanager/device_manager.cpp b/services/core/src/devicemanager/device_manager.cpp new file mode 100755 index 0000000000000000000000000000000000000000..5817be2ebfac33d1fc38e4f84bbdfcdeefd00dbf --- /dev/null +++ b/services/core/src/devicemanager/device_manager.cpp @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "device_manager.h" + +#include +#include + +#include + +#include "parameter.h" + +#include "device_profile_log.h" +#include "device_profile_storage_manager.h" +#include "device_profile_utils.h" + +namespace OHOS { +namespace DeviceProfile { +using namespace std::chrono_literals; + +namespace { +const std::string TAG = "DeviceManager"; + +constexpr uint8_t MAX_DEVICE_TYPE = 3; +constexpr int32_t DEVICE_ID_SIZE = 65; +constexpr int32_t MAX_TIMES_CONNECT_SOFTBUS = 10; +const std::string PKG_NAME = "DBinderBus_" + std::to_string(getpid()); +} + +IMPLEMENT_SINGLE_INSTANCE(DeviceManager); + +bool DeviceManager::Init() +{ + nodeStateCb_.events = EVENT_NODE_STATE_MASK; + nodeStateCb_.onNodeOnline = OnNodeOnlineAdapter; + nodeStateCb_.onNodeOffline = OnNodeOfflineAdapter; + nodeStateCb_.onNodeBasicInfoChanged = OnNodeBasicInfoChangedAdapter; + + auto runner = AppExecFwk::EventRunner::Create("devmgr"); + devMgrHandler_ = std::make_shared(runner); + if (devMgrHandler_ == nullptr) { + return false; + } + if (!ConnectSoftbus()) { + return false; + } + return true; +} + +void DeviceManager::OnNodeOnlineAdapter(NodeBasicInfo* info) +{ + if (info == nullptr) { + HILOGE("null info"); + return; + } + HILOGI("networkId = %{public}s", DeviceProfileUtils::AnonymizeDeviceId(info->networkId).c_str()); + auto deviceBasicInfo = std::make_shared( + info->deviceName, info->networkId, info->deviceTypeId); + DeviceManager::GetInstance().OnNodeOnline(deviceBasicInfo); +} + +void DeviceManager::OnNodeOfflineAdapter(NodeBasicInfo* info) +{ + if (info == nullptr) { + HILOGE("null info"); + return; + } + + std::string deviceId = info->networkId; + DeviceManager::GetInstance().OnNodeOffline(deviceId); +} + +void DeviceManager::OnNodeBasicInfoChangedAdapter(NodeBasicInfoType type, + NodeBasicInfo* info) +{ + std::string deviceId = info->networkId; + DeviceManager::GetInstance().OnNodeBasicInfoChanged(deviceId, type); +} + +void DeviceManager::OnNodeOnline(const std::shared_ptr deviceBasicInfo) +{ + auto onlineNotifyTask = [this, deviceBasicInfo = deviceBasicInfo]() { + HILOGI("online networkId = %{public}s", + DeviceProfileUtils::AnonymizeDeviceId(deviceBasicInfo->GetDeviceId()).c_str()); + DeviceProfileStorageManager::GetInstance().OnNodeOnline(deviceBasicInfo); + AddDeviceIds(deviceBasicInfo->GetDeviceId()); + std::string deviceId = deviceBasicInfo->GetDeviceId(); + std::lock_guard autoLock(deviceLock_); + remoteDeviceInfoMap_[deviceId] = deviceBasicInfo; + }; + if (!devMgrHandler_->PostTask(onlineNotifyTask)) { + HILOGE("post task failed"); + return; + } +} + +void DeviceManager::OnNodeOffline(const std::string& deviceId) +{ + auto offlineNotifyTask = [this, deviceId = std::move(deviceId)]() { + HILOGI("offline networkId = %{public}s", + DeviceProfileUtils::AnonymizeDeviceId(deviceId).c_str()); + RemoveDeviceIds(deviceId); + std::lock_guard autoLock(deviceLock_); + remoteDeviceInfoMap_.erase(deviceId); + }; + if (!devMgrHandler_->PostTask(offlineNotifyTask)) { + HILOGE("post task failed"); + return; + } +} + +void DeviceManager::OnNodeBasicInfoChanged(const std::string& deviceId, + NodeBasicInfoType type) +{ + HILOGD("called"); +} + +bool DeviceManager::ConnectSoftbus() +{ + auto registerTask = [this]() { + HILOGD("register task..."); + int32_t retryTimes = 0; + int32_t errCode = ERR_OK; + while (retryTimes++ < MAX_TIMES_CONNECT_SOFTBUS) { + errCode = RegNodeDeviceStateCb(PKG_NAME.c_str(), &nodeStateCb_); + if (errCode == ERR_OK) { + break; + } + HILOGE("register errCode = %{public}d, retrying...", errCode); + + errCode = UnregNodeDeviceStateCb(&nodeStateCb_); + HILOGI("unregister errCode = %{public}d", errCode); + std::this_thread::sleep_for(1s); + } + + if (errCode == ERR_OK) { + AddLocalDeviceIds(); + RecoverDevicesIfNeeded(); + } + HILOGI("register %{public}s", (errCode == ERR_OK) ? "success" : "timeout"); + }; + if (!devMgrHandler_->PostTask(registerTask)) { + HILOGE("post task failed"); + return false; + } + return true; +} + +void DeviceManager::RecoverDevicesIfNeeded() +{ + HILOGI("called"); + NodeBasicInfo* info = nullptr; + int32_t numInfos = 0; + if (GetAllNodeDeviceInfo(PKG_NAME.c_str(), &info, &numInfos) != ERR_OK) { + FreeNodeInfo(info); + HILOGE("get all node info failed"); + return; + } + for (int32_t i = 0; i < numInfos; i++) { + NodeBasicInfo* nodeBasicInfo = info + i; + std::string networkId = nodeBasicInfo->networkId; + HILOGI("deviceId %{public}s found", + DeviceProfileUtils::AnonymizeDeviceId(networkId).c_str()); + AddDeviceIds(networkId); + { + auto deviceBasicInfo = std::make_shared( + nodeBasicInfo->deviceName, networkId, nodeBasicInfo->deviceTypeId); + std::lock_guard autoLock(deviceLock_); + remoteDeviceInfoMap_.emplace(std::move(networkId), deviceBasicInfo); + } + } + FreeNodeInfo(info); +} + +void DeviceManager::AddLocalDeviceIds() +{ + HILOGI("called"); + auto info = GetLocalBasicInfo(); + if (info != nullptr) { + AddDeviceIds(info->networkId); + } else { + std::string udid; + GetLocalDeviceUdid(udid); + std::vector deviceIds = {"", std::move(udid), ""}; + std::lock_guard autoLock(deviceLock_); + deviceIdsList_.emplace_back(std::move(deviceIds)); + } +} + +void DeviceManager::AddDeviceIds(const std::string& networkId) +{ + HILOGI("called"); + std::string udid; + if (GetUdidByNetworkId(networkId, udid)) { + HILOGI("udid %{public}s", DeviceProfileUtils::AnonymizeDeviceId(udid).c_str()); + } + std::string uuid; + if (GetUuidByNetworkId(networkId, uuid)) { + HILOGI("uuid %{public}s", DeviceProfileUtils::AnonymizeDeviceId(uuid).c_str()); + } + std::vector deviceIds = {networkId, std::move(udid), std::move(uuid)}; + std::lock_guard autoLock(deviceLock_); + deviceIdsList_.emplace_back(std::move(deviceIds)); +} + +void DeviceManager::RemoveDeviceIds(const std::string& networkId) +{ + HILOGI("called"); + std::lock_guard autoLock(deviceLock_); + for (auto iter = deviceIdsList_.begin(); iter != deviceIdsList_.end(); iter++) { + if ((*iter)[static_cast(DeviceIdType::NETWORKID)] == networkId) { + deviceIdsList_.erase(iter); + return; + } + } +} + +void DeviceManager::DisconnectSoftbus() +{ + int32_t errCode = UnregNodeDeviceStateCb(&nodeStateCb_); + if (errCode != ERR_OK) { + HILOGE("remove failed, errCode = %{public}d", errCode); + } +} + +void DeviceManager::GetLocalDeviceUdid(std::string& udid) +{ + char localDeviceId[DEVICE_ID_SIZE] = {0}; + GetDevUdid(localDeviceId, DEVICE_ID_SIZE); + udid = localDeviceId; +} + +std::unique_ptr DeviceManager::GetLocalBasicInfo() +{ + auto info = std::make_unique(); + int32_t errCode = GetLocalNodeDeviceInfo(PKG_NAME.c_str(), info.get()); + if (errCode != ERR_OK) { + HILOGE("errCode = %{public}d", errCode); + return nullptr; + } + return info; +} + +bool DeviceManager::GetUdidByNetworkId(const std::string& networkId, std::string& udid) +{ + return GetUuidOrUdidByNetworkId(networkId, NodeDeivceInfoKey::NODE_KEY_UDID, udid); +} + +bool DeviceManager::GetUuidByNetworkId(const std::string& networkId, std::string& uuid) +{ + return GetUuidOrUdidByNetworkId(networkId, NodeDeivceInfoKey::NODE_KEY_UUID, uuid); +} + +bool DeviceManager::GetUuidOrUdidByNetworkId(const std::string& networkId, + NodeDeivceInfoKey keyType, std::string& uuidOrUdid) +{ + if (networkId.empty()) { + return false; + } + + char id[DEVICE_ID_SIZE] = {0}; + int32_t errCode = GetNodeKeyInfo(PKG_NAME.c_str(), networkId.c_str(), keyType, + reinterpret_cast(id), DEVICE_ID_SIZE); + if (errCode != ERR_OK) { + HILOGE("get udid failed, errCode = %{public}d", errCode); + return false; + } + uuidOrUdid = id; + return true; +} + +bool DeviceManager::TransformDeviceId(const std::string& fromDeviceId, + std::string& toDeviceId, DeviceIdType toType) +{ + if (fromDeviceId.empty()) { + HILOGW("empty device id"); + return false; + } + + uint8_t idx = static_cast(toType); + if (idx > MAX_DEVICE_TYPE - 1) { + return false; + } + + toDeviceId = ""; + std::lock_guard autoLock(deviceLock_); + for (const auto& deviceIds : deviceIdsList_) { + auto iter = std::find(deviceIds.begin(), deviceIds.end(), fromDeviceId); + if (iter != deviceIds.end()) { + toDeviceId = deviceIds[idx]; + return !toDeviceId.empty(); + } + } + return false; +} + +void DeviceManager::GetDeviceIdList(std::list& deviceIdList) +{ + deviceIdList.clear(); + std::lock_guard autoLock(deviceLock_); + for (const auto& [_, deviceInfo] : remoteDeviceInfoMap_) { + deviceIdList.emplace_back(deviceInfo->GetDeviceId()); + } +} + +void DeviceManager::GetDeviceList(std::list>& deviceList) +{ + deviceList.clear(); + std::lock_guard autoLock(deviceLock_); + for (const auto& [_, deviceInfo] : remoteDeviceInfoMap_) { + deviceList.emplace_back(deviceInfo); + } +} +} // namespace DeviceProfile +} // namespace OHOS diff --git a/services/core/src/distributed_device_profile_service.cpp b/services/core/src/distributed_device_profile_service.cpp new file mode 100755 index 0000000000000000000000000000000000000000..066b32ebb5c31d31e88bdee0806b3fbda5fc74ce --- /dev/null +++ b/services/core/src/distributed_device_profile_service.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "distributed_device_profile_service.h" + +#include "content_sensor_manager.h" +#include "device_manager.h" +#include "device_profile_log.h" +#include "device_profile_storage_manager.h" +#include "service_characteristic_profile.h" +#include "subscribe_manager.h" + +#include "system_ability_definition.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "DistributedDeviceProfileService"; +} + +IMPLEMENT_SINGLE_INSTANCE(DistributedDeviceProfileService); +const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(&DistributedDeviceProfileService::GetInstance()); + +DistributedDeviceProfileService::DistributedDeviceProfileService() + : SystemAbility(DISTRIBUTED_DEVICE_PROFILE_SA_ID, true) +{ +} + +bool DistributedDeviceProfileService::Init() +{ + if (!DeviceManager::GetInstance().Init()) { + HILOGE("DeviceManager init failed"); + return false; + } + if (!DeviceProfileStorageManager::GetInstance().Init()) { + HILOGE("DeviceProfileStorageManager init failed"); + return false; + } + if (!ContentSensorManager::GetInstance().Init()) { + HILOGE("ContentSensorManager init failed"); + return false; + } + if (!SubscribeManager::GetInstance().Init()) { + HILOGE("SubscribeManager init failed"); + return false; + } + HILOGI("init succeeded"); + return true; +} + +int32_t DistributedDeviceProfileService::PutDeviceProfile(const ServiceCharacteristicProfile& profile) +{ + return DeviceProfileStorageManager::GetInstance().PutDeviceProfile(profile); +} + +int32_t DistributedDeviceProfileService::GetDeviceProfile(const std::string& udid, const std::string& serviceId, + ServiceCharacteristicProfile& profile) +{ + return DeviceProfileStorageManager::GetInstance().GetDeviceProfile(udid, serviceId, profile); +} + +int32_t DistributedDeviceProfileService::DeleteDeviceProfile(const std::string& serviceId) +{ + HILOGI("service id %{public}s", serviceId.c_str()); + return DeviceProfileStorageManager::GetInstance().DeleteDeviceProfile(serviceId); +} + +int32_t DistributedDeviceProfileService::SubscribeProfileEvents(const std::list& subscribeInfos, + const sptr& profileEventNotifier, + std::list& failedEvents) +{ + return SubscribeManager::GetInstance().SubscribeProfileEvents(subscribeInfos, + profileEventNotifier, failedEvents); +} + +int32_t DistributedDeviceProfileService::UnsubscribeProfileEvents(const std::list& profileEvents, + const sptr& profileEventNotifier, + std::list& failedEvents) +{ + return SubscribeManager::GetInstance().UnsubscribeProfileEvents(profileEvents, + profileEventNotifier, failedEvents); +} + +int32_t DistributedDeviceProfileService::SyncDeviceProfile(const SyncOptions& syncOptions, + const sptr& profileEventNotifier) +{ + return DeviceProfileStorageManager::GetInstance().SyncDeviceProfile(syncOptions, profileEventNotifier); +} + +void DistributedDeviceProfileService::OnStart() +{ + HILOGI("called"); + if (!Init()) { + HILOGE("init failed"); + return; + } + if (!Publish(this)) { + HILOGE("publish SA failed"); + return; + } +} + +void DistributedDeviceProfileService::OnStop() +{ + HILOGI("called"); +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/src/distributed_device_profile_stub.cpp b/services/core/src/distributed_device_profile_stub.cpp new file mode 100755 index 0000000000000000000000000000000000000000..86c8f638c21d383da787638b4026fce551ef4f4d --- /dev/null +++ b/services/core/src/distributed_device_profile_stub.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "distributed_device_profile_stub.h" + +#include + +#include "device_profile_errors.h" +#include "device_profile_log.h" +#include "device_profile_storage.h" +#include "device_profile_utils.h" +#include "iprofile_event_notifier.h" +#include "parcel_helper.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "DistributedDeviceProfileStub"; +} + +DistributedDeviceProfileStub::DistributedDeviceProfileStub() +{ + funcsMap_[PUT_DEVICE_PROFILE] = &DistributedDeviceProfileStub::PutDeviceProfileInner; + funcsMap_[DELETE_DEVICE_PROFILE] = &DistributedDeviceProfileStub::DeleteDeviceProfileInner; + funcsMap_[GET_DEVICE_PROFILE] = &DistributedDeviceProfileStub::GetDeviceProfileInner; + funcsMap_[SUBSCRIBE_PROFILE_EVENT] = &DistributedDeviceProfileStub::SubscribeProfileEventInner; + funcsMap_[UNSUBSCRIBE_PROFILE_EVENT] = &DistributedDeviceProfileStub::UnsubscribeProfileEventInner; + funcsMap_[SYNC_DEVICE_PROFILE] = &DistributedDeviceProfileStub::SyncDeviceProfileInner; +} + +bool DistributedDeviceProfileStub::EnforceInterfaceToken(MessageParcel& data) +{ + return data.ReadInterfaceToken() == IDistributedDeviceProfile::GetDescriptor(); +} + +int32_t DistributedDeviceProfileStub::OnRemoteRequest(uint32_t code, MessageParcel& data, + MessageParcel& reply, MessageOption& option) +{ + HILOGI("code = %{public}d, flags = %{public}d", code, option.GetFlags()); + + auto iter = funcsMap_.find(code); + if (iter != funcsMap_.end()) { + auto func = iter->second; + if (!EnforceInterfaceToken(data)) { + HILOGW("check interface token failed"); + return ERR_DP_INTERFACE_CHECK_FAILED; + } + if (func != nullptr) { + return (this->*func)(data, reply); + } + } + HILOGW("unknown request code, please check"); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +int32_t DistributedDeviceProfileStub::PutDeviceProfileInner(MessageParcel& data, MessageParcel& reply) +{ + HILOGI("called"); + ServiceCharacteristicProfile profile; + if (!profile.Unmarshalling(data)) { + return ERR_NULL_OBJECT; + } + return PutDeviceProfile(profile); +} + +int32_t DistributedDeviceProfileStub::GetDeviceProfileInner(MessageParcel& data, MessageParcel& reply) +{ + HILOGI("called"); + std::string udid; + std::string serviceId; + ServiceCharacteristicProfile profile; + PARCEL_READ_HELPER(data, String, udid); + PARCEL_READ_HELPER(data, String, serviceId); + int32_t ret = GetDeviceProfile(udid, serviceId, profile); + if (!profile.Marshalling(reply)) { + HILOGE("marshall profile failed"); + return ERR_FLATTEN_OBJECT; + } + return ret; +} + +int32_t DistributedDeviceProfileStub::DeleteDeviceProfileInner(MessageParcel& data, MessageParcel& reply) +{ + HILOGI("called"); + return DeleteDeviceProfile(data.ReadString()); +} + +int32_t DistributedDeviceProfileStub::SubscribeProfileEventInner(MessageParcel& data, MessageParcel& reply) +{ + HILOGI("called"); + uint32_t numSubscribeInfos = data.ReadUint32(); + if (numSubscribeInfos == 0) { + return ERR_DP_INVALID_PARAMS; + } + + std::list subscribeInfos; + for (uint32_t i = 0; i < numSubscribeInfos; i++) { + SubscribeInfo subscribeInfo; + if (!subscribeInfo.Unmarshalling(data)) { + return ERR_NULL_OBJECT; + } + HILOGD("profile event = %{public}d", subscribeInfo.profileEvent); + subscribeInfos.emplace_back(std::move(subscribeInfo)); + } + sptr eventNotifier = data.ReadRemoteObject(); + std::list failedEvents; + + int32_t errCode = SubscribeProfileEvents(subscribeInfos, eventNotifier, failedEvents); + HILOGI("errCode = %{public}d", errCode); + if (errCode != ERR_OK) { + if (!DeviceProfileUtils::WriteProfileEvents(failedEvents, reply)) { + HILOGW("write profile events failed"); + } + } + return errCode; +} + +int32_t DistributedDeviceProfileStub::UnsubscribeProfileEventInner(MessageParcel& data, MessageParcel& reply) +{ + HILOGI("called"); + uint32_t numEvents = data.ReadUint32(); + if (numEvents == 0) { + return ERR_DP_INVALID_PARAMS; + } + + std::list profileEvents; + for (uint32_t i = 0; i < numEvents; i++) { + ProfileEvent profileEvent = static_cast(data.ReadUint32()); + if (profileEvent >= EVENT_PROFILE_END || profileEvent == EVENT_UNKNOWN) { + return ERR_DP_INVALID_PARAMS; + } + profileEvents.emplace_back(profileEvent); + } + sptr eventNotifier = data.ReadRemoteObject(); + std::list failedEvents; + + int32_t errCode = UnsubscribeProfileEvents(profileEvents, eventNotifier, failedEvents); + HILOGI("errCode = %{public}d", errCode); + if (errCode != ERR_OK) { + if (!DeviceProfileUtils::WriteProfileEvents(failedEvents, reply)) { + HILOGW("write profile events failed"); + } + } + return errCode; +} + +int32_t DistributedDeviceProfileStub::SyncDeviceProfileInner(MessageParcel& data, MessageParcel& reply) +{ + SyncOptions syncOption; + if (!syncOption.Unmarshalling(data)) { + HILOGD("unmarshalling failed"); + return ERR_NULL_OBJECT; + } + + sptr eventNotifier = data.ReadRemoteObject(); + return SyncDeviceProfile(syncOption, eventNotifier); +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/src/profile_change_notification.cpp b/services/core/src/profile_change_notification.cpp new file mode 100755 index 0000000000000000000000000000000000000000..0f1989ff21db489eaaa1d39ebff8ac690e7d3329 --- /dev/null +++ b/services/core/src/profile_change_notification.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "profile_change_notification.h" + +#include "parcel_helper.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "ProfileChangeNotification"; +} + +const std::vector& ProfileChangeNotification::GetProfileEntries() const +{ + return profileEntries_; +} + +const std::string& ProfileChangeNotification::GetDeviceId() const +{ + return deviceId_; +} + +bool ProfileChangeNotification::IsLocal() const +{ + return isLocal_; +} + +bool ProfileChangeNotification::Marshalling(Parcel& parcel) const +{ + int32_t entrySize = static_cast(profileEntries_.size()); + PARCEL_WRITE_HELPER_RET(parcel, Int32, entrySize, false); + for (const auto& profileEntry : profileEntries_) { + if (!profileEntry.Marshalling(parcel)) { + return false; + } + } + PARCEL_WRITE_HELPER_RET(parcel, String, deviceId_, false); + + return true; +} + +bool ProfileChangeNotification::Unmarshalling(Parcel& parcel) +{ + int32_t entrySize = parcel.ReadInt32(); + if (entrySize < 0) { + HILOGE("invalid entrySize = %{public}d", entrySize); + return false; + } + profileEntries_.reserve(entrySize); + for (int32_t i = 0; i < entrySize; i++) { + ProfileEntry profileEntry; + if (!profileEntry.Unmarshalling(parcel)) { + return false; + } + profileEntries_.emplace_back(std::move(profileEntry)); + } + PARCEL_READ_HELPER_RET(parcel, String, deviceId_, false); + return true; +} + +bool ProfileEntry::Marshalling(Parcel& parcel) const +{ + PARCEL_WRITE_HELPER_RET(parcel, String, key, false); + PARCEL_WRITE_HELPER_RET(parcel, String, value, false); + PARCEL_WRITE_HELPER_RET(parcel, Uint8, changeType, false); + return true; +} + +bool ProfileEntry::Unmarshalling(Parcel& parcel) +{ + PARCEL_READ_HELPER_RET(parcel, String, key, false); + PARCEL_READ_HELPER_RET(parcel, String, value, false); + uint8_t type = 0; + PARCEL_READ_HELPER_RET(parcel, Uint8, type, false); + changeType = static_cast(type); + return true; +} +} // namespace DeviceProfile +} // namespace OHOS diff --git a/services/core/src/service_characteristic_profile.cpp b/services/core/src/service_characteristic_profile.cpp new file mode 100755 index 0000000000000000000000000000000000000000..10f784399789d8acf4b7b7503e3f43c244f3e31b --- /dev/null +++ b/services/core/src/service_characteristic_profile.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "service_characteristic_profile.h" + +#include "device_profile_log.h" +#include "parcel_helper.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "ServiceCharacteristicProfile"; +} + +void ServiceCharacteristicProfile::SetServiceId(const std::string& serviceId) +{ + serviceId_ = serviceId; +} + +void ServiceCharacteristicProfile::SetServiceType(const std::string& serviceType) +{ + serviceType_ = serviceType; +} + +void ServiceCharacteristicProfile::SetServiceProfileJson(const std::string& profileJson) +{ + serviceProfileJson_ = profileJson; +} + +void ServiceCharacteristicProfile::SetCharacteristicProfileJson(const std::string& profileJson) +{ + characteristicProfileJson_ = profileJson; +} + +const std::string& ServiceCharacteristicProfile::GetServiceId() const +{ + return serviceId_; +} + +const std::string& ServiceCharacteristicProfile::GetServiceType() const +{ + return serviceType_; +} + +const std::string& ServiceCharacteristicProfile::GetServiceProfileJson() const +{ + return serviceProfileJson_; +} + +const std::string& ServiceCharacteristicProfile::GetCharacteristicProfileJson() const +{ + return characteristicProfileJson_; +} + +bool ServiceCharacteristicProfile::Marshalling(Parcel& parcel) const +{ + PARCEL_WRITE_HELPER_RET(parcel, String, serviceId_, false); + PARCEL_WRITE_HELPER_RET(parcel, String, serviceType_, false); + PARCEL_WRITE_HELPER_RET(parcel, String, characteristicProfileJson_, false); + PARCEL_WRITE_HELPER_RET(parcel, String, serviceProfileJson_, false); + return true; +} + +bool ServiceCharacteristicProfile::Unmarshalling(Parcel& parcel) +{ + PARCEL_READ_HELPER_RET(parcel, String, serviceId_, false); + PARCEL_READ_HELPER_RET(parcel, String, serviceType_, false); + PARCEL_READ_HELPER_RET(parcel, String, characteristicProfileJson_, false); + PARCEL_READ_HELPER_RET(parcel, String, serviceProfileJson_, false); + return true; +} +} // namespace DeviceProfile +} // namespace OHOS diff --git a/services/core/src/subscribemanager/profile_change_handler.cpp b/services/core/src/subscribemanager/profile_change_handler.cpp new file mode 100755 index 0000000000000000000000000000000000000000..f001f09d51e91af1aca6a40116e543227e489bdd --- /dev/null +++ b/services/core/src/subscribemanager/profile_change_handler.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "profile_change_handler.h" + +#include + +#include "datetime_ex.h" +#include "string_ex.h" + +#include "device_profile_log.h" +#include "device_profile_storage_manager.h" +#include "device_profile_utils.h" +#include "profile_change_notification.h" + +namespace OHOS { +namespace DeviceProfile { +using namespace OHOS::DistributedKv; + +namespace { +const std::string TAG = "ProfileChangeHandler"; + +constexpr int32_t NUM_KEY_FILEDS = 3; +constexpr int32_t DEVICE_ID_SIZE = 64; +} + +struct ProfileKey { + std::string udid; + std::string serviceId; + KeyType type {KeyType::UNKNOWN}; + + static std::unique_ptr Parse(const std::string& entryKey); +}; + +std::unique_ptr ProfileKey::Parse(const std::string& entryKey) +{ + std::vector vec; + SplitStr(entryKey, "/", vec); + if (vec.size() != NUM_KEY_FILEDS) { + HILOGE("parse key failed"); + return nullptr; + } + + int32_t index = 0; + auto profileKey = std::make_unique(); + profileKey->udid = std::move(vec[index++]); + if (profileKey->udid.size() != DEVICE_ID_SIZE) { + HILOGE("parse udid failed"); + return nullptr; + } + int32_t type = 0; + if (!StrToInt(vec[index++], type)) { + HILOGE("parse type failed"); + return nullptr; + } + profileKey->type = static_cast(type); + profileKey->serviceId = std::move(vec[index]); + return profileKey; +} + +void ProfileChangeHandler::OnChange(const ChangeNotification& changeNotification) +{ + std::vector profileEntries; + const auto& insertedEntries = changeNotification.GetInsertEntries(); + const auto& updatedEntries = changeNotification.GetUpdateEntries(); + const auto& deletedEntries = changeNotification.GetDeleteEntries(); + int32_t numEntries = insertedEntries.size() + updatedEntries.size() + deletedEntries.size(); + profileEntries.reserve(numEntries); + HILOGI("numEntries = %{public}d", numEntries); + + int64_t begin = GetTickCount(); + Service2Index service2Index; + Entry entry; + if (!insertedEntries.empty()) { + entry = insertedEntries.front(); + ConvertEntry(insertedEntries, ProfileChangeType::INSERTED, profileEntries, service2Index); + } + if (!updatedEntries.empty()) { + entry = updatedEntries.front(); + ConvertEntry(updatedEntries, ProfileChangeType::UPDATED, profileEntries, service2Index); + } + if (!deletedEntries.empty()) { + entry = deletedEntries.front(); + ConvertEntry(deletedEntries, ProfileChangeType::DELETED, profileEntries, service2Index); + } + HILOGI("convert entry elapsedTime is %{public}" PRId64 " ms", GetTickCount() - begin); + + std::string udid; + auto profileKey = ProfileKey::Parse(entry.key.ToString()); + if (profileKey == nullptr) { + HILOGE("bad profile entry"); + return; + } + udid = std::move(profileKey->udid); + HILOGI("udid = %{public}s", DeviceProfileUtils::AnonymizeDeviceId(udid).c_str()); + std::string localUdid; + // won't fail + DeviceManager::GetInstance().GetLocalDeviceUdid(localUdid); + + std::string networkId; + if (!DeviceManager::GetInstance().TransformDeviceId(udid, networkId, + DeviceIdType::NETWORKID)) { + HILOGE("transform to networkid failed"); + } + + ProfileChangeNotification notification(profileEntries, networkId, localUdid == udid); + auto notifyTask = [this, notification = std::move(notification), + service2Index = std::move(service2Index)]() { + NotifyProfileChanged(notification, service2Index); + }; + std::lock_guard autoLock(notifierLock_); + if (eventHandler_ != nullptr && !eventHandler_->PostTask(notifyTask)) { + HILOGI("post task failed"); + } +} + +void ProfileChangeHandler::ConvertEntry(const std::vector& entries, + ProfileChangeType changeType, std::vector& profileEntries, + Service2Index& service2Index) +{ + for (const auto& entry : entries) { + auto profileKey = ProfileKey::Parse(entry.key.ToString()); + if (profileKey != nullptr && profileKey->type == KeyType::SERVICE) { + std::string trimmedKey = std::move(profileKey->serviceId); + HILOGI("key = %{public}s, state = %{public}d", trimmedKey.c_str(), changeType); + service2Index.emplace(trimmedKey, profileEntries.size()); + profileEntries.emplace_back(std::move(trimmedKey), entry.value.ToString(), changeType); + continue; + } + HILOGD("key = %{public}s, value = %{public}s, state = %{public}d", profileKey->serviceId.c_str(), + entry.value.ToString().c_str(), changeType); + } +} + +void ProfileChangeHandler::NotifyProfileChanged(const ProfileChangeNotification& changeNotification, + const Service2Index& service2Index) +{ + HILOGD("called"); + std::lock_guard autoLock(notifierLock_); + HILOGI("subscribers size = %{public}zu", profileEventSubscribeInfos_.size()); + for (const auto& [notifier, subscribeInfo] : profileEventSubscribeInfos_) { + sptr profileEventNotifier = iface_cast(notifier); + if (profileEventNotifier == nullptr) { + HILOGE("cast to IProfileEventNotifier failed"); + continue; + } + + FilterInfo filterInfo; + FilterChangedProfileLocked(subscribeInfo, changeNotification, service2Index, filterInfo); + int64_t begin = GetTickCount(); + NotifyProfileChangedLocked(changeNotification, filterInfo, profileEventNotifier); + HILOGI("notify elapsedTime is %{public}" PRId64 " ms", GetTickCount() - begin); + } +} + +void ProfileChangeHandler::NotifyProfileChangedLocked(const ProfileChangeNotification& changeNotification, + const FilterInfo& filterInfo, const sptr& profileEventNotifier) +{ + if (!filterInfo.filtered) { + HILOGD("not filtered"); + profileEventNotifier->OnProfileChanged(changeNotification); + return; + } + + const auto& indexes = filterInfo.indexes; + // filtered but not found satisfied service + size_t size = indexes.size(); + if (size == 0) { + return; + } + + std::vector filteredEntries; + filteredEntries.reserve(size); + const auto& profileEntries = changeNotification.GetProfileEntries(); + for (auto index : indexes) { + filteredEntries.emplace_back(profileEntries[index]); + } + HILOGI("filtered with %{public}zu entrie(s)", size); + bool isLocal = changeNotification.IsLocal(); + std::string deviceId = changeNotification.GetDeviceId(); + ProfileChangeNotification filteredNotification(filteredEntries, deviceId, isLocal); + profileEventNotifier->OnProfileChanged(filteredNotification); +} + +void ProfileChangeHandler::FilterChangedProfileLocked(const SubscribeInfo& subscribeInfo, + const ProfileChangeNotification& changeNotification, + const Service2Index& service2Index, FilterInfo& filterInfo) +{ + const auto& extraInfo = subscribeInfo.extraInfo; + + // currently only support specific deviceId + std::string deviceId = extraInfo["deviceId"]; + if (!deviceId.empty()) { + filterInfo.filtered = true; + std::string networkId; + if (!DeviceManager::GetInstance().TransformDeviceId(deviceId, networkId, + DeviceIdType::NETWORKID)) { + HILOGE("transform to networkid failed"); + return; + } + if (networkId != changeNotification.GetDeviceId()) { + return; + } + } + + const auto& serviceIdsJson = extraInfo["serviceIds"]; + auto& indexes = filterInfo.indexes; + if (serviceIdsJson.empty()) { + return; + } + filterInfo.filtered = true; + for (const auto& serviceIdJson : serviceIdsJson) { + std::string serviceId = serviceIdJson; + HILOGI("serviceId = %{public}s", serviceId.c_str()); + auto iter = service2Index.find(serviceId); + if (iter != service2Index.end()) { + indexes.insert(iter->second); + } + } +} + +int32_t ProfileChangeHandler::Register() +{ + HILOGI("called"); + return DeviceProfileStorageManager::GetInstance().SubscribeKvStore(shared_from_this()); +} + +int32_t ProfileChangeHandler::Unregister() +{ + HILOGI("called"); + return DeviceProfileStorageManager::GetInstance().UnSubscribeKvStore(shared_from_this()); +} +} // namespace DeviceProfile +} // namespace OHOS diff --git a/services/core/src/subscribemanager/profile_event_handler.cpp b/services/core/src/subscribemanager/profile_event_handler.cpp new file mode 100755 index 0000000000000000000000000000000000000000..02fe5952f1bd1629ce2dc4dcd706a18aac25344b --- /dev/null +++ b/services/core/src/subscribemanager/profile_event_handler.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "profile_event_handler.h" + +#include "device_profile_errors.h" +#include "device_profile_log.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "ProfileEventHandler"; +} + +bool ProfileEventHandler::Init() +{ + auto runner = AppExecFwk::EventRunner::Create(handlerName_); + eventHandler_ = std::make_shared(runner); + if (eventHandler_ == nullptr) { + return false; + } + return true; +} + +int32_t ProfileEventHandler::Subscribe(const SubscribeInfo& subscribeInfo, + const sptr& profileEventNotifier) +{ + std::lock_guard autoLock(notifierLock_); + auto iter = profileEventSubscribeInfos_.find(profileEventNotifier); + if (iter == profileEventSubscribeInfos_.end()) { + profileEventSubscribeInfos_.emplace(profileEventNotifier, std::move(subscribeInfo)); + } else { + // just overwrite when the follow-ups subscribe with the same notifier + HILOGW("overwrite last subscribed info"); + iter->second = std::move(subscribeInfo); + } + + if (!isRegistered_) { + int32_t errCode = Register(); + if (errCode != ERR_OK) { + HILOGE("errCode = %{public}d", errCode); + return ERR_DP_SUBSCRIBE_FAILED; + } + isRegistered_ = true; + } + return ERR_OK; +} + +int32_t ProfileEventHandler::Unsubscribe(const sptr& profileEventNotifier) +{ + std::lock_guard autoLock(notifierLock_); + auto iter = profileEventSubscribeInfos_.find(profileEventNotifier); + if (iter == profileEventSubscribeInfos_.end()) { + HILOGW("not subscribe yet"); + return ERR_DP_NOT_SUBSCRIBED; + } + profileEventSubscribeInfos_.erase(iter); + if (profileEventSubscribeInfos_.empty()) { + int32_t errCode = Unregister(); + if (errCode != ERR_OK) { + HILOGE("errCode = %{public}d", errCode); + return ERR_DP_UNSUBSCRIBE_FAILED; + } + isRegistered_ = false; + } + return ERR_OK; +} + +void ProfileEventHandler::OnSubscriberDied(const sptr& profileEventNotifier) +{ + HILOGD("called"); + Unsubscribe(profileEventNotifier); +} + +bool ProfileEventHandler::IsRegistered() const +{ + return isRegistered_; +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/src/subscribemanager/profile_event_handler_factory.cpp b/services/core/src/subscribemanager/profile_event_handler_factory.cpp new file mode 100755 index 0000000000000000000000000000000000000000..7c5ed11931e3b3766e66b1f3c81c286f6de8d899 --- /dev/null +++ b/services/core/src/subscribemanager/profile_event_handler_factory.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "profile_event_handler_factory.h" + +#include "device_profile_log.h" +#include "profile_change_handler.h" +#include "profile_sync_handler.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "ProfileEventHandlerFactory"; +} + +IMPLEMENT_SINGLE_INSTANCE(ProfileEventHandlerFactory); + +ProfileEventHandlerFactory::ProfileEventHandlerFactory() +{ + handlersMap_[ProfileEvent::EVENT_SYNC_COMPLETED] = + &ProfileEventHandlerFactory::GetProfileSyncHandlerInner; + handlersMap_[ProfileEvent::EVENT_PROFILE_CHANGED] = + &ProfileEventHandlerFactory::GetProfileChangeHandlerInner; +} + +std::shared_ptr ProfileEventHandlerFactory::GetHandler(ProfileEvent profileEvent) +{ + HILOGI("get handler for event = %{public}d", profileEvent); + auto iter = handlersMap_.find(profileEvent); + if (iter != handlersMap_.end()) { + auto handler = iter->second; + if (handler != nullptr) { + return (this->*handler)(); + } + } + return nullptr; +} + +std::shared_ptr ProfileEventHandlerFactory::GetProfileChangeHandlerInner() +{ + return std::make_shared("profileChange"); +} + +std::shared_ptr ProfileEventHandlerFactory::GetProfileSyncHandlerInner() +{ + return std::make_shared("profileSync"); +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/src/subscribemanager/profile_event_notifier_proxy.cpp b/services/core/src/subscribemanager/profile_event_notifier_proxy.cpp new file mode 100755 index 0000000000000000000000000000000000000000..c303af2cb8720c848d2b7d1bb1093dd2a1f24884 --- /dev/null +++ b/services/core/src/subscribemanager/profile_event_notifier_proxy.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "profile_event_notifier_proxy.h" + +#include "device_profile_log.h" +#include "profile_event.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "ProfileEventNotifierProxy"; +} + +ProfileEventNotifierProxy::ProfileEventNotifierProxy(const sptr& impl) + : IRemoteProxy(impl) +{} + +void ProfileEventNotifierProxy::OnSyncCompleted(const SyncResult& syncResults) +{ + HILOGI("called"); + MessageParcel data; + MessageParcel reply; + if (!data.WriteInterfaceToken(ProfileEventNotifierProxy::GetDescriptor())) { + HILOGE("write descriptor failed"); + return; + } + if (!data.WriteInt32(static_cast(syncResults.size()))) { + HILOGW("write syncResults size failed"); + return; + } + + for (const auto& [deviceId, syncResult] : syncResults) { + if (!data.WriteString(deviceId) || + !data.WriteInt32(static_cast(syncResult))) { + HILOGW("write syncResults failed"); + return; + } + } + MessageOption option { MessageOption::TF_ASYNC }; + int32_t errCode = Remote()->SendRequest(EVENT_SYNC_COMPLETED, data, reply, option); + if (errCode != ERR_OK) { + HILOGE("send request failed, errCode = %{public}d", errCode); + } +} + +void ProfileEventNotifierProxy::OnProfileChanged(const ProfileChangeNotification& changeNotification) +{ + HILOGI("called"); + MessageParcel data; + MessageParcel reply; + if (!data.WriteInterfaceToken(ProfileEventNotifierProxy::GetDescriptor())) { + HILOGE("write descriptor failed"); + return; + } + if (!changeNotification.Marshalling(data)) { + HILOGE("write profile change notification failed"); + return; + } + + MessageOption option { MessageOption::TF_ASYNC }; + int32_t errCode = Remote()->SendRequest(EVENT_PROFILE_CHANGED, data, reply, option); + if (errCode != ERR_OK) { + HILOGE("send request failed, errCode = %{public}d", errCode); + } +} +} // namespace DeviceProfile +} // namespace OHOS diff --git a/services/core/src/subscribemanager/profile_sync_handler.cpp b/services/core/src/subscribemanager/profile_sync_handler.cpp new file mode 100755 index 0000000000000000000000000000000000000000..4da6e39bff486741cc8ccd405d1816c80d2170ca --- /dev/null +++ b/services/core/src/subscribemanager/profile_sync_handler.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "profile_sync_handler.h" + +#include "device_profile_log.h" +#include "device_profile_storage_manager.h" +#include "device_profile_utils.h" +#include "subscribe_manager.h" + +namespace OHOS { +namespace DeviceProfile { +using namespace OHOS::DistributedKv; + +namespace { +const std::string TAG = "ProfileSyncHandler"; +} + +void ProfileSyncHandler::SyncCompleted(const std::map& results) +{ + HILOGI("called"); + SyncResult syncResults; + for (const auto& [deviceId, status] : results) { + HILOGD("deviceId = %{public}s, status = %{public}d", + DeviceProfileUtils::AnonymizeDeviceId(deviceId).c_str(), status); + SyncStatus syncStauts = (status == Status::SUCCESS) ? SUCCEEDED : FAILED; + syncResults.emplace(deviceId, syncStauts); + } + + auto notifyTask = [this, syncResults = std::move(syncResults)]() { + NotifySyncCompleted(syncResults); + }; + std::lock_guard autoLock(notifierLock_); + if (eventHandler_ != nullptr && !eventHandler_->PostTask(notifyTask)) { + HILOGI("post task failed"); + } +} + +void ProfileSyncHandler::NotifySyncCompleted(const SyncResult& syncResults) +{ + { + std::lock_guard autoLock(notifierLock_); + for (const auto& [notifier, _] : profileEventSubscribeInfos_) { + sptr profileEventNotifier = iface_cast(notifier); + if (profileEventNotifier == nullptr) { + HILOGE("cast to IProfileEventNotifier failed"); + continue; + } + profileEventNotifier->OnSyncCompleted(syncResults); + } + } + DeviceProfileStorageManager::GetInstance().NotifySyncCompleted(); +} + +int32_t ProfileSyncHandler::Register() +{ + HILOGI("called"); + return DeviceProfileStorageManager::GetInstance().RegisterSyncCallback(shared_from_this()); +} + +int32_t ProfileSyncHandler::Unregister() +{ + HILOGI("called"); + return DeviceProfileStorageManager::GetInstance().UnRegisterSyncCallback(); +} +} // namespace DeviceProfile +} // namespace OHOS diff --git a/services/core/src/subscribemanager/subscribe_info.cpp b/services/core/src/subscribemanager/subscribe_info.cpp new file mode 100755 index 0000000000000000000000000000000000000000..ef659e20eb6ed77b2147643701f41ca7c6fdc2e5 --- /dev/null +++ b/services/core/src/subscribemanager/subscribe_info.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "subscribe_info.h" + +#include "device_profile_log.h" +#include "parcel_helper.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "SubscribeInfo"; +} + +bool SubscribeInfo::Marshalling(Parcel& parcel) const +{ + PARCEL_WRITE_HELPER_RET(parcel, Uint32, profileEvent, false); + PARCEL_WRITE_HELPER_RET(parcel, String, extraInfo.dump(), false); + return true; +} + +bool SubscribeInfo::Unmarshalling(Parcel& parcel) +{ + profileEvent = static_cast(parcel.ReadUint32()); + if (profileEvent >= EVENT_PROFILE_END || profileEvent == EVENT_UNKNOWN) { + HILOGE("invalid profile event, %{public}d", profileEvent); + return false; + } + std::string value = parcel.ReadString(); + extraInfo = ExtraInfo::parse(value, nullptr, false); + if (extraInfo.is_discarded()) { + HILOGE("parse extra info failed, %{public}s", value.c_str()); + return false; + } + return true; +} + +bool SubscribeInfo::operator!=(const SubscribeInfo& rhs) const +{ + return ((profileEvent != rhs.profileEvent) || (extraInfo != rhs.extraInfo)); +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/src/subscribemanager/subscribe_info_checker.cpp b/services/core/src/subscribemanager/subscribe_info_checker.cpp new file mode 100755 index 0000000000000000000000000000000000000000..adc7fa026461d2b66a1eb0f6c8ce186b91f0966b --- /dev/null +++ b/services/core/src/subscribemanager/subscribe_info_checker.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "subscribe_info_checker.h" + +#include "device_profile_log.h" +#include "profile_event.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "SubscribeInfoChecker"; +} + +IMPLEMENT_SINGLE_INSTANCE(SubscribeInfoChecker); + +SubscribeInfoChecker::SubscribeInfoChecker() +{ + checkersMap_[EVENT_SYNC_COMPLETED] = &SubscribeInfoChecker::CheckSyncEventInner; + checkersMap_[EVENT_PROFILE_CHANGED] = &SubscribeInfoChecker::CheckProfileChangeInner; +} + +bool SubscribeInfoChecker::Check(const std::list& subscribeInfos) +{ + auto checker = [this](const auto& subscribeInfo) { + auto profileEvent = subscribeInfo.profileEvent; + auto iter = checkersMap_.find(profileEvent); + if (iter != checkersMap_.end()) { + if (auto func = iter->second; func != nullptr) { + return (this->*func)(subscribeInfo); + } + } + HILOGE("unknown profile event = %{public}u", static_cast(profileEvent)); + return false; + }; + return std::all_of(subscribeInfos.begin(), subscribeInfos.end(), checker); +} + +bool SubscribeInfoChecker::CheckSyncEventInner([[maybe_unused]] const SubscribeInfo& subscribeInfo) +{ + // currently no need to check for sync event + return true; +} + +bool SubscribeInfoChecker::CheckProfileChangeInner(const SubscribeInfo& subscribeInfo) +{ + const ExtraInfo& extraInfo = subscribeInfo.extraInfo; + const auto& deviceIdJson = extraInfo["deviceId"]; + if (deviceIdJson == nullptr) { + return false; + } + HILOGD("check deviceId"); + if (deviceIdJson.type() != ExtraInfo::value_t::string) { + return false; + } + + const auto& serviceIdsJson = extraInfo["serviceIds"]; + if (serviceIdsJson == nullptr) { + return false; + } + HILOGD("check serviceIds"); + auto type = serviceIdsJson.type(); + if (type != ExtraInfo::value_t::array) { + return false; + } else { + return std::all_of(serviceIdsJson.begin(), serviceIdsJson.end(), + [](const auto& serviceIdJson) { return serviceIdJson.type() == ExtraInfo::value_t::string; }); + } + return true; +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/src/subscribemanager/subscribe_manager.cpp b/services/core/src/subscribemanager/subscribe_manager.cpp new file mode 100755 index 0000000000000000000000000000000000000000..26c338b2f5ef425a5d666f6166eb0e32fe4da007 --- /dev/null +++ b/services/core/src/subscribemanager/subscribe_manager.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "subscribe_manager.h" + +#include "ipc_object_proxy.h" +#include "ipc_skeleton.h" + +#include "device_profile_errors.h" +#include "device_profile_log.h" +#include "device_profile_storage_manager.h" +#include "profile_change_handler.h" +#include "profile_event_handler_factory.h" +#include "subscribe_info_checker.h" +#include "subscriber_death_recipient.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "SubscribeManager"; + +constexpr int32_t MAX_SUBSCRIBS_PER_UID = 100; +} + +IMPLEMENT_SINGLE_INSTANCE(SubscribeManager); + +bool SubscribeManager::Init() +{ + subscriberDeathRecipient_ = sptr( + new (std::nothrow) SubscriberDeathRecipient); + HILOGI("init succeeded"); + return true; +} + +int32_t SubscribeManager::SubscribeProfileEvents(const std::list& subscribeInfos, + const sptr& profileEventNotifier, + std::list& failedEvents) +{ + HILOGI("called"); + if (!SubscribeInfoChecker::GetInstance().Check(subscribeInfos)) { + HILOGE("SubscribeInfo check failed"); + return ERR_DP_INVALID_PARAMS; + } + + int32_t callingUid = IPCSkeleton::GetCallingUid(); + if (!CheckSubsOfUid(callingUid)) { + HILOGE("uid %{public}d subscribed too many times", callingUid); + return ERR_DP_SUBSCRIBE_LIMIT_EXCEEDED; + } + + std::lock_guard autoLock(handlerLock_); + ProfileEvents subProfileEvents; + std::shared_ptr handler; + for (const auto& subscribeInfo : subscribeInfos) { + auto profileEvent = subscribeInfo.profileEvent; + auto iter = handlersMap_.find(profileEvent); + if (iter == handlersMap_.end()) { + handler = ProfileEventHandlerFactory::GetInstance().GetHandler(profileEvent); + if (handler == nullptr || !handler->Init()) { + failedEvents.emplace_back(profileEvent); + HILOGW("get or init handler for event:%{public}d failed", profileEvent); + continue; + } + handlersMap_.emplace(profileEvent, handler); + } else { + handler = iter->second; + } + + if (handler->Subscribe(subscribeInfo, profileEventNotifier) != ERR_OK) { + HILOGE("subscribe event:%{public}d failed", profileEvent); + failedEvents.emplace_back(profileEvent); + } else { + subProfileEvents.set(static_cast(profileEvent)); + } + } + if (!subProfileEvents.none()) { + TryAddNotifierLocked(profileEventNotifier, subProfileEvents); + } + return failedEvents.empty() ? ERR_OK : ERR_DP_SUBSCRIBE_FAILED; +} + +int32_t SubscribeManager::UnsubscribeProfileEvents(const std::list& profileEvents, + const sptr& profileEventNotifier, + std::list& failedEvents) +{ + HILOGI("called"); + std::lock_guard autoLock(handlerLock_); + ProfileEvents unsubProfileEvents; + for (auto profileEvent : profileEvents) { + auto iter = handlersMap_.find(profileEvent); + if (iter == handlersMap_.end()) { + HILOGW("not find event:%{public}d", profileEvent); + continue; + } + auto handler = iter->second; + if (handler->Unsubscribe(profileEventNotifier) != ERR_OK) { + HILOGE("unsubscribe event:%{public}d failed", profileEvent); + failedEvents.emplace_back(profileEvent); + } else { + unsubProfileEvents.set(static_cast(profileEvent)); + } + } + if (!unsubProfileEvents.none()) { + TryRemoveNotiferLocked(profileEventNotifier, unsubProfileEvents); + } + return failedEvents.empty() ? ERR_OK : ERR_DP_UNSUBSCRIBE_FAILED; +} + +void SubscribeManager::TryAddNotifierLocked(const sptr& profileEventNotifier, + const ProfileEvents& subProfileEvents) +{ + auto iter = notifiersMap_.find(profileEventNotifier); + if (iter == notifiersMap_.end()) { + int32_t callingUid = IPCSkeleton::GetCallingUid(); + NotifierInfo notifierInfo = { callingUid, subProfileEvents}; + notifiersMap_.emplace(profileEventNotifier, std::move(notifierInfo)); + profileEventNotifier->AddDeathRecipient(subscriberDeathRecipient_); + HILOGI("notifiers size = %{public}zu", notifiersMap_.size()); + IncSubsOfUidLocked(callingUid); + } else { + iter->second.profileEvents |= subProfileEvents; + } +} + +void SubscribeManager::TryRemoveNotiferLocked(const sptr& profileEventNotifier, + const ProfileEvents& unsubProfileEvents) +{ + auto iter = notifiersMap_.find(profileEventNotifier); + if (iter == notifiersMap_.end()) { + return; + } + auto& subProfileEvents = iter->second.profileEvents; + subProfileEvents &= ~unsubProfileEvents; + if (subProfileEvents.none()) { + int32_t callingUid = iter->second.callingUid; + profileEventNotifier->RemoveDeathRecipient(subscriberDeathRecipient_); + notifiersMap_.erase(iter); + HILOGI("notifiers size = %{public}zu", notifiersMap_.size()); + DecSubsOfUidLocked(callingUid); + return; + } +} + +void SubscribeManager::IncSubsOfUidLocked(int32_t uid) +{ + if (uidSubsMap_.find(uid) != uidSubsMap_.end()) { + ++uidSubsMap_[uid]; + } else { + uidSubsMap_[uid] = 1; + } + HILOGI("uid %{public}d has %{public}u subscription(s)", uid, uidSubsMap_[uid]); +} + +void SubscribeManager::DecSubsOfUidLocked(int32_t uid) +{ + auto iter = uidSubsMap_.find(uid); + if (iter != uidSubsMap_.end()) { + auto& numSubs = iter->second; + if (--numSubs == 0) { + uidSubsMap_.erase(iter); + } + HILOGI("uid %{public}d subscription(s) is %{public}u", uid, numSubs); + } +} + +bool SubscribeManager::CheckSubsOfUid(int32_t uid) +{ + std::lock_guard autoLock(handlerLock_); + auto iter = uidSubsMap_.find(uid); + if (iter == uidSubsMap_.end()) { + return true; + } + if (iter->second >= MAX_SUBSCRIBS_PER_UID) { + return false; + } + return true; +} + +void SubscribeManager::OnSubscriberDied(const sptr& profileEventNotifier) +{ + HILOGI("called"); + DeviceProfileStorageManager::GetInstance().NotifySubscriberDied(profileEventNotifier); + std::lock_guard autoLock(handlerLock_); + auto iter = notifiersMap_.find(profileEventNotifier); + if (iter != notifiersMap_.end()) { + DecSubsOfUidLocked(iter->second.callingUid); + notifiersMap_.erase(iter); + } + for (const auto& [_, handler] : handlersMap_) { + handler->OnSubscriberDied(profileEventNotifier); + } +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/src/subscribemanager/subscriber_death_recipient.cpp b/services/core/src/subscribemanager/subscriber_death_recipient.cpp new file mode 100755 index 0000000000000000000000000000000000000000..73253e0d5c70d104b6fede8e36b2587524beea27 --- /dev/null +++ b/services/core/src/subscribemanager/subscriber_death_recipient.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "subscriber_death_recipient.h" + +#include "subscribe_manager.h" + +namespace OHOS { +namespace DeviceProfile { +void SubscriberDeathRecipient::OnRemoteDied(const wptr& remote) +{ + SubscribeManager::GetInstance().OnSubscriberDied(remote.promote()); +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/src/sync_options.cpp b/services/core/src/sync_options.cpp new file mode 100755 index 0000000000000000000000000000000000000000..5456c87e20cf398fbeac212b5e6b6fe769506a25 --- /dev/null +++ b/services/core/src/sync_options.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sync_options.h" + +#include "device_profile_log.h" +#include "parcel_helper.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "SyncOptions"; +} + +const std::list& SyncOptions::GetDeviceList() const +{ + return syncDevIds_; +} + +void SyncOptions::AddDevice(const std::string& deviceId) +{ + syncDevIds_.emplace_back(deviceId); +} + +DistributedKv::SyncMode SyncOptions::GetSyncMode() const +{ + return syncMode_; +} + +void SyncOptions::SetSyncMode(DistributedKv::SyncMode mode) +{ + syncMode_ = mode; +} + +bool SyncOptions::Marshalling(Parcel& parcel) const +{ + PARCEL_WRITE_HELPER_RET(parcel, Int32, static_cast(syncMode_), false); + PARCEL_WRITE_HELPER_RET(parcel, Int32, static_cast(syncDevIds_.size()), false); + for (const auto& deviceId : syncDevIds_) { + PARCEL_WRITE_HELPER_RET(parcel, String, deviceId, false); + } + return true; +} + +bool SyncOptions::Unmarshalling(Parcel& parcel) +{ + int32_t mode = 0; + PARCEL_READ_HELPER_RET(parcel, Int32, mode, false); + syncMode_ = static_cast(mode); + int32_t size = 0; + PARCEL_READ_HELPER_RET(parcel, Int32, size, false); + for (int32_t i = 0; i < size; i++) { + std::string deviceId; + PARCEL_READ_HELPER_RET(parcel, String, deviceId, false); + syncDevIds_.emplace_back(deviceId); + } + return true; +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/services/core/test/BUILD.gn b/services/core/test/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..c613466ffc7d646fa47e89dbd85bd4d349e4aad1 --- /dev/null +++ b/services/core/test/BUILD.gn @@ -0,0 +1,71 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//build/ohos_var.gni") +import("//build/test.gni") + +module_output_path = "deviceprofile/deviceprofiletest" + +device_profile_path = "//foundation/deviceprofile/device_profile_core" +device_profile_innerkits = "${device_profile_path}/interfaces/innerkits" +device_profile_service = "${device_profile_path}/services" + +device_profile_configs = + [ "${device_profile_service}/core:device_profile_core_config" ] + +device_profile_deps = [ + "${device_profile_innerkits}/core:distributed_device_profile_client", + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//utils/native/base:utils", +] + +device_profile_external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", +] + +device_profile_public_deps = [ "//third_party/googletest:gtest_main" ] + +ohos_unittest("profile_crud_test") { + module_out_path = module_output_path + + sources = [ "unittest/profile_crud_test.cpp" ] + configs = device_profile_configs + deps = device_profile_deps + if (is_standard_system) { + external_deps = device_profile_external_deps + public_deps = device_profile_public_deps + } +} + +ohos_unittest("event_subscribe_test") { + module_out_path = module_output_path + + sources = [ "unittest/event_subscribe_test.cpp" ] + configs = device_profile_configs + deps = device_profile_deps + if (is_standard_system) { + external_deps = device_profile_external_deps + public_deps = device_profile_public_deps + } +} + +group("unittest") { + testonly = true + deps = [ + ":event_subscribe_test", + ":profile_crud_test", + ] +} diff --git a/services/core/test/unittest/event_subscribe_test.cpp b/services/core/test/unittest/event_subscribe_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..c70d0e56335b33a9a0ece3f2fa30b8bbb407e0d6 --- /dev/null +++ b/services/core/test/unittest/event_subscribe_test.cpp @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gtest/gtest.h" + +#include + +#include "utils.h" + +#include "device_profile_errors.h" +#include "distributed_device_profile_client.h" +#include "nlohmann/json.hpp" + +namespace OHOS { +namespace DeviceProfile { +using namespace std::chrono_literals; +using namespace testing; +using namespace testing::ext; + +class EventSubscribeTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void EventSubscribeTest::SetUpTestCase() +{ +} + +void EventSubscribeTest::TearDownTestCase() +{ +} + +void EventSubscribeTest::SetUp() +{ +} + +void EventSubscribeTest::TearDown() +{ +} + +class ProfileEventCallback : public IProfileEventCallback { +public: + ProfileEventCallback() = default; + ~ProfileEventCallback() = default; + + void OnSyncCompleted(const SyncResult& syncResults) override + { + } + + void OnProfileChanged(const ProfileChangeNotification& changeNotification) override + { + if (!subServiceIds_.empty()) { + const auto& profileEntries = changeNotification.GetProfileEntries(); + for (const auto& ProfileEntry : profileEntries) { + auto key = ProfileEntry.key; + DTEST_LOG << "key: " << key << std::endl; + auto iter = std::find(subServiceIds_.begin(), subServiceIds_.end(), key); + EXPECT_TRUE(iter != subServiceIds_.end()); + numNotifications_++; + } + } + } + + void SetSubServiceIds(const std::list& subServiceIds) + { + subServiceIds_ = subServiceIds; + } + + int32_t GetNotificationNum() const + { + return numNotifications_; + } + +private: + std::list subServiceIds_; + int32_t numNotifications_ {0}; +}; + +int32_t PutFakeStorage() +{ + ServiceCharacteristicProfile profile; + profile.SetServiceId("fakeStorage"); + profile.SetServiceType("fakeStorage"); + nlohmann::json j; + j["capacity"] = 0; + profile.SetCharacteristicProfileJson(j.dump()); + return DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile); +} + +int32_t PutFakeSystem() +{ + ServiceCharacteristicProfile profile; + profile.SetServiceId("fakeSystem"); + profile.SetServiceType("fakeSystem"); + nlohmann::json j; + j["harmonyVersion"] = "2.2.0"; + profile.SetCharacteristicProfileJson(j.dump()); + return DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile); +} + +int32_t MockSubscribeEvents(const std::shared_ptr& eventCb, + const std::list& serviceIds, const std::string& deviceId) +{ + eventCb->SetSubServiceIds(serviceIds); + ExtraInfo extraInfo; + extraInfo["deviceId"] = deviceId; + extraInfo["serviceIds"] = serviceIds; + + std::list subscribeInfos; + SubscribeInfo eventChange; + eventChange.profileEvent = ProfileEvent::EVENT_PROFILE_CHANGED; + eventChange.extraInfo = std::move(extraInfo); + subscribeInfos.emplace_back(eventChange); + + SubscribeInfo eventSync; + eventSync.profileEvent = ProfileEvent::EVENT_SYNC_COMPLETED; + subscribeInfos.emplace_back(eventSync); + + std::list failedEvents; + return DistributedDeviceProfileClient::GetInstance().SubscribeProfileEvents( + subscribeInfos, eventCb, failedEvents); +} + +int32_t MockUnsubscribeEvents(const std::shared_ptr& eventCb) +{ + std::list profileEvents; + profileEvents.emplace_back(ProfileEvent::EVENT_PROFILE_CHANGED); + profileEvents.emplace_back(ProfileEvent::EVENT_SYNC_COMPLETED); + std::list failedEvents; + return DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvents( + profileEvents, eventCb, failedEvents); +} + +int32_t MockSubscribeEvent(const std::shared_ptr& eventCb, + const std::list& serviceIds, const std::string& deviceId) +{ + eventCb->SetSubServiceIds(serviceIds); + ExtraInfo extraInfo; + extraInfo["deviceId"] = deviceId; + extraInfo["serviceIds"] = serviceIds; + + SubscribeInfo subscribeInfo; + subscribeInfo.profileEvent = ProfileEvent::EVENT_PROFILE_CHANGED; + subscribeInfo.extraInfo = std::move(extraInfo); + return DistributedDeviceProfileClient::GetInstance().SubscribeProfileEvent(subscribeInfo, eventCb); +} + +/** + * @tc.name: Subscribe001 + * @tc.desc: subscribe a service and put a service profile + * @tc.type: FUNC + */ +HWTEST_F(EventSubscribeTest, Subscribe001, TestSize.Level2) +{ + auto callback = std::make_shared(); + if (MockSubscribeEvent(callback, {"fakeStorage"}, "")) { + DTEST_LOG << "subscribe failed" << std::endl; + return; + } + + int32_t errCode = PutFakeStorage(); + if (errCode == ERR_OK) { + DTEST_LOG << "put succeeded" << std::endl; + std::this_thread::sleep_for(1s); + EXPECT_TRUE(callback->GetNotificationNum() == 1); + } +} + +/** + * @tc.name: Subscribe002 + * @tc.desc: subscribe a service and put a unsubscribed service + * @tc.type: FUNC + */ +HWTEST_F(EventSubscribeTest, Subscribe002, TestSize.Level2) +{ + auto callback = std::make_shared(); + if (MockSubscribeEvent(callback, {"fakeSystem"}, "")) { + DTEST_LOG << "subscribe failed" << std::endl; + return; + } + int32_t errCode = PutFakeStorage(); + if (errCode == ERR_OK) { + DTEST_LOG << "put succeeded" << std::endl; + std::this_thread::sleep_for(1s); + EXPECT_TRUE(callback->GetNotificationNum() == 0); + } +} + +/** + * @tc.name: Subscribe003 + * @tc.desc: subscribe services and put service + * @tc.type: FUNC + */ +HWTEST_F(EventSubscribeTest, Subscribe003, TestSize.Level2) +{ + auto callback = std::make_shared(); + std::list serviceIds = {"fakeStorage", "fakeSystem"}; + if (MockSubscribeEvents(callback, serviceIds, "") != ERR_OK) { + DTEST_LOG << "subscribe failed" << std::endl; + return; + } + int32_t errCode = PutFakeSystem(); + if (errCode == ERR_OK) { + DTEST_LOG << "put succeeded" << std::endl; + std::this_thread::sleep_for(1s); + EXPECT_TRUE(callback->GetNotificationNum() == 1); + } +} + +/** + * @tc.name: Subscribe004 + * @tc.desc: subscribe with invalid deviceId + * @tc.type: FUNC + */ +HWTEST_F(EventSubscribeTest, Subscribe004, TestSize.Level2) +{ + auto callback = std::make_shared(); + std::list serviceIds = {"fakeStorage", "fakeSystem"}; + if (MockSubscribeEvent(callback, serviceIds, "fake_device_id") != ERR_OK) { + DTEST_LOG << "subscribe failed" << std::endl; + return; + } + int32_t errCode = PutFakeStorage(); + if (errCode == ERR_OK) { + DTEST_LOG << "put succeeded" << std::endl; + std::this_thread::sleep_for(1s); + EXPECT_TRUE(callback->GetNotificationNum() == 0); + } +} + +/** + * @tc.name: Subscribe005 + * @tc.desc: subscribe services and put services + * @tc.type: FUNC + */ +HWTEST_F(EventSubscribeTest, Subscribe005, TestSize.Level2) +{ + auto callback = std::make_shared(); + /** + * @tc.steps: step1. subscribe change event with two services + */ + std::list serviceIds = {"fakeStorage", "fakeSystem"}; + if (MockSubscribeEvent(callback, serviceIds, "") != ERR_OK) { + DTEST_LOG << "subscribe failed" << std::endl; + return; + } + + /** + * @tc.steps: step2. put service profile which is subscribed + * @tc.expected: step2. got one notification. + */ + int32_t errCode = PutFakeStorage(); + if (errCode == ERR_OK) { + DTEST_LOG << "put succeeded" << std::endl; + std::this_thread::sleep_for(1s); + EXPECT_TRUE(callback->GetNotificationNum() == 1); + } + /** + * @tc.steps: step3. put the other subscribed service profile + * @tc.expected: step3. got notification again. + */ + errCode = PutFakeSystem(); + if (errCode == ERR_OK) { + DTEST_LOG << "put succeeded" << std::endl; + std::this_thread::sleep_for(1s); + EXPECT_TRUE(callback->GetNotificationNum() == 2); + } +} + +/** + * @tc.name: Subscribe006 + * @tc.desc: subscribe with duplicated events + * @tc.type: FUNC + */ +HWTEST_F(EventSubscribeTest, Subscribe006, TestSize.Level0) +{ + auto callback = std::make_shared(); + std::list subscribeInfos; + ExtraInfo extraInfo; + extraInfo["deviceId"] = ""; + extraInfo["serviceIds"] = {"fakeSystem"}; + + SubscribeInfo eventChange; + eventChange.profileEvent = ProfileEvent::EVENT_PROFILE_CHANGED; + eventChange.extraInfo = std::move(extraInfo); + subscribeInfos.emplace_back(eventChange); + subscribeInfos.emplace_back(eventChange); + + std::list failedEvents; + int32_t errCode = DistributedDeviceProfileClient::GetInstance().SubscribeProfileEvents( + subscribeInfos, callback, failedEvents); + EXPECT_TRUE(errCode == ERR_DP_INVALID_PARAMS); +} + +/** + * @tc.name: Unsubscribe001 + * @tc.desc: unsubscribe event which is not subscribed yet + * @tc.type: FUNC + */ +HWTEST_F(EventSubscribeTest, Unsubscribe001, TestSize.Level0) +{ + auto callback = std::make_shared(); + int32_t errCode = DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvent( + ProfileEvent::EVENT_PROFILE_CHANGED, callback); + EXPECT_TRUE(errCode == ERR_DP_NOT_SUBSCRIBED); +} + +/** + * @tc.name: Unsubscribe002 + * @tc.desc: unsubscribe events which are not subscribed yet + * @tc.type: FUNC + */ +HWTEST_F(EventSubscribeTest, Unsubscribe002, TestSize.Level0) +{ + auto callback = std::make_shared(); + int32_t errCode = MockUnsubscribeEvents(callback); + EXPECT_TRUE(errCode == ERR_DP_NOT_SUBSCRIBED); +} + +/** + * @tc.name: SubscribeWithUnsusbscribe001 + * @tc.desc: subscribe events and then unsubscribe one + * @tc.type: FUNC + */ +HWTEST_F(EventSubscribeTest, SubscribeWithUnsusbscribe001, TestSize.Level2) +{ + auto callback = std::make_shared(); + + /** + * @tc.steps: step1. subscribe sync and change event + */ + std::list serviceIds = {"fakeStorage", "fakeSystem"}; + if (MockSubscribeEvents(callback, serviceIds, "") != ERR_OK) { + DTEST_LOG << "subscribe failed" << std::endl; + return; + } + + /** + * @tc.steps: step2. put service profile which is subscribed + * @tc.expected: step2. got one notification. + */ + int32_t errCode = PutFakeSystem(); + if (errCode == ERR_OK) { + DTEST_LOG << "put succeeded" << std::endl; + std::this_thread::sleep_for(1s); + EXPECT_TRUE(callback->GetNotificationNum() == 1); + } + + /** + * @tc.steps: step3. unsubscribe sync event + */ + errCode = DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvent( + ProfileEvent::EVENT_SYNC_COMPLETED, callback); + if (errCode != ERR_OK) { + DTEST_LOG << "unsubscribe failed" << std::endl; + return; + } + + /** + * @tc.steps: step4. put the other subscribed service profile + * @tc.expected: step4. got notification again. + */ + errCode = PutFakeStorage(); + if (errCode == ERR_OK) { + DTEST_LOG << "put succeeded" << std::endl; + std::this_thread::sleep_for(1s); + EXPECT_TRUE(callback->GetNotificationNum() == 2); + } +} + +/** + * @tc.name: SubscribeWithUnsusbscribe002 + * @tc.desc: subscribe events and then unsubscribe all + * @tc.type: FUNC + */ +HWTEST_F(EventSubscribeTest, SubscribeWithUnsusbscribe002, TestSize.Level2) +{ + auto callback = std::make_shared(); + + /** + * @tc.steps: step1. subscribe sync and change event + */ + std::list serviceIds = {"fakeStorage", "fakeSystem"}; + if (MockSubscribeEvents(callback, serviceIds, "") != ERR_OK) { + DTEST_LOG << "subscribe failed" << std::endl; + return; + } + + /** + * @tc.steps: step2. put service profile which is subscribed + * @tc.expected: step2. got one notification. + */ + int32_t errCode = PutFakeSystem(); + if (errCode == ERR_OK) { + DTEST_LOG << "put succeeded" << std::endl; + std::this_thread::sleep_for(1s); + EXPECT_TRUE(callback->GetNotificationNum() == 1); + } + + /** + * @tc.steps: step3. unsubscribe all events + */ + if (MockUnsubscribeEvents(callback) != ERR_OK) { + DTEST_LOG << "unsubscribe failed" << std::endl; + return; + } + + /** + * @tc.steps: step4. put a other subscribed service profile + * @tc.expected: step4. can't receive notification. + */ + errCode = PutFakeStorage(); + if (errCode == ERR_OK) { + DTEST_LOG << "put succeeded" << std::endl; + std::this_thread::sleep_for(1s); + EXPECT_TRUE(callback->GetNotificationNum() == 1); + } +} +} +} \ No newline at end of file diff --git a/services/core/test/unittest/profile_crud_test.cpp b/services/core/test/unittest/profile_crud_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..fed209a25b6ae459b5af1a2ecaa89934f726b237 --- /dev/null +++ b/services/core/test/unittest/profile_crud_test.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gtest/gtest.h" + +#include "utils.h" + +#define private public +#define protected public +#include "device_profile_errors.h" +#include "distributed_device_profile_client.h" +#include "nlohmann/json.hpp" +#undef private +#undef protected + +namespace OHOS { +namespace DeviceProfile { +using namespace testing; +using namespace testing::ext; + +class ProfileCrudTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void ProfileCrudTest::SetUpTestCase() +{ +} + +void ProfileCrudTest::TearDownTestCase() +{ +} + +void ProfileCrudTest::SetUp() +{ +} + +void ProfileCrudTest::TearDown() +{ +} + +/** + * @tc.name: PutDeviceProfile_001 + * @tc.desc: put device profile with empty service id + * @tc.type: FUNC + */ +HWTEST_F(ProfileCrudTest, PutDeviceProfile_001, TestSize.Level1) +{ + auto dps = DistributedDeviceProfileClient::GetInstance().GetDeviceProfileService(); + if (dps == nullptr) { + DTEST_LOG << "device profile service is nullptr" << std::endl; + return; + } + + ServiceCharacteristicProfile profile; + profile.SetServiceId(""); + profile.SetServiceType("test"); + nlohmann::json j; + j["testVersion"] = "3.0.0"; + j["testApiLevel"] = 7; + profile.SetCharacteristicProfileJson(j.dump()); + int32_t result = DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile); + EXPECT_TRUE(result == ERR_DP_INVALID_PARAMS); +} + +/** + * @tc.name: PutDeviceProfile_002 + * @tc.desc: put device profile with empty service type + * @tc.type: FUNC + */ +HWTEST_F(ProfileCrudTest, PutDeviceProfile_002, TestSize.Level1) +{ + auto dps = DistributedDeviceProfileClient::GetInstance().GetDeviceProfileService(); + if (dps == nullptr) { + DTEST_LOG << "device profile service is nullptr" << std::endl; + return; + } + + ServiceCharacteristicProfile profile; + profile.SetServiceId("test"); + profile.SetServiceType(""); + nlohmann::json j; + j["testVersion"] = "3.0.0"; + j["testApiLevel"] = 7; + profile.SetCharacteristicProfileJson(j.dump()); + int32_t result = DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile); + EXPECT_TRUE(result == ERR_DP_INVALID_PARAMS); +} + +/** + * @tc.name: PutDeviceProfile_003 + * @tc.desc: put device profile with empty characteristics + * @tc.type: FUNC + */ +HWTEST_F(ProfileCrudTest, PutDeviceProfile_003, TestSize.Level1) +{ + auto dps = DistributedDeviceProfileClient::GetInstance().GetDeviceProfileService(); + if (dps == nullptr) { + DTEST_LOG << "device profile service is nullptr" << std::endl; + return; + } + + ServiceCharacteristicProfile profile; + profile.SetServiceId("test"); + profile.SetServiceType("test"); + nlohmann::json j; + // the result string is "null" + profile.SetCharacteristicProfileJson(j.dump()); + int32_t result = DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile); + EXPECT_TRUE(result == ERR_DP_INVALID_PARAMS); +} + +/** + * @tc.name: PutDeviceProfile_004 + * @tc.desc: put device profile without set characteristics + * @tc.type: FUNC + */ +HWTEST_F(ProfileCrudTest, PutDeviceProfile_004, TestSize.Level1) +{ + auto dps = DistributedDeviceProfileClient::GetInstance().GetDeviceProfileService(); + if (dps == nullptr) { + DTEST_LOG << "device profile service is nullptr" << std::endl; + return; + } + + ServiceCharacteristicProfile profile; + profile.SetServiceId("test"); + profile.SetServiceType("test"); + int32_t result = DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile); + EXPECT_TRUE(result == ERR_DP_INVALID_PARAMS); +} + +/** + * @tc.name: PutDeviceProfile_005 + * @tc.desc: put device profile with normal value + * @tc.type: FUNC + */ +HWTEST_F(ProfileCrudTest, PutDeviceProfile_005, TestSize.Level1) +{ + auto dps = DistributedDeviceProfileClient::GetInstance().GetDeviceProfileService(); + if (dps == nullptr) { + DTEST_LOG << "device profile service is nullptr" << std::endl; + return; + } + + ServiceCharacteristicProfile profile; + profile.SetServiceId("test"); + profile.SetServiceType("test"); + nlohmann::json j; + j["testVersion"] = "3.0.0"; + j["testApiLevel"] = 7; + profile.SetCharacteristicProfileJson(j.dump()); + int32_t result = DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile); + EXPECT_TRUE(result == ERR_OK); +} + +/** + * @tc.name: GetDeviceProfile_001 + * @tc.desc: get device profile with normal deviceid + * @tc.type: FUNC + */ +HWTEST_F(ProfileCrudTest, GetDeviceProfile_001, TestSize.Level1) +{ + ServiceCharacteristicProfile profile; + DistributedDeviceProfileClient::GetInstance().GetDeviceProfile("", "test", profile); + std::string jsonData = profile.GetCharacteristicProfileJson(); + auto json = nlohmann::json::parse(jsonData); + EXPECT_EQ(json["testApiLevel"], 7); +} + +/** + * @tc.name: GetDeviceProfile_002 + * @tc.desc: get device profile with unnormal deviceid + * @tc.type: FUNC + */ +HWTEST_F(ProfileCrudTest, GetDeviceProfile_002, TestSize.Level1) +{ + ServiceCharacteristicProfile profile; + DistributedDeviceProfileClient::GetInstance().GetDeviceProfile("123456789", "test", profile); + std::string jsonData = profile.GetCharacteristicProfileJson(); + EXPECT_TRUE(jsonData.empty()); +} + +/** + * @tc.name: CollectDeviceProfile_001 + * @tc.desc: collect system profile infomation + * @tc.type: FUNC + */ +HWTEST_F(ProfileCrudTest, CollectDeviceProfile_001, TestSize.Level1) +{ + ServiceCharacteristicProfile profile; + DistributedDeviceProfileClient::GetInstance().GetDeviceProfile("", "system", profile); + std::string jsonData = profile.GetCharacteristicProfileJson(); + auto json = nlohmann::json::parse(jsonData); + EXPECT_EQ(json["type"], 11); +} + +/** + * @tc.name: CollectDeviceProfile_002 + * @tc.desc: collect device profile infomation + * @tc.type: FUNC + */ +HWTEST_F(ProfileCrudTest, CollectDeviceProfile_002, TestSize.Level1) +{ + ServiceCharacteristicProfile profile; + DistributedDeviceProfileClient::GetInstance().GetDeviceProfile("", "device", profile); + std::string jsonData = profile.GetCharacteristicProfileJson(); + auto json = nlohmann::json::parse(jsonData); + EXPECT_TRUE(!jsonData.empty()); +} + +/** + * @tc.name: DeleteDeviceProfile_001 + * @tc.desc: delete device profile + * @tc.type: FUNC + */ +HWTEST_F(ProfileCrudTest, DeleteDeviceProfile_001, TestSize.Level1) +{ + auto dps = DistributedDeviceProfileClient::GetInstance().GetDeviceProfileService(); + if (dps == nullptr) { + DTEST_LOG << "device profile service is nullptr" << std::endl; + return; + } + + ServiceCharacteristicProfile profilePut; + profilePut.SetServiceId("fakeSystem"); + profilePut.SetServiceType("fakeSystem"); + nlohmann::json j; + j["harmonyVersion"] = "2.2.0"; + profilePut.SetCharacteristicProfileJson(j.dump()); + int32_t result = DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profilePut); + EXPECT_TRUE(result == ERR_OK); + result = DistributedDeviceProfileClient::GetInstance().DeleteDeviceProfile("fakeSystem"); + EXPECT_TRUE(result == ERR_OK); + + ServiceCharacteristicProfile profileGet; + DistributedDeviceProfileClient::GetInstance().GetDeviceProfile("", "fakeSystem", profileGet); + auto profileStr = profileGet.GetCharacteristicProfileJson(); + auto profileJson = nlohmann::json::parse(profileStr, nullptr, false); + if (!profileJson.is_discarded()) { + EXPECT_TRUE(!profileJson.empty()); + } +} +} +} \ No newline at end of file diff --git a/services/core/test/unittest/utils.h b/services/core/test/unittest/utils.h new file mode 100755 index 0000000000000000000000000000000000000000..b452d68e0bfc74914770ec50dccced9081cf8588 --- /dev/null +++ b/services/core/test/unittest/utils.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DEVICE_PROFILE_UNITTEST_UTILS_H +#define OHOS_DEVICE_PROFILE_UNITTEST_UTILS_H + +namespace OHOS { +namespace DeviceProfile { +#define DTEST_LOG std::cout << __FILE__ << ":" << __LINE__ << ":" +} // namespace DeviceProfile +} // namespace OHOS + +#endif // OHOS_DEVICE_PROFILE_UNITTEST_UTILS_H \ No newline at end of file diff --git a/tools/dp/BUILD.gn b/tools/dp/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..5dc247c8121689c8c2f257856923e52847a29f05 --- /dev/null +++ b/tools/dp/BUILD.gn @@ -0,0 +1,52 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//build/ohos_var.gni") + +device_profile_path = "//foundation/deviceprofile/device_profile_core" +device_profile_innerkits = "${device_profile_path}/interfaces/innerkits" +device_profile_configs = [ "${device_profile_innerkits}/device_profile_core:distributed_device_profile_client_config" ] + +ohos_executable("dp") { + install_enable = true + + configs = [] + + configs += device_profile_configs + + include_dirs = [ + "include", + "//third_party/json/include", + ] + + sources = [ + "${device_profile_path}/tools/dp/src/dp_command.cpp", + "${device_profile_path}/tools/dp/src/main.cpp", + "${device_profile_path}/tools/dp/src/shell_command.cpp", + ] + + deps = [ + "${device_profile_innerkits}/device_profile_core:distributed_device_profile_client", + "//utils/native/base:utils", + ] + + external_deps = [ + "dsoftbus_standard:softbus_client", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + part_name = "device_profile_core" + subsystem_name = "deviceprofile" +} diff --git a/tools/dp/include/dp_command.h b/tools/dp/include/dp_command.h new file mode 100755 index 0000000000000000000000000000000000000000..402cc1a15a7ada079dce42c090966664ff6d8d17 --- /dev/null +++ b/tools/dp/include/dp_command.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DEVICE_PROFILE_DP_COMMAND_H +#define DEVICE_PROFILE_DP_COMMAND_H + +#include "shell_command.h" + +#include + +#include "device_profile_log.h" +#include "iprofile_event_callback.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "DpShellCommand"; +const std::string DP_TOOL_NAME = "dp"; +const std::string DP_HELP_MSG = "usage: dp \n" + "These are common dp commands list:\n" + " help list available commands\n" + " getDevice list all devices\n" + " query query device info with options\n" + " put put device info with options\n" + " sync sync device info with options\n" + " delete delete device info with options\n" + " subscribe subscribe device info with options\n"; +const std::string HELP_MSG_QUERY = + "usage: dp query \n" + "options list:\n" + " -h, --help list available commands\n" + " -d query device info by a device id\n" + " -s query device info by a service id\n"; +const std::string HELP_MSG_SYNC = + "usage: dp sync \n" + "options list:\n" + " -h, --help list available commands\n" + " -d sync device info by a device ids\n" + " -m sync device info by mode\n"; +const std::string HELP_MSG_PUT = + "usage: dp put \n" + "options list:\n" + " -h, --help list available commands\n" + " -s put device info by service id\n" + " -t put device info by service type\n"; +const std::string HELP_MSG_SUBSCRIBE = + "usage: dp subscribe \n" + "options list:\n" + " -h, --help list available commands\n" + " -s subscribe device info by service ids\n" + " -d subscribe device info by device id\n"; +} // namespace + +class DpShellCommand : public OHOS::DeviceProfile::ShellCommand { +public: + DpShellCommand(int argc, char *argv[]); + ~DpShellCommand() override {} + +private: + ErrCode CreateCommandMap() override; + ErrCode CreateMessageMap() override; + ErrCode init() override; + + ErrCode HelpCommand(); + ErrCode GetDeviceCommand(); + ErrCode QueryCommand(); + ErrCode PutCommand(); + ErrCode DeleteCommand(); + ErrCode SyncCommand(); + ErrCode SubscribeCommand(); + + int32_t HandleUnknownOption(const char optopt); + int32_t HandleNormalOption(const int option, std::string& deviceId, + std::string& serviceId, std::string& serviceType); + int32_t HandleSyncOption(const int option, std::string& mode, + std::list& deviceIds); + int32_t HandleSubscribeOption(const int option, std::string& deviceId, + std::list& serviceIds); +}; + +class ProfileEventCallback : public IProfileEventCallback { +public: + void OnSyncCompleted(const SyncResult& syncResults) override + { + HILOGI("OnSyncCompleted"); + } + + void OnProfileChanged(const ProfileChangeNotification& changeNotification) override + { + HILOGI("OnProfileChanged"); + } +}; +} // namespace DeviceProfile +} // namespace OHOS + +#endif // DEVICE_PROFILE_DP_COMMAND_H \ No newline at end of file diff --git a/tools/dp/include/shell_command.h b/tools/dp/include/shell_command.h new file mode 100755 index 0000000000000000000000000000000000000000..8c8e783d3a23179753b21d2b4d2331d3c1c39ec0 --- /dev/null +++ b/tools/dp/include/shell_command.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DEVICE_PROFILE_SHELL_COMMAND_H +#define DEVICE_PROFILE_SHELL_COMMAND_H + +#include +#include +#include +#include + +#include "utils/native/base/include/errors.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string HELP_MSG_NO_OPTION = "error: you must specify an option at least."; +const int OFFSET_REQUIRED_ARGUMENT = 2; +} // namespace + +class ShellCommand { +public: + ShellCommand(int argc, char *argv[], std::string name); + virtual ~ShellCommand() = default; + + ErrCode OnCommand(); + std::string ExecCommand(); + std::string GetCommandErrorMsg() const; + std::string GetUnknownOptionMsg(std::string &unknownOption) const; + std::string GetMessageFromCode(const int32_t code) const; + + virtual ErrCode CreateCommandMap() = 0; + virtual ErrCode CreateMessageMap() = 0; + virtual ErrCode init() = 0; + +protected: + static constexpr int MIN_ARGUMENT_NUMBER = 2; + + int argc_; + char **argv_; + + std::string cmd_; + std::vector argList_; + + std::string name_; + std::map> commandMap_; + std::map messageMap_; + + std::string resultReceiver_ = ""; +}; +} // namespace DeviceProfile +} // namespace OHOS + +#endif // DEVICE_PROFILE_SHELL_COMMAND_H \ No newline at end of file diff --git a/tools/dp/src/dp_command.cpp b/tools/dp/src/dp_command.cpp new file mode 100755 index 0000000000000000000000000000000000000000..2aa9af9d008e2dd9eae800148e6ac8aa545d3933 --- /dev/null +++ b/tools/dp/src/dp_command.cpp @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "dp_command.h" + +#include +#include +#include + +#include "device_profile_log.h" +#include "distributed_device_profile_client.h" +#include "nlohmann/json.hpp" +#include "softbus_bus_center.h" +#include "subscribe_info.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +constexpr int32_t API_LEVEL = 7; +constexpr int32_t SYNC_SLEEP_TIME = 10; +constexpr int32_t SUBSCRIBE_SLEEP_TIME = 120; +const std::string SHORT_OPTIONS = "hd:s:m:t:"; +const struct option LONG_OPTIONS[] = { + {"help", no_argument, nullptr, 'h'}, + {"device-id", required_argument, nullptr, 'd'}, + {"service-id", required_argument, nullptr, 's'}, + {"mode", required_argument, nullptr, 'm'}, + {"service-type", required_argument, nullptr, 't'}, + {0, 0, 0, 0}, +}; +} +DpShellCommand::DpShellCommand(int argc, char *argv[]) : ShellCommand(argc, argv, DP_TOOL_NAME) +{ +} + +ErrCode DpShellCommand::init() +{ + return ERR_OK; +} + +ErrCode DpShellCommand::CreateCommandMap() +{ + commandMap_ = { + {"help", std::bind(&DpShellCommand::HelpCommand, this)}, + {"getDevice", std::bind(&DpShellCommand::GetDeviceCommand, this)}, + {"query", std::bind(&DpShellCommand::QueryCommand, this)}, + {"put", std::bind(&DpShellCommand::PutCommand, this)}, + {"delete", std::bind(&DpShellCommand::DeleteCommand, this)}, + {"sync", std::bind(&DpShellCommand::SyncCommand, this)}, + {"subscribe", std::bind(&DpShellCommand::SubscribeCommand, this)}, + }; + return ERR_OK; +} + +ErrCode DpShellCommand::CreateMessageMap() +{ + messageMap_ = {}; + return ERR_OK; +} + +ErrCode DpShellCommand::HelpCommand() +{ + resultReceiver_.append(DP_HELP_MSG); + return ERR_OK; +} + +ErrCode DpShellCommand::GetDeviceCommand() +{ + resultReceiver_.append("[remote device list]\n"); + NodeBasicInfo *info = NULL; + int32_t infoNum = 0; + int32_t ret = GetAllNodeDeviceInfo("dp", &info, &infoNum); + if (ret != ERR_OK) { + resultReceiver_.append("get remote device list error\n"); + return ret; + } + for (int32_t i = 0; i < infoNum; i++) { + resultReceiver_.append("networkId: " + std::string(info->networkId) + + " deviceName:" + std::string(info->deviceName) + "\n"); + info++; + } + + resultReceiver_.append("[local device list]\n"); + NodeBasicInfo localInfo; + ret = GetLocalNodeDeviceInfo("dp", &localInfo); + if (ret != ERR_OK) { + resultReceiver_.append("get local device error\n"); + return ret; + } + resultReceiver_.append("networkId: " + std::string(localInfo.networkId) + + " deviceName:" + std::string(localInfo.deviceName) + "\n"); + return ERR_OK; +} + +ErrCode DpShellCommand::QueryCommand() +{ + int32_t result = ERR_OK; + std::string serviceType; + std::string deviceId; + std::string serviceId; + while (true) { + int option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr); + HILOGI("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind); + if (optind < 0 || optind > argc_) { + return OHOS::ERR_INVALID_VALUE; + } + + if (option == -1) { + break; + } + result = HandleNormalOption(option, deviceId, serviceId, serviceType); + } + + if (result == ERR_OK) { + ServiceCharacteristicProfile profile; + DistributedDeviceProfileClient::GetInstance().GetDeviceProfile(deviceId, serviceId, profile); + std::string jsonData = profile.GetCharacteristicProfileJson(); + resultReceiver_.append("ServiceId:" + profile.GetServiceId() + "\n"); + resultReceiver_.append("ServiceType:" + profile.GetServiceType() + "\n"); + resultReceiver_.append("jsonData:" + jsonData + "\n"); + } else { + resultReceiver_.append(HELP_MSG_QUERY); + } + return result; +} + +ErrCode DpShellCommand::PutCommand() +{ + int32_t result = ERR_OK; + std::string serviceType; + std::string serviceId; + std::string deviceId; + while (true) { + int option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr); + HILOGI("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind); + if (optind < 0 || optind > argc_) { + return OHOS::ERR_INVALID_VALUE; + } + if (option == -1) { + break; + } + result = HandleNormalOption(option, deviceId, serviceId, serviceType); + } + + if (result == ERR_OK) { + ServiceCharacteristicProfile profile; + profile.SetServiceId(serviceId); + profile.SetServiceType(serviceType); + nlohmann::json j; + j["testVersion"] = "3.0.0"; + j["testApiLevel"] = API_LEVEL; + profile.SetCharacteristicProfileJson(j.dump()); + DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile); + } else { + resultReceiver_.append(HELP_MSG_PUT); + } + return result; +} + +ErrCode DpShellCommand::DeleteCommand() +{ + return ERR_OK; +} + +ErrCode DpShellCommand::SyncCommand() +{ + int32_t result = ERR_OK; + std::list deviceIds; + std::string mode; + while (true) { + int option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr); + HILOGI("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind); + if (optind < 0 || optind > argc_) { + return OHOS::ERR_INVALID_VALUE; + } + + if (option == -1) { + break; + } + result = HandleSyncOption(option, mode, deviceIds); + } + + if (result == ERR_OK) { + SyncOptions syncOption; + syncOption.SetSyncMode((OHOS::DistributedKv::SyncMode)atoi(mode.c_str())); + for (const auto& deviceId : deviceIds) { + syncOption.AddDevice(deviceId); + } + DistributedDeviceProfileClient::GetInstance().SyncDeviceProfile(syncOption, + std::make_shared()); + sleep(SYNC_SLEEP_TIME); + HILOGI("sync end"); + } else { + resultReceiver_.append(HELP_MSG_SYNC); + } + return result; +} + +ErrCode DpShellCommand::SubscribeCommand() +{ + int32_t result = ERR_OK; + std::list serviceIds; + std::string deviceId; + while (true) { + int option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr); + HILOGI("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind); + if (optind < 0 || optind > argc_) { + return OHOS::ERR_INVALID_VALUE; + } + + if (option == -1) { + break; + } + result = HandleSubscribeOption(option, deviceId, serviceIds); + } + + if (result == ERR_OK) { + auto callback = std::make_shared(); + std::list subscribeInfos; + ExtraInfo extraInfo; + extraInfo["deviceId"] = deviceId; + extraInfo["serviceIds"] = serviceIds; + + SubscribeInfo info1; + info1.profileEvent = ProfileEvent::EVENT_PROFILE_CHANGED; + info1.extraInfo = std::move(extraInfo); + subscribeInfos.emplace_back(info1); + + SubscribeInfo info2; + info2.profileEvent = ProfileEvent::EVENT_SYNC_COMPLETED; + info2.extraInfo = std::move(extraInfo); + subscribeInfos.emplace_back(info2); + + std::list failedEvents; + DistributedDeviceProfileClient::GetInstance().SubscribeProfileEvents(subscribeInfos, callback, failedEvents); + sleep(SUBSCRIBE_SLEEP_TIME); + std::list profileEvents; + profileEvents.emplace_back(ProfileEvent::EVENT_PROFILE_CHANGED); + failedEvents.clear(); + DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvents(profileEvents, callback, failedEvents); + sleep(SYNC_SLEEP_TIME); + } else { + resultReceiver_.append(HELP_MSG_SUBSCRIBE); + } + return result; +} + +int32_t DpShellCommand::HandleNormalOption(const int option, std::string& deviceId, + std::string& serviceId, std::string& serviceType) +{ + HILOGI("%{public}s start, option: %{public}d", __func__, option); + int32_t result = ERR_OK; + switch (option) { + case 'h': { + HILOGI("'dp query' %{public}s", argv_[optind - 1]); + result = OHOS::ERR_INVALID_VALUE; + break; + } + case 'd': { + if (optarg == nullptr) { + resultReceiver_.append("error: option, requires a value\n"); + result = OHOS::ERR_INVALID_VALUE; + break; + } + deviceId = optarg; + break; + } + case 's': { + if (optarg == nullptr) { + resultReceiver_.append("error: option, requires a value\n"); + result = OHOS::ERR_INVALID_VALUE; + break; + } + serviceId = optarg; + break; + } + case 't': { + if (optarg == nullptr) { + resultReceiver_.append("error: option, requires a value\n"); + result = OHOS::ERR_INVALID_VALUE; + break; + } + serviceType = optarg; + break; + } + default: { + result = OHOS::ERR_INVALID_VALUE; + HILOGE("'dp query' invalid option."); + break; + } + } + return result; +} + +int32_t DpShellCommand::HandleSyncOption(const int option, std::string& mode, std::list& deviceIds) +{ + HILOGI("%{public}s start, option: %{public}d", __func__, option); + int32_t result = ERR_OK; + switch (option) { + case 'h': { + HILOGI("'dp sync' %{public}s", argv_[optind - 1]); + result = OHOS::ERR_INVALID_VALUE; + break; + } + case 'd': { + if (optarg == nullptr) { + resultReceiver_.append("error: option, requires a value\n"); + result = OHOS::ERR_INVALID_VALUE; + break; + } + std::stringstream input(optarg); + std::string temp; + while (std::getline(input, temp, ' ')) { + HILOGI("deviceIds: %{public}s", temp.c_str()); + deviceIds.push_back(temp); + } + break; + } + case 'm': { + if (optarg == nullptr) { + resultReceiver_.append("error: option, requires a value\n"); + result = OHOS::ERR_INVALID_VALUE; + break; + } + mode = optarg; + break; + } + default: { + result = OHOS::ERR_INVALID_VALUE; + HILOGE("'dp sync' invalid option."); + break; + } + } + return result; +} + +int32_t DpShellCommand::HandleSubscribeOption(const int option, std::string& deviceId, + std::list& serviceIds) +{ + HILOGI("%{public}s start, option: %{public}d", __func__, option); + int32_t result = ERR_OK; + switch (option) { + case 'h': { + HILOGI("'dp subscribe' %{public}s", argv_[optind - 1]); + result = OHOS::ERR_INVALID_VALUE; + break; + } + case 's': { + if (optarg == nullptr) { + resultReceiver_.append("error: option, requires a value\n"); + result = OHOS::ERR_INVALID_VALUE; + break; + } + std::stringstream input(optarg); + std::string temp; + while (std::getline(input, temp, ' ')) { + HILOGI("deviceIds: %{public}s", temp.c_str()); + serviceIds.push_back(temp); + } + break; + } + case 'd': { + if (optarg == nullptr) { + resultReceiver_.append("error: option, requires a value\n"); + result = OHOS::ERR_INVALID_VALUE; + break; + } + deviceId = optarg; + break; + } + default: { + result = OHOS::ERR_INVALID_VALUE; + HILOGE("'dp subscribe' invalid option."); + break; + } + } + return result; +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file diff --git a/tools/dp/src/main.cpp b/tools/dp/src/main.cpp new file mode 100755 index 0000000000000000000000000000000000000000..60991b97021d1c063bd2d9f0899711b1f336af6a --- /dev/null +++ b/tools/dp/src/main.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dp_command.h" + +#include + +using namespace std; +using namespace OHOS::DeviceProfile; + +int main(int argc, char *argv[]) +{ + DpShellCommand cmd(argc, argv); + std::cout << cmd.ExecCommand(); + return 0; +} \ No newline at end of file diff --git a/tools/dp/src/shell_command.cpp b/tools/dp/src/shell_command.cpp new file mode 100755 index 0000000000000000000000000000000000000000..e21999f0d89884954206df56ae68e5a52e52675b --- /dev/null +++ b/tools/dp/src/shell_command.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "shell_command.h" + +#include +#include "device_profile_log.h" + +namespace OHOS { +namespace DeviceProfile { +namespace { +const std::string TAG = "ShellCommand"; +} + +ShellCommand::ShellCommand(int argc, char *argv[], std::string name) +{ + opterr = 0; + argc_ = argc; + argv_ = argv; + name_ = name; + + if (argc < MIN_ARGUMENT_NUMBER) { + cmd_ = "help"; + return; + } + cmd_ = argv[1]; + for (int i = 2; i < argc; i++) { + argList_.push_back(argv[i]); + } +} + +ErrCode ShellCommand::OnCommand() +{ + int result = ERR_OK; + + auto respond = commandMap_[cmd_]; + if (respond == nullptr) { + resultReceiver_.append(GetCommandErrorMsg()); + respond = commandMap_["help"]; + } + + if (init() == ERR_OK) { + respond(); + } else { + result = OHOS::ERR_INVALID_VALUE; + } + + return result; +} + +std::string ShellCommand::ExecCommand() +{ + int result = CreateCommandMap(); + if (result != ERR_OK) { + HILOGE("failed to create command map.\n"); + } + + result = CreateMessageMap(); + if (result != ERR_OK) { + HILOGE("failed to create message map.\n"); + } + + result = OnCommand(); + if (result != ERR_OK) { + HILOGE("failed to execute your command.\n"); + resultReceiver_ = "error: failed to execute your command.\n"; + } + + return resultReceiver_; +} + +std::string ShellCommand::GetCommandErrorMsg() const +{ + std::string commandErrorMsg = + name_ + ": '" + cmd_ + "' is not a valid " + name_ + " command. See '" + name_ + " help'.\n"; + return commandErrorMsg; +} + +std::string ShellCommand::GetUnknownOptionMsg(std::string &unknownOption) const +{ + std::string result = ""; + + if (optind < 0 || optind > argc_) { + return result; + } + + result.append("error: unknown option"); + result.append(".\n"); + return result; +} + +std::string ShellCommand::GetMessageFromCode(const int32_t code) const +{ + HILOGI("[%{public}s(%{public}s)] enter", __FILE__, __FUNCTION__); + HILOGI("code = %{public}d", code); + + std::string result = ""; + if (messageMap_.find(code) != messageMap_.end()) { + std::string message = messageMap_.at(code); + if (message.size() != 0) { + result.append(message + "\n"); + } + } + HILOGI("result = %{public}s", result.c_str()); + return result; +} +} // namespace DeviceProfile +} // namespace OHOS \ No newline at end of file