Merge "Put two way binder calls on new thread" into rvc-dev
diff --git a/apex/service/java/com/android/server/stats/StatsCompanionService.java b/apex/service/java/com/android/server/stats/StatsCompanionService.java
index c4f1531..aad5112 100644
--- a/apex/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/service/java/com/android/server/stats/StatsCompanionService.java
@@ -38,6 +38,7 @@
 import android.os.IStatsd;
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.StatsFrameworkInitializer;
 import android.os.SystemClock;
@@ -99,9 +100,9 @@
     private static IStatsd sStatsd;
     private static final Object sStatsdLock = new Object();
 
-    private final OnAlarmListener mAnomalyAlarmListener = new AnomalyAlarmListener();
-    private final OnAlarmListener mPullingAlarmListener = new PullingAlarmListener();
-    private final OnAlarmListener mPeriodicAlarmListener = new PeriodicAlarmListener();
+    private final OnAlarmListener mAnomalyAlarmListener;
+    private final OnAlarmListener mPullingAlarmListener;
+    private final OnAlarmListener mPeriodicAlarmListener;
 
     private StatsManagerService mStatsManagerService;
 
@@ -120,6 +121,9 @@
         handlerThread.start();
         mHandler = new CompanionHandler(handlerThread.getLooper());
 
+        mAnomalyAlarmListener = new AnomalyAlarmListener(context);
+        mPullingAlarmListener = new PullingAlarmListener(context);
+        mPeriodicAlarmListener = new PeriodicAlarmListener(context);
     }
 
     private final static int[] toIntArray(List<Integer> list) {
@@ -232,6 +236,31 @@
         });
     }
 
+    private static class WakelockThread extends Thread {
+        private final PowerManager.WakeLock mWl;
+        private final Runnable mRunnable;
+
+        WakelockThread(Context context, String wakelockName, Runnable runnable) {
+            PowerManager powerManager = (PowerManager)
+                    context.getSystemService(Context.POWER_SERVICE);
+            mWl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakelockName);
+            mRunnable = runnable;
+        }
+        @Override
+        public void run() {
+            try {
+                mRunnable.run();
+            } finally {
+                mWl.release();
+            }
+        }
+        @Override
+        public void start() {
+            mWl.acquire();
+            super.start();
+        }
+    }
+
     private final static class AppUpdateReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -307,6 +336,12 @@
     }
 
     public static final class AnomalyAlarmListener implements OnAlarmListener {
+        private final Context mContext;
+
+        AnomalyAlarmListener(Context context) {
+            mContext = context;
+        }
+
         @Override
         public void onAlarm() {
             if (DEBUG) {
@@ -318,17 +353,30 @@
                 Log.w(TAG, "Could not access statsd to inform it of anomaly alarm firing");
                 return;
             }
-            try {
-                // Two-way call to statsd to retain AlarmManager wakelock
-                statsd.informAnomalyAlarmFired();
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed to inform statsd of anomaly alarm firing", e);
-            }
-            // AlarmManager releases its own wakelock here.
+
+            // Wakelock needs to be retained while calling statsd.
+            Thread thread = new WakelockThread(mContext,
+                    AnomalyAlarmListener.class.getCanonicalName(), new Runnable() {
+                        @Override
+                        public void run() {
+                            try {
+                                statsd.informAnomalyAlarmFired();
+                            } catch (RemoteException e) {
+                                Log.w(TAG, "Failed to inform statsd of anomaly alarm firing", e);
+                            }
+                        }
+                    });
+            thread.start();
         }
     }
 
     public final static class PullingAlarmListener implements OnAlarmListener {
+        private final Context mContext;
+
+        PullingAlarmListener(Context context) {
+            mContext = context;
+        }
+
         @Override
         public void onAlarm() {
             if (DEBUG) {
@@ -339,16 +387,30 @@
                 Log.w(TAG, "Could not access statsd to inform it of pulling alarm firing.");
                 return;
             }
-            try {
-                // Two-way call to statsd to retain AlarmManager wakelock
-                statsd.informPollAlarmFired();
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed to inform statsd of pulling alarm firing.", e);
-            }
+
+            // Wakelock needs to be retained while calling statsd.
+            Thread thread = new WakelockThread(mContext,
+                    PullingAlarmListener.class.getCanonicalName(), new Runnable() {
+                        @Override
+                        public void run() {
+                            try {
+                                statsd.informPollAlarmFired();
+                            } catch (RemoteException e) {
+                                Log.w(TAG, "Failed to inform statsd of pulling alarm firing.", e);
+                            }
+                        }
+                    });
+            thread.start();
         }
     }
 
     public final static class PeriodicAlarmListener implements OnAlarmListener {
+        private final Context mContext;
+
+        PeriodicAlarmListener(Context context) {
+            mContext = context;
+        }
+
         @Override
         public void onAlarm() {
             if (DEBUG) {
@@ -359,13 +421,20 @@
                 Log.w(TAG, "Could not access statsd to inform it of periodic alarm firing.");
                 return;
             }
-            try {
-                // Two-way call to statsd to retain AlarmManager wakelock
-                statsd.informAlarmForSubscriberTriggeringFired();
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed to inform statsd of periodic alarm firing.", e);
-            }
-            // AlarmManager releases its own wakelock here.
+
+            // Wakelock needs to be retained while calling statsd.
+            Thread thread = new WakelockThread(mContext,
+                    PeriodicAlarmListener.class.getCanonicalName(), new Runnable() {
+                        @Override
+                        public void run() {
+                            try {
+                                statsd.informAlarmForSubscriberTriggeringFired();
+                            } catch (RemoteException e) {
+                                Log.w(TAG, "Failed to inform statsd of periodic alarm firing.", e);
+                            }
+                        }
+                    });
+            thread.start();
         }
     }