Revert "support work chain in pulled atoms"

This reverts commit ce8e4dce609541f90c444f27250a6a341b3f1d23.

Reason for revert: breaking multiple targets in master

Change-Id: I3ee74b314e06cb2c4d3d6da82ca116a91aad67d4
diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
index 4e4b8f3..3eb05a9 100644
--- a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
+++ b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
@@ -59,7 +59,7 @@
         }
         data->clear();
         for (const StatsLogEventWrapper& it : returned_value) {
-            LogEvent::createLogEvents(it, *data);
+            data->push_back(make_shared<LogEvent>(it));
         }
         VLOG("StatsCompanionServicePuller::pull succeeded for %d", mTagId);
         return true;
diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp
index f501574..e3f251a 100644
--- a/cmds/statsd/src/external/StatsPuller.cpp
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -32,10 +32,9 @@
 sp<UidMap> StatsPuller::mUidMap = nullptr;
 void StatsPuller::SetUidMap(const sp<UidMap>& uidMap) { mUidMap = uidMap; }
 
+// ValueMetric has a minimum bucket size of 10min so that we don't pull too frequently
 StatsPuller::StatsPuller(const int tagId)
     : mTagId(tagId) {
-    // Pullers can cause significant impact to system health and battery.
-    // So that we don't pull too frequently.
     mCoolDownNs = StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.coolDownNs;
     VLOG("Puller for tag %d created. Cooldown set to %lld", mTagId, (long long)mCoolDownNs);
 }
@@ -65,8 +64,8 @@
         data->setLogdWallClockTimestampNs(wallClockTimeNs);
     }
     if (ret && mCachedData.size() > 0) {
-        mapAndMergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId);
-        (*data) = mCachedData;
+      mergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId);
+      (*data) = mCachedData;
     }
     StatsdStats::getInstance().notePullDelay(mTagId, getElapsedRealtimeNs() - elapsedTimeNs);
     return ret;
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index cbf87a1..ab635a0 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -54,42 +54,52 @@
         // wifi_bytes_transfer
         {android::util::WIFI_BYTES_TRANSFER,
          {{2, 3, 4, 5},
+          {},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER)}},
         // wifi_bytes_transfer_by_fg_bg
         {android::util::WIFI_BYTES_TRANSFER_BY_FG_BG,
          {{3, 4, 5, 6},
+          {2},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)}},
         // mobile_bytes_transfer
         {android::util::MOBILE_BYTES_TRANSFER,
          {{2, 3, 4, 5},
+          {},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER)}},
         // mobile_bytes_transfer_by_fg_bg
         {android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG,
          {{3, 4, 5, 6},
+          {2},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)}},
         // bluetooth_bytes_transfer
         {android::util::BLUETOOTH_BYTES_TRANSFER,
          {{2, 3},
+          {},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::BLUETOOTH_BYTES_TRANSFER)}},
         // kernel_wakelock
         {android::util::KERNEL_WAKELOCK,
-         {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}},
+         {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}},
         // subsystem_sleep_state
         {android::util::SUBSYSTEM_SLEEP_STATE,
-         {{}, 1 * NS_PER_SEC, new SubsystemSleepStatePuller()}},
+         {{}, {}, 1 * NS_PER_SEC, new SubsystemSleepStatePuller()}},
         // on_device_power_measurement
-        {android::util::ON_DEVICE_POWER_MEASUREMENT, {{}, 1 * NS_PER_SEC, new PowerStatsPuller()}},
+        {android::util::ON_DEVICE_POWER_MEASUREMENT,
+         {{}, {}, 1 * NS_PER_SEC, new PowerStatsPuller()}},
         // cpu_time_per_freq
         {android::util::CPU_TIME_PER_FREQ,
-         {{3}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}},
+         {{3},
+          {2},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}},
         // cpu_time_per_uid
         {android::util::CPU_TIME_PER_UID,
          {{2, 3},
+          {},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID)}},
         // cpu_time_per_uid_freq
@@ -97,135 +107,162 @@
         // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
         {android::util::CPU_TIME_PER_UID_FREQ,
          {{4},
+          {2, 3},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID_FREQ)}},
         // cpu_active_time
         // the throttling is 3sec, handled in
         // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
         {android::util::CPU_ACTIVE_TIME,
-         {{2}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_ACTIVE_TIME)}},
+         {{2},
+          {},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::CPU_ACTIVE_TIME)}},
         // cpu_cluster_time
         // the throttling is 3sec, handled in
         // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
         {android::util::CPU_CLUSTER_TIME,
-         {{3}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_CLUSTER_TIME)}},
+         {{3},
+          {2},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::CPU_CLUSTER_TIME)}},
         // wifi_activity_energy_info
         {android::util::WIFI_ACTIVITY_INFO,
-         {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::WIFI_ACTIVITY_INFO)}},
+         {{},
+          {},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::WIFI_ACTIVITY_INFO)}},
         // modem_activity_info
         {android::util::MODEM_ACTIVITY_INFO,
-         {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}},
+         {{},
+          {},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}},
         // bluetooth_activity_info
         {android::util::BLUETOOTH_ACTIVITY_INFO,
          {{},
+          {},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::BLUETOOTH_ACTIVITY_INFO)}},
         // system_elapsed_realtime
         {android::util::SYSTEM_ELAPSED_REALTIME,
          {{},
+          {},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::SYSTEM_ELAPSED_REALTIME)}},
         // system_uptime
         {android::util::SYSTEM_UPTIME,
-         {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}},
+         {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}},
         // remaining_battery_capacity
         {android::util::REMAINING_BATTERY_CAPACITY,
          {{},
+          {},
           1 * NS_PER_SEC,
           new ResourceHealthManagerPuller(android::util::REMAINING_BATTERY_CAPACITY)}},
         // full_battery_capacity
         {android::util::FULL_BATTERY_CAPACITY,
          {{},
+          {},
           1 * NS_PER_SEC,
           new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}},
         // battery_voltage
         {android::util::BATTERY_VOLTAGE,
-         {{}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}},
-         // battery_level
+         {{}, {}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}},
+         // battery_voltage
         {android::util::BATTERY_LEVEL,
-         {{}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_LEVEL)}},
+         {{}, {}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_LEVEL)}},
         // process_memory_state
         {android::util::PROCESS_MEMORY_STATE,
          {{4, 5, 6, 7, 8, 9},
+          {2, 3, 10},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}},
         // native_process_memory_state
         {android::util::NATIVE_PROCESS_MEMORY_STATE,
          {{3, 4, 5, 6},
+          {2, 7},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::NATIVE_PROCESS_MEMORY_STATE)}},
         {android::util::PROCESS_MEMORY_HIGH_WATER_MARK,
          {{3},
+          {2},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_HIGH_WATER_MARK)}},
         // temperature
-        {android::util::TEMPERATURE, {{}, 1 * NS_PER_SEC, new ResourceThermalManagerPuller()}},
+        {android::util::TEMPERATURE, {{}, {}, 1 * NS_PER_SEC, new ResourceThermalManagerPuller()}},
         // binder_calls
         {android::util::BINDER_CALLS,
          {{4, 5, 6, 8, 12},
+          {2, 3, 7, 9, 10, 11, 13},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::BINDER_CALLS)}},
         // binder_calls_exceptions
         {android::util::BINDER_CALLS_EXCEPTIONS,
          {{},
+          {},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}},
         // looper_stats
         {android::util::LOOPER_STATS,
          {{5, 6, 7, 8, 9},
+          {2, 3, 4, 10},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::LOOPER_STATS)}},
         // Disk Stats
         {android::util::DISK_STATS,
-         {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DISK_STATS)}},
+         {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DISK_STATS)}},
         // Directory usage
         {android::util::DIRECTORY_USAGE,
-         {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DIRECTORY_USAGE)}},
+         {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DIRECTORY_USAGE)}},
         // Size of app's code, data, and cache
         {android::util::APP_SIZE,
-         {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::APP_SIZE)}},
+         {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::APP_SIZE)}},
         // Size of specific categories of files. Eg. Music.
         {android::util::CATEGORY_SIZE,
-         {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}},
+         {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}},
         // Number of fingerprints registered to each user.
         {android::util::NUM_FINGERPRINTS,
-         {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS)}},
+         {{},
+          {},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS)}},
         // ProcStats.
         {android::util::PROC_STATS,
-         {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS)}},
+         {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS)}},
         // ProcStatsPkgProc.
         {android::util::PROC_STATS_PKG_PROC,
-         {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS_PKG_PROC)}},
+         {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS_PKG_PROC)}},
         // Disk I/O stats per uid.
         {android::util::DISK_IO,
-         {{2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
+         {{2,3,4,5,6,7,8,9,10,11},
+          {},
           3 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::DISK_IO)}},
         // PowerProfile constants for power model calculations.
         {android::util::POWER_PROFILE,
-         {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::POWER_PROFILE)}},
+         {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::POWER_PROFILE)}},
         // Process cpu stats. Min cool-down is 5 sec, inline with what AcitivityManagerService uses.
         {android::util::PROCESS_CPU_TIME,
-         {{} /* additive fields */,
-          5 * NS_PER_SEC /* min cool-down in seconds*/,
-          new StatsCompanionServicePuller(android::util::PROCESS_CPU_TIME)}},
+            {{} /* additive fields */, {} /* non additive fields */,
+             5 * NS_PER_SEC /* min cool-down in seconds*/,
+             new StatsCompanionServicePuller(android::util::PROCESS_CPU_TIME)}},
         {android::util::CPU_TIME_PER_THREAD_FREQ,
          {{7},
+          {2, 3, 4, 5, 6},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::CPU_TIME_PER_THREAD_FREQ)}},
         // DeviceCalculatedPowerUse.
         {android::util::DEVICE_CALCULATED_POWER_USE,
-         {{},
-          1 * NS_PER_SEC,
+         {{}, {}, 1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_USE)}},
         // DeviceCalculatedPowerBlameUid.
         {android::util::DEVICE_CALCULATED_POWER_BLAME_UID,
-         {{},  // BatteryStats already merged isolated with host ids so it's unnecessary here.
+         {{}, {}, // BatteryStats already merged isolated with host ids so it's unnecessary here.
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_BLAME_UID)}},
         // DeviceCalculatedPowerBlameOther.
         {android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER,
-         {{},
+         {{}, {},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER)}},
 };
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index 3350736..bbf5d9d 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -36,6 +36,9 @@
     // The field numbers of the fields that need to be summed when merging
     // isolated uid with host uid.
     std::vector<int> additiveFields;
+    // The field numbers of the fields that can't be merged when merging
+    // data belong to isolated uid and host uid.
+    std::vector<int> nonAdditiveFields;
     // How long should the puller wait before doing an actual pull again. Default
     // 1 sec. Set this to 0 if this is handled elsewhere.
     int64_t coolDownNs = 1 * NS_PER_SEC;
diff --git a/cmds/statsd/src/external/puller_util.cpp b/cmds/statsd/src/external/puller_util.cpp
index 0b9b6ab..ea7fa97 100644
--- a/cmds/statsd/src/external/puller_util.cpp
+++ b/cmds/statsd/src/external/puller_util.cpp
@@ -25,13 +25,67 @@
 namespace os {
 namespace statsd {
 
-using std::list;
 using std::map;
-using std::set;
 using std::shared_ptr;
-using std::sort;
 using std::vector;
 
+namespace {
+bool shouldMerge(shared_ptr<LogEvent>& lhs, shared_ptr<LogEvent>& rhs,
+                 const vector<int>& nonAdditiveFields) {
+    const auto& l_values = lhs->getValues();
+    const auto& r_values = rhs->getValues();
+
+    for (size_t i : nonAdditiveFields) {
+        // We store everything starting from index 0, so we need to use i-1
+        if (!(l_values.size() > i - 1 && r_values.size() > i - 1 &&
+              l_values[i - 1].mValue == r_values[i - 1].mValue)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+// merge rhs to lhs
+// when calling this function, all sanity check should be done already.
+// e.g., index boundary, nonAdditiveFields matching etc.
+bool mergeEvent(shared_ptr<LogEvent>& lhs, shared_ptr<LogEvent>& rhs,
+                const vector<int>& additiveFields) {
+    vector<FieldValue>* host_values = lhs->getMutableValues();
+    const auto& child_values = rhs->getValues();
+    for (int i : additiveFields) {
+        Value& host = (*host_values)[i - 1].mValue;
+        const Value& child = (child_values[i - 1]).mValue;
+        if (child.getType() != host.getType()) {
+            return false;
+        }
+        switch (child.getType()) {
+            case INT:
+                host.setInt(host.int_value + child.int_value);
+                break;
+            case LONG:
+                host.setLong(host.long_value + child.long_value);
+                break;
+            default:
+                ALOGE("Tried to merge 2 fields with unsupported type");
+                return false;
+        }
+    }
+    return true;
+}
+
+bool tryMerge(vector<shared_ptr<LogEvent>>& data, int child_pos, const vector<int>& host_pos,
+              const vector<int>& nonAdditiveFields, const vector<int>& additiveFields) {
+    for (const auto& pos : host_pos) {
+        if (shouldMerge(data[pos], data[child_pos], nonAdditiveFields) &&
+            mergeEvent(data[pos], data[child_pos], additiveFields)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+}  // namespace
+
 /**
  * Process all data and merge isolated with host if necessary.
  * For example:
@@ -41,7 +95,7 @@
  *       int byte_send = 3;
  *       int byte_recv = 4;
  *   }
- *   additive fields are {3, 4}
+ *   additive fields are {3, 4}, non-additive field is {2}
  * If we pulled the following events (uid1_child is an isolated uid which maps to uid1):
  * [uid1, fg, 100, 200]
  * [uid1_child, fg, 100, 200]
@@ -50,119 +104,65 @@
  * We want to merge them and results should be:
  * [uid1, fg, 200, 400]
  * [uid1, bg, 100, 200]
- *
- * All atoms should be of the same tagId. All fields should be present.
  */
-void mapAndMergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const sp<UidMap>& uidMap,
-                                      int tagId) {
+void mergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const sp<UidMap>& uidMap,
+                                int tagId) {
     if (StatsPullerManager::kAllPullAtomInfo.find(tagId) ==
         StatsPullerManager::kAllPullAtomInfo.end()) {
         VLOG("Unknown pull atom id %d", tagId);
         return;
     }
-    if ((android::util::AtomsInfo::kAtomsWithAttributionChain.find(tagId) ==
-         android::util::AtomsInfo::kAtomsWithAttributionChain.end()) &&
-        (android::util::AtomsInfo::kAtomsWithUidField.find(tagId) ==
-         android::util::AtomsInfo::kAtomsWithUidField.end())) {
-        VLOG("No uid or attribution chain to merge, atom %d", tagId);
+    int uidField;
+    auto it = android::util::AtomsInfo::kAtomsWithUidField.find(tagId);
+    if (it == android::util::AtomsInfo::kAtomsWithUidField.end()) {
+        VLOG("No uid to merge for atom %d", tagId);
         return;
+    } else {
+        uidField = it->second;  // uidField is the field number in proto,
     }
+    const vector<int>& additiveFields =
+            StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.additiveFields;
+    const vector<int>& nonAdditiveFields =
+            StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.nonAdditiveFields;
 
-    // 1. Map all isolated uid in-place to host uid
-    for (shared_ptr<LogEvent>& event : data) {
-        if (event->GetTagId() != tagId) {
-            ALOGE("Wrong atom. Expecting %d, got %d", tagId, event->GetTagId());
-            return;
-        }
-        if (android::util::AtomsInfo::kAtomsWithAttributionChain.find(tagId) !=
-            android::util::AtomsInfo::kAtomsWithAttributionChain.end()) {
-            for (auto& value : *(event->getMutableValues())) {
-                if (value.mField.getPosAtDepth(0) > kAttributionField) {
-                    break;
-                }
-                if (isAttributionUidField(value)) {
-                    const int hostUid = uidMap->getHostUidOrSelf(value.mValue.int_value);
-                    value.mValue.setInt(hostUid);
-                }
-            }
+    // map of host uid to their position in the original vector
+    map<int, vector<int>> hostPosition;
+    vector<bool> toRemove = vector<bool>(data.size(), false);
+
+    for (size_t i = 0; i < data.size(); i++) {
+        vector<FieldValue>* valueList = data[i]->getMutableValues();
+
+        int uid;
+        if (uidField > 0 && (int)data[i]->getValues().size() >= uidField &&
+            (data[i]->getValues())[uidField - 1].mValue.getType() == INT) {
+            uid = (*data[i]->getMutableValues())[uidField - 1].mValue.int_value;
         } else {
-            auto it = android::util::AtomsInfo::kAtomsWithUidField.find(tagId);
-            if (it != android::util::AtomsInfo::kAtomsWithUidField.end()) {
-                int uidField = it->second;  // uidField is the field number in proto,
-                // starting from 1
-                if (uidField > 0 && (int)event->getValues().size() >= uidField &&
-                    (event->getValues())[uidField - 1].mValue.getType() == INT) {
-                    Value& value = (*event->getMutableValues())[uidField - 1].mValue;
-                    const int hostUid = uidMap->getHostUidOrSelf(value.int_value);
-                    value.setInt(hostUid);
-                } else {
-                    ALOGE("Malformed log, uid not found. %s", event->ToString().c_str());
-                    return;
-                }
+            ALOGE("Malformed log, uid not found. %s", data[i]->ToString().c_str());
+            continue;
+        }
+
+        const int hostUid = uidMap->getHostUidOrSelf(uid);
+
+        if (hostUid != uid) {
+            (*valueList)[0].mValue.setInt(hostUid);
+        }
+        if (hostPosition.find(hostUid) == hostPosition.end()) {
+            hostPosition[hostUid].push_back(i);
+        } else {
+            if (tryMerge(data, i, hostPosition[hostUid], nonAdditiveFields, additiveFields)) {
+                toRemove[i] = true;
+            } else {
+                hostPosition[hostUid].push_back(i);
             }
         }
     }
 
-    // 2. sort the data, bit-wise
-    sort(data.begin(), data.end(),
-         [](const shared_ptr<LogEvent>& lhs, const shared_ptr<LogEvent>& rhs) {
-             if (lhs->size() != rhs->size()) {
-                 return lhs->size() < rhs->size();
-             }
-             const std::vector<FieldValue>& lhsValues = lhs->getValues();
-             const std::vector<FieldValue>& rhsValues = rhs->getValues();
-             for (int i = 0; i < (int)lhs->size(); i++) {
-                 if (lhsValues[i] != rhsValues[i]) {
-                     return lhsValues[i] < rhsValues[i];
-                 }
-             }
-             return false;
-         });
-
     vector<shared_ptr<LogEvent>> mergedData;
-    const vector<int>& additiveFieldsVec =
-            StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.additiveFields;
-    const set<int> additiveFields(additiveFieldsVec.begin(), additiveFieldsVec.end());
-    bool needMerge = true;
-
-    // 3. do the merge.
-    // The loop invariant is this: for every event, check if it differs on
-    // non-additive fields, or have different attribution chain length.
-    // If so, no need to merge, add itself to the result.
-    // Otherwise, merge the value onto the one immediately next to it.
-    for (int i = 0; i < (int)data.size() - 1; i++) {
-        // Size different, must be different chains.
-        if (data[i]->size() != data[i + 1]->size()) {
+    for (size_t i = 0; i < toRemove.size(); i++) {
+        if (!toRemove[i]) {
             mergedData.push_back(data[i]);
-            continue;
-        }
-        vector<FieldValue>* lhsValues = data[i]->getMutableValues();
-        vector<FieldValue>* rhsValues = data[i + 1]->getMutableValues();
-        needMerge = true;
-        for (int p = 0; p < (int)lhsValues->size(); p++) {
-            if ((*lhsValues)[p] != (*rhsValues)[p]) {
-                int pos = (*lhsValues)[p].mField.getPosAtDepth(0);
-                // Differ on non-additive field, abort.
-                if (additiveFields.find(pos) == additiveFields.end()) {
-                    needMerge = false;
-                    break;
-                }
-            }
-        }
-        if (!needMerge) {
-            mergedData.push_back(data[i]);
-            continue;
-        }
-        // This should be infrequent operation.
-        for (int p = 0; p < (int)lhsValues->size(); p++) {
-            int pos = (*lhsValues)[p].mField.getPosAtDepth(0);
-            if (additiveFields.find(pos) != additiveFields.end()) {
-                (*rhsValues)[p].mValue += (*lhsValues)[p].mValue;
-            }
         }
     }
-    mergedData.push_back(data.back());
-
     data.clear();
     data = mergedData;
 }
diff --git a/cmds/statsd/src/external/puller_util.h b/cmds/statsd/src/external/puller_util.h
index f703e6c..fd4a4a2 100644
--- a/cmds/statsd/src/external/puller_util.h
+++ b/cmds/statsd/src/external/puller_util.h
@@ -25,8 +25,8 @@
 namespace os {
 namespace statsd {
 
-void mapAndMergeIsolatedUidsToHostUid(std::vector<std::shared_ptr<LogEvent>>& data,
-                                      const sp<UidMap>& uidMap, int tagId);
+void mergeIsolatedUidsToHostUid(std::vector<std::shared_ptr<LogEvent>>& data,
+                                const sp<UidMap>& uidMap, int tagId);
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index b9732a5..625294c 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -41,28 +41,13 @@
     }
 }
 
-LogEvent::LogEvent(const StatsLogEventWrapper& statsLogEventWrapper, int workChainIndex) {
+LogEvent::LogEvent(const StatsLogEventWrapper& statsLogEventWrapper) {
     mTagId = statsLogEventWrapper.getTagId();
     mLogdTimestampNs = statsLogEventWrapper.getWallClockTimeNs();
     mElapsedTimestampNs = statsLogEventWrapper.getElapsedRealTimeNs();
     mLogUid = 0;
-    int workChainPosOffset = 0;
-    if (workChainIndex != -1) {
-        const WorkChain& wc = statsLogEventWrapper.getWorkChains()[workChainIndex];
-        // chains are at field 1, level 2
-        int depth = 2;
-        for (int i = 0; i < (int)wc.uids.size(); i++) {
-            int pos[] = {1, i + 1, 1};
-            mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(wc.uids[i])));
-            pos[2]++;
-            mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(wc.tags[i])));
-            mValues.back().mField.decorateLastPos(2);
-        }
-        mValues.back().mField.decorateLastPos(1);
-        workChainPosOffset = 1;
-    }
     for (int i = 0; i < (int)statsLogEventWrapper.getElements().size(); i++) {
-        Field field(statsLogEventWrapper.getTagId(), getSimpleField(i + 1 + workChainPosOffset));
+        Field field(statsLogEventWrapper.getTagId(), getSimpleField(i + 1));
         switch (statsLogEventWrapper.getElements()[i].type) {
             case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::INT:
                 mValues.push_back(
@@ -94,17 +79,6 @@
     }
 }
 
-void LogEvent::createLogEvents(const StatsLogEventWrapper& statsLogEventWrapper,
-                               std::vector<std::shared_ptr<LogEvent>>& logEvents) {
-    if (statsLogEventWrapper.getWorkChains().size() == 0) {
-        logEvents.push_back(std::make_shared<LogEvent>(statsLogEventWrapper, -1));
-    } else {
-        for (size_t i = 0; i < statsLogEventWrapper.getWorkChains().size(); i++) {
-            logEvents.push_back(std::make_shared<LogEvent>(statsLogEventWrapper, i));
-        }
-    }
-}
-
 LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs) {
     mLogdTimestampNs = wallClockTimestampNs;
     mTagId = tagId;
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 5408d17..3d5b2ab 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -65,16 +65,7 @@
      */
     explicit LogEvent(log_msg& msg);
 
-    /**
-     * Creates LogEvent from StatsLogEventWrapper.
-     */
-    static void createLogEvents(const StatsLogEventWrapper& statsLogEventWrapper,
-                                std::vector<std::shared_ptr<LogEvent>>& logEvents);
-
-    /**
-     * Construct one LogEvent from a StatsLogEventWrapper with the i-th work chain. -1 if no chain.
-     */
-    explicit LogEvent(const StatsLogEventWrapper& statsLogEventWrapper, int workChainIndex);
+    explicit LogEvent(const StatsLogEventWrapper& statsLogEventWrapper);
 
     /**
      * Constructs a LogEvent with synthetic data for testing. Must call init() before reading.
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 9fe84dc..c3912ee 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -165,7 +165,7 @@
     const bool mSkipZeroDiffOutput;
 
     FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsNoCondition);
-    FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering);
+  FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering);
     FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset);
     FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset);
     FRIEND_TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition);
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index b317361..4ac55b5 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -454,16 +454,6 @@
             ALOGW("cannot find \"what\" in ValueMetric \"%lld\"", (long long)metric.id());
             return false;
         }
-        if (!metric.has_value_field()) {
-            ALOGW("cannot find \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
-            return false;
-        }
-        std::vector<Matcher> fieldMatchers;
-        translateFieldMatcher(metric.value_field(), &fieldMatchers);
-        if (fieldMatchers.size() < 1) {
-            ALOGW("incorrect \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
-            return false;
-        }
 
         int metricIndex = allMetricProducers.size();
         metricMap.insert({metric.id(), metricIndex});
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index 90dfa87..6384757 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -394,167 +394,6 @@
     EXPECT_EQ(1.1f, item16.mValue.float_value);
 }
 
-TEST(LogEventTest, TestStatsLogEventWrapperNoChain) {
-    Parcel parcel;
-    // tag id
-    parcel.writeInt32(1);
-    // elapsed realtime
-    parcel.writeInt64(1111L);
-    // wallclock time
-    parcel.writeInt64(2222L);
-    // no chain
-    parcel.writeInt32(0);
-    // 2 data
-    parcel.writeInt32(2);
-    // int 6
-    parcel.writeInt32(1);
-    parcel.writeInt32(6);
-    // long 10
-    parcel.writeInt32(2);
-    parcel.writeInt64(10);
-    parcel.setDataPosition(0);
-
-    StatsLogEventWrapper statsLogEventWrapper;
-    EXPECT_EQ(NO_ERROR, statsLogEventWrapper.readFromParcel(&parcel));
-    EXPECT_EQ(1, statsLogEventWrapper.getTagId());
-    EXPECT_EQ(1111L, statsLogEventWrapper.getElapsedRealTimeNs());
-    EXPECT_EQ(2222L, statsLogEventWrapper.getWallClockTimeNs());
-    EXPECT_EQ(0, statsLogEventWrapper.getWorkChains().size());
-    EXPECT_EQ(2, statsLogEventWrapper.getElements().size());
-    EXPECT_EQ(6, statsLogEventWrapper.getElements()[0].int_value);
-    EXPECT_EQ(10L, statsLogEventWrapper.getElements()[1].long_value);
-    LogEvent event(statsLogEventWrapper, -1);
-    EXPECT_EQ(1, event.GetTagId());
-    EXPECT_EQ(1111L, event.GetElapsedTimestampNs());
-    EXPECT_EQ(2222L, event.GetLogdTimestampNs());
-    EXPECT_EQ(2, event.size());
-    EXPECT_EQ(6, event.getValues()[0].mValue.int_value);
-    EXPECT_EQ(10, event.getValues()[1].mValue.long_value);
-}
-
-TEST(LogEventTest, TestStatsLogEventWrapperWithChain) {
-    Parcel parcel;
-    // tag id
-    parcel.writeInt32(1);
-    // elapsed realtime
-    parcel.writeInt64(1111L);
-    // wallclock time
-    parcel.writeInt64(2222L);
-    // 3 chains
-    parcel.writeInt32(3);
-    // chain1, 2 nodes (1, "tag1") (2, "tag2")
-    parcel.writeInt32(2);
-    parcel.writeInt32(1);
-    parcel.writeString16(String16("tag1"));
-    parcel.writeInt32(2);
-    parcel.writeString16(String16("tag2"));
-    // chain2, 1 node (3, "tag3")
-    parcel.writeInt32(1);
-    parcel.writeInt32(3);
-    parcel.writeString16(String16("tag3"));
-    // chain3, 2 nodes (4, "") (5, "")
-    parcel.writeInt32(2);
-    parcel.writeInt32(4);
-    parcel.writeString16(String16(""));
-    parcel.writeInt32(5);
-    parcel.writeString16(String16(""));
-    // 2 data
-    parcel.writeInt32(2);
-    // int 6
-    parcel.writeInt32(1);
-    parcel.writeInt32(6);
-    // long 10
-    parcel.writeInt32(2);
-    parcel.writeInt64(10);
-    parcel.setDataPosition(0);
-
-    StatsLogEventWrapper statsLogEventWrapper;
-    EXPECT_EQ(NO_ERROR, statsLogEventWrapper.readFromParcel(&parcel));
-    EXPECT_EQ(1, statsLogEventWrapper.getTagId());
-    EXPECT_EQ(1111L, statsLogEventWrapper.getElapsedRealTimeNs());
-    EXPECT_EQ(2222L, statsLogEventWrapper.getWallClockTimeNs());
-    EXPECT_EQ(3, statsLogEventWrapper.getWorkChains().size());
-    EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[0].uids.size());
-    EXPECT_EQ(1, statsLogEventWrapper.getWorkChains()[0].uids[0]);
-    EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[0].uids[1]);
-    EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[0].tags.size());
-    EXPECT_EQ("tag1", statsLogEventWrapper.getWorkChains()[0].tags[0]);
-    EXPECT_EQ("tag2", statsLogEventWrapper.getWorkChains()[0].tags[1]);
-    EXPECT_EQ(1, statsLogEventWrapper.getWorkChains()[1].uids.size());
-    EXPECT_EQ(3, statsLogEventWrapper.getWorkChains()[1].uids[0]);
-    EXPECT_EQ(1, statsLogEventWrapper.getWorkChains()[1].tags.size());
-    EXPECT_EQ("tag3", statsLogEventWrapper.getWorkChains()[1].tags[0]);
-    EXPECT_EQ(2, statsLogEventWrapper.getElements().size());
-    EXPECT_EQ(6, statsLogEventWrapper.getElements()[0].int_value);
-    EXPECT_EQ(10L, statsLogEventWrapper.getElements()[1].long_value);
-    EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[2].uids.size());
-    EXPECT_EQ(4, statsLogEventWrapper.getWorkChains()[2].uids[0]);
-    EXPECT_EQ(5, statsLogEventWrapper.getWorkChains()[2].uids[1]);
-    EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[2].tags.size());
-    EXPECT_EQ("", statsLogEventWrapper.getWorkChains()[2].tags[0]);
-    EXPECT_EQ("", statsLogEventWrapper.getWorkChains()[2].tags[1]);
-
-    LogEvent event(statsLogEventWrapper, -1);
-    EXPECT_EQ(1, event.GetTagId());
-    EXPECT_EQ(1111L, event.GetElapsedTimestampNs());
-    EXPECT_EQ(2222L, event.GetLogdTimestampNs());
-    EXPECT_EQ(2, event.size());
-    EXPECT_EQ(6, event.getValues()[0].mValue.int_value);
-    EXPECT_EQ(10, event.getValues()[1].mValue.long_value);
-
-    LogEvent event1(statsLogEventWrapper, 0);
-
-    EXPECT_EQ(1, event1.GetTagId());
-    EXPECT_EQ(1111L, event1.GetElapsedTimestampNs());
-    EXPECT_EQ(2222L, event1.GetLogdTimestampNs());
-    EXPECT_EQ(6, event1.size());
-    EXPECT_EQ(1, event1.getValues()[0].mValue.int_value);
-    EXPECT_EQ(0x2010101, event1.getValues()[0].mField.getField());
-    EXPECT_EQ("tag1", event1.getValues()[1].mValue.str_value);
-    EXPECT_EQ(0x2010182, event1.getValues()[1].mField.getField());
-    EXPECT_EQ(2, event1.getValues()[2].mValue.int_value);
-    EXPECT_EQ(0x2010201, event1.getValues()[2].mField.getField());
-    EXPECT_EQ("tag2", event1.getValues()[3].mValue.str_value);
-    EXPECT_EQ(0x2018282, event1.getValues()[3].mField.getField());
-    EXPECT_EQ(6, event1.getValues()[4].mValue.int_value);
-    EXPECT_EQ(0x20000, event1.getValues()[4].mField.getField());
-    EXPECT_EQ(10, event1.getValues()[5].mValue.long_value);
-    EXPECT_EQ(0x30000, event1.getValues()[5].mField.getField());
-
-    LogEvent event2(statsLogEventWrapper, 1);
-
-    EXPECT_EQ(1, event2.GetTagId());
-    EXPECT_EQ(1111L, event2.GetElapsedTimestampNs());
-    EXPECT_EQ(2222L, event2.GetLogdTimestampNs());
-    EXPECT_EQ(4, event2.size());
-    EXPECT_EQ(3, event2.getValues()[0].mValue.int_value);
-    EXPECT_EQ(0x2010101, event2.getValues()[0].mField.getField());
-    EXPECT_EQ("tag3", event2.getValues()[1].mValue.str_value);
-    EXPECT_EQ(0x2018182, event2.getValues()[1].mField.getField());
-    EXPECT_EQ(6, event2.getValues()[2].mValue.int_value);
-    EXPECT_EQ(0x20000, event2.getValues()[2].mField.getField());
-    EXPECT_EQ(10, event2.getValues()[3].mValue.long_value);
-    EXPECT_EQ(0x30000, event2.getValues()[3].mField.getField());
-
-    LogEvent event3(statsLogEventWrapper, 2);
-
-    EXPECT_EQ(1, event3.GetTagId());
-    EXPECT_EQ(1111L, event3.GetElapsedTimestampNs());
-    EXPECT_EQ(2222L, event3.GetLogdTimestampNs());
-    EXPECT_EQ(6, event3.size());
-    EXPECT_EQ(4, event3.getValues()[0].mValue.int_value);
-    EXPECT_EQ(0x2010101, event3.getValues()[0].mField.getField());
-    EXPECT_EQ("", event3.getValues()[1].mValue.str_value);
-    EXPECT_EQ(0x2010182, event3.getValues()[1].mField.getField());
-    EXPECT_EQ(5, event3.getValues()[2].mValue.int_value);
-    EXPECT_EQ(0x2010201, event3.getValues()[2].mField.getField());
-    EXPECT_EQ("", event3.getValues()[3].mValue.str_value);
-    EXPECT_EQ(0x2018282, event3.getValues()[3].mField.getField());
-    EXPECT_EQ(6, event3.getValues()[4].mValue.int_value);
-    EXPECT_EQ(0x20000, event3.getValues()[4].mField.getField());
-    EXPECT_EQ(10, event3.getValues()[5].mValue.long_value);
-    EXPECT_EQ(0x30000, event3.getValues()[5].mField.getField());
-}
 
 TEST(LogEventTest, TestBinaryFieldAtom) {
     Atom launcherAtom;
diff --git a/cmds/statsd/tests/external/puller_util_test.cpp b/cmds/statsd/tests/external/puller_util_test.cpp
index 266ea35..fc6e420 100644
--- a/cmds/statsd/tests/external/puller_util_test.cpp
+++ b/cmds/statsd/tests/external/puller_util_test.cpp
@@ -80,7 +80,7 @@
       .WillRepeatedly(Return(hostUid));
   EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
       .WillRepeatedly(ReturnArg<0>());
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+  mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
 
   vector<vector<int>> actual;
   extractIntoVector(inputData, actual);
@@ -120,7 +120,7 @@
       .WillRepeatedly(Return(hostUid));
   EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
       .WillRepeatedly(ReturnArg<0>());
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+  mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
 
   vector<vector<int>> actual;
   extractIntoVector(inputData, actual);
@@ -154,7 +154,7 @@
       .WillRepeatedly(Return(hostUid));
   EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
       .WillRepeatedly(ReturnArg<0>());
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+  mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
 
   // 20->32->31
   // 20->22->21
@@ -190,7 +190,7 @@
       .WillRepeatedly(Return(hostUid));
   EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
       .WillRepeatedly(ReturnArg<0>());
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+  mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
 
   // 20->32->31
   // 20->22->21
@@ -231,7 +231,7 @@
 
   sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
   EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(Return(hostUid));
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+  mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
 
   vector<vector<int>> actual;
   extractIntoVector(inputData, actual);
@@ -256,7 +256,7 @@
   inputData.push_back(event);
 
   sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId);
+  mergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId);
 
   EXPECT_EQ(2, (int)inputData.size());
 }
diff --git a/core/java/android/os/StatsLogEventWrapper.java b/core/java/android/os/StatsLogEventWrapper.java
index acb9eac..866bd9a 100644
--- a/core/java/android/os/StatsLogEventWrapper.java
+++ b/core/java/android/os/StatsLogEventWrapper.java
@@ -43,7 +43,6 @@
     int mTag;
     long mElapsedTimeNs;
     long mWallClockTimeNs;
-    WorkSource mWorkSource = null;
 
     public StatsLogEventWrapper(int tag, long elapsedTimeNs, long wallClockTimeNs) {
         this.mTag = tag;
@@ -72,17 +71,6 @@
             };
 
     /**
-     * Set work source if any.
-     */
-    public void setWorkSource(WorkSource ws) {
-        if (ws.getWorkChains() == null || ws.getWorkChains().size() == 0) {
-            Slog.w(TAG, "Empty worksource!");
-            return;
-        }
-        mWorkSource = ws;
-    }
-
-    /**
      * Write a int value.
      */
     public void writeInt(int val) {
@@ -131,6 +119,11 @@
         mValues.add(val ? 1 : 0);
     }
 
+    /**
+     * Writes the stored fields to a byte array. Will first write a new-line character to denote
+     * END_LIST before writing contents to byte array.
+     */
+
     public void writeToParcel(Parcel out, int flags) {
         if (DEBUG) {
             Slog.d(TAG,
@@ -140,34 +133,6 @@
         out.writeInt(mTag);
         out.writeLong(mElapsedTimeNs);
         out.writeLong(mWallClockTimeNs);
-        if (mWorkSource != null) {
-            ArrayList<android.os.WorkSource.WorkChain> workChains = mWorkSource.getWorkChains();
-            // number of chains
-            out.writeInt(workChains.size());
-            for (int i = 0; i < workChains.size(); i++) {
-                android.os.WorkSource.WorkChain wc = workChains.get(i);
-                if (wc.getSize() == 0) {
-                    Slog.w(TAG, "Empty work chain.");
-                    out.writeInt(0);
-                    continue;
-                }
-                if (wc.getUids().length != wc.getTags().length
-                        || wc.getUids().length != wc.getSize()) {
-                    Slog.w(TAG, "Malformated work chain.");
-                    out.writeInt(0);
-                    continue;
-                }
-                // number of nodes
-                out.writeInt(wc.getSize());
-                for (int j = 0; j < wc.getSize(); j++) {
-                    out.writeInt(wc.getUids()[j]);
-                    out.writeString(wc.getTags()[j] == null ? "" : wc.getTags()[j]);
-                }
-            }
-        } else {
-            // no chains
-            out.writeInt(0);
-        }
         out.writeInt(mTypes.size());
         for (int i = 0; i < mTypes.size(); i++) {
             out.writeInt(mTypes.get(i));
diff --git a/libs/services/include/android/os/StatsLogEventWrapper.h b/libs/services/include/android/os/StatsLogEventWrapper.h
index 8de2ab4..f60c338 100644
--- a/libs/services/include/android/os/StatsLogEventWrapper.h
+++ b/libs/services/include/android/os/StatsLogEventWrapper.h
@@ -82,11 +82,6 @@
   STATS_LOG_VALUE_TYPE type;
 };
 
-struct WorkChain {
-  std::vector<int32_t> uids;
-  std::vector<std::string> tags;
-};
-
 // Represents a parcelable object. Only used to send data from Android OS to statsd.
 class StatsLogEventWrapper : public android::Parcelable {
  public:
@@ -104,9 +99,7 @@
 
   int64_t getWallClockTimeNs() const { return mWallClockTimeNs; }
 
-  const std::vector<StatsLogValue>& getElements() const { return mElements; }
-
-  const std::vector<WorkChain>& getWorkChains() const { return mWorkChains; }
+  std::vector<StatsLogValue> getElements() const { return mElements; }
 
  private:
   int mTagId;
@@ -116,8 +109,6 @@
   int64_t mWallClockTimeNs;
 
   std::vector<StatsLogValue> mElements;
-
-  std::vector<WorkChain> mWorkChains;
 };
 } // Namespace os
 } // Namespace android
diff --git a/libs/services/src/os/StatsLogEventWrapper.cpp b/libs/services/src/os/StatsLogEventWrapper.cpp
index f6dfdef..04c4629 100644
--- a/libs/services/src/os/StatsLogEventWrapper.cpp
+++ b/libs/services/src/os/StatsLogEventWrapper.cpp
@@ -58,31 +58,6 @@
     ALOGE("statsd could not read wall clock time from parcel");
     return res;
   }
-  int numWorkChain = 0;
-  if ((res = in->readInt32(&numWorkChain)) != OK) {
-    ALOGE("statsd could not read number of work chains from parcel");
-    return res;
-  }
-  if (numWorkChain > 0) {
-    for (int i = 0; i < numWorkChain; i++) {
-      int numNodes = 0;
-      if ((res = in->readInt32(&numNodes)) != OK) {
-        ALOGE(
-            "statsd could not read number of nodes in work chain from parcel");
-        return res;
-      }
-      if (numNodes == 0) {
-        ALOGE("empty work chain");
-        return BAD_VALUE;
-      }
-      WorkChain wc;
-      for (int j = 0; j < numNodes; j++) {
-        wc.uids.push_back(in->readInt32());
-        wc.tags.push_back(std::string(String8(in->readString16()).string()));
-      }
-      mWorkChains.push_back(wc);
-    }
-  }
   int dataSize = 0;
   if ((res = in->readInt32(&dataSize)) != OK) {
     ALOGE("statsd could not read data size from parcel");