From edb3be7ea47fba1b12ff4ec8872470cde85fc233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B2=E6=99=93=E6=99=93?= Date: Sat, 22 Feb 2025 11:50:09 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E5=8F=91=E5=B8=83publishId=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 史晓晓 --- .../include/advertise/advertise_manager.h | 7 ++- .../src/advertise/advertise_manager.cpp | 53 ++++++++++++++++++- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/services/service/include/advertise/advertise_manager.h b/services/service/include/advertise/advertise_manager.h index e9aa5ad4a..9f1ed72ab 100644 --- a/services/service/include/advertise/advertise_manager.h +++ b/services/service/include/advertise/advertise_manager.h @@ -31,11 +31,16 @@ public: private: void HandleAutoStopAdvertise(const std::string &timerName, const std::string &pkgName, int32_t publishId); - void ConfigAdvParam(const std::map &advertiseParam, DmPublishInfo *dmPubInfo); + void ConfigAdvParam(const std::map &advertiseParam, DmPublishInfo *dmPubInfo, const std::string &pkgName); + int32_t AddPublishCallback(const std::string &pkgName, int32_t publishId); + int32_t RemovePublishCallback(const std::string &pkgName, int32_t publishId); private: std::shared_ptr timer_; std::shared_ptr softbusListener_; + + std::mutex pubMapLock; + std::map> pkgName2PubIdMap_; }; } // namespace DistributedHardware } // namespace OHOS diff --git a/services/service/src/advertise/advertise_manager.cpp b/services/service/src/advertise/advertise_manager.cpp index 263203e85..ece975990 100644 --- a/services/service/src/advertise/advertise_manager.cpp +++ b/services/service/src/advertise/advertise_manager.cpp @@ -23,6 +23,17 @@ namespace OHOS { namespace DistributedHardware { const int32_t AUTO_STOP_ADVERTISE_DEFAULT_TIME = 120; const std::string AUTO_STOP_ADVERTISE_TASK = "AutoStopAdvertisingTask"; +const uint16_t DM_MIN_RANDOM = 1; +const uint16_t DM_MAX_RANDOM = 65535; +const uint16_t DM_INVALID_FLAG_ID = 0; + +uint16_t GenRandUint(uint16_t randMin, uint16_t randMax) +{ + std::random_device randDevice; + std::mt19937 genRand(randDevice()); + std::uniform_int_distribution disRand(randMin, randMax); + return disRand(genRand); +} AdvertiseManager::AdvertiseManager(std::shared_ptr softbusListener) : softbusListener_(softbusListener) { @@ -81,7 +92,7 @@ int32_t AdvertiseManager::StartAdvertising(const std::string &pkgName, } void AdvertiseManager::ConfigAdvParam(const std::map &advertiseParam, - DmPublishInfo *dmPubInfo) + DmPublishInfo *dmPubInfo, const std::string &pkgName) { if (dmPubInfo == nullptr) { LOGE("ConfigAdvParam failed, dmPubInfo is nullptr."); @@ -96,7 +107,8 @@ void AdvertiseManager::ConfigAdvParam(const std::map & LOGI("StartAdvertising input MetaType=%{public}s", (advertiseParam.find(PARAM_KEY_META_TYPE)->second).c_str()); } if (advertiseParam.find(PARAM_KEY_PUBLISH_ID) != advertiseParam.end()) { - dmPubInfo->publishId = std::atoi((advertiseParam.find(PARAM_KEY_PUBLISH_ID)->second).c_str()); + int32_t publishId = std::atoi((advertiseParam.find(PARAM_KEY_PUBLISH_ID)->second).c_str()); + dmPubInfo->publishId = AddPublishCallback(pkgName, publishId); } if (advertiseParam.find(PARAM_KEY_DISC_MODE) != advertiseParam.end()) { dmPubInfo->mode = @@ -115,6 +127,11 @@ int32_t AdvertiseManager::StopAdvertising(const std::string &pkgName, int32_t pu LOGE("Invalid parameter, pkgName is empty."); return ERR_DM_INPUT_PARA_INVALID; } + int32_t tempPublishId = RemovePublishCallback(pkgName, publishId); + if (publishId == DM_INVALID_FLAG_ID) { + LOGE("Failed: cannot find pkgName in cache map."); + return ERR_DM_INPUT_PARA_INVALID; + } return softbusListener_->StopPublishSoftbusLNN(publishId); } @@ -124,5 +141,37 @@ void AdvertiseManager::HandleAutoStopAdvertise(const std::string &timerName, con LOGI("HandleAutoStopAdvertise, auto stop advertise task timeout, timerName=%{public}s", timerName.c_str()); StopAdvertising(pkgName, publishId); } + +int32_t AdvertiseManager::AddPublishCallback(const std::string &pkgName, int32_t publishId) +{ + int32_t tempPublishId = DM_INVALID_FLAG_ID; + { + std::lock_guard autoLock(pubMapLock); + if (pkgName2PubIdMap_.find(pkgName) == pkgName2PubIdMap_.end()) { + pkgName2PubIdMap_[pkgName] = std::map(); + } + tempPublishId = GenRandUint(DM_MIN_RANDOM, DM_MAX_RANDOM); + pkgName2PubIdMap_[pkgName][publishId] = tempPublishId; + } + return tempPublishId; +} + +int32_t AdvertiseManager::RemovePublishCallback(const std::string &pkgName, int32_t publishId) +{ + uint16_t tempPublishId = DM_INVALID_FLAG_ID; + { + std::lock_guard autoLock(subMapLock); + if (pkgName2PubIdMap_.find(pkgName) != pkgName2PubIdMap_.end() && + pkgName2PubIdMap_[pkgName].find(publishId) != pkgName2PubIdMap_[pkgName].end()) { + tempPublishId = pkgName2PubIdMap_[pkgName][publishId]; + pkgName2PubIdMap_[pkgName].erase(publishId); + } + } + if (pkgName2PubIdMap_[pkgName].empty()) { + devicePublishCallbacks_.erase(pkgName); + } + } + return tempPublishId; +} } // namespace DistributedHardware } // namespace OHOS -- Gitee From 729e4e42e9379bae23a235b4bc501b8287e35e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B2=E6=99=93=E6=99=93?= Date: Sat, 22 Feb 2025 15:36:22 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 史晓晓 --- .../service/include/advertise/advertise_manager.h | 3 ++- services/service/src/advertise/advertise_manager.cpp | 11 ++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/services/service/include/advertise/advertise_manager.h b/services/service/include/advertise/advertise_manager.h index 9f1ed72ab..c1a8d00d4 100644 --- a/services/service/include/advertise/advertise_manager.h +++ b/services/service/include/advertise/advertise_manager.h @@ -31,7 +31,8 @@ public: private: void HandleAutoStopAdvertise(const std::string &timerName, const std::string &pkgName, int32_t publishId); - void ConfigAdvParam(const std::map &advertiseParam, DmPublishInfo *dmPubInfo, const std::string &pkgName); + void ConfigAdvParam(const std::map &advertiseParam, DmPublishInfo *dmPubInfo, + const std::string &pkgName); int32_t AddPublishCallback(const std::string &pkgName, int32_t publishId); int32_t RemovePublishCallback(const std::string &pkgName, int32_t publishId); diff --git a/services/service/src/advertise/advertise_manager.cpp b/services/service/src/advertise/advertise_manager.cpp index ece975990..d4f98af8d 100644 --- a/services/service/src/advertise/advertise_manager.cpp +++ b/services/service/src/advertise/advertise_manager.cpp @@ -15,6 +15,8 @@ #include "advertise_manager.h" +#include + #include "dm_constants.h" #include "dm_log.h" #include "dm_publish_info.h" @@ -54,7 +56,7 @@ int32_t AdvertiseManager::StartAdvertising(const std::string &pkgName, return ERR_DM_INPUT_PARA_INVALID; } DmPublishInfo dmPubInfo; - ConfigAdvParam(advertiseParam, &dmPubInfo); + ConfigAdvParam(advertiseParam, &dmPubInfo, pkgName); std::string capability = DM_CAPABILITY_OSD; if (advertiseParam.find(PARAM_KEY_DISC_CAPABILITY) != advertiseParam.end()) { capability = advertiseParam.find(PARAM_KEY_DISC_CAPABILITY)->second; @@ -148,7 +150,7 @@ int32_t AdvertiseManager::AddPublishCallback(const std::string &pkgName, int32_t { std::lock_guard autoLock(pubMapLock); if (pkgName2PubIdMap_.find(pkgName) == pkgName2PubIdMap_.end()) { - pkgName2PubIdMap_[pkgName] = std::map(); + pkgName2PubIdMap_[pkgName] = std::map(); } tempPublishId = GenRandUint(DM_MIN_RANDOM, DM_MAX_RANDOM); pkgName2PubIdMap_[pkgName][publishId] = tempPublishId; @@ -160,15 +162,14 @@ int32_t AdvertiseManager::RemovePublishCallback(const std::string &pkgName, int3 { uint16_t tempPublishId = DM_INVALID_FLAG_ID; { - std::lock_guard autoLock(subMapLock); + std::lock_guard autoLock(pubMapLock); if (pkgName2PubIdMap_.find(pkgName) != pkgName2PubIdMap_.end() && pkgName2PubIdMap_[pkgName].find(publishId) != pkgName2PubIdMap_[pkgName].end()) { tempPublishId = pkgName2PubIdMap_[pkgName][publishId]; pkgName2PubIdMap_[pkgName].erase(publishId); - } } if (pkgName2PubIdMap_[pkgName].empty()) { - devicePublishCallbacks_.erase(pkgName); + pkgName2PubIdMap_.erase(pkgName); } } return tempPublishId; -- Gitee From fdbad05bdd51fa874045328b617ec7c699fc4e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B2=E6=99=93=E6=99=93?= Date: Sat, 22 Feb 2025 20:33:42 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 史晓晓 --- services/service/src/advertise/advertise_manager.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/services/service/src/advertise/advertise_manager.cpp b/services/service/src/advertise/advertise_manager.cpp index d4f98af8d..a0a952ac3 100644 --- a/services/service/src/advertise/advertise_manager.cpp +++ b/services/service/src/advertise/advertise_manager.cpp @@ -110,6 +110,7 @@ void AdvertiseManager::ConfigAdvParam(const std::map & } if (advertiseParam.find(PARAM_KEY_PUBLISH_ID) != advertiseParam.end()) { int32_t publishId = std::atoi((advertiseParam.find(PARAM_KEY_PUBLISH_ID)->second).c_str()); + LOGI("PublishId=%{public}d", publishId); dmPubInfo->publishId = AddPublishCallback(pkgName, publishId); } if (advertiseParam.find(PARAM_KEY_DISC_MODE) != advertiseParam.end()) { @@ -124,17 +125,18 @@ void AdvertiseManager::ConfigAdvParam(const std::map & int32_t AdvertiseManager::StopAdvertising(const std::string &pkgName, int32_t publishId) { - LOGI("AdvertiseManager::StopDiscovering begin for pkgName = %{public}s.", pkgName.c_str()); + LOGI("AdvertiseManager::StopDiscovering begin for pkgName = %{public}s, publishId = %{public}d.", pkgName.c_str(), + publishId); if (pkgName.empty()) { LOGE("Invalid parameter, pkgName is empty."); return ERR_DM_INPUT_PARA_INVALID; } int32_t tempPublishId = RemovePublishCallback(pkgName, publishId); - if (publishId == DM_INVALID_FLAG_ID) { + if (tempPublishId == DM_INVALID_FLAG_ID) { LOGE("Failed: cannot find pkgName in cache map."); return ERR_DM_INPUT_PARA_INVALID; } - return softbusListener_->StopPublishSoftbusLNN(publishId); + return softbusListener_->StopPublishSoftbusLNN(tempPublishId); } void AdvertiseManager::HandleAutoStopAdvertise(const std::string &timerName, const std::string &pkgName, -- Gitee From 53fc5b78b09d73f04427bc5025b7d6f82eda8f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B2=E6=99=93=E6=99=93?= Date: Mon, 24 Feb 2025 10:09:05 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 史晓晓 --- .../include/advertise/advertise_manager.h | 5 +++-- .../service/include/device_manager_service.h | 1 + .../src/advertise/advertise_manager.cpp | 18 ++++++++++++++---- .../service/src/device_manager_service.cpp | 6 ++++++ .../src/ipc/standard/ipc_server_stub.cpp | 1 + 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/services/service/include/advertise/advertise_manager.h b/services/service/include/advertise/advertise_manager.h index c1a8d00d4..8e0066a79 100644 --- a/services/service/include/advertise/advertise_manager.h +++ b/services/service/include/advertise/advertise_manager.h @@ -28,13 +28,14 @@ public: int32_t StartAdvertising(const std::string &pkgName, const std::map &advertiseParam); int32_t StopAdvertising(const std::string &pkgName, int32_t publishId); + void ClearPulishIdCache(const std::string &pkgName); private: void HandleAutoStopAdvertise(const std::string &timerName, const std::string &pkgName, int32_t publishId); void ConfigAdvParam(const std::map &advertiseParam, DmPublishInfo *dmPubInfo, const std::string &pkgName); - int32_t AddPublishCallback(const std::string &pkgName, int32_t publishId); - int32_t RemovePublishCallback(const std::string &pkgName, int32_t publishId); + int32_t AddPublishId(const std::string &pkgName, int32_t publishId); + int32_t RemovePublishId(const std::string &pkgName, int32_t publishId); private: std::shared_ptr timer_; diff --git a/services/service/include/device_manager_service.h b/services/service/include/device_manager_service.h index f57a29acb..8e14aaca9 100644 --- a/services/service/include/device_manager_service.h +++ b/services/service/include/device_manager_service.h @@ -223,6 +223,7 @@ public: std::vector &deviceProfileInfoList); int32_t GetLocalDisplayDeviceName(const std::string &pkgName, int32_t maxNameLength, std::string &displayName); std::vector GetDeviceNamePrefixs(); + void ClearPulishIdCache(const std::string &pkgName); private: bool IsDMServiceImplReady(); diff --git a/services/service/src/advertise/advertise_manager.cpp b/services/service/src/advertise/advertise_manager.cpp index a0a952ac3..c003449ab 100644 --- a/services/service/src/advertise/advertise_manager.cpp +++ b/services/service/src/advertise/advertise_manager.cpp @@ -111,7 +111,7 @@ void AdvertiseManager::ConfigAdvParam(const std::map & if (advertiseParam.find(PARAM_KEY_PUBLISH_ID) != advertiseParam.end()) { int32_t publishId = std::atoi((advertiseParam.find(PARAM_KEY_PUBLISH_ID)->second).c_str()); LOGI("PublishId=%{public}d", publishId); - dmPubInfo->publishId = AddPublishCallback(pkgName, publishId); + dmPubInfo->publishId = AddPublishId(pkgName, publishId); } if (advertiseParam.find(PARAM_KEY_DISC_MODE) != advertiseParam.end()) { dmPubInfo->mode = @@ -131,7 +131,7 @@ int32_t AdvertiseManager::StopAdvertising(const std::string &pkgName, int32_t pu LOGE("Invalid parameter, pkgName is empty."); return ERR_DM_INPUT_PARA_INVALID; } - int32_t tempPublishId = RemovePublishCallback(pkgName, publishId); + int32_t tempPublishId = RemovePublishId(pkgName, publishId); if (tempPublishId == DM_INVALID_FLAG_ID) { LOGE("Failed: cannot find pkgName in cache map."); return ERR_DM_INPUT_PARA_INVALID; @@ -146,7 +146,7 @@ void AdvertiseManager::HandleAutoStopAdvertise(const std::string &timerName, con StopAdvertising(pkgName, publishId); } -int32_t AdvertiseManager::AddPublishCallback(const std::string &pkgName, int32_t publishId) +int32_t AdvertiseManager::AddPublishId(const std::string &pkgName, int32_t publishId) { int32_t tempPublishId = DM_INVALID_FLAG_ID; { @@ -160,7 +160,7 @@ int32_t AdvertiseManager::AddPublishCallback(const std::string &pkgName, int32_t return tempPublishId; } -int32_t AdvertiseManager::RemovePublishCallback(const std::string &pkgName, int32_t publishId) +int32_t AdvertiseManager::RemovePublishId(const std::string &pkgName, int32_t publishId) { uint16_t tempPublishId = DM_INVALID_FLAG_ID; { @@ -176,5 +176,15 @@ int32_t AdvertiseManager::RemovePublishCallback(const std::string &pkgName, int3 } return tempPublishId; } + +void AdvertiseManager::ClearPulishIdCache(const std::string &pkgName) +{ + LOGI("Begin for pkgName = %{public}s.", pkgName.c_str()); + if (pkgName.empty()) { + LOGE("Invalid parameter, pkgName is empty."); + return; + } + pkgName2PubIdMap_.erase(pkgName); +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/service/src/device_manager_service.cpp b/services/service/src/device_manager_service.cpp index 9b78f1d5f..e9ed80a1e 100755 --- a/services/service/src/device_manager_service.cpp +++ b/services/service/src/device_manager_service.cpp @@ -2695,5 +2695,11 @@ std::vector DeviceManagerService::GetDeviceNamePrefixs() } return dmServiceImplExtResident_->GetDeviceNamePrefixs(); } + +void DeviceManagerService::ClearPulishIdCache(const std::string &pkgName) +{ + CHECK_NULL_VOID(advertiseMgr_); + advertiseMgr_->ClearPulishIdCache(pkgName); +} } // namespace DistributedHardware } // namespace OHOS \ No newline at end of file diff --git a/services/service/src/ipc/standard/ipc_server_stub.cpp b/services/service/src/ipc/standard/ipc_server_stub.cpp index 99dcf8eb6..a3eb40aa9 100644 --- a/services/service/src/ipc/standard/ipc_server_stub.cpp +++ b/services/service/src/ipc/standard/ipc_server_stub.cpp @@ -352,6 +352,7 @@ void AppDeathRecipient::OnRemoteDied(const wptr &remote) IpcServerStub::GetInstance().UnRegisterDeviceManagerListener(processInfo); DeviceManagerService::GetInstance().ClearDiscoveryCache(processInfo); DeviceManagerServiceNotify::GetInstance().ClearDiedProcessCallback(processInfo); + DeviceManagerService::GetInstance().ClearPulishIdCache(processInfo.pkgName); } void IpcServerStub::AddSystemSA(const std::string &pkgName) -- Gitee From e12b2aff24b6e13bc20d6bf9d8fe9f92a947daac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B2=E6=99=93=E6=99=93?= Date: Mon, 24 Feb 2025 12:07:52 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 史晓晓 --- services/service/include/device_manager_service.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/service/include/device_manager_service.h b/services/service/include/device_manager_service.h index ca877b835..ab34dcdbd 100644 --- a/services/service/include/device_manager_service.h +++ b/services/service/include/device_manager_service.h @@ -224,13 +224,13 @@ public: std::vector &deviceProfileInfoList); int32_t GetLocalDisplayDeviceName(const std::string &pkgName, int32_t maxNameLength, std::string &displayName); std::vector GetDeviceNamePrefixs(); - void ClearPulishIdCache(const std::string &pkgName); int64_t GenerateSerivceId(); int32_t RegisterServiceInfo(const DMServiceInfo &serviceInfo); int32_t UnRegisterServiceInfo(int64_t serviceId); int32_t UpdateServiceInfo(const DMServiceInfo &serviceInfo); int32_t GetServiceInfoById(int64_t serviceId, DMServiceInfo &serviceInfo); int32_t GetCallerServiceInfos(std::vector &serviceInfos); + void ClearPulishIdCache(const std::string &pkgName); private: bool IsDMServiceImplReady(); -- Gitee From 001b11f0b0369f490df04b4adec584b0c42c4d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B2=E6=99=93=E6=99=93?= Date: Mon, 24 Feb 2025 18:39:19 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 史晓晓 --- services/service/src/advertise/advertise_manager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/service/src/advertise/advertise_manager.cpp b/services/service/src/advertise/advertise_manager.cpp index 83093c0c5..4eb4eaa9b 100644 --- a/services/service/src/advertise/advertise_manager.cpp +++ b/services/service/src/advertise/advertise_manager.cpp @@ -158,6 +158,9 @@ int32_t AdvertiseManager::AddPublishId(const std::string &pkgName, int32_t publi int32_t tempPublishId = DM_INVALID_FLAG_ID; { std::lock_guard autoLock(pubMapLock); + if (pkgName2PubIdMap_[pkgName].find(publishId) != pkgName2PubIdMap_[pkgName].end()) { + StopAdvertising(pkgName, publishId); + } if (pkgName2PubIdMap_.find(pkgName) == pkgName2PubIdMap_.end()) { pkgName2PubIdMap_[pkgName] = std::map(); } -- Gitee From 36f1235cc79cf8e6fc8c2961c2aba09f70ea9403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B2=E6=99=93=E6=99=93?= Date: Mon, 24 Feb 2025 20:23:43 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 史晓晓 --- services/service/src/advertise/advertise_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/service/src/advertise/advertise_manager.cpp b/services/service/src/advertise/advertise_manager.cpp index 4eb4eaa9b..b481af447 100644 --- a/services/service/src/advertise/advertise_manager.cpp +++ b/services/service/src/advertise/advertise_manager.cpp @@ -159,7 +159,7 @@ int32_t AdvertiseManager::AddPublishId(const std::string &pkgName, int32_t publi { std::lock_guard autoLock(pubMapLock); if (pkgName2PubIdMap_[pkgName].find(publishId) != pkgName2PubIdMap_[pkgName].end()) { - StopAdvertising(pkgName, publishId); + softbusListener_->StopPublishSoftbusLNN(pkgName2PubIdMap_[pkgName][publishId]); } if (pkgName2PubIdMap_.find(pkgName) == pkgName2PubIdMap_.end()) { pkgName2PubIdMap_[pkgName] = std::map(); -- Gitee