merge in oc-release history after reset to master
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 4e083ae..2889356 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -363,6 +363,12 @@
     LOG(FATAL) << "failed to create backtrace map";
   }
 
+  // Collect the list of open files.
+  OpenFilesList open_files;
+  if (!backtrace) {
+    populate_open_files_list(target, &open_files);
+  }
+
   // Drop our capabilities now that we've attached to the threads we care about.
   drop_capabilities();
 
@@ -375,10 +381,6 @@
   if (backtrace) {
     dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, attached_siblings, 0);
   } else {
-    // Collect the list of open files.
-    OpenFilesList open_files;
-    populate_open_files_list(target, &open_files);
-
     engrave_tombstone(output_fd.get(), backtrace_map.get(), open_files, target, main_tid,
                       attached_siblings, abort_address, fatal_signal ? &amfd_data : nullptr);
   }
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index e7503e9..002e940 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -40,10 +40,10 @@
 using android::base::unique_fd;
 
 #if defined(__LP64__)
-#define CRASHER_PATH  "/system/xbin/crasher64"
+#define CRASHER_PATH  "/system/bin/crasher64"
 #define ARCH_SUFFIX "64"
 #else
-#define CRASHER_PATH "/system/xbin/crasher"
+#define CRASHER_PATH "/system/bin/crasher"
 #define ARCH_SUFFIX ""
 #endif
 
@@ -192,7 +192,7 @@
   std::string type = "wait-" + crash_type;
   StartProcess([type]() {
     execl(CRASHER_PATH, CRASHER_PATH, type.c_str(), nullptr);
-    err(1, "exec failed");
+    exit(errno);
   });
 }
 
@@ -216,7 +216,9 @@
     FAIL() << "failed to wait for crasher: " << strerror(errno);
   }
 
-  if (!WIFSIGNALED(status)) {
+  if (WIFEXITED(status)) {
+    FAIL() << "crasher failed to exec: " << strerror(WEXITSTATUS(status));
+  } else if (!WIFSIGNALED(status)) {
     FAIL() << "crasher didn't terminate via a signal";
   }
   ASSERT_EQ(signo, WTERMSIG(status));
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 369a022..4007203 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -348,6 +348,7 @@
 
 status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
     status_t ret = BAD_VALUE;
+    std::string buf;
 
     val->valueInt64 = LONG_MIN;
 
@@ -400,6 +401,15 @@
         }
         break;
 
+    case BATTERY_PROP_BATTERY_STATUS:
+        if (mAlwaysPluggedDevice) {
+            val->valueInt64 = BATTERY_STATUS_CHARGING;
+        } else {
+            val->valueInt64 = getChargeStatus();
+        }
+        ret = NO_ERROR;
+        break;
+
     default:
         break;
     }
diff --git a/liblog/logger_write.c b/liblog/logger_write.c
index 4324125..2599a53 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.c
@@ -343,7 +343,7 @@
             }
         }
         /* tag must be nul terminated */
-        if (strnlen(tag, len) >= len) {
+        if (tag && strnlen(tag, len) >= len) {
             tag = NULL;
         }
 
diff --git a/liblog/pmsg_writer.c b/liblog/pmsg_writer.c
index c1c068e..5e4ff98 100644
--- a/liblog/pmsg_writer.c
+++ b/liblog/pmsg_writer.c
@@ -285,6 +285,7 @@
                 __android_log_unlock();
             } else if (pmsgOpen() < 0) {
                 __android_log_unlock();
+                free(cp);
                 return -EBADF;
             }
         }
diff --git a/storaged/Android.mk b/storaged/Android.mk
index 0e8b574..5abfb7a 100644
--- a/storaged/Android.mk
+++ b/storaged/Android.mk
@@ -2,22 +2,31 @@
 
 LOCAL_PATH := $(call my-dir)
 
-LIBSTORAGED_SHARED_LIBRARIES := libbinder libbase libutils libcutils liblog libsysutils libcap libpackagelistparser
+LIBSTORAGED_SHARED_LIBRARIES := \
+    libbinder \
+    libbase \
+    libutils \
+    libcutils \
+    liblog \
+    libsysutils \
+    libcap \
+    libpackagelistparser \
+    libbatteryservice \
 
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := storaged.cpp \
-                  storaged_service.cpp \
-                  storaged_utils.cpp \
-                  storaged_uid_monitor.cpp \
-                  EventLogTags.logtags
+LOCAL_SRC_FILES := \
+    storaged.cpp \
+    storaged_service.cpp \
+    storaged_utils.cpp \
+    storaged_uid_monitor.cpp \
+    EventLogTags.logtags
 
 LOCAL_MODULE := libstoraged
 LOCAL_CFLAGS := -Werror
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include external/googletest/googletest/include
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 LOCAL_SHARED_LIBRARIES := $(LIBSTORAGED_SHARED_LIBRARIES)
-
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
diff --git a/storaged/include/storaged.h b/storaged/include/storaged.h
index ba78882..7e5048f 100644
--- a/storaged/include/storaged.h
+++ b/storaged/include/storaged.h
@@ -26,8 +26,12 @@
 #include <unordered_map>
 #include <vector>
 
+#include <batteryservice/IBatteryPropertiesListener.h>
+
 #include "storaged_uid_monitor.h"
 
+using namespace android;
+
 #define FRIEND_TEST(test_case_name, test_name) \
 friend class test_case_name##_##test_name##_Test
 
@@ -268,7 +272,7 @@
     int event_time_check_usec;  // check how much cputime spent in event loop
 };
 
-class storaged_t {
+class storaged_t : public BnBatteryPropertiesListener {
 private:
     time_t mTimer;
     storaged_config mConfig;
@@ -294,11 +298,14 @@
     }
 
     std::unordered_map<uint32_t, struct uid_info> get_uids(void) {
-        return mUidm.get_uids();
+        return mUidm.get_uid_io_stats();
     }
-    std::vector<struct uid_event> get_uid_events(int hours) {
-        return mUidm.dump_events(hours);
+    std::map<uint64_t, std::vector<struct uid_record>> get_uid_records(int hours) {
+        return mUidm.dump(hours);
     }
+
+    void init_battery_service();
+    virtual void batteryPropertiesChanged(struct BatteryProperties props);
 };
 
 // Eventlog tag
diff --git a/storaged/include/storaged_uid_monitor.h b/storaged/include/storaged_uid_monitor.h
index ac6a8bd..07e6daa 100644
--- a/storaged/include/storaged_uid_monitor.h
+++ b/storaged/include/storaged_uid_monitor.h
@@ -23,10 +23,22 @@
 #include <unordered_map>
 #include <vector>
 
-enum {
-    UID_FOREGROUND = 0,
-    UID_BACKGROUND = 1,
-    UID_STATS_SIZE = 2
+enum uid_stat_t {
+    FOREGROUND = 0,
+    BACKGROUND = 1,
+    UID_STATS = 2
+};
+
+enum charger_stat_t {
+    CHARGER_OFF = 0,
+    CHARGER_ON = 1,
+    CHARGER_STATS = 2
+};
+
+enum io_type_t {
+    READ = 0,
+    WRITE = 1,
+    IO_TYPES = 2
 };
 
 struct uid_io_stats {
@@ -39,39 +51,51 @@
 struct uid_info {
     uint32_t uid;                   // user id
     std::string name;               // package name
-    struct uid_io_stats io[UID_STATS_SIZE];      // [0]:foreground [1]:background
+    struct uid_io_stats io[UID_STATS];    // [0]:foreground [1]:background
 };
 
-struct uid_event {
+struct uid_io_usage {
+    uint64_t bytes[IO_TYPES][UID_STATS][CHARGER_STATS];
+};
+
+struct uid_record {
     std::string name;
-    uint64_t fg_read_bytes;
-    uint64_t fg_write_bytes;
-    uint64_t bg_read_bytes;
-    uint64_t bg_write_bytes;
-    uint64_t ts;
-    bool operator< (const struct uid_event& e) const {
-        return ts < e.ts;
-    }
+    struct uid_io_usage ios;
 };
 
 class uid_monitor {
 private:
-    std::unordered_map<uint32_t, struct uid_info> last_uids;
-    std::vector<struct uid_event> events;
-    sem_t events_lock;
-    void set_last_uids(std::unordered_map<uint32_t, struct uid_info>&& uids, uint64_t ts);
-    int interval;  // monitor interval in seconds
-    int threshold; // monitor threshold in bytes
-    uint64_t last_report_ts; // timestamp of last report in nsec
+    // last dump from /proc/uid_io/stats, uid -> uid_info
+    std::unordered_map<uint32_t, struct uid_info> last_uid_io_stats;
+    // current io usage for next report, app name -> uid_io_usage
+    std::unordered_map<std::string, struct uid_io_usage> curr_io_stats;
+    // io usage records, timestamp -> vector of events
+    std::map<uint64_t, std::vector<struct uid_record>> records;
+    // charger ON/OFF
+    charger_stat_t charger_stat;
+    // protects curr_io_stats, last_uid_io_stats, records and charger_stat
+    sem_t um_lock;
+
+    // reads from /proc/uid_io/stats
+    std::unordered_map<uint32_t, struct uid_info> get_uid_io_stats_locked();
+    // flushes curr_io_stats to records
+    void add_records_locked(uint64_t curr_ts);
+    // updates curr_io_stats and set last_uid_io_stats
+    void update_curr_io_stats_locked();
+
 public:
     uid_monitor();
     ~uid_monitor();
-    void set_periodic_chores_params(int intvl, int thold) { interval = intvl; threshold = thold; }
-    int get_periodic_chores_interval() { return interval; }
-    std::unordered_map<uint32_t, struct uid_info> get_uids();
+    // called by storaged main thread
+    void init(charger_stat_t stat);
+    // called by storaged -u
+    std::unordered_map<uint32_t, struct uid_info> get_uid_io_stats();
+    // called by dumpsys
+    std::map<uint64_t, std::vector<struct uid_record>> dump(int hours);
+    // called by battery properties listener
+    void set_charger_state(charger_stat_t stat);
+    // called by storaged periodic_chore
     void report();
-    void add_events(const std::vector<struct uid_event>& new_events, uint64_t curr_ts);
-    std::vector<struct uid_event> dump_events(int hours);
 };
 
 #endif /* _STORAGED_UID_MONITOR_H_ */
diff --git a/storaged/main.cpp b/storaged/main.cpp
index ee6a4c9..1103df2 100644
--- a/storaged/main.cpp
+++ b/storaged/main.cpp
@@ -88,6 +88,8 @@
 void* storaged_main(void* s) {
     storaged_t* storaged = (storaged_t*)s;
 
+    storaged->init_battery_service();
+
     LOG_TO(SYSTEM, INFO) << "storaged: Start";
 
     for (;;) {
diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp
index 73df6d0..2f02074 100644
--- a/storaged/storaged.cpp
+++ b/storaged/storaged.cpp
@@ -21,6 +21,9 @@
 #include <unistd.h>
 
 #include <android-base/logging.h>
+#include <batteryservice/BatteryServiceConstants.h>
+#include <batteryservice/IBatteryPropertiesRegistrar.h>
+#include <binder/IServiceManager.h>
 #include <cutils/properties.h>
 #include <log/log.h>
 
@@ -157,6 +160,43 @@
     }
 }
 
+static sp<IBatteryPropertiesRegistrar> get_battery_properties_service() {
+    sp<IServiceManager> sm = defaultServiceManager();
+    if (sm == NULL) return NULL;
+
+    sp<IBinder> binder = sm->getService(String16("batteryproperties"));
+    if (binder == NULL) return NULL;
+
+    sp<IBatteryPropertiesRegistrar> battery_properties =
+        interface_cast<IBatteryPropertiesRegistrar>(binder);
+
+    return battery_properties;
+}
+
+static inline charger_stat_t is_charger_on(int64_t prop) {
+    return (prop == BATTERY_STATUS_CHARGING || prop == BATTERY_STATUS_FULL) ?
+        CHARGER_ON : CHARGER_OFF;
+}
+
+void storaged_t::batteryPropertiesChanged(struct BatteryProperties props) {
+    mUidm.set_charger_state(is_charger_on(props.batteryStatus));
+}
+
+void storaged_t::init_battery_service() {
+    sp<IBatteryPropertiesRegistrar> battery_properties = get_battery_properties_service();
+    if (battery_properties == NULL) {
+        LOG_TO(SYSTEM, WARNING) << "failed to find batteryproperties service";
+        return;
+    }
+
+    struct BatteryProperty val;
+    battery_properties->getProperty(BATTERY_PROP_BATTERY_STATUS, &val);
+    mUidm.init(is_charger_on(val.valueInt64));
+
+    // register listener after init uid_monitor
+    battery_properties->registerListener(this);
+}
+
 /* storaged_t */
 storaged_t::storaged_t(void) {
     mConfig.emmc_available = (access(EMMC_ECSD_PATH, R_OK) >= 0);
@@ -181,9 +221,8 @@
     mConfig.periodic_chores_interval_emmc_info_publish =
         property_get_int32("ro.storaged.emmc_info_pub", DEFAULT_PERIODIC_CHORES_INTERVAL_EMMC_INFO_PUBLISH);
 
-    mUidm.set_periodic_chores_params(
-        property_get_int32("ro.storaged.uid_io.interval", DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO),
-        property_get_int32("ro.storaged.uid_io.threshold", DEFAULT_PERIODIC_CHORES_UID_IO_THRESHOLD));
+    mConfig.periodic_chores_interval_uid_io =
+        property_get_int32("ro.storaged.uid_io.interval", DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO);
 
     mStarttime = time(NULL);
 }
@@ -204,7 +243,7 @@
     }
 
     if (mConfig.proc_uid_io_available && mTimer &&
-            (mTimer % mUidm.get_periodic_chores_interval()) == 0) {
+            (mTimer % mConfig.periodic_chores_interval_uid_io) == 0) {
          mUidm.report();
     }
 
diff --git a/storaged/storaged_service.cpp b/storaged/storaged_service.cpp
index d81e0e5..66354314 100644
--- a/storaged/storaged_service.cpp
+++ b/storaged/storaged_service.cpp
@@ -99,20 +99,26 @@
         }
     }
 
-    const std::vector<struct uid_event>& events = storaged.get_uid_events(hours);
-    for (const auto& event : events) {
-        dprintf(fd, "%llu %s %llu %llu %llu %llu\n",
-            (unsigned long long)event.ts,
-            event.name.c_str(),
-            (unsigned long long)event.fg_read_bytes,
-            (unsigned long long)event.fg_write_bytes,
-            (unsigned long long)event.bg_read_bytes,
-            (unsigned long long)event.bg_write_bytes);
+    const std::map<uint64_t, std::vector<struct uid_record>>& records =
+                storaged.get_uid_records(hours);
+    for (const auto& it : records) {
+        dprintf(fd, "%llu\n", (unsigned long long)it.first);
+        for (const auto& record : it.second) {
+            dprintf(fd, "%s %llu %llu %llu %llu %llu %llu %llu %llu\n",
+                record.name.c_str(),
+                (unsigned long long)record.ios.bytes[READ][FOREGROUND][CHARGER_OFF],
+                (unsigned long long)record.ios.bytes[WRITE][FOREGROUND][CHARGER_OFF],
+                (unsigned long long)record.ios.bytes[READ][BACKGROUND][CHARGER_OFF],
+                (unsigned long long)record.ios.bytes[WRITE][BACKGROUND][CHARGER_OFF],
+                (unsigned long long)record.ios.bytes[READ][FOREGROUND][CHARGER_ON],
+                (unsigned long long)record.ios.bytes[WRITE][FOREGROUND][CHARGER_ON],
+                (unsigned long long)record.ios.bytes[READ][BACKGROUND][CHARGER_ON],
+                (unsigned long long)record.ios.bytes[WRITE][BACKGROUND][CHARGER_ON]);
+        }
     }
     return NO_ERROR;
 }
 
-
 sp<IStoraged> get_storaged_service() {
     sp<IServiceManager> sm = defaultServiceManager();
     if (sm == NULL) return NULL;
diff --git a/storaged/storaged_uid_monitor.cpp b/storaged/storaged_uid_monitor.cpp
index 93c9df4..b46d09a 100644
--- a/storaged/storaged_uid_monitor.cpp
+++ b/storaged/storaged_uid_monitor.cpp
@@ -49,20 +49,19 @@
     return true;
 }
 
-void uid_monitor::set_last_uids(std::unordered_map<uint32_t, struct uid_info>&& uids,
-            uint64_t ts)
+std::unordered_map<uint32_t, struct uid_info> uid_monitor::get_uid_io_stats()
 {
-    last_uids = uids;
-    last_report_ts = ts;
-}
+    std::unique_ptr<lock_t> lock(new lock_t(&um_lock));
+    return get_uid_io_stats_locked();
+};
 
-std::unordered_map<uint32_t, struct uid_info> uid_monitor::get_uids()
+std::unordered_map<uint32_t, struct uid_info> uid_monitor::get_uid_io_stats_locked()
 {
-    std::unordered_map<uint32_t, struct uid_info> uids;
+    std::unordered_map<uint32_t, struct uid_info> uid_io_stats;
     std::string buffer;
     if (!android::base::ReadFileToString(UID_IO_STATS_PATH, &buffer)) {
         PLOG_TO(SYSTEM, ERROR) << UID_IO_STATS_PATH << ": ReadFileToString failed";
-        return uids;
+        return uid_io_stats;
     }
 
     std::stringstream ss(buffer);
@@ -70,144 +69,167 @@
     bool refresh_uid = false;
 
     while (ss >> u.uid) {
-        ss >> u.io[UID_FOREGROUND].rchar >> u.io[UID_FOREGROUND].wchar
-           >> u.io[UID_FOREGROUND].read_bytes >> u.io[UID_FOREGROUND].write_bytes
-           >> u.io[UID_BACKGROUND].rchar >> u.io[UID_BACKGROUND].wchar
-           >> u.io[UID_BACKGROUND].read_bytes >> u.io[UID_BACKGROUND].write_bytes;
+        ss >> u.io[FOREGROUND].rchar >> u.io[FOREGROUND].wchar
+           >> u.io[FOREGROUND].read_bytes >> u.io[FOREGROUND].write_bytes
+           >> u.io[BACKGROUND].rchar >> u.io[BACKGROUND].wchar
+           >> u.io[BACKGROUND].read_bytes >> u.io[BACKGROUND].write_bytes;
 
         if (!ss.good()) {
             ss.clear(std::ios_base::badbit);
             break;
         }
 
-        if (last_uids.find(u.uid) == last_uids.end()) {
+        if (last_uid_io_stats.find(u.uid) == last_uid_io_stats.end()) {
             refresh_uid = true;
             u.name = std::to_string(u.uid);
         } else {
-            u.name = last_uids[u.uid].name;
+            u.name = last_uid_io_stats[u.uid].name;
         }
-        uids[u.uid] = u;
+        uid_io_stats[u.uid] = u;
     }
 
     if (!ss.eof() || ss.bad()) {
-        uids.clear();
+        uid_io_stats.clear();
         LOG_TO(SYSTEM, ERROR) << "read UID IO stats failed";
     }
 
     if (refresh_uid) {
-        packagelist_parse(packagelist_parse_cb, &uids);
+        packagelist_parse(packagelist_parse_cb, &uid_io_stats);
     }
 
-    return uids;
+    return uid_io_stats;
 }
 
-static const int MAX_UID_EVENTS_SIZE = 1000 * 48; // 1000 uids in 48 hours
+static const int MAX_UID_RECORDS_SIZE = 1000 * 48; // 1000 uids in 48 hours
 
-void uid_monitor::add_events(const std::vector<struct uid_event>& new_events,
-                             uint64_t curr_ts)
+static inline int records_size(
+    const std::map<uint64_t, std::vector<struct uid_record>>& records)
 {
-    std::unique_ptr<lock_t> lock(new lock_t(&events_lock));
-
-    // remove events more than 5 days old
-    struct uid_event first_event;
-    first_event.ts = curr_ts / SEC_TO_USEC - 5 * DAY_TO_SEC;
-    auto it = std::upper_bound(events.begin(), events.end(), first_event);
-    events.erase(events.begin(), it);
-
-    // make some room for new events
-    int overflow = events.size() + new_events.size() - MAX_UID_EVENTS_SIZE;
-    if (overflow > 0)
-        events.erase(events.begin(), events.begin() + overflow);
-
-    events.insert(events.end(), new_events.begin(), new_events.end());
+    int count = 0;
+    for (auto const& it : records) {
+        count += it.second.size();
+    }
+    return count;
 }
 
-std::vector<struct uid_event> uid_monitor::dump_events(int hours)
+static struct uid_io_usage zero_io_usage;
+
+void uid_monitor::add_records_locked(uint64_t curr_ts)
 {
-    std::unique_ptr<lock_t> lock(new lock_t(&events_lock));
-    std::vector<struct uid_event> dump_events;
-    struct timespec ts;
-
-    if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
-        PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed";
-        return dump_events;
+    // remove records more than 5 days old
+    if (curr_ts > 5 * DAY_TO_SEC) {
+        auto it = records.lower_bound(curr_ts - 5 * DAY_TO_SEC);
+        records.erase(records.begin(), it);
     }
 
-    struct uid_event first_event;
-    if (hours == 0) {
-        first_event.ts = 0; // dump all events
-    } else {
-        first_event.ts = ts.tv_sec - (uint64_t)hours * HOUR_TO_SEC;
+    std::vector<struct uid_record> new_records;
+    for (const auto& p : curr_io_stats) {
+        struct uid_record record = {};
+        record.name = p.first;
+        record.ios = p.second;
+        if (memcmp(&record.ios, &zero_io_usage, sizeof(struct uid_io_usage))) {
+            new_records.push_back(record);
+        }
     }
-    auto it = std::upper_bound(events.begin(), events.end(), first_event);
 
-    dump_events.assign(it, events.end());
+    curr_io_stats.clear();
 
-    return dump_events;
+    if (new_records.empty())
+      return;
+
+    // make some room for new records
+    int overflow = records_size(records) +
+        new_records.size() - MAX_UID_RECORDS_SIZE;
+    while (overflow > 0 && records.size() > 0) {
+        overflow -= records[0].size();
+        records.erase(records.begin());
+    }
+
+    records[curr_ts].insert(records[curr_ts].end(),
+        new_records.begin(), new_records.end());
+}
+
+std::map<uint64_t, std::vector<struct uid_record>> uid_monitor::dump(int hours)
+{
+    std::unique_ptr<lock_t> lock(new lock_t(&um_lock));
+
+    std::map<uint64_t, std::vector<struct uid_record>> dump_records;
+    uint64_t first_ts = 0;
+
+    if (hours != 0) {
+        first_ts = time(NULL) - (uint64_t)hours * HOUR_TO_SEC;
+    }
+
+    dump_records.insert(records.lower_bound(first_ts), records.end());
+
+    return dump_records;
+}
+
+void uid_monitor::update_curr_io_stats_locked()
+{
+    std::unordered_map<uint32_t, struct uid_info> uid_io_stats =
+        get_uid_io_stats_locked();
+    if (uid_io_stats.empty()) {
+        return;
+    }
+
+    for (const auto& it : uid_io_stats) {
+        const struct uid_info& uid = it.second;
+
+        if (curr_io_stats.find(uid.name) == curr_io_stats.end()) {
+          curr_io_stats[uid.name] = {};
+        }
+
+        struct uid_io_usage& usage = curr_io_stats[uid.name];
+        usage.bytes[READ][FOREGROUND][charger_stat] +=
+            uid.io[FOREGROUND].read_bytes -
+            last_uid_io_stats[uid.uid].io[FOREGROUND].read_bytes;
+        usage.bytes[READ][BACKGROUND][charger_stat] +=
+            uid.io[BACKGROUND].read_bytes -
+            last_uid_io_stats[uid.uid].io[BACKGROUND].read_bytes;
+        usage.bytes[WRITE][FOREGROUND][charger_stat] +=
+            uid.io[FOREGROUND].write_bytes -
+            last_uid_io_stats[uid.uid].io[FOREGROUND].write_bytes;
+        usage.bytes[WRITE][BACKGROUND][charger_stat] +=
+            uid.io[BACKGROUND].write_bytes -
+            last_uid_io_stats[uid.uid].io[BACKGROUND].write_bytes;;
+    }
+
+    last_uid_io_stats = uid_io_stats;
 }
 
 void uid_monitor::report()
 {
-    struct timespec ts;
+    std::unique_ptr<lock_t> lock(new lock_t(&um_lock));
 
-    // Use monotonic to exclude suspend time so that we measure IO bytes/sec
-    // when system is running.
-    if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
-        PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed";
+    update_curr_io_stats_locked();
+    add_records_locked(time(NULL));
+}
+
+void uid_monitor::set_charger_state(charger_stat_t stat)
+{
+    std::unique_ptr<lock_t> lock(new lock_t(&um_lock));
+
+    if (charger_stat == stat) {
         return;
     }
 
-    uint64_t curr_ts = ts.tv_sec * NS_PER_SEC + ts.tv_nsec;
-    uint64_t ts_delta = curr_ts - last_report_ts;
-    uint64_t adjusted_threshold = threshold * ((double)ts_delta / interval / NS_PER_SEC);
+    update_curr_io_stats_locked();
+    charger_stat = stat;
+}
 
-    std::unordered_map<uint32_t, struct uid_info> uids = get_uids();
-    if (uids.empty()) {
-        return;
-    }
-
-    std::vector<struct uid_event> new_events;
-    for (const auto& it : uids) {
-        const struct uid_info& uid = it.second;
-        struct uid_event event;
-
-        event.ts = ts.tv_sec;
-        event.name = uid.name;
-        event.fg_read_bytes = uid.io[UID_FOREGROUND].read_bytes -
-            last_uids[uid.uid].io[UID_FOREGROUND].read_bytes;;
-        event.fg_write_bytes = uid.io[UID_FOREGROUND].write_bytes -
-            last_uids[uid.uid].io[UID_FOREGROUND].write_bytes;;
-        event.bg_read_bytes = uid.io[UID_BACKGROUND].read_bytes -
-            last_uids[uid.uid].io[UID_BACKGROUND].read_bytes;;
-        event.bg_write_bytes = uid.io[UID_BACKGROUND].write_bytes -
-            last_uids[uid.uid].io[UID_BACKGROUND].write_bytes;;
-
-        if (event.fg_read_bytes + event.fg_write_bytes +
-            event.bg_read_bytes + event.bg_write_bytes == 0) {
-            continue;
-        }
-
-        new_events.push_back(event);
-    }
-
-    add_events(new_events, curr_ts);
-    set_last_uids(std::move(uids), curr_ts);
+void uid_monitor::init(charger_stat_t stat)
+{
+    charger_stat = stat;
+    last_uid_io_stats = get_uid_io_stats();
 }
 
 uid_monitor::uid_monitor()
 {
-    struct timespec ts;
-
-    if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
-        PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed";
-        return;
-    }
-    last_report_ts = ts.tv_sec * NS_PER_SEC + ts.tv_nsec;
-
-    sem_init(&events_lock, 0, 1);
+    sem_init(&um_lock, 0, 1);
 }
 
 uid_monitor::~uid_monitor()
 {
-    sem_destroy(&events_lock);
+    sem_destroy(&um_lock);
 }
diff --git a/storaged/storaged_utils.cpp b/storaged/storaged_utils.cpp
index 51ea64f..1ef89af 100644
--- a/storaged/storaged_utils.cpp
+++ b/storaged/storaged_utils.cpp
@@ -247,7 +247,7 @@
 
 static bool cmp_uid_info(struct uid_info l, struct uid_info r) {
     // Compare background I/O first.
-    for (int i = UID_STATS_SIZE - 1; i >= 0; i--) {
+    for (int i = UID_STATS - 1; i >= 0; i--) {
         uint64_t l_bytes = l.io[i].read_bytes + l.io[i].write_bytes;
         uint64_t r_bytes = r.io[i].read_bytes + r.io[i].write_bytes;
         uint64_t l_chars = l.io[i].rchar + l.io[i].wchar;