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