summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pixelstats/StatsHelper.cpp25
-rw-r--r--pixelstats/SysfsCollector.cpp109
-rw-r--r--pixelstats/include/pixelstats/StatsHelper.h3
-rw-r--r--pixelstats/include/pixelstats/SysfsCollector.h11
-rw-r--r--pixelstats/pixelatoms.proto20
-rw-r--r--powerstats/dataproviders/PowerStatsEnergyConsumer.cpp67
-rw-r--r--rebalance_interrupts/rebalance_interrupts.cpp31
-rw-r--r--thermal/Thermal.cpp23
-rw-r--r--thermal/thermal-helper.cpp7
-rw-r--r--thermal/thermal-helper.h2
-rw-r--r--usb/UsbGadgetUtils.cpp2
-rw-r--r--usb/UsbOverheatEvent.cpp44
-rw-r--r--usb/include/pixelusb/UsbOverheatEvent.h8
-rw-r--r--vibrator/cs40l25/Hardware.h3
-rw-r--r--vibrator/cs40l25/Vibrator.cpp51
-rw-r--r--vibrator/cs40l25/Vibrator.h4
-rw-r--r--vibrator/cs40l25/android.hardware.vibrator-service.cs40l25.rc2
-rw-r--r--vibrator/cs40l25/tests/mocks.h1
-rw-r--r--vibrator/cs40l25/tests/test-hwapi.cpp3
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);