[android] Fix synch exec return values when made recursively.

For an explanation of the case, refer to the added unit test.
Related to: https://issues.apache.org/jira/browse/CB-1745
diff --git a/lib/android/exec.js b/lib/android/exec.js
index c339e2c..490633f 100644
--- a/lib/android/exec.js
+++ b/lib/android/exec.js
@@ -105,8 +105,8 @@
 
 function pollingTimerFunc() {
     if (pollEnabled) {
-      pollOnce();
-      setTimeout(pollingTimerFunc, 50);
+        pollOnce();
+        setTimeout(pollingTimerFunc, 50);
     }
 }
 
@@ -199,25 +199,34 @@
 
 // This is called from the NativeToJsMessageQueue.java.
 androidExec.processMessages = function(messages) {
-    messagesFromNative.push(messages);
-    // Check for the reentrant case, and enqueue the message if that's the case.
-    if (messagesFromNative.length > 1) {
-        return;
-    }
-    while (messagesFromNative.length) {
-        messages = messagesFromNative[0];
-        while (messages) {
+    if (messages) {
+        messagesFromNative.push(messages);
+        while (messagesFromNative.length) {
+            messages = messagesFromNative.shift();
+            // The Java side can send a * message to indicate that it
+            // still has messages waiting to be retrieved.
+            // TODO(agrieve): This is currently disabled on the Java side
+            // since it breaks returning the result in exec of synchronous
+            // plugins. Once we remove this ability, we can remove this comment.
             if (messages == '*') {
                 window.setTimeout(pollOnce, 0);
-                break;
+                continue;
             }
+
             var spaceIdx = messages.indexOf(' ');
             var msgLen = +messages.slice(0, spaceIdx);
             var message = messages.substr(spaceIdx + 1, msgLen);
             messages = messages.slice(spaceIdx + msgLen + 1);
-            processMessage(message);
+            // Put the remaining messages back into queue in case an exec()
+            // is made by the callback.
+            if (messages) {
+                messagesFromNative.unshift(messages);
+            }
+
+            if (message) {
+                processMessage(message);
+            }
         }
-        messagesFromNative.shift();
     }
 };
 
diff --git a/test/android/test.exec.js b/test/android/test.exec.js
index f4e760f..3363e45 100644
--- a/test/android/test.exec.js
+++ b/test/android/test.exec.js
@@ -74,6 +74,22 @@
             var result = exec(null, null, 'Service', 'action', []);
             expect(result).toBe(true);
         });
+        it('should return payload value when plugin is synchronous even when called recursively', function() {
+            var winSpy = jasmine.createSpy('win');
+            nativeApi.exec.andCallFake(function(service, action, callbackId, argsJson) {
+                return createCallbackMessage(true, true, 1, callbackId, 't');
+            });
+
+            function firstWin(value) {
+                expect(value).toBe(true);
+                var result = exec(winSpy, null, 'Service', 'action', []);
+                expect(result).toBe(true);
+            }
+
+            var result2 = exec(firstWin, null, 'Service', 'action', []);
+            expect(winSpy).toHaveBeenCalledWith(true);
+            expect(result2).toBe(true);
+        });
     });
 
     describe('processMessages', function() {