Merge "Grant wmtrace access to platform_app:systemui"
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index 28154a7..a05bcec 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -303,86 +303,8 @@
   }
 }
 
-static void print_main_thread(CallbackType callback, const Tombstone& tombstone,
-                              const Thread& thread) {
+static void print_memory_maps(CallbackType callback, const Tombstone& tombstone) {
   int word_size = pointer_width(tombstone);
-  print_thread_header(callback, tombstone, thread, true);
-
-  const Signal& signal_info = tombstone.signal_info();
-  std::string sender_desc;
-
-  if (signal_info.has_sender()) {
-    sender_desc =
-        StringPrintf(" from pid %d, uid %d", signal_info.sender_pid(), signal_info.sender_uid());
-  }
-
-  if (!tombstone.has_signal_info()) {
-    CBL("signal information missing");
-  } else {
-    std::string fault_addr_desc;
-    if (signal_info.has_fault_address()) {
-      fault_addr_desc = StringPrintf("0x%0*" PRIx64, 2 * word_size, signal_info.fault_address());
-    } else {
-      fault_addr_desc = "--------";
-    }
-
-    CBL("signal %d (%s), code %d (%s%s), fault addr %s", signal_info.number(),
-        signal_info.name().c_str(), signal_info.code(), signal_info.code_name().c_str(),
-        sender_desc.c_str(), fault_addr_desc.c_str());
-  }
-
-  if (tombstone.causes_size() == 1) {
-    CBL("Cause: %s", tombstone.causes(0).human_readable().c_str());
-  }
-
-  if (!tombstone.abort_message().empty()) {
-    CBL("Abort message: '%s'", tombstone.abort_message().c_str());
-  }
-
-  print_thread_registers(callback, tombstone, thread, true);
-  print_thread_backtrace(callback, tombstone, thread, true);
-
-  if (tombstone.causes_size() > 1) {
-    CBS("");
-    CBL("Note: multiple potential causes for this crash were detected, listing them in decreasing "
-        "order of likelihood.");
-  }
-
-  for (const Cause& cause : tombstone.causes()) {
-    if (tombstone.causes_size() > 1) {
-      CBS("");
-      CBL("Cause: %s", cause.human_readable().c_str());
-    }
-
-    if (cause.has_memory_error() && cause.memory_error().has_heap()) {
-      const HeapObject& heap_object = cause.memory_error().heap();
-
-      if (heap_object.deallocation_backtrace_size() != 0) {
-        CBS("");
-        CBL("deallocated by thread %" PRIu64 ":", heap_object.deallocation_tid());
-        print_backtrace(callback, tombstone, heap_object.deallocation_backtrace(), true);
-      }
-
-      if (heap_object.allocation_backtrace_size() != 0) {
-        CBS("");
-        CBL("allocated by thread %" PRIu64 ":", heap_object.allocation_tid());
-        print_backtrace(callback, tombstone, heap_object.allocation_backtrace(), true);
-      }
-    }
-  }
-
-  print_tag_dump(callback, tombstone);
-
-  print_thread_memory_dump(callback, tombstone, thread);
-
-  CBS("");
-
-  // No memory maps to print.
-  if (tombstone.memory_mappings().empty()) {
-    CBS("No memory maps found");
-    return;
-  }
-
   const auto format_pointer = [word_size](uint64_t ptr) -> std::string {
     if (word_size == 8) {
       uint64_t top = ptr >> 32;
@@ -397,6 +319,7 @@
       StringPrintf("memory map (%d %s):", tombstone.memory_mappings().size(),
                    tombstone.memory_mappings().size() == 1 ? "entry" : "entries");
 
+  const Signal& signal_info = tombstone.signal_info();
   bool has_fault_address = signal_info.has_fault_address();
   uint64_t fault_address = untag_address(signal_info.fault_address());
   bool preamble_printed = false;
@@ -456,6 +379,106 @@
   }
 }
 
+static void print_main_thread(CallbackType callback, const Tombstone& tombstone,
+                              const Thread& thread) {
+  print_thread_header(callback, tombstone, thread, true);
+
+  const Signal& signal_info = tombstone.signal_info();
+  std::string sender_desc;
+
+  if (signal_info.has_sender()) {
+    sender_desc =
+        StringPrintf(" from pid %d, uid %d", signal_info.sender_pid(), signal_info.sender_uid());
+  }
+
+  bool is_async_mte_crash = false;
+  bool is_mte_crash = false;
+  if (!tombstone.has_signal_info()) {
+    CBL("signal information missing");
+  } else {
+    std::string fault_addr_desc;
+    if (signal_info.has_fault_address()) {
+      fault_addr_desc =
+          StringPrintf("0x%0*" PRIx64, 2 * pointer_width(tombstone), signal_info.fault_address());
+    } else {
+      fault_addr_desc = "--------";
+    }
+
+    CBL("signal %d (%s), code %d (%s%s), fault addr %s", signal_info.number(),
+        signal_info.name().c_str(), signal_info.code(), signal_info.code_name().c_str(),
+        sender_desc.c_str(), fault_addr_desc.c_str());
+#ifdef SEGV_MTEAERR
+    is_async_mte_crash = signal_info.number() == SIGSEGV && signal_info.code() == SEGV_MTEAERR;
+    is_mte_crash = is_async_mte_crash ||
+                   (signal_info.number() == SIGSEGV && signal_info.code() == SEGV_MTESERR);
+#endif
+  }
+
+  if (tombstone.causes_size() == 1) {
+    CBL("Cause: %s", tombstone.causes(0).human_readable().c_str());
+  }
+
+  if (!tombstone.abort_message().empty()) {
+    CBL("Abort message: '%s'", tombstone.abort_message().c_str());
+  }
+
+  print_thread_registers(callback, tombstone, thread, true);
+  if (is_async_mte_crash) {
+    CBL("Note: This crash is a delayed async MTE crash. Memory corruption has occurred");
+    CBL("      in this process. The stack trace below is the first system call or context");
+    CBL("      switch that was executed after the memory corruption happened.");
+  }
+  print_thread_backtrace(callback, tombstone, thread, true);
+
+  if (tombstone.causes_size() > 1) {
+    CBS("");
+    CBL("Note: multiple potential causes for this crash were detected, listing them in decreasing "
+        "order of likelihood.");
+  }
+
+  for (const Cause& cause : tombstone.causes()) {
+    if (tombstone.causes_size() > 1) {
+      CBS("");
+      CBL("Cause: %s", cause.human_readable().c_str());
+    }
+
+    if (cause.has_memory_error() && cause.memory_error().has_heap()) {
+      const HeapObject& heap_object = cause.memory_error().heap();
+
+      if (heap_object.deallocation_backtrace_size() != 0) {
+        CBS("");
+        CBL("deallocated by thread %" PRIu64 ":", heap_object.deallocation_tid());
+        print_backtrace(callback, tombstone, heap_object.deallocation_backtrace(), true);
+      }
+
+      if (heap_object.allocation_backtrace_size() != 0) {
+        CBS("");
+        CBL("allocated by thread %" PRIu64 ":", heap_object.allocation_tid());
+        print_backtrace(callback, tombstone, heap_object.allocation_backtrace(), true);
+      }
+    }
+  }
+
+  print_tag_dump(callback, tombstone);
+
+  if (is_mte_crash) {
+    CBS("");
+    CBL("Learn more about MTE reports: "
+        "https://source.android.com/docs/security/test/memory-safety/mte-reports");
+  }
+
+  print_thread_memory_dump(callback, tombstone, thread);
+
+  CBS("");
+
+  // No memory maps to print.
+  if (!tombstone.memory_mappings().empty()) {
+    print_memory_maps(callback, tombstone);
+  } else {
+    CBS("No memory maps found");
+  }
+}
+
 void print_logs(CallbackType callback, const Tombstone& tombstone, int tail) {
   for (const auto& buffer : tombstone.log_buffers()) {
     if (tail) {
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index 765174b..a801900 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -170,7 +170,7 @@
         "android.hardware.fastboot@1.1",
         "android.hardware.fastboot-V1-ndk",
         "android.hardware.health@2.0",
-        "android.hardware.health-V1-ndk",
+        "android.hardware.health-V2-ndk",
         "libasyncio",
         "libbase",
         "libbinder_ndk",
diff --git a/fs_mgr/TEST_MAPPING b/fs_mgr/TEST_MAPPING
index 2b5e337..b6710d5 100644
--- a/fs_mgr/TEST_MAPPING
+++ b/fs_mgr/TEST_MAPPING
@@ -22,6 +22,12 @@
       "name": "vts_libsnapshot_test"
     },
     {
+      "name": "vab_legacy_tests"
+    },
+    {
+      "name": "vabc_legacy_tests"
+    },
+    {
       "name": "libsnapshot_fuzzer_test"
     },
     {
@@ -37,6 +43,12 @@
     },
     {
       "name": "vts_libsnapshot_test"
+    },
+    {
+      "name": "vab_legacy_tests"
+    },
+    {
+      "name": "vabc_legacy_tests"
     }
   ]
 }
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 46f54cc..46cdb62 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -33,7 +33,7 @@
  */
 #define FS_MGR_CHECK(x) CHECK(x) << "in libfs_mgr "
 
-#define FS_MGR_TAG "[libfs_mgr]"
+#define FS_MGR_TAG "[libfs_mgr] "
 
 // Logs a message to kernel
 #define LINFO    LOG(INFO) << FS_MGR_TAG
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index 2bb9035..5cc0346 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -90,19 +90,3 @@
         min_shipping_api_level: 29,
     },
 }
-
-cc_fuzz {
-    name: "dm_linear_table_fuzzer",
-    defaults: ["fs_mgr_defaults"],
-    srcs: [
-        "dm_linear_fuzzer.cpp",
-        "test_util.cpp",
-    ],
-    static_libs: [
-        "libdm",
-        "libbase",
-        "libext2_uuid",
-        "libfs_mgr",
-        "liblog",
-    ],
-}
diff --git a/fs_mgr/libdm/dm_linear_fuzzer.cpp b/fs_mgr/libdm/dm_linear_fuzzer.cpp
deleted file mode 100644
index 8462901..0000000
--- a/fs_mgr/libdm/dm_linear_fuzzer.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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.
- */
-
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
-#include <chrono>
-
-#include <android-base/file.h>
-#include <android-base/unique_fd.h>
-#include <libdm/dm_table.h>
-#include <libdm/loop_control.h>
-
-#include "test_util.h"
-
-using namespace android;
-using namespace android::base;
-using namespace android::dm;
-using namespace std;
-using namespace std::chrono_literals;
-
-/*
- * This test aims at making the library crash, so these functions are not
- * really useful.
- * Keeping them here for future use.
- */
-template <class T, class C>
-void ASSERT_EQ(const T& /*a*/, const C& /*b*/) {
-    // if (a != b) {}
-}
-
-template <class T>
-void ASSERT_FALSE(const T& /*a*/) {
-    // if (a) {}
-}
-
-template <class T, class C>
-void ASSERT_GE(const T& /*a*/, const C& /*b*/) {
-    // if (a < b) {}
-}
-
-template <class T, class C>
-void ASSERT_NE(const T& /*a*/, const C& /*b*/) {
-    // if (a == b) {}
-}
-
-template <class T>
-void ASSERT_TRUE(const T& /*a*/) {
-    // if (!a) {}
-}
-
-template <class T, class C>
-void EXPECT_EQ(const T& a, const C& b) {
-    ASSERT_EQ(a, b);
-}
-
-template <class T>
-void EXPECT_TRUE(const T& a) {
-    ASSERT_TRUE(a);
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-    uint64_t val[6];
-
-    if (size != sizeof(val)) {
-        return 0;
-    }
-
-    memcpy(&val, &data[0], sizeof(*val));
-
-    unique_fd tmp1(CreateTempFile("file_1", 4096));
-    ASSERT_GE(tmp1, 0);
-    unique_fd tmp2(CreateTempFile("file_2", 4096));
-    ASSERT_GE(tmp2, 0);
-
-    LoopDevice loop_a(tmp1, 10s);
-    ASSERT_TRUE(loop_a.valid());
-    LoopDevice loop_b(tmp2, 10s);
-    ASSERT_TRUE(loop_b.valid());
-
-    // Define a 2-sector device, with each sector mapping to the first sector
-    // of one of our loop devices.
-    DmTable table;
-    ASSERT_TRUE(table.Emplace<DmTargetLinear>(val[0], val[1], loop_a.device(), val[2]));
-    ASSERT_TRUE(table.Emplace<DmTargetLinear>(val[3], val[4], loop_b.device(), val[5]));
-    ASSERT_TRUE(table.valid());
-    ASSERT_EQ(2u, table.num_sectors());
-
-    TempDevice dev("libdm-test-dm-linear", table);
-    ASSERT_TRUE(dev.valid());
-    ASSERT_FALSE(dev.path().empty());
-
-    auto& dm = DeviceMapper::Instance();
-
-    dev_t dev_number;
-    ASSERT_TRUE(dm.GetDeviceNumber(dev.name(), &dev_number));
-    ASSERT_NE(dev_number, 0);
-
-    std::string dev_string;
-    ASSERT_TRUE(dm.GetDeviceString(dev.name(), &dev_string));
-    ASSERT_FALSE(dev_string.empty());
-
-    // Test GetTableStatus.
-    vector<DeviceMapper::TargetInfo> targets;
-    ASSERT_TRUE(dm.GetTableStatus(dev.name(), &targets));
-    ASSERT_EQ(targets.size(), 2);
-    EXPECT_EQ(strcmp(targets[0].spec.target_type, "linear"), 0);
-    EXPECT_TRUE(targets[0].data.empty());
-    EXPECT_EQ(targets[0].spec.sector_start, 0);
-    EXPECT_EQ(targets[0].spec.length, 1);
-    EXPECT_EQ(strcmp(targets[1].spec.target_type, "linear"), 0);
-    EXPECT_TRUE(targets[1].data.empty());
-    EXPECT_EQ(targets[1].spec.sector_start, 1);
-    EXPECT_EQ(targets[1].spec.length, 1);
-
-    // Test GetTargetType().
-    EXPECT_EQ(DeviceMapper::GetTargetType(targets[0].spec), std::string{"linear"});
-    EXPECT_EQ(DeviceMapper::GetTargetType(targets[1].spec), std::string{"linear"});
-
-    // Normally the TestDevice destructor would delete this, but at least one
-    // test should ensure that device deletion works.
-    ASSERT_TRUE(dev.Destroy());
-
-    return 0;
-}
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index 4448d35..788cf51 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -19,6 +19,7 @@
 #include <stdio.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
+#include <sys/utsname.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -692,7 +693,17 @@
 }
 
 TEST(libdm, UeventAfterLoadTable) {
-    static const char* kDeviceName = "libmd-test-uevent-load-table";
+    static const char* kDeviceName = "libdm-test-uevent-load-table";
+
+    struct utsname u;
+    ASSERT_EQ(uname(&u), 0);
+
+    unsigned int major, minor;
+    ASSERT_EQ(sscanf(u.release, "%u.%u", &major, &minor), 2);
+
+    if (major < 5 || (major == 5 && minor < 15)) {
+        GTEST_SKIP() << "Skipping test on kernel < 5.15";
+    }
 
     DeviceMapper& dm = DeviceMapper::Instance();
     ASSERT_TRUE(dm.CreateEmptyDevice(kDeviceName));
diff --git a/fs_mgr/libfs_avb/util.h b/fs_mgr/libfs_avb/util.h
index 427ab7c..29d1e9c 100644
--- a/fs_mgr/libfs_avb/util.h
+++ b/fs_mgr/libfs_avb/util.h
@@ -31,7 +31,7 @@
 using android::base::ErrnoError;
 using android::base::Result;
 
-#define FS_AVB_TAG "[libfs_avb]"
+#define FS_AVB_TAG "[libfs_avb] "
 
 // Logs a message to kernel
 #define LINFO LOG(INFO) << FS_AVB_TAG
diff --git a/fs_mgr/liblp/utility.h b/fs_mgr/liblp/utility.h
index aa3a6a0..32a59a5 100644
--- a/fs_mgr/liblp/utility.h
+++ b/fs_mgr/liblp/utility.h
@@ -30,7 +30,7 @@
 
 #include "liblp/liblp.h"
 
-#define LP_TAG "[liblp]"
+#define LP_TAG "[liblp] "
 #define LWARN LOG(WARNING) << LP_TAG
 #define LINFO LOG(INFO) << LP_TAG
 #define LERROR LOG(ERROR) << LP_TAG
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index 2165961..c2f435f 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -269,14 +269,19 @@
     defaults: ["libsnapshot_test_defaults", "libsnapshot_hal_deps"],
 }
 
-sh_test {
-    name: "run_snapshot_tests",
-    src: "run_snapshot_tests.sh",
-    test_suites: [
-        "device-tests",
+cc_test {
+    name: "vab_legacy_tests",
+    defaults: ["libsnapshot_test_defaults", "libsnapshot_hal_deps"],
+    cppflags: [
+        "-DLIBSNAPSHOT_TEST_VAB_LEGACY",
     ],
-    required: [
-        "vts_libsnapshot_test",
+}
+
+cc_test {
+    name: "vabc_legacy_tests",
+    defaults: ["libsnapshot_test_defaults", "libsnapshot_hal_deps"],
+    cppflags: [
+        "-DLIBSNAPSHOT_TEST_VABC_LEGACY",
     ],
 }
 
diff --git a/fs_mgr/libsnapshot/run_snapshot_tests.sh b/fs_mgr/libsnapshot/run_snapshot_tests.sh
deleted file mode 100644
index b03a4e0..0000000
--- a/fs_mgr/libsnapshot/run_snapshot_tests.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/system/bin/sh
-
-# Detect host or AOSP.
-getprop ro.build.version.sdk > /dev/null 2>&1
-if [ $? -eq 0 ]; then
-    cmd_prefix=""
-    local_root=""
-else
-    cmd_prefix="adb shell"
-    local_root="${ANDROID_PRODUCT_OUT}"
-    set -e
-    set -x
-    adb root
-    adb sync data
-    set +x
-    set +e
-fi
-
-testpath64="/data/nativetest64/vts_libsnapshot_test/vts_libsnapshot_test"
-testpath32="/data/nativetest/vts_libsnapshot_test/vts_libsnapshot_test"
-if [ -f "${local_root}/${testpath64}" ]; then
-    testpath="${testpath64}"
-elif [ -f "${local_root}/${testpath32}" ]; then
-    testpath="${testpath32}"
-else
-    echo "ERROR: vts_libsnapshot_test not found." 1>&2
-    echo "Make sure to build vts_libsnapshot_test or snapshot_tests first." 1>&2
-    exit 1
-fi
-
-# Verbose, error on failure.
-set -x
-set -e
-
-time ${cmd_prefix} ${testpath}
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 2c01cf6..4014380 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -53,7 +53,15 @@
 #include <libsnapshot/mock_device_info.h>
 #include <libsnapshot/mock_snapshot.h>
 
-DEFINE_string(force_mode, "",
+#if defined(LIBSNAPSHOT_TEST_VAB_LEGACY)
+#define DEFAULT_MODE "vab-legacy"
+#elif defined(LIBSNAPSHOT_TEST_VABC_LEGACY)
+#define DEFAULT_MODE "vabc-legacy"
+#else
+#define DEFAULT_MODE ""
+#endif
+
+DEFINE_string(force_mode, DEFAULT_MODE,
               "Force testing older modes (vab-legacy, vabc-legacy) ignoring device config.");
 DEFINE_string(force_iouring_disable, "",
               "Force testing mode (iouring_disabled) - disable io_uring");
diff --git a/fs_mgr/libvbmeta/utility.h b/fs_mgr/libvbmeta/utility.h
index 91db0ad..ab9828d 100644
--- a/fs_mgr/libvbmeta/utility.h
+++ b/fs_mgr/libvbmeta/utility.h
@@ -19,7 +19,7 @@
 #include <android-base/logging.h>
 #include <android-base/result.h>
 
-#define VBMETA_TAG "[libvbmeta]"
+#define VBMETA_TAG "[libvbmeta] "
 #define LWARN LOG(WARNING) << VBMETA_TAG
 #define LINFO LOG(INFO) << VBMETA_TAG
 #define LERROR LOG(ERROR) << VBMETA_TAG
diff --git a/healthd/Android.bp b/healthd/Android.bp
index 76b6ad0..235303f 100644
--- a/healthd/Android.bp
+++ b/healthd/Android.bp
@@ -4,7 +4,6 @@
 
 cc_defaults {
     name: "libbatterymonitor_defaults",
-    srcs: ["BatteryMonitor.cpp"],
     cflags: ["-Wall", "-Werror"],
     vendor_available: true,
     recovery_available: true,
@@ -75,8 +74,9 @@
 cc_library_static {
     name: "libbatterymonitor",
     defaults: ["libbatterymonitor_defaults"],
+    srcs: ["BatteryMonitor.cpp"],
     static_libs: [
-        "android.hardware.health-V1-ndk",
+        "android.hardware.health-V2-ndk",
     ],
     whole_static_libs: [
         // Need to translate HIDL to AIDL to support legacy APIs in
@@ -89,6 +89,7 @@
 cc_library_static {
     name: "libbatterymonitor-V1",
     defaults: ["libbatterymonitor_defaults"],
+    srcs: ["BatteryMonitor_v1.cpp"],
     static_libs: [
         "android.hardware.health-V1-ndk",
     ],
@@ -202,12 +203,12 @@
     defaults: ["libhealthd_charger_ui_defaults"],
 
     static_libs: [
-        "android.hardware.health-V1-ndk",
+        "android.hardware.health-V2-ndk",
         "android.hardware.health-translate-ndk",
     ],
 
     export_static_lib_headers: [
-        "android.hardware.health-V1-ndk",
+        "android.hardware.health-V2-ndk",
     ],
 }
 
@@ -279,7 +280,7 @@
     static_libs: [
         // common
         "android.hardware.health@1.0-convert",
-        "android.hardware.health-V1-ndk",
+        "android.hardware.health-V2-ndk",
         "libbatterymonitor",
         "libcharger_sysprop",
         "libhealthd_charger_nops",
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index a7571a2..4ea452a 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -55,7 +55,10 @@
 using HealthInfo_2_0 = android::hardware::health::V2_0::HealthInfo;
 using HealthInfo_2_1 = android::hardware::health::V2_1::HealthInfo;
 using aidl::android::hardware::health::BatteryCapacityLevel;
+using aidl::android::hardware::health::BatteryChargingPolicy;
+using aidl::android::hardware::health::BatteryChargingState;
 using aidl::android::hardware::health::BatteryHealth;
+using aidl::android::hardware::health::BatteryHealthData;
 using aidl::android::hardware::health::BatteryStatus;
 using aidl::android::hardware::health::HealthInfo;
 
@@ -227,6 +230,37 @@
     return *ret;
 }
 
+BatteryChargingPolicy getBatteryChargingPolicy(const char* chargingPolicy) {
+    static SysfsStringEnumMap<BatteryChargingPolicy> batteryChargingPolicyMap[] = {
+            {"0", BatteryChargingPolicy::INVALID},   {"1", BatteryChargingPolicy::DEFAULT},
+            {"2", BatteryChargingPolicy::LONG_LIFE}, {"3", BatteryChargingPolicy::ADAPTIVE},
+            {NULL, BatteryChargingPolicy::DEFAULT},
+    };
+
+    auto ret = mapSysfsString(chargingPolicy, batteryChargingPolicyMap);
+    if (!ret) {
+        *ret = BatteryChargingPolicy::DEFAULT;
+    }
+
+    return *ret;
+}
+
+BatteryChargingState getBatteryChargingState(const char* chargingState) {
+    static SysfsStringEnumMap<BatteryChargingState> batteryChargingStateMap[] = {
+            {"0", BatteryChargingState::INVALID},   {"1", BatteryChargingState::NORMAL},
+            {"2", BatteryChargingState::TOO_COLD},  {"3", BatteryChargingState::TOO_HOT},
+            {"4", BatteryChargingState::LONG_LIFE}, {"5", BatteryChargingState::ADAPTIVE},
+            {NULL, BatteryChargingState::NORMAL},
+    };
+
+    auto ret = mapSysfsString(chargingState, batteryChargingStateMap);
+    if (!ret) {
+        *ret = BatteryChargingState::NORMAL;
+    }
+
+    return *ret;
+}
+
 static int readFromFile(const String8& path, std::string* buf) {
     buf->clear();
     if (android::base::ReadFileToString(path.c_str(), buf)) {
@@ -235,6 +269,10 @@
     return buf->length();
 }
 
+static bool writeToFile(const String8& path, int32_t in_value) {
+    return android::base::WriteStringToFile(std::to_string(in_value), path.c_str());
+}
+
 static BatteryMonitor::PowerSupplyType readPowerSupplyType(const String8& path) {
     static SysfsStringEnumMap<int> supplyTypeMap[] = {
             {"Unknown", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_UNKNOWN},
@@ -336,6 +374,17 @@
         mHealthInfo->batteryFullChargeDesignCapacityUah =
                 getIntField(mHealthdConfig->batteryFullChargeDesignCapacityUahPath);
 
+    if (!mHealthdConfig->batteryStateOfHealthPath.isEmpty())
+        mHealthInfo->batteryStateOfHealth = getIntField(mHealthdConfig->batteryStateOfHealthPath);
+
+    if (!mHealthdConfig->batteryManufacturingDatePath.isEmpty())
+        mHealthInfo->batteryHealthData->batteryManufacturingDateSeconds =
+                getIntField(mHealthdConfig->batteryManufacturingDatePath);
+
+    if (!mHealthdConfig->batteryFirstUsageDatePath.isEmpty())
+        mHealthInfo->batteryHealthData->batteryFirstUsageSeconds =
+                getIntField(mHealthdConfig->batteryFirstUsageDatePath);
+
     mHealthInfo->batteryTemperatureTenthsCelsius =
             mBatteryFixedTemperature ? mBatteryFixedTemperature
                                      : getIntField(mHealthdConfig->batteryTemperaturePath);
@@ -354,6 +403,12 @@
     if (readFromFile(mHealthdConfig->batteryTechnologyPath, &buf) > 0)
         mHealthInfo->batteryTechnology = String8(buf.c_str());
 
+    if (readFromFile(mHealthdConfig->chargingPolicyPath, &buf) > 0)
+        mHealthInfo->chargingPolicy = getBatteryChargingPolicy(buf.c_str());
+
+    if (readFromFile(mHealthdConfig->chargingStatePath, &buf) > 0)
+        mHealthInfo->chargingState = getBatteryChargingState(buf.c_str());
+
     double MaxPower = 0;
 
     for (size_t i = 0; i < mChargerNames.size(); i++) {
@@ -476,6 +531,43 @@
     return static_cast<int>(result);
 }
 
+status_t BatteryMonitor::setChargingPolicy(int value) {
+    status_t ret = NAME_NOT_FOUND;
+    bool result;
+    if (!mHealthdConfig->chargingPolicyPath.isEmpty()) {
+        result = writeToFile(mHealthdConfig->chargingPolicyPath, value);
+        if (!result) {
+            KLOG_WARNING(LOG_TAG, "setChargingPolicy fail\n");
+            ret = BAD_VALUE;
+        } else {
+            ret = OK;
+        }
+    }
+    return ret;
+}
+
+int BatteryMonitor::getChargingPolicy() {
+    BatteryChargingPolicy result = BatteryChargingPolicy::DEFAULT;
+    if (!mHealthdConfig->chargingPolicyPath.isEmpty()) {
+        std::string buf;
+        if (readFromFile(mHealthdConfig->chargingPolicyPath, &buf) > 0)
+            result = getBatteryChargingPolicy(buf.c_str());
+    }
+    return static_cast<int>(result);
+}
+
+int BatteryMonitor::getBatteryHealthData(int id) {
+    if (id == BATTERY_PROP_MANUFACTURING_DATE) {
+        if (!mHealthdConfig->batteryManufacturingDatePath.isEmpty())
+            return getIntField(mHealthdConfig->batteryManufacturingDatePath);
+    }
+    if (id == BATTERY_PROP_FIRST_USAGE_DATE) {
+        if (!mHealthdConfig->batteryFirstUsageDatePath.isEmpty())
+            return getIntField(mHealthdConfig->batteryFirstUsageDatePath);
+    }
+    return 0;
+}
+
 status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
     status_t ret = BAD_VALUE;
     std::string buf;
@@ -536,6 +628,21 @@
         ret = OK;
         break;
 
+    case BATTERY_PROP_CHARGING_POLICY:
+        val->valueInt64 = getChargingPolicy();
+        ret = OK;
+        break;
+
+    case BATTERY_PROP_MANUFACTURING_DATE:
+        val->valueInt64 = getBatteryHealthData(BATTERY_PROP_MANUFACTURING_DATE);
+        ret = OK;
+        break;
+
+    case BATTERY_PROP_FIRST_USAGE_DATE:
+        val->valueInt64 = getBatteryHealthData(BATTERY_PROP_FIRST_USAGE_DATE);
+        ret = OK;
+        break;
+
     default:
         break;
     }
@@ -758,6 +865,44 @@
                         mHealthdConfig->batteryTechnologyPath = path;
                 }
 
+                if (mHealthdConfig->batteryStateOfHealthPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/state_of_health", POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0) {
+                        mHealthdConfig->batteryStateOfHealthPath = path;
+                    } else {
+                        path.clear();
+                        path.appendFormat("%s/%s/health_index", POWER_SUPPLY_SYSFS_PATH, name);
+                        if (access(path, R_OK) == 0)
+                            mHealthdConfig->batteryStateOfHealthPath = path;
+                    }
+                }
+
+                if (mHealthdConfig->batteryManufacturingDatePath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/manufacturing_date", POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryManufacturingDatePath = path;
+                }
+
+                if (mHealthdConfig->batteryFirstUsageDatePath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/first_usage_date", POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0) mHealthdConfig->batteryFirstUsageDatePath = path;
+                }
+
+                if (mHealthdConfig->chargingStatePath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/charging_state", POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0) mHealthdConfig->chargingStatePath = path;
+                }
+
+                if (mHealthdConfig->chargingPolicyPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/charging_policy", POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0) mHealthdConfig->chargingPolicyPath = path;
+                }
+
                 break;
 
             case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
@@ -810,6 +955,16 @@
             KLOG_WARNING(LOG_TAG, "batteryChargeTimeToFullNowPath. not found\n");
         if (mHealthdConfig->batteryFullChargeDesignCapacityUahPath.isEmpty())
             KLOG_WARNING(LOG_TAG, "batteryFullChargeDesignCapacityUahPath. not found\n");
+        if (mHealthdConfig->batteryStateOfHealthPath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "batteryStateOfHealthPath not found\n");
+        if (mHealthdConfig->batteryManufacturingDatePath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "batteryManufacturingDatePath not found\n");
+        if (mHealthdConfig->batteryFirstUsageDatePath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "batteryFirstUsageDatePath not found\n");
+        if (mHealthdConfig->chargingStatePath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "chargingStatePath not found\n");
+        if (mHealthdConfig->chargingPolicyPath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "chargingPolicyPath not found\n");
     }
 
     if (property_get("ro.boot.fake_battery", pval, NULL) > 0
diff --git a/healthd/BatteryMonitor_v1.cpp b/healthd/BatteryMonitor_v1.cpp
new file mode 100644
index 0000000..b87c493
--- /dev/null
+++ b/healthd/BatteryMonitor_v1.cpp
@@ -0,0 +1,822 @@
+/*
+ * Copyright (C) 2013 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 "healthd"
+
+#include <healthd/healthd.h>
+#include <healthd/BatteryMonitor_v1.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <memory>
+#include <optional>
+
+#include <aidl/android/hardware/health/HealthInfo.h>
+#include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+#include <android/hardware/health/2.1/types.h>
+#include <android/hardware/health/translate-ndk.h>
+#include <batteryservice/BatteryService.h>
+#include <cutils/klog.h>
+#include <cutils/properties.h>
+#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#define POWER_SUPPLY_SUBSYSTEM "power_supply"
+#define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM
+#define FAKE_BATTERY_CAPACITY 42
+#define FAKE_BATTERY_TEMPERATURE 424
+#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 aidl::android::hardware::health::BatteryCapacityLevel;
+using aidl::android::hardware::health::BatteryHealth;
+using aidl::android::hardware::health::BatteryStatus;
+using aidl::android::hardware::health::HealthInfo;
+
+namespace {
+
+// Translate from AIDL back to HIDL definition for getHealthInfo_*_* calls.
+// Skips storageInfo and diskStats.
+void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
+                     ::android::hardware::health::V1_0::HealthInfo* out) {
+    out->chargerAcOnline = in.chargerAcOnline;
+    out->chargerUsbOnline = in.chargerUsbOnline;
+    out->chargerWirelessOnline = in.chargerWirelessOnline;
+    out->maxChargingCurrent = in.maxChargingCurrentMicroamps;
+    out->maxChargingVoltage = in.maxChargingVoltageMicrovolts;
+    out->batteryStatus =
+            static_cast<::android::hardware::health::V1_0::BatteryStatus>(in.batteryStatus);
+    out->batteryHealth =
+            static_cast<::android::hardware::health::V1_0::BatteryHealth>(in.batteryHealth);
+    out->batteryPresent = in.batteryPresent;
+    out->batteryLevel = in.batteryLevel;
+    out->batteryVoltage = in.batteryVoltageMillivolts;
+    out->batteryTemperature = in.batteryTemperatureTenthsCelsius;
+    out->batteryCurrent = in.batteryCurrentMicroamps;
+    out->batteryCycleCount = in.batteryCycleCount;
+    out->batteryFullCharge = in.batteryFullChargeUah;
+    out->batteryChargeCounter = in.batteryChargeCounterUah;
+    out->batteryTechnology = in.batteryTechnology;
+}
+
+void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
+                     ::android::hardware::health::V2_0::HealthInfo* out) {
+    translateToHidl(in, &out->legacy);
+    out->batteryCurrentAverage = in.batteryCurrentAverageMicroamps;
+    // Skip storageInfo and diskStats
+}
+
+void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
+                     ::android::hardware::health::V2_1::HealthInfo* out) {
+    translateToHidl(in, &out->legacy);
+    out->batteryCapacityLevel = static_cast<android::hardware::health::V2_1::BatteryCapacityLevel>(
+            in.batteryCapacityLevel);
+    out->batteryChargeTimeToFullNowSeconds = in.batteryChargeTimeToFullNowSeconds;
+    out->batteryFullChargeDesignCapacityUah = in.batteryFullChargeDesignCapacityUah;
+}
+
+}  // namespace
+
+namespace android {
+
+template <typename T>
+struct SysfsStringEnumMap {
+    const char* s;
+    T val;
+};
+
+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 std::nullopt;
+}
+
+static void initHealthInfo(HealthInfo* health_info) {
+    *health_info = {
+            .batteryCapacityLevel = BatteryCapacityLevel::UNSUPPORTED,
+            .batteryChargeTimeToFullNowSeconds =
+                    (int64_t)HealthInfo::BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED,
+            .batteryStatus = BatteryStatus::UNKNOWN,
+            .batteryHealth = BatteryHealth::UNKNOWN,
+    };
+}
+
+BatteryMonitor::BatteryMonitor()
+    : mHealthdConfig(nullptr),
+      mBatteryDevicePresent(false),
+      mBatteryFixedCapacity(0),
+      mBatteryFixedTemperature(0),
+      mHealthInfo(std::make_unique<HealthInfo>()) {
+    initHealthInfo(mHealthInfo.get());
+}
+
+BatteryMonitor::~BatteryMonitor() {}
+
+HealthInfo_1_0 BatteryMonitor::getHealthInfo_1_0() const {
+    HealthInfo_1_0 health_info_1_0;
+    translateToHidl(*mHealthInfo, &health_info_1_0);
+    return health_info_1_0;
+}
+
+HealthInfo_2_0 BatteryMonitor::getHealthInfo_2_0() const {
+    HealthInfo_2_0 health_info_2_0;
+    translateToHidl(*mHealthInfo, &health_info_2_0);
+    return health_info_2_0;
+}
+
+HealthInfo_2_1 BatteryMonitor::getHealthInfo_2_1() const {
+    HealthInfo_2_1 health_info_2_1;
+    translateToHidl(*mHealthInfo, &health_info_2_1);
+    return health_info_2_1;
+}
+
+const HealthInfo& BatteryMonitor::getHealthInfo() 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},
+    };
+
+    auto ret = mapSysfsString(status, batteryStatusMap);
+    if (!ret) {
+        KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status);
+        *ret = BatteryStatus::UNKNOWN;
+    }
+
+    return *ret;
+}
+
+BatteryCapacityLevel getBatteryCapacityLevel(const char* capacityLevel) {
+    static SysfsStringEnumMap<BatteryCapacityLevel> batteryCapacityLevelMap[] = {
+            {"Unknown", BatteryCapacityLevel::UNKNOWN},
+            {"Critical", BatteryCapacityLevel::CRITICAL},
+            {"Low", BatteryCapacityLevel::LOW},
+            {"Normal", BatteryCapacityLevel::NORMAL},
+            {"High", BatteryCapacityLevel::HIGH},
+            {"Full", BatteryCapacityLevel::FULL},
+            {NULL, BatteryCapacityLevel::UNSUPPORTED},
+    };
+
+    auto ret = mapSysfsString(capacityLevel, batteryCapacityLevelMap);
+    if (!ret) {
+        KLOG_WARNING(LOG_TAG, "Unsupported battery capacity level '%s'\n", capacityLevel);
+        *ret = BatteryCapacityLevel::UNSUPPORTED;
+    }
+
+    return *ret;
+}
+
+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},
+    };
+
+    auto ret = mapSysfsString(status, batteryHealthMap);
+    if (!ret) {
+        KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status);
+        *ret = BatteryHealth::UNKNOWN;
+    }
+
+    return *ret;
+}
+
+static int readFromFile(const String8& path, std::string* buf) {
+    buf->clear();
+    if (android::base::ReadFileToString(path.c_str(), buf)) {
+        *buf = android::base::Trim(*buf);
+    }
+    return buf->length();
+}
+
+static BatteryMonitor::PowerSupplyType readPowerSupplyType(const String8& path) {
+    static SysfsStringEnumMap<int> supplyTypeMap[] = {
+            {"Unknown", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_UNKNOWN},
+            {"Battery", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_BATTERY},
+            {"UPS", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"Mains", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"USB", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_USB},
+            {"USB_DCP", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"USB_HVDCP", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"USB_CDP", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"USB_ACA", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"USB_C", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"USB_PD", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"USB_PD_DRP", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_USB},
+            {"Wireless", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_WIRELESS},
+            {"Dock", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_DOCK},
+            {NULL, 0},
+    };
+    std::string buf;
+
+    if (readFromFile(path, &buf) <= 0) {
+        return BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
+    }
+
+    auto ret = mapSysfsString(buf.c_str(), supplyTypeMap);
+    if (!ret) {
+        KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf.c_str());
+        *ret = BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
+    }
+
+    return static_cast<BatteryMonitor::PowerSupplyType>(*ret);
+}
+
+static bool getBooleanField(const String8& path) {
+    std::string buf;
+    bool value = false;
+
+    if (readFromFile(path, &buf) > 0)
+        if (buf[0] != '0')
+            value = true;
+
+    return value;
+}
+
+static int getIntField(const String8& path) {
+    std::string buf;
+    int value = 0;
+
+    if (readFromFile(path, &buf) > 0)
+        android::base::ParseInt(buf, &value);
+
+    return value;
+}
+
+static bool isScopedPowerSupply(const char* name) {
+    constexpr char kScopeDevice[] = "Device";
+
+    String8 path;
+    path.appendFormat("%s/%s/scope", POWER_SUPPLY_SYSFS_PATH, name);
+    std::string scope;
+    return (readFromFile(path, &scope) > 0 && scope == kScopeDevice);
+}
+
+void BatteryMonitor::updateValues(void) {
+    initHealthInfo(mHealthInfo.get());
+
+    if (!mHealthdConfig->batteryPresentPath.isEmpty())
+        mHealthInfo->batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
+    else
+        mHealthInfo->batteryPresent = mBatteryDevicePresent;
+
+    mHealthInfo->batteryLevel = mBatteryFixedCapacity
+                                        ? mBatteryFixedCapacity
+                                        : getIntField(mHealthdConfig->batteryCapacityPath);
+    mHealthInfo->batteryVoltageMillivolts = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
+
+    if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
+        mHealthInfo->batteryCurrentMicroamps = getIntField(mHealthdConfig->batteryCurrentNowPath);
+
+    if (!mHealthdConfig->batteryFullChargePath.isEmpty())
+        mHealthInfo->batteryFullChargeUah = getIntField(mHealthdConfig->batteryFullChargePath);
+
+    if (!mHealthdConfig->batteryCycleCountPath.isEmpty())
+        mHealthInfo->batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath);
+
+    if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
+        mHealthInfo->batteryChargeCounterUah =
+                getIntField(mHealthdConfig->batteryChargeCounterPath);
+
+    if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty())
+        mHealthInfo->batteryCurrentAverageMicroamps =
+                getIntField(mHealthdConfig->batteryCurrentAvgPath);
+
+    if (!mHealthdConfig->batteryChargeTimeToFullNowPath.isEmpty())
+        mHealthInfo->batteryChargeTimeToFullNowSeconds =
+                getIntField(mHealthdConfig->batteryChargeTimeToFullNowPath);
+
+    if (!mHealthdConfig->batteryFullChargeDesignCapacityUahPath.isEmpty())
+        mHealthInfo->batteryFullChargeDesignCapacityUah =
+                getIntField(mHealthdConfig->batteryFullChargeDesignCapacityUahPath);
+
+    mHealthInfo->batteryTemperatureTenthsCelsius =
+            mBatteryFixedTemperature ? mBatteryFixedTemperature
+                                     : getIntField(mHealthdConfig->batteryTemperaturePath);
+
+    std::string buf;
+
+    if (readFromFile(mHealthdConfig->batteryCapacityLevelPath, &buf) > 0)
+        mHealthInfo->batteryCapacityLevel = getBatteryCapacityLevel(buf.c_str());
+
+    if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
+        mHealthInfo->batteryStatus = getBatteryStatus(buf.c_str());
+
+    if (readFromFile(mHealthdConfig->batteryHealthPath, &buf) > 0)
+        mHealthInfo->batteryHealth = getBatteryHealth(buf.c_str());
+
+    if (readFromFile(mHealthdConfig->batteryTechnologyPath, &buf) > 0)
+        mHealthInfo->batteryTechnology = String8(buf.c_str());
+
+    double MaxPower = 0;
+
+    for (size_t i = 0; i < mChargerNames.size(); i++) {
+        String8 path;
+        path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
+                          mChargerNames[i].string());
+        if (getIntField(path)) {
+            path.clear();
+            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
+                              mChargerNames[i].string());
+            switch(readPowerSupplyType(path)) {
+            case ANDROID_POWER_SUPPLY_TYPE_AC:
+                mHealthInfo->chargerAcOnline = true;
+                break;
+            case ANDROID_POWER_SUPPLY_TYPE_USB:
+                mHealthInfo->chargerUsbOnline = true;
+                break;
+            case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
+                mHealthInfo->chargerWirelessOnline = true;
+                break;
+            case ANDROID_POWER_SUPPLY_TYPE_DOCK:
+                mHealthInfo->chargerDockOnline = true;
+                break;
+            default:
+                path.clear();
+                path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH,
+                                  mChargerNames[i].string());
+                if (access(path.string(), R_OK) == 0)
+                    mHealthInfo->chargerDockOnline = true;
+                else
+                    KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
+                                 mChargerNames[i].string());
+            }
+            path.clear();
+            path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
+                              mChargerNames[i].string());
+            int ChargingCurrent =
+                    (access(path.string(), R_OK) == 0) ? getIntField(path) : 0;
+
+            path.clear();
+            path.appendFormat("%s/%s/voltage_max", POWER_SUPPLY_SYSFS_PATH,
+                              mChargerNames[i].string());
+
+            int ChargingVoltage =
+                (access(path.string(), R_OK) == 0) ? getIntField(path) :
+                DEFAULT_VBUS_VOLTAGE;
+
+            double power = ((double)ChargingCurrent / MILLION) *
+                           ((double)ChargingVoltage / MILLION);
+            if (MaxPower < power) {
+                mHealthInfo->maxChargingCurrentMicroamps = ChargingCurrent;
+                mHealthInfo->maxChargingVoltageMicrovolts = ChargingVoltage;
+                MaxPower = power;
+            }
+        }
+    }
+}
+
+static void doLogValues(const HealthInfo& props, const struct healthd_config& healthd_config) {
+    char dmesgline[256];
+    size_t len;
+    if (props.batteryPresent) {
+        snprintf(dmesgline, sizeof(dmesgline), "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
+                 props.batteryLevel, props.batteryVoltageMillivolts,
+                 props.batteryTemperatureTenthsCelsius < 0 ? "-" : "",
+                 abs(props.batteryTemperatureTenthsCelsius / 10),
+                 abs(props.batteryTemperatureTenthsCelsius % 10), props.batteryHealth,
+                 props.batteryStatus);
+
+        len = strlen(dmesgline);
+        if (!healthd_config.batteryCurrentNowPath.isEmpty()) {
+            len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " c=%d",
+                            props.batteryCurrentMicroamps);
+        }
+
+        if (!healthd_config.batteryFullChargePath.isEmpty()) {
+            len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " fc=%d",
+                            props.batteryFullChargeUah);
+        }
+
+        if (!healthd_config.batteryCycleCountPath.isEmpty()) {
+            len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " cc=%d",
+                            props.batteryCycleCount);
+        }
+    } else {
+        len = snprintf(dmesgline, sizeof(dmesgline), "battery none");
+    }
+
+    snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s%s",
+             props.chargerAcOnline ? "a" : "", props.chargerUsbOnline ? "u" : "",
+             props.chargerWirelessOnline ? "w" : "", props.chargerDockOnline ? "d" : "");
+
+    KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
+}
+
+void BatteryMonitor::logValues(const HealthInfo_2_1& health_info,
+                               const struct healthd_config& healthd_config) {
+    HealthInfo aidl_health_info;
+    (void)android::h2a::translate(health_info, &aidl_health_info);
+    doLogValues(aidl_health_info, healthd_config);
+}
+
+void BatteryMonitor::logValues(void) {
+    doLogValues(*mHealthInfo, *mHealthdConfig);
+}
+
+bool BatteryMonitor::isChargerOnline() {
+    const HealthInfo& props = *mHealthInfo;
+    return props.chargerAcOnline | props.chargerUsbOnline | props.chargerWirelessOnline |
+           props.chargerDockOnline;
+}
+
+int BatteryMonitor::getChargeStatus() {
+    BatteryStatus result = BatteryStatus::UNKNOWN;
+    if (!mHealthdConfig->batteryStatusPath.isEmpty()) {
+        std::string buf;
+        if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
+            result = getBatteryStatus(buf.c_str());
+    }
+    return static_cast<int>(result);
+}
+
+status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
+    status_t ret = BAD_VALUE;
+    std::string buf;
+
+    val->valueInt64 = LONG_MIN;
+
+    switch(id) {
+    case BATTERY_PROP_CHARGE_COUNTER:
+        if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
+            val->valueInt64 =
+                getIntField(mHealthdConfig->batteryChargeCounterPath);
+            ret = OK;
+        } else {
+            ret = NAME_NOT_FOUND;
+        }
+        break;
+
+    case BATTERY_PROP_CURRENT_NOW:
+        if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
+            val->valueInt64 =
+                getIntField(mHealthdConfig->batteryCurrentNowPath);
+            ret = OK;
+        } else {
+            ret = NAME_NOT_FOUND;
+        }
+        break;
+
+    case BATTERY_PROP_CURRENT_AVG:
+        if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
+            val->valueInt64 =
+                getIntField(mHealthdConfig->batteryCurrentAvgPath);
+            ret = OK;
+        } else {
+            ret = NAME_NOT_FOUND;
+        }
+        break;
+
+    case BATTERY_PROP_CAPACITY:
+        if (!mHealthdConfig->batteryCapacityPath.isEmpty()) {
+            val->valueInt64 =
+                getIntField(mHealthdConfig->batteryCapacityPath);
+            ret = OK;
+        } else {
+            ret = NAME_NOT_FOUND;
+        }
+        break;
+
+    case BATTERY_PROP_ENERGY_COUNTER:
+        if (mHealthdConfig->energyCounter) {
+            ret = mHealthdConfig->energyCounter(&val->valueInt64);
+        } else {
+            ret = NAME_NOT_FOUND;
+        }
+        break;
+
+    case BATTERY_PROP_BATTERY_STATUS:
+        val->valueInt64 = getChargeStatus();
+        ret = OK;
+        break;
+
+    default:
+        break;
+    }
+
+    return ret;
+}
+
+void BatteryMonitor::dumpState(int fd) {
+    int v;
+    char vs[128];
+    const HealthInfo& props = *mHealthInfo;
+
+    snprintf(vs, sizeof(vs),
+             "ac: %d usb: %d wireless: %d dock: %d current_max: %d voltage_max: %d\n",
+             props.chargerAcOnline, props.chargerUsbOnline, props.chargerWirelessOnline,
+             props.chargerDockOnline, props.maxChargingCurrentMicroamps,
+             props.maxChargingVoltageMicrovolts);
+    write(fd, vs, strlen(vs));
+    snprintf(vs, sizeof(vs), "status: %d health: %d present: %d\n",
+             props.batteryStatus, props.batteryHealth, props.batteryPresent);
+    write(fd, vs, strlen(vs));
+    snprintf(vs, sizeof(vs), "level: %d voltage: %d temp: %d\n", props.batteryLevel,
+             props.batteryVoltageMillivolts, props.batteryTemperatureTenthsCelsius);
+    write(fd, vs, strlen(vs));
+
+    if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
+        v = getIntField(mHealthdConfig->batteryCurrentNowPath);
+        snprintf(vs, sizeof(vs), "current now: %d\n", v);
+        write(fd, vs, strlen(vs));
+    }
+
+    if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
+        v = getIntField(mHealthdConfig->batteryCurrentAvgPath);
+        snprintf(vs, sizeof(vs), "current avg: %d\n", v);
+        write(fd, vs, strlen(vs));
+    }
+
+    if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
+        v = getIntField(mHealthdConfig->batteryChargeCounterPath);
+        snprintf(vs, sizeof(vs), "charge counter: %d\n", v);
+        write(fd, vs, strlen(vs));
+    }
+
+    if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
+        snprintf(vs, sizeof(vs), "current now: %d\n", props.batteryCurrentMicroamps);
+        write(fd, vs, strlen(vs));
+    }
+
+    if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
+        snprintf(vs, sizeof(vs), "cycle count: %d\n", props.batteryCycleCount);
+        write(fd, vs, strlen(vs));
+    }
+
+    if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
+        snprintf(vs, sizeof(vs), "Full charge: %d\n", props.batteryFullChargeUah);
+        write(fd, vs, strlen(vs));
+    }
+}
+
+void BatteryMonitor::init(struct healthd_config *hc) {
+    String8 path;
+    char pval[PROPERTY_VALUE_MAX];
+
+    mHealthdConfig = hc;
+    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(POWER_SUPPLY_SYSFS_PATH), closedir);
+    if (dir == NULL) {
+        KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
+    } else {
+        struct dirent* entry;
+
+        while ((entry = readdir(dir.get()))) {
+            const char* name = entry->d_name;
+
+            if (!strcmp(name, ".") || !strcmp(name, ".."))
+                continue;
+
+            std::vector<String8>::iterator itIgnoreName =
+                    find(hc->ignorePowerSupplyNames.begin(), hc->ignorePowerSupplyNames.end(),
+                         String8(name));
+            if (itIgnoreName != hc->ignorePowerSupplyNames.end())
+                continue;
+
+            // Look for "type" file in each subdirectory
+            path.clear();
+            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
+            switch(readPowerSupplyType(path)) {
+            case ANDROID_POWER_SUPPLY_TYPE_AC:
+            case ANDROID_POWER_SUPPLY_TYPE_USB:
+            case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
+            case ANDROID_POWER_SUPPLY_TYPE_DOCK:
+                path.clear();
+                path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
+                if (access(path.string(), R_OK) == 0)
+                    mChargerNames.add(String8(name));
+                break;
+
+            case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
+                // Some devices expose the battery status of sub-component like
+                // stylus. Such a device-scoped battery info needs to be skipped
+                // in BatteryMonitor, which is intended to report the status of
+                // the battery supplying the power to the whole system.
+                if (isScopedPowerSupply(name)) continue;
+                mBatteryDevicePresent = true;
+
+                if (mHealthdConfig->batteryStatusPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,
+                                      name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryStatusPath = path;
+                }
+
+                if (mHealthdConfig->batteryHealthPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,
+                                      name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryHealthPath = path;
+                }
+
+                if (mHealthdConfig->batteryPresentPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,
+                                      name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryPresentPath = path;
+                }
+
+                if (mHealthdConfig->batteryCapacityPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,
+                                      name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryCapacityPath = path;
+                }
+
+                if (mHealthdConfig->batteryVoltagePath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/voltage_now",
+                                      POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0) {
+                        mHealthdConfig->batteryVoltagePath = path;
+                    }
+                }
+
+                if (mHealthdConfig->batteryFullChargePath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/charge_full",
+                                      POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryFullChargePath = path;
+                }
+
+                if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/current_now",
+                                      POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryCurrentNowPath = path;
+                }
+
+                if (mHealthdConfig->batteryCycleCountPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/cycle_count",
+                                      POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryCycleCountPath = path;
+                }
+
+                if (mHealthdConfig->batteryCapacityLevelPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/capacity_level", POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0) mHealthdConfig->batteryCapacityLevelPath = path;
+                }
+
+                if (mHealthdConfig->batteryChargeTimeToFullNowPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/time_to_full_now", POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryChargeTimeToFullNowPath = path;
+                }
+
+                if (mHealthdConfig->batteryFullChargeDesignCapacityUahPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/charge_full_design", POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryFullChargeDesignCapacityUahPath = path;
+                }
+
+                if (mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/current_avg",
+                                      POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryCurrentAvgPath = path;
+                }
+
+                if (mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/charge_counter",
+                                      POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryChargeCounterPath = path;
+                }
+
+                if (mHealthdConfig->batteryTemperaturePath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,
+                                      name);
+                    if (access(path, R_OK) == 0) {
+                        mHealthdConfig->batteryTemperaturePath = path;
+                    }
+                }
+
+                if (mHealthdConfig->batteryTechnologyPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/technology",
+                                      POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryTechnologyPath = path;
+                }
+
+                break;
+
+            case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
+                break;
+            }
+
+            // Look for "is_dock" file
+            path.clear();
+            path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH, name);
+            if (access(path.string(), R_OK) == 0) {
+                path.clear();
+                path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
+                if (access(path.string(), R_OK) == 0)
+                    mChargerNames.add(String8(name));
+
+            }
+        }
+    }
+
+    // Typically the case for devices which do not have a battery and
+    // and are always plugged into AC mains.
+    if (!mBatteryDevicePresent) {
+        KLOG_WARNING(LOG_TAG, "No battery devices found\n");
+        hc->periodic_chores_interval_fast = -1;
+        hc->periodic_chores_interval_slow = -1;
+    } else {
+        if (mHealthdConfig->batteryStatusPath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
+        if (mHealthdConfig->batteryHealthPath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "BatteryHealthPath not found\n");
+        if (mHealthdConfig->batteryPresentPath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n");
+        if (mHealthdConfig->batteryCapacityPath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n");
+        if (mHealthdConfig->batteryVoltagePath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n");
+        if (mHealthdConfig->batteryTemperaturePath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
+        if (mHealthdConfig->batteryTechnologyPath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
+        if (mHealthdConfig->batteryCurrentNowPath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "BatteryCurrentNowPath not found\n");
+        if (mHealthdConfig->batteryFullChargePath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "BatteryFullChargePath not found\n");
+        if (mHealthdConfig->batteryCycleCountPath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "BatteryCycleCountPath not found\n");
+        if (mHealthdConfig->batteryCapacityLevelPath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "batteryCapacityLevelPath not found\n");
+        if (mHealthdConfig->batteryChargeTimeToFullNowPath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "batteryChargeTimeToFullNowPath. not found\n");
+        if (mHealthdConfig->batteryFullChargeDesignCapacityUahPath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "batteryFullChargeDesignCapacityUahPath. not found\n");
+    }
+
+    if (property_get("ro.boot.fake_battery", pval, NULL) > 0
+                                               && strtol(pval, NULL, 10) != 0) {
+        mBatteryFixedCapacity = FAKE_BATTERY_CAPACITY;
+        mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
+    }
+}
+
+}; // namespace android
diff --git a/healthd/include/healthd/BatteryMonitor.h b/healthd/include/healthd/BatteryMonitor.h
index 8cbf5ea..4af2a87 100644
--- a/healthd/include/healthd/BatteryMonitor.h
+++ b/healthd/include/healthd/BatteryMonitor.h
@@ -72,6 +72,10 @@
     void logValues(void);
     bool isChargerOnline();
 
+    int setChargingPolicy(int value);
+    int getChargingPolicy();
+    int getBatteryHealthData(int id);
+
     static void logValues(const android::hardware::health::V2_1::HealthInfo& health_info,
                           const struct healthd_config& healthd_config);
 
diff --git a/healthd/include/healthd/BatteryMonitor_v1.h b/healthd/include/healthd/BatteryMonitor_v1.h
new file mode 100644
index 0000000..49f6f9d
--- /dev/null
+++ b/healthd/include/healthd/BatteryMonitor_v1.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef HEALTHD_BATTERYMONITOR_V1_H
+#define HEALTHD_BATTERYMONITOR_V1_H
+
+#include <memory>
+
+#include <batteryservice/BatteryService.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include <healthd/healthd.h>
+
+namespace aidl::android::hardware::health {
+class HealthInfo;
+}  // namespace aidl::android::hardware::health
+
+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:
+
+    enum PowerSupplyType {
+        ANDROID_POWER_SUPPLY_TYPE_UNKNOWN = 0,
+        ANDROID_POWER_SUPPLY_TYPE_AC,
+        ANDROID_POWER_SUPPLY_TYPE_USB,
+        ANDROID_POWER_SUPPLY_TYPE_WIRELESS,
+        ANDROID_POWER_SUPPLY_TYPE_BATTERY,
+        ANDROID_POWER_SUPPLY_TYPE_DOCK
+    };
+
+    BatteryMonitor();
+    ~BatteryMonitor();
+    void init(struct healthd_config *hc);
+    int getChargeStatus();
+    status_t getProperty(int id, struct BatteryProperty *val);
+    void dumpState(int fd);
+
+    android::hardware::health::V1_0::HealthInfo getHealthInfo_1_0() const;
+    android::hardware::health::V2_0::HealthInfo getHealthInfo_2_0() const;
+    android::hardware::health::V2_1::HealthInfo getHealthInfo_2_1() const;
+    const aidl::android::hardware::health::HealthInfo& getHealthInfo() const;
+
+    void updateValues(void);
+    void logValues(void);
+    bool isChargerOnline();
+
+    static void logValues(const android::hardware::health::V2_1::HealthInfo& health_info,
+                          const struct healthd_config& healthd_config);
+
+  private:
+    struct healthd_config *mHealthdConfig;
+    Vector<String8> mChargerNames;
+    bool mBatteryDevicePresent;
+    int mBatteryFixedCapacity;
+    int mBatteryFixedTemperature;
+    std::unique_ptr<aidl::android::hardware::health::HealthInfo> mHealthInfo;
+};
+
+}; // namespace android
+
+#endif // HEALTHD_BATTERYMONITOR_V1_H
diff --git a/healthd/include/healthd/healthd.h b/healthd/include/healthd/healthd.h
index 706c332..e1c357c 100644
--- a/healthd/include/healthd/healthd.h
+++ b/healthd/include/healthd/healthd.h
@@ -72,6 +72,11 @@
     android::String8 batteryCapacityLevelPath;
     android::String8 batteryChargeTimeToFullNowPath;
     android::String8 batteryFullChargeDesignCapacityUahPath;
+    android::String8 batteryStateOfHealthPath;
+    android::String8 batteryManufacturingDatePath;
+    android::String8 batteryFirstUsageDatePath;
+    android::String8 chargingStatePath;
+    android::String8 chargingPolicyPath;
 
     int (*energyCounter)(int64_t *);
     int boot_min_cap;
diff --git a/libcutils/qtaguid.cpp b/libcutils/qtaguid.cpp
index a987b85..f847782 100644
--- a/libcutils/qtaguid.cpp
+++ b/libcutils/qtaguid.cpp
@@ -22,76 +22,60 @@
 
 #include <dlfcn.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
 
 #include <log/log.h>
 
-class netdHandler {
-  public:
+struct netdHandler {
     int (*netdTagSocket)(int, uint32_t, uid_t);
     int (*netdUntagSocket)(int);
 };
 
-int stubTagSocket(int, uint32_t, uid_t) {
+static int stubTagSocket(int, uint32_t, uid_t) {
     return -EREMOTEIO;
 }
 
-int stubUntagSocket(int) {
+static int stubUntagSocket(int) {
     return -EREMOTEIO;
 }
 
-netdHandler initHandler(void) {
-    netdHandler handler = {stubTagSocket, stubUntagSocket};
+static netdHandler initHandler(void) {
+    const netdHandler stubHandler = { stubTagSocket, stubUntagSocket };
 
     void* netdClientHandle = dlopen("libnetd_client.so", RTLD_NOW);
     if (!netdClientHandle) {
         ALOGE("Failed to open libnetd_client.so: %s", dlerror());
-        return handler;
+        return stubHandler;
     }
 
+    netdHandler handler;
     handler.netdTagSocket = (int (*)(int, uint32_t, uid_t))dlsym(netdClientHandle, "tagSocket");
     if (!handler.netdTagSocket) {
         ALOGE("load netdTagSocket handler failed: %s", dlerror());
+        return stubHandler;
     }
 
     handler.netdUntagSocket = (int (*)(int))dlsym(netdClientHandle, "untagSocket");
     if (!handler.netdUntagSocket) {
         ALOGE("load netdUntagSocket handler failed: %s", dlerror());
+        return stubHandler;
     }
 
     return handler;
 }
 
 // The language guarantees that this object will be initialized in a thread-safe way.
-static netdHandler& getHandler() {
-    static netdHandler instance = initHandler();
+static const netdHandler& getHandler() {
+    static const netdHandler instance = initHandler();
     return instance;
 }
 
 int qtaguid_tagSocket(int sockfd, int tag, uid_t uid) {
-    // Check the socket fd passed to us is still valid before we load the netd
-    // client. Pass a already closed socket fd to netd client may let netd open
-    // the unix socket with the same fd number and pass it to server for
-    // tagging.
-    // TODO: move the check into netdTagSocket.
-    int res = fcntl(sockfd, F_GETFD);
-    if (res < 0) return res;
-
     ALOGV("Tagging socket %d with tag %u for uid %d", sockfd, tag, uid);
     return getHandler().netdTagSocket(sockfd, tag, uid);
 }
 
 int qtaguid_untagSocket(int sockfd) {
-    // Similiar to tag socket. We need a check before untag to make sure untag a closed socket fail
-    // as expected.
-    // TODO: move the check into netdTagSocket.
-    int res = fcntl(sockfd, F_GETFD);
-    if (res < 0) return res;
-
     ALOGV("Untagging socket %d", sockfd);
     return getHandler().netdUntagSocket(sockfd);
 }
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index fe23b62..3dd269a 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -213,4 +213,15 @@
 	$(hide) $(foreach lib,$(PRIVATE_SANITIZER_RUNTIME_LIBRARIES), \
 		echo $(lib) >> $@;)
 
+#######################################
+# ramdisk_node_list
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := ramdisk_node_list
+LOCAL_MODULE_CLASS := ETC
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)
+
+include $(BUILD_PREBUILT)
+
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/rootdir/ramdisk_node_list b/rootdir/ramdisk_node_list
new file mode 100644
index 0000000..d3ab8a6
--- /dev/null
+++ b/rootdir/ramdisk_node_list
@@ -0,0 +1,3 @@
+dir dev 0755 0 0
+nod dev/null 0600 0 0 c 1 3
+nod dev/console 0600 0 0 c 5 1
diff --git a/storaged/Android.bp b/storaged/Android.bp
index 7960af3..c3447d2 100644
--- a/storaged/Android.bp
+++ b/storaged/Android.bp
@@ -24,7 +24,7 @@
     shared_libs: [
         "android.hardware.health@1.0",
         "android.hardware.health@2.0",
-        "android.hardware.health-V1-ndk",
+        "android.hardware.health-V2-ndk",
         "libbase",
         "libbinder",
         "libbinder_ndk",
diff --git a/toolbox/modprobe.cpp b/toolbox/modprobe.cpp
index 711586a..17f8156 100644
--- a/toolbox/modprobe.cpp
+++ b/toolbox/modprobe.cpp
@@ -23,8 +23,11 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/strings.h>
+#include <android-base/stringprintf.h>
 #include <modprobe/modprobe.h>
 
+#include <sys/utsname.h>
+
 namespace {
 
 enum modprobe_mode {
@@ -37,9 +40,8 @@
 void print_usage(void) {
     LOG(INFO) << "Usage:";
     LOG(INFO);
-    // -d option is required on Android
-    LOG(INFO) << "  modprobe [options] -d DIR [--all=FILE|MODULE]...";
-    LOG(INFO) << "  modprobe [options] -d DIR MODULE [symbol=value]...";
+    LOG(INFO) << "  modprobe [options] [-d DIR] [--all=FILE|MODULE]...";
+    LOG(INFO) << "  modprobe [options] [-d DIR] MODULE [symbol=value]...";
     LOG(INFO);
     LOG(INFO) << "Options:";
     LOG(INFO) << "  --all=FILE: FILE to acquire module names from";
@@ -189,6 +191,12 @@
         }
     }
 
+    if (mod_dirs.empty()) {
+        utsname uts;
+        uname(&uts);
+        mod_dirs.emplace_back(android::base::StringPrintf("/lib/modules/%s", uts.release));
+    }
+
     LOG(DEBUG) << "mode is " << mode;
     LOG(DEBUG) << "mod_dirs is: " << android::base::Join(mod_dirs, " ");
     LOG(DEBUG) << "modules is: " << android::base::Join(modules, " ");
diff --git a/trusty/keymaster/TEST_MAPPING b/trusty/keymaster/TEST_MAPPING
index ae48327..0dd39fb 100644
--- a/trusty/keymaster/TEST_MAPPING
+++ b/trusty/keymaster/TEST_MAPPING
@@ -1,9 +1,6 @@
 {
   "presubmit": [
       {
-        "name": "RemoteProvisionerUnitTests"
-      },
-      {
         "name": "VtsAidlKeyMintTargetTest"
       },
       {
diff --git a/trusty/libtrusty/Android.bp b/trusty/libtrusty/Android.bp
index 086051d..9d94ec4 100644
--- a/trusty/libtrusty/Android.bp
+++ b/trusty/libtrusty/Android.bp
@@ -33,5 +33,6 @@
     // TODO(b/170753563): cc_fuzz can't deal with vendor components. Build
     // libtrusty for system and vendor.
     vendor_available: true,
+    recovery_available: true,
     defaults: ["libtrusty_defaults"],
 }