diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-12-02 02:17:30 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-12-02 02:17:30 +0000 |
commit | 0689e2abdffa7f5b8050c8329b26b6a2bf728a75 (patch) | |
tree | 046a983b55f04c34aeb5892d7775ea1cdc54a160 | |
parent | 84245f2640e2399e900baee2be53b2a916fbc6cf (diff) | |
parent | 9875ad57db961f533b2cee5963f309ecce56c580 (diff) | |
download | pixel-0689e2abdffa7f5b8050c8329b26b6a2bf728a75.tar.gz |
Snap for 11169761 from 9875ad57db961f533b2cee5963f309ecce56c580 to 24Q1-release
Change-Id: I0e9856cfbdf7fcd157ea645c32ffa381c7e76c0a
-rw-r--r-- | misc_writer/include/misc_writer/misc_writer.h | 3 | ||||
-rw-r--r-- | misc_writer/misc_writer.cpp | 19 | ||||
-rw-r--r-- | misc_writer/misc_writer_main.cpp | 16 | ||||
-rw-r--r-- | thermal/Android.bp | 2 | ||||
-rw-r--r-- | thermal/thermal-helper.cpp | 141 | ||||
-rw-r--r-- | thermal/thermal-helper.h | 2 | ||||
-rw-r--r-- | thermal/utils/thermal_info.cpp | 70 | ||||
-rw-r--r-- | thermal/utils/thermal_info.h | 5 | ||||
-rw-r--r-- | thermal/virtualtemp_estimator/virtualtemp_estimator.cpp | 158 | ||||
-rw-r--r-- | thermal/virtualtemp_estimator/virtualtemp_estimator.h | 58 | ||||
-rw-r--r-- | thermal/virtualtemp_estimator/virtualtemp_estimator_data.h | 75 | ||||
-rw-r--r-- | usb/CommonUtils.cpp | 6 | ||||
-rw-r--r-- | usb/include/pixelusb/CommonUtils.h | 9 |
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 |