From 3604f56e5ed215522a0a7f9149bd303b22c72b92 Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Mon, 17 Jan 2022 20:43:02 -0800 Subject: [PATCH] Migrate IUsb implementation to AIDL This change migrates IUsb implementation to AIDL. Also, IUsb and IUsbGadget now run in its own processes to improve stability and isolation. Bug: 200993386 Bug: 199357330 Change-Id: I02753af4a41916b77ce110f9531504bf8c6a4691 Merged-In: I02753af4a41916b77ce110f9531504bf8c6a4691 (cherry picked from commit 3c97a6bb68f6418ee41026f3bd0024405c97cf0c) --- device.mk | 4 +- usb/Usb.cpp | 938 ------------------ usb/{ => gadget}/Android.bp | 23 +- usb/{ => gadget}/UsbGadget.cpp | 0 usb/{ => gadget}/UsbGadget.h | 0 ...roid.hardware.usb.gadget-service.gs101.rc} | 2 +- ....hardware.usb.gadget@1.2-service.gs101.xml | 0 .../service_gadget.cpp} | 22 +- usb/usb/Android.bp | 52 + usb/usb/Usb.cpp | 850 ++++++++++++++++ usb/{ => usb}/Usb.h | 74 +- usb/usb/android.hardware.usb-service.rc | 21 + .../android.hardware.usb-service.xml} | 6 +- usb/usb/service.cpp | 37 + 14 files changed, 1001 insertions(+), 1028 deletions(-) delete mode 100644 usb/Usb.cpp rename usb/{ => gadget}/Android.bp (67%) rename usb/{ => gadget}/UsbGadget.cpp (100%) rename usb/{ => gadget}/UsbGadget.h (100%) rename usb/{android.hardware.usb@1.3-service.gs101.rc => gadget/android.hardware.usb.gadget-service.gs101.rc} (98%) rename usb/{ => gadget}/android.hardware.usb.gadget@1.2-service.gs101.xml (100%) rename usb/{service.cpp => gadget/service_gadget.cpp} (70%) create mode 100644 usb/usb/Android.bp create mode 100644 usb/usb/Usb.cpp rename usb/{ => usb}/Usb.h (54%) create mode 100644 usb/usb/android.hardware.usb-service.rc rename usb/{android.hardware.usb@1.3-service.gs101.xml => usb/android.hardware.usb-service.xml} (69%) create mode 100644 usb/usb/service.cpp diff --git a/device.mk b/device.mk index 18961b83..968cab3a 100644 --- a/device.mk +++ b/device.mk @@ -368,7 +368,9 @@ endif # USB HAL PRODUCT_PACKAGES += \ - android.hardware.usb@1.3-service.gs101 + android.hardware.usb-service.gs101 +PRODUCT_PACKAGES += \ + android.hardware.usb.gadget-service.gs101 # MIDI feature PRODUCT_COPY_FILES += \ diff --git a/usb/Usb.cpp b/usb/Usb.cpp deleted file mode 100644 index caf4f57b..00000000 --- a/usb/Usb.cpp +++ /dev/null @@ -1,938 +0,0 @@ -/* - * Copyright (C) 2020 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.usb@1.3-service.gs101" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "Usb.h" -#include "UsbGadget.h" - -#include -#include - -using aidl::android::frameworks::stats::IStats; -using android::base::GetProperty; -using android::hardware::google::pixel::getStatsService; -using android::hardware::google::pixel::PixelAtoms::VendorUsbPortOverheat; -using android::hardware::google::pixel::reportUsbPortOverheat; - -namespace android { -namespace hardware { -namespace usb { -namespace V1_3 { -namespace implementation { - -Return Usb::enableUsbDataSignal(bool enable) { - bool result = true; - - ALOGI("Userspace turn %s USB data signaling", enable ? "on" : "off"); - - if(enable) { - if (!WriteStringToFile("1", USB_DATA_PATH)) { - ALOGE("Not able to turn on usb connection notification"); - result = false; - } - - if(!WriteStringToFile(kGadgetName, PULLUP_PATH)) { - ALOGE("Gadget cannot be pulled up"); - result = false; - } - } - else { - if (!WriteStringToFile("1", ID_PATH)) { - ALOGE("Not able to turn off host mode"); - result = false; - } - - if (!WriteStringToFile("0", VBUS_PATH)) { - ALOGE("Not able to set Vbus state"); - result = false; - } - - if (!WriteStringToFile("0", USB_DATA_PATH)) { - ALOGE("Not able to turn off usb connection notification"); - result = false; - } - - if(!WriteStringToFile("none", PULLUP_PATH)) { - ALOGE("Gadget cannot be pulled down"); - result = false; - } - } - - return result; -} - -// Set by the signal handler to destroy the thread -volatile bool destroyThread; - -std::string enabledPath; -constexpr char kHsi2cPath[] = "/sys/devices/platform/10d50000.hsi2c"; -constexpr char kI2CPath[] = "/sys/devices/platform/10d50000.hsi2c/i2c-"; -constexpr char kContaminantDetectionPath[] = "i2c-max77759tcpc/contaminant_detection"; -constexpr char kStatusPath[] = "i2c-max77759tcpc/contaminant_detection_status"; -constexpr char kTypecPath[] = "/sys/class/typec"; -constexpr char kDisableContatminantDetection[] = "vendor.usb.contaminantdisable"; -constexpr char kOverheatStatsPath[] = "/sys/devices/platform/google,usbc_port_cooling_dev/"; -constexpr char kOverheatStatsDev[] = "DRIVER=google,usbc_port_cooling_dev"; -constexpr char kThermalZoneForTrip[] = "VIRTUAL-USB-THROTTLING"; -constexpr char kThermalZoneForTempReadPrimary[] = "usb_pwr_therm2"; -constexpr char kThermalZoneForTempReadSecondary1[] = "usb_pwr_therm"; -constexpr char kThermalZoneForTempReadSecondary2[] = "qi_therm"; -constexpr int kSamplingIntervalSec = 5; - -int32_t readFile(const std::string &filename, std::string *contents) { - FILE *fp; - ssize_t read = 0; - char *line = NULL; - size_t len = 0; - - fp = fopen(filename.c_str(), "r"); - if (fp != NULL) { - if ((read = getline(&line, &len, fp)) != -1) { - char *pos; - if ((pos = strchr(line, '\n')) != NULL) - *pos = '\0'; - *contents = line; - } - free(line); - fclose(fp); - return 0; - } else { - ALOGE("fopen failed"); - } - - return -1; -} - -int32_t writeFile(const std::string &filename, const std::string &contents) { - FILE *fp; - std::string written; - - fp = fopen(filename.c_str(), "w"); - if (fp != NULL) { - // FAILURE RETRY - int ret = fputs(contents.c_str(), fp); - fclose(fp); - if ((ret != EOF) && !readFile(filename, &written) && written == contents) - return 0; - } - return -1; -} - -Status getContaminantDetectionNamesHelper(std::string *name) { - DIR *dp; - - dp = opendir(kHsi2cPath); - if (dp != NULL) { - struct dirent *ep; - - while ((ep = readdir(dp))) { - if (ep->d_type == DT_DIR) { - if (std::string::npos != std::string(ep->d_name).find("i2c-")) { - std::strtok(ep->d_name, "-"); - *name = std::strtok(NULL, "-"); - } - } - } - closedir(dp); - return Status::SUCCESS; - } - - ALOGE("Failed to open %s", kHsi2cPath); - return Status::ERROR; -} - -Status queryMoistureDetectionStatus(hidl_vec *currentPortStatus_1_2) { - std::string enabled, status, path, DetectedPath; - - if (currentPortStatus_1_2 == NULL || currentPortStatus_1_2->size() == 0) { - ALOGE("currentPortStatus_1_2 is not available"); - return Status::ERROR; - } - - (*currentPortStatus_1_2)[0].supportedContaminantProtectionModes = 0; - (*currentPortStatus_1_2)[0].supportedContaminantProtectionModes |= - V1_2::ContaminantProtectionMode::FORCE_SINK; - (*currentPortStatus_1_2)[0].contaminantProtectionStatus = V1_2::ContaminantProtectionStatus::NONE; - (*currentPortStatus_1_2)[0].contaminantDetectionStatus = V1_2::ContaminantDetectionStatus::DISABLED; - (*currentPortStatus_1_2)[0].supportsEnableContaminantPresenceDetection = true; - (*currentPortStatus_1_2)[0].supportsEnableContaminantPresenceProtection = false; - - getContaminantDetectionNamesHelper(&path); - enabledPath = kI2CPath + path + "/" + kContaminantDetectionPath; - if (readFile(enabledPath, &enabled)) { - ALOGE("Failed to open moisture_detection_enabled"); - return Status::ERROR; - } - - if (enabled == "1") { - DetectedPath = kI2CPath + path + "/" + kStatusPath; - if (readFile(DetectedPath, &status)) { - ALOGE("Failed to open moisture_detected"); - return Status::ERROR; - } - if (status == "1") { - (*currentPortStatus_1_2)[0].contaminantDetectionStatus = - V1_2::ContaminantDetectionStatus::DETECTED; - (*currentPortStatus_1_2)[0].contaminantProtectionStatus = - V1_2::ContaminantProtectionStatus::FORCE_SINK; - } else - (*currentPortStatus_1_2)[0].contaminantDetectionStatus = - V1_2::ContaminantDetectionStatus::NOT_DETECTED; - } - - ALOGI("ContaminantDetectionStatus:%d ContaminantProtectionStatus:%d", - (*currentPortStatus_1_2)[0].contaminantDetectionStatus, - (*currentPortStatus_1_2)[0].contaminantProtectionStatus); - - return Status::SUCCESS; -} - -std::string appendRoleNodeHelper(const std::string &portName, PortRoleType type) { - std::string node("/sys/class/typec/" + portName); - - switch (type) { - case PortRoleType::DATA_ROLE: - return node + "/data_role"; - case PortRoleType::POWER_ROLE: - return node + "/power_role"; - case PortRoleType::MODE: - return node + "/port_type"; - default: - return ""; - } -} - -std::string convertRoletoString(PortRole role) { - if (role.type == PortRoleType::POWER_ROLE) { - if (role.role == static_cast(PortPowerRole::SOURCE)) - return "source"; - else if (role.role == static_cast(PortPowerRole::SINK)) - return "sink"; - } else if (role.type == PortRoleType::DATA_ROLE) { - if (role.role == static_cast(PortDataRole::HOST)) - return "host"; - if (role.role == static_cast(PortDataRole::DEVICE)) - return "device"; - } else if (role.type == PortRoleType::MODE) { - if (role.role == static_cast(PortMode_1_1::UFP)) - return "sink"; - if (role.role == static_cast(PortMode_1_1::DFP)) - return "source"; - } - return "none"; -} - -void extractRole(std::string *roleName) { - std::size_t first, last; - - first = roleName->find("["); - last = roleName->find("]"); - - if (first != std::string::npos && last != std::string::npos) { - *roleName = roleName->substr(first + 1, last - first - 1); - } -} - -void switchToDrp(const std::string &portName) { - std::string filename = appendRoleNodeHelper(std::string(portName.c_str()), PortRoleType::MODE); - FILE *fp; - - if (filename != "") { - fp = fopen(filename.c_str(), "w"); - if (fp != NULL) { - int ret = fputs("dual", fp); - fclose(fp); - if (ret == EOF) - ALOGE("Fatal: Error while switching back to drp"); - } else { - ALOGE("Fatal: Cannot open file to switch back to drp"); - } - } else { - ALOGE("Fatal: invalid node type"); - } -} - -bool switchMode(const hidl_string &portName, const PortRole &newRole, struct Usb *usb) { - std::string filename = appendRoleNodeHelper(std::string(portName.c_str()), newRole.type); - std::string written; - FILE *fp; - bool roleSwitch = false; - - if (filename == "") { - ALOGE("Fatal: invalid node type"); - return false; - } - - fp = fopen(filename.c_str(), "w"); - if (fp != NULL) { - // Hold the lock here to prevent loosing connected signals - // as once the file is written the partner added signal - // can arrive anytime. - pthread_mutex_lock(&usb->mPartnerLock); - usb->mPartnerUp = false; - int ret = fputs(convertRoletoString(newRole).c_str(), fp); - fclose(fp); - - if (ret != EOF) { - struct timespec to; - struct timespec now; - - wait_again: - clock_gettime(CLOCK_MONOTONIC, &now); - to.tv_sec = now.tv_sec + PORT_TYPE_TIMEOUT; - to.tv_nsec = now.tv_nsec; - - int err = pthread_cond_timedwait(&usb->mPartnerCV, &usb->mPartnerLock, &to); - // There are no uevent signals which implies role swap timed out. - if (err == ETIMEDOUT) { - ALOGI("uevents wait timedout"); - // Validity check. - } else if (!usb->mPartnerUp) { - goto wait_again; - // Role switch succeeded since usb->mPartnerUp is true. - } else { - roleSwitch = true; - } - } else { - ALOGI("Role switch failed while wrting to file"); - } - pthread_mutex_unlock(&usb->mPartnerLock); - } - - if (!roleSwitch) - switchToDrp(std::string(portName.c_str())); - - return roleSwitch; -} - -Usb::Usb() - : mLock(PTHREAD_MUTEX_INITIALIZER), - mRoleSwitchLock(PTHREAD_MUTEX_INITIALIZER), - mPartnerLock(PTHREAD_MUTEX_INITIALIZER), - mPartnerUp(false), - mOverheat(ZoneInfo(TemperatureType::USB_PORT, kThermalZoneForTrip, - ThrottlingSeverity::CRITICAL), - {ZoneInfo(TemperatureType::UNKNOWN, kThermalZoneForTempReadPrimary, - ThrottlingSeverity::NONE), - ZoneInfo(TemperatureType::UNKNOWN, kThermalZoneForTempReadSecondary1, - ThrottlingSeverity::NONE), - ZoneInfo(TemperatureType::UNKNOWN, kThermalZoneForTempReadSecondary2, - ThrottlingSeverity::NONE)}, kSamplingIntervalSec) { - pthread_condattr_t attr; - if (pthread_condattr_init(&attr)) { - ALOGE("pthread_condattr_init failed: %s", strerror(errno)); - abort(); - } - if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) { - ALOGE("pthread_condattr_setclock failed: %s", strerror(errno)); - abort(); - } - if (pthread_cond_init(&mPartnerCV, &attr)) { - ALOGE("pthread_cond_init failed: %s", strerror(errno)); - abort(); - } - if (pthread_condattr_destroy(&attr)) { - ALOGE("pthread_condattr_destroy failed: %s", strerror(errno)); - abort(); - } -} - -Return Usb::switchRole(const hidl_string &portName, const V1_0::PortRole &newRole) { - std::string filename = appendRoleNodeHelper(std::string(portName.c_str()), newRole.type); - std::string written; - FILE *fp; - bool roleSwitch = false; - - if (filename == "") { - ALOGE("Fatal: invalid node type"); - return Void(); - } - - pthread_mutex_lock(&mRoleSwitchLock); - - ALOGI("filename write: %s role:%s", filename.c_str(), convertRoletoString(newRole).c_str()); - - if (newRole.type == PortRoleType::MODE) { - roleSwitch = switchMode(portName, newRole, this); - } else { - fp = fopen(filename.c_str(), "w"); - if (fp != NULL) { - int ret = fputs(convertRoletoString(newRole).c_str(), fp); - fclose(fp); - if ((ret != EOF) && !readFile(filename, &written)) { - extractRole(&written); - ALOGI("written: %s", written.c_str()); - if (written == convertRoletoString(newRole)) { - roleSwitch = true; - } else { - ALOGE("Role switch failed"); - } - } else { - ALOGE("failed to update the new role"); - } - } else { - ALOGE("fopen failed"); - } - } - - pthread_mutex_lock(&mLock); - if (mCallback_1_0 != NULL) { - Return ret = mCallback_1_0->notifyRoleSwitchStatus( - portName, newRole, roleSwitch ? Status::SUCCESS : Status::ERROR); - if (!ret.isOk()) - ALOGE("RoleSwitchStatus error %s", ret.description().c_str()); - } else { - ALOGE("Not notifying the userspace. Callback is not set"); - } - pthread_mutex_unlock(&mLock); - pthread_mutex_unlock(&mRoleSwitchLock); - - return Void(); -} - -Status getAccessoryConnected(const std::string &portName, std::string *accessory) { - std::string filename = "/sys/class/typec/" + portName + "-partner/accessory_mode"; - - if (readFile(filename, accessory)) { - ALOGE("getAccessoryConnected: Failed to open filesystem node: %s", filename.c_str()); - return Status::ERROR; - } - - return Status::SUCCESS; -} - -Status getCurrentRoleHelper(const std::string &portName, bool connected, PortRoleType type, - uint32_t *currentRole) { - std::string filename; - std::string roleName; - std::string accessory; - - // Mode - - if (type == PortRoleType::POWER_ROLE) { - filename = "/sys/class/typec/" + portName + "/power_role"; - *currentRole = static_cast(PortPowerRole::NONE); - } else if (type == PortRoleType::DATA_ROLE) { - filename = "/sys/class/typec/" + portName + "/data_role"; - *currentRole = static_cast(PortDataRole::NONE); - } else if (type == PortRoleType::MODE) { - filename = "/sys/class/typec/" + portName + "/data_role"; - *currentRole = static_cast(PortMode_1_1::NONE); - } else { - return Status::ERROR; - } - - if (!connected) - return Status::SUCCESS; - - if (type == PortRoleType::MODE) { - if (getAccessoryConnected(portName, &accessory) != Status::SUCCESS) { - return Status::ERROR; - } - if (accessory == "analog_audio") { - *currentRole = static_cast(PortMode_1_1::AUDIO_ACCESSORY); - return Status::SUCCESS; - } else if (accessory == "debug") { - *currentRole = static_cast(PortMode_1_1::DEBUG_ACCESSORY); - return Status::SUCCESS; - } - } - - if (readFile(filename, &roleName)) { - ALOGE("getCurrentRole: Failed to open filesystem node: %s", filename.c_str()); - return Status::ERROR; - } - - extractRole(&roleName); - - if (roleName == "source") { - *currentRole = static_cast(PortPowerRole::SOURCE); - } else if (roleName == "sink") { - *currentRole = static_cast(PortPowerRole::SINK); - } else if (roleName == "host") { - if (type == PortRoleType::DATA_ROLE) - *currentRole = static_cast(PortDataRole::HOST); - else - *currentRole = static_cast(PortMode_1_1::DFP); - } else if (roleName == "device") { - if (type == PortRoleType::DATA_ROLE) - *currentRole = static_cast(PortDataRole::DEVICE); - else - *currentRole = static_cast(PortMode_1_1::UFP); - } else if (roleName != "none") { - /* case for none has already been addressed. - * so we check if the role isn't none. - */ - return Status::UNRECOGNIZED_ROLE; - } - - return Status::SUCCESS; -} - -Status getTypeCPortNamesHelper(std::unordered_map *names) { - DIR *dp; - - dp = opendir(kTypecPath); - if (dp != NULL) { - struct dirent *ep; - - while ((ep = readdir(dp))) { - if (ep->d_type == DT_LNK) { - if (std::string::npos == std::string(ep->d_name).find("-partner")) { - std::unordered_map::const_iterator portName = - names->find(ep->d_name); - if (portName == names->end()) { - names->insert({ep->d_name, false}); - } - } else { - (*names)[std::strtok(ep->d_name, "-")] = true; - } - } - } - closedir(dp); - return Status::SUCCESS; - } - - ALOGE("Failed to open /sys/class/typec"); - return Status::ERROR; -} - -bool canSwitchRoleHelper(const std::string &portName, PortRoleType /*type*/) { - std::string filename = "/sys/class/typec/" + portName + "-partner/supports_usb_power_delivery"; - std::string supportsPD; - - if (!readFile(filename, &supportsPD)) { - if (supportsPD == "yes") { - return true; - } - } - - return false; -} - -/* - * Reuse the same method for both V1_0 and V1_1 callback objects. - * The caller of this method would reconstruct the V1_0::PortStatus - * object if required. - */ -Status getPortStatusHelper(hidl_vec *currentPortStatus_1_2, HALVersion version, - android::hardware::usb::V1_3::implementation::Usb *usb) { - std::unordered_map names; - Status result = getTypeCPortNamesHelper(&names); - int i = -1; - - if (result == Status::SUCCESS) { - currentPortStatus_1_2->resize(names.size()); - for (std::pair port : names) { - i++; - ALOGI("%s", port.first.c_str()); - (*currentPortStatus_1_2)[i].status_1_1.status.portName = port.first; - - uint32_t currentRole; - if (getCurrentRoleHelper(port.first, port.second, PortRoleType::POWER_ROLE, - ¤tRole) == Status::SUCCESS) { - (*currentPortStatus_1_2)[i].status_1_1.status.currentPowerRole = - static_cast(currentRole); - } else { - ALOGE("Error while retrieving portNames"); - goto done; - } - - if (getCurrentRoleHelper(port.first, port.second, PortRoleType::DATA_ROLE, - ¤tRole) == Status::SUCCESS) { - (*currentPortStatus_1_2)[i].status_1_1.status.currentDataRole = - static_cast(currentRole); - } else { - ALOGE("Error while retrieving current port role"); - goto done; - } - - if (getCurrentRoleHelper(port.first, port.second, PortRoleType::MODE, ¤tRole) == - Status::SUCCESS) { - (*currentPortStatus_1_2)[i].status_1_1.currentMode = - static_cast(currentRole); - (*currentPortStatus_1_2)[i].status_1_1.status.currentMode = - static_cast(currentRole); - } else { - ALOGE("Error while retrieving current data role"); - goto done; - } - - (*currentPortStatus_1_2)[i].status_1_1.status.canChangeMode = true; - (*currentPortStatus_1_2)[i].status_1_1.status.canChangeDataRole = - port.second ? canSwitchRoleHelper(port.first, PortRoleType::DATA_ROLE) : false; - (*currentPortStatus_1_2)[i].status_1_1.status.canChangePowerRole = - port.second ? canSwitchRoleHelper(port.first, PortRoleType::POWER_ROLE) : false; - - if (version == HALVersion::V1_0) { - ALOGI("HAL version V1_0"); - (*currentPortStatus_1_2)[i].status_1_1.status.supportedModes = V1_0::PortMode::DRP; - } else { - if (version == HALVersion::V1_1) - ALOGI("HAL version V1_1"); - else - ALOGI("HAL version V1_2"); - (*currentPortStatus_1_2)[i].status_1_1.supportedModes = 0 | PortMode_1_1::DRP; - (*currentPortStatus_1_2)[i].status_1_1.status.supportedModes = V1_0::PortMode::NONE; - (*currentPortStatus_1_2)[i].status_1_1.status.currentMode = V1_0::PortMode::NONE; - } - - // Query temperature for the first connect - if (port.second && !usb->mPluggedTemperatureCelsius) { - usb->mOverheat.getCurrentTemperature(kThermalZoneForTempReadPrimary, - &usb->mPluggedTemperatureCelsius); - ALOGV("USB Initial temperature: %f", usb->mPluggedTemperatureCelsius); - } - ALOGI( - "%d:%s connected:%d canChangeMode:%d canChagedata:%d canChangePower:%d " - "supportedModes:%d", - i, port.first.c_str(), port.second, - (*currentPortStatus_1_2)[i].status_1_1.status.canChangeMode, - (*currentPortStatus_1_2)[i].status_1_1.status.canChangeDataRole, - (*currentPortStatus_1_2)[i].status_1_1.status.canChangePowerRole, - (*currentPortStatus_1_2)[i].status_1_1.supportedModes); - } - return Status::SUCCESS; - } -done: - return Status::ERROR; -} - -void queryVersionHelper(android::hardware::usb::V1_3::implementation::Usb *usb, - hidl_vec *currentPortStatus_1_2) { - hidl_vec currentPortStatus_1_1; - hidl_vec currentPortStatus; - Status status; - sp callback_V1_1 = V1_1::IUsbCallback::castFrom(usb->mCallback_1_0); - sp callback_V1_2 = IUsbCallback::castFrom(usb->mCallback_1_0); - - pthread_mutex_lock(&usb->mLock); - if (usb->mCallback_1_0 != NULL) { - if (callback_V1_2 != NULL) { - status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_2, usb); - if (status == Status::SUCCESS) - queryMoistureDetectionStatus(currentPortStatus_1_2); - } else if (callback_V1_1 != NULL) { - status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_1, usb); - currentPortStatus_1_1.resize(currentPortStatus_1_2->size()); - for (unsigned long i = 0; i < currentPortStatus_1_2->size(); i++) - currentPortStatus_1_1[i] = (*currentPortStatus_1_2)[i].status_1_1; - } else { - status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_0, usb); - currentPortStatus.resize(currentPortStatus_1_2->size()); - for (unsigned long i = 0; i < currentPortStatus_1_2->size(); i++) - currentPortStatus[i] = (*currentPortStatus_1_2)[i].status_1_1.status; - } - - Return ret; - - if (callback_V1_2 != NULL) - ret = callback_V1_2->notifyPortStatusChange_1_2(*currentPortStatus_1_2, status); - else if (callback_V1_1 != NULL) - ret = callback_V1_1->notifyPortStatusChange_1_1(currentPortStatus_1_1, status); - else - ret = usb->mCallback_1_0->notifyPortStatusChange(currentPortStatus, status); - - if (!ret.isOk()) - ALOGE("queryPortStatus_1_2 error %s", ret.description().c_str()); - } else { - ALOGI("Notifying userspace skipped. Callback is NULL"); - } - pthread_mutex_unlock(&usb->mLock); -} - -Return Usb::queryPortStatus() { - hidl_vec currentPortStatus_1_2; - - queryVersionHelper(this, ¤tPortStatus_1_2); - return Void(); -} - -Return Usb::enableContaminantPresenceDetection(const hidl_string & /*portName*/, - bool enable) { - - std::string disable = GetProperty(kDisableContatminantDetection, ""); - - if (disable != "true") - writeFile(enabledPath, enable ? "1" : "0"); - - hidl_vec currentPortStatus_1_2; - - queryVersionHelper(this, ¤tPortStatus_1_2); - return Void(); -} - -Return Usb::enableContaminantPresenceProtection(const hidl_string & /*portName*/, - bool /*enable*/) { - hidl_vec currentPortStatus_1_2; - - queryVersionHelper(this, ¤tPortStatus_1_2); - return Void(); -} - -void report_overheat_event(android::hardware::usb::V1_3::implementation::Usb *usb) { - VendorUsbPortOverheat overheat_info; - std::string contents; - - overheat_info.set_plug_temperature_deci_c(usb->mPluggedTemperatureCelsius * 10); - overheat_info.set_max_temperature_deci_c(usb->mOverheat.getMaxOverheatTemperature() * 10); - if (ReadFileToString(std::string(kOverheatStatsPath) + "trip_time", &contents)) { - overheat_info.set_time_to_overheat_secs(stoi(contents)); - } else { - ALOGE("Unable to read trip_time"); - return; - } - if (ReadFileToString(std::string(kOverheatStatsPath) + "hysteresis_time", &contents)) { - overheat_info.set_time_to_hysteresis_secs(stoi(contents)); - } else { - ALOGE("Unable to read hysteresis_time"); - return; - } - if (ReadFileToString(std::string(kOverheatStatsPath) + "cleared_time", &contents)) { - overheat_info.set_time_to_inactive_secs(stoi(contents)); - } else { - ALOGE("Unable to read cleared_time"); - return; - } - - const std::shared_ptr stats_client = getStatsService(); - if (!stats_client) { - ALOGE("Unable to get AIDL Stats service"); - } else { - reportUsbPortOverheat(stats_client, overheat_info); - } -} - -struct data { - int uevent_fd; - android::hardware::usb::V1_3::implementation::Usb *usb; -}; - -static void uevent_event(uint32_t /*epevents*/, struct data *payload) { - char msg[UEVENT_MSG_LEN + 2]; - char *cp; - int n; - - n = uevent_kernel_multicast_recv(payload->uevent_fd, msg, UEVENT_MSG_LEN); - if (n <= 0) - return; - if (n >= UEVENT_MSG_LEN) /* overflow -- discard */ - return; - - msg[n] = '\0'; - msg[n + 1] = '\0'; - cp = msg; - - while (*cp) { - if (std::regex_match(cp, std::regex("(add)(.*)(-partner)"))) { - ALOGI("partner added"); - pthread_mutex_lock(&payload->usb->mPartnerLock); - payload->usb->mPartnerUp = true; - pthread_cond_signal(&payload->usb->mPartnerCV); - pthread_mutex_unlock(&payload->usb->mPartnerLock); - // Update Plugged temperature - payload->usb->mOverheat.getCurrentTemperature(kThermalZoneForTempReadPrimary, - &payload->usb->mPluggedTemperatureCelsius); - ALOGI("Usb Plugged temp: %f", payload->usb->mPluggedTemperatureCelsius); - } else if (!strncmp(cp, "DEVTYPE=typec_", strlen("DEVTYPE=typec_")) || - !strncmp(cp, "DRIVER=max77759tcpc", - strlen("DRIVER=max77759tcpc"))) { - hidl_vec currentPortStatus_1_2; - queryVersionHelper(payload->usb, ¤tPortStatus_1_2); - - // Role switch is not in progress and port is in disconnected state - if (!pthread_mutex_trylock(&payload->usb->mRoleSwitchLock)) { - for (unsigned long i = 0; i < currentPortStatus_1_2.size(); i++) { - DIR *dp = - opendir(std::string("/sys/class/typec/" + - std::string(currentPortStatus_1_2[i] - .status_1_1.status.portName.c_str()) + - "-partner") - .c_str()); - if (dp == NULL) { - // PortRole role = {.role = static_cast(PortMode::UFP)}; - switchToDrp(currentPortStatus_1_2[i].status_1_1.status.portName); - } else { - closedir(dp); - } - } - pthread_mutex_unlock(&payload->usb->mRoleSwitchLock); - } - break; - } else if (!strncmp(cp, kOverheatStatsDev, strlen(kOverheatStatsDev))) { - ALOGV("Overheat Cooling device suez update"); - report_overheat_event(payload->usb); - } - /* advance to after the next \0 */ - while (*cp++) { - } - } -} - -void *work(void *param) { - int epoll_fd, uevent_fd; - struct epoll_event ev; - int nevents = 0; - struct data payload; - - ALOGE("creating thread"); - - uevent_fd = uevent_open_socket(64 * 1024, true); - - if (uevent_fd < 0) { - ALOGE("uevent_init: uevent_open_socket failed\n"); - return NULL; - } - - payload.uevent_fd = uevent_fd; - payload.usb = (android::hardware::usb::V1_3::implementation::Usb *)param; - - fcntl(uevent_fd, F_SETFL, O_NONBLOCK); - - ev.events = EPOLLIN; - ev.data.ptr = (void *)uevent_event; - - epoll_fd = epoll_create(64); - if (epoll_fd == -1) { - ALOGE("epoll_create failed; errno=%d", errno); - goto error; - } - - if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1) { - ALOGE("epoll_ctl failed; errno=%d", errno); - goto error; - } - - while (!destroyThread) { - struct epoll_event events[64]; - - nevents = epoll_wait(epoll_fd, events, 64, -1); - if (nevents == -1) { - if (errno == EINTR) - continue; - ALOGE("usb epoll_wait failed; errno=%d", errno); - break; - } - - for (int n = 0; n < nevents; ++n) { - if (events[n].data.ptr) - (*(void (*)(int, struct data *payload))events[n].data.ptr)(events[n].events, - &payload); - } - } - - ALOGI("exiting worker thread"); -error: - close(uevent_fd); - - if (epoll_fd >= 0) - close(epoll_fd); - - return NULL; -} - -void sighandler(int sig) { - if (sig == SIGUSR1) { - destroyThread = true; - ALOGI("destroy set"); - return; - } - signal(SIGUSR1, sighandler); -} - -Return Usb::setCallback(const sp &callback) { - sp callback_V1_1 = V1_1::IUsbCallback::castFrom(callback); - sp callback_V1_2 = IUsbCallback::castFrom(callback); - - if (callback != NULL) { - if (callback_V1_2 != NULL) - ALOGI("Registering 1.2 callback"); - else if (callback_V1_1 != NULL) - ALOGI("Registering 1.1 callback"); - } - - pthread_mutex_lock(&mLock); - /* - * When both the old callback and new callback values are NULL, - * there is no need to spin off the worker thread. - * When both the values are not NULL, we would already have a - * worker thread running, so updating the callback object would - * be suffice. - */ - if ((mCallback_1_0 == NULL && callback == NULL) || - (mCallback_1_0 != NULL && callback != NULL)) { - /* - * Always store as V1_0 callback object. Type cast to V1_1 - * when the callback is actually invoked. - */ - mCallback_1_0 = callback; - pthread_mutex_unlock(&mLock); - return Void(); - } - - mCallback_1_0 = callback; - ALOGI("registering callback"); - - // Kill the worker thread if the new callback is NULL. - if (mCallback_1_0 == NULL) { - pthread_mutex_unlock(&mLock); - if (!pthread_kill(mPoll, SIGUSR1)) { - pthread_join(mPoll, NULL); - ALOGI("pthread destroyed"); - } - return Void(); - } - - destroyThread = false; - signal(SIGUSR1, sighandler); - - /* - * Create a background thread if the old callback value is NULL - * and being updated with a new value. - */ - if (pthread_create(&mPoll, NULL, work, this)) { - ALOGE("pthread creation failed %d", errno); - mCallback_1_0 = NULL; - } - - pthread_mutex_unlock(&mLock); - return Void(); -} - -} // namespace implementation -} // namespace V1_3 -} // namespace usb -} // namespace hardware -} // namespace android diff --git a/usb/Android.bp b/usb/gadget/Android.bp similarity index 67% rename from usb/Android.bp rename to usb/gadget/Android.bp index 5aafe145..ab7ac325 100644 --- a/usb/Android.bp +++ b/usb/gadget/Android.bp @@ -1,5 +1,5 @@ // -// Copyright (C) 2017 The Android Open Source Project +// Copyright (C) 2021 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. @@ -25,14 +25,13 @@ package { } cc_binary { - name: "android.hardware.usb@1.3-service.gs101", + name: "android.hardware.usb.gadget-service.gs101", relative_install_path: "hw", - init_rc: ["android.hardware.usb@1.3-service.gs101.rc"], + init_rc: ["android.hardware.usb.gadget-service.gs101.rc"], vintf_fragments: [ - "android.hardware.usb@1.3-service.gs101.xml", "android.hardware.usb.gadget@1.2-service.gs101.xml", ], - srcs: ["service.cpp", "Usb.cpp", "UsbGadget.cpp"], + srcs: ["service_gadget.cpp", "UsbGadget.cpp"], cflags: ["-Wall", "-Werror"], shared_libs: [ "libbase", @@ -41,27 +40,13 @@ cc_binary { "liblog", "libutils", "libhardware", - "android.hardware.usb@1.0", - "android.hardware.usb@1.1", - "android.hardware.usb@1.2", - "android.hardware.usb@1.3", "android.hardware.usb.gadget@1.0", "android.hardware.usb.gadget@1.1", "android.hardware.usb.gadget@1.2", - "android.hardware.thermal@1.0", - "android.hardware.thermal@2.0", "libcutils", - "android.frameworks.stats-V1-ndk", - "pixelatoms-cpp", - "libbinder_ndk", ], static_libs: [ "libpixelusb", - "libpixelstats", - ], - export_shared_lib_headers: [ - "android.frameworks.stats-V1-ndk", - "pixelatoms-cpp", ], proprietary: true, } diff --git a/usb/UsbGadget.cpp b/usb/gadget/UsbGadget.cpp similarity index 100% rename from usb/UsbGadget.cpp rename to usb/gadget/UsbGadget.cpp diff --git a/usb/UsbGadget.h b/usb/gadget/UsbGadget.h similarity index 100% rename from usb/UsbGadget.h rename to usb/gadget/UsbGadget.h diff --git a/usb/android.hardware.usb@1.3-service.gs101.rc b/usb/gadget/android.hardware.usb.gadget-service.gs101.rc similarity index 98% rename from usb/android.hardware.usb@1.3-service.gs101.rc rename to usb/gadget/android.hardware.usb.gadget-service.gs101.rc index 4112b4ec..dcf44bb9 100644 --- a/usb/android.hardware.usb@1.3-service.gs101.rc +++ b/usb/gadget/android.hardware.usb.gadget-service.gs101.rc @@ -1,4 +1,4 @@ -service vendor.usb-hal-1-3 /vendor/bin/hw/android.hardware.usb@1.3-service.gs101 +service vendor.usb-gadget-hal-1-2 /vendor/bin/hw/android.hardware.usb.gadget-service.gs101 class hal user system group system shell mtp wakelock diff --git a/usb/android.hardware.usb.gadget@1.2-service.gs101.xml b/usb/gadget/android.hardware.usb.gadget@1.2-service.gs101.xml similarity index 100% rename from usb/android.hardware.usb.gadget@1.2-service.gs101.xml rename to usb/gadget/android.hardware.usb.gadget@1.2-service.gs101.xml diff --git a/usb/service.cpp b/usb/gadget/service_gadget.cpp similarity index 70% rename from usb/service.cpp rename to usb/gadget/service_gadget.cpp index a4a30d2a..d0908ee4 100644 --- a/usb/service.cpp +++ b/usb/gadget/service_gadget.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright (C) 2021 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. @@ -14,10 +14,9 @@ * limitations under the License. */ -#define LOG_TAG "android.hardware.usb@1.3-service.gs101" +#define LOG_TAG "android.hardware.usb.gadget-service.gs101" #include -#include "Usb.h" #include "UsbGadget.h" using android::sp; @@ -29,34 +28,23 @@ using android::hardware::joinRpcThreadpool; // Generated HIDL files using android::hardware::usb::gadget::V1_2::IUsbGadget; using android::hardware::usb::gadget::V1_2::implementation::UsbGadget; -using android::hardware::usb::V1_3::IUsb; -using android::hardware::usb::V1_3::implementation::Usb; using android::OK; using android::status_t; int main() { - android::sp service = new Usb(); - android::sp service2 = new UsbGadget(); - + android::sp service = new UsbGadget(); configureRpcThreadpool(2, true /*callerWillJoin*/); status_t status = service->registerAsService(); - if (status != OK) { - ALOGE("Cannot register USB HAL service"); - return 1; - } - - status = service2->registerAsService(); - if (status != OK) { ALOGE("Cannot register USB Gadget HAL service"); return 1; } - ALOGI("USB HAL Ready."); + ALOGI("USB gadget HAL Ready."); joinRpcThreadpool(); // Under noraml cases, execution will not reach this line. - ALOGI("USB HAL failed to join thread pool."); + ALOGI("USB gadget HAL failed to join thread pool."); return 1; } diff --git a/usb/usb/Android.bp b/usb/usb/Android.bp new file mode 100644 index 00000000..0ce3167a --- /dev/null +++ b/usb/usb/Android.bp @@ -0,0 +1,52 @@ +// +// Copyright (C) 2021 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. +// + +cc_binary { + name: "android.hardware.usb-service.gs101", + relative_install_path: "hw", + init_rc: ["android.hardware.usb-service.rc"], + vintf_fragments: ["android.hardware.usb-service.xml"], + vendor: true, + srcs: [ + "service.cpp", + "Usb.cpp", + ], + shared_libs: [ + "libbase", + "libbinder", + "libhidlbase", + "liblog", + "libutils", + "libhardware", + "android.hardware.thermal@1.0", + "android.hardware.thermal@2.0", + "android.hardware.usb.gadget@1.0", + "android.hardware.usb-V1-ndk", + "libcutils", + "android.frameworks.stats-V1-ndk", + "pixelatoms-cpp", + "libbinder_ndk", + + ], + static_libs: [ + "libpixelusb", + "libpixelstats", + ], + export_shared_lib_headers: [ + "android.frameworks.stats-V1-ndk", + "pixelatoms-cpp", + ], +} diff --git a/usb/usb/Usb.cpp b/usb/usb/Usb.cpp new file mode 100644 index 00000000..7aa4ced0 --- /dev/null +++ b/usb/usb/Usb.cpp @@ -0,0 +1,850 @@ +/* + * Copyright (C) 2021 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.usb.aidl-service" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "Usb.h" + +#include +#include +#include + +using aidl::android::frameworks::stats::IStats; +using android::base::GetProperty; +using android::base::Trim; +using android::hardware::google::pixel::getStatsService; +using android::hardware::google::pixel::PixelAtoms::VendorUsbPortOverheat; +using android::hardware::google::pixel::reportUsbPortOverheat; + +namespace aidl { +namespace android { +namespace hardware { +namespace usb { +// Set by the signal handler to destroy the thread +volatile bool destroyThread; + +string enabledPath; +constexpr char kHsi2cPath[] = "/sys/devices/platform/10d50000.hsi2c"; +constexpr char kI2CPath[] = "/sys/devices/platform/10d50000.hsi2c/i2c-"; +constexpr char kContaminantDetectionPath[] = "i2c-max77759tcpc/contaminant_detection"; +constexpr char kStatusPath[] = "i2c-max77759tcpc/contaminant_detection_status"; +constexpr char kTypecPath[] = "/sys/class/typec"; +constexpr char kDisableContatminantDetection[] = "vendor.usb.contaminantdisable"; +constexpr char kOverheatStatsPath[] = "/sys/devices/platform/google,usbc_port_cooling_dev/"; +constexpr char kOverheatStatsDev[] = "DRIVER=google,usbc_port_cooling_dev"; +constexpr char kThermalZoneForTrip[] = "VIRTUAL-USB-THROTTLING"; +constexpr char kThermalZoneForTempReadPrimary[] = "usb_pwr_therm2"; +constexpr char kThermalZoneForTempReadSecondary1[] = "usb_pwr_therm"; +constexpr char kThermalZoneForTempReadSecondary2[] = "qi_therm"; +constexpr int kSamplingIntervalSec = 5; +void queryVersionHelper(android::hardware::usb::Usb *usb, + std::vector *currentPortStatus); + +ScopedAStatus Usb::enableUsbData(const string& in_portName, bool in_enable, + int64_t in_transactionId) { + bool result = true; + std::vector currentPortStatus; + + ALOGI("Userspace turn %s USB data signaling. opID:%ld", in_enable ? "on" : "off", + in_transactionId); + + if (in_enable) { + if (!WriteStringToFile("1", USB_DATA_PATH)) { + ALOGE("Not able to turn on usb connection notification"); + result = false; + } + + if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) { + ALOGE("Gadget cannot be pulled up"); + result = false; + } + } else { + if (!WriteStringToFile("1", ID_PATH)) { + ALOGE("Not able to turn off host mode"); + result = false; + } + + if (!WriteStringToFile("0", VBUS_PATH)) { + ALOGE("Not able to set Vbus state"); + result = false; + } + + if (!WriteStringToFile("0", USB_DATA_PATH)) { + ALOGE("Not able to turn on usb connection notification"); + result = false; + } + + if (!WriteStringToFile("none", PULLUP_PATH)) { + ALOGE("Gadget cannot be pulled down"); + result = false; + } + } + + if (result) { + mUsbDataEnabled = in_enable; + } + pthread_mutex_lock(&mLock); + if (mCallback != NULL) { + ScopedAStatus ret = mCallback->notifyEnableUsbDataStatus( + in_portName, in_enable, result ? Status::SUCCESS : Status::ERROR, in_transactionId); + if (!ret.isOk()) + ALOGE("notifyEnableUsbDataStatus error %s", ret.getDescription().c_str()); + } else { + ALOGE("Not notifying the userspace. Callback is not set"); + } + pthread_mutex_unlock(&mLock); + queryVersionHelper(this, ¤tPortStatus); + + return ScopedAStatus::ok(); +} + +Status getContaminantDetectionNamesHelper(string *name) { + DIR *dp; + + dp = opendir(kHsi2cPath); + if (dp != NULL) { + struct dirent *ep; + + while ((ep = readdir(dp))) { + if (ep->d_type == DT_DIR) { + if (string::npos != string(ep->d_name).find("i2c-")) { + std::strtok(ep->d_name, "-"); + *name = std::strtok(NULL, "-"); + } + } + } + closedir(dp); + return Status::SUCCESS; + } + + ALOGE("Failed to open %s", kHsi2cPath); + return Status::ERROR; +} + +Status queryMoistureDetectionStatus(std::vector *currentPortStatus) { + string enabled, status, path, DetectedPath; + + (*currentPortStatus)[0].supportedContaminantProtectionModes + .push_back(ContaminantProtectionMode::FORCE_DISABLE); + (*currentPortStatus)[0].contaminantProtectionStatus = ContaminantProtectionStatus::NONE; + (*currentPortStatus)[0].contaminantDetectionStatus = ContaminantDetectionStatus::DISABLED; + (*currentPortStatus)[0].supportsEnableContaminantPresenceDetection = true; + (*currentPortStatus)[0].supportsEnableContaminantPresenceProtection = false; + + getContaminantDetectionNamesHelper(&path); + enabledPath = kI2CPath + path + "/" + kContaminantDetectionPath; + if (!ReadFileToString(enabledPath, &enabled)) { + ALOGE("Failed to open moisture_detection_enabled"); + return Status::ERROR; + } + + enabled = Trim(enabled); + if (enabled == "1") { + DetectedPath = kI2CPath + path + "/" + kStatusPath; + if (!ReadFileToString(DetectedPath, &status)) { + ALOGE("Failed to open moisture_detected"); + return Status::ERROR; + } + status = Trim(status); + if (status == "1") { + (*currentPortStatus)[0].contaminantDetectionStatus = + ContaminantDetectionStatus::DETECTED; + (*currentPortStatus)[0].contaminantProtectionStatus = + ContaminantProtectionStatus::FORCE_DISABLE; + } else { + (*currentPortStatus)[0].contaminantDetectionStatus = + ContaminantDetectionStatus::NOT_DETECTED; + } + } + + ALOGI("ContaminantDetectionStatus:%d ContaminantProtectionStatus:%d", + (*currentPortStatus)[0].contaminantDetectionStatus, + (*currentPortStatus)[0].contaminantProtectionStatus); + + return Status::SUCCESS; +} + +string appendRoleNodeHelper(const string &portName, PortRole::Tag tag) { + string node("/sys/class/typec/" + portName); + + switch (tag) { + case PortRole::dataRole: + return node + "/data_role"; + case PortRole::powerRole: + return node + "/power_role"; + case PortRole::mode: + return node + "/port_type"; + default: + return ""; + } +} + +string convertRoletoString(PortRole role) { + if (role.getTag() == PortRole::powerRole) { + if (role.get() == PortPowerRole::SOURCE) + return "source"; + else if (role.get() == PortPowerRole::SINK) + return "sink"; + } else if (role.getTag() == PortRole::dataRole) { + if (role.get() == PortDataRole::HOST) + return "host"; + if (role.get() == PortDataRole::DEVICE) + return "device"; + } else if (role.getTag() == PortRole::mode) { + if (role.get() == PortMode::UFP) + return "sink"; + if (role.get() == PortMode::DFP) + return "source"; + } + return "none"; +} + +void extractRole(string *roleName) { + std::size_t first, last; + + first = roleName->find("["); + last = roleName->find("]"); + + if (first != string::npos && last != string::npos) { + *roleName = roleName->substr(first + 1, last - first - 1); + } +} + +void switchToDrp(const string &portName) { + string filename = appendRoleNodeHelper(string(portName.c_str()), PortRole::mode); + FILE *fp; + + if (filename != "") { + fp = fopen(filename.c_str(), "w"); + if (fp != NULL) { + int ret = fputs("dual", fp); + fclose(fp); + if (ret == EOF) + ALOGE("Fatal: Error while switching back to drp"); + } else { + ALOGE("Fatal: Cannot open file to switch back to drp"); + } + } else { + ALOGE("Fatal: invalid node type"); + } +} + +bool switchMode(const string &portName, const PortRole &in_role, struct Usb *usb) { + string filename = appendRoleNodeHelper(string(portName.c_str()), in_role.getTag()); + string written; + FILE *fp; + bool roleSwitch = false; + + if (filename == "") { + ALOGE("Fatal: invalid node type"); + return false; + } + + fp = fopen(filename.c_str(), "w"); + if (fp != NULL) { + // Hold the lock here to prevent loosing connected signals + // as once the file is written the partner added signal + // can arrive anytime. + pthread_mutex_lock(&usb->mPartnerLock); + usb->mPartnerUp = false; + int ret = fputs(convertRoletoString(in_role).c_str(), fp); + fclose(fp); + + if (ret != EOF) { + struct timespec to; + struct timespec now; + + wait_again: + clock_gettime(CLOCK_MONOTONIC, &now); + to.tv_sec = now.tv_sec + PORT_TYPE_TIMEOUT; + to.tv_nsec = now.tv_nsec; + + int err = pthread_cond_timedwait(&usb->mPartnerCV, &usb->mPartnerLock, &to); + // There are no uevent signals which implies role swap timed out. + if (err == ETIMEDOUT) { + ALOGI("uevents wait timedout"); + // Validity check. + } else if (!usb->mPartnerUp) { + goto wait_again; + // Role switch succeeded since usb->mPartnerUp is true. + } else { + roleSwitch = true; + } + } else { + ALOGI("Role switch failed while wrting to file"); + } + pthread_mutex_unlock(&usb->mPartnerLock); + } + + if (!roleSwitch) + switchToDrp(string(portName.c_str())); + + return roleSwitch; +} + +Usb::Usb() + : mLock(PTHREAD_MUTEX_INITIALIZER), + mRoleSwitchLock(PTHREAD_MUTEX_INITIALIZER), + mPartnerLock(PTHREAD_MUTEX_INITIALIZER), + mPartnerUp(false), + mOverheat(ZoneInfo(TemperatureType::USB_PORT, kThermalZoneForTrip, + ThrottlingSeverity::CRITICAL), + {ZoneInfo(TemperatureType::UNKNOWN, kThermalZoneForTempReadPrimary, + ThrottlingSeverity::NONE), + ZoneInfo(TemperatureType::UNKNOWN, kThermalZoneForTempReadSecondary1, + ThrottlingSeverity::NONE), + ZoneInfo(TemperatureType::UNKNOWN, kThermalZoneForTempReadSecondary2, + ThrottlingSeverity::NONE)}, kSamplingIntervalSec), + mUsbDataEnabled(true) { + pthread_condattr_t attr; + if (pthread_condattr_init(&attr)) { + ALOGE("pthread_condattr_init failed: %s", strerror(errno)); + abort(); + } + if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) { + ALOGE("pthread_condattr_setclock failed: %s", strerror(errno)); + abort(); + } + if (pthread_cond_init(&mPartnerCV, &attr)) { + ALOGE("pthread_cond_init failed: %s", strerror(errno)); + abort(); + } + if (pthread_condattr_destroy(&attr)) { + ALOGE("pthread_condattr_destroy failed: %s", strerror(errno)); + abort(); + } +} + +ScopedAStatus Usb::switchRole(const string& in_portName, const PortRole& in_role, + int64_t in_transactionId) { + string filename = appendRoleNodeHelper(string(in_portName.c_str()), in_role.getTag()); + string written; + FILE *fp; + bool roleSwitch = false; + + if (filename == "") { + ALOGE("Fatal: invalid node type"); + return ScopedAStatus::ok(); + } + + pthread_mutex_lock(&mRoleSwitchLock); + + ALOGI("filename write: %s role:%s", filename.c_str(), convertRoletoString(in_role).c_str()); + + if (in_role.getTag() == PortRole::mode) { + roleSwitch = switchMode(in_portName, in_role, this); + } else { + fp = fopen(filename.c_str(), "w"); + if (fp != NULL) { + int ret = fputs(convertRoletoString(in_role).c_str(), fp); + fclose(fp); + if ((ret != EOF) && ReadFileToString(filename, &written)) { + written = Trim(written); + extractRole(&written); + ALOGI("written: %s", written.c_str()); + if (written == convertRoletoString(in_role)) { + roleSwitch = true; + } else { + ALOGE("Role switch failed"); + } + } else { + ALOGE("failed to update the new role"); + } + } else { + ALOGE("fopen failed"); + } + } + + pthread_mutex_lock(&mLock); + if (mCallback != NULL) { + ScopedAStatus ret = mCallback->notifyRoleSwitchStatus( + in_portName, in_role, roleSwitch ? Status::SUCCESS : Status::ERROR, in_transactionId); + if (!ret.isOk()) + ALOGE("RoleSwitchStatus error %s", ret.getDescription().c_str()); + } else { + ALOGE("Not notifying the userspace. Callback is not set"); + } + pthread_mutex_unlock(&mLock); + pthread_mutex_unlock(&mRoleSwitchLock); + + return ScopedAStatus::ok(); +} + +Status getAccessoryConnected(const string &portName, string *accessory) { + string filename = "/sys/class/typec/" + portName + "-partner/accessory_mode"; + + if (!ReadFileToString(filename, accessory)) { + ALOGE("getAccessoryConnected: Failed to open filesystem node: %s", filename.c_str()); + return Status::ERROR; + } + *accessory = Trim(*accessory); + + return Status::SUCCESS; +} + +Status getCurrentRoleHelper(const string &portName, bool connected, PortRole *currentRole) { + string filename; + string roleName; + string accessory; + + // Mode + + if (currentRole->getTag() == PortRole::powerRole) { + filename = "/sys/class/typec/" + portName + "/power_role"; + currentRole->set(PortPowerRole::NONE); + } else if (currentRole->getTag() == PortRole::dataRole) { + filename = "/sys/class/typec/" + portName + "/data_role"; + currentRole->set(PortDataRole::NONE); + } else if (currentRole->getTag() == PortRole::mode) { + filename = "/sys/class/typec/" + portName + "/data_role"; + currentRole->set(PortMode::NONE); + } else { + return Status::ERROR; + } + + if (!connected) + return Status::SUCCESS; + + if (currentRole->getTag() == PortRole::mode) { + if (getAccessoryConnected(portName, &accessory) != Status::SUCCESS) { + return Status::ERROR; + } + if (accessory == "analog_audio") { + currentRole->set(PortMode::AUDIO_ACCESSORY); + return Status::SUCCESS; + } else if (accessory == "debug") { + currentRole->set(PortMode::DEBUG_ACCESSORY); + return Status::SUCCESS; + } + } + + if (!ReadFileToString(filename, &roleName)) { + ALOGE("getCurrentRole: Failed to open filesystem node: %s", filename.c_str()); + return Status::ERROR; + } + + roleName = Trim(roleName); + extractRole(&roleName); + + if (roleName == "source") { + currentRole->set(PortPowerRole::SOURCE); + } else if (roleName == "sink") { + currentRole->set(PortPowerRole::SINK); + } else if (roleName == "host") { + if (currentRole->getTag() == PortRole::dataRole) + currentRole->set(PortDataRole::HOST); + else + currentRole->set(PortMode::DFP); + } else if (roleName == "device") { + if (currentRole->getTag() == PortRole::dataRole) + currentRole->set(PortDataRole::DEVICE); + else + currentRole->set(PortMode::UFP); + } else if (roleName != "none") { + /* case for none has already been addressed. + * so we check if the role isn't none. + */ + return Status::UNRECOGNIZED_ROLE; + } + return Status::SUCCESS; +} + +Status getTypeCPortNamesHelper(std::unordered_map *names) { + DIR *dp; + + dp = opendir(kTypecPath); + if (dp != NULL) { + struct dirent *ep; + + while ((ep = readdir(dp))) { + if (ep->d_type == DT_LNK) { + if (string::npos == string(ep->d_name).find("-partner")) { + std::unordered_map::const_iterator portName = + names->find(ep->d_name); + if (portName == names->end()) { + names->insert({ep->d_name, false}); + } + } else { + (*names)[std::strtok(ep->d_name, "-")] = true; + } + } + } + closedir(dp); + return Status::SUCCESS; + } + + ALOGE("Failed to open /sys/class/typec"); + return Status::ERROR; +} + +bool canSwitchRoleHelper(const string &portName) { + string filename = "/sys/class/typec/" + portName + "-partner/supports_usb_power_delivery"; + string supportsPD; + + if (ReadFileToString(filename, &supportsPD)) { + supportsPD = Trim(supportsPD); + if (supportsPD == "yes") { + return true; + } + } + + return false; +} + +Status getPortStatusHelper(android::hardware::usb::Usb *usb, + std::vector *currentPortStatus) { + std::unordered_map names; + Status result = getTypeCPortNamesHelper(&names); + int i = -1; + + if (result == Status::SUCCESS) { + currentPortStatus->resize(names.size()); + for (std::pair port : names) { + i++; + ALOGI("%s", port.first.c_str()); + (*currentPortStatus)[i].portName = port.first; + + PortRole currentRole; + currentRole.set(PortPowerRole::NONE); + if (getCurrentRoleHelper(port.first, port.second, ¤tRole) == Status::SUCCESS){ + (*currentPortStatus)[i].currentPowerRole = currentRole.get(); + } else { + ALOGE("Error while retrieving portNames"); + goto done; + } + + currentRole.set(PortDataRole::NONE); + if (getCurrentRoleHelper(port.first, port.second, ¤tRole) == Status::SUCCESS) { + (*currentPortStatus)[i].currentDataRole = currentRole.get(); + } else { + ALOGE("Error while retrieving current port role"); + goto done; + } + + currentRole.set(PortMode::NONE); + if (getCurrentRoleHelper(port.first, port.second, ¤tRole) == Status::SUCCESS) { + (*currentPortStatus)[i].currentMode = currentRole.get(); + } else { + ALOGE("Error while retrieving current data role"); + goto done; + } + + (*currentPortStatus)[i].canChangeMode = true; + (*currentPortStatus)[i].canChangeDataRole = + port.second ? canSwitchRoleHelper(port.first) : false; + (*currentPortStatus)[i].canChangePowerRole = + port.second ? canSwitchRoleHelper(port.first) : false; + + (*currentPortStatus)[i].supportedModes.push_back(PortMode::DRP); + (*currentPortStatus)[i].usbDataEnabled = usb->mUsbDataEnabled; + + ALOGI("%d:%s connected:%d canChangeMode:%d canChagedata:%d canChangePower:%d " + "usbDataEnabled:%d", + i, port.first.c_str(), port.second, + (*currentPortStatus)[i].canChangeMode, + (*currentPortStatus)[i].canChangeDataRole, + (*currentPortStatus)[i].canChangePowerRole, + (*currentPortStatus)[i].usbDataEnabled ? 1 : 0); + } + return Status::SUCCESS; + } +done: + return Status::ERROR; +} + +void queryVersionHelper(android::hardware::usb::Usb *usb, + std::vector *currentPortStatus) { + Status status; + pthread_mutex_lock(&usb->mLock); + status = getPortStatusHelper(usb, currentPortStatus); + queryMoistureDetectionStatus(currentPortStatus); + if (usb->mCallback != NULL) { + ScopedAStatus ret = usb->mCallback->notifyPortStatusChange(*currentPortStatus, + status); + if (!ret.isOk()) + ALOGE("queryPortStatus error %s", ret.getDescription().c_str()); + } else { + ALOGI("Notifying userspace skipped. Callback is NULL"); + } + pthread_mutex_unlock(&usb->mLock); +} + +ScopedAStatus Usb::queryPortStatus(int64_t in_transactionId) { + std::vector currentPortStatus; + + queryVersionHelper(this, ¤tPortStatus); + pthread_mutex_lock(&mLock); + if (mCallback != NULL) { + ScopedAStatus ret = mCallback->notifyQueryPortStatus( + "all", Status::SUCCESS, in_transactionId); + if (!ret.isOk()) + ALOGE("notifyQueryPortStatus error %s", ret.getDescription().c_str()); + } else { + ALOGE("Not notifying the userspace. Callback is not set"); + } + pthread_mutex_unlock(&mLock); + + return ScopedAStatus::ok(); +} + +ScopedAStatus Usb::enableContaminantPresenceDetection(const string& in_portName, + bool in_enable, int64_t in_transactionId) { + string disable = GetProperty(kDisableContatminantDetection, ""); + std::vector currentPortStatus; + bool success = true; + + if (disable != "true") + success = WriteStringToFile(in_enable ? "1" : "0", enabledPath); + + pthread_mutex_lock(&mLock); + if (mCallback != NULL) { + ScopedAStatus ret = mCallback->notifyContaminantEnabledStatus( + in_portName, in_enable, success ? Status::SUCCESS : Status::ERROR, in_transactionId); + if (!ret.isOk()) + ALOGE("notifyContaminantEnabledStatus error %s", ret.getDescription().c_str()); + } else { + ALOGE("Not notifying the userspace. Callback is not set"); + } + pthread_mutex_unlock(&mLock); + + queryVersionHelper(this, ¤tPortStatus); + return ScopedAStatus::ok(); +} + + +void report_overheat_event(android::hardware::usb::Usb *usb) { + VendorUsbPortOverheat overheat_info; + string contents; + + overheat_info.set_plug_temperature_deci_c(usb->mPluggedTemperatureCelsius * 10); + overheat_info.set_max_temperature_deci_c(usb->mOverheat.getMaxOverheatTemperature() * 10); + if (ReadFileToString(string(kOverheatStatsPath) + "trip_time", &contents)) { + overheat_info.set_time_to_overheat_secs(stoi(Trim(contents))); + } else { + ALOGE("Unable to read trip_time"); + return; + } + if (ReadFileToString(string(kOverheatStatsPath) + "hysteresis_time", &contents)) { + overheat_info.set_time_to_hysteresis_secs(stoi(Trim(contents))); + } else { + ALOGE("Unable to read hysteresis_time"); + return; + } + if (ReadFileToString(string(kOverheatStatsPath) + "cleared_time", &contents)) { + overheat_info.set_time_to_inactive_secs(stoi(Trim(contents))); + } else { + ALOGE("Unable to read cleared_time"); + return; + } + + const shared_ptr stats_client = getStatsService(); + if (!stats_client) { + ALOGE("Unable to get AIDL Stats service"); + } else { + reportUsbPortOverheat(stats_client, overheat_info); + } +} + +struct data { + int uevent_fd; + ::aidl::android::hardware::usb::Usb *usb; +}; + +static void uevent_event(uint32_t /*epevents*/, struct data *payload) { + char msg[UEVENT_MSG_LEN + 2]; + char *cp; + int n; + + n = uevent_kernel_multicast_recv(payload->uevent_fd, msg, UEVENT_MSG_LEN); + if (n <= 0) + return; + if (n >= UEVENT_MSG_LEN) /* overflow -- discard */ + return; + + msg[n] = '\0'; + msg[n + 1] = '\0'; + cp = msg; + + while (*cp) { + if (std::regex_match(cp, std::regex("(add)(.*)(-partner)"))) { + ALOGI("partner added"); + pthread_mutex_lock(&payload->usb->mPartnerLock); + payload->usb->mPartnerUp = true; + pthread_cond_signal(&payload->usb->mPartnerCV); + pthread_mutex_unlock(&payload->usb->mPartnerLock); + } else if (!strncmp(cp, "DEVTYPE=typec_", strlen("DEVTYPE=typec_")) || + !strncmp(cp, "DRIVER=max77759tcpc", + strlen("DRIVER=max77759tcpc"))) { + std::vector currentPortStatus; + queryVersionHelper(payload->usb, ¤tPortStatus); + + // Role switch is not in progress and port is in disconnected state + if (!pthread_mutex_trylock(&payload->usb->mRoleSwitchLock)) { + for (unsigned long i = 0; i < currentPortStatus.size(); i++) { + DIR *dp = + opendir(string("/sys/class/typec/" + + string(currentPortStatus[i].portName.c_str()) + + "-partner").c_str()); + if (dp == NULL) { + switchToDrp(currentPortStatus[i].portName); + } else { + closedir(dp); + } + } + pthread_mutex_unlock(&payload->usb->mRoleSwitchLock); + } + break; + } else if (!strncmp(cp, kOverheatStatsDev, strlen(kOverheatStatsDev))) { + ALOGV("Overheat Cooling device suez update"); + report_overheat_event(payload->usb); + } + /* advance to after the next \0 */ + while (*cp++) { + } + } +} + +void *work(void *param) { + int epoll_fd, uevent_fd; + struct epoll_event ev; + int nevents = 0; + struct data payload; + + ALOGE("creating thread"); + + uevent_fd = uevent_open_socket(64 * 1024, true); + + if (uevent_fd < 0) { + ALOGE("uevent_init: uevent_open_socket failed\n"); + return NULL; + } + + payload.uevent_fd = uevent_fd; + payload.usb = (::aidl::android::hardware::usb::Usb *)param; + + fcntl(uevent_fd, F_SETFL, O_NONBLOCK); + + ev.events = EPOLLIN; + ev.data.ptr = (void *)uevent_event; + + epoll_fd = epoll_create(64); + if (epoll_fd == -1) { + ALOGE("epoll_create failed; errno=%d", errno); + goto error; + } + + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1) { + ALOGE("epoll_ctl failed; errno=%d", errno); + goto error; + } + + while (!destroyThread) { + struct epoll_event events[64]; + + nevents = epoll_wait(epoll_fd, events, 64, -1); + if (nevents == -1) { + if (errno == EINTR) + continue; + ALOGE("usb epoll_wait failed; errno=%d", errno); + break; + } + + for (int n = 0; n < nevents; ++n) { + if (events[n].data.ptr) + (*(void (*)(int, struct data *payload))events[n].data.ptr)(events[n].events, + &payload); + } + } + + ALOGI("exiting worker thread"); +error: + close(uevent_fd); + + if (epoll_fd >= 0) + close(epoll_fd); + + return NULL; +} + +void sighandler(int sig) { + if (sig == SIGUSR1) { + destroyThread = true; + ALOGI("destroy set"); + return; + } + signal(SIGUSR1, sighandler); +} + +ScopedAStatus Usb::setCallback(const shared_ptr& in_callback) { + pthread_mutex_lock(&mLock); + if ((mCallback == NULL && in_callback == NULL) || + (mCallback != NULL && in_callback != NULL)) { + mCallback = in_callback; + pthread_mutex_unlock(&mLock); + return ScopedAStatus::ok(); + } + + mCallback = in_callback; + ALOGI("registering callback"); + + if (mCallback == NULL) { + if (!pthread_kill(mPoll, SIGUSR1)) { + pthread_join(mPoll, NULL); + ALOGI("pthread destroyed"); + } + pthread_mutex_unlock(&mLock); + return ScopedAStatus::ok(); + } + + destroyThread = false; + signal(SIGUSR1, sighandler); + + /* + * Create a background thread if the old callback value is NULL + * and being updated with a new value. + */ + if (pthread_create(&mPoll, NULL, work, this)) { + ALOGE("pthread creation failed %d", errno); + mCallback = NULL; + } + + pthread_mutex_unlock(&mLock); + return ScopedAStatus::ok(); +} + +} // namespace usb +} // namespace hardware +} // namespace android +} // aidl diff --git a/usb/Usb.h b/usb/usb/Usb.h similarity index 54% rename from usb/Usb.h rename to usb/usb/Usb.h index 23ed0111..51f9d439 100644 --- a/usb/Usb.h +++ b/usb/usb/Usb.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2021 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. @@ -17,10 +17,8 @@ #pragma once #include -#include -#include -#include -#include +#include +#include #include #include @@ -31,46 +29,23 @@ // structures created and uvent fired. #define PORT_TYPE_TIMEOUT 8 +namespace aidl { namespace android { namespace hardware { namespace usb { -namespace V1_3 { -namespace implementation { -using ::android::base::WriteStringToFile; +using ::aidl::android::hardware::usb::IUsbCallback; +using ::aidl::android::hardware::usb::PortRole; using ::android::base::ReadFileToString; -using ::android::hardware::hidl_array; -using ::android::hardware::hidl_memory; -using ::android::hardware::hidl_string; -using ::android::hardware::hidl_vec; -using ::android::hardware::Return; -using ::android::hardware::Void; +using ::android::base::WriteStringToFile; using ::android::hardware::google::pixel::usb::UsbOverheatEvent; using ::android::hardware::google::pixel::usb::ZoneInfo; using ::android::hardware::thermal::V2_0::TemperatureType; using ::android::hardware::thermal::V2_0::ThrottlingSeverity; -using ::android::hardware::usb::V1_0::PortRole; -using ::android::hardware::usb::V1_0::PortRoleType; -using ::android::hardware::usb::V1_0::PortDataRole; -using ::android::hardware::usb::V1_0::PortPowerRole; -using ::android::hardware::usb::V1_0::PortRole; -using ::android::hardware::usb::V1_0::PortRoleType; -using ::android::hardware::usb::V1_0::Status; -using ::android::hardware::usb::V1_3::IUsb; -using ::android::hardware::usb::V1_2::IUsbCallback; -using ::android::hardware::usb::V1_2::PortStatus; -using ::android::hardware::usb::V1_1::PortMode_1_1; -using ::android::hardware::usb::V1_1::PortStatus_1_1; -using ::android::hidl::base::V1_0::DebugInfo; -using ::android::hidl::base::V1_0::IBase; using ::android::sp; - -enum class HALVersion{ - V1_0, - V1_1, - V1_2, - V1_3 -}; +using ::ndk::ScopedAStatus; +using ::std::shared_ptr; +using ::std::string; constexpr char kGadgetName[] = "11110000.dwc3"; #define NEW_UDC_PATH "/sys/devices/platform/11110000.usb/" @@ -79,17 +54,19 @@ constexpr char kGadgetName[] = "11110000.dwc3"; #define VBUS_PATH NEW_UDC_PATH "dwc3_exynos_otg_b_sess" #define USB_DATA_PATH NEW_UDC_PATH "usb_data_enabled" -struct Usb : public IUsb { +struct Usb : public BnUsb { Usb(); - Return switchRole(const hidl_string &portName, const PortRole &role) override; - Return setCallback(const sp& callback) override; - Return queryPortStatus() override; - Return enableContaminantPresenceDetection(const hidl_string &portName, bool enable); - Return enableContaminantPresenceProtection(const hidl_string &portName, bool enable); - Return enableUsbDataSignal(bool enable) override; + ScopedAStatus enableContaminantPresenceDetection(const std::string& in_portName, + bool in_enable, int64_t in_transactionId) override; + ScopedAStatus queryPortStatus(int64_t in_transactionId) override; + ScopedAStatus setCallback(const shared_ptr& in_callback) override; + ScopedAStatus switchRole(const string& in_portName, const PortRole& in_role, + int64_t in_transactionId) override; + ScopedAStatus enableUsbData(const string& in_portName, bool in_enable, + int64_t in_transactionId) override; - sp mCallback_1_0; + std::shared_ptr<::aidl::android::hardware::usb::IUsbCallback> mCallback; // Protects mCallback variable pthread_mutex_t mLock; // Protects roleSwitch operation @@ -105,13 +82,14 @@ struct Usb : public IUsb { UsbOverheatEvent mOverheat; // Temperature when connected float mPluggedTemperatureCelsius; + // Usb Data status + bool mUsbDataEnabled; private: pthread_t mPoll; }; -} // namespace implementation -} // namespace V1_3 -} // namespace usb -} // namespace hardware -} // namespace android +} // namespace usb +} // namespace hardware +} // namespace android +} // aidl diff --git a/usb/usb/android.hardware.usb-service.rc b/usb/usb/android.hardware.usb-service.rc new file mode 100644 index 00000000..c842877b --- /dev/null +++ b/usb/usb/android.hardware.usb-service.rc @@ -0,0 +1,21 @@ +service vendor.usb /vendor/bin/hw/android.hardware.usb-service.gs101 + class hal + user system + group system shell wakelock + capabilities WAKE_ALARM BLOCK_SUSPEND + +on post-fs + chown root system /sys/class/typec/port0/power_role + chown root system /sys/class/typec/port0/data_role + chown root system /sys/class/typec/port0/port_type + chown root system /sys/devices/platform/10d50000.hsi2c/i2c-5/i2c-max77759tcpc/contaminant_detection + chown root system /sys/devices/platform/10d50000.hsi2c/i2c-6/i2c-max77759tcpc/contaminant_detection + 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 + chmod 664 /sys/class/typec/port0/power_role + chmod 664 /sys/class/typec/port0/data_role + chmod 664 /sys/class/typec/port0/port_type + chmod 664 /sys/devices/platform/11110000.usb/dwc3_exynos_otg_b_sess + chmod 664 /sys/devices/platform/11110000.usb/dwc3_exynos_otg_id + chmod 664 /sys/devices/platform/11110000.usb/usb_data_enabled diff --git a/usb/android.hardware.usb@1.3-service.gs101.xml b/usb/usb/android.hardware.usb-service.xml similarity index 69% rename from usb/android.hardware.usb@1.3-service.gs101.xml rename to usb/usb/android.hardware.usb-service.xml index cd542687..60881948 100644 --- a/usb/android.hardware.usb@1.3-service.gs101.xml +++ b/usb/usb/android.hardware.usb-service.xml @@ -1,12 +1,10 @@ - + android.hardware.usb - hwbinder - 1.3 + 1 IUsb default - diff --git a/usb/usb/service.cpp b/usb/usb/service.cpp new file mode 100644 index 00000000..2c0a5963 --- /dev/null +++ b/usb/usb/service.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 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. + */ + +#include +#include +#include +#include + +#include "Usb.h" + +using ::aidl::android::hardware::usb::Usb; + +int main() { + ABinderProcess_setThreadPoolMaxThreadCount(0); + std::shared_ptr usb = ndk::SharedRefBase::make(); + + const std::string instance = std::string() + Usb::descriptor + "/default"; + binder_status_t status = AServiceManager_addService(usb->asBinder().get(), instance.c_str()); + CHECK(status == STATUS_OK); + + ALOGV("AIDL USB HAL about to start"); + ABinderProcess_joinThreadPool(); + return -1; // Should never be reached +}