Enable passing of publishedData to scripts.

Modifies and adds tests accordingly.

Removed hello_world test because it is redundant and other existing
tests do the same and more.

Also solves inconsistency issue that output integer arrays are always
arrays of longs, but individual long and int output field are converted
into int type. Now we treat both as long type. The reason why
it is happening in this CL is because published data test case that sums
up a very large array inside a script produces an integer that does not
fit into 32 bit. Putting it into Java int fails the test due to integer
overflow. This inconsistency was fixed in this CL in order to make the
test pass.

Fixes: 189241508
Fixes: 199921035
Fixes: 192285332
Test: atest ScriptExecutorUnitTest:ScriptExecutorTest
Change-Id: I1f685098f5c14e83f5bd8c7a0cd5448353fafb93
diff --git a/packages/ScriptExecutor/src/BundleWrapper.cpp b/packages/ScriptExecutor/src/BundleWrapper.cpp
index 938854f..8957833 100644
--- a/packages/ScriptExecutor/src/BundleWrapper.cpp
+++ b/packages/ScriptExecutor/src/BundleWrapper.cpp
@@ -49,10 +49,11 @@
                             static_cast<jboolean>(value));
 }
 
-void BundleWrapper::putInteger(const char* key, int value) {
-    jmethodID putIntMethod = mJNIEnv->GetMethodID(mBundleClass, "putInt", "(Ljava/lang/String;I)V");
-    mJNIEnv->CallVoidMethod(mBundle, putIntMethod, mJNIEnv->NewStringUTF(key),
-                            static_cast<jint>(value));
+void BundleWrapper::putLong(const char* key, int64_t value) {
+    jmethodID putLongMethod =
+            mJNIEnv->GetMethodID(mBundleClass, "putLong", "(Ljava/lang/String;J)V");
+    mJNIEnv->CallVoidMethod(mBundle, putLongMethod, mJNIEnv->NewStringUTF(key),
+                            static_cast<jlong>(value));
 }
 
 void BundleWrapper::putDouble(const char* key, double value) {
diff --git a/packages/ScriptExecutor/src/BundleWrapper.h b/packages/ScriptExecutor/src/BundleWrapper.h
index e15c56a..7303bd0 100644
--- a/packages/ScriptExecutor/src/BundleWrapper.h
+++ b/packages/ScriptExecutor/src/BundleWrapper.h
@@ -40,7 +40,7 @@
     // Family of methods that puts the provided 'value' into the PersistableBundle
     // under provided 'key'.
     void putBoolean(const char* key, bool value);
-    void putInteger(const char* key, int value);
+    void putLong(const char* key, int64_t value);
     void putDouble(const char* key, double value);
     void putString(const char* key, const char* value);
     void putLongArray(const char* key, const std::vector<int64_t>& value);
diff --git a/packages/ScriptExecutor/src/JniUtils.cpp b/packages/ScriptExecutor/src/JniUtils.cpp
index 90683ce..3152722 100644
--- a/packages/ScriptExecutor/src/JniUtils.cpp
+++ b/packages/ScriptExecutor/src/JniUtils.cpp
@@ -44,6 +44,7 @@
 
     jclass booleanClass = env->FindClass("java/lang/Boolean");
     jclass integerClass = env->FindClass("java/lang/Integer");
+    jclass longClass = env->FindClass("java/lang/Long");
     jclass numberClass = env->FindClass("java/lang/Number");
     jclass stringClass = env->FindClass("java/lang/String");
     jclass intArrayClass = env->FindClass("[I");
@@ -70,6 +71,10 @@
         } else if (env->IsInstanceOf(value, integerClass)) {
             jmethodID intMethod = env->GetMethodID(integerClass, "intValue", "()I");
             lua_pushinteger(luaEngine->getLuaState(), env->CallIntMethod(value, intMethod));
+        } else if (env->IsInstanceOf(value, longClass)) {
+            jmethodID longMethod = env->GetMethodID(longClass, "longValue", "()J");
+            lua_pushinteger(luaEngine->getLuaState(), env->CallLongMethod(value, longMethod));
+
         } else if (env->IsInstanceOf(value, numberClass)) {
             // Condense other numeric types using one class. Because lua supports only
             // integer or double, and we handled integer in previous if clause.
diff --git a/packages/ScriptExecutor/src/LuaEngine.cpp b/packages/ScriptExecutor/src/LuaEngine.cpp
index 55bb977..023333d 100644
--- a/packages/ScriptExecutor/src/LuaEngine.cpp
+++ b/packages/ScriptExecutor/src/LuaEngine.cpp
@@ -72,7 +72,7 @@
         if (lua_isboolean(lua, /* index = */ -1)) {
             bundleWrapper->putBoolean(key, static_cast<bool>(lua_toboolean(lua, /* index = */ -1)));
         } else if (lua_isinteger(lua, /* index = */ -1)) {
-            bundleWrapper->putInteger(key, static_cast<int>(lua_tointeger(lua, /* index = */ -1)));
+            bundleWrapper->putLong(key, static_cast<int64_t>(lua_tointeger(lua, /* index = */ -1)));
         } else if (lua_isnumber(lua, /* index = */ -1)) {
             bundleWrapper->putDouble(key, static_cast<double>(lua_tonumber(lua, /* index = */ -1)));
         } else if (lua_isstring(lua, /* index = */ -1)) {
@@ -248,10 +248,8 @@
     // input arguments are in the Lua stack as well in proper order.
     // On how to call Lua functions: https://www.lua.org/pil/25.2.html
     // Doc on lua_pcall: https://www.lua.org/manual/5.3/manual.html#lua_pcall
-    // TODO(b/189241508): Once we implement publishedData parsing, nargs should
-    // change from 1 to 2.
     // TODO(b/192284612): add test case for failed call.
-    return lua_pcall(mLuaState, /* nargs= */ 1, /* nresults= */ 0, /*errfunc= */ 0);
+    return lua_pcall(mLuaState, /* nargs= */ 2, /* nresults= */ 0, /*errfunc= */ 0);
 }
 
 int LuaEngine::onSuccess(lua_State* lua) {
diff --git a/packages/ScriptExecutor/src/ScriptExecutorJni.cpp b/packages/ScriptExecutor/src/ScriptExecutorJni.cpp
index c11a30b..a5add58 100644
--- a/packages/ScriptExecutor/src/ScriptExecutorJni.cpp
+++ b/packages/ScriptExecutor/src/ScriptExecutorJni.cpp
@@ -108,11 +108,8 @@
         return;
     }
 
-    // TODO(b/189241508): Provide implementation to parse publishedData input,
-    // convert it into Lua table and push into Lua stack.
-    if (publishedData) {
-        LOG(WARNING) << "Parsing of publishedData is not implemented yet.";
-    }
+    // Unpack bundle in publishedData, convert to Lua table and push it to Lua stack.
+    pushBundleToLuaTable(env, engine, publishedData);
 
     // Unpack bundle in savedState, convert to Lua table and push it to Lua
     // stack.
diff --git a/packages/ScriptExecutor/src/com/android/car/scriptexecutor/ScriptExecutor.java b/packages/ScriptExecutor/src/com/android/car/scriptexecutor/ScriptExecutor.java
index d2cb1c8..06e318b 100644
--- a/packages/ScriptExecutor/src/com/android/car/scriptexecutor/ScriptExecutor.java
+++ b/packages/ScriptExecutor/src/com/android/car/scriptexecutor/ScriptExecutor.java
@@ -84,9 +84,7 @@
                     return;
                 }
 
-                // TODO(b/189241508): Start passing publishedData instead of null
-                // once publishedData parser is implemented.
-                nativeInvokeScript(mLuaEnginePtr, scriptBody, functionName, null,
+                nativeInvokeScript(mLuaEnginePtr, scriptBody, functionName, publishedData,
                         savedState, listener);
             });
         }
diff --git a/packages/ScriptExecutor/tests/unit/src/com/android/car/scriptexecutor/ScriptExecutorTest.java b/packages/ScriptExecutor/tests/unit/src/com/android/car/scriptexecutor/ScriptExecutorTest.java
index cb76a75..52b5cc7 100644
--- a/packages/ScriptExecutor/tests/unit/src/com/android/car/scriptexecutor/ScriptExecutorTest.java
+++ b/packages/ScriptExecutor/tests/unit/src/com/android/car/scriptexecutor/ScriptExecutorTest.java
@@ -86,18 +86,9 @@
     private final ScriptExecutorListener mFakeScriptExecutorListener =
             new ScriptExecutorListener();
 
-    // TODO(b/189241508). Parsing of publishedData is not implemented yet.
-    // Null is the only accepted input.
-    private final PersistableBundle mPublishedData = null;
+    private final PersistableBundle mPublishedData = new PersistableBundle();
     private final PersistableBundle mSavedState = new PersistableBundle();
 
-    private static final String LUA_SCRIPT =
-            "function hello(state)\n"
-                    + "    print(\"Hello World\")\n"
-                    + "end\n";
-
-    private static final String LUA_METHOD = "hello";
-
     private final CountDownLatch mBindLatch = new CountDownLatch(1);
 
     private static final int BIND_SERVICE_TIMEOUT_SEC = 5;
@@ -120,9 +111,9 @@
 
     // Helper method to invoke the script and wait for it to complete and return a response.
     private void runScriptAndWaitForResponse(String script, String function,
-            PersistableBundle previousState)
+            PersistableBundle publishedData, PersistableBundle previousState)
             throws RemoteException {
-        mScriptExecutor.invokeScript(script, function, mPublishedData, previousState,
+        mScriptExecutor.invokeScript(script, function, publishedData, previousState,
                 mFakeScriptExecutorListener);
         try {
             if (!mFakeScriptExecutorListener.mResponseLatch.await(SCRIPT_PROCESSING_TIMEOUT_SEC,
@@ -136,7 +127,8 @@
     }
 
     private void runScriptAndWaitForError(String script, String function) throws RemoteException {
-        runScriptAndWaitForResponse(script, function, new PersistableBundle());
+        runScriptAndWaitForResponse(script, function, new PersistableBundle(),
+                new PersistableBundle());
     }
 
     @Before
@@ -152,32 +144,15 @@
     }
 
     @Test
-    public void invokeScript_helloWorld() throws RemoteException {
-        // Expect to load "hello world" script successfully and push the function.
-        mScriptExecutor.invokeScript(LUA_SCRIPT, LUA_METHOD, mPublishedData, mSavedState,
-                mFakeScriptExecutorListener);
-        // Sleep, otherwise the test case will complete before the script loads
-        // because invokeScript is non-blocking.
-        try {
-            // TODO(b/192285332): Replace sleep logic with waiting for specific callbacks
-            // to be called once they are implemented. Otherwise, this could be a flaky test.
-            TimeUnit.SECONDS.sleep(10);
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-            fail(e.getMessage());
-        }
-    }
-
-    @Test
     public void invokeScript_returnsResult() throws RemoteException {
         String returnResultScript =
-                "function hello(state)\n"
+                "function hello(data, state)\n"
                         + "    result = {hello=\"world\"}\n"
                         + "    on_success(result)\n"
                         + "end\n";
 
 
-        runScriptAndWaitForResponse(returnResultScript, "hello", mSavedState);
+        runScriptAndWaitForResponse(returnResultScript, "hello", mPublishedData, mSavedState);
 
         // Expect to get back a bundle with a single string key: string value pair:
         // {"hello": "world"}
@@ -189,34 +164,34 @@
     @Test
     public void invokeScript_allSupportedPrimitiveTypes() throws RemoteException {
         String script =
-                "function knows(state)\n"
+                "function knows(data, state)\n"
                         + "    result = {string=\"hello\", boolean=true, integer=1, number=1.1}\n"
                         + "    on_success(result)\n"
                         + "end\n";
 
 
-        runScriptAndWaitForResponse(script, "knows", mSavedState);
+        runScriptAndWaitForResponse(script, "knows", mPublishedData, mSavedState);
 
         // Expect to get back a bundle with 4 keys, each corresponding to a distinct supported type.
         assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(4);
         assertThat(mFakeScriptExecutorListener.mSavedBundle.getString("string")).isEqualTo(
                 "hello");
         assertThat(mFakeScriptExecutorListener.mSavedBundle.getBoolean("boolean")).isEqualTo(true);
-        assertThat(mFakeScriptExecutorListener.mSavedBundle.getInt("integer")).isEqualTo(1);
+        assertThat(mFakeScriptExecutorListener.mSavedBundle.getLong("integer")).isEqualTo(1);
         assertThat(mFakeScriptExecutorListener.mSavedBundle.getDouble("number")).isEqualTo(1.1);
     }
 
     @Test
     public void invokeScript_skipsUnsupportedTypes() throws RemoteException {
         String script =
-                "function nested(state)\n"
+                "function nested(data, state)\n"
                         + "    result = {string=\"hello\", boolean=true, integer=1, number=1.1}\n"
                         + "    result.nested_table = {x=0, y=0}\n"
                         + "    on_success(result)\n"
                         + "end\n";
 
 
-        runScriptAndWaitForResponse(script, "nested", mSavedState);
+        runScriptAndWaitForResponse(script, "nested", mPublishedData, mSavedState);
 
         // Verify that expected error is received.
         assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
@@ -228,13 +203,13 @@
     @Test
     public void invokeScript_emptyBundle() throws RemoteException {
         String script =
-                "function empty(state)\n"
+                "function empty(data, state)\n"
                         + "    result = {}\n"
                         + "    on_success(result)\n"
                         + "end\n";
 
 
-        runScriptAndWaitForResponse(script, "empty", mSavedState);
+        runScriptAndWaitForResponse(script, "empty", mPublishedData, mSavedState);
 
         // If a script returns empty table as the result, we get an empty bundle.
         assertThat(mFakeScriptExecutorListener.mSavedBundle).isNotNull();
@@ -245,9 +220,8 @@
     public void invokeScript_processPreviousStateAndReturnResult() throws RemoteException {
         // Here we verify that the script actually processes provided state from a previous run
         // and makes calculation based on that and returns the result.
-        // TODO(b/189241508): update function signatures.
         String script =
-                "function update(state)\n"
+                "function update(data, state)\n"
                         + "    result = {y = state.x+1}\n"
                         + "    on_success(result)\n"
                         + "end\n";
@@ -255,11 +229,11 @@
         previousState.putInt("x", 1);
 
 
-        runScriptAndWaitForResponse(script, "update", previousState);
+        runScriptAndWaitForResponse(script, "update", mPublishedData, previousState);
 
         // Verify that y = 2, because y = x + 1 and x = 1.
         assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(1);
-        assertThat(mFakeScriptExecutorListener.mSavedBundle.getInt("y")).isEqualTo(2);
+        assertThat(mFakeScriptExecutorListener.mSavedBundle.getLong("y")).isEqualTo(2);
     }
 
     @Test
@@ -267,9 +241,8 @@
             throws RemoteException {
         // Here we verify that all supported primitive types in supplied previous state Bundle
         // are interpreted by the script as expected.
-        // TODO(b/189241508): update function signatures.
         String script =
-                "function update_all(state)\n"
+                "function update_all(data, state)\n"
                         + "    result = {}\n"
                         + "    result.integer = state.integer + 1\n"
                         + "    result.number = state.number + 0.1\n"
@@ -284,11 +257,11 @@
         previousState.putString("string", "ABRA");
 
 
-        runScriptAndWaitForResponse(script, "update_all", previousState);
+        runScriptAndWaitForResponse(script, "update_all", mPublishedData, previousState);
 
         // Verify that keys are preserved but the values are modified as expected.
         assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(4);
-        assertThat(mFakeScriptExecutorListener.mSavedBundle.getInt("integer")).isEqualTo(2);
+        assertThat(mFakeScriptExecutorListener.mSavedBundle.getLong("integer")).isEqualTo(2);
         assertThat(mFakeScriptExecutorListener.mSavedBundle.getDouble("number")).isEqualTo(0.2);
         assertThat(mFakeScriptExecutorListener.mSavedBundle.getBoolean("boolean")).isEqualTo(true);
         assertThat(mFakeScriptExecutorListener.mSavedBundle.getString("string")).isEqualTo(
@@ -300,9 +273,8 @@
             throws RemoteException {
         // Here we verify that all supported array types in supplied previous state Bundle are
         // interpreted by the script as expected.
-        // TODO(b/189241508): update function signatures.
         String script =
-                "function arrays(state)\n"
+                "function arrays(data, state)\n"
                         + "    result = {}\n"
                         + "    result.int_array = state.int_array\n"
                         + "    result.long_array = state.long_array\n"
@@ -319,7 +291,7 @@
         previousState.putStringArray("string_array", string_array);
 
 
-        runScriptAndWaitForResponse(script, "arrays", previousState);
+        runScriptAndWaitForResponse(script, "arrays", mPublishedData, previousState);
 
         // Verify that keys are preserved but the values are modified as expected.
         assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(3);
@@ -338,9 +310,8 @@
     public void invokeScript_modifiesArray()
             throws RemoteException {
         // Verify that an array modified by a script is properly sent back by the callback.
-        // TODO(b/189241508): update function signatures.
         String script =
-                "function modify_array(state)\n"
+                "function modify_array(data, state)\n"
                         + "    result = {}\n"
                         + "    result.long_array = state.long_array\n"
                         + "    result.long_array[2] = 100\n"
@@ -352,7 +323,7 @@
         long[] expected_array = new long[]{1, 100, 3};
 
 
-        runScriptAndWaitForResponse(script, "modify_array", previousState);
+        runScriptAndWaitForResponse(script, "modify_array", mPublishedData, previousState);
 
         // Verify that keys are preserved but the values are modified as expected.
         assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(1);
@@ -364,9 +335,8 @@
     public void invokeScript_processesStringArray()
             throws RemoteException {
         // Verify that an array modified by a script is properly sent back by the callback.
-        // TODO(b/189241508): update function signatures.
         String script =
-                "function process_string_array(state)\n"
+                "function process_string_array(data, state)\n"
                         + "    result = {}\n"
                         + "    result.answer = state.string_array[1] .. state.string_array[2]\n"
                         + "    on_success(result)\n"
@@ -375,7 +345,7 @@
         String[] string_array = new String[]{"Hello ", "world!"};
         previousState.putStringArray("string_array", string_array);
 
-        runScriptAndWaitForResponse(script, "process_string_array", previousState);
+        runScriptAndWaitForResponse(script, "process_string_array", mPublishedData, previousState);
 
         // Verify that keys are preserved but the values are modified as expected.
         assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(1);
@@ -387,9 +357,8 @@
     public void invokeScript_arraysWithLengthAboveLimitCauseError()
             throws RemoteException {
         // Verifies that arrays pushed by Lua that have their size over the limit cause error.
-        // TODO(b/189241508): update function signatures.
         String script =
-                "function size_limit(state)\n"
+                "function size_limit(data, state)\n"
                         + "    result = {}\n"
                         + "    result.huge_array = {}\n"
                         + "    for i=1, 10000 do\n"
@@ -398,7 +367,7 @@
                         + "    on_success(result)\n"
                         + "end\n";
 
-        runScriptAndWaitForResponse(script, "size_limit", mSavedState);
+        runScriptAndWaitForResponse(script, "size_limit", mPublishedData, mSavedState);
 
         // Verify that expected error is received.
         assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
@@ -414,9 +383,8 @@
             throws RemoteException {
         // Verifies that values in returned array must be the same integer type.
         // For example string values in a Lua array are not allowed.
-        // TODO(b/189241508): update function signatures.
         String script =
-                "function table_with_numbers_and_strings(state)\n"
+                "function table_with_numbers_and_strings(data, state)\n"
                         + "    result = {}\n"
                         + "    result.mixed_array = state.long_array\n"
                         + "    result.mixed_array[2] = 'a'\n"
@@ -426,7 +394,8 @@
         long[] long_array = new long[]{1, 2, 3};
         previousState.putLongArray("long_array", long_array);
 
-        runScriptAndWaitForResponse(script, "table_with_numbers_and_strings", previousState);
+        runScriptAndWaitForResponse(script, "table_with_numbers_and_strings", mPublishedData,
+                previousState);
 
         // Verify that expected error is received.
         assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
@@ -440,9 +409,8 @@
             throws RemoteException {
         // Documents the current behavior that copies only indexed values in a Lua table that
         // contains both keyed and indexed data.
-        // TODO(b/189241508): update function signatures.
         String script =
-                "function keys_and_indices(state)\n"
+                "function keys_and_indices(data, state)\n"
                         + "    result = {}\n"
                         + "    result.mixed_array = state.long_array\n"
                         + "    result.mixed_array['a'] = 130\n"
@@ -452,7 +420,7 @@
         long[] long_array = new long[]{1, 2, 3};
         previousState.putLongArray("long_array", long_array);
 
-        runScriptAndWaitForResponse(script, "keys_and_indices", previousState);
+        runScriptAndWaitForResponse(script, "keys_and_indices", mPublishedData, previousState);
 
         // Verify that keys are preserved but the values are modified as expected.
         assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(1);
@@ -464,9 +432,8 @@
     public void invokeScript_noLuaBufferOverflowForLargeInputArrays() throws RemoteException {
         // Tests that arrays with length that exceed internal Lua buffer size of 20 elements
         // do not cause buffer overflow and are handled properly.
-        // TODO(b/189241508): update function signatures.
         String script =
-                "function large_input_array(state)\n"
+                "function large_input_array(data, state)\n"
                         + "    sum = 0\n"
                         + "    for _, val in ipairs(state.long_array) do\n"
                         + "        sum = sum + val\n"
@@ -485,11 +452,11 @@
         long expected_sum =
                 (longArray[0] + longArray[n - 1]) * n / 2; // sum of an arithmetic sequence.
 
-        runScriptAndWaitForResponse(script, "large_input_array", previousState);
+        runScriptAndWaitForResponse(script, "large_input_array", mPublishedData, previousState);
 
         // Verify that keys are preserved but the values are modified as expected.
         assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(1);
-        assertThat(mFakeScriptExecutorListener.mSavedBundle.getInt("total")).isEqualTo(
+        assertThat(mFakeScriptExecutorListener.mSavedBundle.getLong("total")).isEqualTo(
                 expected_sum);
     }
 
@@ -549,19 +516,20 @@
     @Test
     public void invokeScript_returnsFinalResult() throws RemoteException {
         String returnFinalResultScript =
-                "function script_finishes(state)\n"
+                "function script_finishes(data, state)\n"
                         + "    result = {data = state.input + 1}\n"
                         + "    on_script_finished(result)\n"
                         + "end\n";
         PersistableBundle previousState = new PersistableBundle();
         previousState.putInt("input", 1);
 
-        runScriptAndWaitForResponse(returnFinalResultScript, "script_finishes", previousState);
+        runScriptAndWaitForResponse(returnFinalResultScript, "script_finishes", mPublishedData,
+                previousState);
 
         // Expect to get back a bundle with a single key-value pair {"data": 2}
         // because data = state.input + 1 as in the script body above.
         assertThat(mFakeScriptExecutorListener.mFinalResult.size()).isEqualTo(1);
-        assertThat(mFakeScriptExecutorListener.mFinalResult.getInt("data")).isEqualTo(2);
+        assertThat(mFakeScriptExecutorListener.mFinalResult.getLong("data")).isEqualTo(2);
     }
 
     @Test
@@ -569,9 +537,8 @@
             throws RemoteException {
         // Here we verify that all supported primitive types are present in the returned final
         // result bundle are present.
-        // TODO(b/189241508): update function signatures.
         String script =
-                "function finalize_all(state)\n"
+                "function finalize_all(data, state)\n"
                         + "    result = {}\n"
                         + "    result.integer = state.integer + 1\n"
                         + "    result.number = state.number + 0.1\n"
@@ -586,11 +553,11 @@
         previousState.putString("string", "ABRA");
 
 
-        runScriptAndWaitForResponse(script, "finalize_all", previousState);
+        runScriptAndWaitForResponse(script, "finalize_all", mPublishedData, previousState);
 
         // Verify that keys are preserved but the values are modified as expected.
         assertThat(mFakeScriptExecutorListener.mFinalResult.size()).isEqualTo(4);
-        assertThat(mFakeScriptExecutorListener.mFinalResult.getInt("integer")).isEqualTo(2);
+        assertThat(mFakeScriptExecutorListener.mFinalResult.getLong("integer")).isEqualTo(2);
         assertThat(mFakeScriptExecutorListener.mFinalResult.getDouble("number")).isEqualTo(0.2);
         assertThat(mFakeScriptExecutorListener.mFinalResult.getBoolean("boolean")).isEqualTo(true);
         assertThat(mFakeScriptExecutorListener.mFinalResult.getString("string")).isEqualTo(
@@ -600,13 +567,13 @@
     @Test
     public void invokeScript_emptyFinalResultBundle() throws RemoteException {
         String script =
-                "function empty_final_result(state)\n"
+                "function empty_final_result(data, state)\n"
                         + "    result = {}\n"
                         + "    on_script_finished(result)\n"
                         + "end\n";
 
 
-        runScriptAndWaitForResponse(script, "empty_final_result", mSavedState);
+        runScriptAndWaitForResponse(script, "empty_final_result", mPublishedData, mSavedState);
 
         // If a script returns empty table as the final result, we get an empty bundle.
         assertThat(mFakeScriptExecutorListener.mFinalResult).isNotNull();
@@ -617,7 +584,7 @@
     public void invokeScript_wrongNumberOfCallbackInputsInOnScriptFinished()
             throws RemoteException {
         String script =
-                "function wrong_number_of_outputs_in_on_script_finished(state)\n"
+                "function wrong_number_of_outputs_in_on_script_finished(data, state)\n"
                         + "    result = {}\n"
                         + "    extra = 1\n"
                         + "    on_script_finished(result, extra)\n"
@@ -625,7 +592,7 @@
 
 
         runScriptAndWaitForResponse(script, "wrong_number_of_outputs_in_on_script_finished",
-                mSavedState);
+                mPublishedData, mSavedState);
 
         // We expect to get an error here because we expect only 1 input parameter in
         // on_script_finished.
@@ -638,14 +605,15 @@
     @Test
     public void invokeScript_wrongNumberOfCallbackInputsInOnSuccess() throws RemoteException {
         String script =
-                "function wrong_number_of_outputs_in_on_success(state)\n"
+                "function wrong_number_of_outputs_in_on_success(data, state)\n"
                         + "    result = {}\n"
                         + "    extra = 1\n"
                         + "    on_success(result, extra)\n"
                         + "end\n";
 
 
-        runScriptAndWaitForResponse(script, "wrong_number_of_outputs_in_on_success", mSavedState);
+        runScriptAndWaitForResponse(script, "wrong_number_of_outputs_in_on_success",
+                mPublishedData, mSavedState);
 
         // We expect to get an error here because we expect only 1 input parameter in on_success.
         assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
@@ -657,13 +625,14 @@
     @Test
     public void invokeScript_wrongTypeInOnSuccess() throws RemoteException {
         String script =
-                "function wrong_type_in_on_success(state)\n"
+                "function wrong_type_in_on_success(data, state)\n"
                         + "    result = 1\n"
                         + "    on_success(result)\n"
                         + "end\n";
 
 
-        runScriptAndWaitForResponse(script, "wrong_type_in_on_success", mSavedState);
+        runScriptAndWaitForResponse(script, "wrong_type_in_on_success",
+                mPublishedData, mSavedState);
 
         // We expect to get an error here because the type of the input parameter for on_success
         // must be a Lua table.
@@ -676,13 +645,14 @@
     @Test
     public void invokeScript_wrongTypeInOnScriptFinished() throws RemoteException {
         String script =
-                "function wrong_type_in_on_script_finished(state)\n"
+                "function wrong_type_in_on_script_finished(data, state)\n"
                         + "    result = 1\n"
                         + "    on_success(result)\n"
                         + "end\n";
 
 
-        runScriptAndWaitForResponse(script, "wrong_type_in_on_script_finished", mSavedState);
+        runScriptAndWaitForResponse(script, "wrong_type_in_on_script_finished",
+                mPublishedData, mSavedState);
 
         // We expect to get an error here because the type of the input parameter for
         // on_script_finished must be a Lua table.
@@ -696,11 +666,13 @@
     public void invokeScriptLargeInput_largePublishedData() throws Exception {
         // Verifies that large input does not overwhelm Binder's buffer because pipes are used
         // instead.
-        // TODO(b/189241508): Once publishedData parsing is implemented, change the script and
-        //  the test to process the published data input and return something meaningful.
         String script =
-                "function large_published_data(state)\n"
-                        + "    result = {success = true}\n"
+                "function large_published_data(data, state)\n"
+                        + "    sum = 0\n"
+                        + "    for _, val in ipairs(data.array) do\n"
+                        + "        sum = sum + val\n"
+                        + "    end\n"
+                        + "    result = {total = sum}\n"
                         + "    on_script_finished(result)\n"
                         + "end\n";
 
@@ -715,6 +687,8 @@
             array8Mb[i] = i;
         }
         bundle.putLongArray("array", array8Mb);
+        long expectedSum =
+                (array8Mb[0] + array8Mb[n - 1]) * n / 2; // sum of an arithmetic sequence.
 
         mScriptExecutor.invokeScriptForLargeInput(script, "large_published_data", readFd,
                 mSavedState,
@@ -729,10 +703,70 @@
                 SCRIPT_PROCESSING_TIMEOUT_SEC,
                 TimeUnit.SECONDS);
 
-        assertWithMessage("Failed to get the callback method called by the script on time").that(
-                gotResponse).isTrue();
+        assertWithMessage("Failed to get the callback method called by the script on time")
+                .that(gotResponse).isTrue();
         assertThat(mFakeScriptExecutorListener.mFinalResult.size()).isEqualTo(1);
-        assertThat(mFakeScriptExecutorListener.mFinalResult.getBoolean("success")).isTrue();
+        assertThat(mFakeScriptExecutorListener.mFinalResult.getLong("total"))
+                .isEqualTo(expectedSum);
+    }
+
+    @Test
+    public void invokeScript_bothPublishedDataAndPreviousStateAreProvided() throws RemoteException {
+        // Verifies that both published data and previous state PersistableBundles
+        // are piped into script.
+        String script =
+                "function data_and_state(data, state)\n"
+                        + "    result = {answer = data.a .. data.b .. state.c .. state.d}\n"
+                        + "    on_script_finished(result)\n"
+                        + "end\n";
+
+        PersistableBundle publishedData = new PersistableBundle();
+        publishedData.putString("a", "A");
+        publishedData.putString("b", "B");
+
+        PersistableBundle previousState = new PersistableBundle();
+        previousState.putString("c", "C");
+        previousState.putString("d", "D");
+
+        runScriptAndWaitForResponse(script, "data_and_state", publishedData, previousState);
+
+        // If a script returns empty table as the final result, we get an empty bundle.
+        assertThat(mFakeScriptExecutorListener.mFinalResult).isNotNull();
+        assertThat(mFakeScriptExecutorListener.mFinalResult.size()).isEqualTo(1);
+        assertThat(mFakeScriptExecutorListener.mFinalResult.getString("answer")).isEqualTo(
+                "ABCD");
+    }
+
+    @Test
+    public void invokeScript_outputIntAndLongAreTreatedAsLong() throws RemoteException {
+        // Verifies that we treat output both integer and long as long integer type although we
+        // distinguish between int and long in the script input.
+        String script =
+                "function int_and_long_are_output_long(data, state)\n"
+                        + "    result = {int = data.int, long = state.long}\n"
+                        + "    on_script_finished(result)\n"
+                        + "end\n";
+
+        PersistableBundle publishedData = new PersistableBundle();
+        publishedData.putInt("int", 100);
+
+        PersistableBundle previousState = new PersistableBundle();
+        previousState.putLong("long", 200);
+
+        runScriptAndWaitForResponse(script, "int_and_long_are_output_long",
+                publishedData, previousState);
+
+        // If a script returns empty table as the final result, we get an empty bundle.
+        assertThat(mFakeScriptExecutorListener.mFinalResult).isNotNull();
+        assertThat(mFakeScriptExecutorListener.mFinalResult.size()).isEqualTo(2);
+        // getInt should always return "empty" value (zero) because all integer types are treated
+        // as Java long.
+        assertThat(mFakeScriptExecutorListener.mFinalResult.getInt("int")).isEqualTo(0);
+        assertThat(mFakeScriptExecutorListener.mFinalResult.getInt("long")).isEqualTo(0);
+        // Instead all expected integer values are successfully retrieved using getLong method
+        // from the output bundle.
+        assertThat(mFakeScriptExecutorListener.mFinalResult.getLong("int")).isEqualTo(100);
+        assertThat(mFakeScriptExecutorListener.mFinalResult.getLong("long")).isEqualTo(200);
     }
 }
 
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/telemetry/CarTelemetryTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/telemetry/CarTelemetryTestFragment.java
index 7c4a4b1..d2f011f 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/telemetry/CarTelemetryTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/telemetry/CarTelemetryTestFragment.java
@@ -43,7 +43,7 @@
 
 public class CarTelemetryTestFragment extends Fragment {
     private static final String LUA_SCRIPT_ON_GEAR_CHANGE =
-            "function onGearChange(state)\n"
+            "function onGearChange(published_data, state)\n"
                     + "    result = {data = \"Hello World!\"}\n"
                     + "    on_script_finished(result)\n"
                     + "end\n";