1 /*
2  * Copyright (c) 2023 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 "softbus_adapter/softbus_adapter.h"
17 
18 #include <sys/prctl.h>
19 
20 #include "broadcast.h"
21 #include "dfx/distributed_radar.h"
22 #include "dtbschedmgr_log.h"
23 #include "softbus_error_code.h"
24 
25 namespace OHOS {
26 namespace DistributedSchedule {
27 namespace {
28 const std::string TAG = "SoftbusAdapter";
29 const std::string SOFTBUS_ADAPTER = "softbus_adapter";
30 const std::string RETRY_SENT_EVENT_TASK = "retry_on_sent_event_task";
31 constexpr int32_t RETRY_SENT_EVENT_DELAY = 50;
32 constexpr int32_t RETRY_SENT_EVENT_MAX_TIME = 3;
33 }
34 
35 IMPLEMENT_SINGLE_INSTANCE(SoftbusAdapter);
36 
Init()37 void SoftbusAdapter::Init()
38 {
39     if (eventHandler_ != nullptr) {
40         HILOGI("Already inited, end.");
41         return;
42     }
43     eventThread_ = std::thread(&SoftbusAdapter::StartEvent, this);
44     std::unique_lock<std::mutex> lock(eventMutex_);
45     eventCon_.wait(lock, [this] {
46         return eventHandler_ != nullptr;
47     });
48 }
49 
StartEvent()50 void SoftbusAdapter::StartEvent()
51 {
52     HILOGI("StartEvent start");
53     prctl(PR_SET_NAME, SOFTBUS_ADAPTER.c_str());
54     auto runner = AppExecFwk::EventRunner::Create(false);
55     {
56         std::lock_guard<std::mutex> lock(eventMutex_);
57         eventHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
58     }
59     eventCon_.notify_one();
60     if (runner != nullptr) {
61         runner->Run();
62     } else {
63         HILOGE("runner is null");
64     }
65     HILOGI("StartEvent end");
66 }
67 
UnInit()68 void SoftbusAdapter::UnInit()
69 {
70     HILOGI("UnInit start");
71     if (eventHandler_ != nullptr && eventHandler_->GetEventRunner() != nullptr) {
72         eventHandler_->GetEventRunner()->Stop();
73         eventThread_.join();
74         eventHandler_ = nullptr;
75     } else {
76         HILOGE("eventHandler_ or eventRunner is nullptr");
77     }
78     HILOGI("UnInit end");
79 }
80 
SendSoftbusEvent(std::shared_ptr<DSchedDataBuffer> buffer)81 int32_t SoftbusAdapter::SendSoftbusEvent(std::shared_ptr<DSchedDataBuffer> buffer)
82 {
83     HILOGI("SendSoftbusEvent pkgName: %{public}s.", pkgName_.c_str());
84     auto feedfunc = [this, buffer]() {
85         DealSendSoftbusEvent(buffer);
86     };
87     if (eventHandler_ != nullptr) {
88         eventHandler_->PostTask(feedfunc);
89     } else {
90         HILOGE("eventHandler_ is nullptr");
91     }
92 
93     return SOFTBUS_OK;
94 }
95 
DealSendSoftbusEvent(std::shared_ptr<DSchedDataBuffer> buffer,const int32_t retry)96 int32_t SoftbusAdapter::DealSendSoftbusEvent(std::shared_ptr<DSchedDataBuffer> buffer, const int32_t retry)
97 {
98     if (eventHandler_ != nullptr) {
99         eventHandler_->RemoveTask(RETRY_SENT_EVENT_TASK);
100     } else {
101         HILOGE("eventHandler_ is nullptr");
102         return INVALID_PARAMETERS_ERR;
103     }
104 
105     if (buffer == nullptr) {
106         HILOGE("buffer is nullptr");
107         return INVALID_PARAMETERS_ERR;
108     }
109     EventData eventData;
110     eventData.event = FOREGROUND_APP;
111     eventData.freq = EVENT_HIGH_FREQ;
112     eventData.data = buffer->Data();
113     eventData.dataLen = buffer->Capacity();
114     eventData.screenOff = true;
115     int32_t ret = SendEvent(pkgName_.c_str(), BROADCAST_TARGET_AREA, &eventData);
116     if (ret != SOFTBUS_OK) {
117         HILOGW("SendEvent failed, ret:%{public}d.", ret);
118         return RetrySendSoftbusEvent(buffer, retry);
119     }
120     return ret;
121 }
122 
RetrySendSoftbusEvent(std::shared_ptr<DSchedDataBuffer> buffer,const int32_t retry)123 int32_t SoftbusAdapter::RetrySendSoftbusEvent(std::shared_ptr<DSchedDataBuffer> buffer, const int32_t retry)
124 {
125     HILOGI("Retry post broadcast, current retry times %{public}d", retry);
126     if (retry == RETRY_SENT_EVENT_MAX_TIME) {
127         HILOGE("meet max retry time!");
128         return INVALID_PARAMETERS_ERR;
129     }
130     auto feedfunc = [this, buffer, retry]() mutable {
131         DealSendSoftbusEvent(buffer, retry + 1);
132     };
133     if (eventHandler_ != nullptr) {
134         eventHandler_->RemoveTask(RETRY_SENT_EVENT_TASK);
135         eventHandler_->PostTask(feedfunc, RETRY_SENT_EVENT_TASK, RETRY_SENT_EVENT_DELAY);
136     } else {
137         HILOGE("eventHandler_ is nullptr");
138         return INVALID_PARAMETERS_ERR;
139     }
140     return ERR_OK;
141 }
142 
StopSoftbusEvent()143 int32_t SoftbusAdapter::StopSoftbusEvent()
144 {
145     HILOGI("StopSoftbusEvent pkgName: %{public}s.", pkgName_.c_str());
146     int32_t ret = StopEvent(pkgName_.c_str(), BROADCAST_TARGET_AREA, FOREGROUND_APP);
147     if (ret != SOFTBUS_OK) {
148         HILOGE("StopEvent failed, ret:%{public}d.", ret);
149         return ret;
150     }
151     return SOFTBUS_OK;
152 }
153 
EventListenerReceived(const EventNotify * eventNotify)154 static void EventListenerReceived(const EventNotify *eventNotify)
155 {
156     HILOGD("called.");
157     if (eventNotify == nullptr) {
158         HILOGE("eventNotify is null");
159         return;
160     }
161     std::string networkId(eventNotify->senderNetworkId);
162     SoftbusAdapter::GetInstance().OnBroadCastRecv(networkId, eventNotify->data, eventNotify->dataLen);
163 }
164 
OnBroadCastRecv(std::string & networkId,uint8_t * data,uint32_t dataLen)165 void SoftbusAdapter::OnBroadCastRecv(std::string& networkId, uint8_t* data, uint32_t dataLen)
166 {
167     if (softbusAdapterListener_ != nullptr) {
168         softbusAdapterListener_->OnDataRecv(networkId, data, dataLen);
169     } else {
170         HILOGE("softbusAdapterListener_ is nullptr");
171     }
172 }
173 
RegisterSoftbusEventListener(const std::shared_ptr<SoftbusAdapterListener> & listener)174 int32_t SoftbusAdapter::RegisterSoftbusEventListener(const std::shared_ptr<SoftbusAdapterListener>& listener)
175 {
176     if (listener == nullptr) {
177         HILOGE("Registering listener failed");
178         return SOFTBUS_INVALID_PARAM;
179     }
180     {
181         std::lock_guard<std::mutex> lock(softbusAdapterListenerMutex_);
182         softbusAdapterListener_ = listener;
183     }
184     EventListener eventListener;
185     eventListener.event = FOREGROUND_APP;
186     eventListener.freq = EVENT_MID_FREQ;
187     eventListener.deduplicate = true;
188     eventListener.OnEventReceived = EventListenerReceived;
189     HILOGI("RegisterSoftbusEventListener pkgName: %s.", pkgName_.c_str());
190     int32_t ret = RegisterEventListener(pkgName_.c_str(), &eventListener);
191     DmsRadar::GetInstance().RegisterSoftbusCallbackRes("RegisterSoftbusEventListener", ret);
192     if (ret != SOFTBUS_OK) {
193         HILOGE("RegisterSoftbusEventListener failed, ret: %{public}d.", ret);
194         return ret;
195     }
196     return SOFTBUS_OK;
197 }
198 
UnregisterSoftbusEventListener(const std::shared_ptr<SoftbusAdapterListener> & listener)199 int32_t SoftbusAdapter::UnregisterSoftbusEventListener(const std::shared_ptr<SoftbusAdapterListener>& listener)
200 {
201     if (listener == nullptr) {
202         HILOGE("Unregistering listener failed");
203         return SOFTBUS_INVALID_PARAM;
204     }
205     {
206         std::lock_guard<std::mutex> lock(softbusAdapterListenerMutex_);
207         softbusAdapterListener_ = listener;
208     }
209     EventListener eventListener;
210     eventListener.event = FOREGROUND_APP;
211     eventListener.freq = EVENT_MID_FREQ;
212     eventListener.deduplicate = true;
213     eventListener.OnEventReceived = EventListenerReceived;
214     HILOGI("UnregisterSoftbusEventListener pkgName: %s.", pkgName_.c_str());
215     int32_t ret = UnregisterEventListener(pkgName_.c_str(), &eventListener);
216     if (ret != SOFTBUS_OK) {
217         HILOGE("UnregisterSoftbusEventListener failed, ret: %{public}d.", ret);
218         return ret;
219     }
220     return SOFTBUS_OK;
221 }
222 } // namespace DistributedSchedule
223 } // namespace OHOS
224