diff options
-rw-r--r-- | pixelstats/StatsHelper.cpp | 25 | ||||
-rw-r--r-- | pixelstats/SysfsCollector.cpp | 109 | ||||
-rw-r--r-- | pixelstats/include/pixelstats/StatsHelper.h | 3 | ||||
-rw-r--r-- | pixelstats/include/pixelstats/SysfsCollector.h | 11 | ||||
-rw-r--r-- | pixelstats/pixelatoms.proto | 20 | ||||
-rw-r--r-- | powerstats/dataproviders/PowerStatsEnergyConsumer.cpp | 67 | ||||
-rw-r--r-- | rebalance_interrupts/rebalance_interrupts.cpp | 31 | ||||
-rw-r--r-- | thermal/Thermal.cpp | 23 | ||||
-rw-r--r-- | thermal/thermal-helper.cpp | 7 | ||||
-rw-r--r-- | thermal/thermal-helper.h | 2 | ||||
-rw-r--r-- | usb/UsbGadgetUtils.cpp | 2 | ||||
-rw-r--r-- | usb/UsbOverheatEvent.cpp | 44 | ||||
-rw-r--r-- | usb/include/pixelusb/UsbOverheatEvent.h | 8 | ||||
-rw-r--r-- | vibrator/cs40l25/Hardware.h | 3 | ||||
-rw-r--r-- | vibrator/cs40l25/Vibrator.cpp | 51 | ||||
-rw-r--r-- | vibrator/cs40l25/Vibrator.h | 4 | ||||
-rw-r--r-- | vibrator/cs40l25/android.hardware.vibrator-service.cs40l25.rc | 2 | ||||
-rw-r--r-- | vibrator/cs40l25/tests/mocks.h | 1 | ||||
-rw-r--r-- | vibrator/cs40l25/tests/test-hwapi.cpp | 3 |
19 files changed, 337 insertions, 79 deletions
diff --git a/pixelstats/StatsHelper.cpp b/pixelstats/StatsHelper.cpp index e41ef8ad..8fdb988e 100644 --- a/pixelstats/StatsHelper.cpp +++ b/pixelstats/StatsHelper.cpp @@ -67,6 +67,31 @@ void reportSpeakerImpedance(const std::shared_ptr<IStats> &stats_client, ALOGE("Unable to report VendorSpeakerImpedance to Stats service"); } +void reportSpeakerHealthStat(const std::shared_ptr<IStats> &stats_client, + const PixelAtoms::VendorSpeakerStatsReported &speakerHealthStat) { + // Load values array + std::vector<VendorAtomValue> values(5); + VendorAtomValue tmp; + tmp.set<VendorAtomValue::intValue>(speakerHealthStat.speaker_location()); + values[0] = tmp; + tmp.set<VendorAtomValue::intValue>(speakerHealthStat.impedance()); + values[1] = tmp; + tmp.set<VendorAtomValue::intValue>(speakerHealthStat.max_temperature()); + values[2] = tmp; + tmp.set<VendorAtomValue::intValue>(speakerHealthStat.excursion()); + values[3] = tmp; + tmp.set<VendorAtomValue::intValue>(speakerHealthStat.heartbeat()); + values[4] = tmp; + + // Send vendor atom to IStats HAL + VendorAtom event = {.reverseDomainName = PixelAtoms::ReverseDomainNames().pixel(), + .atomId = PixelAtoms::Atom::kVendorSpeakerStatsReported, + .values = std::move(values)}; + const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event); + if (!ret.isOk()) + ALOGE("Unable to report VendorSpeakerStatsReported to Stats service"); +} + void reportSlowIo(const std::shared_ptr<IStats> &stats_client, const PixelAtoms::VendorSlowIo &slowIo) { // Load values array diff --git a/pixelstats/SysfsCollector.cpp b/pixelstats/SysfsCollector.cpp index 8b002d02..f2fdeea8 100644 --- a/pixelstats/SysfsCollector.cpp +++ b/pixelstats/SysfsCollector.cpp @@ -45,14 +45,15 @@ using android::base::WriteStringToFile; using android::hardware::google::pixel::PixelAtoms::BatteryCapacity; using android::hardware::google::pixel::PixelAtoms::BootStatsInfo; using android::hardware::google::pixel::PixelAtoms::F2fsCompressionInfo; -using android::hardware::google::pixel::PixelAtoms::F2fsStatsInfo; using android::hardware::google::pixel::PixelAtoms::F2fsGcSegmentInfo; +using android::hardware::google::pixel::PixelAtoms::F2fsStatsInfo; using android::hardware::google::pixel::PixelAtoms::StorageUfsHealth; using android::hardware::google::pixel::PixelAtoms::StorageUfsResetCount; using android::hardware::google::pixel::PixelAtoms::VendorChargeCycles; using android::hardware::google::pixel::PixelAtoms::VendorHardwareFailed; using android::hardware::google::pixel::PixelAtoms::VendorSlowIo; using android::hardware::google::pixel::PixelAtoms::VendorSpeakerImpedance; +using android::hardware::google::pixel::PixelAtoms::VendorSpeakerStatsReported; using android::hardware::google::pixel::PixelAtoms::VendorSpeechDspStat; using android::hardware::google::pixel::PixelAtoms::ZramBdStat; using android::hardware::google::pixel::PixelAtoms::ZramMmStat; @@ -72,12 +73,15 @@ SysfsCollector::SysfsCollector(const struct SysfsPaths &sysfs_paths) kUFSLifetimeA(sysfs_paths.UFSLifetimeA), kUFSLifetimeB(sysfs_paths.UFSLifetimeB), kUFSLifetimeC(sysfs_paths.UFSLifetimeC), - kUFSHostResetPath(sysfs_paths.UFSHostResetPath), kF2fsStatsPath(sysfs_paths.F2fsStatsPath), kZramMmStatPath("/sys/block/zram0/mm_stat"), kZramBdStatPath("/sys/block/zram0/bd_stat"), kEEPROMPath(sysfs_paths.EEPROMPath), - kPowerMitigationStatsPath(sysfs_paths.MitigationPath) {} + kPowerMitigationStatsPath(sysfs_paths.MitigationPath), + kSpeakerTemperaturePath(sysfs_paths.SpeakerTemperaturePath), + kSpeakerExcursionPath(sysfs_paths.SpeakerExcursionPath), + kSpeakerHeartbeatPath(sysfs_paths.SpeakerHeartBeatPath), + kUFSErrStatsPath(sysfs_paths.UFSErrStatsPath) {} bool SysfsCollector::ReadFileToInt(const std::string &path, int *val) { return ReadFileToInt(path.c_str(), val); @@ -271,6 +275,91 @@ void SysfsCollector::logSpeakerImpedance(const std::shared_ptr<IStats> &stats_cl } /** + * Report the last-detected impedance, temperature and heartbeats of left & right speakers. + */ +void SysfsCollector::logSpeakerHealthStats(const std::shared_ptr<IStats> &stats_client) { + std::string file_contents; + + if (kImpedancePath == nullptr || strlen(kImpedancePath) == 0) { + ALOGD("Audio impedance path not specified"); + return; + } + + if (kSpeakerTemperaturePath == nullptr || strlen(kSpeakerTemperaturePath) == 0) { + ALOGD("Audio speaker temperature path not specified"); + return; + } + + if (kSpeakerHeartbeatPath == nullptr || strlen(kSpeakerHeartbeatPath) == 0) { + ALOGD("Audio speaker heartbeat path not specified"); + return; + } + + if (kSpeakerExcursionPath == nullptr || strlen(kSpeakerExcursionPath) == 0) { + ALOGD("Audio speaker excursion path not specified"); + return; + } + + float left_impedance_ohm, right_impedance_ohm; + + if (!ReadFileToString(kImpedancePath, &file_contents)) { + ALOGE("Unable to read speaker impedance path %s", kImpedancePath); + return; + } + if (sscanf(file_contents.c_str(), "%g,%g", &left_impedance_ohm, &right_impedance_ohm) != 2) { + ALOGE("Unable to parse speaker impedance %s", file_contents.c_str()); + return; + } + + float left_temperature_C, right_temperature_C; + if (!ReadFileToString(kSpeakerTemperaturePath, &file_contents)) { + ALOGE("Unable to read speaker temperature path %s", kSpeakerTemperaturePath); + return; + } + if (sscanf(file_contents.c_str(), "%g,%g", &left_temperature_C, &right_temperature_C) != 2) { + ALOGE("Unable to parse speaker temperature %s", file_contents.c_str()); + return; + } + + float left_excursion_mm, right_excursion_mm; + if (!ReadFileToString(kSpeakerExcursionPath, &file_contents)) { + ALOGE("Unable to read speaker excursion path %s", kSpeakerExcursionPath); + return; + } + if (sscanf(file_contents.c_str(), "%g,%g", &left_excursion_mm, &right_excursion_mm) != 2) { + ALOGE("Unable to parse speaker excursion %s", file_contents.c_str()); + return; + } + + float left_heartbeat, right_heartbeat; + if (!ReadFileToString(kSpeakerHeartbeatPath, &file_contents)) { + ALOGE("Unable to read speaker heartbeat path %s", kSpeakerHeartbeatPath); + return; + } + if (sscanf(file_contents.c_str(), "%g,%g", &left_heartbeat, &right_heartbeat) != 2) { + ALOGE("Unable to parse speaker heartbeat %s", file_contents.c_str()); + return; + } + + VendorSpeakerStatsReported left_obj; + left_obj.set_speaker_location(0); + left_obj.set_impedance(static_cast<int32_t>(left_impedance_ohm * 1000)); + left_obj.set_max_temperature(static_cast<int32_t>(left_temperature_C * 1000)); + left_obj.set_excursion(static_cast<int32_t>(left_excursion_mm * 1000)); + left_obj.set_heartbeat(static_cast<int32_t>(left_heartbeat)); + + VendorSpeakerStatsReported right_obj; + right_obj.set_speaker_location(1); + right_obj.set_impedance(static_cast<int32_t>(right_impedance_ohm * 1000)); + right_obj.set_max_temperature(static_cast<int32_t>(right_temperature_C * 1000)); + right_obj.set_excursion(static_cast<int32_t>(right_excursion_mm * 1000)); + right_obj.set_heartbeat(static_cast<int32_t>(right_heartbeat)); + + reportSpeakerHealthStat(stats_client, left_obj); + reportSpeakerHealthStat(stats_client, right_obj); +} + +/** * Report the Speech DSP state. */ void SysfsCollector::logSpeechDspStat(const std::shared_ptr<IStats> &stats_client) { @@ -378,16 +467,19 @@ void SysfsCollector::logUFSLifetime(const std::shared_ptr<IStats> &stats_client) } void SysfsCollector::logUFSErrorStats(const std::shared_ptr<IStats> &stats_client) { - int host_reset_count; + int value, host_reset_count = 0; - if (kUFSHostResetPath == nullptr || strlen(kUFSHostResetPath) == 0) { + if (kUFSErrStatsPath.empty() || strlen(kUFSErrStatsPath.front().c_str()) == 0) { ALOGV("UFS host reset count specified"); return; } - if (!ReadFileToInt(kUFSHostResetPath, &host_reset_count)) { - ALOGE("Unable to read host reset count"); - return; + for (int i = 0; i < kUFSErrStatsPath.size(); i++) { + if (!ReadFileToInt(kUFSErrStatsPath[i], &value)) { + ALOGE("Unable to read host reset count"); + return; + } + host_reset_count += value; } // Load values array @@ -803,6 +895,7 @@ void SysfsCollector::logPerDay() { logUFSLifetime(stats_client); logUFSErrorStats(stats_client); logZramStats(stats_client); + logSpeakerHealthStats(stats_client); mm_metrics_reporter_.logCmaStatus(stats_client); mm_metrics_reporter_.logPixelMmMetricsPerDay(stats_client); } diff --git a/pixelstats/include/pixelstats/StatsHelper.h b/pixelstats/include/pixelstats/StatsHelper.h index b8a23902..7c79b6bf 100644 --- a/pixelstats/include/pixelstats/StatsHelper.h +++ b/pixelstats/include/pixelstats/StatsHelper.h @@ -50,6 +50,9 @@ void reportPhysicalDropDetected(const std::shared_ptr<IStats> &stats_client, void reportUsbPortOverheat(const std::shared_ptr<IStats> &stats_client, const PixelAtoms::VendorUsbPortOverheat &overheat_info); +void reportSpeakerHealthStat(const std::shared_ptr<IStats> &stats_client, + const PixelAtoms::VendorSpeakerStatsReported &speakerHealthStat); + } // namespace pixel } // namespace google } // namespace hardware diff --git a/pixelstats/include/pixelstats/SysfsCollector.h b/pixelstats/include/pixelstats/SysfsCollector.h index 8045d4aa..097a4c76 100644 --- a/pixelstats/include/pixelstats/SysfsCollector.h +++ b/pixelstats/include/pixelstats/SysfsCollector.h @@ -48,13 +48,16 @@ class SysfsCollector { const char *const UFSLifetimeA; const char *const UFSLifetimeB; const char *const UFSLifetimeC; - const char *const UFSHostResetPath; const char *const F2fsStatsPath; const char *const UserdataBlockProp; const char *const ZramMmStatPath; const char *const ZramBdStatPath; const char *const EEPROMPath; const char *const MitigationPath; + const char *const SpeakerTemperaturePath; + const char *const SpeakerExcursionPath; + const char *const SpeakerHeartBeatPath; + const std::vector<std::string> UFSErrStatsPath; }; SysfsCollector(const struct SysfsPaths &paths); @@ -81,6 +84,7 @@ class SysfsCollector { void logZramStats(const std::shared_ptr<IStats> &stats_client); void logBootStats(const std::shared_ptr<IStats> &stats_client); void logBatteryEEPROM(const std::shared_ptr<IStats> &stats_client); + void logSpeakerHealthStats(const std::shared_ptr<IStats> &stats_client); void reportSlowIoFromFile(const std::shared_ptr<IStats> &stats_client, const char *path, const VendorSlowIo::IoOperation &operation_s); @@ -102,12 +106,15 @@ class SysfsCollector { const char *const kUFSLifetimeA; const char *const kUFSLifetimeB; const char *const kUFSLifetimeC; - const char *const kUFSHostResetPath; const char *const kF2fsStatsPath; const char *const kZramMmStatPath; const char *const kZramBdStatPath; const char *const kEEPROMPath; const char *const kPowerMitigationStatsPath; + const char *const kSpeakerTemperaturePath; + const char *const kSpeakerExcursionPath; + const char *const kSpeakerHeartbeatPath; + const std::vector<std::string> kUFSErrStatsPath; BatteryEEPROMReporter battery_EEPROM_reporter_; MmMetricsReporter mm_metrics_reporter_; diff --git a/pixelstats/pixelatoms.proto b/pixelstats/pixelatoms.proto index 1e6b0ebb..104f3799 100644 --- a/pixelstats/pixelatoms.proto +++ b/pixelstats/pixelatoms.proto @@ -68,6 +68,7 @@ message Atom { CitadelVersion citadel_version = 100018; // moved from vendor proprietary CitadelEvent citadel_event = 100019; // moved from vendor proprietary + VendorSpeakerStatsReported vendor_speaker_stats_reported = 105030; } // AOSP atom ID range ends at 109999 } @@ -453,6 +454,25 @@ message CitadelVersion { optional int32 impedance = 3; } +/** + * Logs the reported vendor speaker health stats. + * Logged from: hardware/google/pixel/pixelstats/SysfsCollector.cpp + */ +message VendorSpeakerStatsReported { + /* Vendor reverse domain name (expecting "com.google.pixel") */ + optional string reverse_domain_name = 1; + /* The location of speaker; 0 = left , 1 = right */ + optional int32 speaker_location = 2; + /* The speaker's impedance value (milliOhm) */ + optional int32 impedance = 3; + /* The speaker's maximum temperature (milliDegree C) */ + optional int32 max_temperature = 4; + /* The speaker's execursion length (micrometer) */ + optional int32 excursion = 5; + /* The speaker's heart beat count */ + optional int32 heartbeat = 6; +} + /* A message containing how many times of ufs host reset */ message StorageUfsResetCount { optional string reverse_domain_name = 1; diff --git a/powerstats/dataproviders/PowerStatsEnergyConsumer.cpp b/powerstats/dataproviders/PowerStatsEnergyConsumer.cpp index c2425960..0b641659 100644 --- a/powerstats/dataproviders/PowerStatsEnergyConsumer.cpp +++ b/powerstats/dataproviders/PowerStatsEnergyConsumer.cpp @@ -119,8 +119,8 @@ bool PowerStatsEnergyConsumer::addAttribution(std::unordered_map<int32_t, std::s if (paths.count(UID_TIME_IN_STATE)) { mEnergyAttribution = PowerStatsEnergyAttribution(); AttributionStats attrStats = mEnergyAttribution.getAttributionStats(paths); - if (attrStats.uidTimeInStats.empty() || attrStats.uidTimeInStateNames.empty()) { - LOG(ERROR) << "Missing uid_time_in_state"; + if (attrStats.uidTimeInStateNames.empty()) { + LOG(ERROR) << "Failed to read uid_time_in_state"; return false; } @@ -166,44 +166,43 @@ std::optional<EnergyConsumerResult> PowerStatsEnergyConsumer::getEnergyConsumed( if (mWithAttribution) { AttributionStats attrStats = mEnergyAttribution.getAttributionStats(mAttrInfoPath); if (attrStats.uidTimeInStats.empty() || attrStats.uidTimeInStateNames.empty()) { - LOG(ERROR) << "Missing uid_time_in_state"; - return {}; - } - - int64_t totalRelativeEnergyUWs = 0; - for (const auto &uidTimeInStat : attrStats.uidTimeInStats) { - int64_t uidEnergyUWs = 0; - for (int id = 0; id < uidTimeInStat.second.size(); id++) { - if (mCoefficients.count(id)) { - int64_t d_time_in_state = uidTimeInStat.second.at(id); - if (mUidTimeInStateSS.count(uidTimeInStat.first)) { - d_time_in_state -= mUidTimeInStateSS.at(uidTimeInStat.first).at(id); + LOG(ERROR) << "Failed to read uid_time_in_state for attribution, return default EnergyConsumer"; + } else { + int64_t totalRelativeEnergyUWs = 0; + for (const auto &uidTimeInStat : attrStats.uidTimeInStats) { + int64_t uidEnergyUWs = 0; + for (int id = 0; id < uidTimeInStat.second.size(); id++) { + if (mCoefficients.count(id)) { + int64_t d_time_in_state = uidTimeInStat.second.at(id); + if (mUidTimeInStateSS.count(uidTimeInStat.first)) { + d_time_in_state -= mUidTimeInStateSS.at(uidTimeInStat.first).at(id); + } + uidEnergyUWs += mCoefficients.at(id) * d_time_in_state; } - uidEnergyUWs += mCoefficients.at(id) * d_time_in_state; } + totalRelativeEnergyUWs += uidEnergyUWs; + + EnergyConsumerAttribution attr = { + .uid = uidTimeInStat.first, + .energyUWs = uidEnergyUWs, + }; + attribution.emplace_back(attr); } - totalRelativeEnergyUWs += uidEnergyUWs; - EnergyConsumerAttribution attr = { - .uid = uidTimeInStat.first, - .energyUWs = uidEnergyUWs, - }; - attribution.emplace_back(attr); - } + int64_t d_totalEnergyUWs = totalEnergyUWs - mTotalEnergySS; + float powerScale = 0; + if (totalRelativeEnergyUWs != 0) { + powerScale = static_cast<float>(d_totalEnergyUWs) / totalRelativeEnergyUWs; + } + for (auto &attr : attribution) { + attr.energyUWs = (int64_t)(attr.energyUWs * powerScale) + + (mUidEnergySS.count(attr.uid) ? mUidEnergySS.at(attr.uid) : 0); + mUidEnergySS[attr.uid] = attr.energyUWs; + } - int64_t d_totalEnergyUWs = totalEnergyUWs - mTotalEnergySS; - float powerScale = 0; - if (totalRelativeEnergyUWs != 0) { - powerScale = static_cast<float>(d_totalEnergyUWs) / totalRelativeEnergyUWs; + mUidTimeInStateSS = attrStats.uidTimeInStats; + mTotalEnergySS = totalEnergyUWs; } - for (auto &attr : attribution) { - attr.energyUWs = (int64_t)(attr.energyUWs * powerScale) + - (mUidEnergySS.count(attr.uid) ? mUidEnergySS.at(attr.uid) : 0); - mUidEnergySS[attr.uid] = attr.energyUWs; - } - - mUidTimeInStateSS = attrStats.uidTimeInStats; - mTotalEnergySS = totalEnergyUWs; } else { std::vector<StateResidencyResult> results; if (mPowerStats->getStateResidency({mPowerEntityId}, &results).isOk()) { diff --git a/rebalance_interrupts/rebalance_interrupts.cpp b/rebalance_interrupts/rebalance_interrupts.cpp index b0d2f69e..77a0bfb0 100644 --- a/rebalance_interrupts/rebalance_interrupts.cpp +++ b/rebalance_interrupts/rebalance_interrupts.cpp @@ -224,6 +224,33 @@ bool RebalanceIrqs(const list<pair<string, list<string>>>& action_to_irqs) { return true; } +void ChownIrqAffinity() { + std::unique_ptr<DIR, decltype(&closedir)> irq_dir(opendir(PROC_IRQDIR), closedir); + if (!irq_dir) { + PLOG(ERROR) << "opening dir " PROC_IRQDIR; + return; + } + + struct dirent *entry; + while ((entry = readdir(irq_dir.get()))) { + // If the directory entry isn't a parsable number, skip it. + // . and .. get skipped here. + unsigned throwaway; + if (!ParseUint(entry->d_name, &throwaway)) + continue; + + string affinity_path(PROC_IRQDIR "/"); + affinity_path += entry->d_name; + affinity_path += "/smp_affinity"; + chown(affinity_path.c_str(), 1000, 1000); + + string affinity_list_path(PROC_IRQDIR "/"); + affinity_list_path += entry->d_name; + affinity_list_path += "/smp_affinity_list"; + chown(affinity_list_path.c_str(), 1000, 1000); + } +} + int main(int /* argc */, char* /* argv */[]) { map<string, list<string>> irq_mapping; list<pair<string, list<string>>> action_to_irqs; @@ -238,6 +265,10 @@ int main(int /* argc */, char* /* argv */[]) { return 1; } + // Change ownership of smp_affinity and smp_affinity_list handles + // from root to system. + ChownIrqAffinity(); + // Some IRQs are already assigned to a subset of cores, usually for // good reason (like some drivers have an IRQ per core, for per-core // queues.) Find the set of IRQs that haven't been mapped to specific diff --git a/thermal/Thermal.cpp b/thermal/Thermal.cpp index 80aa53c4..c448b709 100644 --- a/thermal/Thermal.cpp +++ b/thermal/Thermal.cpp @@ -121,7 +121,7 @@ Return<void> Thermal::getCurrentTemperatures(bool filterType, TemperatureType_2_ return setInitFailureAndCallback(_hidl_cb, temperatures); } - if (!thermal_helper_.fillCurrentTemperatures(filterType, type, &temperatures)) { + if (!thermal_helper_.fillCurrentTemperatures(filterType, false, type, &temperatures)) { return setFailureAndCallback(_hidl_cb, temperatures, "Failed to read thermal sensors."); } @@ -171,6 +171,8 @@ Return<void> Thermal::registerThermalChangedCallback(const sp<IThermalChangedCal bool filterType, TemperatureType_2_0 type, registerThermalChangedCallback_cb _hidl_cb) { ThermalStatus status; + hidl_vec<Temperature_2_0> temperatures; + if (callback == nullptr) { status.code = ThermalStatusCode::FAILURE; status.debugMessage = "Invalid nullptr callback"; @@ -193,6 +195,21 @@ Return<void> Thermal::registerThermalChangedCallback(const sp<IThermalChangedCal << " Type: " << android::hardware::thermal::V2_0::toString(type); } _hidl_cb(status); + + // Send notification right away after thermal callback registration + if (thermal_helper_.fillCurrentTemperatures(filterType, true, type, &temperatures)) { + for (const auto &t : temperatures) { + if (!filterType || t.type == type) { + LOG(INFO) << "Sending notification: " + << " Type: " << android::hardware::thermal::V2_0::toString(t.type) + << " Name: " << t.name << " CurrentValue: " << t.value + << " ThrottlingStatus: " + << android::hardware::thermal::V2_0::toString(t.throttlingStatus); + callback->notifyThrottling(t); + } + } + } + return Void(); } @@ -565,8 +582,8 @@ Return<void> Thermal::debug(const hidl_handle &handle, const hidl_vec<hidl_strin { dump_buf << "getCurrentTemperatures:" << std::endl; hidl_vec<Temperature_2_0> temperatures; - if (!thermal_helper_.fillCurrentTemperatures(false, TemperatureType_2_0::SKIN, - &temperatures)) { + if (!thermal_helper_.fillCurrentTemperatures( + false, false, TemperatureType_2_0::SKIN, &temperatures)) { dump_buf << "Failed to getCurrentTemperatures." << std::endl; } diff --git a/thermal/thermal-helper.cpp b/thermal/thermal-helper.cpp index cbd63939..6eb0d508 100644 --- a/thermal/thermal-helper.cpp +++ b/thermal/thermal-helper.cpp @@ -1016,7 +1016,8 @@ bool ThermalHelper::fillTemperatures(hidl_vec<Temperature_1_0> *temperatures) co return current_index > 0; } -bool ThermalHelper::fillCurrentTemperatures(bool filterType, TemperatureType_2_0 type, +bool ThermalHelper::fillCurrentTemperatures(bool filterType, bool filterCallback, + TemperatureType_2_0 type, hidl_vec<Temperature_2_0> *temperatures) const { std::vector<Temperature_2_0> ret; for (const auto &name_info_pair : sensor_info_map_) { @@ -1024,13 +1025,15 @@ bool ThermalHelper::fillCurrentTemperatures(bool filterType, TemperatureType_2_0 if (filterType && name_info_pair.second.type != type) { continue; } + if (filterCallback && !name_info_pair.second.send_cb) { + continue; + } if (readTemperature(name_info_pair.first, &temp, nullptr, name_info_pair.second.virtual_sensor_info != nullptr)) { ret.emplace_back(std::move(temp)); } else { LOG(ERROR) << __func__ << ": error reading temperature for sensor: " << name_info_pair.first; - return false; } } *temperatures = ret; diff --git a/thermal/thermal-helper.h b/thermal/thermal-helper.h index 672d3522..20205979 100644 --- a/thermal/thermal-helper.h +++ b/thermal/thermal-helper.h @@ -112,7 +112,7 @@ class ThermalHelper { ~ThermalHelper() = default; bool fillTemperatures(hidl_vec<Temperature_1_0> *temperatures) const; - bool fillCurrentTemperatures(bool filterType, TemperatureType_2_0 type, + bool fillCurrentTemperatures(bool filterType, bool filterCallback, TemperatureType_2_0 type, hidl_vec<Temperature_2_0> *temperatures) const; bool fillTemperatureThresholds(bool filterType, TemperatureType_2_0 type, hidl_vec<TemperatureThreshold> *thresholds) const; diff --git a/usb/UsbGadgetUtils.cpp b/usb/UsbGadgetUtils.cpp index 4df6215c..7da4b784 100644 --- a/usb/UsbGadgetUtils.cpp +++ b/usb/UsbGadgetUtils.cpp @@ -100,7 +100,7 @@ std::string getVendorFunctions() { if (vendorFunctions != "") { ret = vendorFunctions; } else if (bootMode == "usbradio" || bootMode == "factory" || bootMode == "ffbm-00" || - bootMode == "ffbm-01") { + bootMode == "ffbm-01" || bootMode == "usbuwb") { if (persistVendorFunctions != "") ret = persistVendorFunctions; else diff --git a/usb/UsbOverheatEvent.cpp b/usb/UsbOverheatEvent.cpp index f00258f5..a80f8b22 100644 --- a/usb/UsbOverheatEvent.cpp +++ b/usb/UsbOverheatEvent.cpp @@ -54,8 +54,6 @@ UsbOverheatEvent::UsbOverheatEvent(const ZoneInfo &monitored_zone, : monitored_zone_(monitored_zone), queried_zones_(queried_zones), monitor_interval_sec_(monitor_interval_sec), - lock_(), - cv_(), monitor_() { int fd = timerfd_create(CLOCK_BOOTTIME_ALARM, 0); if (fd < 0) { @@ -129,17 +127,12 @@ void *UsbOverheatEvent::monitorThread(void *param) { UsbOverheatEvent *overheatEvent = (UsbOverheatEvent *)param; struct epoll_event events[kEpollEvents]; struct itimerspec delay = itimerspec(); - std::unique_lock<std::mutex> lk(overheatEvent->lock_); - - delay.it_value.tv_sec = overheatEvent->monitor_interval_sec_; while (true) { uint64_t fired; float temperature = 0; string status; - overheatEvent->cv_.wait(lk, [] { return monitorTemperature; }); - for (vector<ZoneInfo>::size_type i = 0; i < overheatEvent->queried_zones_.size(); i++) { if (overheatEvent->getCurrentTemperature(overheatEvent->queried_zones_[i].name_, &temperature)) { @@ -154,10 +147,11 @@ void *UsbOverheatEvent::monitorThread(void *param) { } ALOGW("%s", status.c_str()); + delay.it_value.tv_sec = monitorTemperature ? overheatEvent->monitor_interval_sec_ : 0; int ret = timerfd_settime(overheatEvent->timer_fd_, 0, &delay, NULL); if (ret < 0) { - ALOGE("timerfd_settime failed. err:%d", errno); - return NULL; + ALOGE("timerfd_settime failed. err:%d tv_sec:%ld", errno, delay.it_value.tv_sec); + continue; } wakeLockRelease(); @@ -172,6 +166,7 @@ void *UsbOverheatEvent::monitorThread(void *param) { ALOGV("event=%u on fd=%d\n", events[i].events, events[i].data.fd); if (events[i].data.fd == overheatEvent->timer_fd_) { + ALOGI("Wake up caused by timer fd"); int numRead = read(overheatEvent->timer_fd_, &fired, sizeof(fired)); if (numRead != sizeof(fired)) { ALOGV("numRead incorrect"); @@ -180,6 +175,7 @@ void *UsbOverheatEvent::monitorThread(void *param) { ALOGV("Fired not set to 1"); } } else { + ALOGI("Wake up caused by event fd"); read(overheatEvent->event_fd_, &fired, sizeof(fired)); } } @@ -204,25 +200,37 @@ bool UsbOverheatEvent::registerListener() { return false; } +void UsbOverheatEvent::wakeupMonitor() { + // <flag> value does not have any significance here + uint64_t flag = 100; + + unsigned long ret = TEMP_FAILURE_RETRY(write(event_fd_, &flag, sizeof(flag))); + if (ret < 0) { + ALOGE("Error writing eventfd errno=%d", errno); + } +} + bool UsbOverheatEvent::startRecording() { - lock_guard<mutex> lock(lock_); + ALOGI("Start recording. monitorTemperature:%d", monitorTemperature ? 1 : 0); + // Bail out if temperature was being monitored previously + if (monitorTemperature) + return true; + wakeLockAcquire(); monitorTemperature = true; - cv_.notify_all(); + wakeupMonitor(); return true; } bool UsbOverheatEvent::stopRecording() { - // <flag> value does not have any significance here - uint64_t flag = 100; - unsigned long ret; + ALOGI("Stop recording. monitorTemperature:%d", monitorTemperature ? 1 : 0); + // Bail out if temperature was not being monitored previously + if (!monitorTemperature) + return true; wakeLockRelease(); monitorTemperature = false; - ret = TEMP_FAILURE_RETRY(write(event_fd_, &flag, sizeof(flag))); - if (ret < 0) { - ALOGE("Error writing eventfd errno=%d", errno); - } + wakeupMonitor(); return true; } diff --git a/usb/include/pixelusb/UsbOverheatEvent.h b/usb/include/pixelusb/UsbOverheatEvent.h index ac8b6b0a..de8cc240 100644 --- a/usb/include/pixelusb/UsbOverheatEvent.h +++ b/usb/include/pixelusb/UsbOverheatEvent.h @@ -86,7 +86,7 @@ class UsbOverheatEvent : public IServiceNotification, public IThermalChangedCall private: // To wake up thread to record max temperature unique_fd timer_fd_; - // Pools on timer_fd_ + // Polls on timer_fd_ & event_fd. Thread waits here when port is cold. unique_fd epoll_fd_; // To wake up the thread when waiting on TimerFd unique_fd event_fd_; @@ -99,10 +99,6 @@ class UsbOverheatEvent : public IServiceNotification, public IThermalChangedCall vector<ZoneInfo> queried_zones_; // Sampling interval for monitoring the temperature int monitor_interval_sec_; - // protects the CV. - std::mutex lock_; - // Thread waits here when mRecordMaxTemp is false - std::condition_variable cv_; // Thread object that executes the ep monitoring logic unique_ptr<thread> monitor_; // Maximum overheat temperature recorded @@ -113,6 +109,8 @@ class UsbOverheatEvent : public IServiceNotification, public IThermalChangedCall static void *monitorThread(void *param); // Register service notification listener bool registerListener(); + // Helper function to wakeup monitor thread + void wakeupMonitor(); // Thermal ServiceNotification listener Return<void> onRegistration(const hidl_string & /*fully_qualified_name*/, const hidl_string & /*instance_name*/, diff --git a/vibrator/cs40l25/Hardware.h b/vibrator/cs40l25/Hardware.h index d1883e53..f74fe931 100644 --- a/vibrator/cs40l25/Hardware.h +++ b/vibrator/cs40l25/Hardware.h @@ -48,6 +48,7 @@ class HwApi : public Vibrator::HwApi, private HwApiBase { open("device/clab_enable", &mClabEnable); open("device/available_pwle_segments", &mAvailablePwleSegments); open("device/pwle", &mPwle); + open("device/pwle_ramp_down", &mPwleRampDown); } bool setF0(uint32_t value) override { return set(value, &mF0); } @@ -76,6 +77,7 @@ class HwApi : public Vibrator::HwApi, private HwApiBase { bool getAvailablePwleSegments(uint32_t *value) override { return get(value, &mAvailablePwleSegments); } bool hasPwle() override { return has(mPwle); } bool setPwle(std::string value) override { return set(value, &mPwle); } + bool setPwleRampDown(uint32_t value) override { return set(value, &mPwleRampDown); } void debug(int fd) override { HwApiBase::debug(fd); } private: @@ -101,6 +103,7 @@ class HwApi : public Vibrator::HwApi, private HwApiBase { std::ofstream mClabEnable; std::ifstream mAvailablePwleSegments; std::ofstream mPwle; + std::ofstream mPwleRampDown; }; class HwCal : public Vibrator::HwCal, private HwCalBase { diff --git a/vibrator/cs40l25/Vibrator.cpp b/vibrator/cs40l25/Vibrator.cpp index d3da217b..8110cb37 100644 --- a/vibrator/cs40l25/Vibrator.cpp +++ b/vibrator/cs40l25/Vibrator.cpp @@ -75,8 +75,6 @@ static constexpr uint32_t MAX_TIME_MS = UINT32_MAX; static constexpr float AMP_ATTENUATE_STEP_SIZE = 0.125f; static constexpr float EFFECT_FREQUENCY_KHZ = 48.0f; -static constexpr auto ASYNC_COMPLETION_TIMEOUT = std::chrono::milliseconds(100); - static constexpr int32_t COMPOSE_DELAY_MAX_MS = 10000; static constexpr int32_t COMPOSE_SIZE_MAX = 127; static constexpr int32_t COMPOSE_PWLE_SIZE_MAX_DEFAULT = 127; @@ -103,6 +101,8 @@ static constexpr float PWLE_FREQUENCY_MIN_HZ = 0.25; static constexpr float PWLE_FREQUENCY_MAX_HZ = 1023.75; static constexpr float PWLE_BW_MAP_SIZE = 1 + ((PWLE_FREQUENCY_MAX_HZ - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ); +static constexpr float RAMP_DOWN_CONSTANT = 1048.576; +static constexpr float RAMP_DOWN_TIME_MS = 50.0; static struct pcm_config haptic_nohost_config = { .channels = 1, @@ -234,6 +234,8 @@ Vibrator::Vibrator(std::unique_ptr<HwApi> hwapi, std::unique_ptr<HwCal> hwcal) } createPwleMaxLevelLimitMap(); + mIsUnderExternalControl = false; + setPwleRampDown(); } ndk::ScopedAStatus Vibrator::getCapabilities(int32_t *_aidl_return) { @@ -309,6 +311,27 @@ ndk::ScopedAStatus Vibrator::setExternalControl(bool enabled) { ATRACE_NAME("Vibrator::setExternalControl"); setGlobalAmplitude(enabled); + if (isUnderExternalControl() == enabled) { + if (enabled) { + ALOGE("Restart the external process."); + if (mHasHapticAlsaDevice) { + if (!enableHapticPcmAmp(&mHapticPcm, !enabled, mCard, mDevice)) { + ALOGE("Failed to %s haptic pcm device: %d", (enabled ? "enable" : "disable"), + mDevice); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } + } + if (mHwApi->hasAspEnable()) { + if (!mHwApi->setAspEnable(!enabled)) { + ALOGE("Failed to set external control (%d): %s", errno, strerror(errno)); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } + } + } else { + ALOGE("The external control is already disabled."); + return ndk::ScopedAStatus::ok(); + } + } if (mHasHapticAlsaDevice) { if (!enableHapticPcmAmp(&mHapticPcm, enabled, mCard, mDevice)) { ALOGE("Failed to %s haptic pcm device: %d", (enabled ? "enable" : "disable"), mDevice); @@ -415,10 +438,12 @@ ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect> &composi ndk::ScopedAStatus Vibrator::on(uint32_t timeoutMs, uint32_t effectIndex, const std::shared_ptr<IVibratorCallback> &callback) { - if (mAsyncHandle.wait_for(ASYNC_COMPLETION_TIMEOUT) != std::future_status::ready) { - ALOGE("Previous vibration pending."); - return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + if (isUnderExternalControl()) { + setExternalControl(false); + ALOGE("Device is under external control mode. Force to disable it to prevent chip hang " + "problem."); } + mHwApi->setActivate(0); mHwApi->setEffectIndex(effectIndex); mHwApi->setDuration(timeoutMs); @@ -1125,6 +1150,22 @@ fail: return false; } +void Vibrator::setPwleRampDown() { + // The formula for calculating the ramp down coefficient to be written into + // pwle_ramp_down is as follows: + // Crd = 1048.576 / Trd + // where Trd is the desired ramp down time in seconds + // pwle_ramp_down accepts only 24 bit integers values + + const float seconds = RAMP_DOWN_TIME_MS / 1000; + const auto ramp_down_coefficient = static_cast<uint32_t>(RAMP_DOWN_CONSTANT / seconds); + + if (!mHwApi->setPwleRampDown(ramp_down_coefficient)) { + ALOGE("Failed to write \"%d\" to pwle_ramp_down (%d): %s", ramp_down_coefficient, errno, + strerror(errno)); + } +} + } // namespace vibrator } // namespace hardware } // namespace android diff --git a/vibrator/cs40l25/Vibrator.h b/vibrator/cs40l25/Vibrator.h index 08a115e4..88f7abd8 100644 --- a/vibrator/cs40l25/Vibrator.h +++ b/vibrator/cs40l25/Vibrator.h @@ -101,6 +101,9 @@ class Vibrator : public BnVibrator { // Specifies piecewise-linear specifications to generate complex // waveforms. virtual bool setPwle(std::string value) = 0; + // Specifies the coefficient required for a ramp down when a waveform + // ends + virtual bool setPwleRampDown(uint32_t value) = 0; // Emit diagnostic information to the given file. virtual void debug(int fd) = 0; }; @@ -200,6 +203,7 @@ class Vibrator : public BnVibrator { bool hasHapticAlsaDevice(); bool enableHapticPcmAmp(struct pcm **haptic_pcm, bool enable, int card, int device); void createPwleMaxLevelLimitMap(); + void setPwleRampDown(); std::unique_ptr<HwApi> mHwApi; std::unique_ptr<HwCal> mHwCal; diff --git a/vibrator/cs40l25/android.hardware.vibrator-service.cs40l25.rc b/vibrator/cs40l25/android.hardware.vibrator-service.cs40l25.rc index 3f28d81f..f373d31f 100644 --- a/vibrator/cs40l25/android.hardware.vibrator-service.cs40l25.rc +++ b/vibrator/cs40l25/android.hardware.vibrator-service.cs40l25.rc @@ -34,6 +34,7 @@ on boot chown system system /sys/class/leds/vibrator/device/hw_reset chown system system /sys/class/leds/vibrator/device/num_waves chown system system /sys/class/leds/vibrator/device/pwle + chown system system /sys/class/leds/vibrator/device/pwle_ramp_down chown system system /sys/class/leds/vibrator/device/q_stored chown system system /sys/class/leds/vibrator/device/redc_comp_enable chown system system /sys/class/leds/vibrator/device/redc_stored @@ -67,6 +68,7 @@ service vendor.vibrator.cs40l25 /vendor/bin/hw/android.hardware.vibrator-service device/heartbeat device/num_waves device/pwle + device/pwle_ramp_down device/q_stored device/redc_stored state diff --git a/vibrator/cs40l25/tests/mocks.h b/vibrator/cs40l25/tests/mocks.h index 2c69e27b..8f2c672e 100644 --- a/vibrator/cs40l25/tests/mocks.h +++ b/vibrator/cs40l25/tests/mocks.h @@ -49,6 +49,7 @@ class MockApi : public ::aidl::android::hardware::vibrator::Vibrator::HwApi { MOCK_METHOD1(getAvailablePwleSegments, bool(uint32_t *value)); MOCK_METHOD0(hasPwle, bool()); MOCK_METHOD1(setPwle, bool(std::string value)); + MOCK_METHOD1(setPwleRampDown, bool(uint32_t value)); MOCK_METHOD1(debug, void(int fd)); ~MockApi() override { destructor(); }; diff --git a/vibrator/cs40l25/tests/test-hwapi.cpp b/vibrator/cs40l25/tests/test-hwapi.cpp index 7f2ae01b..a339207b 100644 --- a/vibrator/cs40l25/tests/test-hwapi.cpp +++ b/vibrator/cs40l25/tests/test-hwapi.cpp @@ -55,6 +55,7 @@ class HwApiTest : public Test { "device/num_waves", "device/available_pwle_segments", "device/pwle", + "device/pwle_ramp_down", }; public: @@ -319,6 +320,8 @@ INSTANTIATE_TEST_CASE_P( &Vibrator::HwApi::setGpioRiseIndex), SetUint32Test::MakeParam("device/gpio1_rise_dig_scale", &Vibrator::HwApi::setGpioRiseScale), + SetUint32Test::MakeParam("device/pwle_ramp_down", + &Vibrator::HwApi::setPwleRampDown), }), SetUint32Test::PrintParam); |