diff --git a/datamgr_service/services/distributeddataservice/service/BUILD.gn b/datamgr_service/services/distributeddataservice/service/BUILD.gn index d05b54c5fdb61e21d692e98f5549b6bfe23f6569..4ea16865ffda2d21a391d711ab9e215f3534cd69 100644 --- a/datamgr_service/services/distributeddataservice/service/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/BUILD.gn @@ -30,6 +30,7 @@ config("module_public_config") { "object", "permission/include", "rdb", + "wlmatrix/include", "//third_party/json/single_include", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/include", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/app/src", @@ -101,6 +102,19 @@ ohos_shared_library("distributeddatasvc") { "rdb/rdb_service_stub.cpp", "rdb/rdb_store_observer_impl.cpp", "rdb/rdb_syncer.cpp", + "wlmatrix/src/devices_simulator.cpp", + "wlmatrix/src/local_device_status_listener.cpp", + "wlmatrix/src/mock_database.cpp", + "wlmatrix/src/status_statistic.cpp", + "wlmatrix/src/sub_waterlevel_matrix.cpp", + "wlmatrix/src/sync_matrix.cpp", + "wlmatrix/src/sysdatasync_service.cpp", + "wlmatrix/src/sysdatasync_strategy.cpp", + "wlmatrix/src/waterlevel_matrix.cpp", + "wlmatrix/src/wlmatrix_helper.cpp", + "wlmatrix/src/wlsync_scheduler.cpp", + "wlmatrix/src/wlsync_service.cpp", + "wlmatrix/src/wlsync_strategy.cpp", ] cflags = [ "-Wno-multichar" ] diff --git a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt index a90fab7b223e75ea8417a95181b4ffbee5cf975f..03606d0f0dd3b0995f6dd379704fd20208dee5ac 100644 --- a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt @@ -19,6 +19,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/crypto/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/rdb serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/kvdb serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/matrix/src serviceSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/wlmatrix/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/object serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/data_share serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/permission/src serviceSrc) @@ -30,6 +31,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/directory/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/permission/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/matrix/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/wlmatrix/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/rdb) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/kvdb) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../framework/include) diff --git a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn index 70ad6fddbf99bd05d4b6dbd047e361a6af889c04..a983b691055350753e5ba0430bda7aa89aa4a22a 100644 --- a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn @@ -27,6 +27,7 @@ config("module_private_config") { "../directory/include/", "../matrix/include/", "../../framework/include/", + "../wlmatrix/include/", ] defines = [ @@ -139,6 +140,66 @@ ohos_unittest("DeviceMatrixTest") { ] } +ohos_unittest("WaterLevelMatrixTest") { + module_out_path = module_output_path + sources = [ + + "wlmatrix_test.cpp", + "device_simulator_test.cpp", + "mock/db_change_data_mock.cpp", + "mock/db_store_mock.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + deps = [ + "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter:distributeddata_adapter", + "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", + "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", + "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", + "//third_party/googletest:gtest_main", + ] +} + +ohos_unittest("DeviceSimulatorTest") { + module_out_path = module_output_path + sources = [ + "device_simulator_test.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + deps = [ + "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter:distributeddata_adapter", + "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", + "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", + "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", + "//third_party/googletest:gtest_main", + ] +} + ############################################################################### group("unittest") { testonly = true @@ -149,6 +210,8 @@ group("unittest") { ":ConfigFactoryTest", ":CryptoManagerTest", ":DeviceMatrixTest", + ":WaterLevelMatrixTest", + ":DeviceSimulatorTest", ":DirectoryManagerTest", ] } diff --git a/datamgr_service/services/distributeddataservice/service/test/device_simulator_test.cpp b/datamgr_service/services/distributeddataservice/service/test/device_simulator_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d87c99ae77e8d8267c86626ce38f359f1712f104 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/device_simulator_test.cpp @@ -0,0 +1,341 @@ +/* +* Copyright (c) 2022 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 "devices_simulator.h" +#include "gtest/gtest.h" +#include "wlmatrix_config.h" +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::DistributedData; + +class DevicesSimulatorTest : public testing::Test { +public: + void SetUp(); + void TearDown(); + + bool StringContain(std::string inputStr, std::string subStr); + int GetLastVectorPerfIndex(std::vector perfVec, int pos); +}; + +void DevicesSimulatorTest::SetUp() {} + +void DevicesSimulatorTest::TearDown() {} + +bool DevicesSimulatorTest::StringContain(std::string inputStr, std::string subStr) +{ + return inputStr.find(subStr) != std::string::npos; +} + +int DevicesSimulatorTest::GetLastVectorPerfIndex(std::vector perfVec, int pos) +{ + if (pos < perfVec.size()) { + return atoi(perfVec[perfVec.size() - pos].c_str()); + } + return -1; +} + +/** +* @tc.name: DeviceSimulatorInitTest +* @tc.desc: Init & GetDeviceList test of DeviceSimulator; +* @tc.type: input test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(DevicesSimulatorTest, InitInputTest, TestSize.Level0) +{ + DevicesSimulator simulator; + + // case 1: invalid input, too large deviceNum + std::int32_t invalidDeviceNum = MAX_DEVICE_NUM + 1; + simulator.Init(invalidDeviceNum); + EXPECT_TRUE(simulator.GetDeviceList().empty()); + + // case 2: valid deviceNum + std::int32_t validDeviceNum = 5; + simulator.Init(validDeviceNum); + EXPECT_FALSE(simulator.GetDeviceList().empty()); + + /* + * case 3 & 4: init while the device list is not empty + * current simulator has contained some devices, + * after executing case 2, the simulator is not empty + * */ + std::int32_t addDeviceNumLess = validDeviceNum - 1; + simulator.Init(addDeviceNumLess); + EXPECT_NE(simulator.GetDeviceList().size(), addDeviceNumLess); + + std::int32_t addDeviceNumLarge = validDeviceNum + 1; + simulator.Init(addDeviceNumLarge); + EXPECT_EQ(simulator.GetDeviceList().size(), addDeviceNumLarge); +} + +/** +* @tc.name: DeviceStatusSettingTest +* @tc.desc: SetDeviceActive/SetDeviceOffline/SetDeviceSleep test of DeviceSimulator; +* @tc.type: input test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(DevicesSimulatorTest, DeviceSettingTest, TestSize.Level0) +{ + DevicesSimulator simulator; + std::int32_t defaultDeviceNum = 5; + simulator.Init(defaultDeviceNum); + std::string validDeviceName = simulator.GetDeviceList()[0]; + std::string invalidDeviceName = "InvalidDevice"; + + simulator.SetDeviceActive(validDeviceName); + EXPECT_EQ(simulator.GetDeviceStatus(validDeviceName), (std::int32_t)WlDeviceStatus::WL_DEVICE_ACTIVE); + simulator.SetDeviceSleep(validDeviceName); + EXPECT_EQ(simulator.GetDeviceStatus(validDeviceName), (std::int32_t)WlDeviceStatus::WL_DEVICE_SLEEP); + simulator.SetDeviceOffline(validDeviceName); + EXPECT_EQ(simulator.GetDeviceStatus(validDeviceName), (std::int32_t)WlDeviceStatus::WL_DEVICE_OFFLINE); + + // expect -1 + simulator.SetDeviceActive(invalidDeviceName); + EXPECT_EQ(simulator.GetDeviceStatus(invalidDeviceName), -1); + simulator.SetDeviceSleep(invalidDeviceName); + EXPECT_EQ(simulator.GetDeviceStatus(invalidDeviceName), -1); + simulator.SetDeviceOffline(invalidDeviceName); + EXPECT_EQ(simulator.GetDeviceStatus(invalidDeviceName), -1); +} + +/** +* @tc.name: DeviceDataGeneTest +* @tc.desc: DeviceDataGene test of DeviceSimulator; +* @tc.type: input test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(DevicesSimulatorTest, DeviceDataGeneTest, TestSize.Level0) +{ + DevicesSimulator simulator; + std::int32_t defaultDeviceNum = 5; + simulator.Init(defaultDeviceNum); + std::string validDeviceName = simulator.GetDeviceList()[0]; + std::string invalidDeviceName = "InvalidDevice"; + + std::uint8_t validApp = 5; + std::uint8_t uninstalledApp = 35; + std::uint8_t defaultDtype = 0; + + simulator.SetDeviceDataGene(invalidDeviceName, uninstalledApp, defaultDtype); + EXPECT_FALSE(DevicesSimulatorTest::StringContain(simulator.DisplayDeviceDatabase(invalidDeviceName), ": 20")); + + simulator.SetDeviceDataGene(invalidDeviceName, validApp, defaultDtype); + EXPECT_FALSE(DevicesSimulatorTest::StringContain(simulator.DisplayDeviceDatabase(invalidDeviceName), ": 20")); + + simulator.SetDeviceDataGene(validDeviceName, uninstalledApp, defaultDtype); + EXPECT_FALSE(DevicesSimulatorTest::StringContain(simulator.DisplayDeviceDatabase(validDeviceName), ": 20")); + + simulator.SetDeviceDataGene(validDeviceName, validApp, defaultDtype); + EXPECT_TRUE(DevicesSimulatorTest::StringContain(simulator.DisplayDeviceDatabase(validDeviceName), ": 20")); +} + +/** +* @tc.name: DeviceDataConsTest +* @tc.desc: DeviceDataCons test of DeviceSimulator; +* @tc.type: input test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(DevicesSimulatorTest, DeviceDataConsTest, TestSize.Level0) +{ + DevicesSimulator simulator; + std::int32_t defaultDeviceNum = 5; + simulator.Init(defaultDeviceNum); + std::string validDeviceName = simulator.GetDeviceList()[0]; // active device + std::string validSleepDeviceName = simulator.GetDeviceList()[3]; // sleep device + std::string invalidDeviceName = "InvalidDevice"; + + std::uint8_t pullApp = 8; + std::uint8_t pushApp = 101; + + std::int32_t pull_b = DevicesSimulatorTest::GetLastVectorPerfIndex(simulator.DisplayPerformanceIndexList(), 3); + simulator.SetDeviceDataCons(validDeviceName, pullApp); + std::int32_t pull_a = DevicesSimulatorTest::GetLastVectorPerfIndex(simulator.DisplayPerformanceIndexList(), 3); + EXPECT_GE(pull_a, pull_b); + + std::int32_t pull_b_2 = DevicesSimulatorTest::GetLastVectorPerfIndex(simulator.DisplayPerformanceIndexList(), 3); + simulator.SetDeviceDataCons(validSleepDeviceName, pullApp); + simulator.SetDeviceDataCons(invalidDeviceName, pullApp); + std::int32_t pull_a_2 = DevicesSimulatorTest::GetLastVectorPerfIndex(simulator.DisplayPerformanceIndexList(), 3); + EXPECT_EQ(pull_a_2, pull_b_2); + + std::int32_t push_b = DevicesSimulatorTest::GetLastVectorPerfIndex(simulator.DisplayPushPerfIndexList(), 4); + simulator.SetDeviceDataCons(validDeviceName, pushApp); + std::int32_t push_a = DevicesSimulatorTest::GetLastVectorPerfIndex(simulator.DisplayPushPerfIndexList(), 4); + EXPECT_GE(push_a, push_b); + + std::int32_t push_b_2 = DevicesSimulatorTest::GetLastVectorPerfIndex(simulator.DisplayPushPerfIndexList(), 4); + simulator.SetDeviceDataCons(invalidDeviceName, pushApp); + std::int32_t push_a_2 = DevicesSimulatorTest::GetLastVectorPerfIndex(simulator.DisplayPushPerfIndexList(), 4); + EXPECT_EQ(push_a_2, push_b_2); +} + +/** +* @tc.name: SetDeviceInstalledAppTest +* @tc.desc: SetDeviceInstalledApp test of DeviceSimulator; +* @tc.type: input test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(DevicesSimulatorTest, SetDeviceInstalledAppTest, TestSize.Level0) +{ + DevicesSimulator simulator; + std::int32_t defaultDeviceNum = 5; + simulator.Init(defaultDeviceNum); + std::string validDeviceName = simulator.GetDeviceList()[0]; // active device + std::string invalidDeviceName = "InvalidDevice"; + + std::uint8_t appId = 21; + + size_t beforeAppNum = simulator.GetDeviceInstalledApps(validDeviceName).size(); + simulator.SetDeviceInstalledApp(validDeviceName, appId); + size_t afterAppNum = simulator.GetDeviceInstalledApps(validDeviceName).size(); + EXPECT_EQ(beforeAppNum + 1, afterAppNum); + + size_t beforeAppNum_invalid = simulator.GetDeviceInstalledApps(validDeviceName).size(); + simulator.SetDeviceInstalledApp(invalidDeviceName, appId); + size_t afterAppNum_invalid = simulator.GetDeviceInstalledApps(validDeviceName).size(); + EXPECT_EQ(beforeAppNum_invalid, afterAppNum_invalid); +} + +/** +* @tc.name: DisplayInfoTest +* @tc.desc: Display functions test of DeviceSimulator; +* @tc.type: input test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(DevicesSimulatorTest, DisplayInfoTest, TestSize.Level0) +{ + DevicesSimulator simulator; + std::int32_t defaultDeviceNum = 5; + simulator.Init(defaultDeviceNum); + std::string validDeviceName = simulator.GetDeviceList()[0]; // active device + std::string invalidDeviceName = "InvalidDevice"; + + // DisplayDeviceDatabase + EXPECT_FALSE(simulator.DisplayDeviceDatabase(validDeviceName).empty()); + EXPECT_TRUE(simulator.DisplayDeviceDatabase(invalidDeviceName).empty()); + + // DisplayDeviceWaterLevelMatrix + EXPECT_FALSE(simulator.DisplayDeviceWaterLevelMatrix(validDeviceName).empty()); + EXPECT_TRUE(simulator.DisplayDeviceWaterLevelMatrix(invalidDeviceName).empty()); + + // DisplayDeviceSyncMatrix + EXPECT_FALSE(simulator.DisplayDeviceSyncMatrix(validDeviceName).empty()); + EXPECT_TRUE(simulator.DisplayDeviceSyncMatrix(invalidDeviceName).empty()); + + // DisplayDeviceInstalledApp + EXPECT_FALSE(simulator.DisplayDeviceInstalledApp(validDeviceName).empty()); + EXPECT_TRUE(simulator.DisplayDeviceInstalledApp(invalidDeviceName).empty()); + + // DisplayPerformanceIndexList + EXPECT_FALSE(simulator.DisplayPerformanceIndexList().empty()); + + // DisplayPushPerfIndexList + EXPECT_FALSE(simulator.DisplayPerformanceIndexList().empty()); +} + +/** +* @tc.name: AutoTestTest +* @tc.desc: auto test of DeviceSimulator; +* @tc.type: input test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(DevicesSimulatorTest, AutoTestTest, TestSize.Level0) +{ + DevicesSimulator simulator; + std::int32_t defaultDeviceNum = 5; + simulator.Init(defaultDeviceNum); + + std::int32_t autoTestNum = 100; + simulator.AutoTestCase(autoTestNum); + + std::vector perfRes = simulator.DisplayPerformanceIndexList(); + std::int32_t pull_error = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 1); + std::int32_t actuallyAutoTestNum = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 3); + std::int32_t awake_ours = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 6); + std::int32_t awake_baseline = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 7); + + EXPECT_GE(actuallyAutoTestNum, autoTestNum); + EXPECT_LE((double)pull_error / (double)actuallyAutoTestNum, 0.05); + EXPECT_LE((double)awake_ours / (double)awake_baseline, 0.5); + + simulator.ClearDeviceSimulator(); + EXPECT_TRUE(simulator.GetDeviceList().empty()); + + simulator.Init(defaultDeviceNum); + simulator.AutoTestCase2(autoTestNum); + perfRes = simulator.DisplayPerformanceIndexList(); + pull_error = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 1); + actuallyAutoTestNum = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 3); + awake_ours = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 6); + awake_baseline = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 7); + + EXPECT_GE(actuallyAutoTestNum, autoTestNum); + EXPECT_LE((double)pull_error / (double)actuallyAutoTestNum, 0.05); + EXPECT_LE((double)awake_ours / (double)awake_baseline, 0.5); + + simulator.ClearDeviceSimulator(); + EXPECT_TRUE(simulator.GetDeviceList().empty()); + + simulator.Init(defaultDeviceNum); + WlAIMDFactor wlAimdFactor = { + .InitDelay = 0.5, + .AIFactor = 0.2, + .MDFactor = 3.0, + .mFactor = 0.1, + .DelayUpBound = 10.0, + }; + simulator.SetWlAIMDFactor(wlAimdFactor); + simulator.PushAutoTestCase(100, 2000, 3000, 0.5); + perfRes = simulator.DisplayPushPerfIndexList(); + std::int32_t geneNum = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 1); + std::int32_t push_error = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 3); + std::int32_t push_count = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 4); + awake_ours = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 6); + awake_baseline = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 7); + + EXPECT_GE(geneNum, autoTestNum); + EXPECT_LE((double)push_error / (double)push_count, 0.03); + EXPECT_LE((double)awake_ours / (double)awake_baseline, 0.5); + + simulator.ClearDeviceSimulator(); + EXPECT_TRUE(simulator.GetDeviceList().empty()); + + simulator.Init(defaultDeviceNum); + WlAIMDFactor wlAimdFactor2 = { + .InitDelay = 1.0, + .AIFactor = 0.2, + .MDFactor = 3.0, + .mFactor = 0.1, + .DelayUpBound = 10.0, + }; + simulator.SetWlAIMDFactor(wlAimdFactor2); + simulator.PushAutoTestCase2(100, 2000, 3000, 2); + perfRes = simulator.DisplayPushPerfIndexList(); + geneNum = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 1); + push_error = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 3); + push_count = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 4); + awake_ours = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 6); + awake_baseline = DevicesSimulatorTest::GetLastVectorPerfIndex(perfRes, 7); + + EXPECT_GE(geneNum, autoTestNum); + EXPECT_LE((double)push_error / (double)push_count, 0.03); + EXPECT_LE((double)awake_ours / (double)awake_baseline, 0.5); +} diff --git a/datamgr_service/services/distributeddataservice/service/test/wlmatrix_test.cpp b/datamgr_service/services/distributeddataservice/service/test/wlmatrix_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ef0bd71a47ba3e6281e5c7b0d87296fc7dbd522 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/wlmatrix_test.cpp @@ -0,0 +1,327 @@ +/* +* Copyright (c) 2022 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 "local_device_status_listener.h" +#include "wlmatrix_config.h" +#include "gtest/gtest.h" +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::DistributedData; +class WlMatrixTest : public testing::Test { +public: + void SetUp(); + void TearDown(); +}; + +void WlMatrixTest::SetUp() {} + +void WlMatrixTest::TearDown() {} +/** +* @tc.name: OnPowerOnErrorTest +* @tc.desc: OnPowerOn test for error code; +* @tc.type: Error code test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(WlMatrixTest, OnPowerOnErrorTest, TestSize.Level0) +{ + LocalDeviceStatusListener localDevice; + std::string deviceName = "TestDevice"; + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_SLEEP, + .installedApps = { 1, 2 }, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + localDevice.Init(deviceName, wlDeviceInfo); + + localDevice.OnPowerOn(); +} + +/** +* @tc.name: OnPowerOffErrorTest +* @tc.desc: OnPowerOff test for error code; +* @tc.type: Error code test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(WlMatrixTest, OnPowerOffErrorTest, TestSize.Level0) +{ + LocalDeviceStatusListener localDevice; + std::string deviceName = "TestDevice"; + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_SLEEP, + .installedApps = { 1, 2 }, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + localDevice.Init(deviceName, wlDeviceInfo); + + localDevice.OnPowerOff(); +} + +/** +* @tc.name: OnChangeAsleepErrorTest +* @tc.desc: OnChangeAsleep test for error code; +* @tc.type: Error code test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(WlMatrixTest, OnChangeAsleepErrorTest, TestSize.Level0) +{ + LocalDeviceStatusListener localDevice; + std::string deviceName = "TestDevice"; + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_SLEEP, + .installedApps = { 1, 2 }, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + localDevice.Init(deviceName, wlDeviceInfo); + + localDevice.OnChangeAsleep(); +} + +/** +* @tc.name: OnDataConsumingErrorTestCase01 +* @tc.desc: OnDataConsuming test for error code; +* @tc.type: Error code test, invalid appId +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(WlMatrixTest, OnDataConsumingErrorTestCase01, TestSize.Level0) +{ + LocalDeviceStatusListener localDevice; + std::string deviceName = "TestDevice"; + uint8_t appId = 8; + uint8_t testAppId = 9; + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_ACTIVE, + .installedApps = { appId }, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + localDevice.Init(deviceName, wlDeviceInfo); + + localDevice.OnDataConsuming(testAppId); +} + +/** +* @tc.name: OnDataConsumingErrorTestCase02 +* @tc.desc: OnDataConsuming test for error code; +* @tc.type: Error code test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(WlMatrixTest, OnDataConsumingErrorTestCase02, TestSize.Level0) +{ + LocalDeviceStatusListener localDevice; + std::string deviceName = "TestDevice"; + uint8_t appId = 8; + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_SLEEP, + .installedApps = { appId }, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + localDevice.Init(deviceName, wlDeviceInfo); + + localDevice.OnDataConsuming(appId); +} + +/** +* @tc.name: OnDataGeneratingErrorTestCase01 +* @tc.desc: OnDataGenerating test for error code, appId error +* @tc.type: Error code test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(WlMatrixTest, OnDataGeneratingErrorTestCase01, TestSize.Level0) +{ + LocalDeviceStatusListener localDevice; + std::string deviceName = "TestDevice"; + uint8_t appId = 8; + uint8_t testAppId = 9; + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_ACTIVE, + .installedApps = { appId }, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + localDevice.Init(deviceName, wlDeviceInfo); + + localDevice.OnDataGenerating(testAppId, 0); +} + +/** +* @tc.name: OnDataGeneratingErrorTest02 +* @tc.desc: OnDataGenerating test for error code, data type Id error +* @tc.type: Error code test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(WlMatrixTest, OnDataGeneratingErrorTestCase02, TestSize.Level0) +{ + LocalDeviceStatusListener localDevice; + std::string deviceName = "TestDevice"; + uint8_t appId = 8; + uint8_t dtypeId = 17; + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_ACTIVE, + .installedApps = { appId }, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + localDevice.Init(deviceName, wlDeviceInfo); + + localDevice.OnDataGenerating(appId, dtypeId); +} + +/** +* @tc.name: OnPulledByErrorTest +* @tc.desc: OnPulledByError test for error code, peer deviceId error +* @tc.type: Error code test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(WlMatrixTest, OnPulledByErrorTest, TestSize.Level0) +{ + LocalDeviceStatusListener localDevice; + std::string deviceName = "TestDevice"; + std::string peerDeviceName = "NoDevice"; + uint8_t appId = 8; + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_SLEEP, + .installedApps = { appId }, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + localDevice.Init(deviceName, wlDeviceInfo); + + auto changedApp = localDevice.OnPulledBy(peerDeviceName); + EXPECT_TRUE(changedApp.empty()); +} + +/** +* @tc.name: OnReceivedWaterLevelTest +* @tc.desc: OnReceivedWaterLevel test for error code, received bytes empty +* @tc.type: Error code test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(WlMatrixTest, OnReceivedWaterLevelTestCase01, TestSize.Level0) +{ + LocalDeviceStatusListener localDevice; + std::string deviceName = "TestDevice"; + std::string peerDeviceName = "NoDevice"; + uint8_t appId = 8; + std::vector testEmptyBytes = {}; + std::vector testOneByte = { appId }; + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_SLEEP, + .installedApps = { appId }, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + localDevice.Init(deviceName, wlDeviceInfo); + + EXPECT_TRUE(localDevice.OnReceivedWaterLevel(peerDeviceName, testEmptyBytes)); + EXPECT_TRUE(localDevice.OnReceivedWaterLevel(peerDeviceName, testOneByte)); +} + +/** +* @tc.name: OnReceivedWaterLevelTestCase02 +* @tc.desc: OnReceivedWaterLevel test for error code, status offline +* @tc.type: Error code test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(WlMatrixTest, OnReceivedWaterLevelTestCase02, TestSize.Level0) +{ + LocalDeviceStatusListener localDevice; + std::string deviceName = "TestDevice"; + std::string peerDeviceName = "NoDevice"; + uint8_t appId = 8; + std::vector testBytes = { appId, 0x00, 0x01 }; + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_OFFLINE, + .installedApps = { appId }, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + localDevice.Init(deviceName, wlDeviceInfo); + + EXPECT_FALSE(localDevice.OnReceivedWaterLevel(peerDeviceName, testBytes)); +} + +/** +* @tc.name: OnReceivedDataTestCase01 +* @tc.desc: OnReceivedData test for error code, status offline +* @tc.type: Error code test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(WlMatrixTest, OnReceivedDataTestCase01, TestSize.Level0) +{ + LocalDeviceStatusListener localDevice; + std::string deviceName = "TestDevice"; + std::string peerDeviceName = "NoDevice"; + uint8_t appId = 8; + std::vector testBytes = { appId, 0x00, 0x01 }; + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_OFFLINE, + .installedApps = { appId }, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + localDevice.Init(deviceName, wlDeviceInfo); + // set some value in the mock database + localDevice.OnDataGenerating(appId, 0); + + localDevice.OnReceivedData(peerDeviceName, appId, "000"); +} + +/** +* @tc.name: OnReceivedDataTestCase02 +* @tc.desc: OnReceivedData test for error code, status offline +* @tc.type: Error code test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(WlMatrixTest, OnReceivedDataTestCase02, TestSize.Level0) +{ + LocalDeviceStatusListener localDevice; + std::string deviceName = "TestDevice"; + std::string peerDeviceName = "NoDevice"; + uint8_t appId = 8; + uint8_t testAppId = 9; + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_SLEEP, + .installedApps = { appId }, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + localDevice.Init(deviceName, wlDeviceInfo); + + localDevice.OnReceivedData(peerDeviceName, testAppId, GetCurrentTimeStr()); +} + +/** +* @tc.name: OnPushToTest +* @tc.desc: OnPushTo test for error code, status offline +* @tc.type: Error code test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(WlMatrixTest, OnPushToTest, TestSize.Level0) +{ + LocalDeviceStatusListener localDevice; + std::string deviceName = "TestDevice"; + std::string peerDeviceName = "NoDevice"; + uint8_t appId = 8; + + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_OFFLINE, + .installedApps = { appId }, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + localDevice.Init(deviceName, wlDeviceInfo); + + EXPECT_TRUE(localDevice.OnPushTo(peerDeviceName).empty()); +} + +/** +* @tc.name: GetPushDelayTest +* @tc.desc: GetPushDelay test for error code, status offline +* @tc.type: Error code test +* @tc.require: +* @tc.author: hui zeng +*/ +HWTEST_F(WlMatrixTest, GetPushDelayTest, TestSize.Level0) +{ + LocalDeviceStatusListener localDevice; + std::string deviceName = "TestDevice"; + std::string peerDeviceName = "NoDevice"; + uint8_t appId = 8; + + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_OFFLINE, + .installedApps = { appId }, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + localDevice.Init(deviceName, wlDeviceInfo); + + EXPECT_FLOAT_EQ(localDevice.GetPushDelay(peerDeviceName, appId), 0.0); +} diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/devices_simulator.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/devices_simulator.h new file mode 100644 index 0000000000000000000000000000000000000000..7b2fc818a06dc7a5a616fac2660e700decb973cd --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/devices_simulator.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 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 DEVICES_SIMULATOR_H +#define DEVICES_SIMULATOR_H + +#include "local_device_status_listener.h" +#include "wlmatrix_config.h" +#include "visibility.h" +namespace OHOS::DistributedData { +class API_EXPORT DevicesSimulator { +public: + static DevicesSimulator &GetInstance(); + void Init(std::int32_t deviceNum); + std::vector GetDeviceList(); + void AddDevice(const std::string &deviceName, const WlDeviceInfo &wlDeviceInfo); + void SetWlAIMDFactor(WlAIMDFactor wlAimdFactor); + + void SetDeviceOnline(const std::string &deviceId); + void SetDeviceOffline(const std::string &deviceId); + void SetDeviceActive(const std::string &deviceId); + void SetDeviceSleep(const std::string &deviceId); + void SetDeviceDataGene(const std::string &deviceId, std::uint8_t appId, std::uint8_t typeId); + void SetDeviceDataCons(const std::string &deviceId, std::uint8_t appId); + void SetDeviceInstalledApp(const std::string &deviceId, std::uint8_t appId); + void SetDeviceWlVersion(const std::string &deviceId, WlVersion version); + + void DeviceDataConsPull(const std::string& deviceId, std::uint8_t appId); + void DeviceDataConsPush(const std::string& deviceId, std::uint8_t appId); + + std::vector GetDeviceInstalledApps(const std::string &deviceId); + int32_t GetDeviceStatus(const std::string &deviceId); + + std::string DisplayDeviceDatabase(const std::string &deviceId); + std::string DisplayDeviceWaterLevelMatrix(const std::string &deviceId); + std::string DisplayDeviceSyncMatrix(const std::string &deviceId); + std::string DisplayDeviceInstalledApp(const std::string &deviceId); + + void ClearDeviceSimulator(); + + void DeviceReceiveWaterLevel(const std::string &deviceId, const CommBuff &commBuff_); + void DeviceSendingWaterLevel(const std::string &srcDeviceId); + void DeviceSyncWaterLevelWithPeer(const std::string &srcDeviceId, const std::string &dstDeviceId); + + void DeviceReceiveAppLst(const std::string &deviceId, const CommBuff &commBuff_); + void DeviceSendingAppLst(const std::string &srcDeviceId); + void DeviceSyncAppLstWithPeer(const std::string &srcDeviceId, const std::string &dstDeviceId); + + void DevicePullFrom(const std::string &srcDeviceId, const std::vector &dstDevices); + + void DevicePushing(std::string srcDeviceId, std::uint8_t appId); + void DevicePushToPeer(std::string srcDeviceId, std::string dstDeviceId); + std::map DeviceTimeStampOfApp(std::uint8_t appId); + + std::vector DevicesListOfFreshAppData(const std::string &deviceId, uint8_t appId); + + std::string PerformanceIndexSummary(); + std::vector DisplayPerformanceIndexList(); + + std::string PushPerfIndexSummary(); + std::vector DisplayPushPerfIndexList(); + + void AutoTestCase(std::int32_t testNum); + void AutoTestCase2(std::int32_t testNum); + + void PushAutoTestCase(std::int32_t testNum, int onlineLow, int onlineHigh, double dataGeneFreq); + void PushAutoTestCase2(std::int32_t testNum, int onlineLow, int onlineHigh, double waitPeriod); + +private: + std::map> devices; + std::unique_ptr wlSyncScheduler; + PerfIndex perfIndex; +}; +} // namespace OHOS::DistributedData +#endif // DEVICES_SIMULATOR_H diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/local_device_status_listener.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/local_device_status_listener.h new file mode 100644 index 0000000000000000000000000000000000000000..4a7f640489c374c187d7614ddb886f1dd6add3cd --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/local_device_status_listener.h @@ -0,0 +1,152 @@ +/* +* Copyright (c) 2023 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 LOCAL_DEVICE_STATUS_LISTENER_H +#define LOCAL_DEVICE_STATUS_LISTENER_H + +#include +#include + +#include "log_print.h" +#include "mock_database.h" +#include "status_statistic.h" +#include "sync_matrix.h" +#include "waterlevel_matrix.h" +#include "wlmatrix_config.h" +#include "wlmatrix_helper.h" +#include "wlsync_service.h" +#include "sysdata_sync_service.h" +#include "visibility.h" +namespace OHOS::DistributedData { +class API_EXPORT LocalDeviceStatusListener { +public: + // Init the listener + void Init(std::string deviceId, WlDeviceInfo wlDeviceInfo); + // After device power on + void OnPowerOn(); + // Before device power off + void OnPowerOff(); + // Before device change to sleep + void OnChangeAsleep(); + // Before the apps read the data or access to the database + std::vector OnDataConsuming(std::uint8_t appId); + // After the data generated by the app or the database has been changed + void OnDataGenerating(std::uint8_t appId, std::uint8_t typeId); + // After other device pull data from local device + std::vector OnPulledBy(std::string sourceDeviceId); + // After receiving the WaterLevel packet + bool OnReceivedWaterLevel(std::string sourceDeviceId, std::vector bytes); + // After receiving the installed apps + void OnReceiveInstalledApps(std::string sourceDeviceId, std::vector bytes); + // after receiving the database data + void OnReceivedData(std::string deviceId, std::uint8_t appId, std::string bytes); + + // Get the current installed Apps in the device + std::vector GetLocalInstalledApps(); + // Set the local installed apps, false -> no changes; true -> change + void SetLocalInstalledApps(std::vector installedApps_); + // Checking the apps has been synced + void CheckingInstalledAppsSync(); + // Set the tag whether the installed app have been synced + void SetAppSyncTag(std::string peerDeviceId, bool value_); + // Get all the devices whose appsync tag equal to value_ + std::vector GetDevicesAppSync(bool value_); + // cached peer device installed Apps + void SetPeerInstalledApps(std::string peerDeviceId, std::vector peerInstalledApp); + + // Set the device ID + void SetLocalDeviceId(std::string deviceId); + // Get the device ID + std::string GetLocalDeviceId(); + + // A module for listen to other devices in the network + // listen to the online event of other devices + void OnRemoteDeviceOnline(std::string peerDeviceId); + // listen to the offline event of other devices + void OnRemoteDeviceOffline(std::string peerDeviceId); + // listen to the sleep event of other devices + void OnRemoteDeviceSleep(std::string peerDeviceId); + // listen to the active event of other devices + void OnRemoteDeviceActive(std::string peerDeviceId); + // get the status of remote device + WlDeviceStatus GetRemoteDeviceStatus(std::string peerDeviceId); + // set the status of the remote device, when the device first sensing other devices + void SetRemoteDeviceInfo(std::string peerDeviceId, WlDeviceInfo wlDeviceInfo); + // get the status of local device + WlDeviceInfo GetLocalDeviceInfo(); + // set the status of local device + void SetLocalDeviceStatus(WlDeviceStatus wlDeviceStatus); + + std::vector GetDevicesWithStatus(WlDeviceStatus wlDeviceStatus); + std::vector GetAllDevices(); + + std::string GetWaterLevelString(); + std::string GetDeviceSyncString(); + std::string GetMockDatabaseString(); + std::string GetMockDatabaseOfApp(std::uint8_t appId); + + // set the device info of local device when the device init and ready to connect to the network + void SetLocalDeviceInfo(WlDeviceInfo wlDeviceInfo); + void SetWlMatrixHelper(std::shared_ptr wlMatrixHelper); + + bool CheckToBePulled(std::string peerDeviceId, std::uint8_t appId); + + // receive and send build link feature when the device first connect to the network + void OnReceiveBuildLinkFeature(std::string peerDeviceId, BuildLinkFeature buildLinkFeature); + BuildLinkFeature SendBuildLinkFeature(); + + // version compatibility, add API + void SetWlVersion(WlVersion version); + /* + * This function is only used in the simulator. + * We assume that the wlVersion will remain unchanged for a short time. + * The local device can only use this function to detect changes + * when remote devices upgrade or update their version. + * */ + void OnRemoteDeviceSetWlVersion(std::string peerDeviceId, WlVersion wlVersion); + std::vector GetOldVersionDevices(); + + /* + * This function retrieves a list of App buffers + * that have been generated but not yet synchronized. + * */ + std::vector OnPushTo(std::string peerDeviceId); + double GetPushDelay(std::string peerDeviceId, std::uint8_t appId); + void SetWlAIMDFactor(WlAIMDFactor wlAimdFactor); + +private: + // send WaterLevelMatrix to target list + void SendWaterLevel(std::vector deviceList); + // Sync installed App + void SendInstalledApps(std::string peerDeviceId); + // push data to other devices immediately + void PushData(std::string peerDeviceId); + + std::string deviceId_; + std::map appSyncTag_; + + WlDeviceInfo localDeviceInfo_; + std::map remoteDevicesStatus_; + + std::unique_ptr mockDatabase_; + std::unique_ptr waterLevelMatrix_; + std::unique_ptr wlSyncService_; + std::unique_ptr wlStatusStatistic_; + std::unique_ptr deviceSyncMatrix_; + std::unique_ptr sysDataSyncService_; + std::shared_ptr wlHelper_; +}; +} // namespace OHOS::DistributedData +#endif // LOCAL_DEVICE_STATUS_LISTENER_H diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/mock_database.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/mock_database.h new file mode 100644 index 0000000000000000000000000000000000000000..850931eb9277d4ea17000cb2a5347421ca596b53 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/mock_database.h @@ -0,0 +1,36 @@ +/* +* Copyright (c) 2023 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 WL_MOCK_DATABASE_H +#define WL_MOCK_DATABASE_H + +#include +#include +#include +#include "visibility.h" +namespace OHOS::DistributedData { +class API_EXPORT MockDatabase { +public: + void Init(const std::vector &installedApps); + void UpdateInstalledApps(const std::vector &installedApps); + bool WriteToDataBase(std::uint8_t appId, const std::string &value_); + std::map GetDatabase(); + std::string DisplayDatabase(); + +private: + std::map database_; +}; +} // namespace OHOS::DistributedData +#endif // WL_MOCK_DATABASE_H diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/status_statistic.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/status_statistic.h new file mode 100644 index 0000000000000000000000000000000000000000..6212c9416b684ec63e98bee4e74c0feb6c113ee9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/status_statistic.h @@ -0,0 +1,114 @@ +/* +* Copyright (c) 2023 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 WL_STATUS_STATISTIC_H +#define WL_STATUS_STATISTIC_H + +#include +#include +#include + +#include "visibility.h" +#include "wlmatrix_config.h" +namespace OHOS::DistributedData { +struct API_EXPORT AppSyncStatistic { + uint32_t pushTimes = 0; + uint32_t pullTimes = 0; +}; + +struct API_EXPORT HardwareStatistic { + double powerPercent; + uint32_t activeDevices; +}; + +struct API_EXPORT RemoteStatistic { + // record the on-off period of remote devices + std::map> onOffPeriod; // OfflineStatusFeature: feature code -> time + // record the usage frequency of remote devices + std::map appFreq; // appId -> frequency +}; + +enum AlreadyOnline { + SHORT = 0, + MID, + LONG +}; + +enum CurrentTime { + AM = 0, + PM +}; + +enum PowerLevel { + LOW = 0, + MID_POWER, + HIGH +}; + +struct API_EXPORT OfflineStatusFeature { + AlreadyOnline alreadyOnline; + CurrentTime currentTime; + PowerLevel powerLevel; + std::string FeatureCode() const + { + std::string featureCode; + featureCode.append(std::to_string(int(alreadyOnline))); + featureCode.append(std::to_string(int(currentTime))); + featureCode.append(std::to_string(int(powerLevel))); + return featureCode; + }; +}; + +class API_EXPORT WlStatusStatistic { +public: + WlStatusStatistic() = default; + ~WlStatusStatistic() = default; + + void PushTimesIncr(std::uint8_t appId); + void PullTimesIncr(std::uint8_t appId); + AppSyncStatistic GetDataSyncStatistic(std::uint8_t appId); + + void SetPowerPercent(double powerPercent); + void SetActiveDevices(uint32_t activeDevices); + HardwareStatistic GetHardwareStatistic(); + + void SetInServiceHeatIncr(const std::string &deviceId); + void SetAppHeatIncr(const std::string &deviceId, std::uint8_t appId); + void SetSyncHeatIncr(const std::string &deviceId); + + void SetBuildLinkFeature(const std::string &deviceId, BuildLinkFeature feature); + std::map GetBuildLinkFeature(); + + void SetOnOffPeriod(const std::string &deviceId, const std::string &featureCode, double periodTime); + std::vector GetOnOffPeriod(const std::string &deviceId, const std::string &featureCode); + + void SetAppFreq(const std::string &deviceId, const std::map &appFreq); + void SetAppFreq(const std::string &deviceId, std::uint8_t appId, uint32_t value); + void SetAppFreqIncr(const std::string &deviceId, std::uint8_t appId); + std::map GetAppFreq(const std::string &deviceId); + + bool IsBuildLinks(std::uint8_t appId); + std::vector GetBuildLinksOrder(const std::vector &deviceList, std::uint8_t appId); + +private: + // appId -> record; record each App has been pulled or pushed + std::map pushPullTimes; + HardwareStatistic hardwareStatistic = { .powerPercent = 0.0, .activeDevices = 1 }; + std::map buildLinksFeature; + + std::map remoteStatistic; +}; +} // namespace OHOS::DistributedData +#endif // WL_STATUS_STATISTIC_H diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/sub_waterlevel_matrix.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/sub_waterlevel_matrix.h new file mode 100644 index 0000000000000000000000000000000000000000..78044a6f407d2465c4efde3ed68909b82f7a4fe6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/sub_waterlevel_matrix.h @@ -0,0 +1,59 @@ +/* +* Copyright (c) 2023 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 SUB_WATER_LEVEL_MATRIX_H +#define SUB_WATER_LEVEL_MATRIX_H + +#include +#include +#include +#include + +#include "log_print.h" +#include "visibility.h" +#include "wlmatrix_config.h" +#include "wlmatrix_error.h" +namespace OHOS::DistributedData { +class API_EXPORT SubWaterLevelMatrix { +public: + SubWaterLevelMatrix(); + ~SubWaterLevelMatrix() = default; + SubWaterLevelMatrix(std::string peerDeviceId); + + bool Init(std::string srcDeviceId, std::string peerDeviceId, const std::vector &appList); + + void SetAppWl(const std::uint8_t &appId); + void SetAppWl(const std::uint8_t &appId, uint8_t typeId); // set value = 1 + uint16_t GetAppWl(const std::uint8_t &appId); + void ResetAllWl(); + void ResetAppWl(const std::uint8_t &appId, uint8_t typeId); // set value = 0 + + std::string DisplaySubWaterLevelMatrix(); + + std::vector CompressSubWaterLevelMatrix(); + + void SetSrcDeviceId(std::string srcDeviceId); + std::string GetSrcDeviceId(); + + void SetPeerDeviceId(std::string peerDeviceId); + std::string GetPeerDeviceId(); + +private: + std::map subWaterLevel_; + std::string srcDeviceId_; + std::string peerDeviceId_; +}; +} // namespace OHOS::DistributedData +#endif // SUB_WATER_LEVEL_MATRIX_H diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/sync_matrix.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/sync_matrix.h new file mode 100644 index 0000000000000000000000000000000000000000..87adf75f5070522d3f7b128d1da27081e624f1d5 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/sync_matrix.h @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2023 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_SYNC_MATRIX_H +#define DEVICE_SYNC_MATRIX_H + +#include +#include +#include +#include +#include +#include + +#include "log_print.h" +#include "visibility.h" +#include "wlmatrix_config.h" +#include "wlmatrix_error.h" +namespace OHOS::DistributedData { +class API_EXPORT SyncMatrix { +public: + SyncMatrix() = default; + ~SyncMatrix() = default; + + void Init(const std::vector &installedApp); + void LocalUpdateDeviceSyncMatrix(std::vector syncDevices, std::vector installedApp); + void UpdateDeviceSyncMatrix(const std::string &peerDeviceId, const std::vector &wltransUnit); + std::vector GetSyncDeviceList(const std::uint8_t &appId); + void RemoveSyncDevices(const std::uint8_t &appId, const std::string &peerDeviceId); + void ClearAppSyncDevices(const std::uint8_t &appId); + std::string GetSyncDeviceString(const std::uint8_t &appId); + std::string GetAllSyncDeviceString(); + + struct SubDeviceSyncMatrix { + std::map> syncDevices; + }; + +private: + /* Data: + * app -> subwaterlevel + * */ + std::map deviceSyncMatrix_; // +}; +} // namespace OHOS::DistributedData +#endif // DEVICE_SYNC_MATRIX_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/sysdata_sync_service.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/sysdata_sync_service.h new file mode 100644 index 0000000000000000000000000000000000000000..215bcd837af0db7a60a5a733f86106ae546d9605 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/sysdata_sync_service.h @@ -0,0 +1,67 @@ +/* +* Copyright (c) 2023 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 WL_MATRIX_SYS_DATA_SYNC_SERVICE_H +#define WL_MATRIX_SYS_DATA_SYNC_SERVICE_H + +#include +#include +#include +#include + +#include "log_print.h" +#include "sysdata_sync_strategy.h" +#include "visibility.h" +#include "wlmatrix_config.h" +#include "wlsync_scheduler.h" +namespace OHOS::DistributedData { +class API_EXPORT SysDataSyncService { +public: + using AppSyncBuffLst = std::vector; + + SysDataSyncService(WlAIMDFactor aimdFactor); + ~SysDataSyncService() = default; + + void AddAppToSyncBuffLst(std::string peerDeviceId, std::uint8_t appId); + void ClearSyncBuffLst(std::string peerDeviceId); + std::vector GetSyncBuffLst(std::string peerDeviceId); + void GetSyncBuffLstRef(std::string peerDeviceId, std::vector &syncBuffLst_); + bool IsSyncBuffLstEmpty(std::string peerDeviceId); + void SetAIMDFactor(WlAIMDFactor aimdFactor); + /* + * Param: + * peerDeviceId + * adjustMode: true -> AI(additive increase), false -> MD(multiple decrease) + * Op: + * adjust the push delay + * */ + void AdjustPushDelayAIMD(std::string peerDeviceId, WlAIMDMode adjustMode); + void AdjustPushDelayAIMD(std::string peerDeviceId, std::uint8_t appId, WlAIMDMode adjustMode); + void AdjustPushDelayAIMD(std::string peerDeviceId, std::vector appLst, WlAIMDMode adjustMode); + double GetPushDelay(std::string peerDeviceId, double appScaleFactor, bool isAIMD); + double GetPushDelay(std::string peerDeviceId, std::uint8_t appId, bool isAIMD); + +private: + /* + * Maintain a AppSyncBuffLst for each device, + * The AppSyncBuffLst records the appId of which the App has generated the data but not sync. + * The device will wait for the delay, and then push all the App data in AppSyncBuffLst + * */ + std::map syncBuffLst; + SysDataAIMDStrategy *AIMDStrategy; + std::mutex mutex_; +}; +} // namespace OHOS::DistributedData +#endif // WL_MATRIX_SYS_DATA_SYNC_SERVICE_H diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/sysdata_sync_strategy.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/sysdata_sync_strategy.h new file mode 100644 index 0000000000000000000000000000000000000000..d89ff6bfa3af408c0f48f75cf2253d6e8ce44039 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/sysdata_sync_strategy.h @@ -0,0 +1,42 @@ +/* +* Copyright (c) 2023 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 WL_MATRIX_SYS_DATA_SYNC_STRATEGY_H +#define WL_MATRIX_SYS_DATA_SYNC_STRATEGY_H + +#include "log_print.h" +#include "visibility.h" +#include "wlmatrix_config.h" +namespace OHOS::DistributedData { +class API_EXPORT SysDataAIMDStrategy { +public: + explicit SysDataAIMDStrategy(WlAIMDFactor aimdFactor); + double GetPushDelay(std::string deviceId, double appScaleFactor); + double GetPushDelay(std::string deviceId, std::uint8_t appId); + // adjustMode : true -> AI, false -> MD + void AdjustPushDelay(std::string deviceId, WlAIMDMode adjustMode); + void AdjustPushDelayOfApp(std::string deviceId, std::uint8_t appId, WlAIMDMode adjustMode); + void SetAIMDFactor(WlAIMDFactor aimdFactor_); + double AdjustPushDelayMD(double preDelay, double MDFactor); + +private: + // AIMDFactor to adjust the push delay + WlAIMDFactor aimdFactor; + // deviceId -> push delay; record the push delay of each device + std::map pushDelay; + std::map> pushDelayOfApp; +}; +} // namespace OHOS::DistributedData +#endif // WL_MATRIX_SYS_DATA_SYNC_STRATEGY_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/waterlevel_matrix.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/waterlevel_matrix.h new file mode 100644 index 0000000000000000000000000000000000000000..ef545c5cdc603b49659b89af6b7ec4f6ef3bc1a2 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/waterlevel_matrix.h @@ -0,0 +1,57 @@ +/* +* Copyright (c) 2023 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 WATER_LEVEL_MATRIX_H +#define WATER_LEVEL_MATRIX_H + +#include +#include +#include + +#include "sub_waterlevel_matrix.h" +#include "visibility.h" +#include "wlmatrix_config.h" +namespace OHOS::DistributedData { +class API_EXPORT WaterLevelMatrix { +public: + WaterLevelMatrix() = default; + ~WaterLevelMatrix() = default; + WaterLevelMatrix(const WaterLevelMatrix &) = delete; + WaterLevelMatrix(WaterLevelMatrix &&) noexcept = delete; + WaterLevelMatrix &operator=(const WaterLevelMatrix &) = delete; + WaterLevelMatrix &operator=(WaterLevelMatrix &&) noexcept = delete; + + void Init(std::string deviceId); + std::string GetDeviceId() const; + + void SetSubWaterLevelMatrix(const std::uint8_t &appId, uint8_t typeId); + void ResetAll(); + void ResetDeviceWaterLevel(const std::string &deviceId); + + void UpdateWaterLevelMatrix(const std::string &peerDeviceId, const std::vector &appList); + + std::string DisplayAllSubWaterLevelMatrix(); + + std::vector CompressWaterLevelMatrix(const std::string &peerDeviceId); + std::vector CompressWaterLevelMatrixApp(const std::string &peerDeviceId); + + bool CheckAppWl(const std::string &peerDeviceId, uint8_t appId); + +private: + std::string deviceId_; + std::map> waterlevel_; +}; +} // namespace OHOS::DistributedData +#endif // WATER_LEVEL_MATRIX_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlmatrix_config.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlmatrix_config.h new file mode 100644 index 0000000000000000000000000000000000000000..3da602caa02386e6a531f59af6f0a8da92282e84 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlmatrix_config.h @@ -0,0 +1,397 @@ +/* +* Copyright (c) 2023 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 WL_MATRIX_CONFIG_H +#define WL_MATRIX_CONFIG_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "visibility.h" +#include "wlmatrix_error.h" +namespace OHOS::DistributedData { +constexpr uint16_t SUB_WL_MATRIX_ELE_ZERO = 0x0; +constexpr uint16_t SUB_WL_MATRIX_ELE_ONE = 0x1; +constexpr uint16_t SUB_WL_MATRIX_ELE_ALL = 0xffff; + +const std::string DEFAULT_DEVICE_ID = "unKnow"; + +const std::int32_t PRINT_CHAR_NUM = 10; +const std::int32_t BYTE_TO_BIT = 8; +const std::int32_t WLTRANSUINT_FORMAT_SIZE = 3; + +const std::int32_t MAX_DEVICE_NAME = NAME_MAX; +const std::int32_t MAX_DEVICE_NUM = 10; +const std::int32_t MAX_APP_NUM = 200; +const std::int32_t DEFAULT_APP_NUM = 20; +const std::int32_t MAX_DATA_TYPE = 16; +const std::int32_t MAX_REPEAT_SEND = 3; +const std::int32_t MAX_ACTIVE_DEVICES = 2; + +const std::int32_t DEFAULT_PUSH_APP_NUM = 10; +const std::int32_t DEFAULT_HEAT_UP_BOUND = 20; +const std::int32_t PUSH_APP_BOUND = 100; +const std::int32_t DEFAULT_MD_FACTOR = 2; + +const double APP_PULL_PUSH_THRESHOLD = 1.0; +const double POWER_PERCENT_ACTIVE_DEVICE_THRESHOLD = 1.0; + +const double PROB_DATA_GENE = 0.5; +const std::int32_t TIME_STR_LENGTH = 16; + +const std::int32_t DATA_CONSUME_TIME = 10; +const std::int64_t TIME_CONVERT = 1000; + +enum API_EXPORT WlVersion : int32_t { + OLDER_WATER_LEVEL = 0, + CURRENT_WATER_LEVEL = 1 +}; + +enum API_EXPORT WlPushMode : int32_t { + IMMEDIATELY = 0, + DELAY = 1 +}; + +enum CommStatus : int32_t { + SUCCESS = E_WL_OK, + ERROR = E_WL_ERROR +}; + +enum CommType : int32_t { + WL = 0, + APP = 1, + PUSH = 2 +}; + +enum class API_EXPORT WlDeviceStatus { + WL_DEVICE_ONLINE = 0, + WL_DEVICE_ACTIVE = 1, + WL_DEVICE_OFFLINE = 2, + WL_DEVICE_SLEEP = 3 +}; + +enum WlAIMDMode : int32_t { + WL_AIMD_AI = 0, + WL_AIMD_MD = 1 +}; + +struct API_EXPORT WlTransUnit { + std::uint8_t appId; + uint16_t wlValue; +}; + +struct API_EXPORT WlAIMDFactor { + double InitDelay = 0.1; // the measurement of all factor is second + double AIFactor = 1; + double MDFactor = DEFAULT_MD_FACTOR; + double mFactor = 0.1; + double DelayUpBound = 20; +}; + +struct API_EXPORT WlDeviceInfo { + WlDeviceStatus wlDeviceStatus; + std::vector installedApps; + WlVersion wlVersion; + WlAIMDFactor wlAimdFactor; +}; + +struct API_EXPORT BuildLinkFeature { + std::string deviceId; + uint32_t inServiceHeat; // in service num + uint32_t targetAppHeat; + std::map appHeat; // appId -> value + uint32_t syncHeat; // deviceId -> value +}; + +struct API_EXPORT CommBuff { + std::string sourceId; + std::string dstDevice; + std::vector bytes; + bool commTag; // false -> not in communication status, true -> wl need to be received + std::vector app_bytes; + bool app_commTag; + std::string data_bytes; + std::vector data_app; + bool data_commTag; // false -> no data, true -> dstDevice pull from sourceId + bool pushCommTag; // false -> no app data should be push + std::vector pushAppLst; +}; + +struct API_EXPORT PerfIndex { + std::map awake_count; // deviceId -> awake times + std::int32_t error_pull; + std::int32_t pull_count; + std::map baseline_awake; + + std::map push_awake_count; + std::map push_baseline; + std::int32_t push_gene_count; + std::map access_error_count; + std::map access_count; +}; + +__attribute__((unused)) static bool IsDeviceNameValid(const std::string &deviceId) +{ + if (deviceId.size() > MAX_DEVICE_NAME || deviceId.empty()) { + return false; + } + return true; +} + +__attribute__((unused)) static bool IsAppIdValid(std::uint8_t appId) +{ + if (appId > MAX_APP_NUM) { + return false; + } + return true; +} + +__attribute__((unused)) static bool IsDataTypeValid(uint8_t typeId) +{ + if (typeId > MAX_DATA_TYPE) { + return false; + } + return true; +} + +template +__attribute__((unused)) static bool IsVectorSetEqual(std::vector vec1, std::vector vec2) +{ + std::set set1(vec1.begin(), vec1.end()); + std::set set2(vec2.begin(), vec2.end()); + + if (set1 == set2) { + return true; + } else { + return false; + } +} + +// get the index of the wlValue whose bit equals to 1 +__attribute__((unused)) static std::vector GetWlValueIndex(uint16_t wlValue) +{ + std::vector index_; + for (uint8_t i = 0; i < sizeof(uint16_t) * BYTE_TO_BIT; i++) { + uint16_t temp = 0x01 << i; + if ((wlValue & temp) == temp) { + index_.push_back(i); + } + } + return index_; +} + +__attribute__((unused)) static std::vector DecompressWaterLevel(std::vector bytes) +{ + std::vector decompressWl; + + // new version water level matrix, size can be 0, or, number % 3 == 0 + if (bytes.size() % WLTRANSUINT_FORMAT_SIZE == 0) { + for (size_t i = 0; i < bytes.size(); i = i + WLTRANSUINT_FORMAT_SIZE) { + decompressWl.push_back(WlTransUnit { .appId = bytes[i], + .wlValue = static_cast((bytes[i + 1] << BYTE_TO_BIT) + bytes[i + 2]) }); + } + } + return decompressWl; +} + +template +__attribute__((unused)) static std::vector VectorsIntersection(std::vector v1, std::vector v2) +{ + std::vector v; + sort(v1.begin(), v1.end()); + sort(v2.begin(), v2.end()); + set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), back_inserter(v)); + return v; +} + +__attribute__((unused)) static std::string GetCurrentTimeStr() +{ + std::time_t t = std::time(nullptr); + + struct tm *info = std::localtime(&t); + + char buff[TIME_STR_LENGTH]; + std::strftime(buff, TIME_STR_LENGTH, "%Y%m%d%H%M%S", info); + + std::string timeStr(buff); + + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + auto ms = std::chrono::duration_cast(now.time_since_epoch()) % 1000; + std::string msStr = std::to_string(ms.count()); + timeStr += msStr; + + return timeStr; +} + +__attribute__((unused)) static std::string GetTimeStr() +{ + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + auto ms = std::chrono::duration_cast(now.time_since_epoch()) % 1000; + std::time_t t = std::chrono::system_clock::to_time_t(now); + std::stringstream ss; + ss << std::put_time(std::localtime(&t), "%Y%m%d%H%M%S") << ms.count() << std::put_time(std::localtime(&t), "%3"); + return ss.str(); +} + +/* + * Get the result whether v1 belongs to v2, or, v1 is the subset of v2 + * */ + +template +__attribute__((unused)) static bool IsVecSubset(std::vector v1, std::vector v2) +{ + std::set setV2(v2.begin(), v2.end()); + for (std::uint8_t i = 0; i < v1.size(); i++) { + if (setV2.find(v1[i]) == setV2.end()) { + return false; + } + } + return true; +} + +template +__attribute__((unused)) static bool isVecEqual(std::vector v1, std::vector v2) +{ + std::set setV1(v1.begin(), v1.end()); + std::set setV2(v2.begin(), v2.end()); + + return std::equal(setV1.begin(), setV1.end(), setV2.begin(), setV2.end()); +} + +template +__attribute__((unused)) static std::vector CombVec(std::vector v1, std::vector v2) +{ + std::set resSet(v1.begin(), v1.end()); + std::vector res; + for (auto it : v2) { + resSet.insert(it); + } + res.assign(resSet.begin(), resSet.end()); + return res; +} + +template +__attribute__((unused)) static T GetRandomElement(std::vector arr, int arrSize) +{ + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(0, arrSize - 1); + int randomIndex = dis(gen); + return arr[randomIndex]; +} + +__attribute__((unused)) static bool GetRandomWithProb(double prob) +{ + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution<> dis(0, 1); + double randomValue = dis(gen); + return randomValue < prob; +} + +__attribute__((unused)) static int GetUniformRandomValue(int low, int high) +{ + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(low, high); + return dis(gen); +} + +template +__attribute__((unused)) static T GetUniformRandomRealValue(T low, T high) +{ + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution dis(low, high); + return dis(gen); +} + +__attribute__((unused)) static std::string JoinStrings(const std::vector &strings, + const std::string &delimiter) +{ + return std::accumulate(strings.begin(), strings.end(), std::string(), + [&](const std::string &acc, const std::string &str) { + return acc.empty() ? str : acc + delimiter + str; + }); +} + +__attribute__((unused)) static std::string MapToString(std::map dataMap) +{ + std::string dataStr = "\n"; + for (auto [key, value] : dataMap) { + dataStr += key + ": " + value + "\n"; + } + return dataStr; +} + +__attribute__((unused)) static bool BuildLinkCmp(const BuildLinkFeature &feature1, const BuildLinkFeature &feature2) +{ + if (feature1.inServiceHeat > feature2.inServiceHeat) { + return true; + } else if (feature1.inServiceHeat == feature2.inServiceHeat) { + if (feature1.targetAppHeat > feature2.targetAppHeat) { + return true; + } else if (feature1.targetAppHeat == feature2.targetAppHeat) { + if (feature1.syncHeat > feature2.syncHeat) { + return true; + } else if (feature1.syncHeat == feature2.syncHeat) { + return feature1.deviceId < feature2.deviceId; + } + } + } + return false; +} + +__attribute__((unused)) static void StartAfterDelay(int delay, std::function task) +{ + std::thread([delay, task]() { + std::this_thread::sleep_for(std::chrono::milliseconds(delay)); + task(); + }).detach(); +} + +__attribute__((unused)) static std::map GetFreqPercent( + std::map appFreq) +{ + std::map appFreqPercent; + std::uint32_t totalFrequency = 0; + for (auto [app, freq] : appFreq) { + totalFrequency += freq; + } + for (auto [app, freq] : appFreq) { + double percentage = static_cast(freq) / totalFrequency; + appFreqPercent[app] = percentage; + } + return appFreqPercent; +} + +__attribute__((unused)) static std::int64_t ConvertSecondToMilli(double seconds_) +{ + return static_cast(seconds_ * TIME_CONVERT); +} +} // namespace OHOS::DistributedData +#endif // WL_MATRIX_CONFIG_H diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlmatrix_error.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlmatrix_error.h new file mode 100644 index 0000000000000000000000000000000000000000..030cba0ee59e1440f0d7aaadd111865dab184850 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlmatrix_error.h @@ -0,0 +1,55 @@ +/* +* Copyright (c) 2023 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 WLMATRIX_ERROR_H +#define WLMATRIX_ERROR_H + +#include +namespace OHOS::DistributedData { +/** +* @brief The error code in the correct case. +*/ +constexpr int E_WL_OK = 0; + +/** +* @brief The base code of the exception error code. +*/ +constexpr int E_WL_BASE = -2000; // different from the other error. + +/** +* @brief The error code for common exceptions. +*/ +constexpr int E_WL_ERROR = (E_WL_BASE - 1); + +/** +* @brief The error code for the input args is invalid. +*/ +constexpr int E_WL_INVALID_ARGS = (E_WL_BASE - 2); // the input args is invalid. +const std::string E_WL_INVALID_APP_INDEX = "WlError Code 1: Args: appId not exist"; +const std::string E_WL_INVALID_DATATYPE_INDEX = "WlError Code 2: Args: typeId not exist"; +const std::string E_WL_INVALID_DEVICE_ID = "WlError Code 3: Args: deviceId invalid"; +const std::string E_WL_INVALID_WLAIMDFACTOR_MD = "WlError Code 4: Args: WlAIMDFactor::MDFactor invalid"; +/** +* @brief The error code for overflow/out of bounds. +*/ +constexpr int E_WL_OVERFLOW = (E_WL_BASE - 3); +const std::string E_WL_OVERFLOW_DATA_TYPE = "WlError Code 5: TypeId out of bounds"; + +/** +* @brief The error code for WlScheduler. +*/ +const std::string E_WL_WLSCHEDULER_ADD_FAILER = "WlError Code 6: Add wltask failed"; +} // namespace OHOS::DistributedData +#endif // WLMATRIX_ERROR_H diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlmatrix_helper.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlmatrix_helper.h new file mode 100644 index 0000000000000000000000000000000000000000..ea62ba631e7bf4fd6c9976bc74cf4dc6e90bc0f1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlmatrix_helper.h @@ -0,0 +1,103 @@ +/* +* Copyright (c) 2023 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 WLMATRIX_HELPER_H +#define WLMATRIX_HELPER_H + +#include +#include +#include + +#include "wlmatrix_config.h" +namespace OHOS::DistributedData { +extern std::map commBuff; + +static CommStatus FakeSendDataFunction(std::string srcDeviceId, std::string dstDeviceId, + std::vector bytes, CommType mode_) +{ + std::string key_ = srcDeviceId + dstDeviceId; + if (mode_ == CommType::WL) { + commBuff[key_].sourceId = std::move(srcDeviceId); + commBuff[key_].dstDevice = std::move(dstDeviceId); + commBuff[key_].bytes = std::move(bytes); + commBuff[key_].commTag = true; + } else if (mode_ == CommType::APP) { + commBuff[key_].sourceId = std::move(srcDeviceId); + commBuff[key_].dstDevice = std::move(dstDeviceId); + commBuff[key_].app_bytes = std::move(bytes); + commBuff[key_].app_commTag = true; + } else if (mode_ == CommType::PUSH) { + commBuff[key_].sourceId = std::move(srcDeviceId); + commBuff[key_].dstDevice = std::move(dstDeviceId); + commBuff[key_].pushAppLst = std::move(bytes); + commBuff[key_].pushCommTag = true; + } else { + return CommStatus::ERROR; + } + return CommStatus::SUCCESS; +} + +static std::vector FakeGetInstalledAppsFunction() +{ + return { 0, 1, 2, 3 }; +} + +// srcDeviceId --> pull data from dstDeviceId = dstDeviceId -> send data -> srcDeviceId +static void FakePullFromDevice(std::string srcDeviceId, std::string dstDeviceId) +{ + std::string fakeData = "|" + dstDeviceId + "|"; + std::string key_ = dstDeviceId + srcDeviceId; + commBuff[key_].data_commTag = true; + commBuff[key_].data_bytes = fakeData; + std::string infoStr = srcDeviceId + "pull data: [" + fakeData + "] from " + dstDeviceId + "\n"; +} + +static std::map FakeGetRemoteDevicesStatusFunction() +{ + std::map remote_status; + + return remote_status; +} + +static BuildLinkFeature FakeGetBuildLinkFeatureFunction(std::string deviceId, std::vector appLst) +{ + BuildLinkFeature buildLinkFeature; + buildLinkFeature.deviceId = deviceId; + buildLinkFeature.inServiceHeat = GetUniformRandomValue(0, DEFAULT_HEAT_UP_BOUND); + buildLinkFeature.targetAppHeat = 0; + + std::map appHeat; + for (auto it : appLst) { + appHeat.insert_or_assign(it, GetUniformRandomValue(0, DEFAULT_HEAT_UP_BOUND)); + } + buildLinkFeature.appHeat = appHeat; + buildLinkFeature.syncHeat = GetUniformRandomValue(0, DEFAULT_HEAT_UP_BOUND); + return buildLinkFeature; +} + +class API_EXPORT WlMatrixHelper { +public: + std::function, CommType)> SendDataFunction = + &FakeSendDataFunction; + std::function BroadcastFunction; + std::function()> GetInstalledAppsFunction = &FakeGetInstalledAppsFunction; + std::function PullFromDevice = &FakePullFromDevice; + std::function()> GetRemoteDevicesStatusFunction = + &FakeGetRemoteDevicesStatusFunction; + std::function)> GetBuildLinkFeatureFunction = + &FakeGetBuildLinkFeatureFunction; +}; +} // namespace OHOS::DistributedData +#endif // WLMATRIX_HELPER_H diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlsync_scheduler.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlsync_scheduler.h new file mode 100644 index 0000000000000000000000000000000000000000..6bd992218be9ebce3e3a841b918f3ea64862cc8c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlsync_scheduler.h @@ -0,0 +1,75 @@ +/* +* Copyright (c) 2023 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 WLSYNC_SCHEDULER_H +#define WLSYNC_SCHEDULER_H + +#include +#include +#include +#include +#include +#include + +#include "log_print.h" +#include "visibility.h" +namespace OHOS::DistributedData { +class API_EXPORT WlSyncScheduler { +public: + using TimePoint = std::chrono::steady_clock::time_point; + using Duration = std::chrono::steady_clock::duration; + inline static constexpr std::string_view EMPTY_TASK_ID = "EMPTY_TASK_ID"; + + struct WlTask { + std::string taskId; + std::function taskFunc; + TimePoint executeTime; + std::uint8_t taskContent; + }; + WlSyncScheduler(); + WlSyncScheduler(size_t capacity); + WlSyncScheduler(std::string name); + WlSyncScheduler(size_t capacity, std::string name); + ~WlSyncScheduler(); + + // init the Scheduler + void Start(size_t capacity, std::string name); + // Scheduler should be stopped + void Stop(); + // thread sleep, delay is the millisecond + void Sleep(int duration); + // add wl task, the param is the function and delay (execute time = delay + now) + void AddWlTask(std::string taskId, std::function taskFunc, Duration delay, std::uint8_t taskContent); + // add wl task, no taskContent + void AddWlTask(std::string taskId, std::function taskFunc, Duration delay); + void Clear(); + // clear task by taskId + void ClearTasksById(std::string taskId); + +private: + void WorkerThread(); + + volatile bool isRunning_; + size_t capacity_; + // multimap can sort the WlTask by TimePoint + std::multimap wlTasks_; + // taskId list + std::multimap taskLst; + std::mutex mutex_; + std::unique_ptr thread_; + std::condition_variable condition_; +}; +} // namespace OHOS::DistributedData +#endif // WLSYNC_SCHEDULER_H diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlsync_service.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlsync_service.h new file mode 100644 index 0000000000000000000000000000000000000000..02209898ca07366a5f1969090eb1120b4bf5aadd --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlsync_service.h @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2023 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 WLMATRIX_WLSYNC_SERVICE_H +#define WLMATRIX_WLSYNC_SERVICE_H + +#include +#include +#include +#include + +#include "log_print.h" +#include "visibility.h" +#include "wlsync_strategy.h" +namespace OHOS::DistributedData { +class API_EXPORT WlSyncService { +public: + WlSyncService() = default; + ~WlSyncService() = default; + + void SetSendTag(const std::string &deviceId, bool tag); + bool GetSendTag(const std::string &deviceId); + std::vector GetSyncDevices(bool tag); + void SetSyncStrategy(bool buildlink = true); // true -> buildlink; false -> broadcasr + CommStatus BuildLinkToSync(std::string srcDeviceId, const std::string &peerDeviceId, + std::vector content); + std::function, CommType)> SendDataFunction; + +private: + std::map sendTag; // default false, true: the water level need to send + WlSyncStrategy *strategy; +}; +} // namespace OHOS::DistributedData +#endif // WLMATRIX_WLSYNC_SERVICE_H diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlsync_strategy.h b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlsync_strategy.h new file mode 100644 index 0000000000000000000000000000000000000000..2f1ae7e1194814245871aef1f94ca748aea73519 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/include/wlsync_strategy.h @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2023 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 WLMATRIX_WLSYNC_STRATEGY_H +#define WLMATRIX_WLSYNC_STRATEGY_H + +#include "log_print.h" +#include "visibility.h" +#include "wlmatrix_config.h" +namespace OHOS::DistributedData { +class API_EXPORT WlSyncStrategy { +public: + virtual CommStatus DoWaterLevelSync(std::string deviceId, std::string dstDeviceId, + std::vector content) = 0; + std::function, CommType)> SendDataFunction; +}; + +class API_EXPORT WlBroadcastStrategy : public WlSyncStrategy { +public: + WlBroadcastStrategy(); + CommStatus DoWaterLevelSync(std::string deviceId, std::string dstDeviceId, + std::vector content) override; +}; + +class API_EXPORT WlBuildLinksStrategy : public WlSyncStrategy { +public: + WlBuildLinksStrategy(); + CommStatus DoWaterLevelSync(std::string deviceId, std::string dstDeviceId, + std::vector content) override; +}; +} // namespace OHOS::DistributedData +#endif // WLMATRIX_WLSYNC_STRATEGY_H diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/src/devices_simulator.cpp b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/devices_simulator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e72e41afdc9c3904b210be9c13d65313bc23cb43 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/devices_simulator.cpp @@ -0,0 +1,760 @@ +/* +* Copyright (c) 2023 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. +*/ +#define LOG_TAG "DeviceSimulator" +#include "devices_simulator.h" +#include "log_print.h" +namespace OHOS::DistributedData { +DevicesSimulator &DevicesSimulator::GetInstance() +{ + static DevicesSimulator instance; + return instance; +} + +void DevicesSimulator::Init(std::int32_t deviceNum) +{ + if (deviceNum < MAX_DEVICE_NUM) { + if (devices.empty()) { + perfIndex.error_pull = 0; + perfIndex.pull_count = 0; + perfIndex.push_gene_count = 0; + wlSyncScheduler = std::make_unique("simulator"); + } + std::string deviceName_base = "Device_"; + std::vector installedApps; + // install the app in scene pull + for (std::int32_t i = 0; i < DEFAULT_APP_NUM; i++) { + installedApps.push_back(i); + } + // install the app in scene push + for (std::int32_t i = 0; i < DEFAULT_PUSH_APP_NUM; i++) { + installedApps.push_back(PUSH_APP_BOUND + i); + } + for (int32_t i = 0; i < deviceNum; i++) { + std::string deviceId = deviceName_base + std::to_string(i); + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = i < MAX_ACTIVE_DEVICES ? WlDeviceStatus::WL_DEVICE_ACTIVE + : WlDeviceStatus::WL_DEVICE_SLEEP, + .installedApps = installedApps, + .wlVersion = WlVersion::CURRENT_WATER_LEVEL }; + AddDevice(deviceId, wlDeviceInfo); + perfIndex.awake_count.insert_or_assign(deviceId, 0); + perfIndex.baseline_awake.insert_or_assign(deviceId, 0); + + perfIndex.push_awake_count.insert_or_assign(deviceId, 0); + perfIndex.push_baseline.insert_or_assign(deviceId, 0); + perfIndex.access_error_count.insert_or_assign(deviceId, 0); + perfIndex.access_count.insert_or_assign(deviceId, 0); + } + } +} + +std::vector DevicesSimulator::GetDeviceList() +{ + std::vector deviceLst; + for (const auto &it : devices) { + deviceLst.push_back(it.first); + } + return deviceLst; +} + +void DevicesSimulator::AddDevice(const std::string &deviceName, const WlDeviceInfo &wlDeviceInfo) +{ + if (devices.find(deviceName) == devices.end()) { + std::shared_ptr device_node = std::make_shared(); + device_node->Init(deviceName, wlDeviceInfo); + + for (const auto &it : GetDeviceList()) { + device_node->SetRemoteDeviceInfo(it, devices[it]->GetLocalDeviceInfo()); + devices[it]->SetRemoteDeviceInfo(deviceName, wlDeviceInfo); + + // add build link feature + device_node->OnReceiveBuildLinkFeature(it, devices[it]->SendBuildLinkFeature()); + devices[it]->OnReceiveBuildLinkFeature(deviceName, device_node->SendBuildLinkFeature()); + } + devices.insert_or_assign(deviceName, device_node); + + perfIndex.awake_count.insert_or_assign(deviceName, 0); + } +} + +void DevicesSimulator::SetWlAIMDFactor(WlAIMDFactor wlAimdFactor) +{ + for (auto it : GetDeviceList()) { + devices[it]->SetWlAIMDFactor(wlAimdFactor); + } +} + +void DevicesSimulator::SetDeviceOnline(const std::string &deviceId) +{ + // deviceId power on first + if (devices.find(deviceId) != devices.end()) { + devices[deviceId]->OnPowerOn(); + DeviceSendingAppLst(deviceId); + + for (const auto &it : GetDeviceList()) { + if (deviceId != it) { + devices[it]->OnRemoteDeviceOnline(deviceId); + + DeviceSyncAppLstWithPeer(it, deviceId); + DeviceSyncWaterLevelWithPeer(it, deviceId); + } + } + } +} + +void DevicesSimulator::SetDeviceOffline(const std::string &deviceId) +{ + if (devices.find(deviceId) != devices.end()) { + devices[deviceId]->OnPowerOff(); + + for (const auto &it : GetDeviceList()) { + if (deviceId != it) { + // check the buff and push the data immediately, OnPowerOff have set the signal + DevicePushToPeer(deviceId, it); + wlSyncScheduler->ClearTasksById(deviceId + it); + devices[it]->OnRemoteDeviceOffline(deviceId); + } + } + } +} + +void DevicesSimulator::SetDeviceActive(const std::string &deviceId) +{ + if (devices.find(deviceId) != devices.end()) { + devices[deviceId]->OnPowerOn(); + devices[deviceId]->SetLocalDeviceStatus(WlDeviceStatus::WL_DEVICE_ACTIVE); + DeviceSendingAppLst(deviceId); + + for (const auto &it : GetDeviceList()) { + if (deviceId != it) { + devices[it]->OnRemoteDeviceActive(deviceId); + DeviceSyncAppLstWithPeer(it, deviceId); + DeviceSyncWaterLevelWithPeer(it, deviceId); + // push to active device + DevicePushToPeer(it, deviceId); + wlSyncScheduler->ClearTasksById(it + deviceId); + } + } + } +} + +void DevicesSimulator::SetDeviceSleep(const std::string &deviceId) +{ + if (devices.find(deviceId) != devices.end()) { + devices[deviceId]->OnChangeAsleep(); + DeviceSendingWaterLevel(deviceId); + + for (const auto &it : GetDeviceList()) { + if (deviceId != it) { + DevicePushToPeer(deviceId, it); + wlSyncScheduler->ClearTasksById(deviceId + it); + devices[it]->OnRemoteDeviceSleep(deviceId); + } + } + } +} + +void DevicesSimulator::SetDeviceDataGene(const std::string &deviceId, std::uint8_t appId, std::uint8_t typeId) +{ + if (devices.find(deviceId) != devices.end()) { + devices[deviceId]->OnDataGenerating(appId, typeId); + if ((std::int32_t)appId < PUSH_APP_BOUND) { + DeviceSendingWaterLevel(deviceId); + } else { + DevicePushing(deviceId, appId); + perfIndex.push_gene_count += 1; + } + } +} + +void DevicesSimulator::SetDeviceDataCons(const std::string &deviceId, std::uint8_t appId) +{ + if (devices.find(deviceId) != devices.end()) { + if ((std::int32_t)appId < PUSH_APP_BOUND) { + if (devices[deviceId]->GetLocalDeviceInfo().wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ACTIVE) { + DeviceDataConsPull(deviceId, appId); + } + } else { + DeviceDataConsPush(deviceId, appId); + } + } +} + +void DevicesSimulator::SetDeviceInstalledApp(const std::string &deviceId, std::uint8_t appId) +{ + if (devices.find(deviceId) != devices.end()) { + auto currentApps = devices[deviceId]->GetLocalInstalledApps(); + auto infoStr = deviceId; + if (std::find(currentApps.begin(), currentApps.end(), appId) != currentApps.end()) { + infoStr += " local installed Apps is not change\n"; + } else { + infoStr += " install new Apps: " + std::to_string(static_cast(appId)) + "\n"; + currentApps.push_back(appId); + } + devices[deviceId]->SetLocalInstalledApps(currentApps); + DeviceSendingAppLst(deviceId); + ZLOGI("%{public}s", infoStr.c_str()); + } +} + +void DevicesSimulator::SetDeviceWlVersion(const std::string &deviceId, WlVersion version) +{ + if (devices.find(deviceId) != devices.end()) { + devices[deviceId]->SetWlVersion(version); + for (auto it : GetDeviceList()) { + if (it != deviceId) { + devices[it]->OnRemoteDeviceSetWlVersion(deviceId, version); + } + } + } +} + +void DevicesSimulator::DeviceDataConsPull(const std::string &deviceId, std::uint8_t appId) +{ + auto syncDevices = devices[deviceId]->OnDataConsuming(appId); + auto groundTruth = DevicesListOfFreshAppData(deviceId, appId); + + ZLOGI("PULL [%{public}d], GroundTruth: [%{public}s], Ours: [%{public}s]", perfIndex.pull_count, + JoinStrings(groundTruth, ",").c_str(), JoinStrings(syncDevices, ",").c_str()); + // device pull data from target devices + DevicePullFrom(deviceId, syncDevices); + + perfIndex.pull_count += 1; + if (!IsVectorSetEqual(groundTruth, syncDevices)) { + perfIndex.error_pull += 1; + } + + for (const auto &it : syncDevices) { + auto dStatus = devices[it]->GetLocalDeviceInfo().wlDeviceStatus; + if (dStatus == WlDeviceStatus::WL_DEVICE_SLEEP) { + perfIndex.awake_count[it] += 1; + } + } + for (const auto &it : GetDeviceList()) { + auto dStatus = devices[it]->GetLocalDeviceInfo().wlDeviceStatus; + if (dStatus == WlDeviceStatus::WL_DEVICE_SLEEP) { + perfIndex.baseline_awake[it] += 1; + } + } +} + +void DevicesSimulator::DeviceDataConsPush(const std::string &deviceId, std::uint8_t appId) +{ + auto timeStampOfApp = DeviceTimeStampOfApp(appId); + ZLOGI("PUSH: Current Device %{public}s, Current App %{public}d, the timeStamp of each device is " + "%{public}s", + deviceId.c_str(), (int)appId, MapToString(timeStampOfApp).c_str()); + for (auto [peer, appTime] : timeStampOfApp) { + if (timeStampOfApp[deviceId] < appTime) { + perfIndex.access_error_count[deviceId] += 1; + ZLOGI("PUSH ERROR"); + break; + } + } + perfIndex.access_count[deviceId] += 1; +} + +std::vector DevicesSimulator::GetDeviceInstalledApps(const std::string &deviceId) +{ + std::vector installedApps; + if (devices.find(deviceId) != devices.end()) { + installedApps = devices[deviceId]->GetLocalDeviceInfo().installedApps; + } + return installedApps; +} + +int32_t DevicesSimulator::GetDeviceStatus(const std::string &deviceId) +{ + if (devices.find(deviceId) != devices.end()) { + return static_cast(devices[deviceId]->GetLocalDeviceInfo().wlDeviceStatus); + } + return -1; +} + +std::string DevicesSimulator::DisplayDeviceDatabase(const std::string &deviceId) +{ + std::string infoStr; + if (devices.find(deviceId) != devices.end()) { + infoStr = devices[deviceId]->GetMockDatabaseString(); + } + return infoStr; +} + +std::string DevicesSimulator::DisplayDeviceWaterLevelMatrix(const std::string &deviceId) +{ + std::string infoStr; + if (devices.find(deviceId) != devices.end()) { + infoStr = devices[deviceId]->GetWaterLevelString(); + } + return infoStr; +} + +std::string DevicesSimulator::DisplayDeviceSyncMatrix(const std::string &deviceId) +{ + std::string infoStr; + if (devices.find(deviceId) != devices.end()) { + infoStr = devices[deviceId]->GetDeviceSyncString(); + } + return infoStr; +} + +std::string DevicesSimulator::DisplayDeviceInstalledApp(const std::string &deviceId) +{ + std::string infoStr; + if (devices.find(deviceId) != devices.end()) { + infoStr.append("install Apps: "); + for (auto it : devices[deviceId]->GetLocalInstalledApps()) { + infoStr.append(std::to_string(static_cast(it))); + infoStr.append(" "); + } + infoStr.append("\n"); + } + return infoStr; +} + +void DevicesSimulator::ClearDeviceSimulator() +{ + if (!devices.empty()) { + for (auto it = devices.begin(); it != devices.end();) { + it->second.reset(); + it->second = nullptr; + it++; + } + devices.clear(); + // clear performance index + perfIndex.pull_count = 0; + perfIndex.error_pull = 0; + perfIndex.baseline_awake.clear(); + perfIndex.awake_count.clear(); + + perfIndex.push_baseline.clear(); + perfIndex.push_awake_count.clear(); + perfIndex.access_count.clear(); + perfIndex.access_error_count.clear(); + } +} + +void DevicesSimulator::DeviceReceiveWaterLevel(const std::string &deviceId, const CommBuff &commBuff_) +{ + if (deviceId == commBuff_.dstDevice) { + bool receiveTag = devices[deviceId]->OnReceivedWaterLevel(commBuff_.sourceId, commBuff_.bytes); + if (receiveTag && devices[deviceId]->GetLocalDeviceInfo().wlDeviceStatus == WlDeviceStatus::WL_DEVICE_SLEEP) { + // awake these devices and successfully send the wl + perfIndex.awake_count[deviceId] += 1; + } + } +} + +void DevicesSimulator::DeviceSendingWaterLevel(const std::string &srcDeviceId) +{ + for (const auto &it : GetDeviceList()) { + if (it != srcDeviceId) { + // tag -> true buff need to be received + if (commBuff.find(srcDeviceId + it) != commBuff.end()) { + if (commBuff[srcDeviceId + it].commTag) { + DeviceReceiveWaterLevel(it, commBuff[srcDeviceId + it]); + commBuff[srcDeviceId + it].commTag = false; + } + } + } + } +} + +void DevicesSimulator::DeviceSyncWaterLevelWithPeer(const std::string &srcDeviceId, const std::string &dstDeviceId) +{ + if (commBuff.find(srcDeviceId + dstDeviceId) != commBuff.end()) { + if (commBuff[srcDeviceId + dstDeviceId].commTag) { + DeviceReceiveWaterLevel(dstDeviceId, commBuff[srcDeviceId + dstDeviceId]); + commBuff[srcDeviceId + dstDeviceId].commTag = false; + } + } +} + +void DevicesSimulator::DeviceReceiveAppLst(const std::string &deviceId, const CommBuff &commBuff_) +{ + if (deviceId == commBuff_.dstDevice) { + devices[deviceId]->OnReceiveInstalledApps(commBuff_.sourceId, commBuff_.app_bytes); + } +} + +void DevicesSimulator::DeviceSendingAppLst(const std::string &srcDeviceId) +{ + for (const auto &it : GetDeviceList()) { + if (it != srcDeviceId) { + if (commBuff.find(srcDeviceId + it) != commBuff.end()) { + if (commBuff[srcDeviceId + it].app_commTag) { + DeviceReceiveAppLst(it, commBuff[srcDeviceId + it]); + commBuff[srcDeviceId + it].app_commTag = false; + } + } + } + } +} + +void DevicesSimulator::DeviceSyncAppLstWithPeer(const std::string &srcDeviceId, const std::string &dstDeviceId) +{ + if (commBuff.find(srcDeviceId + dstDeviceId) != commBuff.end()) { + if (commBuff[srcDeviceId + dstDeviceId].app_commTag) { + DeviceReceiveAppLst(dstDeviceId, commBuff[srcDeviceId + dstDeviceId]); + commBuff[srcDeviceId + dstDeviceId].app_commTag = false; + } + } +} + +void DevicesSimulator::DevicePullFrom(const std::string &srcDeviceId, const std::vector &dstDevices) +{ + for (const auto &it : dstDevices) { + if (it != srcDeviceId) { + std::string buffKey_ = it + srcDeviceId; + if (commBuff.find(buffKey_) != commBuff.end()) { + if (commBuff[buffKey_].data_commTag) { + auto changedApps = devices[it]->OnPulledBy(srcDeviceId); + for (auto app : changedApps) { + auto tran_data = devices[it]->GetMockDatabaseOfApp(app); + devices[srcDeviceId]->OnReceivedData(it, app, tran_data); + } + commBuff[buffKey_].data_commTag = false; + } + } + } + } +} + +void DevicesSimulator::DevicePushing(std::string srcDeviceId, std::uint8_t appId) +{ + for (auto it : GetDeviceList()) { + if (it != srcDeviceId) { + double delay = devices[srcDeviceId]->GetPushDelay(it, appId); + std::string pushTaskId = srcDeviceId + it; + wlSyncScheduler->AddWlTask(pushTaskId, + std::bind(&DevicesSimulator::DevicePushToPeer, this, srcDeviceId, it), + std::chrono::milliseconds(ConvertSecondToMilli(delay)), 0); + ZLOGI("%{public}s: %{public}s push App %{public}d data to %{public}s with [Delay]: %{public}f", + GetCurrentTimeStr().c_str(), srcDeviceId.c_str(), (int)appId, it.c_str(), delay); + + // count baseline awake + if (devices[it]->GetLocalDeviceInfo().wlDeviceStatus == WlDeviceStatus::WL_DEVICE_SLEEP) { + perfIndex.push_baseline[it] += 1; + } + } + } +} + +void DevicesSimulator::DevicePushToPeer(std::string srcDeviceId, std::string dstDeviceId) +{ + std::string buffKey_ = srcDeviceId + dstDeviceId; + if (commBuff.find(buffKey_) != commBuff.end()) { + if (commBuff[buffKey_].pushCommTag) { + auto pushAppLst = devices[srcDeviceId]->OnPushTo(dstDeviceId); + for (auto it : pushAppLst) { + auto tran_data = devices[srcDeviceId]->GetMockDatabaseOfApp(it); + devices[dstDeviceId]->OnReceivedData(srcDeviceId, it, tran_data); + } + if (devices[dstDeviceId]->GetLocalDeviceInfo().wlDeviceStatus == WlDeviceStatus::WL_DEVICE_SLEEP) { + perfIndex.push_awake_count[dstDeviceId] += 1; + } + commBuff[buffKey_].pushCommTag = false; + ZLOGI("%{public}s: %{public}s sync with %{public}s now.", GetCurrentTimeStr().c_str(), srcDeviceId.c_str(), + dstDeviceId.c_str()); + } + } +} + +std::map DevicesSimulator::DeviceTimeStampOfApp(std::uint8_t appId) +{ + std::map dataStamp; + for (auto it : GetDeviceList()) { + dataStamp.insert_or_assign(it, devices[it]->GetMockDatabaseOfApp(appId)); + } + return dataStamp; +} + +std::vector DevicesSimulator::DevicesListOfFreshAppData(const std::string &deviceId, std::uint8_t appId) +{ + std::vector devicesList; + for (const auto &it : GetDeviceList()) { + if (deviceId != it) { + if (devices[it]->CheckToBePulled(deviceId, appId)) { + devicesList.push_back(it); + } + } + } + return devicesList; +} + +std::string DevicesSimulator::PerformanceIndexSummary() +{ + std::string summaryStr = "PullIndex -> Pull: " + std::to_string(perfIndex.pull_count) + + " Pull Error: " + std::to_string(perfIndex.error_pull) + "\n"; + int awake_summary = 0; + int baseline_summary = 0; + for (const auto &it : perfIndex.awake_count) { + awake_summary += perfIndex.awake_count[it.first]; + baseline_summary += perfIndex.baseline_awake[it.first]; + } + summaryStr += "Awakenings -> Ours: " + std::to_string(awake_summary) + + " Baseline: " + std::to_string(baseline_summary) + "\n"; + return summaryStr; +} + +std::vector DevicesSimulator::DisplayPerformanceIndexList() +{ + std::vector perfIndexLst; + // head str + perfIndexLst.emplace_back("DeviceName"); + perfIndexLst.emplace_back("Baseline"); + perfIndexLst.emplace_back("Ours"); + perfIndexLst.emplace_back("Diff"); + + std::int32_t baselineSum = 0; + std::int32_t oursSum = 0; + std::int32_t diffSum = 0; + // awake times content + for (const auto &it : GetDeviceList()) { + auto diff_it = static_cast(perfIndex.baseline_awake[it] - perfIndex.awake_count[it]); + baselineSum += perfIndex.baseline_awake[it]; + oursSum += perfIndex.awake_count[it]; + diffSum += diff_it; + + perfIndexLst.push_back(it); + perfIndexLst.push_back(std::to_string(perfIndex.baseline_awake[it])); + perfIndexLst.push_back(std::to_string(perfIndex.awake_count[it])); + perfIndexLst.push_back(std::to_string(diff_it)); + } + // awake summary + perfIndexLst.emplace_back("Summary"); + perfIndexLst.push_back(std::to_string(baselineSum)); + perfIndexLst.push_back(std::to_string(oursSum)); + perfIndexLst.push_back(std::to_string(diffSum)); + + // pull times and error + perfIndexLst.emplace_back("Pull"); + perfIndexLst.push_back(std::to_string(perfIndex.pull_count)); + perfIndexLst.emplace_back("Error"); + perfIndexLst.push_back(std::to_string(perfIndex.error_pull)); + + return perfIndexLst; +} + +std::string DevicesSimulator::PushPerfIndexSummary() +{ + std::string summaryStr = "Data Generation: " + std::to_string(perfIndex.push_gene_count); + + return summaryStr; +} + +std::vector DevicesSimulator::DisplayPushPerfIndexList() +{ + std::vector pushPerfIndexLst; + pushPerfIndexLst.emplace_back("DeviceName"); + pushPerfIndexLst.emplace_back("Baseline"); + pushPerfIndexLst.emplace_back("Ours"); + pushPerfIndexLst.emplace_back("Diff"); + pushPerfIndexLst.emplace_back("Access"); + pushPerfIndexLst.emplace_back("Error"); + + std::int32_t baselineSum = 0; + std::int32_t oursSum = 0; + std::int32_t diffSum = 0; + std::int32_t accessSum = 0; + std::int32_t errorSum = 0; + + for (auto it : GetDeviceList()) { + auto diff_it = static_cast(perfIndex.push_baseline[it] - perfIndex.push_awake_count[it]); + baselineSum += perfIndex.push_baseline[it]; + oursSum += perfIndex.push_awake_count[it]; + diffSum += diff_it; + accessSum += perfIndex.access_count[it]; + errorSum += perfIndex.access_error_count[it]; + + pushPerfIndexLst.push_back(it); + pushPerfIndexLst.push_back(std::to_string(perfIndex.push_baseline[it])); + pushPerfIndexLst.push_back(std::to_string(perfIndex.push_awake_count[it])); + pushPerfIndexLst.push_back(std::to_string(diff_it)); + pushPerfIndexLst.push_back(std::to_string(perfIndex.access_count[it])); + pushPerfIndexLst.push_back(std::to_string(perfIndex.access_error_count[it])); + } + pushPerfIndexLst.emplace_back("Summary"); + pushPerfIndexLst.push_back(std::to_string(baselineSum)); + pushPerfIndexLst.push_back(std::to_string(oursSum)); + pushPerfIndexLst.push_back(std::to_string(diffSum)); + pushPerfIndexLst.push_back(std::to_string(accessSum)); + pushPerfIndexLst.push_back(std::to_string(errorSum)); + + pushPerfIndexLst.emplace_back("DataGene"); + pushPerfIndexLst.push_back(std::to_string(perfIndex.push_gene_count)); + return pushPerfIndexLst; +} + +void DevicesSimulator::AutoTestCase(std::int32_t testNum) +{ + // test already init + if (!devices.empty()) { + while (perfIndex.pull_count < testNum) { + std::vector activeDevices, sleepDevices; + // get the current devices list + for (const auto &it : GetDeviceList()) { + if (devices[it]->GetLocalDeviceInfo().wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ACTIVE) { + activeDevices.push_back(it); + } else if (devices[it]->GetLocalDeviceInfo().wlDeviceStatus == WlDeviceStatus::WL_DEVICE_SLEEP) { + sleepDevices.push_back(it); + } + } + std::string currentDevice = GetRandomElement(activeDevices, (int)activeDevices.size()); + std::uint8_t currentApp = GetRandomElement(GetDeviceInstalledApps(currentDevice), + (int)GetDeviceInstalledApps(currentDevice).size()); + + // current device random an App, then generating + SetDeviceDataGene(currentDevice, currentApp, 0); + + // active device cons + for (const auto &it : activeDevices) { + if (it != currentDevice) { + SetDeviceDataCons(it, currentApp); + } + } + // set device sleep + currentDevice = GetRandomElement(activeDevices, (int)activeDevices.size()); + SetDeviceSleep(currentDevice); + + // sleep device cons + for (const auto &it : sleepDevices) { + SetDeviceActive(it); + SetDeviceDataCons(it, currentApp); + SetDeviceSleep(it); + } + + // select next active device + currentDevice = GetRandomElement(sleepDevices, (int)sleepDevices.size()); + SetDeviceActive(currentDevice); + } + } +} + +void DevicesSimulator::AutoTestCase2(std::int32_t testNum) +{ + if (!devices.empty()) { + while (perfIndex.pull_count < testNum) { + std::vector activeDevices, sleepDevices; + // get the current devices list + for (const auto &it : GetDeviceList()) { + if (devices[it]->GetLocalDeviceInfo().wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ACTIVE) { + activeDevices.push_back(it); + } else if (devices[it]->GetLocalDeviceInfo().wlDeviceStatus == WlDeviceStatus::WL_DEVICE_SLEEP) { + sleepDevices.push_back(it); + } + } + std::string readySleepDevice = GetRandomElement(activeDevices, (int)activeDevices.size()); + SetDeviceSleep(readySleepDevice); + std::string readyActiveDevice = GetRandomElement(sleepDevices, (int)sleepDevices.size()); + SetDeviceActive(readyActiveDevice); + + std::int32_t repeat_time = static_cast(GetUniformRandomValue((int)0, DATA_CONSUME_TIME)); + + for (int32_t i = 0; i < repeat_time; i++) { + std::uint8_t currentApp = GetRandomElement(GetDeviceInstalledApps(readySleepDevice), + (int)GetDeviceInstalledApps(readySleepDevice).size()); + SetDeviceDataCons(readyActiveDevice, currentApp); + + SetDeviceDataGene(readyActiveDevice, currentApp, 0); + } + } + } +} + +void DevicesSimulator::PushAutoTestCase(std::int32_t testNum, int onlineLow, int onlineHigh, double dataGeneFreq) +{ + if (!devices.empty()) { + while (perfIndex.push_gene_count < testNum) { + std::vector activeDevices, sleepDevices; + for (const auto &it : GetDeviceList()) { + if (devices[it]->GetLocalDeviceInfo().wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ACTIVE) { + activeDevices.push_back(it); + } else if (devices[it]->GetLocalDeviceInfo().wlDeviceStatus == WlDeviceStatus::WL_DEVICE_SLEEP) { + sleepDevices.push_back(it); + } + } + std::string currentDevice = GetRandomElement(activeDevices, activeDevices.size()); + std::string sleepToOfflineDevice = GetRandomElement(sleepDevices, sleepDevices.size()); + std::vector pushAppLst; + std::vector dataGeneAppLst; + for (auto app : GetDeviceInstalledApps(currentDevice)) { + if ((std::int32_t)app >= PUSH_APP_BOUND) { + pushAppLst.push_back(app); + } + } + for (auto app : pushAppLst) { + if (GetRandomWithProb(dataGeneFreq)) { + dataGeneAppLst.push_back(app); + SetDeviceDataGene(currentDevice, app, 0); + } + } + int onlineTime = GetUniformRandomValue(onlineLow, onlineHigh); + ZLOGI("%{public}s online %{public}f", currentDevice.c_str(), (double)onlineTime / TIME_CONVERT); + + std::this_thread::sleep_for(std::chrono::milliseconds(onlineTime)); + + SetDeviceOffline(sleepToOfflineDevice); + for (auto it : dataGeneAppLst) { + SetDeviceDataCons(sleepToOfflineDevice, it); + } + // status change + SetDeviceActive(sleepToOfflineDevice); + SetDeviceSleep(currentDevice); + } + } +} + +void DevicesSimulator::PushAutoTestCase2(std::int32_t testNum, int onlineLow, int onlineHigh, double waitPeriod) +{ + if (!devices.empty()) { + while (perfIndex.push_gene_count < testNum) { + std::vector activeDevices, sleepDevices; + for (const auto &it : GetDeviceList()) { + if (devices[it]->GetLocalDeviceInfo().wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ACTIVE) { + activeDevices.push_back(it); + } else if (devices[it]->GetLocalDeviceInfo().wlDeviceStatus == WlDeviceStatus::WL_DEVICE_SLEEP) { + sleepDevices.push_back(it); + } + } + std::string currentDevice = GetRandomElement(activeDevices, activeDevices.size()); + std::string sleepToOfflineDevice = GetRandomElement(sleepDevices, sleepDevices.size()); + + std::vector currentDeviceApp = GetDeviceInstalledApps(currentDevice); + int onlineTime = GetUniformRandomValue(onlineLow, onlineHigh); + std::vector pushAppLst; + std::int32_t repeatTime = static_cast(GetUniformRandomValue(0, (int)currentDeviceApp.size())); + for (int i = 0; i < repeatTime; i++) { + std::uint8_t appId = GetRandomElement(currentDeviceApp, currentDeviceApp.size()); + int appIdGenePeriod = GetUniformRandomValue(0, onlineTime); + pushAppLst.push_back(appId); + wlSyncScheduler->AddWlTask(currentDevice + "Gene" + std::to_string((int)appId), + std::bind(&DevicesSimulator::SetDeviceDataGene, this, currentDevice, appId, 0), + std::chrono::milliseconds(appIdGenePeriod), 0); + } + ZLOGI("%{public}s online %{public}f", currentDevice.c_str(), (double)onlineTime / TIME_CONVERT); + + std::this_thread::sleep_for(std::chrono::milliseconds(onlineTime + ConvertSecondToMilli(waitPeriod))); + + SetDeviceOffline(sleepToOfflineDevice); + for (auto it : pushAppLst) { + SetDeviceDataCons(sleepToOfflineDevice, it); + } + // status change + SetDeviceActive(sleepToOfflineDevice); + SetDeviceSleep(currentDevice); + } + } +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/src/local_device_status_listener.cpp b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/local_device_status_listener.cpp new file mode 100644 index 0000000000000000000000000000000000000000..85be2ca1488b2d031cb1cbd28d4e698dc90470d0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/local_device_status_listener.cpp @@ -0,0 +1,669 @@ +/* +* Copyright (c) 2023 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. +*/ +#define LOG_TAG "LocalDeviceStatusListener" + +#include "local_device_status_listener.h" +namespace OHOS::DistributedData { +void LocalDeviceStatusListener::Init(std::string deviceId, WlDeviceInfo wlDeviceInfo) +{ + waterLevelMatrix_ = std::make_unique(); + wlSyncService_ = std::make_unique(); + wlStatusStatistic_ = std::make_unique(); + deviceSyncMatrix_ = std::make_unique(); + wlHelper_ = std::make_unique(); + mockDatabase_ = std::make_unique(); + sysDataSyncService_ = std::make_unique(wlDeviceInfo.wlAimdFactor); + + wlSyncService_->SendDataFunction = wlHelper_->SendDataFunction; + + // DeviceName Init + if (IsDeviceNameValid(deviceId) && deviceId != DEFAULT_DEVICE_ID) { + SetLocalDeviceId(deviceId); + waterLevelMatrix_->Init(deviceId); + } else { + ZLOGE("%{public}s", E_WL_INVALID_DEVICE_ID.c_str()); + } + + std::string infoStr = deviceId_ + " Init"; + ZLOGI("%{public}s", infoStr.c_str()); + + // DeviceInfo Init + SetLocalDeviceInfo(wlDeviceInfo); +} + +void LocalDeviceStatusListener::OnPowerOn() +{ + std::string infoStr = deviceId_ + " Power On"; + ZLOGI("%{public}s", infoStr.c_str()); + + // Get/Update the status of each device in the network + if (!wlHelper_->GetRemoteDevicesStatusFunction().empty()) { + remoteDevicesStatus_ = wlHelper_->GetRemoteDevicesStatusFunction(); + } else { + ZLOGE("CODE: WL01, Can not Access to the network, get remote devices status update fail"); + } + // Check the local installed Apps, trans to all other active devices + SetLocalDeviceStatus(WlDeviceStatus::WL_DEVICE_ONLINE); + CheckingInstalledAppsSync(); +} + +void LocalDeviceStatusListener::OnPowerOff() +{ + std::string infoStr = deviceId_ + " Power Off, LocalDeviceStatusListener stop"; + ZLOGI("%{public}s", infoStr.c_str()); + // local status change from active to offline, force to push + if (localDeviceInfo_.wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ACTIVE) { + for (auto it : GetDevicesWithStatus(WlDeviceStatus::WL_DEVICE_ONLINE)) { + if (it != deviceId_) { + if (!sysDataSyncService_->IsSyncBuffLstEmpty(it)) { + PushData(it); + } + } + } + } else { + ZLOGE("CODE: WL01, Can not Access to the network, local device is not active"); + } + SetLocalDeviceStatus(WlDeviceStatus::WL_DEVICE_OFFLINE); +} + +void LocalDeviceStatusListener::OnChangeAsleep() +{ + std::string infoStr = deviceId_ + " Active/Online -> Sleep"; + ZLOGI("%{public}s", infoStr.c_str()); + + std::vector syncList; + // get the devices that have not been sync-ed, then sync these waterlevel by buildlinks + if (localDeviceInfo_.wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ACTIVE || + localDeviceInfo_.wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ONLINE) { + auto deviceList = wlSyncService_->GetSyncDevices(true); + + for (auto it : deviceList) { + if (remoteDevicesStatus_[it].wlDeviceStatus != WlDeviceStatus::WL_DEVICE_OFFLINE) { + syncList.push_back(it); + } + } + SendWaterLevel(syncList); + + for (auto it : GetDevicesWithStatus(WlDeviceStatus::WL_DEVICE_ONLINE)) { + if (it != deviceId_) { + if (!sysDataSyncService_->IsSyncBuffLstEmpty(it)) { + PushData(it); + } + } + } + } else { + ZLOGE("CODE: WL01, Can not Access to the network, local device is not active or online"); + } + + SetLocalDeviceStatus(WlDeviceStatus::WL_DEVICE_SLEEP); +} + +std::vector LocalDeviceStatusListener::OnDataConsuming(std::uint8_t appId) +{ + std::vector syncDevices; + if (localDeviceInfo_.wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ACTIVE || + localDeviceInfo_.wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ONLINE) { + // + std::string infoStr = deviceId_ + " is using App :" + std::to_string(static_cast(appId)); + ZLOGI("%{public}s", infoStr.c_str()); + + infoStr = deviceId_ + " Get Sync Devices"; + ZLOGI("%{public}s", infoStr.c_str()); + + // version check + if (localDeviceInfo_.wlVersion == WlVersion::CURRENT_WATER_LEVEL) { + syncDevices = deviceSyncMatrix_->GetSyncDeviceList(appId); + syncDevices = CombVec(syncDevices, GetOldVersionDevices()); + } else if (localDeviceInfo_.wlVersion == WlVersion::OLDER_WATER_LEVEL) { + syncDevices = GetAllDevices(); + } + + ZLOGI("Current water level version is %{public}d, %{public}s sync from [%{public}s]", + localDeviceInfo_.wlVersion, deviceId_.c_str(), JoinStrings(syncDevices, ",").c_str()); + + if (!syncDevices.empty()) { + // Pull Data from others + for (auto it : syncDevices) { + wlHelper_->PullFromDevice(deviceId_, it); + + wlStatusStatistic_->PullTimesIncr(appId); + } + } else { + ZLOGI("%{public}s pull from an empty device list", deviceId_.c_str()); + } + } else { + ZLOGE("CODE: WL01, Can not Access to the network, local device is not active or online"); + } + return syncDevices; +} + +void LocalDeviceStatusListener::OnDataGenerating(std::uint8_t appId, std::uint8_t typeId) +{ + if (localDeviceInfo_.wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ACTIVE || + localDeviceInfo_.wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ONLINE) { + std::string generatedData = GetCurrentTimeStr(); + + ZLOGI("%{public}s Generate Data, App %{public}d, value %{public}s, Write to database", deviceId_.c_str(), + (int)appId, generatedData.c_str()); + + if (!mockDatabase_->WriteToDataBase(appId, generatedData)) { + ZLOGE("WL02, Fail to write to database"); + } + + if ((std::int32_t)appId < PUSH_APP_BOUND) { + ZLOGI("%{public}s Set WaterLevelMatrix", deviceId_.c_str()); + waterLevelMatrix_->SetSubWaterLevelMatrix(appId, typeId); + // set the sync tag of WaterLevelMatrix, and (true) for it should be sync-ed with other devices + // if the wlVersion is old version, no need to set the tag + for (auto it : GetAllDevices()) { + // add for compatibility + if (remoteDevicesStatus_[it].wlVersion == WlVersion::CURRENT_WATER_LEVEL) { + wlSyncService_->SetSendTag(it, true); + } + } + // Sync WaterLevelMatrix to active device + ZLOGI("%{public}s Sync WaterLevelMatrix to active device", deviceId_.c_str()); + if (wlStatusStatistic_->IsBuildLinks(appId)) { + wlSyncService_->SetSyncStrategy(true); + auto targetDevices = GetDevicesWithStatus(WlDeviceStatus::WL_DEVICE_ACTIVE); + targetDevices = wlStatusStatistic_->GetBuildLinksOrder(targetDevices, appId); + SendWaterLevel(targetDevices); + } + } else { + for (auto it : GetAllDevices()) { + sysDataSyncService_->AddAppToSyncBuffLst(it, appId); + PushData(it); + } + } + } +} + +std::vector LocalDeviceStatusListener::OnPulledBy(std::string sourceDeviceId) +{ + std::string infoStr = deviceId_ + " pulled by (send to) " + sourceDeviceId; + if (localDeviceInfo_.wlDeviceStatus == WlDeviceStatus::WL_DEVICE_SLEEP) { + infoStr += deviceId_ + " should be [awaken]"; + } + ZLOGI("%{public}s", infoStr.c_str()); + + auto dataChangedApp = waterLevelMatrix_->CompressWaterLevelMatrixApp(sourceDeviceId); + + infoStr = deviceId_ + " reset DeviceWaterLevel"; + ZLOGI("%{public}s", infoStr.c_str()); + + waterLevelMatrix_->ResetDeviceWaterLevel(sourceDeviceId); + + return dataChangedApp; +} + +bool LocalDeviceStatusListener::OnReceivedWaterLevel(std::string sourceDeviceId, std::vector bytes) +{ + if (localDeviceInfo_.wlDeviceStatus == WlDeviceStatus::WL_DEVICE_OFFLINE) { + return false; + } else { + std::string infoStr = deviceId_ + " successfully recv WaterLevel from " + sourceDeviceId; + ZLOGI("%{public}s", infoStr.c_str()); + + // decompress the received bytes to WaterLevel info + auto receivedWl = DecompressWaterLevel(bytes); + if (receivedWl.empty()) { + ZLOGE("WL04, No data of bytes"); + } + + infoStr = deviceId_ + " Update SyncMatrix"; + ZLOGI("%{public}s", infoStr.c_str()); + + deviceSyncMatrix_->UpdateDeviceSyncMatrix(sourceDeviceId, receivedWl); + + return true; + } +} + +void LocalDeviceStatusListener::OnReceiveInstalledApps(std::string sourceDeviceId, std::vector bytes) +{ + std::string infoStr = deviceId_ + " successfully recv App list from " + sourceDeviceId; + ZLOGI("%{public}s", infoStr.c_str()); + + infoStr = deviceId_ + " Update WaterLevelMatrix & RemoteDeviceInfo"; + ZLOGI("%{public}s", infoStr.c_str()); + + auto intersectionApps = VectorsIntersection(GetLocalInstalledApps(), bytes); + if (bytes.empty() || intersectionApps.empty()) { + ZLOGE("WL04, No data of bytes"); + } + + waterLevelMatrix_->UpdateWaterLevelMatrix(sourceDeviceId, intersectionApps); + SetPeerInstalledApps(sourceDeviceId, bytes); +} + +void LocalDeviceStatusListener::OnReceivedData(std::string deviceId, std::uint8_t appId, std::string bytes) +{ + std::string infoStr = deviceId_ + " successfully recv Database from " + deviceId; + ZLOGI("%{public}s", infoStr.c_str()); + + // if pull the data success + infoStr = deviceId_ + " Remove " + deviceId + " from SyncMatrix & Write " + bytes + " to database"; + ZLOGI("%{public}s", infoStr.c_str()); + + deviceSyncMatrix_->RemoveSyncDevices(appId, deviceId); + if (!mockDatabase_->WriteToDataBase(appId, bytes)) { + ZLOGE("WL02, Fail to write to database"); + } +} + +std::vector LocalDeviceStatusListener::GetLocalInstalledApps() +{ + return localDeviceInfo_.installedApps; +} + +void LocalDeviceStatusListener::SetLocalInstalledApps(std::vector installedApps_) +{ + // check the whether the parameter: [installedApps] all valid, using wlmatrix_config.h to filter + std::vector installedApps; + for (auto it : installedApps_) { + if (IsAppIdValid(it)) { + installedApps.push_back(it); + } + } + + // app has changed + if (!IsVectorSetEqual(localDeviceInfo_.installedApps, installedApps)) { + ZLOGI("Device %{public}s Local installed Apps changed.", deviceId_.c_str()); + /* set the tag to inform, the local installed Apps have changed, + * and (true) for it should be sync-ed with other devices + */ + std::string infoStr = deviceId_ + " Set the App Sync Tag"; + ZLOGI("%{public}s", infoStr.c_str()); + + for (auto it : GetAllDevices()) { + SetAppSyncTag(it, true); + } + + infoStr = deviceId_ + " Update Local SyncMatrix & Database & DeviceInfo & WaterLevelMatrix Apps list"; + ZLOGI("%{public}s", infoStr.c_str()); + + deviceSyncMatrix_->LocalUpdateDeviceSyncMatrix(GetAllDevices(), installedApps); + mockDatabase_->UpdateInstalledApps(installedApps); + localDeviceInfo_.installedApps = installedApps; + + // update WaterLevelMatrix appList with all other devices + for (auto it : remoteDevicesStatus_) { + auto intersecApp = VectorsIntersection(localDeviceInfo_.installedApps, it.second.installedApps); + waterLevelMatrix_->UpdateWaterLevelMatrix(it.first, intersecApp); + } + + // sync the installed apps to other devices + if (localDeviceInfo_.wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ACTIVE || + localDeviceInfo_.wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ONLINE) { + for (auto it : GetDevicesWithStatus(WlDeviceStatus::WL_DEVICE_ACTIVE)) { + SendInstalledApps(it); + } + } + } +} + +void LocalDeviceStatusListener::CheckingInstalledAppsSync() +{ + for (auto it : appSyncTag_) { + // if the App list has not sync + if (it.second && remoteDevicesStatus_[it.first].wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ACTIVE) { + SendInstalledApps(it.first); + } + } +} + +void LocalDeviceStatusListener::SetAppSyncTag(std::string peerDeviceId, bool value_) +{ + appSyncTag_.insert_or_assign(peerDeviceId, value_); +} + +std::vector LocalDeviceStatusListener::GetDevicesAppSync(bool value_) +{ + std::vector syncList; + for (auto it : appSyncTag_) { + if (it.second == value_) { + syncList.push_back(it.first); + } + } + return syncList; +} + +void LocalDeviceStatusListener::SetPeerInstalledApps(std::string peerDeviceId, + std::vector peerInstalledApp) +{ + remoteDevicesStatus_[peerDeviceId].installedApps = peerInstalledApp; +} + +void LocalDeviceStatusListener::SetLocalDeviceId(std::string deviceId) +{ + if (deviceId != DEFAULT_DEVICE_ID && IsDeviceNameValid(deviceId)) { + deviceId_ = std::move(deviceId); + } else { + ZLOGE("%{public}s", E_WL_INVALID_DEVICE_ID.c_str()); + } +} + +std::string LocalDeviceStatusListener::GetLocalDeviceId() +{ + return deviceId_; +} + +// A module for listen to other devices in the network +void LocalDeviceStatusListener::OnRemoteDeviceOnline(std::string peerDeviceId) +{ + // Sync the app list and update the WaterLevelMatrix + // device in the list + ZLOGI("%{public}s Knows %{public}s [Online]", deviceId_.c_str(), peerDeviceId.c_str()); + + if (remoteDevicesStatus_.find(peerDeviceId) != remoteDevicesStatus_.end()) { + remoteDevicesStatus_[peerDeviceId].wlDeviceStatus = WlDeviceStatus::WL_DEVICE_ONLINE; + + // Sync App list with peer + ZLOGI("%{public}s Check App Sync tag of %{public}s", deviceId_.c_str(), peerDeviceId.c_str()); + + if (appSyncTag_[peerDeviceId]) { + SendInstalledApps(peerDeviceId); + } + } else { + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_ONLINE, + .installedApps = std::vector() }; + remoteDevicesStatus_.insert_or_assign(peerDeviceId, wlDeviceInfo); + + ZLOGI("%{public}s Send App list to %{public}s", deviceId_.c_str(), peerDeviceId.c_str()); + + appSyncTag_.insert_or_assign(peerDeviceId, false); + SendInstalledApps(peerDeviceId); + } + // Sync WaterLevel + if (wlSyncService_->GetSendTag(peerDeviceId)) { + ZLOGI("%{public}s Send WaterLevelMatrix", deviceId_.c_str()); + SendWaterLevel(std::vector { peerDeviceId }); + } + // Sync push data + if (!sysDataSyncService_->IsSyncBuffLstEmpty(peerDeviceId)) { + PushData(peerDeviceId); + } +} + +void LocalDeviceStatusListener::OnRemoteDeviceOffline(std::string peerDeviceId) +{ + if (remoteDevicesStatus_.find(peerDeviceId) != remoteDevicesStatus_.end()) { + remoteDevicesStatus_[peerDeviceId].wlDeviceStatus = WlDeviceStatus::WL_DEVICE_OFFLINE; + + ZLOGI("%{public}s Knows %{public}s [Offline]", deviceId_.c_str(), peerDeviceId.c_str()); + } +} + +void LocalDeviceStatusListener::OnRemoteDeviceSleep(std::string peerDeviceId) +{ + if (remoteDevicesStatus_.find(peerDeviceId) != remoteDevicesStatus_.end()) { + remoteDevicesStatus_[peerDeviceId].wlDeviceStatus = WlDeviceStatus::WL_DEVICE_SLEEP; + + ZLOGI("%{public}s Knows %{public}s [Sleep]", deviceId_.c_str(), peerDeviceId.c_str()); + } +} + +void LocalDeviceStatusListener::OnRemoteDeviceActive(std::string peerDeviceId) +{ + ZLOGI("%{public}s Knows %{public}s [Online]", deviceId_.c_str(), peerDeviceId.c_str()); + + if (remoteDevicesStatus_.find(peerDeviceId) != remoteDevicesStatus_.end()) { + remoteDevicesStatus_[peerDeviceId].wlDeviceStatus = WlDeviceStatus::WL_DEVICE_ACTIVE; + // Sync App list with peer + ZLOGI("%{public}s Check App Sync tag of %{public}s", deviceId_.c_str(), peerDeviceId.c_str()); + if (appSyncTag_[peerDeviceId]) { + SendInstalledApps(peerDeviceId); + } + } else { + WlDeviceInfo wlDeviceInfo = { .wlDeviceStatus = WlDeviceStatus::WL_DEVICE_ACTIVE, + .installedApps = std::vector() }; + remoteDevicesStatus_.insert_or_assign(peerDeviceId, wlDeviceInfo); + ZLOGI("%{public}s Send App list to %{public}s", deviceId_.c_str(), peerDeviceId.c_str()); + appSyncTag_.insert_or_assign(peerDeviceId, false); + SendInstalledApps(peerDeviceId); + } + + if (wlSyncService_->GetSendTag(peerDeviceId)) { + ZLOGI("%{public}s Send WaterLevelMatrix", deviceId_.c_str()); + SendWaterLevel(std::vector { peerDeviceId }); + } + // Sync push data + if (!sysDataSyncService_->IsSyncBuffLstEmpty(peerDeviceId)) { + PushData(peerDeviceId); + } +} + +WlDeviceStatus LocalDeviceStatusListener::GetRemoteDeviceStatus(std::string peerDeviceId) +{ + if (remoteDevicesStatus_.find(peerDeviceId) != remoteDevicesStatus_.end()) { + return remoteDevicesStatus_[peerDeviceId].wlDeviceStatus; + } else { + return WlDeviceStatus::WL_DEVICE_OFFLINE; + } +} + +void LocalDeviceStatusListener::SetRemoteDeviceInfo(std::string peerDeviceId, WlDeviceInfo wlDeviceInfo) +{ + ZLOGI("%{public}s Knows %{public}s", deviceId_.c_str(), peerDeviceId.c_str()); + + remoteDevicesStatus_.insert_or_assign(peerDeviceId, wlDeviceInfo); + if (!wlDeviceInfo.installedApps.empty()) { + ZLOGI("%{public}s Update WaterLevelMatrix with %{public}s", deviceId_.c_str(), peerDeviceId.c_str()); + + waterLevelMatrix_->UpdateWaterLevelMatrix(peerDeviceId, wlDeviceInfo.installedApps); + } +} + +WlDeviceInfo LocalDeviceStatusListener::GetLocalDeviceInfo() +{ + return localDeviceInfo_; +} + +void LocalDeviceStatusListener::SetLocalDeviceStatus(WlDeviceStatus wlDeviceStatus) +{ + localDeviceInfo_.wlDeviceStatus = wlDeviceStatus; +} + +void LocalDeviceStatusListener::SetLocalDeviceInfo(WlDeviceInfo wlDeviceInfo) +{ + localDeviceInfo_ = wlDeviceInfo; + if (!localDeviceInfo_.installedApps.empty()) { + deviceSyncMatrix_->Init(localDeviceInfo_.installedApps); + mockDatabase_->Init(localDeviceInfo_.installedApps); + } +} + +std::vector LocalDeviceStatusListener::GetDevicesWithStatus(WlDeviceStatus wlDeviceStatus) +{ + std::vector statusDevices; + if (wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ONLINE) { + for (auto it : remoteDevicesStatus_) { + if (it.second.wlDeviceStatus != WlDeviceStatus::WL_DEVICE_OFFLINE) { + statusDevices.push_back(it.first); + } + } + } else { + for (auto it : remoteDevicesStatus_) { + if (it.second.wlDeviceStatus == wlDeviceStatus) { + statusDevices.push_back(it.first); + } + } + } + return statusDevices; +} + +std::vector LocalDeviceStatusListener::GetAllDevices() +{ + std::vector allDevices; + for (auto it : remoteDevicesStatus_) { + allDevices.push_back(it.first); + } + return allDevices; +} + +std::string LocalDeviceStatusListener::GetWaterLevelString() +{ + return waterLevelMatrix_->DisplayAllSubWaterLevelMatrix(); +} + +std::string LocalDeviceStatusListener::GetDeviceSyncString() +{ + return deviceSyncMatrix_->GetAllSyncDeviceString(); +} + +std::string LocalDeviceStatusListener::GetMockDatabaseString() +{ + return mockDatabase_->DisplayDatabase(); +} + +std::string LocalDeviceStatusListener::GetMockDatabaseOfApp(std::uint8_t appId) +{ + auto database_ = mockDatabase_->GetDatabase(); + if (database_.find(appId) != database_.end()) { + return database_[appId]; + } else { + return ""; + } +} + +void LocalDeviceStatusListener::SetWlMatrixHelper(std::shared_ptr wlMatrixHelper) +{ + wlHelper_ = std::move(wlMatrixHelper); +} + +bool LocalDeviceStatusListener::CheckToBePulled(std::string peerDeviceId, std::uint8_t appId) +{ + return waterLevelMatrix_->CheckAppWl(peerDeviceId, appId); +} +// the function should be called after the device init the local installed apps +BuildLinkFeature LocalDeviceStatusListener::SendBuildLinkFeature() +{ + return wlHelper_->GetBuildLinkFeatureFunction(deviceId_, localDeviceInfo_.installedApps); +} + +void LocalDeviceStatusListener::OnReceiveBuildLinkFeature(std::string peerDeviceId, BuildLinkFeature buildLinkFeature) +{ + wlStatusStatistic_->SetBuildLinkFeature(peerDeviceId, buildLinkFeature); +} + +void LocalDeviceStatusListener::SetWlVersion(WlVersion version) +{ + localDeviceInfo_.wlVersion = version; +} + +void LocalDeviceStatusListener::OnRemoteDeviceSetWlVersion(std::string peerDeviceId, WlVersion wlVersion) +{ + if (remoteDevicesStatus_.find(peerDeviceId) != remoteDevicesStatus_.end()) { + remoteDevicesStatus_[peerDeviceId].wlVersion = wlVersion; + } +} + +std::vector LocalDeviceStatusListener::GetOldVersionDevices() +{ + std::vector oldVersionDevices; + for (auto [deviceId, info] : remoteDevicesStatus_) { + if (info.wlVersion == WlVersion::OLDER_WATER_LEVEL) { + oldVersionDevices.push_back(deviceId); + } + } + return oldVersionDevices; +} + +std::vector LocalDeviceStatusListener::OnPushTo(std::string peerDeviceId) +{ + std::vector syncBuffLst; + if (remoteDevicesStatus_.find(peerDeviceId) != remoteDevicesStatus_.end()) { + syncBuffLst = sysDataSyncService_->GetSyncBuffLst(peerDeviceId); + sysDataSyncService_->ClearSyncBuffLst(peerDeviceId); + ZLOGI("%{public}s clear the buff with Peer %{public}s", deviceId_.c_str(), peerDeviceId.c_str()); + if (localDeviceInfo_.wlDeviceStatus == WlDeviceStatus::WL_DEVICE_ACTIVE) { + if (remoteDevicesStatus_[peerDeviceId].wlDeviceStatus == WlDeviceStatus::WL_DEVICE_SLEEP) { + sysDataSyncService_->AdjustPushDelayAIMD(peerDeviceId, syncBuffLst, WlAIMDMode::WL_AIMD_AI); + } else if (remoteDevicesStatus_[peerDeviceId].wlDeviceStatus == WlDeviceStatus::WL_DEVICE_OFFLINE) { + sysDataSyncService_->AdjustPushDelayAIMD(peerDeviceId, syncBuffLst, WlAIMDMode::WL_AIMD_MD); + } + ZLOGI("%{public}s adjust the push delay with Peer %{public}s", deviceId_.c_str(), peerDeviceId.c_str()); + } + } else { + ZLOGE("%{public}s can not access to %{public}s.", deviceId_.c_str(), peerDeviceId.c_str()); + } + return syncBuffLst; +} + +double LocalDeviceStatusListener::GetPushDelay(std::string peerDeviceId, std::uint8_t appId) +{ + double delay = 0.0; + if (localDeviceInfo_.wlVersion == WlVersion::CURRENT_WATER_LEVEL) { + if (remoteDevicesStatus_.find(peerDeviceId) != remoteDevicesStatus_.end()) { + if (remoteDevicesStatus_[peerDeviceId].wlDeviceStatus == WlDeviceStatus::WL_DEVICE_SLEEP) { + delay = sysDataSyncService_->GetPushDelay(peerDeviceId, appId, true); + } + } + } + return delay; +} + +void LocalDeviceStatusListener::SetWlAIMDFactor(WlAIMDFactor wlAimdFactor) +{ + sysDataSyncService_->SetAIMDFactor(wlAimdFactor); +} + +void LocalDeviceStatusListener::SendWaterLevel(std::vector deviceList) +{ + if ((waterLevelMatrix_ != NULL) && (wlSyncService_ != NULL)) { + for (auto it : deviceList) { + auto compressedWl = waterLevelMatrix_->CompressWaterLevelMatrix(it); + if (!compressedWl.empty()) { + std::string infoStr = deviceId_ + " Send WaterLevelMatrix to " + it; + ZLOGI("%{public}s", infoStr.c_str()); + + wlSyncService_->BuildLinkToSync(deviceId_, it, compressedWl); + } + } + } +} + +void LocalDeviceStatusListener::SendInstalledApps(std::string peerDeviceId) +{ + if (remoteDevicesStatus_.find(peerDeviceId) != remoteDevicesStatus_.end()) { + if (!localDeviceInfo_.installedApps.empty()) { + CommStatus cstatus = + wlHelper_->SendDataFunction(deviceId_, peerDeviceId, localDeviceInfo_.installedApps, CommType::APP); + if (cstatus == CommStatus::SUCCESS) { + SetAppSyncTag(peerDeviceId, false); + } else { + ZLOGE("WL05, Send failed"); + } + std::string infoStr = deviceId_ + " successfully send App list to " + peerDeviceId; + ZLOGI("%{public}s", infoStr.c_str()); + } + } +} + +void LocalDeviceStatusListener::PushData(std::string peerDeviceId) +{ + if (remoteDevicesStatus_.find(peerDeviceId) != remoteDevicesStatus_.end()) { + if (!sysDataSyncService_->GetSyncBuffLst(peerDeviceId).empty()) { + CommStatus cStatus = wlHelper_->SendDataFunction(deviceId_, peerDeviceId, + sysDataSyncService_->GetSyncBuffLst(peerDeviceId), CommType::PUSH); + ZLOGI("%{public}s successfully send data to %{public}s, status %{public}d", deviceId_.c_str(), + peerDeviceId.c_str(), cStatus); + if (cStatus == CommStatus::ERROR) { + ZLOGE("WL05, Send failed"); + } + } + } +} +} // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/src/mock_database.cpp b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/mock_database.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1815c179350354ce7acd4326a817ab4500b0c09 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/mock_database.cpp @@ -0,0 +1,66 @@ +/* +* Copyright (c) 2023 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 "mock_database.h" + +#include "wlmatrix_config.h" +namespace OHOS::DistributedData { +void MockDatabase::Init(const std::vector &installedApps) +{ + for (auto it : installedApps) { + database_.insert_or_assign(it, " "); + } +} + +void MockDatabase::UpdateInstalledApps(const std::vector &installedApps) +{ + for (auto it : installedApps) { + if (database_.find(it) == database_.end()) { + database_.insert_or_assign(it, " "); + } + } +} + +bool MockDatabase::WriteToDataBase(std::uint8_t appId, const std::string &value_) +{ + if (database_.find(appId) != database_.end()) { + if (value_ >= database_[appId]) { + database_[appId] = value_; + return true; + } + } + return false; +} + +std::map MockDatabase::GetDatabase() +{ + return database_; +} + +std::string MockDatabase::DisplayDatabase() +{ + std::string databaseStr(PRINT_CHAR_NUM, '+'); + databaseStr.append("\n"); + + for (const auto &it : database_) { + databaseStr.append(std::to_string(static_cast(it.first))); + databaseStr.append(": "); + databaseStr.append(it.second); + databaseStr.append("\n"); + } + + return databaseStr; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/src/status_statistic.cpp b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/status_statistic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ddda68c899449a536b1f82ef307222af0777e625 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/status_statistic.cpp @@ -0,0 +1,202 @@ +/* +* Copyright (c) 2023 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 "status_statistic.h" +namespace OHOS::DistributedData { +void WlStatusStatistic::PullTimesIncr(std::uint8_t appId) +{ + if (IsAppIdValid(appId)) { + if (pushPullTimes.find(appId) == pushPullTimes.end()) { + AppSyncStatistic dataSyncStatistic; + pushPullTimes.insert_or_assign(appId, dataSyncStatistic); + } + pushPullTimes[appId].pullTimes += 1; + } +} + +void WlStatusStatistic::PushTimesIncr(std::uint8_t appId) +{ + if (IsAppIdValid(appId)) { + if (pushPullTimes.find(appId) == pushPullTimes.end()) { + AppSyncStatistic dataSyncStatistic; + pushPullTimes.insert_or_assign(appId, dataSyncStatistic); + } + pushPullTimes[appId].pushTimes += 1; + } +} + +AppSyncStatistic WlStatusStatistic::GetDataSyncStatistic(std::uint8_t appId) +{ + if (pushPullTimes.find(appId) != pushPullTimes.end()) { + return pushPullTimes[appId]; + } else { + // empty struct + return AppSyncStatistic { .pushTimes = 0, .pullTimes = 0 } ; + } +} + +void WlStatusStatistic::SetPowerPercent(double powerPercent) +{ + if (powerPercent >= 0 && powerPercent < 1) { + hardwareStatistic.powerPercent = powerPercent; + } +} + +void WlStatusStatistic::SetActiveDevices(uint32_t activeDevices) +{ + if (activeDevices <= MAX_DEVICE_NUM) { + hardwareStatistic.activeDevices = activeDevices; + } +} + +HardwareStatistic WlStatusStatistic::GetHardwareStatistic() +{ + return hardwareStatistic; +} + +void WlStatusStatistic::SetInServiceHeatIncr(const std::string &deviceId) +{ + if (buildLinksFeature.find(deviceId) != buildLinksFeature.end()) { + buildLinksFeature[deviceId].inServiceHeat += 1; + } +} + +void WlStatusStatistic::SetAppHeatIncr(const std::string &deviceId, std::uint8_t appId) +{ + if (buildLinksFeature.find(deviceId) != buildLinksFeature.end()) { + if (buildLinksFeature[deviceId].appHeat.find(appId) != buildLinksFeature[deviceId].appHeat.end()) { + buildLinksFeature[deviceId].appHeat[appId] += 1; + } + } +} + +void WlStatusStatistic::SetSyncHeatIncr(const std::string &deviceId) +{ + if (buildLinksFeature.find(deviceId) != buildLinksFeature.end()) { + buildLinksFeature[deviceId].syncHeat += 1; + } +} + +void WlStatusStatistic::SetBuildLinkFeature(const std::string &deviceId, BuildLinkFeature feature) +{ + buildLinksFeature.insert_or_assign(deviceId, feature); +} + +std::map WlStatusStatistic::GetBuildLinkFeature() +{ + return buildLinksFeature; +} + +void WlStatusStatistic::SetOnOffPeriod(const std::string &deviceId, const std::string &featureCode, double periodTime) +{ + if (remoteStatistic.find(deviceId) != remoteStatistic.end()) { + if (remoteStatistic[deviceId].onOffPeriod.find(featureCode) != remoteStatistic[deviceId].onOffPeriod.end()) { + remoteStatistic[deviceId].onOffPeriod[featureCode].push_back(periodTime); + } else { + remoteStatistic[deviceId].onOffPeriod.insert_or_assign(featureCode, std::vector { periodTime }); + } + } +} + +std::vector WlStatusStatistic::GetOnOffPeriod(const std::string &deviceId, const std::string &featureCode) +{ + std::vector onOffPeriod_; + if (remoteStatistic.find(deviceId) != remoteStatistic.end()) { + if (remoteStatistic[deviceId].onOffPeriod.find(featureCode) != remoteStatistic[deviceId].onOffPeriod.end()) { + return remoteStatistic[deviceId].onOffPeriod[featureCode]; + } + } + return onOffPeriod_; +} + +void WlStatusStatistic::SetAppFreq(const std::string &deviceId, const std::map &appFreq) +{ + if (remoteStatistic.find(deviceId) != remoteStatistic.end()) { + remoteStatistic[deviceId].appFreq = appFreq; + } else { + RemoteStatistic deviceRemoteStatistic; + deviceRemoteStatistic.appFreq = appFreq; + remoteStatistic.insert_or_assign(deviceId, deviceRemoteStatistic); + } +} + +void WlStatusStatistic::SetAppFreq(const std::string &deviceId, std::uint8_t appId, uint32_t value) +{ + if (remoteStatistic.find(deviceId) != remoteStatistic.end()) { + if (IsAppIdValid(appId)) { + remoteStatistic[deviceId].appFreq.insert_or_assign(appId, value); + } + } +} + +void WlStatusStatistic::SetAppFreqIncr(const std::string &deviceId, std::uint8_t appId) +{ + if (remoteStatistic.find(deviceId) != remoteStatistic.end()) { + if (IsAppIdValid(appId)) { + if (remoteStatistic[deviceId].appFreq.find(appId) != remoteStatistic[deviceId].appFreq.end()) { + remoteStatistic[deviceId].appFreq[appId] += 1; + } else { + remoteStatistic[deviceId].appFreq.insert_or_assign(appId, 1); + } + } + } +} + +std::map WlStatusStatistic::GetAppFreq(const std::string &deviceId) +{ + std::map appFreq_; + if (buildLinksFeature.find(deviceId) != buildLinksFeature.end()) { + appFreq_ = buildLinksFeature[deviceId].appHeat; + } + return appFreq_; +} + +bool WlStatusStatistic::IsBuildLinks(std::uint8_t appId) +{ + if (pushPullTimes.find(appId) != pushPullTimes.end()) { + auto appSyncSta_ = pushPullTimes[appId]; + double cond_pp = appSyncSta_.pushTimes == 0 ? 0 : (double)appSyncSta_.pullTimes / (double)appSyncSta_.pushTimes; + double cond_pa = hardwareStatistic.activeDevices == 0 + ? 0 + : hardwareStatistic.powerPercent / (double)hardwareStatistic.activeDevices; + if (cond_pp < APP_PULL_PUSH_THRESHOLD || cond_pa < POWER_PERCENT_ACTIVE_DEVICE_THRESHOLD) { + return true; + } else { + return false; + } + } + return true; +} + +std::vector WlStatusStatistic::GetBuildLinksOrder(const std::vector &deviceList, + std::uint8_t appId) +{ + // the dict order + std::vector featureLst; + for (const auto &it : deviceList) { + BuildLinkFeature feature = buildLinksFeature[it]; + feature.targetAppHeat = feature.appHeat[appId]; + featureLst.push_back(feature); + } + + std::sort(featureLst.begin(), featureLst.end(), BuildLinkCmp); + std::vector deviceLst; + for (const auto &it : featureLst) { + deviceLst.push_back(it.deviceId); + } + + return deviceLst; +} +} // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/src/sub_waterlevel_matrix.cpp b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/sub_waterlevel_matrix.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9242af9f5b93007f3548391684e0ad8998c6d734 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/sub_waterlevel_matrix.cpp @@ -0,0 +1,160 @@ +/* +* Copyright (c) 2023 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. +*/ + +#define LOG_TAG "SubWaterLevelMatrix" + +#include "sub_waterlevel_matrix.h" +namespace OHOS::DistributedData { +SubWaterLevelMatrix::SubWaterLevelMatrix() +{ + srcDeviceId_ = DEFAULT_DEVICE_ID; + peerDeviceId_ = DEFAULT_DEVICE_ID; +} + +SubWaterLevelMatrix::SubWaterLevelMatrix(std::string peerDeviceId) +{ + peerDeviceId_ = std::move(peerDeviceId); +} + +bool SubWaterLevelMatrix::Init(std::string srcDeviceId, std::string peerDeviceId, + const std::vector &appList) +{ + SetSrcDeviceId(std::move(srcDeviceId)); + SetPeerDeviceId(std::move(peerDeviceId)); + bool structChange = false; + std::map subWaterLevel_new; + for (const auto &it : appList) { + if (subWaterLevel_.find(it) == subWaterLevel_.end()) { + structChange = true; + subWaterLevel_new.insert_or_assign(it, SUB_WL_MATRIX_ELE_ZERO); + ZLOGI("SubWaterLevelMatrix insert one raw, [app: %{public}d, value: all zero]", it); + } else { + subWaterLevel_new.insert_or_assign(it, subWaterLevel_[it]); + } + } + subWaterLevel_ = std::move(subWaterLevel_new); + ZLOGI("Init finished."); + return structChange; +} + +void SubWaterLevelMatrix::SetAppWl(const std::uint8_t &appId) +{ + subWaterLevel_.insert_or_assign(appId, SUB_WL_MATRIX_ELE_ALL); + ZLOGI("Set app: %{public}d all one", appId); +} + +// set water level to one +void SubWaterLevelMatrix::SetAppWl(const std::uint8_t &appId, uint8_t typeId) +{ + uint16_t appWl; + // based on the original water level + if (subWaterLevel_.find(appId) != subWaterLevel_.end()) { + appWl = subWaterLevel_[appId]; + if (IsDataTypeValid(typeId)) { + appWl = (SUB_WL_MATRIX_ELE_ONE << typeId) | appWl; + subWaterLevel_.insert_or_assign(appId, appWl); + ZLOGI("Set app: %{public}d, type: %{public}d to one", static_cast(appId), static_cast(typeId)); + } else { + ZLOGE("%{public}s, value: %{public}d", E_WL_OVERFLOW_DATA_TYPE.c_str(), static_cast(typeId)); + } + } +} + +uint16_t SubWaterLevelMatrix::GetAppWl(const std::uint8_t &appId) +{ + if (subWaterLevel_.find(appId) != subWaterLevel_.end()) { + return subWaterLevel_[appId]; + } else { + ZLOGE("%{public}s in SubWaterLevelMatrix, value: %{public}d", E_WL_INVALID_APP_INDEX.c_str(), appId); + return SUB_WL_MATRIX_ELE_ZERO; + } +} + +// reset all the waterlevel matrix +void SubWaterLevelMatrix::ResetAllWl() +{ + for (auto it : subWaterLevel_) { + subWaterLevel_[it.first] = SUB_WL_MATRIX_ELE_ZERO; + } + ZLOGI("Reset SubWaterLevelMatrix"); +} + +void SubWaterLevelMatrix::ResetAppWl(const std::uint8_t &appId, uint8_t typeId) +{ + if (subWaterLevel_.find(appId) != subWaterLevel_.end()) { + uint16_t appWl = subWaterLevel_[appId]; + if (IsDataTypeValid(typeId)) { + appWl = ~(SUB_WL_MATRIX_ELE_ONE << typeId) & appWl; + subWaterLevel_.insert_or_assign(appId, appWl); + } else { + ZLOGE("%{public}s, value: %{public}d", E_WL_OVERFLOW_DATA_TYPE.c_str(), static_cast(typeId)); + } + } else { + ZLOGE("%{public}s in SubWaterLevelMatrix, value: %{public}d", E_WL_INVALID_APP_INDEX.c_str(), + static_cast(appId)); + } +} + +std::string SubWaterLevelMatrix::DisplaySubWaterLevelMatrix() +{ + std::string wl_string; + for (const auto &it : subWaterLevel_) { + wl_string.append(std::to_string(static_cast(it.first))); + wl_string.append(": "); + wl_string.append(std::bitset(it.second).to_string()); + wl_string.append("\n"); + } + return wl_string; +} + +std::vector SubWaterLevelMatrix::CompressSubWaterLevelMatrix() +{ + std::vector wlTransUint; + for (const auto &it : subWaterLevel_) { + if (it.second > 0) { + wlTransUint.push_back(WlTransUnit { .appId = it.first, .wlValue = it.second }); + } + } + return wlTransUint; +} + +void SubWaterLevelMatrix::SetSrcDeviceId(std::string srcDeviceId) +{ + if (IsDeviceNameValid(srcDeviceId) && srcDeviceId != DEFAULT_DEVICE_ID) { + srcDeviceId_ = std::move(srcDeviceId); + } else { + ZLOGE("Parameter: [srcDeviceId] too long"); + } +} + +std::string SubWaterLevelMatrix::GetSrcDeviceId() +{ + return srcDeviceId_; +} + +void SubWaterLevelMatrix::SetPeerDeviceId(std::string peerDeviceId) +{ + if (IsDeviceNameValid(peerDeviceId) && peerDeviceId != DEFAULT_DEVICE_ID) { + peerDeviceId_ = std::move(peerDeviceId); + } else { + ZLOGE("Parameter: [peerDeviceId] too long"); + } +} + +std::string SubWaterLevelMatrix::GetPeerDeviceId() +{ + return peerDeviceId_; +} +} // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/src/sync_matrix.cpp b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/sync_matrix.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1209e05f964b373962fe4382b55826bca05dce6d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/sync_matrix.cpp @@ -0,0 +1,150 @@ +/* +* Copyright (c) 2023 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. +*/ + +#define LOG_TAG "SyncMatrix" + +#include "sync_matrix.h" +namespace OHOS::DistributedData { +void SyncMatrix::Init(const std::vector &installedApp) +{ + // init or update + ZLOGI("SyncMatrix Init."); + for (const auto &app : installedApp) { + if (deviceSyncMatrix_.find(app) == deviceSyncMatrix_.end()) { + deviceSyncMatrix_.insert_or_assign(app, SubDeviceSyncMatrix()); + ZLOGI("SyncMatrix insert column app: %{public}d", app); + } + } +} + +void SyncMatrix::LocalUpdateDeviceSyncMatrix(std::vector syncDevices, + std::vector installedApp) +{ + ZLOGI("SyncMatrix Update."); + for (const auto &app : installedApp) { + if (deviceSyncMatrix_.find(app) == deviceSyncMatrix_.end()) { + SubDeviceSyncMatrix subDeviceSyncMatrix; + subDeviceSyncMatrix.syncDevices.insert_or_assign(0, syncDevices); + + deviceSyncMatrix_.insert_or_assign(app, subDeviceSyncMatrix); + ZLOGI("SyncMatrix insert column app: %{public}d", app); + } + } +} + +void SyncMatrix::UpdateDeviceSyncMatrix(const std::string &peerDeviceId, const std::vector &wltransUnit) +{ + for (const auto &it : wltransUnit) { + if (deviceSyncMatrix_.find(it.appId) != deviceSyncMatrix_.end()) { + auto syncDevices_ = deviceSyncMatrix_[it.appId].syncDevices; + for (auto typeId : GetWlValueIndex(it.wlValue)) { + if (IsDataTypeValid(typeId)) { + if (syncDevices_.find(typeId) != syncDevices_.end()) { + deviceSyncMatrix_[it.appId].syncDevices[typeId].push_back(peerDeviceId); + } else { + deviceSyncMatrix_[it.appId].syncDevices.insert_or_assign(typeId, + std::vector { peerDeviceId }); + } + ZLOGI("add device [%{public}s] on the SyncMatrix [app: %{public}d, typeid: %{public}d", + peerDeviceId.c_str(), static_cast(it.appId), static_cast(typeId)); + } else { + ZLOGE("%{public}s, value: %{public}d", E_WL_OVERFLOW_DATA_TYPE.c_str(), static_cast(typeId)); + } + } + } + } +} + +// Get the union of the devices in the DataSyncMatrix of target app: appId +std::vector SyncMatrix::GetSyncDeviceList(const std::uint8_t &appId) +{ + std::set syncDeviceList; + if (deviceSyncMatrix_.find(appId) != deviceSyncMatrix_.end()) { + for (auto it : deviceSyncMatrix_[appId].syncDevices) { + set_union(syncDeviceList.begin(), syncDeviceList.end(), it.second.begin(), it.second.end(), + inserter(syncDeviceList, syncDeviceList.begin())); + } + ZLOGI("Get the sync devices of app: %{public}d", appId); + } else { + // ZLOGI("App: %{public}s No need to sync from other devices",appId.c_str()); + ZLOGE("%{public}s", E_WL_INVALID_APP_INDEX.c_str()); + } + + return std::vector(syncDeviceList.begin(), syncDeviceList.end()); +} + +void SyncMatrix::RemoveSyncDevices(const std::uint8_t &appId, const std::string &peerDeviceId) +{ + if (deviceSyncMatrix_.find(appId) != deviceSyncMatrix_.end()) { + for (const auto &it : deviceSyncMatrix_[appId].syncDevices) { + auto deviceList = it.second; + if (std::find(deviceList.begin(), deviceList.end(), peerDeviceId) != deviceList.end()) { + auto item = std::remove(deviceList.begin(), deviceList.end(), peerDeviceId); + deviceList.erase(item, deviceList.end()); + deviceSyncMatrix_[appId].syncDevices[it.first] = deviceList; + ZLOGI("Remove peer device: [%{public}s] from SyncMatrix: [app: %{public}d] successfully", + peerDeviceId.c_str(), appId); + } else { + ZLOGI("Peer device: [%{public}s] not exist in SyncMatrix: [%{public}d]", peerDeviceId.c_str(), appId); + } + } + } else { + ZLOGE("App: [%{public}d] not exist in SyncMatrix", appId); + } +} + +void SyncMatrix::ClearAppSyncDevices(const std::uint8_t &appId) +{ + if (deviceSyncMatrix_.find(appId) != deviceSyncMatrix_.end()) { + deviceSyncMatrix_[appId].syncDevices.clear(); + ZLOGI("Clear SyncMatrix: [%{public}d]", static_cast(appId)); + } else { + ZLOGE("%{public}s in SyncMatrix, value: %{public}d", E_WL_INVALID_APP_INDEX.c_str(), static_cast(appId)); + } +} + +std::string SyncMatrix::GetSyncDeviceString(const std::uint8_t &appId) +{ + std::vector deviceString = GetSyncDeviceList(appId); + std::string syncString = "{"; + for (const auto &it : deviceString) { + syncString.append(it); + syncString.append(","); + } + syncString.append("}\n"); + return syncString; +} + +std::string SyncMatrix::GetAllSyncDeviceString() +{ + std::string syncString; + for (const auto &it : deviceSyncMatrix_) { + syncString.append(std::to_string(static_cast(it.first))); + syncString.append("|"); + for (const auto &sit : it.second.syncDevices) { + uint32_t typeId = sit.first; + syncString.append(std::to_string(typeId)); + syncString.append(": {"); + for (const auto &sitv : sit.second) { + syncString.append(sitv); + syncString.append(","); + } + syncString.append("}|"); + } + syncString.append("\n"); + } + return syncString; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/src/sysdatasync_service.cpp b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/sysdatasync_service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e8224f6401bbd44b8ae6dd0ca3bb01f33f389e35 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/sysdatasync_service.cpp @@ -0,0 +1,135 @@ +/* +* Copyright (c) 2023 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. +*/ +#define LOG_TAG "SysDataSyncService" +#include "sysdata_sync_service.h" +namespace OHOS::DistributedData { +SysDataSyncService::SysDataSyncService(WlAIMDFactor aimdFactor) +{ + AIMDStrategy = new SysDataAIMDStrategy(aimdFactor); +} + +void SysDataSyncService::AddAppToSyncBuffLst(std::string peerDeviceId, std::uint8_t appId) +{ + if (appId >= PUSH_APP_BOUND) { + if (syncBuffLst.find(peerDeviceId) != syncBuffLst.end()) { + { + std::unique_lock lock(mutex_); + syncBuffLst[peerDeviceId].push_back(appId); + + ZLOGI("Add App %{public}d to buff list", (int)appId); + } + } else { + if (IsDeviceNameValid(peerDeviceId)) { + { + std::unique_lock lock(mutex_); + syncBuffLst.insert_or_assign(peerDeviceId, std::vector { appId }); + + ZLOGI("%{public}s not exist in the buff before, add App %{public}d to buff list", + peerDeviceId.c_str(), (int)appId); + } + } + } + } +} + +void SysDataSyncService::ClearSyncBuffLst(std::string peerDeviceId) +{ + if (syncBuffLst.find(peerDeviceId) != syncBuffLst.end()) { + { + std::unique_lock lock(mutex_); + syncBuffLst[peerDeviceId].clear(); + } + } +} + +std::vector SysDataSyncService::GetSyncBuffLst(std::string peerDeviceId) +{ + std::vector deviceSyncBuffLst; + if (syncBuffLst.find(peerDeviceId) != syncBuffLst.end()) { + { + std::unique_lock lock(mutex_); + deviceSyncBuffLst = syncBuffLst[peerDeviceId]; + } + } + return deviceSyncBuffLst; +} + +void SysDataSyncService::GetSyncBuffLstRef(std::string peerDeviceId, std::vector &syncBuffLst_) +{ + if (syncBuffLst.find(peerDeviceId) != syncBuffLst.end()) { + { + std::unique_lock lock(mutex_); + syncBuffLst_ = syncBuffLst[peerDeviceId]; + } + } +} + +bool SysDataSyncService::IsSyncBuffLstEmpty(std::string peerDeviceId) +{ + if (syncBuffLst.find(peerDeviceId) != syncBuffLst.end()) { + return syncBuffLst[peerDeviceId].empty(); + } + return true; +} + +void SysDataSyncService::SetAIMDFactor(WlAIMDFactor aimdFactor) +{ + if (AIMDStrategy != NULL) { + AIMDStrategy->SetAIMDFactor(aimdFactor); + } +} + +void SysDataSyncService::AdjustPushDelayAIMD(std::string peerDeviceId, WlAIMDMode adjustMode) +{ + if (AIMDStrategy != NULL) { + AIMDStrategy->AdjustPushDelay(peerDeviceId, adjustMode); + } +} + +void SysDataSyncService::AdjustPushDelayAIMD(std::string peerDeviceId, std::uint8_t appId, WlAIMDMode adjustMode) +{ + if (AIMDStrategy != NULL) { + AIMDStrategy->AdjustPushDelayOfApp(peerDeviceId, appId, adjustMode); + } +} + +void SysDataSyncService::AdjustPushDelayAIMD(std::string peerDeviceId, std::vector appLst, + WlAIMDMode adjustMode) +{ + if (AIMDStrategy != NULL) { + for (auto it : appLst) { + AdjustPushDelayAIMD(peerDeviceId, it, adjustMode); + } + } +} + +double SysDataSyncService::GetPushDelay(std::string peerDeviceId, double appScaleFactor, bool isAIMD) +{ + double delay = 0.0; + if (isAIMD) { + delay = AIMDStrategy->GetPushDelay(peerDeviceId, appScaleFactor); + } + return delay; +} + +double SysDataSyncService::GetPushDelay(std::string peerDeviceId, std::uint8_t appId, bool isAIMD) +{ + double delay = 0.0; + if (isAIMD) { + delay = AIMDStrategy->GetPushDelay(peerDeviceId, appId); + } + return delay; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/src/sysdatasync_strategy.cpp b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/sysdatasync_strategy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dea02a708bdb8558d9dae55992cbaffa2cd02763 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/sysdatasync_strategy.cpp @@ -0,0 +1,111 @@ +/* +* Copyright (c) 2023 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. +*/ +#define LOG_TAG "SysDataSyncStrategy" + +#include "sysdata_sync_strategy.h" +namespace OHOS::DistributedData { +SysDataAIMDStrategy::SysDataAIMDStrategy(WlAIMDFactor aimdFactor) +{ + SetAIMDFactor(aimdFactor); +} + +double SysDataAIMDStrategy::GetPushDelay(std::string deviceId, double appScaleFactor) +{ + if (pushDelay.empty() || pushDelay.find(deviceId) == pushDelay.end()) { + pushDelay.insert_or_assign(deviceId, aimdFactor.InitDelay); + } + + double pushDelay_ = 0.0; + if (appScaleFactor != 0) { + pushDelay_ = pushDelay[deviceId] * (aimdFactor.mFactor / appScaleFactor); + } + pushDelay_ = pushDelay_ > pushDelay[deviceId] ? pushDelay[deviceId] : pushDelay_; + return pushDelay_; +} + +double SysDataAIMDStrategy::GetPushDelay(std::string deviceId, std::uint8_t appId) +{ + double pushDelay_; + if (pushDelayOfApp.find(deviceId) != pushDelayOfApp.end()) { + if (pushDelayOfApp[deviceId].find(appId) != pushDelayOfApp[deviceId].end()) { + pushDelay_ = pushDelayOfApp[deviceId][appId]; + } else { + pushDelayOfApp[deviceId].insert_or_assign(appId, aimdFactor.InitDelay); + pushDelay_ = aimdFactor.InitDelay; + } + } else { + pushDelayOfApp.insert_or_assign(deviceId, std::map { { appId, aimdFactor.InitDelay } }); + pushDelay_ = aimdFactor.InitDelay; + } + return pushDelay_; +} + +void SysDataAIMDStrategy::AdjustPushDelay(std::string deviceId, WlAIMDMode adjustMode) +{ + if (pushDelay.find(deviceId) != pushDelay.end()) { + if (adjustMode == WlAIMDMode::WL_AIMD_AI) { + pushDelay[deviceId] += aimdFactor.AIFactor; + ZLOGI("Additive Increase, factor: %{public}f, %{public}s change push delay from %{public}f to %{public}f", + aimdFactor.AIFactor, deviceId.c_str(), pushDelay[deviceId] - aimdFactor.AIFactor, pushDelay[deviceId]); + if (pushDelay[deviceId] > aimdFactor.DelayUpBound) { + pushDelay[deviceId] = aimdFactor.DelayUpBound; + ZLOGI("The push delay is greater than the upBound %{public}f", aimdFactor.DelayUpBound); + } + } else if (adjustMode == WlAIMDMode::WL_AIMD_MD) { + pushDelay[deviceId] /= aimdFactor.MDFactor; + ZLOGI("Multi Decrease, factor: %{public}f, %{public}s change push delay from %{public}f to %{public}f", + aimdFactor.MDFactor, deviceId.c_str(), pushDelay[deviceId] * aimdFactor.MDFactor, pushDelay[deviceId]); + } + } +} + +void SysDataAIMDStrategy::AdjustPushDelayOfApp(std::string deviceId, std::uint8_t appId, WlAIMDMode adjustMode) +{ + if (pushDelayOfApp.find(deviceId) != pushDelayOfApp.end()) { + if (pushDelayOfApp[deviceId].find(appId) != pushDelayOfApp[deviceId].end()) { + if (adjustMode == WlAIMDMode::WL_AIMD_AI) { + double changedDelay = pushDelayOfApp[deviceId][appId] + aimdFactor.AIFactor; + changedDelay = changedDelay > aimdFactor.DelayUpBound ? aimdFactor.DelayUpBound : changedDelay; + ZLOGI("Additive Increase, factor: %{public}f, %{public}s App %{public}d change push delay from " + "%{public}f to %{public}f", + aimdFactor.AIFactor, deviceId.c_str(), (int)appId, pushDelayOfApp[deviceId][appId], changedDelay); + pushDelayOfApp[deviceId][appId] = changedDelay; + } else if (adjustMode == WlAIMDMode::WL_AIMD_MD) { + double changedDelay = AdjustPushDelayMD(pushDelayOfApp[deviceId][appId], aimdFactor.MDFactor); + ZLOGI("Multi Decrease, factor: %{public}f, %{public}s change push delay from %{public}f to " + "%{public}f", + aimdFactor.MDFactor, deviceId.c_str(), pushDelayOfApp[deviceId][appId], changedDelay); + pushDelayOfApp[deviceId][appId] = changedDelay; + } + } + } +} + +void SysDataAIMDStrategy::SetAIMDFactor(WlAIMDFactor aimdFactor_) +{ + aimdFactor = aimdFactor_; +} + +double SysDataAIMDStrategy::AdjustPushDelayMD(double preDelay, double MDFactor) +{ + if (MDFactor != 0) { + return preDelay / MDFactor; + } else { + ZLOGE("Invalid parameter: AIMDFactor::MDFactor %{public}f, %{public}s", aimdFactor.MDFactor, + E_WL_INVALID_WLAIMDFACTOR_MD.c_str()); + return preDelay / DEFAULT_MD_FACTOR; + } +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/src/waterlevel_matrix.cpp b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/waterlevel_matrix.cpp new file mode 100644 index 0000000000000000000000000000000000000000..39109898c5651d74f07c6145b02cc55c15cf363b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/waterlevel_matrix.cpp @@ -0,0 +1,130 @@ +/* +* Copyright (c) 2023 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. +*/ + +#define LOG_TAG "WaterLevelMatrix" + +#include "waterlevel_matrix.h" + +#include "log_print.h" +namespace OHOS::DistributedData { +void WaterLevelMatrix::Init(std::string deviceId) +{ + if (deviceId != DEFAULT_DEVICE_ID && IsDeviceNameValid(deviceId)) { + deviceId_ = std::move(deviceId); + } else { + ZLOGE("%{public}s", E_WL_INVALID_DEVICE_ID.c_str()); + } +} + +std::string WaterLevelMatrix::GetDeviceId() const +{ + return deviceId_; +} + +void WaterLevelMatrix::SetSubWaterLevelMatrix(const std::uint8_t &appId, uint8_t typeId) +{ + // Set the SubWaterLevelMatrix of each device, put one on WLM[appId][typeID] + for (auto &it : waterlevel_) { + waterlevel_[it.first]->SetAppWl(appId, typeId); + } +} + +void WaterLevelMatrix::ResetAll() +{ + for (auto &it : waterlevel_) { + waterlevel_[it.first]->ResetAllWl(); + } +} + +void WaterLevelMatrix::ResetDeviceWaterLevel(const std::string &deviceId) +{ + if (waterlevel_.find(deviceId) != waterlevel_.end()) { + waterlevel_[deviceId]->ResetAllWl(); + } else { + ZLOGE("WL03, %{public}s, %{public}s invalid", E_WL_INVALID_DEVICE_ID.c_str(), deviceId.c_str()); + } +} + +/* Param: + * peerDeviceId: the deviceId of peer device + * appList: the change of the app intersection of two devices + * device A: appListA + * device B: appListB + * previous intersection: preAppListInter + * + * */ +void WaterLevelMatrix::UpdateWaterLevelMatrix(const std::string &peerDeviceId, const std::vector &appList) +{ + if (waterlevel_.find(peerDeviceId) != waterlevel_.end()) { + waterlevel_[peerDeviceId]->Init(deviceId_, peerDeviceId, appList); + } else { + // key not exist + std::shared_ptr subWlm = std::make_shared(peerDeviceId); + subWlm->Init(deviceId_, peerDeviceId, appList); + waterlevel_.insert(make_pair(peerDeviceId, subWlm)); + } +} + +std::string WaterLevelMatrix::DisplayAllSubWaterLevelMatrix() +{ + std::string waterLevelStr(PRINT_CHAR_NUM, '+'); + + waterLevelStr.append("\n"); + for (const auto &it : waterlevel_) { + waterLevelStr.append("<" + it.second->GetSrcDeviceId() + "," + it.second->GetPeerDeviceId() + ">\n"); + waterLevelStr.append(it.second->DisplaySubWaterLevelMatrix()); + } + waterLevelStr.append(PRINT_CHAR_NUM, '+'); + waterLevelStr.append("\n"); + return waterLevelStr; +} + +std::vector WaterLevelMatrix::CompressWaterLevelMatrix(const std::string &peerDeviceId) +{ + std::vector compressedWl; + if (waterlevel_.find(peerDeviceId) != waterlevel_.end()) { + auto wlTransUnit = waterlevel_[peerDeviceId]->CompressSubWaterLevelMatrix(); + + for (auto it : wlTransUnit) { + compressedWl.push_back(it.appId); + compressedWl.push_back((std::uint8_t)(it.wlValue >> BYTE_TO_BIT)); + compressedWl.push_back((std::uint8_t)(it.wlValue)); + } + } + return compressedWl; +} + +std::vector WaterLevelMatrix::CompressWaterLevelMatrixApp(const std::string &peerDeviceId) +{ + std::vector compressedWl; + if (waterlevel_.find(peerDeviceId) != waterlevel_.end()) { + auto wlTransUnit = waterlevel_[peerDeviceId]->CompressSubWaterLevelMatrix(); + for (auto it : wlTransUnit) { + compressedWl.push_back(it.appId); + } + } + return compressedWl; +} + +bool WaterLevelMatrix::CheckAppWl(const std::string &peerDeviceId, std::uint8_t appId) +{ + bool checkRst = false; + if (waterlevel_.find(peerDeviceId) != waterlevel_.end()) { + auto subWl = waterlevel_[peerDeviceId]->GetAppWl(appId); + return subWl > 0; + } + return checkRst; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/src/wlmatrix_helper.cpp b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/wlmatrix_helper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6b6064a5fd4b5c67eebf3043ac567e8eb724844a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/wlmatrix_helper.cpp @@ -0,0 +1,19 @@ +/* +* Copyright (c) 2023 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 "wlmatrix_helper.h" +namespace OHOS::DistributedData { +std::map commBuff; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/src/wlsync_scheduler.cpp b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/wlsync_scheduler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fc97b05f172202e7283ceb04e55cb72577230f76 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/wlsync_scheduler.cpp @@ -0,0 +1,154 @@ +/* +* Copyright (c) 2023 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. +*/ + +#define LOG_TAG "WlSyncScheduler" +#include "wlsync_scheduler.h" + +#include "wlmatrix_error.h" +namespace OHOS::DistributedData { +WlSyncScheduler::WlSyncScheduler() +{ + size_t capacity = std::numeric_limits::max(); + std::string name = "Default"; + Start(capacity, name); +} + +WlSyncScheduler::WlSyncScheduler(size_t capacity) +{ + std::string name = "Default"; + Start(capacity, name); +} + +WlSyncScheduler::WlSyncScheduler(std::string name) +{ + size_t capacity = std::numeric_limits::max(); + Start(capacity, name); +} + +WlSyncScheduler::WlSyncScheduler(size_t capacity, std::string name) +{ + Start(capacity, name); +} + +WlSyncScheduler::~WlSyncScheduler() +{ + if (isRunning_) { + ZLOGI("~WlSyncScheduler"); + Stop(); + } +} + +void WlSyncScheduler::Start(size_t capacity, std::string name) +{ + capacity_ = capacity; + isRunning_ = true; + thread_ = std::make_unique([this, name]() { + auto realName = std::string("scheduler_") + name; + pthread_setname_np(pthread_self(), realName.c_str()); + this->WorkerThread(); + }); +} + +void WlSyncScheduler::Stop() +{ + isRunning_ = false; + Clear(); + AddWlTask( + std::string { EMPTY_TASK_ID }, []() { }, std::chrono::milliseconds(0), 0); + thread_->join(); +} + +void WlSyncScheduler::Sleep(int duration) +{ + std::this_thread::sleep_for(std::chrono::milliseconds(duration)); +} + +void WlSyncScheduler::AddWlTask(std::string taskId, std::function taskFunc, Duration delay, + std::uint8_t taskContent) +{ + std::unique_lock lock(mutex_); + if (wlTasks_.size() < capacity_) { + TimePoint executeTime = std::chrono::steady_clock::now() + delay; + WlTask wlTask = { .taskId = taskId, + .taskFunc = taskFunc, + .executeTime = executeTime, + .taskContent = taskContent }; + auto it = wlTasks_.insert(std::make_pair(executeTime, wlTask)); + taskLst.insert(std::make_pair(taskId, it)); + if (it == wlTasks_.begin()) { + condition_.notify_one(); + } + if (taskId != EMPTY_TASK_ID) { + ZLOGI("App %{public}d add successfully, Create at %{public}s, delay is %{public}d", (int)taskContent, + taskId.c_str(), static_cast(delay.count())); + } + } else { + ZLOGE("App %{public}d add failed, %{public}s", (int)taskContent, E_WL_WLSCHEDULER_ADD_FAILER.c_str()); + } +} + +void WlSyncScheduler::AddWlTask(std::string taskId, std::function taskFunc, Duration delay) +{ + AddWlTask(taskId, taskFunc, delay, 0); +} + +void WlSyncScheduler::Clear() +{ + ZLOGI("WlSyncScheduler Clear"); + std::unique_lock lock(mutex_); + wlTasks_.clear(); + taskLst.clear(); +} + +void WlSyncScheduler::ClearTasksById(std::string taskId) +{ + ZLOGI("WlSyncScheduler Clear Task By taskId"); + std::unique_lock lock(mutex_); + auto taskRange = taskLst.equal_range(taskId); + if (taskRange.first != taskRange.second) { + for (auto it = taskRange.first; it != taskRange.second; ++it) { + wlTasks_.erase(it->second); + } + taskLst.erase(taskRange.first, taskRange.second); + } +} + +void WlSyncScheduler::WorkerThread() +{ + while (isRunning_) { + std::function exec; + { + std::unique_lock lock(mutex_); + condition_.wait(lock, [this] { + return !wlTasks_.empty(); + }); + + if (wlTasks_.begin()->first > std::chrono::steady_clock::now()) { + auto time = wlTasks_.begin()->first; + condition_.wait_until(lock, time); + continue; + } + auto it = wlTasks_.begin(); + exec = it->second.taskFunc; + lock.unlock(); + ClearTasksById(it->second.taskId); + } + + if (exec) { + exec(); + } + } +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/src/wlsync_service.cpp b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/wlsync_service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b974bc7e3883671922ee605397cf43b5d907f8a0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/wlsync_service.cpp @@ -0,0 +1,71 @@ +/* +* Copyright (c) 2023 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. +*/ + +#define LOG_TAG "WlSyncService" + +#include "wlsync_service.h" +namespace OHOS::DistributedData { +void WlSyncService::SetSendTag(const std::string &deviceId, bool tag) +{ + if (IsDeviceNameValid(deviceId)) { + sendTag.insert_or_assign(deviceId, tag); + } else { + ZLOGE("%{public}s", E_WL_INVALID_DEVICE_ID.c_str()); + } +} + +bool WlSyncService::GetSendTag(const std::string &deviceId) +{ + bool tag = false; + if (sendTag.find(deviceId) != sendTag.end()) { + tag = sendTag[deviceId]; + } + return tag; +} + +std::vector WlSyncService::GetSyncDevices(bool tag) +{ + std::vector devices; + for (const auto &it : sendTag) { + if (it.second == tag) { + devices.push_back(it.first); + } + } + return devices; +} + +void WlSyncService::SetSyncStrategy(bool buildlink) +{ + if (buildlink) { + strategy = new WlBuildLinksStrategy(); + strategy->SendDataFunction = SendDataFunction; + } else { + strategy = new WlBroadcastStrategy(); + } +} + +CommStatus WlSyncService::BuildLinkToSync(std::string deviceId, const std::string &peerDeviceId, + std::vector content) +{ + strategy = new WlBuildLinksStrategy(); + strategy->SendDataFunction = SendDataFunction; + CommStatus cStatus = strategy->DoWaterLevelSync(deviceId, peerDeviceId, content); + if (cStatus == CommStatus::SUCCESS) { + ZLOGI("Successfully send bytes to Device: %{public}s", peerDeviceId.c_str()); + SetSendTag(peerDeviceId, false); + } + return cStatus; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/wlmatrix/src/wlsync_strategy.cpp b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/wlsync_strategy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e3bc7be80a0bc2ede7c336057539de519af1bfb0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/wlmatrix/src/wlsync_strategy.cpp @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2023 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. +*/ +#define LOG_TAG "WlSyncStrategy" + +#include "wlsync_strategy.h" +namespace OHOS::DistributedData { +WlBroadcastStrategy::WlBroadcastStrategy() +{ + ZLOGI("WlBroadcastStrategy"); +} + +WlBuildLinksStrategy::WlBuildLinksStrategy() +{ + ZLOGI("WlBuildLinksStrategy"); +} + +CommStatus WlBroadcastStrategy::DoWaterLevelSync(std::string deviceId, std::string dstDeviceId, + std::vector content) +{ + return CommStatus::ERROR; +} + +CommStatus WlBuildLinksStrategy::DoWaterLevelSync(std::string deviceId, std::string dstDeviceId, + std::vector content) +{ + if (!content.empty()) { + return SendDataFunction(deviceId, dstDeviceId, content, CommType::WL); + } else { + return CommStatus::ERROR; + } +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/test/include/CMakeLists.txt b/test/include/CMakeLists.txt index 3b964f9c86703396dcd0d2f3d4bdcd93c3aac61d..65e1d85d84d528943bf1af743e7a88ddd0ebd56b 100644 --- a/test/include/CMakeLists.txt +++ b/test/include/CMakeLists.txt @@ -24,6 +24,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/dist include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/crypto/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/directory/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/matrix/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/wlmatrix/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/kvdb) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/rdb) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/crypto/include)