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 android { 29 namespace hardware { 30 namespace google { 31 namespace pixel { 32 namespace usb { 33 34 using ::aidl::android::hardware::usb::ComplianceWarning; 35 using ::aidl::android::hardware::usb::PortDataRole; 36 using ::android::base::boot_clock; 37 using ::android::base::unique_fd; 38 39 /* 40 * UsbDataSessionMonitor monitors the usb device state sysfs of 3 different usb devices 41 * including device mode (udc), host mode high-speed port and host mode super-speed port. It 42 * reports Suez metrics for each data session and also provides API to query the compliance 43 * warnings detected in the current usb data session. 44 */ 45 class UsbDataSessionMonitor { 46 public: 47 /* 48 * The host mode high-speed port and super-speed port can be assigned to either host1 or 49 * host2 without affecting functionality. 50 * 51 * UeventRegex: name regex of the device that's being monitored. The regex is matched against 52 * uevent to detect dynamic creation/deletion/change of the device. 53 * StatePath: usb device state sysfs path of the device, monitored by epoll. 54 * dataRolePath: path to the usb data role sysfs, monitored by epoll. 55 * updatePortStatusCb: the callback is invoked when the compliance warings changes. 56 */ 57 UsbDataSessionMonitor(const std::string &deviceUeventRegex, const std::string &deviceStatePath, 58 const std::string &host1UeventRegex, const std::string &host1StatePath, 59 const std::string &host2UeventRegex, const std::string &host2StatePath, 60 const std::string &dataRolePath, 61 std::function<void()> updatePortStatusCb); 62 ~UsbDataSessionMonitor(); 63 // Returns the compliance warnings detected in the current data session. 64 void getComplianceWarnings(const PortDataRole &role, std::vector<ComplianceWarning> *warnings); 65 66 private: 67 struct usbDeviceState { 68 // The name of the usb device, e.g. udc, host1, host2. 69 std::string name; 70 unique_fd fd; 71 std::string filePath; 72 std::string ueventRegex; 73 bool delayEpoll; 74 // Usb device states reported by state sysfs 75 std::vector<std::string> states; 76 // Timestamps of when the usb device states were captured 77 std::vector<boot_clock::time_point> timestamps; 78 }; 79 80 static void *monitorThread(void *param); 81 void handleUevent(); 82 void handleTimerEvent(); 83 void handleDataRoleEvent(); 84 void handleDeviceStateEvent(struct usbDeviceState *deviceState); 85 void clearDeviceStateEvents(struct usbDeviceState *deviceState); 86 void setupNewSession(); 87 void reportUsbDataSessionMetrics(); 88 void evaluateComplianceWarning(); 89 void notifyComplianceWarning(); 90 void updateUdcBindStatus(const std::string &devname); 91 92 pthread_t mMonitor; 93 unique_fd mPipefd0; 94 unique_fd mPipefd1; 95 unique_fd mEpollFd; 96 unique_fd mUeventFd; 97 unique_fd mTimerFd; 98 unique_fd mDataRoleFd; 99 struct usbDeviceState mDeviceState; 100 struct usbDeviceState mHost1State; 101 struct usbDeviceState mHost2State; 102 std::set<ComplianceWarning> mWarningSet; 103 // Callback function to notify the caller when there's a change in compliance warnings. 104 std::function<void()> mUpdatePortStatusCb; 105 /* 106 * Cache relevant info for a USB data session when one starts, including 107 * the data role and the time when the session starts. 108 */ 109 PortDataRole mDataRole; 110 boot_clock::time_point mDataSessionStart; 111 /* 112 * In gadget mode: this indicates whether the udc device is bound to the configfs driver, which 113 * is done by userspace writing the udc device name to /config/usb_gadget/g1/UDC. When unbound, 114 * the gadget is in soft pulldown state and is expected not to enumerate. During gadget 115 * function switch, the udc device usually go through unbind and bind. 116 */ 117 bool mUdcBind; 118 }; 119 120 } // namespace usb 121 } // namespace pixel 122 } // namespace google 123 } // namespace hardware 124 } // namespace android 125