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
23 namespace OHOS {
24 namespace DistributedHardware {
25 const int32_t AUTO_STOP_ADVERTISE_DEFAULT_TIME = 120;
26 const std::string AUTO_STOP_ADVERTISE_TASK = "AutoStopAdvertisingTask";
27 const int32_t DM_MIN_RANDOM = 1;
28 const int32_t DM_MAX_RANDOM = INT32_MAX;
29 const int32_t DM_INVALID_FLAG_ID = 0;
30
AdvertiseManager(std::shared_ptr<SoftbusListener> softbusListener)31 AdvertiseManager::AdvertiseManager(std::shared_ptr<SoftbusListener> softbusListener) : softbusListener_(softbusListener)
32 {
33 LOGI("AdvertiseManager constructor.");
34 }
35
~AdvertiseManager()36 AdvertiseManager::~AdvertiseManager()
37 {
38 LOGI("AdvertiseManager destructor.");
39 }
40
StartAdvertising(const std::string & pkgName,const std::map<std::string,std::string> & advertiseParam)41 int32_t AdvertiseManager::StartAdvertising(const std::string &pkgName,
42 const std::map<std::string, std::string> &advertiseParam)
43 {
44 LOGI("AdvertiseManager::StartAdvertising begin for pkgName = %{public}s.", pkgName.c_str());
45 if (pkgName.empty()) {
46 LOGE("Invalid parameter, pkgName is empty.");
47 return ERR_DM_INPUT_PARA_INVALID;
48 }
49 DmPublishInfo dmPubInfo;
50 ConfigAdvParam(advertiseParam, &dmPubInfo, pkgName);
51 std::string capability = DM_CAPABILITY_OSD;
52 if (advertiseParam.find(PARAM_KEY_DISC_CAPABILITY) != advertiseParam.end()) {
53 capability = advertiseParam.find(PARAM_KEY_DISC_CAPABILITY)->second;
54 }
55 if (capability == DM_CAPABILITY_APPROACH || capability == DM_CAPABILITY_TOUCH) {
56 dmPubInfo.mode = DmDiscoverMode::DM_DISCOVER_MODE_ACTIVE;
57 }
58 if (capability == DM_CAPABILITY_OOP) {
59 dmPubInfo.ranging = false;
60 }
61 std::string customData = "";
62 if (advertiseParam.find(PARAM_KEY_CUSTOM_DATA) != advertiseParam.end()) {
63 customData = advertiseParam.find(PARAM_KEY_CUSTOM_DATA)->second;
64 }
65
66 int32_t ret = softbusListener_->PublishSoftbusLNN(dmPubInfo, capability, customData);
67 if (ret != DM_OK) {
68 LOGE("StartAdvertising failed, softbus publish lnn ret: %{public}d", ret);
69 return ret;
70 }
71
72 if (advertiseParam.find(PARAM_KEY_AUTO_STOP_ADVERTISE) != advertiseParam.end()) {
73 int32_t stopTime = std::atoi((advertiseParam.find(PARAM_KEY_AUTO_STOP_ADVERTISE)->second).c_str());
74 if ((stopTime <= 0) || (stopTime > AUTO_STOP_ADVERTISE_DEFAULT_TIME)) {
75 LOGE("StartAdvertising error, invalid input auto stop advertise time: %{public}d", stopTime);
76 return DM_OK;
77 }
78 if (timer_ == nullptr) {
79 timer_ = std::make_shared<DmTimer>();
80 }
81 int32_t publishId = dmPubInfo.publishId;
82 timer_->StartTimer(std::string(AUTO_STOP_ADVERTISE_TASK), stopTime,
83 [this, pkgName, publishId] (std::string name) {
84 AdvertiseManager::HandleAutoStopAdvertise(name, pkgName, publishId);
85 });
86 }
87 return DM_OK;
88 }
89
ConfigAdvParam(const std::map<std::string,std::string> & advertiseParam,DmPublishInfo * dmPubInfo,const std::string & pkgName)90 void AdvertiseManager::ConfigAdvParam(const std::map<std::string, std::string> &advertiseParam,
91 DmPublishInfo *dmPubInfo, const std::string &pkgName)
92 {
93 if (dmPubInfo == nullptr) {
94 LOGE("ConfigAdvParam failed, dmPubInfo is nullptr.");
95 return;
96 }
97 dmPubInfo->publishId = -1;
98 dmPubInfo->mode = DmDiscoverMode::DM_DISCOVER_MODE_PASSIVE;
99 dmPubInfo->freq = DmExchangeFreq::DM_LOW;
100 dmPubInfo->ranging = true;
101 dmPubInfo->medium = DmExchangeMedium::DM_AUTO;
102
103 if (advertiseParam.find(PARAM_KEY_META_TYPE) != advertiseParam.end()) {
104 LOGI("StartAdvertising input MetaType=%{public}s", (advertiseParam.find(PARAM_KEY_META_TYPE)->second).c_str());
105 }
106 if (advertiseParam.find(PARAM_KEY_PUBLISH_ID) != advertiseParam.end() &&
107 IsNumberString(advertiseParam.find(PARAM_KEY_PUBLISH_ID)->second)) {
108 int32_t publishId = std::atoi((advertiseParam.find(PARAM_KEY_PUBLISH_ID)->second).c_str());
109 LOGI("PublishId=%{public}d", publishId);
110 dmPubInfo->publishId = GenInnerPublishId(pkgName, publishId);
111 }
112 if (advertiseParam.find(PARAM_KEY_DISC_MODE) != advertiseParam.end()) {
113 dmPubInfo->mode =
114 static_cast<DmDiscoverMode>(std::atoi((advertiseParam.find(PARAM_KEY_DISC_MODE)->second).c_str()));
115 }
116 if (advertiseParam.find(PARAM_KEY_DISC_FREQ) != advertiseParam.end()) {
117 dmPubInfo->freq =
118 static_cast<DmExchangeFreq>(std::atoi((advertiseParam.find(PARAM_KEY_DISC_FREQ)->second).c_str()));
119 }
120 if (advertiseParam.find(PARAM_KEY_DISC_MEDIUM) != advertiseParam.end()) {
121 if (IsNumberString(advertiseParam.find(PARAM_KEY_DISC_MEDIUM)->second)) {
122 dmPubInfo->medium =
123 static_cast<DmExchangeMedium>(std::atoi((advertiseParam.find(PARAM_KEY_DISC_MEDIUM)->second).c_str()));
124 }
125 }
126 }
127
StopAdvertising(const std::string & pkgName,int32_t publishId)128 int32_t AdvertiseManager::StopAdvertising(const std::string &pkgName, int32_t publishId)
129 {
130 LOGI("AdvertiseManager::StopDiscovering begin for pkgName = %{public}s, publishId = %{public}d.", pkgName.c_str(),
131 publishId);
132 if (pkgName.empty()) {
133 LOGE("Invalid parameter, pkgName is empty.");
134 return ERR_DM_INPUT_PARA_INVALID;
135 }
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("HandleAutoStopAdvertise, 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 if (pkgName2PubIdMap_[pkgName].find(publishId) != pkgName2PubIdMap_[pkgName].end()) {
157 softbusListener_->StopPublishSoftbusLNN(pkgName2PubIdMap_[pkgName][publishId]);
158 publishIdSet_.erase(pkgName2PubIdMap_[pkgName][publishId]);
159 }
160 if (pkgName2PubIdMap_.find(pkgName) == pkgName2PubIdMap_.end()) {
161 pkgName2PubIdMap_[pkgName] = std::map<int32_t, int32_t>();
162 }
163 bool isExist = false;
164 do {
165 tempPublishId = GenRandInt(DM_MIN_RANDOM, DM_MAX_RANDOM);
166 if (publishIdSet_.find(tempPublishId) != publishIdSet_.end()) {
167 LOGE("The tempPublishId: %{public}d is exist.", tempPublishId);
168 isExist = true;
169 } else {
170 isExist = false;
171 }
172 } while (isExist);
173 publishIdSet_.emplace(tempPublishId);
174 pkgName2PubIdMap_[pkgName][publishId] = tempPublishId;
175 }
176 return tempPublishId;
177 }
178
GetAndRemoveInnerPublishId(const std::string & pkgName,int32_t publishId)179 int32_t AdvertiseManager::GetAndRemoveInnerPublishId(const std::string &pkgName, int32_t publishId)
180 {
181 int32_t tempPublishId = DM_INVALID_FLAG_ID;
182 {
183 std::lock_guard<std::mutex> autoLock(pubMapLock_);
184 if (pkgName2PubIdMap_.find(pkgName) != pkgName2PubIdMap_.end() &&
185 pkgName2PubIdMap_[pkgName].find(publishId) != pkgName2PubIdMap_[pkgName].end()) {
186 tempPublishId = pkgName2PubIdMap_[pkgName][publishId];
187 pkgName2PubIdMap_[pkgName].erase(publishId);
188 publishIdSet_.erase(tempPublishId);
189 }
190 if (pkgName2PubIdMap_[pkgName].empty()) {
191 pkgName2PubIdMap_.erase(pkgName);
192 }
193 }
194 return tempPublishId;
195 }
196
ClearPulishIdCache(const std::string & pkgName)197 void AdvertiseManager::ClearPulishIdCache(const std::string &pkgName)
198 {
199 LOGI("Begin for pkgName = %{public}s.", pkgName.c_str());
200 if (pkgName.empty()) {
201 LOGE("Invalid parameter, pkgName is empty.");
202 return;
203 }
204 std::lock_guard<std::mutex> autoLock(pubMapLock_);
205 for (auto iter : pkgName2PubIdMap_[pkgName]) {
206 softbusListener_->StopPublishSoftbusLNN(iter.second);
207 publishIdSet_.erase(iter.second);
208 }
209 pkgName2PubIdMap_.erase(pkgName);
210 }
211 } // namespace DistributedHardware
212 } // namespace OHOS
213