Snap for 5719587 from 23add075b34cca3f58b1635b922f06d485194714 to qt-release

Change-Id: I9bda4c97158a5d6d8e27fa435837d858dec88f81
diff --git a/libraries/collectors-helper/statsd/src/com/android/helpers/CpuUsageHelper.java b/libraries/collectors-helper/statsd/src/com/android/helpers/CpuUsageHelper.java
index 2858c73..231100b 100644
--- a/libraries/collectors-helper/statsd/src/com/android/helpers/CpuUsageHelper.java
+++ b/libraries/collectors-helper/statsd/src/com/android/helpers/CpuUsageHelper.java
@@ -25,10 +25,12 @@
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ListMultimap;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.regex.Pattern;
 
 /**
  * CpuUsageHelper consist of helper methods to set the app
@@ -47,12 +49,18 @@
     private static final String FREQ_INDEX = "freq_index";
     private static final String USER_TIME = "user_time";
     private static final String SYSTEM_TIME = "system_time";
+    private static final String TOTAL_CPU_TIME = "total_cpu_time";
+    private static final String CPU_UTILIZATION = "cpu_utilization_average_per_core_percent";
 
     private StatsdHelper mStatsdHelper = new StatsdHelper();
     private boolean isPerFreqDisabled;
     private boolean isPerPkgDisabled;
     private boolean isTotalPkgDisabled;
     private boolean isTotalFreqDisabled;
+    private boolean isCpuUtilizationEnabled;
+    private long mStartTime;
+    private long mEndTime;
+    private Integer mCpuCores = null;
 
     @Override
     public boolean startCollecting() {
@@ -62,6 +70,10 @@
         atomIdList.add(Atom.CPU_TIME_PER_UID_FIELD_NUMBER);
         atomIdList.add(Atom.CPU_TIME_PER_FREQ_FIELD_NUMBER);
 
+        if (isCpuUtilizationEnabled) {
+            mStartTime = System.currentTimeMillis();
+        }
+
         return mStatsdHelper.addGaugeConfig(atomIdList);
     }
 
@@ -70,6 +82,11 @@
         Map<String, Long> cpuUsageFinalMap = new HashMap<>();
 
         List<GaugeMetricData> gaugeMetricList = mStatsdHelper.getGaugeMetrics();
+
+        if (isCpuUtilizationEnabled) {
+            mEndTime = System.currentTimeMillis();
+        }
+
         ListMultimap<String, Long> cpuUsageMap = ArrayListMultimap.create();
 
         for (GaugeMetricData gaugeMetric : gaugeMetricList) {
@@ -158,6 +175,18 @@
         if (!isTotalFreqDisabled) {
             cpuUsageFinalMap.put(TOTAL_CPU_USAGE_FREQ, totalCpuFreq);
         }
+
+        // Calculate cpu utilization
+        if (isCpuUtilizationEnabled) {
+            long totalCpuTime = (mEndTime - mStartTime) * getCores();
+            cpuUsageFinalMap.put(TOTAL_CPU_TIME, totalCpuTime);
+            if (!isTotalPkgDisabled) {
+                double utilization =
+                        ((double) cpuUsageFinalMap.get(TOTAL_CPU_USAGE) / totalCpuTime) * 100;
+                cpuUsageFinalMap.put(CPU_UTILIZATION, (long) utilization);
+            }
+        }
+
         return cpuUsageFinalMap;
     }
 
@@ -196,4 +225,30 @@
     public void setDisableTotalFrequency() {
         isTotalFreqDisabled = true;
     }
+
+    /**
+     * Enable the collection of cpu utilization.
+     */
+    public void setEnableCpuUtilization() {
+        isCpuUtilizationEnabled = true;
+    }
+
+    /**
+     * return the number of cores that the device has.
+     */
+    private int getCores() {
+        if (mCpuCores == null) {
+            int count = 0;
+            // every core corresponds to a folder named "cpu[0-9]+" under /sys/devices/system/cpu
+            File cpuDir = new File("/sys/devices/system/cpu");
+            File[] files = cpuDir.listFiles();
+            for (File file : files) {
+                if (Pattern.matches("cpu[0-9]+", file.getName())) {
+                    ++count;
+                }
+            }
+            mCpuCores = count;
+        }
+        return mCpuCores.intValue();
+    }
 }
diff --git a/libraries/collectors-helper/statsd/test/src/com/android/helpers/CpuUsageHelperTest.java b/libraries/collectors-helper/statsd/test/src/com/android/helpers/CpuUsageHelperTest.java
index 37e0ac4..ed55156 100644
--- a/libraries/collectors-helper/statsd/test/src/com/android/helpers/CpuUsageHelperTest.java
+++ b/libraries/collectors-helper/statsd/test/src/com/android/helpers/CpuUsageHelperTest.java
@@ -51,6 +51,10 @@
     private static final String TOTAL_CPU_USAGE = "total_cpu_usage";
     // Key used for total CPU usage in frequency buckets
     private static final String TOTAL_CPU_USAGE_FREQ = "total_cpu_usage_freq";
+    // key used for total CPU time
+    private static final String TOTAL_CPU_TIME = "total_cpu_time";
+    // Key used for CPU utilization average over each core
+    private static final String CPU_UTILIZATION = "cpu_utilization_average_per_core_percent";
 
     private CpuUsageHelper mCpuUsageHelper;
     private HelperAccessor<ICalendarHelper> mHelper =
@@ -206,4 +210,27 @@
         assertTrue(mCpuUsageHelper.stopCollecting());
         mHelper.get().exit();
     }
+
+    /**
+     * Test cpu utilization is collected.
+     */
+    @Test
+    public void testCpuEnableCpuUtilization() throws Exception {
+        mCpuUsageHelper.setEnableCpuUtilization();
+        assertTrue(mCpuUsageHelper.startCollecting());
+        mHelper.get().open();
+        Map<String, Long> cpuUsage = mCpuUsageHelper.getMetrics();
+        assertTrue(cpuUsage.size() > 3);
+        assertTrue(cpuUsage.containsKey(TOTAL_CPU_USAGE));
+        assertTrue(cpuUsage.containsKey(TOTAL_CPU_TIME));
+        assertTrue(cpuUsage.containsKey(CPU_UTILIZATION));
+        // TOTAL_CPU_TIME >= TOTAL_CPU_USAGE > 0
+        assertTrue(cpuUsage.get(TOTAL_CPU_TIME) >= cpuUsage.get(TOTAL_CPU_USAGE));
+        assertTrue(cpuUsage.get(TOTAL_CPU_USAGE) > 0);
+        // 100 >= CPU_UTILIZATION >=0 (%), it could be equal to 0 due to rounding.
+        assertTrue(100 >= cpuUsage.get(CPU_UTILIZATION));
+        assertTrue(cpuUsage.get(CPU_UTILIZATION) >= 0);
+        assertTrue(mCpuUsageHelper.stopCollecting());
+        mHelper.get().exit();
+    }
 }
diff --git a/libraries/device-collectors/src/main/platform-collectors/src/android/device/collectors/CpuUsageListener.java b/libraries/device-collectors/src/main/platform-collectors/src/android/device/collectors/CpuUsageListener.java
index 3835548..cefcb41 100644
--- a/libraries/device-collectors/src/main/platform-collectors/src/android/device/collectors/CpuUsageListener.java
+++ b/libraries/device-collectors/src/main/platform-collectors/src/android/device/collectors/CpuUsageListener.java
@@ -33,6 +33,7 @@
     private static final String DISABLE_PER_FREQ = "disable_per_freq";
     private static final String DISABLE_TOTAL_PKG = "disable_total_pkg";
     private static final String DISABLE_TOTAL_FREQ = "disable_total_freq";
+    private static final String ENABLE_CPU_UTILIZATION = "enable_cpu_utilization";
 
     public CpuUsageListener() {
         createHelperInstance(new CpuUsageHelper());
@@ -60,6 +61,10 @@
         if ("true".equals(args.getString(DISABLE_TOTAL_FREQ))) {
             cpuUsageHelper.setDisableTotalFrequency();
         }
+
+        if ("true".equals(args.getString(ENABLE_CPU_UTILIZATION))) {
+            cpuUsageHelper.setEnableCpuUtilization();
+        }
     }
 }