1 /*
2  * Copyright (c) 2021-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 "usb_device_manager.h"
17 #include <hdf_base.h>
18 #include "common_event_data.h"
19 #include "common_event_manager.h"
20 #include "common_event_support.h"
21 #include "hisysevent.h"
22 #include "usb_errors.h"
23 #include "usb_srv_support.h"
24 #include "usbd_type.h"
25 
26 using namespace OHOS::AAFwk;
27 using namespace OHOS::EventFwk;
28 using namespace OHOS::HiviewDFX;
29 using namespace OHOS::HDI::Usb::V1_0;
30 
31 namespace OHOS {
32 namespace USB {
33 constexpr int32_t PARAM_COUNT_TWO = 2;
34 constexpr int32_t PARAM_COUNT_THR = 3;
35 constexpr uint32_t CMD_INDEX = 1;
36 constexpr uint32_t PARAM_INDEX = 2;
37 constexpr uint32_t DELAY_CONNECT_INTERVAL = 300;
38 constexpr uint32_t DELAY_DISCONN_INTERVAL = 1400;
39 const std::map<std::string_view, uint32_t> UsbDeviceManager::FUNCTION_MAPPING_N2C = {
40     {UsbSrvSupport::FUNCTION_NAME_NONE, UsbSrvSupport::FUNCTION_NONE},
41     {UsbSrvSupport::FUNCTION_NAME_ACM, UsbSrvSupport::FUNCTION_ACM},
42     {UsbSrvSupport::FUNCTION_NAME_ECM, UsbSrvSupport::FUNCTION_ECM},
43     {UsbSrvSupport::FUNCTION_NAME_HDC, UsbSrvSupport::FUNCTION_HDC},
44     {UsbSrvSupport::FUNCTION_NAME_MTP, UsbSrvSupport::FUNCTION_MTP},
45     {UsbSrvSupport::FUNCTION_NAME_PTP, UsbSrvSupport::FUNCTION_PTP},
46     {UsbSrvSupport::FUNCTION_NAME_RNDIS, UsbSrvSupport::FUNCTION_RNDIS},
47     {UsbSrvSupport::FUNCTION_NAME_STORAGE, UsbSrvSupport::FUNCTION_STORAGE},
48 };
49 
UsbDeviceManager()50 UsbDeviceManager::UsbDeviceManager()
51 {
52     USB_HILOGI(MODULE_USB_SERVICE, "UsbDeviceManager::Init start");
53     usbd_ = IUsbInterface::Get();
54     if (usbd_ == nullptr) {
55         USB_HILOGE(MODULE_USB_SERVICE, "UsbDeviceManager::Get inteface failed");
56     }
57     auto ret = delayDisconn_.Setup();
58     if (ret != UEC_OK) {
59         USB_HILOGE(MODULE_USB_SERVICE, "set up timer failed %{public}u", ret);
60     }
61 }
62 
~UsbDeviceManager()63 UsbDeviceManager::~UsbDeviceManager()
64 {
65     delayDisconn_.Shutdown();
66 }
67 
Init()68 int32_t UsbDeviceManager::Init()
69 {
70     std::shared_ptr<UsbFunctionSwitchWindow> window_ = UsbFunctionSwitchWindow::GetInstance();
71     if (window_ == nullptr) {
72         USB_HILOGE(MODULE_USB_SERVICE, "get usb function switch window failed");
73         return UEC_SERVICE_INNER_ERR;
74     }
75 
76     int32_t ret = window_->Init();
77     if (ret != UEC_OK) {
78         USB_HILOGE(MODULE_USB_SERVICE, "Init usb function switch window failed");
79     }
80     return ret;
81 }
82 
SetUsbd(const sptr<IUsbInterface> & usbd)83 int32_t UsbDeviceManager::SetUsbd(const sptr<IUsbInterface> &usbd)
84 {
85     if (usbd == nullptr) {
86         USB_HILOGE(MODULE_USB_SERVICE, "UsbDeviceManager usbd is nullptr");
87         return UEC_SERVICE_INVALID_VALUE;
88     }
89     usbd_ = usbd;
90     return UEC_OK;
91 }
92 
AreSettableFunctions(int32_t funcs)93 bool UsbDeviceManager::AreSettableFunctions(int32_t funcs)
94 {
95     return static_cast<uint32_t>(funcs) == UsbSrvSupport::FUNCTION_NONE ||
96         ((~functionSettable_ & static_cast<uint32_t>(funcs)) == 0);
97 }
98 
ConvertFromString(std::string_view strFun)99 uint32_t UsbDeviceManager::ConvertFromString(std::string_view strFun)
100 {
101     if (strFun == UsbSrvSupport::FUNCTION_NAME_NONE) {
102         return UsbSrvSupport::FUNCTION_NONE;
103     }
104 
105     size_t len = strFun.length();
106     if (len == 0) {
107         return UEC_SERVICE_INVALID_VALUE;
108     }
109 
110     std::vector<std::string_view> vModeStr;
111     size_t pos = 0;
112     while (pos < len) {
113         size_t findPos = strFun.find(",", pos);
114         if (findPos == strFun.npos) {
115             vModeStr.push_back(strFun.substr(pos, len - pos));
116             break;
117         }
118         vModeStr.push_back(strFun.substr(pos, findPos - pos));
119         pos = findPos + 1;
120     }
121 
122     uint32_t ret = 0;
123     for (auto &&item : vModeStr) {
124         auto it = FUNCTION_MAPPING_N2C.find(item);
125         if (it != FUNCTION_MAPPING_N2C.end()) {
126             ret |= it->second;
127         } else {
128             USB_HILOGE(MODULE_USB_SERVICE, "UsbDeviceManager::ConvertFromString Invalid argument of usb function");
129             return UEC_SERVICE_INVALID_VALUE;
130         }
131     }
132 
133     return ret;
134 }
135 
ConvertToString(uint32_t function)136 std::string UsbDeviceManager::ConvertToString(uint32_t function)
137 {
138     std::string stream;
139     if (function <= UsbSrvSupport::FUNCTION_NONE || function > functionSettable_) {
140         stream = std::string {UsbSrvSupport::FUNCTION_NAME_NONE};
141         return stream;
142     }
143     bool flag = false;
144     for (auto it = FUNCTION_MAPPING_N2C.begin(); it != FUNCTION_MAPPING_N2C.end(); ++it) {
145         if ((function & it->second) != 0) {
146             if (flag) {
147                 stream += ",";
148             }
149             stream += std::string {it->first};
150             flag = true;
151         }
152     }
153     USB_HILOGI(MODULE_USB_SERVICE, "UsbDeviceManager::ConvertToString success");
154     return stream;
155 }
156 
UpdateFunctions(int32_t func)157 void UsbDeviceManager::UpdateFunctions(int32_t func)
158 {
159     if (func == currentFunctions_) {
160         return;
161     }
162     ReportFuncChangeSysEvent(currentFunctions_, func);
163     currentFunctions_ = func;
164     BroadcastFuncChange(connected_, currentFunctions_);
165 }
166 
GetCurrentFunctions()167 int32_t UsbDeviceManager::GetCurrentFunctions()
168 {
169     return currentFunctions_;
170 }
171 
HandleEvent(int32_t status)172 void UsbDeviceManager::HandleEvent(int32_t status)
173 {
174     if (usbd_ == nullptr) {
175         return;
176     }
177     bool curConnect = false;
178     switch (status) {
179         case ACT_UPDEVICE:
180             curConnect = true;
181             gadgetConnected_ = true;
182             break;
183 
184         case ACT_DOWNDEVICE:
185             curConnect = false;
186             gadgetConnected_ = false;
187             break;
188         case ACT_ACCESSORYUP:
189         case ACT_ACCESSORYDOWN:
190         case ACT_ACCESSORYSEND:
191             ProcessFunctionSwitchWindow(false);
192             return;
193         default:
194             USB_HILOGE(MODULE_USB_SERVICE, "invalid status %{public}d", status);
195             return;
196     }
197     delayDisconn_.Unregister(delayDisconnTimerId_);
198     if (curConnect && (connected_ != curConnect)) {
199         auto task = [&]() {
200             connected_ = true;
201             usbd_->GetCurrentFunctions(currentFunctions_);
202             ProcessFuncChange(connected_, currentFunctions_);
203         };
204         delayDisconnTimerId_ = delayDisconn_.Register(task, DELAY_CONNECT_INTERVAL, true);
205     } else if (!curConnect && (connected_ != curConnect)) {
206         auto task = [&]() {
207             connected_ = false;
208             if ((currentFunctions_ & USB_FUNCTION_MTP) != 0 || (currentFunctions_ & USB_FUNCTION_PTP) != 0) {
209                 currentFunctions_ = currentFunctions_ & (~USB_FUNCTION_MTP) & (~USB_FUNCTION_PTP);
210                 USB_HILOGI(MODULE_USB_SERVICE, "usb function reset %{public}u", currentFunctions_);
211                 currentFunctions_ = currentFunctions_ == 0 ? USB_FUNCTION_STORAGE : currentFunctions_;
212                 usbd_->SetCurrentFunctions(currentFunctions_);
213             }
214             ProcessFuncChange(connected_, currentFunctions_);
215             return;
216         };
217         delayDisconnTimerId_ = delayDisconn_.Register(task, DELAY_DISCONN_INTERVAL, true);
218     } else {
219         USB_HILOGI(MODULE_USB_SERVICE, "else info cur status %{public}d, bconnected: %{public}d", status, connected_);
220     }
221 }
222 
UserChangeProcess()223 int32_t UsbDeviceManager::UserChangeProcess()
224 {
225     if ((currentFunctions_ & USB_FUNCTION_MTP) != 0 || (currentFunctions_ & USB_FUNCTION_PTP) != 0) {
226         currentFunctions_ = currentFunctions_ & (~USB_FUNCTION_MTP) & (~USB_FUNCTION_PTP);
227         currentFunctions_ = currentFunctions_ == 0 ? USB_FUNCTION_STORAGE : currentFunctions_;
228         USB_HILOGI(MODULE_USB_SERVICE, "usb function reset %{public}d", currentFunctions_);
229         return usbd_->SetCurrentFunctions(currentFunctions_);
230     }
231     return UEC_OK;
232 }
233 
BroadcastFuncChange(bool connected,int32_t currentFunc)234 void UsbDeviceManager::BroadcastFuncChange(bool connected, int32_t currentFunc)
235 {
236     USB_HILOGI(MODULE_USB_SERVICE, "Current Connect %{public}d,bconnected: %{public}d", connected, currentFunc);
237     Want want;
238     want.SetAction(CommonEventSupport::COMMON_EVENT_USB_STATE);
239 
240     want.SetParam(std::string {UsbSrvSupport::CONNECTED}, connected);
241     uint32_t remainderFunc = static_cast<uint32_t>(currentFunc);
242     // start from bit 1
243     uint32_t bit = 1;
244     while (remainderFunc != 0) {
245         if (remainderFunc & bit) {
246             want.SetParam(ConvertToString(bit), true);
247             // set current bit to zero
248             remainderFunc &= ~bit;
249         }
250         // 1 means to next bit
251         bit = bit << 1;
252     }
253     CommonEventData data(want);
254     CommonEventPublishInfo publishInfo;
255     USB_HILOGI(MODULE_SERVICE, "send COMMON_EVENT_USB_STATE broadcast connected:%{public}d, "
256         "currentFunctions:%{public}d", connected, currentFunc);
257     CommonEventManager::PublishCommonEvent(data, publishInfo);
258     ReportDevicePlugSysEvent(currentFunc, connected);
259 }
260 
ProcessFuncChange(bool connected,int32_t currentFunc)261 void UsbDeviceManager::ProcessFuncChange(bool connected, int32_t currentFunc)
262 {
263     BroadcastFuncChange(connected, currentFunc);
264     ProcessFunctionSwitchWindow(connected);
265 }
266 
ProcessFunctionSwitchWindow(bool connected)267 void UsbDeviceManager::ProcessFunctionSwitchWindow(bool connected)
268 {
269     std::shared_ptr<UsbFunctionSwitchWindow> window_ = UsbFunctionSwitchWindow::GetInstance();
270     if (window_ == nullptr) {
271         USB_HILOGE(MODULE_USB_SERVICE, "show window: get usb function switch window failed");
272         return;
273     }
274 
275     if (connected) {
276         USB_HILOGD(MODULE_USB_SERVICE, "start pop up usb service switch window");
277         if (!window_->PopUpFunctionSwitchWindow()) {
278             USB_HILOGE(MODULE_USB_SERVICE, "start pop up usb service switch window failed");
279         }
280     } else {
281         USB_HILOGD(MODULE_USB_SERVICE, "start dismiss usb service switch window");
282         if (!window_->DismissFunctionSwitchWindow()) {
283             USB_HILOGE(MODULE_USB_SERVICE, "start dismiss usb service switch window failed");
284         }
285     }
286 }
287 
GetDumpHelp(int32_t fd)288 void UsbDeviceManager::GetDumpHelp(int32_t fd)
289 {
290     dprintf(fd, "========= dump the all device function =========\n");
291     dprintf(fd, "usb_device -a:    Query all function\n");
292     dprintf(fd, "usb_device -f Q:  Query Current function\n");
293     dprintf(fd, "usb_device -f 0:  Switch to function:none\n");
294     dprintf(fd, "usb_device -f 1:  Switch to function:acm\n");
295     dprintf(fd, "usb_device -f 2:  Switch to function:ecm\n");
296     dprintf(fd, "usb_device -f 3:  Switch to function:acm&ecm\n");
297     dprintf(fd, "usb_device -f 4:  Switch to function:hdc\n");
298     dprintf(fd, "usb_device -f 5:  Switch to function:acm&hdc\n");
299     dprintf(fd, "usb_device -f 6:  Switch to function:ecm&hdc\n");
300     dprintf(fd, "usb_device -f 32: Switch to function:rndis\n");
301     dprintf(fd, "usb_device -f 512:Switch to function:storage\n");
302     dprintf(fd, "usb_device -f 36: Switch to function:rndis&hdc\n");
303     dprintf(fd, "usb_device -f 516:Switch to function:storage&hdc\n");
304     dprintf(fd, "------------------------------------------------\n");
305 }
306 
DumpGetSupportFunc(int32_t fd)307 void UsbDeviceManager::DumpGetSupportFunc(int32_t fd)
308 {
309     dprintf(fd, "Usb Device function list info:\n");
310     dprintf(fd, "current function: %s\n", ConvertToString(currentFunctions_).c_str());
311     dprintf(fd, "supported functions list: %s\n", ConvertToString(functionSettable_).c_str());
312 }
313 
DumpSetFunc(int32_t fd,const std::string & args)314 void UsbDeviceManager::DumpSetFunc(int32_t fd, const std::string &args)
315 {
316     int32_t currentFunction;
317     int32_t ret;
318     if (usbd_ == nullptr) {
319         USB_HILOGE(MODULE_USB_SERVICE, "UsbDeviceManager::DumpSetFunc usbd_ is nullptr");
320         return;
321     }
322     if (args.compare("Q") == 0) {
323         ret = usbd_->GetCurrentFunctions(currentFunction);
324         if (ret != UEC_OK) {
325             dprintf(fd, "GetCurrentFunctions failed: %d\n", __LINE__);
326             return;
327         }
328         dprintf(fd, "current function: %s\n", ConvertToString(currentFunction).c_str());
329         return;
330     }
331 
332     int32_t mode = stoi(args);
333     ret = usbd_->SetCurrentFunctions(mode);
334     if (ret != UEC_OK) {
335         dprintf(fd, "SetCurrentFunctions failed");
336         return;
337     }
338     ret = usbd_->GetCurrentFunctions(currentFunction);
339     if (ret != UEC_OK) {
340         dprintf(fd, "GetCurrentFunctions failed: %d\n", __LINE__);
341         return;
342     }
343 
344     dprintf(fd, "current function: %s\n", ConvertToString(currentFunction).c_str());
345 }
346 
Dump(int32_t fd,const std::vector<std::string> & args)347 void UsbDeviceManager::Dump(int32_t fd, const std::vector<std::string> &args)
348 {
349     if (args.size() < PARAM_COUNT_TWO || args.size() > PARAM_COUNT_THR) {
350         GetDumpHelp(fd);
351         return;
352     }
353 
354     if (args[CMD_INDEX] == "-a" && args.size() == PARAM_COUNT_TWO) {
355         DumpGetSupportFunc(fd);
356     } else if (args[CMD_INDEX] == "-f" && args.size() == PARAM_COUNT_THR) {
357         DumpSetFunc(fd, args[PARAM_INDEX]);
358     } else {
359         dprintf(fd, "func param error, please enter again\n");
360         GetDumpHelp(fd);
361     }
362 }
363 
ReportFuncChangeSysEvent(int32_t currentFunctions,int32_t updateFunctions)364 void UsbDeviceManager::ReportFuncChangeSysEvent(int32_t currentFunctions, int32_t updateFunctions)
365 {
366     USB_HILOGI(MODULE_USB_SERVICE, "Device function Indicates the switch point information:");
367     HiSysEventWrite(HiSysEvent::Domain::USB, "FUNCTION_CHANGED",
368         HiSysEvent::EventType::BEHAVIOR, "CURRENT_FUNCTION",
369         currentFunctions_, "UPDATE_FUNCTION", updateFunctions);
370 }
371 
ReportDevicePlugSysEvent(int32_t currentFunctions,bool connected)372 void UsbDeviceManager::ReportDevicePlugSysEvent(int32_t currentFunctions, bool connected)
373 {
374     USB_HILOGI(MODULE_USB_SERVICE, "Device mode Indicates the insertion and removal information:");
375     HiSysEventWrite(HiSysEvent::Domain::USB, "PLUG_IN_OUT_DEVICE_MODE",
376         HiSysEvent::EventType::BEHAVIOR, "CURRENT_FUNCTIONS",
377         currentFunctions, "CONNECTED", connected);
378 }
IsGadgetConnected(void)379 bool UsbDeviceManager::IsGadgetConnected(void)
380 {
381     return gadgetConnected_;
382 }
383 } // namespace USB
384 } // namespace OHOS
385