Merge "zipinfo: support DOS attributes."
diff --git a/TEST_MAPPING b/TEST_MAPPING
index cc1978d..375207b 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -10,7 +10,7 @@
"name": "debuggerd_test"
},
{
- "name": "fs_mgr_unit_test"
+ "name": "CtsFsMgrTestCases"
},
{
"name": "fs_mgr_vendor_overlay_test"
diff --git a/fs_mgr/libsnapshot/partition_cow_creator.cpp b/fs_mgr/libsnapshot/partition_cow_creator.cpp
index eedc1cd..77315b4 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator.cpp
+++ b/fs_mgr/libsnapshot/partition_cow_creator.cpp
@@ -17,8 +17,9 @@
#include <math.h>
#include <android-base/logging.h>
-
#include <android/snapshot/snapshot.pb.h>
+
+#include "dm_snapshot_internals.h"
#include "utility.h"
using android::dm::kSectorSize;
@@ -33,13 +34,6 @@
namespace android {
namespace snapshot {
-// Round |d| up to a multiple of |block_size|.
-static uint64_t RoundUp(double d, uint64_t block_size) {
- uint64_t ret = ((uint64_t)ceil(d) + block_size - 1) / block_size * block_size;
- CHECK(ret >= d) << "Can't round " << d << " up to a multiple of " << block_size;
- return ret;
-}
-
// Intersect two linear extents. If no intersection, return an extent with length 0.
static std::unique_ptr<Extent> Intersect(Extent* target_extent, Extent* existing_extent) {
// Convert target_extent and existing_extent to linear extents. Zero extents
@@ -68,33 +62,58 @@
return false;
}
-std::optional<uint64_t> PartitionCowCreator::GetCowSize(uint64_t snapshot_size) {
- // TODO: Use |operations|. to determine a minimum COW size.
- // kCowEstimateFactor is good for prototyping but we can't use that in production.
- static constexpr double kCowEstimateFactor = 1.05;
- auto cow_size = RoundUp(snapshot_size * kCowEstimateFactor, kDefaultBlockSize);
- return cow_size;
+uint64_t PartitionCowCreator::GetCowSize() {
+ // WARNING: The origin partition should be READ-ONLY
+ const uint64_t logical_block_size = current_metadata->logical_block_size();
+ const unsigned int sectors_per_block = logical_block_size / kSectorSize;
+ DmSnapCowSizeCalculator sc(kSectorSize, kSnapshotChunkSize);
+
+ if (operations == nullptr) return sc.cow_size_bytes();
+
+ for (const auto& iop : *operations) {
+ for (const auto& de : iop.dst_extents()) {
+ // Skip if no blocks are written
+ if (de.num_blocks() == 0) continue;
+
+ // Flag all the blocks that were written
+ const auto block_boundary = de.start_block() + de.num_blocks();
+ for (auto b = de.start_block(); b < block_boundary; ++b) {
+ for (unsigned int s = 0; s < sectors_per_block; ++s) {
+ const auto sector_id = b * sectors_per_block + s;
+ sc.WriteSector(sector_id);
+ }
+ }
+ }
+ }
+
+ return sc.cow_size_bytes();
}
std::optional<PartitionCowCreator::Return> PartitionCowCreator::Run() {
CHECK(current_metadata->GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME &&
target_metadata->GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME);
- uint64_t logical_block_size = current_metadata->logical_block_size();
+ const uint64_t logical_block_size = current_metadata->logical_block_size();
CHECK(logical_block_size != 0 && !(logical_block_size & (logical_block_size - 1)))
<< "logical_block_size is not power of 2";
Return ret;
ret.snapshot_status.set_name(target_partition->name());
ret.snapshot_status.set_device_size(target_partition->size());
-
- // TODO(b/141889746): Optimize by using a smaller snapshot. Some ranges in target_partition
- // may be written directly.
ret.snapshot_status.set_snapshot_size(target_partition->size());
- auto cow_size = GetCowSize(ret.snapshot_status.snapshot_size());
- if (!cow_size.has_value()) return std::nullopt;
-
+ // Being the COW partition virtual, its size doesn't affect the storage
+ // memory that will be occupied by the target.
+ // The actual storage space is affected by the COW file, whose size depends
+ // on the chunks that diverged between |current| and |target|.
+ // If the |target| partition is bigger than |current|, the data that is
+ // modified outside of |current| can be written directly to |current|.
+ // This because the data that will be written outside of |current| would
+ // not invalidate any useful information of |current|, thus:
+ // - if the snapshot is accepted for merge, this data would be already at
+ // the right place and should not be copied;
+ // - in the unfortunate case of the snapshot to be discarded, the regions
+ // modified by this data can be set as free regions and reused.
// Compute regions that are free in both current and target metadata. These are the regions
// we can use for COW partition.
auto target_free_regions = target_metadata->GetFreeRegions();
@@ -102,13 +121,15 @@
auto free_regions = Interval::Intersect(target_free_regions, current_free_regions);
uint64_t free_region_length = 0;
for (const auto& interval : free_regions) {
- free_region_length += interval.length() * kSectorSize;
+ free_region_length += interval.length();
}
+ free_region_length *= kSectorSize;
LOG(INFO) << "Remaining free space for COW: " << free_region_length << " bytes";
+ auto cow_size = GetCowSize();
// Compute the COW partition size.
- uint64_t cow_partition_size = std::min(*cow_size, free_region_length);
+ uint64_t cow_partition_size = std::min(cow_size, free_region_length);
// Round it down to the nearest logical block. Logical partitions must be a multiple
// of logical blocks.
cow_partition_size &= ~(logical_block_size - 1);
@@ -116,8 +137,7 @@
// Assign cow_partition_usable_regions to indicate what regions should the COW partition uses.
ret.cow_partition_usable_regions = std::move(free_regions);
- // The rest of the COW space is allocated on ImageManager.
- uint64_t cow_file_size = (*cow_size) - ret.snapshot_status.cow_partition_size();
+ auto cow_file_size = cow_size - cow_partition_size;
// Round it up to the nearest sector.
cow_file_size += kSectorSize - 1;
cow_file_size &= ~(kSectorSize - 1);
diff --git a/fs_mgr/libsnapshot/partition_cow_creator.h b/fs_mgr/libsnapshot/partition_cow_creator.h
index 8888f78..d3d186b 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator.h
+++ b/fs_mgr/libsnapshot/partition_cow_creator.h
@@ -60,7 +60,7 @@
private:
bool HasExtent(Partition* p, Extent* e);
- std::optional<uint64_t> GetCowSize(uint64_t snapshot_size);
+ uint64_t GetCowSize();
};
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
index f683f5b..eae6c35 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
+++ b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
@@ -14,12 +14,14 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <libdm/dm.h>
#include <liblp/builder.h>
#include <liblp/property_fetcher.h>
#include "dm_snapshot_internals.h"
#include "partition_cow_creator.h"
#include "test_helpers.h"
+#include "utility.h"
using namespace android::fs_mgr;
@@ -100,6 +102,90 @@
ASSERT_TRUE(ret.has_value());
}
+TEST_F(PartitionCowCreatorTest, CowSize) {
+ using InstallOperation = chromeos_update_engine::InstallOperation;
+ using RepeatedInstallOperationPtr = google::protobuf::RepeatedPtrField<InstallOperation>;
+ using Extent = chromeos_update_engine::Extent;
+
+ constexpr uint64_t initial_size = 50_MiB;
+ constexpr uint64_t final_size = 40_MiB;
+
+ auto builder_a = MetadataBuilder::New(initial_size, 1_KiB, 2);
+ ASSERT_NE(builder_a, nullptr);
+ auto system_a = builder_a->AddPartition("system_a", LP_PARTITION_ATTR_READONLY);
+ ASSERT_NE(system_a, nullptr);
+ ASSERT_TRUE(builder_a->ResizePartition(system_a, final_size));
+
+ auto builder_b = MetadataBuilder::New(initial_size, 1_KiB, 2);
+ ASSERT_NE(builder_b, nullptr);
+ auto system_b = builder_b->AddPartition("system_b", LP_PARTITION_ATTR_READONLY);
+ ASSERT_NE(system_b, nullptr);
+ ASSERT_TRUE(builder_b->ResizePartition(system_b, final_size));
+
+ const uint64_t block_size = builder_b->logical_block_size();
+ const uint64_t chunk_size = kSnapshotChunkSize * dm::kSectorSize;
+ ASSERT_EQ(chunk_size, block_size);
+
+ auto cow_device_size = [](const std::vector<InstallOperation>& iopv, MetadataBuilder* builder_a,
+ MetadataBuilder* builder_b, Partition* system_b) {
+ RepeatedInstallOperationPtr riop(iopv.begin(), iopv.end());
+ PartitionCowCreator creator{.target_metadata = builder_b,
+ .target_suffix = "_b",
+ .target_partition = system_b,
+ .current_metadata = builder_a,
+ .current_suffix = "_a",
+ .operations = &riop};
+
+ auto ret = creator.Run();
+
+ if (ret.has_value()) {
+ return ret->snapshot_status.cow_file_size() + ret->snapshot_status.cow_partition_size();
+ }
+ return std::numeric_limits<uint64_t>::max();
+ };
+
+ std::vector<InstallOperation> iopv;
+ InstallOperation iop;
+ Extent* e;
+
+ // No data written, no operations performed
+ ASSERT_EQ(2 * chunk_size, cow_device_size(iopv, builder_a.get(), builder_b.get(), system_b));
+
+ // No data written
+ e = iop.add_dst_extents();
+ e->set_start_block(0);
+ e->set_num_blocks(0);
+ iopv.push_back(iop);
+ ASSERT_EQ(2 * chunk_size, cow_device_size(iopv, builder_a.get(), builder_b.get(), system_b));
+
+ e = iop.add_dst_extents();
+ e->set_start_block(1);
+ e->set_num_blocks(0);
+ iopv.push_back(iop);
+ ASSERT_EQ(2 * chunk_size, cow_device_size(iopv, builder_a.get(), builder_b.get(), system_b));
+
+ // Fill the first block
+ e = iop.add_dst_extents();
+ e->set_start_block(0);
+ e->set_num_blocks(1);
+ iopv.push_back(iop);
+ ASSERT_EQ(3 * chunk_size, cow_device_size(iopv, builder_a.get(), builder_b.get(), system_b));
+
+ // Fill the second block
+ e = iop.add_dst_extents();
+ e->set_start_block(1);
+ e->set_num_blocks(1);
+ iopv.push_back(iop);
+ ASSERT_EQ(4 * chunk_size, cow_device_size(iopv, builder_a.get(), builder_b.get(), system_b));
+
+ // Jump to 5th block and write 2
+ e = iop.add_dst_extents();
+ e->set_start_block(5);
+ e->set_num_blocks(2);
+ iopv.push_back(iop);
+ ASSERT_EQ(6 * chunk_size, cow_device_size(iopv, builder_a.get(), builder_b.get(), system_b));
+}
+
TEST(DmSnapshotInternals, CowSizeCalculator) {
DmSnapCowSizeCalculator cc(512, 8);
unsigned long int b;
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 2161e5b..5728582 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -784,9 +784,17 @@
}
// Grow all partitions.
- SetSize(sys_, 3788_KiB);
- SetSize(vnd_, 3788_KiB);
- SetSize(prd_, 3788_KiB);
+ constexpr uint64_t partition_size = 3788_KiB;
+ SetSize(sys_, partition_size);
+ SetSize(vnd_, partition_size);
+ SetSize(prd_, partition_size);
+
+ // Create fake install operations to grow the COW device size.
+ for (auto& partition : {sys_, vnd_, prd_}) {
+ auto e = partition->add_operations()->add_dst_extents();
+ e->set_start_block(0);
+ e->set_num_blocks(GetSize(partition) / manifest_.block_size());
+ }
// Execute the update.
ASSERT_TRUE(sm->BeginUpdate());
@@ -949,6 +957,13 @@
ASSERT_TRUE(sm->BeginUpdate());
ASSERT_TRUE(sm->UnmapUpdateSnapshot("sys_b"));
+ // Create fake install operations to grow the COW device size.
+ for (auto& partition : {sys_, vnd_, prd_}) {
+ auto e = partition->add_operations()->add_dst_extents();
+ e->set_start_block(0);
+ e->set_num_blocks(GetSize(partition) / manifest_.block_size());
+ }
+
ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
// Write some data to target partitions.
diff --git a/fs_mgr/libsnapshot/test_helpers.cpp b/fs_mgr/libsnapshot/test_helpers.cpp
index 539c5c5..312fa3e 100644
--- a/fs_mgr/libsnapshot/test_helpers.cpp
+++ b/fs_mgr/libsnapshot/test_helpers.cpp
@@ -140,5 +140,9 @@
partition_update->mutable_new_partition_info()->set_size(size);
}
+uint64_t GetSize(PartitionUpdate* partition_update) {
+ return partition_update->mutable_new_partition_info()->size();
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/test_helpers.h b/fs_mgr/libsnapshot/test_helpers.h
index 5fe701f..0f70afe 100644
--- a/fs_mgr/libsnapshot/test_helpers.h
+++ b/fs_mgr/libsnapshot/test_helpers.h
@@ -141,5 +141,8 @@
// In the update package metadata, set a partition with the given size.
void SetSize(PartitionUpdate* partition_update, uint64_t size);
+// Get partition size from update package metadata.
+uint64_t GetSize(PartitionUpdate* partition_update);
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/tests/Android.bp b/fs_mgr/tests/Android.bp
index 83668e9..4f6ec5a 100644
--- a/fs_mgr/tests/Android.bp
+++ b/fs_mgr/tests/Android.bp
@@ -13,8 +13,21 @@
// limitations under the License.
cc_test {
- name: "fs_mgr_unit_test",
- test_suites: ["device-tests"],
+ name: "CtsFsMgrTestCases",
+ test_suites: [
+ "cts",
+ "device-tests",
+ "vts",
+ ],
+ compile_multilib: "both",
+ multilib: {
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
+ },
shared_libs: [
"libbase",
diff --git a/fs_mgr/tests/AndroidTest.xml b/fs_mgr/tests/AndroidTest.xml
new file mode 100644
index 0000000..91c3fb9
--- /dev/null
+++ b/fs_mgr/tests/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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.
+-->
+<configuration description="Config for CTS fs_mgr test cases">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="systems" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="CtsFsMgrTestCases->/data/local/tmp/CtsFsMgrTestCases" />
+ <option name="append-bitness" value="true" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="CtsFsMgrTestCases" />
+ <option name="runtime-hint" value="65s" />
+ </test>
+</configuration>
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 05607a0..1cbaf45 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -962,3 +962,10 @@
EXPECT_EQ("none5", entry->mount_point);
EXPECT_EQ("/dev/path2", entry->zram_backing_dev_path);
}
+
+TEST(fs_mgr, DefaultFstabContainsUserdata) {
+ Fstab fstab;
+ ASSERT_TRUE(ReadDefaultFstab(&fstab)) << "Failed to read default fstab";
+ ASSERT_NE(nullptr, GetEntryForMountPoint(&fstab, "/data"))
+ << "Default fstab doesn't contain /data entry";
+}
diff --git a/healthd/Android.bp b/healthd/Android.bp
index 4f89bfb..e04f70f 100644
--- a/healthd/Android.bp
+++ b/healthd/Android.bp
@@ -17,6 +17,10 @@
shared_libs: [
"libutils",
"libbase",
+
+ // Need latest HealthInfo definition from headers of this shared
+ // library. Clients don't need to link to this.
+ "android.hardware.health@2.1",
],
header_libs: ["libhealthd_headers"],
export_header_lib_headers: ["libhealthd_headers"],
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 57ed362..9e168e9 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -29,10 +29,12 @@
#include <algorithm>
#include <memory>
+#include <optional>
#include <android-base/file.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
+#include <android/hardware/health/2.1/types.h>
#include <batteryservice/BatteryService.h>
#include <cutils/klog.h>
#include <cutils/properties.h>
@@ -47,97 +49,93 @@
#define MILLION 1.0e6
#define DEFAULT_VBUS_VOLTAGE 5000000
+using HealthInfo_1_0 = android::hardware::health::V1_0::HealthInfo;
+using HealthInfo_2_0 = android::hardware::health::V2_0::HealthInfo;
+using HealthInfo_2_1 = android::hardware::health::V2_1::HealthInfo;
+using android::hardware::health::V1_0::BatteryHealth;
+using android::hardware::health::V1_0::BatteryStatus;
+using android::hardware::health::V2_1::BatteryCapacityLevel;
+
namespace android {
-struct sysfsStringEnumMap {
+template <typename T>
+struct SysfsStringEnumMap {
const char* s;
- int val;
+ T val;
};
-static int mapSysfsString(const char* str,
- struct sysfsStringEnumMap map[]) {
+template <typename T>
+static std::optional<T> mapSysfsString(const char* str, SysfsStringEnumMap<T> map[]) {
for (int i = 0; map[i].s; i++)
if (!strcmp(str, map[i].s))
return map[i].val;
- return -1;
-}
-
-static void initBatteryProperties(BatteryProperties* props) {
- props->chargerAcOnline = false;
- props->chargerUsbOnline = false;
- props->chargerWirelessOnline = false;
- props->maxChargingCurrent = 0;
- props->maxChargingVoltage = 0;
- props->batteryStatus = BATTERY_STATUS_UNKNOWN;
- props->batteryHealth = BATTERY_HEALTH_UNKNOWN;
- props->batteryPresent = false;
- props->batteryLevel = 0;
- props->batteryVoltage = 0;
- props->batteryTemperature = 0;
- props->batteryCurrent = 0;
- props->batteryCycleCount = 0;
- props->batteryFullCharge = 0;
- props->batteryChargeCounter = 0;
- props->batteryTechnology.clear();
+ return std::nullopt;
}
BatteryMonitor::BatteryMonitor()
: mHealthdConfig(nullptr),
mBatteryDevicePresent(false),
mBatteryFixedCapacity(0),
- mBatteryFixedTemperature(0) {
- initBatteryProperties(&props);
+ mBatteryFixedTemperature(0),
+ mHealthInfo(std::make_unique<HealthInfo_2_1>()) {}
+
+BatteryMonitor::~BatteryMonitor() {}
+
+const HealthInfo_1_0& BatteryMonitor::getHealthInfo_1_0() const {
+ return getHealthInfo_2_0().legacy;
}
-struct BatteryProperties getBatteryProperties(BatteryMonitor* batteryMonitor) {
- return batteryMonitor->props;
+const HealthInfo_2_0& BatteryMonitor::getHealthInfo_2_0() const {
+ return getHealthInfo_2_1().legacy;
}
-int BatteryMonitor::getBatteryStatus(const char* status) {
- int ret;
- struct sysfsStringEnumMap batteryStatusMap[] = {
- { "Unknown", BATTERY_STATUS_UNKNOWN },
- { "Charging", BATTERY_STATUS_CHARGING },
- { "Discharging", BATTERY_STATUS_DISCHARGING },
- { "Not charging", BATTERY_STATUS_NOT_CHARGING },
- { "Full", BATTERY_STATUS_FULL },
- { NULL, 0 },
+const HealthInfo_2_1& BatteryMonitor::getHealthInfo_2_1() const {
+ return *mHealthInfo;
+}
+
+BatteryStatus getBatteryStatus(const char* status) {
+ static SysfsStringEnumMap<BatteryStatus> batteryStatusMap[] = {
+ {"Unknown", BatteryStatus::UNKNOWN},
+ {"Charging", BatteryStatus::CHARGING},
+ {"Discharging", BatteryStatus::DISCHARGING},
+ {"Not charging", BatteryStatus::NOT_CHARGING},
+ {"Full", BatteryStatus::FULL},
+ {NULL, BatteryStatus::UNKNOWN},
};
- ret = mapSysfsString(status, batteryStatusMap);
- if (ret < 0) {
+ auto ret = mapSysfsString(status, batteryStatusMap);
+ if (!ret) {
KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status);
- ret = BATTERY_STATUS_UNKNOWN;
+ *ret = BatteryStatus::UNKNOWN;
}
- return ret;
+ return *ret;
}
-int BatteryMonitor::getBatteryHealth(const char* status) {
- int ret;
- struct sysfsStringEnumMap batteryHealthMap[] = {
- { "Unknown", BATTERY_HEALTH_UNKNOWN },
- { "Good", BATTERY_HEALTH_GOOD },
- { "Overheat", BATTERY_HEALTH_OVERHEAT },
- { "Dead", BATTERY_HEALTH_DEAD },
- { "Over voltage", BATTERY_HEALTH_OVER_VOLTAGE },
- { "Unspecified failure", BATTERY_HEALTH_UNSPECIFIED_FAILURE },
- { "Cold", BATTERY_HEALTH_COLD },
- // battery health values from JEITA spec
- { "Warm", BATTERY_HEALTH_GOOD },
- { "Cool", BATTERY_HEALTH_GOOD },
- { "Hot", BATTERY_HEALTH_OVERHEAT },
- { NULL, 0 },
+BatteryHealth getBatteryHealth(const char* status) {
+ static SysfsStringEnumMap<BatteryHealth> batteryHealthMap[] = {
+ {"Unknown", BatteryHealth::UNKNOWN},
+ {"Good", BatteryHealth::GOOD},
+ {"Overheat", BatteryHealth::OVERHEAT},
+ {"Dead", BatteryHealth::DEAD},
+ {"Over voltage", BatteryHealth::OVER_VOLTAGE},
+ {"Unspecified failure", BatteryHealth::UNSPECIFIED_FAILURE},
+ {"Cold", BatteryHealth::COLD},
+ // battery health values from JEITA spec
+ {"Warm", BatteryHealth::GOOD},
+ {"Cool", BatteryHealth::GOOD},
+ {"Hot", BatteryHealth::OVERHEAT},
+ {NULL, BatteryHealth::UNKNOWN},
};
- ret = mapSysfsString(status, batteryHealthMap);
- if (ret < 0) {
+ auto ret = mapSysfsString(status, batteryHealthMap);
+ if (!ret) {
KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status);
- ret = BATTERY_HEALTH_UNKNOWN;
+ *ret = BatteryHealth::UNKNOWN;
}
- return ret;
+ return *ret;
}
int BatteryMonitor::readFromFile(const String8& path, std::string* buf) {
@@ -148,35 +146,34 @@
}
BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) {
- std::string buf;
- int ret;
- struct sysfsStringEnumMap supplyTypeMap[] = {
- { "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN },
- { "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY },
- { "UPS", ANDROID_POWER_SUPPLY_TYPE_AC },
- { "Mains", ANDROID_POWER_SUPPLY_TYPE_AC },
- { "USB", ANDROID_POWER_SUPPLY_TYPE_USB },
- { "USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC },
- { "USB_HVDCP", ANDROID_POWER_SUPPLY_TYPE_AC },
- { "USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC },
- { "USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC },
- { "USB_C", ANDROID_POWER_SUPPLY_TYPE_AC },
- { "USB_PD", ANDROID_POWER_SUPPLY_TYPE_AC },
- { "USB_PD_DRP", ANDROID_POWER_SUPPLY_TYPE_USB },
- { "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS },
- { NULL, 0 },
+ static SysfsStringEnumMap<int> supplyTypeMap[] = {
+ {"Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN},
+ {"Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY},
+ {"UPS", ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"Mains", ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"USB", ANDROID_POWER_SUPPLY_TYPE_USB},
+ {"USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"USB_HVDCP", ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"USB_C", ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"USB_PD", ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"USB_PD_DRP", ANDROID_POWER_SUPPLY_TYPE_USB},
+ {"Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS},
+ {NULL, 0},
};
+ std::string buf;
if (readFromFile(path, &buf) <= 0)
return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
- ret = mapSysfsString(buf.c_str(), supplyTypeMap);
+ auto ret = mapSysfsString(buf.c_str(), supplyTypeMap);
if (ret < 0) {
KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf.c_str());
- ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
+ *ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
}
- return static_cast<BatteryMonitor::PowerSupplyType>(ret);
+ return static_cast<BatteryMonitor::PowerSupplyType>(*ret);
}
bool BatteryMonitor::getBooleanField(const String8& path) {
@@ -201,7 +198,9 @@
}
void BatteryMonitor::updateValues(void) {
- initBatteryProperties(&props);
+ *mHealthInfo = HealthInfo_2_1{};
+
+ HealthInfo_1_0& props = mHealthInfo->legacy.legacy;
if (!mHealthdConfig->batteryPresentPath.isEmpty())
props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
@@ -225,6 +224,15 @@
if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
props.batteryChargeCounter = getIntField(mHealthdConfig->batteryChargeCounterPath);
+ if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty())
+ mHealthInfo->legacy.batteryCurrentAverage =
+ getIntField(mHealthdConfig->batteryCurrentAvgPath);
+
+ // TODO(b/142260281): Retrieve these values correctly.
+ mHealthInfo->batteryCapacityLevel = BatteryCapacityLevel::UNKNOWN;
+ mHealthInfo->batteryChargeTimeToFullNowSeconds = 0;
+ mHealthInfo->batteryFullCapacityUah = props.batteryFullCharge;
+
props.batteryTemperature = mBatteryFixedTemperature ?
mBatteryFixedTemperature :
getIntField(mHealthdConfig->batteryTemperaturePath);
@@ -292,6 +300,7 @@
void BatteryMonitor::logValues(void) {
char dmesgline[256];
size_t len;
+ const HealthInfo_1_0& props = mHealthInfo->legacy.legacy;
if (props.batteryPresent) {
snprintf(dmesgline, sizeof(dmesgline), "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
props.batteryLevel, props.batteryVoltage, props.batteryTemperature < 0 ? "-" : "",
@@ -325,18 +334,19 @@
}
bool BatteryMonitor::isChargerOnline() {
+ const HealthInfo_1_0& props = mHealthInfo->legacy.legacy;
return props.chargerAcOnline | props.chargerUsbOnline |
props.chargerWirelessOnline;
}
int BatteryMonitor::getChargeStatus() {
- int result = BATTERY_STATUS_UNKNOWN;
+ BatteryStatus result = BatteryStatus::UNKNOWN;
if (!mHealthdConfig->batteryStatusPath.isEmpty()) {
std::string buf;
if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
result = getBatteryStatus(buf.c_str());
}
- return result;
+ return static_cast<int>(result);
}
status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
@@ -409,6 +419,7 @@
void BatteryMonitor::dumpState(int fd) {
int v;
char vs[128];
+ const HealthInfo_1_0& props = mHealthInfo->legacy.legacy;
snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d current_max: %d voltage_max: %d\n",
props.chargerAcOnline, props.chargerUsbOnline,
diff --git a/healthd/include/healthd/BatteryMonitor.h b/healthd/include/healthd/BatteryMonitor.h
index 0fd3824..d41a374 100644
--- a/healthd/include/healthd/BatteryMonitor.h
+++ b/healthd/include/healthd/BatteryMonitor.h
@@ -17,6 +17,8 @@
#ifndef HEALTHD_BATTERYMONITOR_H
#define HEALTHD_BATTERYMONITOR_H
+#include <memory>
+
#include <batteryservice/BatteryService.h>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -24,6 +26,19 @@
#include <healthd/healthd.h>
namespace android {
+namespace hardware {
+namespace health {
+namespace V1_0 {
+struct HealthInfo;
+} // namespace V1_0
+namespace V2_0 {
+struct HealthInfo;
+} // namespace V2_0
+namespace V2_1 {
+struct HealthInfo;
+} // namespace V2_1
+} // namespace health
+} // namespace hardware
class BatteryMonitor {
public:
@@ -37,11 +52,15 @@
};
BatteryMonitor();
+ ~BatteryMonitor();
void init(struct healthd_config *hc);
int getChargeStatus();
status_t getProperty(int id, struct BatteryProperty *val);
void dumpState(int fd);
- friend struct BatteryProperties getBatteryProperties(BatteryMonitor* batteryMonitor);
+
+ const android::hardware::health::V1_0::HealthInfo& getHealthInfo_1_0() const;
+ const android::hardware::health::V2_0::HealthInfo& getHealthInfo_2_0() const;
+ const android::hardware::health::V2_1::HealthInfo& getHealthInfo_2_1() const;
void updateValues(void);
void logValues(void);
@@ -53,10 +72,8 @@
bool mBatteryDevicePresent;
int mBatteryFixedCapacity;
int mBatteryFixedTemperature;
- struct BatteryProperties props;
+ std::unique_ptr<android::hardware::health::V2_1::HealthInfo> mHealthInfo;
- int getBatteryStatus(const char* status);
- int getBatteryHealth(const char* status);
int readFromFile(const String8& path, std::string* buf);
PowerSupplyType readPowerSupplyType(const String8& path);
bool getBooleanField(const String8& path);