Ease contention on the mProcessStatsThread mutex in updateCpuStats.

BUG=2606839

Change-Id: I444af0bb4a7b0be7ebf9ee5887805f2f09a426d0
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 13690bc..f8f8a0d 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -123,6 +123,8 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
 
 public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
     static final String TAG = "ActivityManager";
@@ -927,7 +929,9 @@
      */
     final ProcessStats mProcessStats = new ProcessStats(
             MONITOR_THREAD_CPU_USAGE);
-    long mLastCpuTime = 0;
+    final AtomicLong mLastCpuTime = new AtomicLong(0);
+    final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
+
     long mLastWriteTime = 0;
 
     long mInitialStartTime = 0;
@@ -1430,7 +1434,7 @@
                         try {
                             synchronized(this) {
                                 final long now = SystemClock.uptimeMillis();
-                                long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
+                                long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
                                 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
                                 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
                                 //        + ", write delay=" + nextWriteDelay);
@@ -1438,12 +1442,12 @@
                                     nextCpuDelay = nextWriteDelay;
                                 }
                                 if (nextCpuDelay > 0) {
+                                    mProcessStatsMutexFree.set(true);
                                     this.wait(nextCpuDelay);
                                 }
                             }
                         } catch (InterruptedException e) {
                         }
-                        
                         updateCpuStatsNow();
                     } catch (Exception e) {
                         Slog.e(TAG, "Unexpected exception collecting process stats", e);
@@ -1470,22 +1474,26 @@
     }
 
     void updateCpuStats() {
-        synchronized (mProcessStatsThread) {
-            final long now = SystemClock.uptimeMillis();
-            if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
+        final long now = SystemClock.uptimeMillis();
+        if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
+            return;
+        }
+        if (mProcessStatsMutexFree.compareAndSet(true, false)) {
+            synchronized (mProcessStatsThread) {
                 mProcessStatsThread.notify();
             }
         }
     }
-    
+
     void updateCpuStatsNow() {
         synchronized (mProcessStatsThread) {
+            mProcessStatsMutexFree.set(false);
             final long now = SystemClock.uptimeMillis();
             boolean haveNewCpuStats = false;
 
             if (MONITOR_CPU_USAGE &&
-                    mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
-                mLastCpuTime = now;
+                    mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
+                mLastCpuTime.set(now);
                 haveNewCpuStats = true;
                 mProcessStats.update();
                 //Slog.i(TAG, mProcessStats.printCurrentState());