summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-02 02:17:30 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-02 02:17:30 +0000
commit0689e2abdffa7f5b8050c8329b26b6a2bf728a75 (patch)
tree046a983b55f04c34aeb5892d7775ea1cdc54a160
parent84245f2640e2399e900baee2be53b2a916fbc6cf (diff)
parent9875ad57db961f533b2cee5963f309ecce56c580 (diff)
downloadpixel-0689e2abdffa7f5b8050c8329b26b6a2bf728a75.tar.gz
Snap for 11169761 from 9875ad57db961f533b2cee5963f309ecce56c580 to 24Q1-release
Change-Id: I0e9856cfbdf7fcd157ea645c32ffa381c7e76c0a
-rw-r--r--misc_writer/include/misc_writer/misc_writer.h3
-rw-r--r--misc_writer/misc_writer.cpp19
-rw-r--r--misc_writer/misc_writer_main.cpp16
-rw-r--r--thermal/Android.bp2
-rw-r--r--thermal/thermal-helper.cpp141
-rw-r--r--thermal/thermal-helper.h2
-rw-r--r--thermal/utils/thermal_info.cpp70
-rw-r--r--thermal/utils/thermal_info.h5
-rw-r--r--thermal/virtualtemp_estimator/virtualtemp_estimator.cpp158
-rw-r--r--thermal/virtualtemp_estimator/virtualtemp_estimator.h58
-rw-r--r--thermal/virtualtemp_estimator/virtualtemp_estimator_data.h75
-rw-r--r--usb/CommonUtils.cpp6
-rw-r--r--usb/include/pixelusb/CommonUtils.h9
13 files changed, 482 insertions, 82 deletions
diff --git a/misc_writer/include/misc_writer/misc_writer.h b/misc_writer/include/misc_writer/misc_writer.h
index 3b1bcb21..7757640d 100644
--- a/misc_writer/include/misc_writer/misc_writer.h
+++ b/misc_writer/include/misc_writer/misc_writer.h
@@ -42,7 +42,7 @@ enum class MiscWriterActions : int32_t {
kClearMaxRamSize,
kWriteTimeRtcOffset,
kWriteTimeMinRtc,
- kSetSotaState,
+ kSetSotaConfig,
kUnset = -1,
};
@@ -70,6 +70,7 @@ class MiscWriter {
static constexpr uint32_t kRTimeMinRtcValOffsetInVendorSpace = 296;
static constexpr char kTimeMinRtc[] = "timeminrtc=";
static constexpr uint32_t kFaceauthEvalValOffsetInVendorSpace = 328;
+ static constexpr uint32_t kSotaScheduleShipmodeOffsetInVendorSpace = 360;
// Minimum and maximum valid value for max-ram-size
static constexpr int32_t kRamSizeDefault = -1;
diff --git a/misc_writer/misc_writer.cpp b/misc_writer/misc_writer.cpp
index edef20d6..710c2ffe 100644
--- a/misc_writer/misc_writer.cpp
+++ b/misc_writer/misc_writer.cpp
@@ -103,11 +103,8 @@ bool MiscWriter::PerformAction(std::optional<size_t> override_offset) {
content = std::string(kTimeMinRtc) + stringdata_;
content.resize(32);
break;
- case MiscWriterActions::kSetSotaState:
- offset = override_offset.value_or(kSotaStateOffsetInVendorSpace);
- content = stringdata_;
- content.resize(40);
- break;
+ case MiscWriterActions::kSetSotaConfig:
+ goto sota_config;
case MiscWriterActions::kUnset:
LOG(ERROR) << "The misc writer action must be set";
return false;
@@ -119,7 +116,8 @@ bool MiscWriter::PerformAction(std::optional<size_t> override_offset) {
return false;
}
- if (action_ == MiscWriterActions::kSetSotaFlag) {
+sota_config:
+ if (action_ == MiscWriterActions::kSetSotaFlag || action_ == MiscWriterActions::kSetSotaConfig) {
content = ::android::base::GetProperty("persist.vendor.nfc.factoryota.state", "");
if (content.size() != 0 && content.size() <= 40) {
offset = kSotaStateOffsetInVendorSpace;
@@ -129,6 +127,15 @@ bool MiscWriter::PerformAction(std::optional<size_t> override_offset) {
return false;
}
}
+ content = ::android::base::GetProperty("persist.vendor.nfc.factoryota.schedule_shipmode", "");
+ if (content.size() != 0 && content.size() <= 32) {
+ offset = kSotaScheduleShipmodeOffsetInVendorSpace;
+ if (std::string err;
+ !WriteMiscPartitionVendorSpace(content.data(), content.size(), offset, &err)) {
+ LOG(ERROR) << "Failed to write " << content << " at offset " << offset << " : " << err;
+ return false;
+ }
+ }
}
return true;
diff --git a/misc_writer/misc_writer_main.cpp b/misc_writer/misc_writer_main.cpp
index 72d6426a..f3546ef6 100644
--- a/misc_writer/misc_writer_main.cpp
+++ b/misc_writer/misc_writer_main.cpp
@@ -42,7 +42,7 @@ static int Usage(std::string_view name) {
std::cerr << " --clear-dark-theme Clear the dark theme flag\n";
std::cerr << " --set-sota Write the silent OTA flag\n";
std::cerr << " --clear-sota Clear the silent OTA flag\n";
- std::cerr << " --set-sota-state Set the silent OTA state\n";
+ std::cerr << " --set-sota-config Set the silent OTA configs\n";
std::cerr << " --set-enable-pkvm Write the enable pKVM flag\n";
std::cerr << " --set-disable-pkvm Write the disable pKVM flag\n";
std::cerr << " --set-wrist-orientation <0-3> Write the wrist orientation flag\n";
@@ -76,7 +76,7 @@ int main(int argc, char** argv) {
{ "set-max-ram-size", required_argument, nullptr, 0},
{ "set-timertcoffset", required_argument, nullptr, 0},
{ "set-minrtc", required_argument, nullptr, 0},
- { "set-sota-state", required_argument, nullptr, 0 },
+ { "set-sota-config", no_argument, nullptr, 0 },
{ nullptr, 0, nullptr, 0 },
};
@@ -88,7 +88,7 @@ int main(int argc, char** argv) {
{ "set-enable-pkvm", MiscWriterActions::kSetEnablePkvmFlag },
{ "set-disable-pkvm", MiscWriterActions::kSetDisablePkvmFlag },
{ "clear-wrist-orientation", MiscWriterActions::kClearWristOrientationFlag },
- { "set-sota-state", MiscWriterActions::kSetSotaState },
+ { "set-sota-config", MiscWriterActions::kSetSotaConfig },
};
std::unique_ptr<MiscWriter> misc_writer;
@@ -204,16 +204,6 @@ int main(int argc, char** argv) {
}
misc_writer = std::make_unique<MiscWriter>(MiscWriterActions::kWriteTimeMinRtc,
std::to_string(minrtc));
- } else if (option_name == "set-sota-state"s) {
- const char *char_state = optarg;
- std::string state(char_state);
-
- if (misc_writer) {
- LOG(ERROR) << "Misc writer action has already been set";
- return Usage(argv[0]);
- }
- misc_writer = std::make_unique<MiscWriter>(MiscWriterActions::kSetSotaState,
- state);
} else if (auto iter = action_map.find(option_name); iter != action_map.end()) {
if (misc_writer) {
LOG(ERROR) << "Misc writer action has already been set";
diff --git a/thermal/Android.bp b/thermal/Android.bp
index 0097adfc..51f98d66 100644
--- a/thermal/Android.bp
+++ b/thermal/Android.bp
@@ -15,6 +15,7 @@ cc_binary {
"utils/powerhal_helper.cpp",
"utils/thermal_stats_helper.cpp",
"utils/thermal_watcher.cpp",
+ "virtualtemp_estimator/virtualtemp_estimator.cpp",
],
vendor: true,
relative_install_path: "hw",
@@ -79,6 +80,7 @@ cc_test {
"utils/thermal_watcher.cpp",
"tests/mock_thermal_helper.cpp",
"tests/thermal_looper_test.cpp",
+ "virtualtemp_estimator/virtualtemp_estimator.cpp",
],
shared_libs: [
"libbase",
diff --git a/thermal/thermal-helper.cpp b/thermal/thermal-helper.cpp
index b059f6d3..61de8bcc 100644
--- a/thermal/thermal-helper.cpp
+++ b/thermal/thermal-helper.cpp
@@ -906,12 +906,55 @@ bool ThermalHelperImpl::readDataByType(std::string_view sensor_data, float *read
return true;
}
+float ThermalHelperImpl::runVirtualTempEstimator(std::string_view sensor_name,
+ std::map<std::string, float> *sensor_log_map) {
+ std::vector<float> model_inputs;
+ float estimated_vt = NAN;
+ constexpr int kCelsius2mC = 1000;
+
+ ATRACE_NAME(StringPrintf("ThermalHelper::runVirtualTempEstimator - %s", sensor_name.data())
+ .c_str());
+ if (!(sensor_info_map_.count(sensor_name.data()) &&
+ sensor_status_map_.count(sensor_name.data()))) {
+ LOG(ERROR) << sensor_name << " not part of sensor_info_map_ or sensor_status_map_";
+ return NAN;
+ }
+
+ const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
+ if (!sensor_info.virtual_sensor_info->vt_estimator) {
+ LOG(ERROR) << "vt_estimator not valid for " << sensor_name;
+ return NAN;
+ }
+
+ model_inputs.reserve(sensor_info.virtual_sensor_info->linked_sensors.size());
+
+ for (size_t i = 0; i < sensor_info.virtual_sensor_info->linked_sensors.size(); i++) {
+ std::string linked_sensor = sensor_info.virtual_sensor_info->linked_sensors[i];
+
+ if ((*sensor_log_map).count(linked_sensor.data())) {
+ float value = (*sensor_log_map)[linked_sensor.data()];
+ model_inputs.push_back(value / kCelsius2mC);
+ } else {
+ LOG(ERROR) << "failed to read sensor: " << linked_sensor;
+ return NAN;
+ }
+ }
+
+ ::thermal::vtestimator::VtEstimatorStatus ret =
+ sensor_info.virtual_sensor_info->vt_estimator->Estimate(model_inputs, &estimated_vt);
+ if (ret != ::thermal::vtestimator::kVtEstimatorOk) {
+ LOG(ERROR) << "Failed to run estimator (ret: " << ret << ") for " << sensor_name;
+ return NAN;
+ }
+
+ return (estimated_vt * kCelsius2mC);
+}
+
constexpr int kTranTimeoutParam = 2;
bool ThermalHelperImpl::readThermalSensor(std::string_view sensor_name, float *temp,
const bool force_no_cache,
std::map<std::string, float> *sensor_log_map) {
- float temp_val = 0.0;
std::string file_reading;
boot_clock::time_point now = boot_clock::now();
@@ -955,57 +998,75 @@ bool ThermalHelperImpl::readThermalSensor(std::string_view sensor_name, float *t
}
*temp = std::stof(::android::base::Trim(file_reading));
} else {
- for (size_t i = 0; i < sensor_info.virtual_sensor_info->linked_sensors.size(); i++) {
- float sensor_reading = 0.0;
- // Get the sensor reading data
- if (!readDataByType(sensor_info.virtual_sensor_info->linked_sensors[i], &sensor_reading,
+ const auto &linked_sensors_size = sensor_info.virtual_sensor_info->linked_sensors.size();
+ std::vector<float> sensor_readings(linked_sensors_size, 0.0);
+
+ // Calculate temperature of each of the linked sensor
+ for (size_t i = 0; i < linked_sensors_size; i++) {
+ if (!readDataByType(sensor_info.virtual_sensor_info->linked_sensors[i],
+ &sensor_readings[i],
sensor_info.virtual_sensor_info->linked_sensors_type[i],
force_no_cache, sensor_log_map)) {
LOG(ERROR) << "Failed to read " << sensor_name.data() << "'s linked sensor "
<< sensor_info.virtual_sensor_info->linked_sensors[i];
return false;
}
-
- float coefficient = 0.0;
- if (!readDataByType(sensor_info.virtual_sensor_info->coefficients[i], &coefficient,
- sensor_info.virtual_sensor_info->coefficients_type[i],
- force_no_cache, sensor_log_map)) {
- LOG(ERROR) << "Failed to read " << sensor_name.data() << "'s coefficient "
- << sensor_info.virtual_sensor_info->coefficients[i];
- return false;
- }
-
- if (std::isnan(sensor_reading) || std::isnan(coefficient)) {
+ if (std::isnan(sensor_readings[i])) {
LOG(INFO) << sensor_name << " data is under collecting";
return true;
}
+ }
- switch (sensor_info.virtual_sensor_info->formula) {
- case FormulaOption::COUNT_THRESHOLD:
- if ((coefficient < 0 && sensor_reading < -coefficient) ||
- (coefficient >= 0 && sensor_reading >= coefficient))
- temp_val += 1;
- break;
- case FormulaOption::WEIGHTED_AVG:
- temp_val += sensor_reading * coefficient;
- break;
- case FormulaOption::MAXIMUM:
- if (i == 0)
- temp_val = std::numeric_limits<float>::lowest();
- if (sensor_reading * coefficient > temp_val)
- temp_val = sensor_reading * coefficient;
- break;
- case FormulaOption::MINIMUM:
- if (i == 0)
- temp_val = std::numeric_limits<float>::max();
- if (sensor_reading * coefficient < temp_val)
- temp_val = sensor_reading * coefficient;
- break;
- default:
- break;
+ if (sensor_info.virtual_sensor_info->formula == FormulaOption::USE_ML_MODEL) {
+ *temp = runVirtualTempEstimator(sensor_name, sensor_log_map);
+
+ if (std::isnan(*temp)) {
+ LOG(ERROR) << "VirtualEstimator returned NAN for " << sensor_name;
+ return false;
+ }
+ } else {
+ float temp_val = 0.0;
+ for (size_t i = 0; i < linked_sensors_size; i++) {
+ float coefficient = 0.0;
+ if (!readDataByType(sensor_info.virtual_sensor_info->coefficients[i], &coefficient,
+ sensor_info.virtual_sensor_info->coefficients_type[i],
+ force_no_cache, sensor_log_map)) {
+ LOG(ERROR) << "Failed to read " << sensor_name.data() << "'s coefficient "
+ << sensor_info.virtual_sensor_info->coefficients[i];
+ return false;
+ }
+ if (std::isnan(coefficient)) {
+ LOG(INFO) << sensor_name << " data is under collecting";
+ return true;
+ }
+ switch (sensor_info.virtual_sensor_info->formula) {
+ case FormulaOption::COUNT_THRESHOLD:
+ if ((coefficient < 0 && sensor_readings[i] < -coefficient) ||
+ (coefficient >= 0 && sensor_readings[i] >= coefficient))
+ temp_val += 1;
+ break;
+ case FormulaOption::WEIGHTED_AVG:
+ temp_val += sensor_readings[i] * coefficient;
+ break;
+ case FormulaOption::MAXIMUM:
+ if (i == 0)
+ temp_val = std::numeric_limits<float>::lowest();
+ if (sensor_readings[i] * coefficient > temp_val)
+ temp_val = sensor_readings[i] * coefficient;
+ break;
+ case FormulaOption::MINIMUM:
+ if (i == 0)
+ temp_val = std::numeric_limits<float>::max();
+ if (sensor_readings[i] * coefficient < temp_val)
+ temp_val = sensor_readings[i] * coefficient;
+ break;
+ default:
+ LOG(ERROR) << "Unknown formula type for sensor " << sensor_name.data();
+ return false;
+ }
}
+ *temp = (temp_val + sensor_info.virtual_sensor_info->offset);
}
- *temp = (temp_val + sensor_info.virtual_sensor_info->offset);
}
if (!isnan(sensor_info.step_ratio) && !isnan(sensor_status.thermal_cached.temp) &&
diff --git a/thermal/thermal-helper.h b/thermal/thermal-helper.h
index ebf6f81a..489b792a 100644
--- a/thermal/thermal-helper.h
+++ b/thermal/thermal-helper.h
@@ -212,6 +212,8 @@ class ThermalHelperImpl : public ThermalHelper {
// Read temperature data according to thermal sensor's info
bool readThermalSensor(std::string_view sensor_name, float *temp, const bool force_sysfs,
std::map<std::string, float> *sensor_log_map);
+ float runVirtualTempEstimator(std::string_view sensor_name,
+ std::map<std::string, float> *sensor_log_map);
void updateCoolingDevices(const std::vector<std::string> &cooling_devices_to_update);
// Check the max CDEV state for cdev_ceiling
void maxCoolingRequestCheck(
diff --git a/thermal/utils/thermal_info.cpp b/thermal/utils/thermal_info.cpp
index 68033abf..d03b6d87 100644
--- a/thermal/utils/thermal_info.cpp
+++ b/thermal/utils/thermal_info.cpp
@@ -232,6 +232,8 @@ bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sens
std::vector<std::string> coefficients;
std::vector<SensorFusionType> coefficients_type;
FormulaOption formula = FormulaOption::COUNT_THRESHOLD;
+ std::string vt_estimator_model_file;
+ std::unique_ptr<::thermal::vtestimator::VirtualTempEstimator> vt_estimator;
Json::Value values = sensor["Combination"];
if (values.size()) {
@@ -245,6 +247,21 @@ bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sens
return false;
}
+ if (sensor["Formula"].asString().compare("COUNT_THRESHOLD") == 0) {
+ formula = FormulaOption::COUNT_THRESHOLD;
+ } else if (sensor["Formula"].asString().compare("WEIGHTED_AVG") == 0) {
+ formula = FormulaOption::WEIGHTED_AVG;
+ } else if (sensor["Formula"].asString().compare("MAXIMUM") == 0) {
+ formula = FormulaOption::MAXIMUM;
+ } else if (sensor["Formula"].asString().compare("MINIMUM") == 0) {
+ formula = FormulaOption::MINIMUM;
+ } else if (sensor["Formula"].asString().compare("USE_ML_MODEL") == 0) {
+ formula = FormulaOption::USE_ML_MODEL;
+ } else {
+ LOG(ERROR) << "Sensor[" << name << "]'s Formula is invalid";
+ return false;
+ }
+
values = sensor["CombinationType"];
if (!values.size()) {
linked_sensors_type.reserve(linked_sensors.size());
@@ -283,7 +300,8 @@ bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sens
LOG(ERROR) << "Sensor[" << name << "] has no Coefficient setting";
return false;
}
- if (linked_sensors.size() != coefficients.size()) {
+ if ((linked_sensors.size() != coefficients.size()) &&
+ (formula != FormulaOption::USE_ML_MODEL)) {
LOG(ERROR) << "Sensor[" << name << "] has invalid Coefficient size";
return false;
}
@@ -347,21 +365,43 @@ bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sens
}
}
- if (sensor["Formula"].asString().compare("COUNT_THRESHOLD") == 0) {
- formula = FormulaOption::COUNT_THRESHOLD;
- } else if (sensor["Formula"].asString().compare("WEIGHTED_AVG") == 0) {
- formula = FormulaOption::WEIGHTED_AVG;
- } else if (sensor["Formula"].asString().compare("MAXIMUM") == 0) {
- formula = FormulaOption::MAXIMUM;
- } else if (sensor["Formula"].asString().compare("MINIMUM") == 0) {
- formula = FormulaOption::MINIMUM;
- } else {
- LOG(ERROR) << "Sensor[" << name << "]'s Formula is invalid";
- return false;
+ if (formula == FormulaOption::USE_ML_MODEL) {
+ if (sensor["ModelPath"].empty()) {
+ LOG(ERROR) << "Sensor[" << name << "] has no ModelPath";
+ return false;
+ }
+
+ if (!linked_sensors.size()) {
+ LOG(ERROR) << "Sensor[" << name << "] uses USE_ML_MODEL and has zero linked_sensors";
+ return false;
+ }
+
+ vt_estimator = std::make_unique<::thermal::vtestimator::VirtualTempEstimator>(
+ linked_sensors.size());
+ if (!vt_estimator) {
+ LOG(ERROR) << "Failed to create vt estimator for Sensor[" << name
+ << "] with linked sensor size : " << linked_sensors.size();
+ return false;
+ }
+
+ vt_estimator_model_file = "vendor/etc/" + sensor["ModelPath"].asString();
+
+ ::thermal::vtestimator::VtEstimatorStatus ret =
+ vt_estimator->Initialize(vt_estimator_model_file.c_str());
+ if (ret != ::thermal::vtestimator::kVtEstimatorOk) {
+ LOG(ERROR) << "Failed to initialize vt estimator for Sensor[" << name
+ << "] with ModelPath: " << vt_estimator_model_file
+ << " with ret code : " << ret;
+ return false;
+ }
+
+ LOG(INFO) << "Successfully created vt_estimator for Sensor[" << name
+ << "] with input samples: " << linked_sensors.size();
}
- virtual_sensor_info->reset(new VirtualSensorInfo{linked_sensors, linked_sensors_type,
- coefficients, coefficients_type, offset,
- trigger_sensors, formula});
+
+ virtual_sensor_info->reset(new VirtualSensorInfo{
+ linked_sensors, linked_sensors_type, coefficients, coefficients_type, offset,
+ trigger_sensors, formula, vt_estimator_model_file, std::move(vt_estimator)});
return true;
}
diff --git a/thermal/utils/thermal_info.h b/thermal/utils/thermal_info.h
index ce2f5d09..843424e6 100644
--- a/thermal/utils/thermal_info.h
+++ b/thermal/utils/thermal_info.h
@@ -27,6 +27,8 @@
#include <unordered_set>
#include <variant>
+#include "virtualtemp_estimator/virtualtemp_estimator.h"
+
namespace aidl {
namespace android {
namespace hardware {
@@ -53,6 +55,7 @@ enum class FormulaOption : uint32_t {
WEIGHTED_AVG,
MAXIMUM,
MINIMUM,
+ USE_ML_MODEL
};
template <typename T>
@@ -136,6 +139,8 @@ struct VirtualSensorInfo {
float offset;
std::vector<std::string> trigger_sensors;
FormulaOption formula;
+ std::string vt_estimator_model_file;
+ std::unique_ptr<::thermal::vtestimator::VirtualTempEstimator> vt_estimator;
};
struct VirtualPowerRailInfo {
diff --git a/thermal/virtualtemp_estimator/virtualtemp_estimator.cpp b/thermal/virtualtemp_estimator/virtualtemp_estimator.cpp
new file mode 100644
index 00000000..2dc2185c
--- /dev/null
+++ b/thermal/virtualtemp_estimator/virtualtemp_estimator.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2023 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 "virtualtemp_estimator.h"
+
+#include <android-base/logging.h>
+#include <dlfcn.h>
+
+#include <vector>
+
+namespace thermal {
+namespace vtestimator {
+
+void VirtualTempEstimator::LoadTFLiteWrapper() {
+ if (!data_) {
+ LOG(ERROR) << "data_ is nullptr during LoadTFLiteWrapper";
+ return;
+ }
+
+ std::unique_lock<std::mutex> lock(data_->tflite_methods.mutex_);
+
+ void *mLibHandle = dlopen("/vendor/lib64/libthermal_tflite_wrapper.so", 0);
+ if (mLibHandle == nullptr) {
+ LOG(ERROR) << "Could not load libthermal_tflite_wrapper library with error: " << dlerror();
+ return;
+ }
+
+ data_->tflite_methods.create =
+ reinterpret_cast<tflitewrapper_create>(dlsym(mLibHandle, "Create"));
+ if (!data_->tflite_methods.create) {
+ LOG(ERROR) << "Could not link and cast tflitewrapper_create with error: " << dlerror();
+ }
+
+ data_->tflite_methods.init = reinterpret_cast<tflitewrapper_init>(dlsym(mLibHandle, "Init"));
+ if (!data_->tflite_methods.init) {
+ LOG(ERROR) << "Could not link and cast tflitewrapper_init with error: " << dlerror();
+ }
+
+ data_->tflite_methods.invoke =
+ reinterpret_cast<tflitewrapper_invoke>(dlsym(mLibHandle, "Invoke"));
+ if (!data_->tflite_methods.invoke) {
+ LOG(ERROR) << "Could not link and cast tflitewrapper_invoke with error: " << dlerror();
+ }
+
+ data_->tflite_methods.destroy =
+ reinterpret_cast<tflitewrapper_destroy>(dlsym(mLibHandle, "Destroy"));
+ if (!data_->tflite_methods.destroy) {
+ LOG(ERROR) << "Could not link and cast tflitewrapper_destroy with error: " << dlerror();
+ }
+}
+
+VirtualTempEstimator::VirtualTempEstimator(size_t num_input_samples) {
+ data_ = std::make_unique<VirtualTempEstimatorTFLiteData>(num_input_samples);
+ LoadTFLiteWrapper();
+}
+
+VirtualTempEstimator::~VirtualTempEstimator() {
+ LOG(INFO) << "VirtualTempEstimator destructor";
+}
+
+VtEstimatorStatus VirtualTempEstimator::Initialize(const char *model_path) {
+ LOG(INFO) << "Initialize VirtualTempEstimator\n";
+
+ if (!data_) {
+ LOG(ERROR) << "data_ is nullptr during Initialize\n";
+ return kVtEstimatorInitFailed;
+ }
+
+ std::unique_lock<std::mutex> lock(data_->tflite_methods.mutex_);
+
+ if (!model_path) {
+ LOG(ERROR) << "Invalid model_path:" << model_path;
+ return kVtEstimatorInvalidArgs;
+ }
+
+ if (!data_->input_buffer || !data_->input_buffer_size) {
+ LOG(ERROR) << "Invalid data_ members " << model_path
+ << " input_buffer: " << data_->input_buffer
+ << " input_buffer_size: " << data_->input_buffer_size;
+ return kVtEstimatorInitFailed;
+ }
+
+ if (!data_->tflite_methods.create || !data_->tflite_methods.init ||
+ !data_->tflite_methods.invoke || !data_->tflite_methods.destroy) {
+ LOG(ERROR) << "Invalid tflite methods";
+ return kVtEstimatorInitFailed;
+ }
+
+ data_->tflite_wrapper = data_->tflite_methods.create(kNumInputTensors, kNumOutputTensors);
+ if (!data_->tflite_wrapper) {
+ LOG(ERROR) << "Failed to create tflite wrapper";
+ return kVtEstimatorInitFailed;
+ }
+
+ int ret = data_->tflite_methods.init(data_->tflite_wrapper, model_path);
+ if (ret) {
+ LOG(ERROR) << "Failed to Init tflite_wrapper for " << model_path << " (ret: )" << ret
+ << ")";
+ return kVtEstimatorInitFailed;
+ }
+
+ data_->is_initialized = true;
+ data_->model_path = model_path;
+
+ LOG(INFO) << "Successfully initialized VirtualTempEstimator for " << model_path;
+ return kVtEstimatorOk;
+}
+
+VtEstimatorStatus VirtualTempEstimator::Estimate(const std::vector<float> &thermistors,
+ float *output) {
+ if (!data_) {
+ LOG(ERROR) << "data_ is nullptr during Estimate\n";
+ return kVtEstimatorInitFailed;
+ }
+
+ std::unique_lock<std::mutex> lock(data_->tflite_methods.mutex_);
+
+ if (!data_->is_initialized) {
+ LOG(ERROR) << "data_ not initialized for " << data_->model_path;
+ return kVtEstimatorInitFailed;
+ }
+
+ if ((thermistors.size() != data_->input_buffer_size) || (!output)) {
+ LOG(ERROR) << "Invalid args for " << data_->model_path
+ << " thermistors.size(): " << thermistors.size()
+ << " input_buffer_size: " << data_->input_buffer_size << " output: " << output;
+ return kVtEstimatorInvalidArgs;
+ }
+
+ // copy input data into input tensors
+ for (size_t i = 0; i < data_->input_buffer_size; ++i) {
+ data_->input_buffer[i] = thermistors[i];
+ }
+
+ int ret = data_->tflite_methods.invoke(data_->tflite_wrapper, data_->input_buffer,
+ data_->input_buffer_size, output, 1);
+ if (ret) {
+ LOG(ERROR) << "Failed to Invoke for " << data_->model_path << " (ret: " << ret << ")";
+ return kVtEstimatorInvokeFailed;
+ }
+
+ return kVtEstimatorOk;
+}
+
+} // namespace vtestimator
+} // namespace thermal
diff --git a/thermal/virtualtemp_estimator/virtualtemp_estimator.h b/thermal/virtualtemp_estimator/virtualtemp_estimator.h
new file mode 100644
index 00000000..0ae37f9e
--- /dev/null
+++ b/thermal/virtualtemp_estimator/virtualtemp_estimator.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <vector>
+
+#include "virtualtemp_estimator_data.h"
+
+namespace thermal {
+namespace vtestimator {
+
+enum VtEstimatorStatus {
+ kVtEstimatorOk = 0,
+ kVtEstimatorInvalidArgs = 1,
+ kVtEstimatorInitFailed = 2,
+ kVtEstimatorInvokeFailed = 3,
+ kVtEstimatorUnSupported = 4,
+};
+
+// Class to estimate virtual temperature based on a model
+class VirtualTempEstimator {
+ public:
+ // Implicit copy-move headers.
+ VirtualTempEstimator(const VirtualTempEstimator &) = delete;
+ VirtualTempEstimator(VirtualTempEstimator &&) = default;
+ VirtualTempEstimator &operator=(const VirtualTempEstimator &) = delete;
+ VirtualTempEstimator &operator=(VirtualTempEstimator &&) = default;
+
+ VirtualTempEstimator(size_t num_input_samples);
+ ~VirtualTempEstimator();
+
+ // Initializes the model provided by model_path.
+ VtEstimatorStatus Initialize(const char *model_path);
+
+ // Performs the inference on the loaded VT model.
+ // Output of the inference is returned in output argument
+ VtEstimatorStatus Estimate(const std::vector<float> &thermistors, float *output);
+
+ private:
+ void LoadTFLiteWrapper();
+ std::unique_ptr<VirtualTempEstimatorTFLiteData> data_;
+};
+
+} // namespace vtestimator
+} // namespace thermal
diff --git a/thermal/virtualtemp_estimator/virtualtemp_estimator_data.h b/thermal/virtualtemp_estimator/virtualtemp_estimator_data.h
new file mode 100644
index 00000000..075d66ff
--- /dev/null
+++ b/thermal/virtualtemp_estimator/virtualtemp_estimator_data.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2023 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 <cstddef>
+#include <mutex>
+#include <string>
+
+#pragma once
+
+namespace thermal {
+namespace vtestimator {
+
+// Current version only supports single input/output tensors
+constexpr int kNumInputTensors = 1;
+constexpr int kNumOutputTensors = 1;
+
+typedef void *(*tflitewrapper_create)(int num_input_tensors, int num_output_tensors);
+typedef bool (*tflitewrapper_init)(void *handle, const char *model_path);
+typedef bool (*tflitewrapper_invoke)(void *handle, float *input_samples, int num_input_samples,
+ float *output_samples, int num_output_samples);
+typedef void (*tflitewrapper_destroy)(void *handle);
+
+struct TFLiteWrapperMethods {
+ tflitewrapper_create create;
+ tflitewrapper_init init;
+ tflitewrapper_invoke invoke;
+ tflitewrapper_destroy destroy;
+ mutable std::mutex mutex_;
+};
+
+struct VirtualTempEstimatorTFLiteData {
+ VirtualTempEstimatorTFLiteData(size_t num_input_samples) {
+ input_buffer = new float[num_input_samples];
+ input_buffer_size = num_input_samples;
+ is_initialized = false;
+
+ tflite_methods.create = nullptr;
+ tflite_methods.init = nullptr;
+ tflite_methods.invoke = nullptr;
+ tflite_methods.destroy = nullptr;
+ }
+
+ void *tflite_wrapper;
+ float *input_buffer;
+ size_t input_buffer_size;
+ std::string model_path;
+ TFLiteWrapperMethods tflite_methods;
+ bool is_initialized;
+
+ ~VirtualTempEstimatorTFLiteData() {
+ if (tflite_wrapper && tflite_methods.destroy) {
+ tflite_methods.destroy(tflite_wrapper);
+ }
+
+ if (input_buffer) {
+ delete input_buffer;
+ }
+ }
+};
+
+} // namespace vtestimator
+} // namespace thermal
diff --git a/usb/CommonUtils.cpp b/usb/CommonUtils.cpp
index 91688b98..6e0f08c9 100644
--- a/usb/CommonUtils.cpp
+++ b/usb/CommonUtils.cpp
@@ -200,10 +200,10 @@ static VendorUsbDataSessionEvent_UsbDeviceState stringToUsbDeviceStateProto(
}
}
-void BuildVendorUsbDataSessionEvent(bool is_host, steady_clock::time_point currentTime,
- steady_clock::time_point startTime,
+void BuildVendorUsbDataSessionEvent(bool is_host, boot_clock::time_point currentTime,
+ boot_clock::time_point startTime,
std::vector<std::string> *states,
- std::vector<steady_clock::time_point> *timestamps,
+ std::vector<boot_clock::time_point> *timestamps,
VendorUsbDataSessionEvent *event) {
if (is_host) {
event->set_usb_role(VendorUsbDataSessionEvent_UsbDataRole_USB_ROLE_HOST);
diff --git a/usb/include/pixelusb/CommonUtils.h b/usb/include/pixelusb/CommonUtils.h
index 93855be3..dbd59c63 100644
--- a/usb/include/pixelusb/CommonUtils.h
+++ b/usb/include/pixelusb/CommonUtils.h
@@ -17,6 +17,7 @@
#ifndef HARDWARE_GOOGLE_PIXEL_USB_UTILSCOMMON_H_
#define HARDWARE_GOOGLE_PIXEL_USB_UTILSCOMMON_H_
+#include <android-base/chrono_utils.h>
#include <android-base/unique_fd.h>
#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
@@ -58,8 +59,8 @@ constexpr char kUvcEnabled[] = "ro.usb.uvc.enabled";
#define FUNCTION_PATH CONFIG_PATH FUNCTION_NAME
#define RNDIS_PATH FUNCTIONS_PATH "gsi.rndis"
+using ::android::base::boot_clock;
using android::hardware::google::pixel::PixelAtoms::VendorUsbDataSessionEvent;
-using ::std::chrono::steady_clock;
// Adds the given fd to the epollfd(epfd).
int addEpollFd(const ::android::base::unique_fd &epfd, const ::android::base::unique_fd &fd);
@@ -73,10 +74,10 @@ int linkFunction(const char *function, int index);
bool setVidPidCommon(const char *vid, const char *pid);
// Pulls down USB gadget. Returns true on success, false on failure
bool resetGadgetCommon();
-void BuildVendorUsbDataSessionEvent(bool is_host, steady_clock::time_point currentTime,
- steady_clock::time_point startTime,
+void BuildVendorUsbDataSessionEvent(bool is_host, boot_clock::time_point currentTime,
+ boot_clock::time_point startTime,
std::vector<std::string> *states,
- std::vector<steady_clock::time_point> *timestamps,
+ std::vector<boot_clock::time_point> *timestamps,
VendorUsbDataSessionEvent *event);
} // namespace usb