Merge "iorap: Fix data race in AppLaunchObserver on the binder remote"
diff --git a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
index 31bd341..902da4c 100644
--- a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
+++ b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
@@ -275,7 +275,8 @@
             Log.e(TAG, "connectToRemoteAndConfigure - null iorap remote. check for Log.wtf?");
             return false;
         }
-        invokeRemote( () -> mIorapRemote.setTaskListener(new RemoteTaskListener()) );
+        invokeRemote(mIorapRemote,
+            (IIorap remote) -> remote.setTaskListener(new RemoteTaskListener()) );
         registerInProcessListenersLocked();
 
         return true;
@@ -323,8 +324,9 @@
                         mSequenceId, intent));
             }
 
-            invokeRemote(() ->
-                    mIorapRemote.onAppLaunchEvent(RequestId.nextValueForSequence(),
+            invokeRemote(mIorapRemote,
+                (IIorap remote) ->
+                    remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
                         new AppLaunchEvent.IntentStarted(mSequenceId, intent))
             );
         }
@@ -335,8 +337,9 @@
                 Log.v(TAG, String.format("AppLaunchObserver#onIntentFailed(%d)", mSequenceId));
             }
 
-            invokeRemote(() ->
-                    mIorapRemote.onAppLaunchEvent(RequestId.nextValueForSequence(),
+            invokeRemote(mIorapRemote,
+                (IIorap remote) ->
+                    remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
                         new AppLaunchEvent.IntentFailed(mSequenceId))
             );
         }
@@ -349,8 +352,9 @@
                         mSequenceId, activity, temperature));
             }
 
-            invokeRemote(() ->
-                    mIorapRemote.onAppLaunchEvent(RequestId.nextValueForSequence(),
+            invokeRemote(mIorapRemote,
+                (IIorap remote) ->
+                    remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
                             new AppLaunchEvent.ActivityLaunched(mSequenceId, activity, temperature))
             );
         }
@@ -362,8 +366,9 @@
                         mSequenceId, activity));
             }
 
-            invokeRemote(() ->
-                    mIorapRemote.onAppLaunchEvent(RequestId.nextValueForSequence(),
+            invokeRemote(mIorapRemote,
+                (IIorap remote) ->
+                    remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
                             new AppLaunchEvent.ActivityLaunchCancelled(mSequenceId,
                                     activity)));
         }
@@ -375,8 +380,9 @@
                         mSequenceId, activity));
             }
 
-            invokeRemote(() ->
-                mIorapRemote.onAppLaunchEvent(RequestId.nextValueForSequence(),
+            invokeRemote(mIorapRemote,
+                (IIorap remote) ->
+                    remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
                         new AppLaunchEvent.ActivityLaunchFinished(mSequenceId, activity))
             );
         }
@@ -501,8 +507,8 @@
                 mRunningJobs.put(request, params);
             }
 
-            if (!invokeRemote( () ->
-                    mIorapRemote.onJobScheduledEvent(request,
+            if (!invokeRemote(mIorapRemote, (IIorap remote) ->
+                    remote.onJobScheduledEvent(request,
                             JobScheduledEvent.createIdleMaintenance(
                                     JobScheduledEvent.TYPE_START_JOB,
                                     params))
@@ -539,8 +545,8 @@
 
             // Notify iorapd to stop (abort) the job.
             if (wasTracking) {
-                invokeRemote(() ->
-                        mIorapRemote.onJobScheduledEvent(RequestId.nextValueForSequence(),
+                invokeRemote(mIorapRemote, (IIorap remote) ->
+                        remote.onJobScheduledEvent(RequestId.nextValueForSequence(),
                                 JobScheduledEvent.createIdleMaintenance(
                                         JobScheduledEvent.TYPE_STOP_JOB,
                                         params))
@@ -632,12 +638,17 @@
     /** Allow passing lambdas to #invokeRemote */
     private interface RemoteRunnable {
         // TODO: run(RequestId) ?
-        void run() throws RemoteException;
+        void run(IIorap iorap) throws RemoteException;
     }
 
-    private static boolean invokeRemote(RemoteRunnable r) {
+    // Always pass in the iorap directly here to avoid data race.
+    private static boolean invokeRemote(IIorap iorap, RemoteRunnable r) {
+       if (iorap == null) {
+         Log.w(TAG, "IIorap went to null in this thread, drop invokeRemote.");
+         return false;
+       }
        try {
-           r.run();
+           r.run(iorap);
            return true;
        } catch (RemoteException e) {
            // This could be a logic error (remote side returning error), which we need to fix.