From 833435e20a2c28bbfdbbf181085a5d7c55c2daed Mon Sep 17 00:00:00 2001 From: Adam Shih Date: Wed, 22 Mar 2023 11:24:35 +0800 Subject: [PATCH 1/5] Move pixel dumpstate to gs-common Bug: 240530709 Test: adb bugreport Change-Id: Ief9dc020bad3ab6a37c81161121f9424fd4ddff5 Merged-In: I70a1cd1a2a2b78b043f3c7fa8ff47f2fec75e078 (cherry picked from commit 72a8053cd61bacdcb4f8c6a72ddab2063a9c8d32) --- device.mk | 4 - dumpstate/Android.bp | 25 -- dumpstate/Dumpstate.cpp | 215 ------------------ dumpstate/Dumpstate.h | 53 ----- ...android.hardware.dumpstate-service.zuma.rc | 5 - ...ndroid.hardware.dumpstate-service.zuma.xml | 9 - dumpstate/service.cpp | 37 --- 7 files changed, 348 deletions(-) delete mode 100644 dumpstate/Dumpstate.cpp delete mode 100644 dumpstate/Dumpstate.h delete mode 100644 dumpstate/android.hardware.dumpstate-service.zuma.rc delete mode 100644 dumpstate/android.hardware.dumpstate-service.zuma.xml delete mode 100644 dumpstate/service.cpp diff --git a/device.mk b/device.mk index 62892adf..8dfe5c49 100644 --- a/device.mk +++ b/device.mk @@ -471,10 +471,6 @@ include hardware/google/pixel/rebalance_interrupts/rebalance_interrupts.mk PRODUCT_PACKAGES += \ android.hardware.power.stats-service.pixel -# dumpstate HAL -PRODUCT_PACKAGES += \ - android.hardware.dumpstate-service.zuma - # # Audio HALs # diff --git a/dumpstate/Android.bp b/dumpstate/Android.bp index 6d53152c..7494e694 100644 --- a/dumpstate/Android.bp +++ b/dumpstate/Android.bp @@ -23,28 +23,3 @@ sh_binary { sub_dir: "dump", } -cc_binary { - name: "android.hardware.dumpstate-service.zuma", - srcs: [ - "Dumpstate.cpp", - "service.cpp", - ], - init_rc: ["android.hardware.dumpstate-service.zuma.rc"], - vintf_fragments: ["android.hardware.dumpstate-service.zuma.xml"], - cflags: [ - "-Wall", - "-Werror", - ], - shared_libs: [ - "libbase", - "libbinder_ndk", - "libcutils", - "libdumpstateutil", - "liblog", - "libutils", - "libdump", - "android.hardware.dumpstate-V1-ndk", - ], - vendor: true, - relative_install_path: "hw", -} diff --git a/dumpstate/Dumpstate.cpp b/dumpstate/Dumpstate.cpp deleted file mode 100644 index 550d95ec..00000000 --- a/dumpstate/Dumpstate.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "dumpstate_device" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include "Dumpstate.h" - -#include "DumpstateUtil.h" - -#define HW_REVISION "ro.boot.hardware.revision" - -using android::os::dumpstate::CommandOptions; -using android::os::dumpstate::DumpFileToFd; -using android::os::dumpstate::PropertiesHelper; -using android::os::dumpstate::RunCommandToFd; - -namespace aidl { -namespace android { -namespace hardware { -namespace dumpstate { - -typedef std::chrono::time_point timepoint_t; - -const char kVerboseLoggingProperty[] = "persist.vendor.verbose_logging_enabled"; - -timepoint_t startSection(int fd, const std::string §ionName) { - ::android::base::WriteStringToFd( - "\n" - "------ Section start: " + sectionName + " ------\n" - "\n", fd); - return std::chrono::steady_clock::now(); -} - -void endSection(int fd, const std::string §ionName, timepoint_t startTime) { - auto endTime = std::chrono::steady_clock::now(); - auto elapsedMsec = std::chrono::duration_cast - (endTime - startTime).count(); - - ::android::base::WriteStringToFd( - "\n" - "------ Section end: " + sectionName + " ------\n" - "Elapsed msec: " + std::to_string(elapsedMsec) + "\n" - "\n", fd); -} - -// Dump data requested by an argument to the "dump" interface, or help info -// if the specified section is not supported. -void Dumpstate::dumpTextSection(int fd, const std::string §ionName) { - bool dumpAll = (sectionName == kAllSections); - std::string dumpFiles; - - // Execute all or designated programs under vendor/bin/dump/ - std::unique_ptr dir(opendir("/vendor/bin/dump"), closedir); - if (!dir) { - ALOGE("Fail To Open Dir vendor/bin/dump/"); - ::android::base::WriteStringToFd("Fail To Open Dir vendor/bin/dump/\n", fd); - return; - } - dirent *entry; - while ((entry = readdir(dir.get())) != nullptr) { - // Skip '.', '..' - if (entry->d_name[0] == '.') { - continue; - } - std::string bin(entry->d_name); - dumpFiles = dumpFiles + " " + bin; - if (dumpAll || sectionName == bin) { - auto startTime = startSection(fd, bin); - RunCommandToFd(fd, "/vendor/bin/dump/"+bin, {"/vendor/bin/dump/"+bin}, CommandOptions::WithTimeout(15).Build()); - endSection(fd, bin, startTime); - if (!dumpAll) { - return; - } - } - } - - if (dumpAll) { - RunCommandToFd(fd, "VENDOR PROPERTIES", {"/vendor/bin/getprop"}); - return; - } - - // An unsupported section was requested on the command line - ::android::base::WriteStringToFd("Unrecognized text section: " + sectionName + "\n", fd); - ::android::base::WriteStringToFd("Try \"" + kAllSections + "\" or one of the following:", fd); - ::android::base::WriteStringToFd(dumpFiles, fd); - ::android::base::WriteStringToFd("\nNote: sections with attachments (e.g. dump_soc) are" - "not avalable from the command line.\n", fd); -} - -void Dumpstate::dumpLogSection(int fd, int fd_bin) -{ - std::string logDir = MODEM_LOG_DIRECTORY; - const std::string logCombined = logDir + "/combined_logs.tar"; - const std::string logAllDir = logDir + "/all_logs"; - - RunCommandToFd(fd, "MKDIR LOG", {"/vendor/bin/mkdir", "-p", logAllDir.c_str()}, CommandOptions::WithTimeout(2).Build()); - - dumpTextSection(fd, kAllSections); - - RunCommandToFd(fd, "TAR LOG", {"/vendor/bin/tar", "cvf", logCombined.c_str(), "-C", logAllDir.c_str(), "."}, CommandOptions::WithTimeout(20).Build()); - RunCommandToFd(fd, "CHG PERM", {"/vendor/bin/chmod", "a+w", logCombined.c_str()}, CommandOptions::WithTimeout(2).Build()); - - std::vector buffer(65536); - ::android::base::unique_fd fdLog(TEMP_FAILURE_RETRY(open(logCombined.c_str(), O_RDONLY | O_CLOEXEC | O_NONBLOCK))); - - if (fdLog >= 0) { - while (1) { - ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fdLog, buffer.data(), buffer.size())); - - if (bytes_read == 0) { - break; - } else if (bytes_read < 0) { - ALOGD("read(%s): %s\n", logCombined.c_str(), strerror(errno)); - break; - } - - ssize_t result = TEMP_FAILURE_RETRY(write(fd_bin, buffer.data(), bytes_read)); - - if (result != bytes_read) { - ALOGD("Failed to write %ld bytes, actually written: %ld", bytes_read, result); - break; - } - } - } - - RunCommandToFd(fd, "RM LOG DIR", { "/vendor/bin/rm", "-r", logAllDir.c_str()}, CommandOptions::WithTimeout(2).Build()); - RunCommandToFd(fd, "RM LOG", { "/vendor/bin/rm", logCombined.c_str()}, CommandOptions::WithTimeout(2).Build()); -} - -ndk::ScopedAStatus Dumpstate::dumpstateBoard(const std::vector<::ndk::ScopedFileDescriptor>& in_fds, - IDumpstateDevice::DumpstateMode in_mode, - int64_t in_timeoutMillis) { - // Unused arguments. - (void) in_timeoutMillis; - (void) in_mode; - - if (in_fds.size() < 1) { - ALOGE("no FDs\n"); - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, - "No file descriptor"); - } - - int fd = in_fds[0].get(); - if (fd < 0) { - ALOGE("invalid FD: %d\n", fd); - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, - "Invalid file descriptor"); - } - - if (in_fds.size() < 2) { - ALOGE("no FD for dumpstate_board binary\n"); - } else { - int fd_bin = in_fds[1].get(); - dumpLogSection(fd, fd_bin); - } - - return ndk::ScopedAStatus::ok(); -} - -ndk::ScopedAStatus Dumpstate::setVerboseLoggingEnabled(bool in_enable) { - ::android::base::SetProperty(kVerboseLoggingProperty, in_enable ? "true" : "false"); - return ndk::ScopedAStatus::ok(); -} - -ndk::ScopedAStatus Dumpstate::getVerboseLoggingEnabled(bool* _aidl_return) { - *_aidl_return = ::android::base::GetBoolProperty(kVerboseLoggingProperty, false); - return ndk::ScopedAStatus::ok(); -} - -// Since AIDLs that support the dump() interface are automatically invoked during -// bugreport generation and we don't want to generate a second copy of the same -// data that will go into dumpstate_board.txt, this function will only do -// something if it is called with an option, e.g. -// dumpsys android.hardware.dumpstate.IDumpstateDevice/default all -// -// Also, note that sections which generate attachments and/or binary data when -// included in a bugreport are not available through the dump() interface. -binder_status_t Dumpstate::dump(int fd, const char** args, uint32_t numArgs) { - - if (numArgs != 1) { - return STATUS_OK; - } - - dumpTextSection(fd, static_cast(args[0])); - - fsync(fd); - return STATUS_OK; -} - -} // namespace dumpstate -} // namespace hardware -} // namespace android -} // namespace aidl diff --git a/dumpstate/Dumpstate.h b/dumpstate/Dumpstate.h deleted file mode 100644 index 787b7747..00000000 --- a/dumpstate/Dumpstate.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include - -namespace aidl { -namespace android { -namespace hardware { -namespace dumpstate { - -class Dumpstate : public BnDumpstateDevice { - public: - ::ndk::ScopedAStatus dumpstateBoard(const std::vector<::ndk::ScopedFileDescriptor>& in_fds, - IDumpstateDevice::DumpstateMode in_mode, - int64_t in_timeoutMillis) override; - - ::ndk::ScopedAStatus getVerboseLoggingEnabled(bool* _aidl_return) override; - - ::ndk::ScopedAStatus setVerboseLoggingEnabled(bool in_enable) override; - - binder_status_t dump(int fd, const char** args, uint32_t numArgs) override; - - private: - const std::string kAllSections = "all"; - - void dumpTextSection(int fd, std::string const& sectionName); - void dumpLogSection(int fd, int fdModem); - - //bool getVerboseLoggingEnabledImpl(); - //::ndk::ScopedAStatus dumpstateBoardImpl(const int fd, const bool full); -}; - -} // namespace dumpstate -} // namespace hardware -} // namespace android -} // namespace aidl diff --git a/dumpstate/android.hardware.dumpstate-service.zuma.rc b/dumpstate/android.hardware.dumpstate-service.zuma.rc deleted file mode 100644 index e73602bb..00000000 --- a/dumpstate/android.hardware.dumpstate-service.zuma.rc +++ /dev/null @@ -1,5 +0,0 @@ -service vendor.dumpstate-default /vendor/bin/hw/android.hardware.dumpstate-service.zuma - class hal - user system - group system shell - interface aidl android.hardware.dumpstate.IDumpstateDevice/default diff --git a/dumpstate/android.hardware.dumpstate-service.zuma.xml b/dumpstate/android.hardware.dumpstate-service.zuma.xml deleted file mode 100644 index 5e51b287..00000000 --- a/dumpstate/android.hardware.dumpstate-service.zuma.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - android.hardware.dumpstate - - IDumpstateDevice - default - - - diff --git a/dumpstate/service.cpp b/dumpstate/service.cpp deleted file mode 100644 index 1953fd67..00000000 --- a/dumpstate/service.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#define LOG_TAG "android.hardware.dumpstate-service.zuma" - -#include "Dumpstate.h" - -#include -#include -#include - -using aidl::android::hardware::dumpstate::Dumpstate; - -int main() { - ABinderProcess_setThreadPoolMaxThreadCount(0); - std::shared_ptr dumpstate = ndk::SharedRefBase::make(); - - const std::string instance = std::string() + Dumpstate::descriptor + "/default"; - binder_status_t status = - AServiceManager_addService(dumpstate->asBinder().get(), instance.c_str()); - CHECK_EQ(status, STATUS_OK); - - ABinderProcess_joinThreadPool(); - return EXIT_FAILURE; // Unreachable -} From de0fc9d2201685b5eb4c3905e652911b192a542f Mon Sep 17 00:00:00 2001 From: RD Babiera Date: Thu, 2 Feb 2023 22:49:51 +0000 Subject: [PATCH 2/5] Port dp changes to drm sysfs Write pin assignment, hpd, and orientation from type-c class to drmdp platform device attributes using epoll when displayport driver binds to device, and determine whether or not to shut down epoll on displayport driver change uevents. Test: manual testing with form factor device Bug: 260915739 Change-Id: Iec9fc76166481a4611bb2fc023aea044b497f2c0 --- usb/usb/Android.bp | 2 +- usb/usb/Usb.cpp | 342 ++++++++++++++++++++++- usb/usb/Usb.h | 22 ++ usb/usb/android.hardware.usb-service.rc | 8 + usb/usb/android.hardware.usb-service.xml | 2 +- 5 files changed, 372 insertions(+), 4 deletions(-) diff --git a/usb/usb/Android.bp b/usb/usb/Android.bp index 5a73f9a4..b1e0a9ea 100644 --- a/usb/usb/Android.bp +++ b/usb/usb/Android.bp @@ -46,7 +46,7 @@ cc_binary { "android.hardware.thermal@2.0", "android.hardware.thermal-V1-ndk", "android.hardware.usb.gadget@1.0", - "android.hardware.usb-V1-ndk", + "android.hardware.usb-V2-ndk", "android.hardware.usb.gadget-V1-ndk", "libcutils", "android.frameworks.stats-V1-ndk", diff --git a/usb/usb/Usb.cpp b/usb/usb/Usb.cpp index cee66977..c7109353 100644 --- a/usb/usb/Usb.cpp +++ b/usb/usb/Usb.cpp @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -44,6 +45,8 @@ using aidl::android::frameworks::stats::IStats; using android::base::GetProperty; +using android::base::Join; +using android::base::Tokenize; using android::base::Trim; using android::hardware::google::pixel::getStatsService; using android::hardware::google::pixel::PixelAtoms::VendorUsbPortOverheat; @@ -55,11 +58,14 @@ namespace hardware { namespace usb { // Set by the signal handler to destroy the thread volatile bool destroyThread; +volatile bool destroyDisplayPortThread; string enabledPath; constexpr char kHsi2cPath[] = "/sys/devices/platform/10CB0000.hsi2c"; constexpr char kI2CPath[] = "/sys/devices/platform/10CB0000.hsi2c/i2c-"; constexpr char kContaminantDetectionPath[] = "i2c-max77759tcpc/contaminant_detection"; +constexpr char kDisplayPortDrmPath[] = "/sys/devices/platform/110f0000.drmdp/drm-displayport/"; +constexpr char kDisplayPortUsbPath[] = "/sys/class/typec/port0-partner/"; constexpr char kStatusPath[] = "i2c-max77759tcpc/contaminant_detection_status"; constexpr char kSinkLimitEnable[] = "i2c-max77759tcpc/usb_limit_sink_enable"; constexpr char kSourceLimitEnable[] = "i2c-max77759tcpc/usb_limit_source_enable"; @@ -395,7 +401,8 @@ Usb::Usb() ThrottlingSeverity::NONE), ZoneInfo(TemperatureType::UNKNOWN, kThermalZoneForTempReadSecondary2, ThrottlingSeverity::NONE)}, kSamplingIntervalSec), - mUsbDataEnabled(true) { + mUsbDataEnabled(true), + mDisplayPortLock(PTHREAD_MUTEX_INITIALIZER) { pthread_condattr_t attr; if (pthread_condattr_init(&attr)) { ALOGE("pthread_condattr_init failed: %s", strerror(errno)); @@ -413,6 +420,11 @@ Usb::Usb() ALOGE("pthread_condattr_destroy failed: %s", strerror(errno)); abort(); } + mDisplayPortShutdown = eventfd(0, EFD_NONBLOCK); + if (mDisplayPortShutdown == -1) { + ALOGE("mDisplayPortShutdown eventfd failed: %s", strerror(errno)); + abort(); + } } ScopedAStatus Usb::switchRole(const string& in_portName, const PortRole& in_role, @@ -752,6 +764,11 @@ done: return Status::ERROR; } +Status queryDisplayPortStatus(std::vector *currentPortStatus) { + + return Status::SUCCESS; +} + void queryVersionHelper(android::hardware::usb::Usb *usb, std::vector *currentPortStatus) { Status status; @@ -850,10 +867,22 @@ struct data { ::aidl::android::hardware::usb::Usb *usb; }; +enum UeventType { UNKNOWN, BIND, CHANGE }; + +enum UeventType matchUeventType(char* str) { + if (!strncmp(str, "ACTION=bind", strlen("ACTION=bind"))) { + return UeventType::BIND; + } else if (!strncmp(str, "ACTION=change", strlen("ACTION=change"))) { + return UeventType::CHANGE; + } + return UeventType::UNKNOWN; +} + static void uevent_event(uint32_t /*epevents*/, struct data *payload) { char msg[UEVENT_MSG_LEN + 2]; char *cp; int n; + enum UeventType uevent_type = UeventType::UNKNOWN; n = uevent_kernel_multicast_recv(payload->uevent_fd, msg, UEVENT_MSG_LEN); if (n <= 0) @@ -897,10 +926,25 @@ static void uevent_event(uint32_t /*epevents*/, struct data *payload) { } pthread_mutex_unlock(&payload->usb->mRoleSwitchLock); } - break; + if (!!strncmp(cp, "DEVTYPE=typec_alternate_mode", strlen("DEVTYPE=typec_alternate_mode"))) { + break; + } } else if (!strncmp(cp, kOverheatStatsDev, strlen(kOverheatStatsDev))) { ALOGV("Overheat Cooling device suez update"); report_overheat_event(payload->usb); + } else if (!(strncmp(cp, "ACTION=", strlen("ACTION=")))) { + uevent_type = matchUeventType(cp); + } else if (!strncmp(cp, "DRIVER=typec_displayport", strlen("DRIVER=typec_displayport"))) { + if (uevent_type == UeventType::BIND) { + pthread_mutex_lock(&payload->usb->mDisplayPortLock); + payload->usb->setupDisplayPortPoll(); + pthread_mutex_unlock(&payload->usb->mDisplayPortLock); + } else if (uevent_type == UeventType::CHANGE) { + pthread_mutex_lock(&payload->usb->mDisplayPortLock); + payload->usb->shutdownDisplayPortPoll(); + pthread_mutex_unlock(&payload->usb->mDisplayPortLock); + } + break; } /* advance to after the next \0 */ while (*cp++) { @@ -1016,6 +1060,300 @@ ScopedAStatus Usb::setCallback(const shared_ptr& in_callback) { return ScopedAStatus::ok(); } +Status Usb::getDisplayPortUsbPathHelper(string *path) { + DIR *dp; + Status result = Status::ERROR; + + dp = opendir(kDisplayPortUsbPath); + if (dp != NULL) { + struct dirent *ep; + // Iterate through all alt mode directories to find displayport driver + while ((ep = readdir(dp))) { + if (ep->d_type == DT_DIR) { + DIR *displayPortDp; + string portPartnerPath = string(kDisplayPortUsbPath) + string(ep->d_name) + + "/displayport/"; + displayPortDp = opendir(portPartnerPath.c_str()); + if (displayPortDp != NULL) { + *path = portPartnerPath; + closedir(displayPortDp); + result = Status::SUCCESS; + break; + } + } + } + closedir(dp); + } + return result; +} + +Status Usb::writeDisplayPortAttributeOverride(string attribute, string value) { + string attrDrmPath; + + // Get Drm Path + attrDrmPath = string(kDisplayPortDrmPath) + attribute; + + // Write to drm + if(!WriteStringToFile(value, attrDrmPath)) { + ALOGE("usbdp: Failed to write attribute %s to drm: %s", attribute.c_str(), value.c_str()); + return Status::ERROR; + } + ALOGI("usbdp: Successfully wrote attribute %s: %s to drm.", attribute.c_str(), value.c_str()); + return Status::SUCCESS; +} + +Status Usb::writeDisplayPortAttribute(string attribute, string usb_path) { + string attrUsb, attrDrm, attrDrmPath; + + // Get Drm Path + attrDrmPath = string(kDisplayPortDrmPath) + attribute; + + // Read Attribute + if(!ReadFileToString(usb_path, &attrUsb)) { + ALOGE("usbdp: Failed to open or read Type-C attribute %s", attribute.c_str()); + return Status::ERROR; + } + + // Separate Logic for hpd and pin_assignment + if (!strncmp(attribute.c_str(), "hpd", strlen("hpd"))) { + if (!strncmp(attrUsb.c_str(), "0", strlen("0"))) { + // Read DRM attribute to compare + if(!ReadFileToString(attrDrmPath, &attrDrm)) { + ALOGE("usbdp: Failed to open or read hpd from drm"); + return Status::ERROR; + } + if (!strncmp(attrDrm.c_str(), "0", strlen("0"))) { + ALOGI("usbdp: Skipping hpd write when drm and usb both equal 0"); + return Status::SUCCESS; + } + } + } else if (!strncmp(attribute.c_str(), "pin_assignment", strlen("pin_assignment"))) { + size_t pos = attrUsb.find("["); + if (pos != string::npos) { + ALOGI("usbdp: Modifying Pin Config from %s", attrUsb.c_str()); + attrUsb = attrUsb.substr(pos+1, 1); + } else { + // Don't write anything + ALOGI("usbdp: Pin config not yet chosen, nothing written."); + return Status::SUCCESS; + } + } + + // Write to drm + if(!WriteStringToFile(attrUsb, attrDrmPath)) { + ALOGE("usbdp: Failed to write attribute %s to drm: %s", attribute.c_str(), attrUsb.c_str()); + return Status::ERROR; + } + ALOGI("usbdp: Successfully wrote attribute %s: %s to drm.", attribute.c_str(), attrUsb.c_str()); + return Status::SUCCESS; +} + +bool Usb::determineDisplayPortRetry(string linkPath, string hpdPath) { + string linkStatus, hpd; + + if(ReadFileToString(linkPath, &linkStatus) && ReadFileToString(hpdPath, &hpd)) { + if (!strncmp(linkStatus.c_str(), "2", strlen("2")) && + !strncmp(hpd.c_str(), "1", strlen("1"))) { + return true; + } + } + + return false; +} + +static int displayPortPollOpenFileHelper(const char *file, int flags) { + int fd = open(file, flags); + if (fd == -1) { + ALOGE("usbdp: open at %s failed; errno=%d", file, errno); + } + return fd; +} + +void *displayPortPollWork(void *param) { + int epoll_fd; + struct epoll_event ev_hpd, ev_pin, ev_orientation, ev_eventfd, ev_link; + int nevents = 0; + int numRetries = 0; + int hpd_fd, pin_fd, orientation_fd, link_fd; + int file_flags = O_RDONLY; + int epoll_flags; + bool orientationSet = false; + bool pinSet = false; + string displayPortUsbPath; + string hpdPath, pinAssignmentPath, orientationPath, linkPath; + ::aidl::android::hardware::usb::Usb *usb = (::aidl::android::hardware::usb::Usb *)param; + + if (usb->getDisplayPortUsbPathHelper(&displayPortUsbPath) == Status::ERROR) { + ALOGE("usbdp: could not locate usb displayport directory"); + goto error; + } + ALOGI("usbdp: displayport usb path located at %s", displayPortUsbPath.c_str()); + hpdPath = displayPortUsbPath + "hpd"; + pinAssignmentPath = displayPortUsbPath + "pin_assignment"; + orientationPath = "/sys/class/typec/port0/orientation"; + linkPath = string(kDisplayPortDrmPath) + "link_status"; + + epoll_fd = epoll_create(64); + if (epoll_fd == -1) { + ALOGE("usbdp: epoll_create failed; errno=%d", errno); + goto error; + } + + if ((hpd_fd = displayPortPollOpenFileHelper(hpdPath.c_str(), file_flags)) == -1){ + goto error; + } + if ((pin_fd = displayPortPollOpenFileHelper(pinAssignmentPath.c_str(), file_flags)) == -1){ + goto error; + } + if ((orientation_fd = displayPortPollOpenFileHelper(orientationPath.c_str(), file_flags)) + == -1){ + goto error; + } + if ((link_fd = displayPortPollOpenFileHelper(linkPath.c_str(), file_flags)) == -1){ + goto error; + } + + // Set epoll_event events and flags + epoll_flags = EPOLLIN | EPOLLET; + ev_hpd.events = epoll_flags; + ev_pin.events = epoll_flags; + ev_orientation.events = epoll_flags; + ev_eventfd.events = epoll_flags; + ev_link.events = epoll_flags; + ev_hpd.data.fd = hpd_fd; + ev_pin.data.fd = pin_fd; + ev_orientation.data.fd = orientation_fd; + ev_eventfd.data.fd = usb->mDisplayPortShutdown; + ev_link.data.fd = link_fd; + + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, hpd_fd, &ev_hpd) == -1) { + ALOGE("usbdp: epoll_ctl failed to add hpd; errno=%d", errno); + goto error; + } + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pin_fd, &ev_pin) == -1) { + ALOGE("usbdp: epoll_ctl failed to add pin; errno=%d", errno); + goto error; + } + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, orientation_fd, &ev_orientation) == -1) { + ALOGE("usbdp: epoll_ctl failed to add orientation; errno=%d", errno); + goto error; + } + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, link_fd, &ev_link) == -1) { + ALOGE("usbdp: epoll_ctl failed to add link status; errno=%d", errno); + goto error; + } + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, usb->mDisplayPortShutdown, &ev_eventfd) == -1) { + ALOGE("usbdp: epoll_ctl failed to add orientation; errno=%d", errno); + goto error; + } + + while (!destroyDisplayPortThread) { + struct epoll_event events[64]; + + nevents = epoll_wait(epoll_fd, events, 64, -1); + if (nevents == -1) { + if (errno == EINTR) + continue; + ALOGE("usbdp: epoll_wait failed; errno=%d", errno); + break; + } + + for (int n = 0; n < nevents; n++) { + if (events[n].data.fd == hpd_fd) { + if (!pinSet || !orientationSet) { + ALOGW("usbdp: HPD may be set before pin_assignment and orientation"); + } + usb->writeDisplayPortAttribute("hpd", hpdPath); + } else if (events[n].data.fd == pin_fd) { + usb->writeDisplayPortAttribute("pin_assignment", pinAssignmentPath); + pinSet = true; + } else if (events[n].data.fd == orientation_fd) { + usb->writeDisplayPortAttribute("orientation", orientationPath); + orientationSet = true; + } else if (events[n].data.fd == link_fd) { + if (usb->determineDisplayPortRetry(linkPath, hpdPath) && numRetries < 3) { + ALOGW("usbdp: Link Training Failed, rewriting hpd to trigger retry."); + usb->writeDisplayPortAttributeOverride("hpd", "1"); + numRetries++; + } + } else if (events[n].data.fd == usb->mDisplayPortShutdown) { + uint64_t flag = 0; + if (!read(usb->mDisplayPortShutdown, &flag, sizeof(flag))) { + if (errno == EAGAIN) + continue; + ALOGI("usbdp: Shutdown eventfd read error"); + goto error; + } + if (flag == DISPLAYPORT_SHUTDOWN_SET) { + ALOGI("usbdp: Shutdown eventfd triggered"); + destroyDisplayPortThread = true; + break; + } + } + } + } + +error: + ALOGI("usbdp: Exiting worker thread"); + close(hpd_fd); + close(pin_fd); + close(orientation_fd); + close(link_fd); + + if (epoll_fd >= 0) + epoll_ctl(epoll_fd, EPOLL_CTL_DEL, usb->mDisplayPortShutdown, &ev_eventfd); + close(epoll_fd); + return NULL; +} + +void Usb::setupDisplayPortPoll() { + uint64_t flag = DISPLAYPORT_SHUTDOWN_CLEAR; + + write(mDisplayPortShutdown, &flag, sizeof(flag)); + destroyDisplayPortThread = false; + + /* + * Create a background thread to poll DisplayPort system files + */ + if (pthread_create(&mDisplayPortPoll, NULL, displayPortPollWork, this)) { + ALOGE("usbdp: failed to create displayport poll thread %d", errno); + } + ALOGI("usbdp: successfully started DisplayPort poll thread"); + return; +} + +void Usb::shutdownDisplayPortPollHelper() { + pthread_join(mDisplayPortPoll, NULL); +} + +void *shutdownDisplayPortPollWork(void *param) { + ::aidl::android::hardware::usb::Usb *usb = (::aidl::android::hardware::usb::Usb *)param; + + usb->shutdownDisplayPortPollHelper(); + ALOGI("usbdp: DisplayPort Thread Shutdown"); + return NULL; +} + +void Usb::shutdownDisplayPortPoll() { + uint64_t flag = DISPLAYPORT_SHUTDOWN_SET; + string displayPortUsbPath; + + // Determine if should shutdown thread + // getDisplayPortUsbPathHelper locates a DisplayPort directory, no need to double check + // directory. + if (getDisplayPortUsbPathHelper(&displayPortUsbPath) == Status::SUCCESS) { + return; + } + + // Shutdown thread, make sure to rewrite hpd because file no longer exists. + write(mDisplayPortShutdown, &flag, sizeof(flag)); + if (pthread_create(&mDisplayPortShutdownHelper, NULL, shutdownDisplayPortPollWork, NULL)) { + ALOGE("pthread creation failed %d", errno); + } + writeDisplayPortAttributeOverride("hpd", "0"); + destroyDisplayPortThread = false; +} + } // namespace usb } // namespace hardware } // namespace android diff --git a/usb/usb/Usb.h b/usb/usb/Usb.h index d8d6d001..8a1a663e 100644 --- a/usb/usb/Usb.h +++ b/usb/usb/Usb.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #define UEVENT_MSG_LEN 2048 @@ -38,6 +39,7 @@ using ::aidl::android::hardware::usb::IUsbCallback; using ::aidl::android::hardware::usb::PortRole; using ::android::base::ReadFileToString; using ::android::base::WriteStringToFile; +using ::android::base::unique_fd; using ::android::hardware::google::pixel::usb::UsbOverheatEvent; using ::android::hardware::google::pixel::usb::ZoneInfo; using ::android::hardware::thermal::V2_0::TemperatureType; @@ -46,6 +48,7 @@ using ::android::sp; using ::ndk::ScopedAStatus; using ::std::shared_ptr; using ::std::string; +using ::std::thread; constexpr char kGadgetName[] = "11210000.dwc3"; #define NEW_UDC_PATH "/sys/devices/platform/11210000.usb/" @@ -54,6 +57,9 @@ constexpr char kGadgetName[] = "11210000.dwc3"; #define VBUS_PATH NEW_UDC_PATH "dwc3_exynos_otg_b_sess" #define USB_DATA_PATH NEW_UDC_PATH "usb_data_enabled" +#define DISPLAYPORT_SHUTDOWN_CLEAR 0 +#define DISPLAYPORT_SHUTDOWN_SET 1 + struct Usb : public BnUsb { Usb(); @@ -71,6 +77,14 @@ struct Usb : public BnUsb { int64_t in_transactionId) override; ScopedAStatus resetUsbPort(const string& in_portName, int64_t in_transactionId) override; + Status getDisplayPortUsbPathHelper(string *path); + Status writeDisplayPortAttributeOverride(string attribute, string value); + Status writeDisplayPortAttribute(string attribute, string usb_path); + bool determineDisplayPortRetry(string linkPath, string hpdPath); + void setupDisplayPortPoll(); + void shutdownDisplayPortPollHelper(); + void shutdownDisplayPortPoll(); + std::shared_ptr<::aidl::android::hardware::usb::IUsbCallback> mCallback; // Protects mCallback variable pthread_mutex_t mLock; @@ -89,8 +103,16 @@ struct Usb : public BnUsb { float mPluggedTemperatureCelsius; // Usb Data status bool mUsbDataEnabled; + + // Protects writeDisplayPortToExynos(), setupDisplayPortPoll(), and + // shutdownDisplayPortPoll() + pthread_mutex_t mDisplayPortLock; + // eventfd to signal DisplayPort thread + int mDisplayPortShutdown; private: pthread_t mPoll; + pthread_t mDisplayPortPoll; + pthread_t mDisplayPortShutdownHelper; }; } // namespace usb diff --git a/usb/usb/android.hardware.usb-service.rc b/usb/usb/android.hardware.usb-service.rc index 127d9a23..c6d38f1d 100644 --- a/usb/usb/android.hardware.usb-service.rc +++ b/usb/usb/android.hardware.usb-service.rc @@ -20,6 +20,10 @@ on post-fs chown root system /sys/devices/platform/10d50000.hsi2c/i2c-6/i2c-max77759tcpc/usb_limit_sink_enable chown root system /sys/devices/platform/10d50000.hsi2c/i2c-5/i2c-max77759tcpc/usb_limit_source_enable chown root system /sys/devices/platform/10d50000.hsi2c/i2c-6/i2c-max77759tcpc/usb_limit_source_enable + chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/hpd + chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/orientation + chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/pin_assignment + chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/link_status chown root system /sys/devices/platform/11110000.usb/dwc3_exynos_otg_b_sess chown root system /sys/devices/platform/11110000.usb/dwc3_exynos_otg_id chown root system /sys/devices/platform/11110000.usb/usb_data_enabled @@ -42,4 +46,8 @@ on post-fs chmod 664 /sys/devices/platform/10d50000.hsi2c/i2c-6/i2c-max77759tcpc/usb_limit_sink_enable chmod 664 /sys/devices/platform/10d50000.hsi2c/i2c-5/i2c-max77759tcpc/usb_limit_source_enable chmod 664 /sys/devices/platform/10d50000.hsi2c/i2c-6/i2c-max77759tcpc/usb_limit_source_enable + chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/hpd + chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/orientation + chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/pin_assignment + chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/link_status chmod 664 /sys/devices/platform/google,pogo/enable_usb diff --git a/usb/usb/android.hardware.usb-service.xml b/usb/usb/android.hardware.usb-service.xml index 60881948..c3f07f52 100644 --- a/usb/usb/android.hardware.usb-service.xml +++ b/usb/usb/android.hardware.usb-service.xml @@ -1,7 +1,7 @@ android.hardware.usb - 1 + 2 IUsb default From 2173dc37da793599239a974d8f7bc40b2bf1ee80 Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Wed, 5 Apr 2023 20:40:30 +0000 Subject: [PATCH 3/5] usb: Expose persistent vendor property for USB-C Dp Alt Mode The change exposes persist.vendor.usb.displayport.enabled to enable/disable USB-C Dp Alt Mode i.e. DisplayPort over USB-C. By default persist.vendor.usb.displayport.enabled is to 0 in user builds and 1 in all other build variants. Bug: 277107943 Change-Id: I596d3af52f2a813f5f78c4f9b77b6ae3dd8a161b Signed-off-by: Badhri Jagan Sridharan --- conf/init.zuma.usb.rc | 6 ++++++ device.mk | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/conf/init.zuma.usb.rc b/conf/init.zuma.usb.rc index 0f5d22c9..7b4ef192 100644 --- a/conf/init.zuma.usb.rc +++ b/conf/init.zuma.usb.rc @@ -192,3 +192,9 @@ on property:sys.usb.config=charger && property:sys.usb.configfs=1 on property:ro.bootmode=usbuwb setprop persist.vendor.usb.usbradio.config uwb_acm + +on property:persist.vendor.usb.displayport.enabled=1 + write /sys/class/typec/port0/port0.0/mode1/active "yes" + +on property:persist.vendor.usb.displayport.enabled=0 + write /sys/class/typec/port0/port0.0/mode1/active "no" diff --git a/device.mk b/device.mk index 8dfe5c49..be01d7df 100644 --- a/device.mk +++ b/device.mk @@ -196,6 +196,14 @@ PRODUCT_PROPERTY_OVERRIDES += \ PRODUCT_PROPERTY_OVERRIDES += \ telephony.active_modems.max_count=2 +ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT))) +PRODUCT_PROPERTY_OVERRIDES += \ + persist.vendor.usb.displayport.enabled=1 +else +PRODUCT_PROPERTY_OVERRIDES += \ + persist.vendor.usb.displayport.enabled=0 +endif + USE_LASSEN_OEMHOOK := true # Use for GRIL From cc50d9950807280653973a0dd9cd3b22e323bcd5 Mon Sep 17 00:00:00 2001 From: RD Babiera Date: Mon, 17 Apr 2023 22:43:31 +0000 Subject: [PATCH 4/5] usb: provide usb reference to DisplayPort shutdown thread Passes usb object reference to thread creation of mDisplayPortShutdownHelper so that it can properly call DisplayPort shutdown method instead of calling on NULL reference. Test: manual test on device Bug: 278395605 Change-Id: Ie4dabb5e3ae9065f57cc0fbf2593fbe399097472 --- usb/usb/Usb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usb/usb/Usb.cpp b/usb/usb/Usb.cpp index 474164ee..04eabd54 100644 --- a/usb/usb/Usb.cpp +++ b/usb/usb/Usb.cpp @@ -1347,7 +1347,7 @@ void Usb::shutdownDisplayPortPoll() { // Shutdown thread, make sure to rewrite hpd because file no longer exists. write(mDisplayPortShutdown, &flag, sizeof(flag)); - if (pthread_create(&mDisplayPortShutdownHelper, NULL, shutdownDisplayPortPollWork, NULL)) { + if (pthread_create(&mDisplayPortShutdownHelper, NULL, shutdownDisplayPortPollWork, this)) { ALOGE("pthread creation failed %d", errno); } writeDisplayPortAttributeOverride("hpd", "0"); From 4e29924d3d5ef1e9e13df46bf249f91593c73946 Mon Sep 17 00:00:00 2001 From: RD Babiera Date: Thu, 20 Apr 2023 17:33:00 +0000 Subject: [PATCH 5/5] usb: Fix HAL build warnings related to DisplayPort Adds proper error handling go-to points to remove warnings arising from uninitialized variables, and removes unused queryDisplayPortStatus() method. Test: manual test on device, verify compiler warnings Bug: 278951278 Change-Id: I54f7b710a0805b32c894d741e473d64814200134 --- usb/usb/Usb.cpp | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/usb/usb/Usb.cpp b/usb/usb/Usb.cpp index 04eabd54..19454049 100644 --- a/usb/usb/Usb.cpp +++ b/usb/usb/Usb.cpp @@ -764,11 +764,6 @@ done: return Status::ERROR; } -Status queryDisplayPortStatus(std::vector *currentPortStatus) { - - return Status::SUCCESS; -} - void queryVersionHelper(android::hardware::usb::Usb *usb, std::vector *currentPortStatus) { Status status; @@ -1185,7 +1180,7 @@ void *displayPortPollWork(void *param) { if (usb->getDisplayPortUsbPathHelper(&displayPortUsbPath) == Status::ERROR) { ALOGE("usbdp: could not locate usb displayport directory"); - goto error; + goto usb_path_error; } ALOGI("usbdp: displayport usb path located at %s", displayPortUsbPath.c_str()); hpdPath = displayPortUsbPath + "hpd"; @@ -1196,21 +1191,21 @@ void *displayPortPollWork(void *param) { epoll_fd = epoll_create(64); if (epoll_fd == -1) { ALOGE("usbdp: epoll_create failed; errno=%d", errno); - goto error; + goto epoll_fd_error; } if ((hpd_fd = displayPortPollOpenFileHelper(hpdPath.c_str(), file_flags)) == -1){ - goto error; + goto hpd_fd_error; } if ((pin_fd = displayPortPollOpenFileHelper(pinAssignmentPath.c_str(), file_flags)) == -1){ - goto error; + goto pin_fd_error; } if ((orientation_fd = displayPortPollOpenFileHelper(orientationPath.c_str(), file_flags)) == -1){ - goto error; + goto orientation_fd_error; } if ((link_fd = displayPortPollOpenFileHelper(linkPath.c_str(), file_flags)) == -1){ - goto error; + goto link_fd_error; } // Set epoll_event events and flags @@ -1294,15 +1289,19 @@ void *displayPortPollWork(void *param) { } error: - ALOGI("usbdp: Exiting worker thread"); - close(hpd_fd); - close(pin_fd); - close(orientation_fd); close(link_fd); - - if (epoll_fd >= 0) - epoll_ctl(epoll_fd, EPOLL_CTL_DEL, usb->mDisplayPortShutdown, &ev_eventfd); - close(epoll_fd); +link_fd_error: + close(orientation_fd); +orientation_fd_error: + close(pin_fd); +pin_fd_error: + close(hpd_fd); +hpd_fd_error: + epoll_ctl(epoll_fd, EPOLL_CTL_DEL, usb->mDisplayPortShutdown, &ev_eventfd); + close(epoll_fd); +epoll_fd_error: +usb_path_error: + ALOGI("usbdp: Exiting worker thread"); return NULL; }