aboutsummaryrefslogtreecommitdiff
path: root/cpp/telemetry
diff options
context:
space:
mode:
authorMax Dashouk <mdashouk@google.com>2021-08-02 15:39:33 -0700
committerMax Dashouk <mdashouk@google.com>2021-08-11 17:48:24 -0700
commit73dd476165a96dc4b0bc08a247bf66718e83fbd0 (patch)
tree57f5c7b487a871253346223c03f9290684ca4897 /cpp/telemetry
parent829606b4460140c9e7f84f9a137792975a9ee0b2 (diff)
downloadCar-73dd476165a96dc4b0bc08a247bf66718e83fbd0.tar.gz
Create a separate package for ScriptExecutor. DO NOT MERGE
Important changes: 1. Create a separate library for ScriptExecutor interfaces, that both ScriptExecutor and CarService would depend on. 2. Put all ScriptExecutor code under the same namespace. 3. Break all dependencies of ScriptExecutor on CarService. 4. Add instructions on how to run unit tests. Test: atest ScriptExecutorUnitTest:ScriptExecutorTest Bug: 193028600 Change-Id: Ia8b5b16cb0d114ffb1a6f4695290372de38a4beb
Diffstat (limited to 'cpp/telemetry')
-rw-r--r--cpp/telemetry/script_executor/Android.bp85
-rw-r--r--cpp/telemetry/script_executor/src/BundleWrapper.cpp79
-rw-r--r--cpp/telemetry/script_executor/src/BundleWrapper.h63
-rw-r--r--cpp/telemetry/script_executor/src/JniUtils.cpp95
-rw-r--r--cpp/telemetry/script_executor/src/JniUtils.h39
-rw-r--r--cpp/telemetry/script_executor/src/LuaEngine.cpp178
-rw-r--r--cpp/telemetry/script_executor/src/LuaEngine.h100
-rw-r--r--cpp/telemetry/script_executor/src/ScriptExecutorJni.cpp136
-rw-r--r--cpp/telemetry/script_executor/src/ScriptExecutorListener.cpp76
-rw-r--r--cpp/telemetry/script_executor/src/ScriptExecutorListener.h59
-rw-r--r--cpp/telemetry/script_executor/src/tests/JniUtilsTestHelper.cpp138
11 files changed, 0 insertions, 1048 deletions
diff --git a/cpp/telemetry/script_executor/Android.bp b/cpp/telemetry/script_executor/Android.bp
deleted file mode 100644
index 5df2670e35..0000000000
--- a/cpp/telemetry/script_executor/Android.bp
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_defaults {
- name: "scriptexecutor_defaults",
- cflags: [
- "-Wno-unused-parameter",
- ],
- static_libs: [
- "libbase",
- "liblog",
- "liblua",
- ],
-}
-
-cc_library {
- name: "libscriptexecutor",
- defaults: [
- "scriptexecutor_defaults",
- ],
- srcs: [
- ":iscriptexecutorconstants_aidl",
- "src/BundleWrapper.cpp",
- "src/JniUtils.cpp",
- "src/LuaEngine.cpp",
- "src/ScriptExecutorListener.cpp",
- ],
- shared_libs: [
- "libandroid_runtime",
- "libbase",
- "libbinder",
- "libnativehelper",
- "libutils",
- ],
- // Allow dependents to use the header files.
- export_include_dirs: [
- "src",
- ],
- aidl: {
- include_dirs: ["packages/services/Car/car-lib/src/android/car/telemetry"],
- },
-}
-
-cc_library_shared {
- name: "libscriptexecutorjniutils-test",
- defaults: [
- "scriptexecutor_defaults",
- ],
- srcs: [
- "src/tests/JniUtilsTestHelper.cpp",
- ],
- shared_libs: [
- "libnativehelper",
- "libscriptexecutor",
- ],
-}
-
-cc_library {
- name: "libscriptexecutorjni",
- defaults: [
- "scriptexecutor_defaults",
- ],
- srcs: [
- "src/ScriptExecutorJni.cpp",
- ],
- shared_libs: [
- "libnativehelper",
- "libscriptexecutor",
- ],
-}
diff --git a/cpp/telemetry/script_executor/src/BundleWrapper.cpp b/cpp/telemetry/script_executor/src/BundleWrapper.cpp
deleted file mode 100644
index 77d2a5f93f..0000000000
--- a/cpp/telemetry/script_executor/src/BundleWrapper.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2021, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BundleWrapper.h"
-
-#include <android-base/logging.h>
-#include <android_runtime/AndroidRuntime.h>
-
-namespace android {
-namespace automotive {
-namespace telemetry {
-namespace script_executor {
-
-BundleWrapper::BundleWrapper(JNIEnv* env) {
- mJNIEnv = env;
- mBundleClass =
- static_cast<jclass>(mJNIEnv->NewGlobalRef(mJNIEnv->FindClass("android/os/Bundle")));
- jmethodID bundleConstructor = mJNIEnv->GetMethodID(mBundleClass, "<init>", "()V");
- mBundle = mJNIEnv->NewGlobalRef(mJNIEnv->NewObject(mBundleClass, bundleConstructor));
-}
-
-BundleWrapper::~BundleWrapper() {
- // Delete global JNI references.
- if (mBundle != NULL) {
- mJNIEnv->DeleteGlobalRef(mBundle);
- }
- if (mBundleClass != NULL) {
- mJNIEnv->DeleteGlobalRef(mBundleClass);
- }
-}
-
-void BundleWrapper::putBoolean(const char* key, bool value) {
- jmethodID putBooleanMethod =
- mJNIEnv->GetMethodID(mBundleClass, "putBoolean", "(Ljava/lang/String;Z)V");
- mJNIEnv->CallVoidMethod(mBundle, putBooleanMethod, mJNIEnv->NewStringUTF(key),
- 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::putDouble(const char* key, double value) {
- jmethodID putDoubleMethod =
- mJNIEnv->GetMethodID(mBundleClass, "putDouble", "(Ljava/lang/String;D)V");
- mJNIEnv->CallVoidMethod(mBundle, putDoubleMethod, mJNIEnv->NewStringUTF(key),
- static_cast<jdouble>(value));
-}
-
-void BundleWrapper::putString(const char* key, const char* value) {
- jmethodID putStringMethod = mJNIEnv->GetMethodID(mBundleClass, "putString",
- "(Ljava/lang/String;Ljava/lang/String;)V");
- mJNIEnv->CallVoidMethod(mBundle, putStringMethod, mJNIEnv->NewStringUTF(key),
- mJNIEnv->NewStringUTF(value));
-}
-
-jobject BundleWrapper::getBundle() {
- return mBundle;
-}
-
-} // namespace script_executor
-} // namespace telemetry
-} // namespace automotive
-} // namespace android
diff --git a/cpp/telemetry/script_executor/src/BundleWrapper.h b/cpp/telemetry/script_executor/src/BundleWrapper.h
deleted file mode 100644
index 8c42c4670b..0000000000
--- a/cpp/telemetry/script_executor/src/BundleWrapper.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2021, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CPP_TELEMETRY_SCRIPT_EXECUTOR_SRC_BUNDLEWRAPPER_H_
-#define CPP_TELEMETRY_SCRIPT_EXECUTOR_SRC_BUNDLEWRAPPER_H_
-
-#include "jni.h"
-
-namespace android {
-namespace automotive {
-namespace telemetry {
-namespace script_executor {
-
-// Used to create a java bundle object and populate its fields one at a time.
-class BundleWrapper {
-public:
- explicit BundleWrapper(JNIEnv* env);
- // BundleWrapper is not copyable.
- BundleWrapper(const BundleWrapper&) = delete;
- BundleWrapper& operator=(const BundleWrapper&) = delete;
-
- virtual ~BundleWrapper();
-
- // Family of methods that puts the provided 'value' into the Bundle under provided 'key'.
- void putBoolean(const char* key, bool value);
- void putInteger(const char* key, int value);
- void putDouble(const char* key, double value);
- void putString(const char* key, const char* value);
-
- jobject getBundle();
-
-private:
- // The class asks Java to create Bundle object and stores the reference.
- // When the instance of this class is destroyed the actual Java Bundle object behind
- // this reference stays on and is managed by Java.
- jobject mBundle;
-
- // Reference to java Bundle class cached for performance reasons.
- jclass mBundleClass;
-
- // Stores a JNIEnv* pointer.
- JNIEnv* mJNIEnv; // not owned
-};
-
-} // namespace script_executor
-} // namespace telemetry
-} // namespace automotive
-} // namespace android
-
-#endif // CPP_TELEMETRY_SCRIPT_EXECUTOR_SRC_BUNDLEWRAPPER_H_
diff --git a/cpp/telemetry/script_executor/src/JniUtils.cpp b/cpp/telemetry/script_executor/src/JniUtils.cpp
deleted file mode 100644
index cfe1da4cb7..0000000000
--- a/cpp/telemetry/script_executor/src/JniUtils.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2021, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "JniUtils.h"
-
-namespace android {
-namespace automotive {
-namespace telemetry {
-namespace script_executor {
-
-void pushBundleToLuaTable(JNIEnv* env, LuaEngine* luaEngine, jobject bundle) {
- lua_newtable(luaEngine->getLuaState());
- // null bundle object is allowed. We will treat it as an empty table.
- if (bundle == nullptr) {
- return;
- }
-
- // TODO(b/188832769): Consider caching some of these JNI references for
- // performance reasons.
- jclass bundleClass = env->FindClass("android/os/Bundle");
- jmethodID getKeySetMethod = env->GetMethodID(bundleClass, "keySet", "()Ljava/util/Set;");
- jobject keys = env->CallObjectMethod(bundle, getKeySetMethod);
- jclass setClass = env->FindClass("java/util/Set");
- jmethodID iteratorMethod = env->GetMethodID(setClass, "iterator", "()Ljava/util/Iterator;");
- jobject keySetIteratorObject = env->CallObjectMethod(keys, iteratorMethod);
-
- jclass iteratorClass = env->FindClass("java/util/Iterator");
- jmethodID hasNextMethod = env->GetMethodID(iteratorClass, "hasNext", "()Z");
- jmethodID nextMethod = env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
-
- jclass booleanClass = env->FindClass("java/lang/Boolean");
- jclass integerClass = env->FindClass("java/lang/Integer");
- jclass numberClass = env->FindClass("java/lang/Number");
- jclass stringClass = env->FindClass("java/lang/String");
- // TODO(b/188816922): Handle more types such as float and integer arrays,
- // and perhaps nested Bundles.
-
- jmethodID getMethod =
- env->GetMethodID(bundleClass, "get", "(Ljava/lang/String;)Ljava/lang/Object;");
-
- // Iterate over key set of the bundle one key at a time.
- while (env->CallBooleanMethod(keySetIteratorObject, hasNextMethod)) {
- // Read the value object that corresponds to this key.
- jstring key = (jstring)env->CallObjectMethod(keySetIteratorObject, nextMethod);
- jobject value = env->CallObjectMethod(bundle, getMethod, key);
-
- // Get the value of the type, extract it accordingly from the bundle and
- // push the extracted value and the key to the Lua table.
- if (env->IsInstanceOf(value, booleanClass)) {
- jmethodID boolMethod = env->GetMethodID(booleanClass, "booleanValue", "()Z");
- bool boolValue = static_cast<bool>(env->CallBooleanMethod(value, boolMethod));
- lua_pushboolean(luaEngine->getLuaState(), boolValue);
- } 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, numberClass)) {
- // Condense other numeric types using one class. Because lua supports only
- // integer or double, and we handled integer in previous if clause.
- jmethodID numberMethod = env->GetMethodID(numberClass, "doubleValue", "()D");
- /* Pushes a double onto the stack */
- lua_pushnumber(luaEngine->getLuaState(), env->CallDoubleMethod(value, numberMethod));
- } else if (env->IsInstanceOf(value, stringClass)) {
- const char* rawStringValue = env->GetStringUTFChars((jstring)value, nullptr);
- lua_pushstring(luaEngine->getLuaState(), rawStringValue);
- env->ReleaseStringUTFChars((jstring)value, rawStringValue);
- } else {
- // Other types are not implemented yet, skipping.
- continue;
- }
-
- const char* rawKey = env->GetStringUTFChars(key, nullptr);
- // table[rawKey] = value, where value is on top of the stack,
- // and the table is the next element in the stack.
- lua_setfield(luaEngine->getLuaState(), /* idx= */ -2, rawKey);
- env->ReleaseStringUTFChars(key, rawKey);
- }
-}
-
-} // namespace script_executor
-} // namespace telemetry
-} // namespace automotive
-} // namespace android
diff --git a/cpp/telemetry/script_executor/src/JniUtils.h b/cpp/telemetry/script_executor/src/JniUtils.h
deleted file mode 100644
index 85034d71eb..0000000000
--- a/cpp/telemetry/script_executor/src/JniUtils.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2021, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef CPP_TELEMETRY_SCRIPT_EXECUTOR_SRC_JNIUTILS_H_
-#define CPP_TELEMETRY_SCRIPT_EXECUTOR_SRC_JNIUTILS_H_
-
-#include "LuaEngine.h"
-#include "jni.h"
-
-namespace android {
-namespace automotive {
-namespace telemetry {
-namespace script_executor {
-
-// Helper function which takes android.os.Bundle object in "bundle" argument
-// and converts it to Lua table on top of Lua stack. All key-value pairs are
-// converted to the corresponding key-value pairs of the Lua table as long as
-// the Bundle value types are supported. At this point, we support boolean,
-// integer, double and String types in Java.
-void pushBundleToLuaTable(JNIEnv* env, LuaEngine* luaEngine, jobject bundle);
-
-} // namespace script_executor
-} // namespace telemetry
-} // namespace automotive
-} // namespace android
-
-#endif // CPP_TELEMETRY_SCRIPT_EXECUTOR_SRC_JNIUTILS_H_
diff --git a/cpp/telemetry/script_executor/src/LuaEngine.cpp b/cpp/telemetry/script_executor/src/LuaEngine.cpp
deleted file mode 100644
index e4be1dfda9..0000000000
--- a/cpp/telemetry/script_executor/src/LuaEngine.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 2021, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "LuaEngine.h"
-
-#include "BundleWrapper.h"
-
-#include <android-base/logging.h>
-#include <android/car/telemetry/IScriptExecutorConstants.h>
-
-#include <utility>
-
-extern "C" {
-#include "lauxlib.h"
-#include "lua.h"
-#include "lualib.h"
-}
-
-namespace android {
-namespace automotive {
-namespace telemetry {
-namespace script_executor {
-
-using android::car::telemetry::IScriptExecutorConstants;
-
-namespace {
-
-enum LuaNumReturnedResults {
- ZERO_RETURNED_RESULTS = 0,
-};
-
-} // namespace
-
-ScriptExecutorListener* LuaEngine::sListener = nullptr;
-
-LuaEngine::LuaEngine() {
- // Instantiate Lua environment
- mLuaState = luaL_newstate();
- luaL_openlibs(mLuaState);
-}
-
-LuaEngine::~LuaEngine() {
- lua_close(mLuaState);
-}
-
-lua_State* LuaEngine::getLuaState() {
- return mLuaState;
-}
-
-void LuaEngine::resetListener(ScriptExecutorListener* listener) {
- if (sListener != nullptr) {
- delete sListener;
- }
- sListener = listener;
-}
-
-int LuaEngine::loadScript(const char* scriptBody) {
- // As the first step in Lua script execution we want to load
- // the body of the script into Lua stack and have it processed by Lua
- // to catch any errors.
- // More on luaL_dostring: https://www.lua.org/manual/5.3/manual.html#lual_dostring
- // If error, pushes the error object into the stack.
- const auto status = luaL_dostring(mLuaState, scriptBody);
- if (status) {
- // Removes error object from the stack.
- // Lua stack must be properly maintained due to its limited size,
- // ~20 elements and its critical function because all interaction with
- // Lua happens via the stack.
- // Starting read about Lua stack: https://www.lua.org/pil/24.2.html
- // TODO(b/192284232): add test case to trigger this.
- lua_pop(mLuaState, 1);
- return status;
- }
-
- // Register limited set of reserved methods for Lua to call native side.
- lua_register(mLuaState, "on_success", LuaEngine::onSuccess);
- lua_register(mLuaState, "on_error", LuaEngine::onError);
- return status;
-}
-
-bool LuaEngine::pushFunction(const char* functionName) {
- // Interaction between native code and Lua happens via Lua stack.
- // In such model, a caller first pushes the name of the function
- // that needs to be called, followed by the function's input
- // arguments, one input value pushed at a time.
- // More info: https://www.lua.org/pil/24.2.html
- lua_getglobal(mLuaState, functionName);
- const auto status = lua_isfunction(mLuaState, /*idx= */ -1);
- // TODO(b/192284785): add test case for wrong function name in Lua.
- if (status == 0) lua_pop(mLuaState, 1);
- return status;
-}
-
-int LuaEngine::run() {
- // Performs blocking call of the provided Lua function. Assumes all
- // 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);
-}
-
-int LuaEngine::onSuccess(lua_State* lua) {
- // Any script we run can call on_success only with a single argument of Lua table type.
- if (lua_gettop(lua) != 1 || !lua_istable(lua, /* index =*/-1)) {
- // TODO(b/193565932): Return programming error through binder callback interface.
- LOG(ERROR) << "Only a single input argument, a Lua table object, expected here";
- }
-
- // Helper object to create and populate Java Bundle object.
- BundleWrapper bundleWrapper(sListener->getCurrentJNIEnv());
- // Iterate over Lua table which is expected to be at the top of Lua stack.
- // lua_next call pops the key from the top of the stack and finds the next
- // key-value pair for the popped key. It returns 0 if the next pair was not found.
- // More on lua_next in: https://www.lua.org/manual/5.3/manual.html#lua_next
- lua_pushnil(lua); // First key is a null value.
- while (lua_next(lua, /* index = */ -2) != 0) {
- // 'key' is at index -2 and 'value' is at index -1
- // -1 index is the top of the stack.
- // remove 'value' and keep 'key' for next iteration
- // Process each key-value depending on a type and push it to Java Bundle.
- const char* key = lua_tostring(lua, /* index = */ -2);
- 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)));
- } 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)) {
- bundleWrapper.putString(key, lua_tostring(lua, /* index = */ -1));
- } else {
- // not supported yet...
- LOG(WARNING) << "key=" << key << " has a Lua type which is not supported yet. "
- << "The bundle object will not have this key-value pair.";
- }
- // Pop 1 element from the stack.
- lua_pop(lua, 1);
- // The key is at index -1, the table is at index -2 now.
- }
-
- // Forward the populated Bundle object to Java callback.
- sListener->onSuccess(bundleWrapper.getBundle());
- // We explicitly must tell Lua how many results we return, which is 0 in this case.
- // More on the topic: https://www.lua.org/manual/5.3/manual.html#lua_CFunction
- return ZERO_RETURNED_RESULTS;
-}
-
-int LuaEngine::onError(lua_State* lua) {
- // Any script we run can call on_error only with a single argument of Lua string type.
- if (lua_gettop(lua) != 1 || !lua_isstring(lua, /* index = */ -1)) {
- sListener->onError(IScriptExecutorConstants::ERROR_TYPE_LUA_SCRIPT_ERROR,
- "on_error can push only a single string parameter from Lua", "");
- return ZERO_RETURNED_RESULTS;
- }
- sListener->onError(IScriptExecutorConstants::ERROR_TYPE_LUA_SCRIPT_ERROR,
- lua_tostring(lua, /* index = */ -1), /* stackTrace =*/"");
- return ZERO_RETURNED_RESULTS;
-}
-
-} // namespace script_executor
-} // namespace telemetry
-} // namespace automotive
-} // namespace android
diff --git a/cpp/telemetry/script_executor/src/LuaEngine.h b/cpp/telemetry/script_executor/src/LuaEngine.h
deleted file mode 100644
index 03252a7082..0000000000
--- a/cpp/telemetry/script_executor/src/LuaEngine.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2021, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CPP_TELEMETRY_SCRIPT_EXECUTOR_SRC_LUAENGINE_H_
-#define CPP_TELEMETRY_SCRIPT_EXECUTOR_SRC_LUAENGINE_H_
-
-#include "ScriptExecutorListener.h"
-
-#include <memory>
-
-extern "C" {
-#include "lua.h"
-}
-
-namespace android {
-namespace automotive {
-namespace telemetry {
-namespace script_executor {
-
-// Encapsulates Lua script execution environment.
-class LuaEngine {
-public:
- LuaEngine();
-
- virtual ~LuaEngine();
-
- // Returns pointer to Lua state object.
- lua_State* getLuaState();
-
- // Loads Lua script provided as scriptBody string.
- // Returns 0 if successful. Otherwise returns non-zero Lua error code.
- int loadScript(const char* scriptBody);
-
- // Pushes a Lua function under provided name into the stack.
- // Returns true if successful.
- bool pushFunction(const char* functionName);
-
- // Invokes function with the inputs provided in the stack.
- // Assumes that the script body has been already loaded and successfully
- // compiled and run, and all input arguments, and the function have been
- // pushed to the stack.
- // Returns 0 if successful. Otherwise returns non-zero Lua error code.
- int run();
-
- // Updates stored listener and destroys the previous one.
- static void resetListener(ScriptExecutorListener* listener);
-
-private:
- // Invoked by a running Lua script to store intermediate results.
- // The script will provide the results as a Lua table.
- // We currently support only non-nested fields in the table and the fields can be the following
- // Lua types: boolean, number, integer, and string.
- // The result pushed by Lua is converted to Android Bundle and forwarded to
- // ScriptExecutor service via callback interface.
- // This method returns 0 to indicate that no results were pushed to Lua stack according
- // to Lua C function calling convention.
- // More info: https://www.lua.org/manual/5.3/manual.html#lua_CFunction
- static int onSuccess(lua_State* lua);
-
- // Invoked by a running Lua script to indicate than an error occurred. This is the mechanism to
- // for a script author to receive error logs. The caller script encapsulates all the information
- // about the error that the author wants to provide in a single string parameter.
- // This method returns 0 to indicate that no results were pushed to Lua stack according
- // to Lua C function calling convention.
- // More info: https://www.lua.org/manual/5.3/manual.html#lua_CFunction
- static int onError(lua_State* lua);
-
- // Points to the current listener object.
- // Lua cannot call non-static class methods. We need to access listener object instance in
- // Lua callbacks. Therefore, callbacks callable by Lua are static class methods and the pointer
- // to a listener object needs to be static, since static methods cannot access non-static
- // members.
- // Only one listener is supported at any given time.
- // Since listeners are heap-allocated, the destructor does not need to run at shutdown
- // of the service because the memory allocated to the current listener object will be
- // reclaimed by the OS.
- static ScriptExecutorListener* sListener;
-
- lua_State* mLuaState; // owned
-};
-
-} // namespace script_executor
-} // namespace telemetry
-} // namespace automotive
-} // namespace android
-
-#endif // CPP_TELEMETRY_SCRIPT_EXECUTOR_SRC_LUAENGINE_H_
diff --git a/cpp/telemetry/script_executor/src/ScriptExecutorJni.cpp b/cpp/telemetry/script_executor/src/ScriptExecutorJni.cpp
deleted file mode 100644
index 0bdc692dd7..0000000000
--- a/cpp/telemetry/script_executor/src/ScriptExecutorJni.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2021, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "JniUtils.h"
-#include "LuaEngine.h"
-#include "ScriptExecutorListener.h"
-#include "jni.h"
-
-#include <android-base/logging.h>
-
-#include <cstdint>
-
-namespace android {
-namespace automotive {
-namespace telemetry {
-namespace script_executor {
-
-extern "C" {
-
-JNIEXPORT jlong JNICALL
-Java_com_android_car_telemetry_ScriptExecutor_nativeInitLuaEngine(JNIEnv* env, jobject object) {
- // Cast first to intptr_t to ensure int can hold the pointer without loss.
- return static_cast<jlong>(reinterpret_cast<intptr_t>(new LuaEngine()));
-}
-
-JNIEXPORT void JNICALL Java_com_android_car_telemetry_ScriptExecutor_nativeDestroyLuaEngine(
- JNIEnv* env, jobject object, jlong luaEnginePtr) {
- delete reinterpret_cast<LuaEngine*>(static_cast<intptr_t>(luaEnginePtr));
-}
-
-// Parses the inputs and loads them to Lua one at a time.
-// Loading of data into Lua also triggers checks on Lua side to verify the
-// inputs are valid. For example, pushing "functionName" into Lua stack verifies
-// that the function name actually exists in the previously loaded body of the
-// script.
-//
-// The steps are:
-// Step 1: Parse the inputs for obvious programming errors.
-// Step 2: Parse and load the body of the script.
-// Step 3: Parse and push function name we want to execute in the provided
-// script body to Lua stack. If the function name doesn't exist, we exit.
-// Step 4: Parse publishedData, convert it into Lua table and push it to the
-// stack.
-// Step 5: Parse savedState Bundle object, convert it into Lua table and push it
-// to the stack.
-// Any errors that occur at the stage above result in quick exit or crash.
-//
-// All interaction with Lua happens via Lua stack. Therefore, order of how the
-// inputs are parsed and processed is critical because Lua API methods such as
-// lua_pcall assume specific order between function name and the input arguments
-// on the stack.
-// More information about how to work with Lua stack: https://www.lua.org/pil/24.2.html
-// and how Lua functions are called via Lua API: https://www.lua.org/pil/25.2.html
-//
-// Finally, once parsing and pushing to Lua stack is complete, we go on to the final step,
-// Step 6: Attempt to run the provided function.
-JNIEXPORT void JNICALL Java_com_android_car_telemetry_ScriptExecutor_nativeInvokeScript(
- JNIEnv* env, jobject object, jlong luaEnginePtr, jstring scriptBody, jstring functionName,
- jobject publishedData, jobject savedState, jobject listener) {
- if (!luaEnginePtr) {
- env->FatalError("luaEnginePtr parameter cannot be nil");
- }
- if (scriptBody == nullptr) {
- env->FatalError("scriptBody parameter cannot be null");
- }
- if (functionName == nullptr) {
- env->FatalError("functionName parameter cannot be null");
- }
- if (listener == nullptr) {
- env->FatalError("listener parameter cannot be null");
- }
-
- LuaEngine* engine = reinterpret_cast<LuaEngine*>(static_cast<intptr_t>(luaEnginePtr));
-
- // Load and parse the script
- const char* scriptStr = env->GetStringUTFChars(scriptBody, nullptr);
- auto status = engine->loadScript(scriptStr);
- env->ReleaseStringUTFChars(scriptBody, scriptStr);
- // status == 0 if the script loads successfully.
- if (status) {
- env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"),
- "Failed to load the script.");
- return;
- }
- LuaEngine::resetListener(new ScriptExecutorListener(env, listener));
-
- // Push the function name we want to invoke to Lua stack
- const char* functionNameStr = env->GetStringUTFChars(functionName, nullptr);
- status = engine->pushFunction(functionNameStr);
- env->ReleaseStringUTFChars(functionName, functionNameStr);
- // status == 1 if the name is indeed a function.
- if (!status) {
- env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"),
- "symbol functionName does not correspond to a function.");
- return;
- }
-
- // TODO(b/189241508): Provide implementation to parse publishedData input,
- // convert it into Lua table and push into Lua stack.
- if (publishedData) {
- env->ThrowNew(env->FindClass("java/lang/RuntimeException"),
- "Parsing of publishedData is not implemented yet.");
- return;
- }
-
- // Unpack bundle in savedState, convert to Lua table and push it to Lua
- // stack.
- pushBundleToLuaTable(env, engine, savedState);
-
- // Execute the function. This will block until complete or error.
- if (engine->run()) {
- env->ThrowNew(env->FindClass("java/lang/RuntimeException"),
- "Runtime error occurred while running the function.");
- return;
- }
-}
-
-} // extern "C"
-
-} // namespace script_executor
-} // namespace telemetry
-} // namespace automotive
-} // namespace android
diff --git a/cpp/telemetry/script_executor/src/ScriptExecutorListener.cpp b/cpp/telemetry/script_executor/src/ScriptExecutorListener.cpp
deleted file mode 100644
index 75a5e8d30f..0000000000
--- a/cpp/telemetry/script_executor/src/ScriptExecutorListener.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2021, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "ScriptExecutorListener.h"
-
-#include <android-base/logging.h>
-
-namespace android {
-namespace automotive {
-namespace telemetry {
-namespace script_executor {
-
-ScriptExecutorListener::~ScriptExecutorListener() {
- JNIEnv* env = getCurrentJNIEnv();
- if (mScriptExecutorListener != nullptr) {
- env->DeleteGlobalRef(mScriptExecutorListener);
- }
-}
-
-ScriptExecutorListener::ScriptExecutorListener(JNIEnv* env, jobject script_executor_listener) {
- mScriptExecutorListener = env->NewGlobalRef(script_executor_listener);
- env->GetJavaVM(&mJavaVM);
-}
-
-void ScriptExecutorListener::onSuccess(jobject bundle) {
- JNIEnv* env = getCurrentJNIEnv();
- if (mScriptExecutorListener == nullptr) {
- env->FatalError(
- "mScriptExecutorListener must point to a valid listener object, not nullptr.");
- }
- jclass listenerClass = env->GetObjectClass(mScriptExecutorListener);
- jmethodID onSuccessMethod =
- env->GetMethodID(listenerClass, "onSuccess", "(Landroid/os/Bundle;)V");
- env->CallVoidMethod(mScriptExecutorListener, onSuccessMethod, bundle);
-}
-
-void ScriptExecutorListener::onError(const int errorType, const char* message,
- const char* stackTrace) {
- JNIEnv* env = getCurrentJNIEnv();
- if (mScriptExecutorListener == nullptr) {
- env->FatalError(
- "mScriptExecutorListener must point to a valid listener object, not nullptr.");
- }
- jclass listenerClass = env->GetObjectClass(mScriptExecutorListener);
- jmethodID onErrorMethod =
- env->GetMethodID(listenerClass, "onError", "(ILjava/lang/String;Ljava/lang/String;)V");
-
- env->CallVoidMethod(mScriptExecutorListener, onErrorMethod, errorType,
- env->NewStringUTF(message), env->NewStringUTF(stackTrace));
-}
-
-JNIEnv* ScriptExecutorListener::getCurrentJNIEnv() {
- JNIEnv* env;
- if (mJavaVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- LOG(FATAL) << "Unable to return JNIEnv from JavaVM";
- }
- return env;
-}
-
-} // namespace script_executor
-} // namespace telemetry
-} // namespace automotive
-} // namespace android
diff --git a/cpp/telemetry/script_executor/src/ScriptExecutorListener.h b/cpp/telemetry/script_executor/src/ScriptExecutorListener.h
deleted file mode 100644
index f86476ce76..0000000000
--- a/cpp/telemetry/script_executor/src/ScriptExecutorListener.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2021, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CPP_TELEMETRY_SCRIPT_EXECUTOR_SRC_SCRIPTEXECUTORLISTENER_H_
-#define CPP_TELEMETRY_SCRIPT_EXECUTOR_SRC_SCRIPTEXECUTORLISTENER_H_
-
-#include "jni.h"
-
-#include <string>
-
-namespace android {
-namespace automotive {
-namespace telemetry {
-namespace script_executor {
-
-// Wrapper class for IScriptExecutorListener.aidl.
-class ScriptExecutorListener {
-public:
- ScriptExecutorListener(JNIEnv* jni, jobject script_executor_listener);
-
- virtual ~ScriptExecutorListener();
-
- void onScriptFinished() {}
-
- void onSuccess(jobject bundle);
-
- void onError(const int errorType, const char* message, const char* stackTrace);
-
- JNIEnv* getCurrentJNIEnv();
-
-private:
- // Stores a jni global reference to Java Script Executor listener object.
- jobject mScriptExecutorListener;
-
- // Stores JavaVM pointer in order to be able to get JNIEnv pointer.
- // This is done because JNIEnv cannot be shared between threads.
- // https://developer.android.com/training/articles/perf-jni.html#javavm-and-jnienv
- JavaVM* mJavaVM;
-};
-
-} // namespace script_executor
-} // namespace telemetry
-} // namespace automotive
-} // namespace android
-
-#endif // CPP_TELEMETRY_SCRIPT_EXECUTOR_SRC_SCRIPTEXECUTORLISTENER_H_
diff --git a/cpp/telemetry/script_executor/src/tests/JniUtilsTestHelper.cpp b/cpp/telemetry/script_executor/src/tests/JniUtilsTestHelper.cpp
deleted file mode 100644
index 8cdf87a6f5..0000000000
--- a/cpp/telemetry/script_executor/src/tests/JniUtilsTestHelper.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2021, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "JniUtils.h"
-#include "LuaEngine.h"
-#include "jni.h"
-
-#include <cstdint>
-#include <cstring>
-
-namespace android {
-namespace automotive {
-namespace telemetry {
-namespace script_executor {
-namespace {
-
-extern "C" {
-
-#include "lua.h"
-
-JNIEXPORT jlong JNICALL
-Java_com_android_car_telemetry_JniUtilsTest_nativeCreateLuaEngine(JNIEnv* env, jobject object) {
- // Cast first to intptr_t to ensure int can hold the pointer without loss.
- return static_cast<jlong>(reinterpret_cast<intptr_t>(new LuaEngine()));
-}
-
-JNIEXPORT void JNICALL Java_com_android_car_telemetry_JniUtilsTest_nativeDestroyLuaEngine(
- JNIEnv* env, jobject object, jlong luaEnginePtr) {
- delete reinterpret_cast<LuaEngine*>(static_cast<intptr_t>(luaEnginePtr));
-}
-
-JNIEXPORT void JNICALL Java_com_android_car_telemetry_JniUtilsTest_nativePushBundleToLuaTableCaller(
- JNIEnv* env, jobject object, jlong luaEnginePtr, jobject bundle) {
- pushBundleToLuaTable(env, reinterpret_cast<LuaEngine*>(static_cast<intptr_t>(luaEnginePtr)),
- bundle);
-}
-
-JNIEXPORT jint JNICALL Java_com_android_car_telemetry_JniUtilsTest_nativeGetObjectSize(
- JNIEnv* env, jobject object, jlong luaEnginePtr, jint index) {
- LuaEngine* engine = reinterpret_cast<LuaEngine*>(static_cast<intptr_t>(luaEnginePtr));
- return lua_rawlen(engine->getLuaState(), static_cast<int>(index));
-}
-
-JNIEXPORT bool JNICALL Java_com_android_car_telemetry_JniUtilsTest_nativeHasBooleanValue(
- JNIEnv* env, jobject object, jlong luaEnginePtr, jstring key, jboolean value) {
- const char* rawKey = env->GetStringUTFChars(key, nullptr);
- LuaEngine* engine = reinterpret_cast<LuaEngine*>(static_cast<intptr_t>(luaEnginePtr));
- auto* luaState = engine->getLuaState();
- lua_pushstring(luaState, rawKey);
- env->ReleaseStringUTFChars(key, rawKey);
- lua_gettable(luaState, -2);
- bool result = false;
- if (!lua_isboolean(luaState, -1))
- result = false;
- else
- result = static_cast<bool>(lua_toboolean(luaState, -1)) == static_cast<bool>(value);
- lua_pop(luaState, 1);
- return result;
-}
-
-JNIEXPORT bool JNICALL Java_com_android_car_telemetry_JniUtilsTest_nativeHasIntValue(
- JNIEnv* env, jobject object, jlong luaEnginePtr, jstring key, jint value) {
- const char* rawKey = env->GetStringUTFChars(key, nullptr);
- LuaEngine* engine = reinterpret_cast<LuaEngine*>(static_cast<intptr_t>(luaEnginePtr));
- // Assumes the table is on top of the stack.
- auto* luaState = engine->getLuaState();
- lua_pushstring(luaState, rawKey);
- env->ReleaseStringUTFChars(key, rawKey);
- lua_gettable(luaState, -2);
- bool result = false;
- if (!lua_isinteger(luaState, -1))
- result = false;
- else
- result = lua_tointeger(luaState, -1) == static_cast<int>(value);
- lua_pop(luaState, 1);
- return result;
-}
-
-JNIEXPORT bool JNICALL Java_com_android_car_telemetry_JniUtilsTest_nativeHasDoubleValue(
- JNIEnv* env, jobject object, jlong luaEnginePtr, jstring key, jdouble value) {
- const char* rawKey = env->GetStringUTFChars(key, nullptr);
- LuaEngine* engine = reinterpret_cast<LuaEngine*>(static_cast<intptr_t>(luaEnginePtr));
- // Assumes the table is on top of the stack.
- auto* luaState = engine->getLuaState();
- lua_pushstring(luaState, rawKey);
- env->ReleaseStringUTFChars(key, rawKey);
- lua_gettable(luaState, -2);
- bool result = false;
- if (!lua_isnumber(luaState, -1))
- result = false;
- else
- result = static_cast<double>(lua_tonumber(luaState, -1)) == static_cast<double>(value);
- lua_pop(luaState, 1);
- return result;
-}
-
-JNIEXPORT bool JNICALL Java_com_android_car_telemetry_JniUtilsTest_nativeHasStringValue(
- JNIEnv* env, jobject object, jlong luaEnginePtr, jstring key, jstring value) {
- const char* rawKey = env->GetStringUTFChars(key, nullptr);
- LuaEngine* engine = reinterpret_cast<LuaEngine*>(static_cast<intptr_t>(luaEnginePtr));
- // Assumes the table is on top of the stack.
- auto* luaState = engine->getLuaState();
- lua_pushstring(luaState, rawKey);
- env->ReleaseStringUTFChars(key, rawKey);
- lua_gettable(luaState, -2);
- bool result = false;
- if (!lua_isstring(luaState, -1)) {
- result = false;
- } else {
- std::string s = lua_tostring(luaState, -1);
- const char* rawValue = env->GetStringUTFChars(value, nullptr);
- result = strcmp(lua_tostring(luaState, -1), rawValue) == 0;
- env->ReleaseStringUTFChars(value, rawValue);
- }
- lua_pop(luaState, 1);
- return result;
-}
-
-} // extern "C"
-
-} // namespace
-} // namespace script_executor
-} // namespace telemetry
-} // namespace automotive
-} // namespace android