blob: ceb4946c4a24f43da50b4f9ad0f11041666b09a0 [file] [log] [blame] [edit]
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "pixelstats: BatteryTTFReporter"
#include <android-base/file.h>
#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
#include <log/log.h>
#include <pixelstats/BatteryTTFReporter.h>
#include <pixelstats/StatsHelper.h>
#include <time.h>
#include <utils/Timers.h>
#include <cinttypes>
namespace android {
namespace hardware {
namespace google {
namespace pixel {
using aidl::android::frameworks::stats::IStats;
using aidl::android::frameworks::stats::VendorAtom;
using aidl::android::frameworks::stats::VendorAtomValue;
using android::base::ReadFileToString;
using android::base::WriteStringToFile;
using android::hardware::google::pixel::PixelAtoms::BatteryTimeToFullStatsReported;
const int SECONDS_PER_MONTH = 60 * 60 * 24 * 30;
BatteryTTFReporter::BatteryTTFReporter() {}
int64_t BatteryTTFReporter::getTimeSecs(void) {
return nanoseconds_to_seconds(systemTime(SYSTEM_TIME_BOOTTIME));
}
bool BatteryTTFReporter::reportBatteryTTFStats(const std::shared_ptr<IStats> &stats_client) {
std::string path = kBatteryTTFPath;
std::string file_contents, line;
std::istringstream ss;
if (!ReadFileToString(path.c_str(), &file_contents)) {
ALOGD("Unsupported path %s - %s", path.c_str(), strerror(errno));
return false;
}
ss.str(file_contents);
while (std::getline(ss, line)) {
reportBatteryTTFStatsEvent(stats_client, line.c_str());
}
return true;
}
void BatteryTTFReporter::reportBatteryTTFStatsEvent(
const std::shared_ptr<IStats> &stats_client, const char *line) {
int ttf_stats_stats_fields[] = {
BatteryTimeToFullStatsReported::kTtfTypeFieldNumber,
BatteryTimeToFullStatsReported::kTtfRangeFieldNumber,
BatteryTimeToFullStatsReported::kSoc0FieldNumber,
BatteryTimeToFullStatsReported::kSoc1FieldNumber,
BatteryTimeToFullStatsReported::kSoc2FieldNumber,
BatteryTimeToFullStatsReported::kSoc3FieldNumber,
BatteryTimeToFullStatsReported::kSoc4FieldNumber,
BatteryTimeToFullStatsReported::kSoc5FieldNumber,
BatteryTimeToFullStatsReported::kSoc6FieldNumber,
BatteryTimeToFullStatsReported::kSoc7FieldNumber,
BatteryTimeToFullStatsReported::kSoc8FieldNumber,
BatteryTimeToFullStatsReported::kSoc9FieldNumber,
};
const int32_t fields_size = std::size(ttf_stats_stats_fields);
const int32_t soc_start = 2; /* after type and range */
int32_t size, range, type, i = 0, soc[fields_size - soc_start] = { 0 };
std::vector<VendorAtomValue> values(fields_size);
VendorAtomValue val;
char ttf_type;
size = sscanf(line, "%c%d:\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d",
&ttf_type, &range, &soc[0], &soc[1], &soc[2], &soc[3],
&soc[4], &soc[5], &soc[6], &soc[7], &soc[8], &soc[9]);
if (size != fields_size)
return;
if (ttf_type == 'T') /* Elap Time */
type = 0;
else if (ttf_type == 'C') /* Charge Counter */
type = 1;
else
return; /* Unknown */
ALOGD("BatteryTTFStats: processed %s", line);
val.set<VendorAtomValue::intValue>(type);
values[ttf_stats_stats_fields[0] - kVendorAtomOffset] = val;
val.set<VendorAtomValue::intValue>(range);
values[ttf_stats_stats_fields[1] - kVendorAtomOffset] = val;
for (i = soc_start; i < fields_size; i++) {
val.set<VendorAtomValue::intValue>(soc[i - soc_start]);
values[ttf_stats_stats_fields[i] - kVendorAtomOffset] = val;
}
VendorAtom event = {.reverseDomainName = "",
.atomId = PixelAtoms::Atom::kBatteryTimeToFullStatsReported,
.values = std::move(values)};
const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
if (!ret.isOk())
ALOGE("Unable to report BatteryTTFStats to Stats service");
}
void BatteryTTFReporter::checkAndReportStats(const std::shared_ptr<IStats> &stats_client) {
int64_t now = getTimeSecs();
if ((report_time_ != 0) && (now - report_time_ < SECONDS_PER_MONTH)) {
ALOGD("Do not upload yet. now: %" PRId64 ", pre: %" PRId64, now, report_time_);
return;
}
bool successStats = reportBatteryTTFStats(stats_client);
if (successStats) {
report_time_ = now;
}
}
} // namespace pixel
} // namespace google
} // namespace hardware
} // namespace android