1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <aidl/android/hardware/usb/ComplianceWarning.h> 20 #include <aidl/android/hardware/usb/PortDataRole.h> 21 #include <android-base/chrono_utils.h> 22 #include <android-base/unique_fd.h> 23 24 #include <set> 25 #include <string> 26 #include <vector> 27 28 namespace aidl { 29 namespace android { 30 namespace hardware { 31 namespace usb { 32 33 using ::aidl::android::hardware::usb::ComplianceWarning; 34 using ::aidl::android::hardware::usb::PortDataRole; 35 using ::android::base::boot_clock; 36 using ::android::base::unique_fd; 37 38 /* 39 * UsbDataSessionMonitor monitors the usb device state sysfs of 3 different usb devices 40 * including device mode (udc), host mode high-speed port and host mode super-speed port. It 41 * reports Suez metrics for each data session and also provides API to query the compliance 42 * warnings detected in the current usb data session. 43 */ 44 class UsbDataSessionMonitor { 45 public: 46 /* 47 * The host mode high-speed port and super-speed port can be assigned to either host1 or 48 * host2 without affecting functionality. 49 * 50 * UeventRegex: name regex of the device that's being monitored. The regex is matched against 51 * uevent to detect dynamic creation/deletion/change of the device. 52 * StatePath: usb device state sysfs path of the device, monitored by epoll. 53 * dataRolePath: path to the usb data role sysfs, monitored by epoll. 54 * updatePortStatusCb: the callback is invoked when the compliance warings changes. 55 */ 56 UsbDataSessionMonitor(const std::string &deviceUeventRegex, const std::string &deviceStatePath, 57 const std::string &host1UeventRegex, const std::string &host1StatePath, 58 const std::string &host2UeventRegex, const std::string &host2StatePath, 59 const std::string &dataRolePath, 60 std::function<void()> updatePortStatusCb); 61 ~UsbDataSessionMonitor(); 62 // Returns the compliance warnings detected in the current data session. 63 void getComplianceWarnings(const PortDataRole &role, std::vector<ComplianceWarning> *warnings); 64 65 private: 66 struct usbDeviceState { 67 unique_fd fd; 68 std::string filePath; 69 std::string ueventRegex; 70 // Usb device states reported by state sysfs 71 std::vector<std::string> states; 72 // Timestamps of when the usb device states were captured 73 std::vector<boot_clock::time_point> timestamps; 74 }; 75 76 static void *monitorThread(void *param); 77 void handleUevent(); 78 void handleTimerEvent(); 79 void handleDataRoleEvent(); 80 void handleDeviceStateEvent(struct usbDeviceState *deviceState); 81 void clearDeviceStateEvents(struct usbDeviceState *deviceState); 82 void setupNewSession(); 83 void reportUsbDataSessionMetrics(); 84 void evaluateComplianceWarning(); 85 void notifyComplianceWarning(); 86 void updateUdcBindStatus(const std::string &devname); 87 88 pthread_t mMonitor; 89 unique_fd mEpollFd; 90 unique_fd mUeventFd; 91 unique_fd mTimerFd; 92 unique_fd mDataRoleFd; 93 struct usbDeviceState mDeviceState; 94 struct usbDeviceState mHost1State; 95 struct usbDeviceState mHost2State; 96 std::set<ComplianceWarning> mWarningSet; 97 // Callback function to notify the caller when there's a change in compliance warnings. 98 std::function<void()> mUpdatePortStatusCb; 99 /* 100 * Cache relevant info for a USB data session when one starts, including 101 * the data role and the time when the session starts. 102 */ 103 PortDataRole mDataRole; 104 boot_clock::time_point mDataSessionStart; 105 /* 106 * In gadget mode: this indicates whether the udc device is bound to the configfs driver, which 107 * is done by userspace writing the udc device name to /config/usb_gadget/g1/UDC. When unbound, 108 * the gadget is in soft pulldown state and is expected not to enumerate. During gadget 109 * function switch, the udc device usually go through unbind and bind. 110 */ 111 bool mUdcBind; 112 }; 113 114 } // namespace usb 115 } // namespace hardware 116 } // namespace android 117 } // namespace aidl 118