1 /*
2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "advertise_manager.h"
17
18 #include "dm_constants.h"
19 #include "dm_log.h"
20 #include "dm_publish_info.h"
21 #include "dm_random.h"
22 #include "system_ability_definition.h"
23
24 namespace OHOS {
25 namespace DistributedHardware {
26 const int32_t AUTO_STOP_ADVERTISE_DEFAULT_TIME = 120;
27 const std::string AUTO_STOP_ADVERTISE_TASK = "AutoStopAdvertisingTask";
28 const int32_t DM_MIN_RANDOM = 1;
29 const int32_t DM_MAX_RANDOM = INT32_MAX;
30 const int32_t DM_INVALID_FLAG_ID = 0;
31
AdvertiseManager(std::shared_ptr<SoftbusListener> softbusListener)32 AdvertiseManager::AdvertiseManager(std::shared_ptr<SoftbusListener> softbusListener) : softbusListener_(softbusListener)
33 {
34 LOGI("AdvertiseManager constructor.");
35 }
36
~AdvertiseManager()37 AdvertiseManager::~AdvertiseManager()
38 {
39 LOGI("AdvertiseManager destructor.");
40 }
41
StartAdvertising(const std::string & pkgName,const std::map<std::string,std::string> & advertiseParam)42 int32_t AdvertiseManager::StartAdvertising(const std::string &pkgName,
43 const std::map<std::string, std::string> &advertiseParam)
44 {
45 if (pkgName.empty()) {
46 LOGE("Invalid parameter, pkgName is empty.");
47 return ERR_DM_INPUT_PARA_INVALID;
48 }
49 LOGI("begin for pkgName = %{public}s.", pkgName.c_str());
50 DmPublishInfo dmPubInfo;
51 ConfigAdvParam(advertiseParam, &dmPubInfo, pkgName);
52 std::string capability = DM_CAPABILITY_OSD;
53 if (advertiseParam.find(PARAM_KEY_DISC_CAPABILITY) != advertiseParam.end()) {
54 capability = advertiseParam.find(PARAM_KEY_DISC_CAPABILITY)->second;
55 }
56 if (capability == DM_CAPABILITY_APPROACH || capability == DM_CAPABILITY_TOUCH) {
57 dmPubInfo.mode = DmDiscoverMode::DM_DISCOVER_MODE_ACTIVE;
58 }
59 if (capability == DM_CAPABILITY_OOP) {
60 dmPubInfo.ranging = false;
61 }
62 std::string customData = "";
63 if (advertiseParam.find(PARAM_KEY_CUSTOM_DATA) != advertiseParam.end()) {
64 customData = advertiseParam.find(PARAM_KEY_CUSTOM_DATA)->second;
65 }
66
67 int32_t ret = softbusListener_->PublishSoftbusLNN(dmPubInfo, capability, customData);
68 if (ret != DM_OK) {
69 LOGE("failed, softbus publish lnn ret: %{public}d", ret);
70 return ret;
71 }
72
73 if (advertiseParam.find(PARAM_KEY_AUTO_STOP_ADVERTISE) != advertiseParam.end()) {
74 int32_t stopTime = std::atoi((advertiseParam.find(PARAM_KEY_AUTO_STOP_ADVERTISE)->second).c_str());
75 if ((stopTime <= 0) || (stopTime > AUTO_STOP_ADVERTISE_DEFAULT_TIME)) {
76 LOGE("StartAdvertising error, invalid input auto stop advertise time: %{public}d", stopTime);
77 return DM_OK;
78 }
79 if (timer_ == nullptr) {
80 timer_ = std::make_shared<DmTimer>();
81 }
82 int32_t publishId = dmPubInfo.publishId;
83 timer_->StartTimer(std::string(AUTO_STOP_ADVERTISE_TASK), stopTime,
84 [this, pkgName, publishId] (std::string name) {
85 AdvertiseManager::HandleAutoStopAdvertise(name, pkgName, publishId);
86 });
87 }
88 return DM_OK;
89 }
90
ConfigAdvParam(const std::map<std::string,std::string> & advertiseParam,DmPublishInfo * dmPubInfo,const std::string & pkgName)91 void AdvertiseManager::ConfigAdvParam(const std::map<std::string, std::string> &advertiseParam,
92 DmPublishInfo *dmPubInfo, const std::string &pkgName)
93 {
94 if (dmPubInfo == nullptr) {
95 LOGE("ConfigAdvParam failed, dmPubInfo is nullptr.");
96 return;
97 }
98 dmPubInfo->publishId = -1;
99 dmPubInfo->mode = DmDiscoverMode::DM_DISCOVER_MODE_PASSIVE;
100 dmPubInfo->freq = DmExchangeFreq::DM_LOW;
101 dmPubInfo->ranging = true;
102 dmPubInfo->medium = DmExchangeMedium::DM_AUTO;
103
104 if (advertiseParam.find(PARAM_KEY_META_TYPE) != advertiseParam.end()) {
105 LOGI("StartAdvertising input MetaType=%{public}s", (advertiseParam.find(PARAM_KEY_META_TYPE)->second).c_str());
106 }
107 if (advertiseParam.find(PARAM_KEY_PUBLISH_ID) != advertiseParam.end() &&
108 IsNumberString(advertiseParam.find(PARAM_KEY_PUBLISH_ID)->second)) {
109 int32_t publishId = std::atoi((advertiseParam.find(PARAM_KEY_PUBLISH_ID)->second).c_str());
110 LOGI("PublishId=%{public}d", publishId);
111 dmPubInfo->publishId = GenInnerPublishId(pkgName, publishId);
112 }
113 if (advertiseParam.find(PARAM_KEY_DISC_MODE) != advertiseParam.end()) {
114 dmPubInfo->mode =
115 static_cast<DmDiscoverMode>(std::atoi((advertiseParam.find(PARAM_KEY_DISC_MODE)->second).c_str()));
116 }
117 if (advertiseParam.find(PARAM_KEY_DISC_FREQ) != advertiseParam.end()) {
118 dmPubInfo->freq =
119 static_cast<DmExchangeFreq>(std::atoi((advertiseParam.find(PARAM_KEY_DISC_FREQ)->second).c_str()));
120 }
121 if (advertiseParam.find(PARAM_KEY_DISC_MEDIUM) != advertiseParam.end()) {
122 if (IsNumberString(advertiseParam.find(PARAM_KEY_DISC_MEDIUM)->second)) {
123 dmPubInfo->medium =
124 static_cast<DmExchangeMedium>(std::atoi((advertiseParam.find(PARAM_KEY_DISC_MEDIUM)->second).c_str()));
125 }
126 }
127 }
128
StopAdvertising(const std::string & pkgName,int32_t publishId)129 int32_t AdvertiseManager::StopAdvertising(const std::string &pkgName, int32_t publishId)
130 {
131 if (pkgName.empty()) {
132 LOGE("Invalid parameter, pkgName is empty.");
133 return ERR_DM_INPUT_PARA_INVALID;
134 }
135 LOGI("begin for pkgName = %{public}s, publishId = %{public}d.", pkgName.c_str(), publishId);
136 int32_t innerPublishId = GetAndRemoveInnerPublishId(pkgName, publishId);
137 if (innerPublishId == DM_INVALID_FLAG_ID) {
138 LOGE("Failed: cannot find pkgName in cache map.");
139 return ERR_DM_INPUT_PARA_INVALID;
140 }
141 return softbusListener_->StopPublishSoftbusLNN(innerPublishId);
142 }
143
HandleAutoStopAdvertise(const std::string & timerName,const std::string & pkgName,int32_t publishId)144 void AdvertiseManager::HandleAutoStopAdvertise(const std::string &timerName, const std::string &pkgName,
145 int32_t publishId)
146 {
147 LOGI("auto stop advertise task timeout, timerName=%{public}s", timerName.c_str());
148 StopAdvertising(pkgName, publishId);
149 }
150
GenInnerPublishId(const std::string & pkgName,int32_t publishId)151 int32_t AdvertiseManager::GenInnerPublishId(const std::string &pkgName, int32_t publishId)
152 {
153 int32_t tempPublishId = DM_INVALID_FLAG_ID;
154 {
155 std::lock_guard<std::mutex> autoLock(pubMapLock_);
156 CHECK_SIZE_RETURN(pkgName2PubIdMap_, DM_INVALID_FLAG_ID);
157 CHECK_SIZE_RETURN(publishIdSet_, DM_INVALID_FLAG_ID);
158 if (pkgName2PubIdMap_[pkgName].find(publishId) != pkgName2PubIdMap_[pkgName].end()) {
159 return pkgName2PubIdMap_[pkgName][publishId];
160 }
161 if (pkgName2PubIdMap_.find(pkgName) == pkgName2PubIdMap_.end()) {
162 pkgName2PubIdMap_[pkgName] = std::map<int32_t, int32_t>();
163 }
164 bool isExist = false;
165 do {
166 tempPublishId = GenRandInt(DM_MIN_RANDOM, DM_MAX_RANDOM);
167 if (publishIdSet_.find(tempPublishId) != publishIdSet_.end() ||
168 tempPublishId == DISTRIBUTED_HARDWARE_DEVICEMANAGER_SA_ID) {
169 LOGE("The tempPublishId: %{public}d is exist.", tempPublishId);
170 isExist = true;
171 } else {
172 isExist = false;
173 }
174 } while (isExist);
175 publishIdSet_.emplace(tempPublishId);
176 pkgName2PubIdMap_[pkgName][publishId] = tempPublishId;
177 }
178 return tempPublishId;
179 }
180
GetAndRemoveInnerPublishId(const std::string & pkgName,int32_t publishId)181 int32_t AdvertiseManager::GetAndRemoveInnerPublishId(const std::string &pkgName, int32_t publishId)
182 {
183 int32_t tempPublishId = DM_INVALID_FLAG_ID;
184 {
185 std::lock_guard<std::mutex> autoLock(pubMapLock_);
186 if (pkgName2PubIdMap_.find(pkgName) != pkgName2PubIdMap_.end() &&
187 pkgName2PubIdMap_[pkgName].find(publishId) != pkgName2PubIdMap_[pkgName].end()) {
188 tempPublishId = pkgName2PubIdMap_[pkgName][publishId];
189 pkgName2PubIdMap_[pkgName].erase(publishId);
190 publishIdSet_.erase(tempPublishId);
191 }
192 if (pkgName2PubIdMap_[pkgName].empty()) {
193 pkgName2PubIdMap_.erase(pkgName);
194 }
195 }
196 return tempPublishId;
197 }
198
ClearPublishIdCache(const std::string & pkgName)199 void AdvertiseManager::ClearPublishIdCache(const std::string &pkgName)
200 {
201 if (pkgName.empty()) {
202 LOGE("Invalid parameter, pkgName is empty.");
203 return;
204 }
205 LOGI("Begin for pkgName = %{public}s.", pkgName.c_str());
206 std::lock_guard<std::mutex> autoLock(pubMapLock_);
207 for (auto iter : pkgName2PubIdMap_[pkgName]) {
208 softbusListener_->StopPublishSoftbusLNN(iter.second);
209 publishIdSet_.erase(iter.second);
210 }
211 pkgName2PubIdMap_.erase(pkgName);
212 }
213 } // namespace DistributedHardware
214 } // namespace OHOS
215