Track per-cluster times of each uid in microsec.

Bug: 62805443
Test: Used some apps and verified that battery usage is attributed to
      these apps in Settings>Battery.

Change-Id: I0e604fdc0d1704d7d061b6a711a0017b82a39b8f
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 54d5860..7d664ec 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -686,7 +686,7 @@
         public abstract long getSystemCpuTimeUs(int which);
 
         /**
-         * Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed for a
+         * Returns the approximate cpu time (in microseconds) spent at a certain CPU speed for a
          * given CPU cluster.
          * @param cluster the index of the CPU cluster.
          * @param step the index of the CPU speed. This is not the actual speed of the CPU.
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 3599e64..d7ecaec 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -119,7 +119,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 162 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 163 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS;
@@ -5702,7 +5702,7 @@
 
         LongSamplingCounter mUserCpuTime;
         LongSamplingCounter mSystemCpuTime;
-        LongSamplingCounter[][] mCpuClusterSpeed;
+        LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
 
         LongSamplingCounterArray mCpuFreqTimeMs;
         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
@@ -6551,12 +6551,12 @@
 
         @Override
         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
-            if (mCpuClusterSpeed != null) {
-                if (cluster >= 0 && cluster < mCpuClusterSpeed.length) {
-                    final LongSamplingCounter[] cpuSpeeds = mCpuClusterSpeed[cluster];
-                    if (cpuSpeeds != null) {
-                        if (step >= 0 && step < cpuSpeeds.length) {
-                            final LongSamplingCounter c = cpuSpeeds[step];
+            if (mCpuClusterSpeedTimesUs != null) {
+                if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
+                    final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
+                    if (cpuSpeedTimesUs != null) {
+                        if (step >= 0 && step < cpuSpeedTimesUs.length) {
+                            final LongSamplingCounter c = cpuSpeedTimesUs[step];
                             if (c != null) {
                                 return c.getCountLocked(which);
                             }
@@ -6707,8 +6707,8 @@
             mUserCpuTime.reset(false);
             mSystemCpuTime.reset(false);
 
-            if (mCpuClusterSpeed != null) {
-                for (LongSamplingCounter[] speeds : mCpuClusterSpeed) {
+            if (mCpuClusterSpeedTimesUs != null) {
+                for (LongSamplingCounter[] speeds : mCpuClusterSpeedTimesUs) {
                     if (speeds != null) {
                         for (LongSamplingCounter speed : speeds) {
                             if (speed != null) {
@@ -6897,8 +6897,8 @@
                 mUserCpuTime.detach();
                 mSystemCpuTime.detach();
 
-                if (mCpuClusterSpeed != null) {
-                    for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) {
+                if (mCpuClusterSpeedTimesUs != null) {
+                    for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
                         if (cpuSpeeds != null) {
                             for (LongSamplingCounter c : cpuSpeeds) {
                                 if (c != null) {
@@ -7151,10 +7151,10 @@
             mUserCpuTime.writeToParcel(out);
             mSystemCpuTime.writeToParcel(out);
 
-            if (mCpuClusterSpeed != null) {
+            if (mCpuClusterSpeedTimesUs != null) {
                 out.writeInt(1);
-                out.writeInt(mCpuClusterSpeed.length);
-                for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) {
+                out.writeInt(mCpuClusterSpeedTimesUs.length);
+                for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
                     if (cpuSpeeds != null) {
                         out.writeInt(1);
                         out.writeInt(cpuSpeeds.length);
@@ -7448,7 +7448,7 @@
                     throw new ParcelFormatException("Incompatible number of cpu clusters");
                 }
 
-                mCpuClusterSpeed = new LongSamplingCounter[numCpuClusters][];
+                mCpuClusterSpeedTimesUs = new LongSamplingCounter[numCpuClusters][];
                 for (int cluster = 0; cluster < numCpuClusters; cluster++) {
                     if (in.readInt() != 0) {
                         int numSpeeds = in.readInt();
@@ -7458,18 +7458,19 @@
                         }
 
                         final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
-                        mCpuClusterSpeed[cluster] = cpuSpeeds;
+                        mCpuClusterSpeedTimesUs[cluster] = cpuSpeeds;
                         for (int speed = 0; speed < numSpeeds; speed++) {
                             if (in.readInt() != 0) {
-                                cpuSpeeds[speed] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
+                                cpuSpeeds[speed] = new LongSamplingCounter(
+                                        mBsi.mOnBatteryTimeBase, in);
                             }
                         }
                     } else {
-                        mCpuClusterSpeed[cluster] = null;
+                        mCpuClusterSpeedTimesUs[cluster] = null;
                     }
                 }
             } else {
-                mCpuClusterSpeed = null;
+                mCpuClusterSpeedTimesUs = null;
             }
 
             mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
@@ -10424,46 +10425,48 @@
             }
         }
 
-        long totalCpuClustersTime = 0;
+        long totalCpuClustersTimeMs = 0;
         // Read the time spent for each cluster at various cpu frequencies.
-        final long[][] clusterSpeeds = new long[mKernelCpuSpeedReaders.length][];
+        final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
-            clusterSpeeds[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
-            if (clusterSpeeds[cluster] != null) {
-                for (int speed = clusterSpeeds[cluster].length - 1; speed >= 0; --speed) {
-                    totalCpuClustersTime += clusterSpeeds[cluster][speed];
+            clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
+            if (clusterSpeedTimesMs[cluster] != null) {
+                for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
+                    totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
                 }
             }
         }
-        if (totalCpuClustersTime != 0) {
+        if (totalCpuClustersTimeMs != 0) {
             // We have cpu times per freq aggregated over all uids but we need the times per uid.
             // So, we distribute total time spent by an uid to different cpu freqs based on the
             // amount of time cpu was running at that freq.
             final int updatedUidsCount = updatedUids.size();
             for (int i = 0; i < updatedUidsCount; ++i) {
                 final Uid u = getUidStatsLocked(updatedUids.keyAt(i));
-                final long appCpuTimeMs = updatedUids.valueAt(i) / 1000;
+                final long appCpuTimeUs = updatedUids.valueAt(i);
                 // Add the cpu speeds to this UID.
                 final int numClusters = mPowerProfile.getNumCpuClusters();
-                if (u.mCpuClusterSpeed == null || u.mCpuClusterSpeed.length !=
+                if (u.mCpuClusterSpeedTimesUs == null || u.mCpuClusterSpeedTimesUs.length !=
                         numClusters) {
-                    u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
+                    u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
                 }
 
-                for (int cluster = 0; cluster < clusterSpeeds.length; cluster++) {
-                    final int speedsInCluster = clusterSpeeds[cluster].length;
-                    if (u.mCpuClusterSpeed[cluster] == null || speedsInCluster !=
-                            u.mCpuClusterSpeed[cluster].length) {
-                        u.mCpuClusterSpeed[cluster] = new LongSamplingCounter[speedsInCluster];
+                for (int cluster = 0; cluster < clusterSpeedTimesMs.length; cluster++) {
+                    final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
+                    if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
+                            u.mCpuClusterSpeedTimesUs[cluster].length) {
+                        u.mCpuClusterSpeedTimesUs[cluster]
+                                = new LongSamplingCounter[speedsInCluster];
                     }
 
-                    final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeed[cluster];
+                    final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
                     for (int speed = 0; speed < speedsInCluster; speed++) {
                         if (cpuSpeeds[speed] == null) {
                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
                         }
-                        cpuSpeeds[speed].addCountLocked(appCpuTimeMs * clusterSpeeds[cluster][speed]
-                                / totalCpuClustersTime);
+                        cpuSpeeds[speed].addCountLocked(appCpuTimeUs
+                                * clusterSpeedTimesMs[cluster][speed]
+                                / totalCpuClustersTimeMs);
                     }
                 }
             }
@@ -11747,7 +11750,7 @@
                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
                 }
 
-                u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
+                u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
                 for (int cluster = 0; cluster < numClusters; cluster++) {
                     if (in.readInt() != 0) {
                         final int NSB = in.readInt();
@@ -11757,20 +11760,20 @@
                                     NSB);
                         }
 
-                        u.mCpuClusterSpeed[cluster] = new LongSamplingCounter[NSB];
+                        u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
                         for (int speed = 0; speed < NSB; speed++) {
                             if (in.readInt() != 0) {
-                                u.mCpuClusterSpeed[cluster][speed] = new LongSamplingCounter(
+                                u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
                                         mOnBatteryTimeBase);
-                                u.mCpuClusterSpeed[cluster][speed].readSummaryFromParcelLocked(in);
+                                u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
                             }
                         }
                     } else {
-                        u.mCpuClusterSpeed[cluster] = null;
+                        u.mCpuClusterSpeedTimesUs[cluster] = null;
                     }
                 }
             } else {
-                u.mCpuClusterSpeed = null;
+                u.mCpuClusterSpeedTimesUs = null;
             }
 
             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
@@ -12178,10 +12181,10 @@
             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
 
-            if (u.mCpuClusterSpeed != null) {
+            if (u.mCpuClusterSpeedTimesUs != null) {
                 out.writeInt(1);
-                out.writeInt(u.mCpuClusterSpeed.length);
-                for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeed) {
+                out.writeInt(u.mCpuClusterSpeedTimesUs.length);
+                for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
                     if (cpuSpeeds != null) {
                         out.writeInt(1);
                         out.writeInt(cpuSpeeds.length);
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index 9d52e19..bb743c1 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -22,6 +22,7 @@
 public class CpuPowerCalculator extends PowerCalculator {
     private static final String TAG = "CpuPowerCalculator";
     private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
+    private static final long MICROSEC_IN_HR = (long) 60 * 60 * 1000 * 1000;
     private final PowerProfile mProfile;
 
     public CpuPowerCalculator(PowerProfile profile) {
@@ -35,21 +36,22 @@
         app.cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
         final int numClusters = mProfile.getNumCpuClusters();
 
-        double cpuPowerMaMs = 0;
+        double cpuPowerMaUs = 0;
         for (int cluster = 0; cluster < numClusters; cluster++) {
             final int speedsForCluster = mProfile.getNumSpeedStepsInCpuCluster(cluster);
             for (int speed = 0; speed < speedsForCluster; speed++) {
-                final double cpuSpeedStepPower = u.getTimeAtCpuSpeed(cluster, speed, statsType) *
+                final long timeUs = u.getTimeAtCpuSpeed(cluster, speed, statsType);
+                final double cpuSpeedStepPower = timeUs *
                         mProfile.getAveragePowerForCpu(cluster, speed);
                 if (DEBUG) {
                     Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " step #"
-                            + speed + " power="
-                            + BatteryStatsHelper.makemAh(cpuSpeedStepPower / (60 * 60 * 1000)));
+                            + speed + " timeUs=" + timeUs + " power="
+                            + BatteryStatsHelper.makemAh(cpuSpeedStepPower / MICROSEC_IN_HR));
                 }
-                cpuPowerMaMs += cpuSpeedStepPower;
+                cpuPowerMaUs += cpuSpeedStepPower;
             }
         }
-        app.cpuPowerMah = cpuPowerMaMs / (60 * 60 * 1000);
+        app.cpuPowerMah = cpuPowerMaUs / MICROSEC_IN_HR;
 
         if (DEBUG && (app.cpuTimeMs != 0 || app.cpuPowerMah != 0)) {
             Log.d(TAG, "UID " + u.getUid() + ": CPU time=" + app.cpuTimeMs + " ms power="
diff --git a/core/java/com/android/internal/os/KernelCpuSpeedReader.java b/core/java/com/android/internal/os/KernelCpuSpeedReader.java
index 9c7debb..757a112 100644
--- a/core/java/com/android/internal/os/KernelCpuSpeedReader.java
+++ b/core/java/com/android/internal/os/KernelCpuSpeedReader.java
@@ -39,8 +39,8 @@
     private static final String TAG = "KernelCpuSpeedReader";
 
     private final String mProcFile;
-    private final long[] mLastSpeedTimes;
-    private final long[] mDeltaSpeedTimes;
+    private final long[] mLastSpeedTimesMs;
+    private final long[] mDeltaSpeedTimesMs;
 
     // How long a CPU jiffy is in milliseconds.
     private final long mJiffyMillis;
@@ -51,8 +51,8 @@
     public KernelCpuSpeedReader(int cpuNumber, int numSpeedSteps) {
         mProcFile = String.format("/sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state",
                 cpuNumber);
-        mLastSpeedTimes = new long[numSpeedSteps];
-        mDeltaSpeedTimes = new long[numSpeedSteps];
+        mLastSpeedTimesMs = new long[numSpeedSteps];
+        mDeltaSpeedTimesMs = new long[numSpeedSteps];
         long jiffyHz = Libcore.os.sysconf(OsConstants._SC_CLK_TCK);
         mJiffyMillis = 1000/jiffyHz;
     }
@@ -68,27 +68,27 @@
             TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' ');
             String line;
             int speedIndex = 0;
-            while (speedIndex < mLastSpeedTimes.length && (line = reader.readLine()) != null) {
+            while (speedIndex < mLastSpeedTimesMs.length && (line = reader.readLine()) != null) {
                 splitter.setString(line);
-                Long.parseLong(splitter.next());
+                splitter.next();
 
                 long time = Long.parseLong(splitter.next()) * mJiffyMillis;
-                if (time < mLastSpeedTimes[speedIndex]) {
+                if (time < mLastSpeedTimesMs[speedIndex]) {
                     // The stats reset when the cpu hotplugged. That means that the time
                     // we read is offset from 0, so the time is the delta.
-                    mDeltaSpeedTimes[speedIndex] = time;
+                    mDeltaSpeedTimesMs[speedIndex] = time;
                 } else {
-                    mDeltaSpeedTimes[speedIndex] = time - mLastSpeedTimes[speedIndex];
+                    mDeltaSpeedTimesMs[speedIndex] = time - mLastSpeedTimesMs[speedIndex];
                 }
-                mLastSpeedTimes[speedIndex] = time;
+                mLastSpeedTimesMs[speedIndex] = time;
                 speedIndex++;
             }
         } catch (IOException e) {
             Slog.e(TAG, "Failed to read cpu-freq: " + e.getMessage());
-            Arrays.fill(mDeltaSpeedTimes, 0);
+            Arrays.fill(mDeltaSpeedTimesMs, 0);
         } finally {
             StrictMode.setThreadPolicy(policy);
         }
-        return mDeltaSpeedTimes;
+        return mDeltaSpeedTimesMs;
     }
 }