1 /* 2 * Copyright (c) 2021, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef PACKAGES_SCRIPTEXECUTOR_SRC_LUAENGINE_H_ 18 #define PACKAGES_SCRIPTEXECUTOR_SRC_LUAENGINE_H_ 19 20 #include "ScriptExecutorListener.h" 21 22 #include <memory> 23 24 extern "C" { 25 #include "lua.h" 26 } 27 28 namespace com { 29 namespace android { 30 namespace car { 31 namespace scriptexecutor { 32 33 // Encapsulates Lua script execution environment. 34 class LuaEngine { 35 public: 36 LuaEngine(); 37 38 virtual ~LuaEngine(); 39 40 // Returns pointer to Lua state object. 41 lua_State* getLuaState(); 42 43 // Loads Lua script provided as scriptBody string. 44 // Returns 0 if successful. Otherwise returns non-zero Lua error code. 45 int loadScript(const char* scriptBody); 46 47 // Pushes a Lua function under provided name into the stack. 48 // Returns 1 if successful. Otherwise, an error is sent back to the client via the callback 49 // and 0 is returned. 50 int pushFunction(const char* functionName); 51 52 // Invokes function with the inputs provided in the stack. 53 // Assumes that the script body has been already loaded and successfully 54 // compiled and run, and all input arguments, and the function have been 55 // pushed to the stack. 56 // Returns 0 if successful. Otherwise returns non-zero Lua error code 57 // and sends the error via a callback back to the client. 58 int run(); 59 60 // Updates stored listener and destroys the previous one. 61 static void resetListener(ScriptExecutorListener* listener); 62 63 private: 64 // Invoked by a running Lua script to produce a log to logcat. This is useful for debugging. 65 // This does not invoke ScriptExecutorListener. Scripts are expected to call one of the 66 // terminating functions to end the script execution. 67 // This method returns 0 to indicate that no results were pushed to Lua stack according 68 // to Lua C function calling convention. 69 // More info: https://www.lua.org/manual/5.3/manual.html#lua_CFunction 70 // Usage in lua script: 71 // log("selected gear: ", g) 72 static int scriptLog(lua_State* lua); 73 74 // Invoked by a running Lua script to store intermediate results. 75 // The script will provide the results as a Lua table. 76 // We currently support only non-nested fields in the table and the fields can be the following 77 // Lua types: boolean, number, integer, and string. 78 // The result pushed by Lua is converted to PersistableBundle and forwarded to 79 // ScriptExecutor service via callback interface. 80 // This method returns 0 to indicate that no results were pushed to Lua stack according 81 // to Lua C function calling convention. 82 // More info: https://www.lua.org/manual/5.3/manual.html#lua_CFunction 83 static int onSuccess(lua_State* lua); 84 85 // Invoked by a running Lua script to effectively mark the completion of the script's lifecycle, 86 // and send the final results to CarTelemetryService and then to the user. 87 // The script will provide the final results as a Lua table. 88 // We currently support only non-nested fields in the table and the fields can be the following 89 // Lua types: boolean, number, integer, and string. 90 // The result pushed by Lua is converted to Android PersistableBundle and forwarded to 91 // ScriptExecutor service via callback interface. 92 // This method returns 0 to indicate that no results were pushed to Lua stack according 93 // to Lua C function calling convention. 94 // More info: https://www.lua.org/manual/5.3/manual.html#lua_CFunction 95 static int onScriptFinished(lua_State* lua); 96 97 // Invoked by a running Lua script to indicate than an error occurred. This is the mechanism to 98 // for a script author to receive error logs. The caller script encapsulates all the information 99 // about the error that the author wants to provide in a single string parameter. 100 // This method returns 0 to indicate that no results were pushed to Lua stack according 101 // to Lua C function calling convention. 102 // More info: https://www.lua.org/manual/5.3/manual.html#lua_CFunction 103 static int onError(lua_State* lua); 104 105 // Invoked by a running Lua script to produce a metrics report without completing 106 // the script's lifecycle, 107 // The metrics report will be sent to CarTelemetryService and then to the user. 108 // The script will provide the report as a Lua table. 109 // We currently support only non-nested fields in the table and the fields can be the following 110 // Lua types: boolean, number, integer, and string. 111 // The result pushed by Lua is converted to Android PersistableBundle and forwarded to 112 // ScriptExecutor service via callback interface. 113 // This method returns 0 to indicate that no results were pushed to Lua stack according 114 // to Lua C function calling convention. 115 // More info: https://www.lua.org/manual/5.3/manual.html#lua_CFunction 116 // Usage in lua script: 117 // on_metrics_report(report_as_a_table) 118 // on_metrics_report(report_as_a_table, saved_state_as_a_table) 119 static int onMetricsReport(lua_State* lua); 120 121 // Points to the current listener object. 122 // Lua cannot call non-static class methods. We need to access listener object instance in 123 // Lua callbacks. Therefore, callbacks callable by Lua are static class methods and the pointer 124 // to a listener object needs to be static, since static methods cannot access non-static 125 // members. 126 // Only one listener is supported at any given time. 127 // Since listeners are heap-allocated, the destructor does not need to run at shutdown 128 // of the service because the memory allocated to the current listener object will be 129 // reclaimed by the OS. 130 static ScriptExecutorListener* sListener; 131 132 lua_State* mLuaState; // owned 133 }; 134 135 } // namespace scriptexecutor 136 } // namespace car 137 } // namespace android 138 } // namespace com 139 140 #endif // PACKAGES_SCRIPTEXECUTOR_SRC_LUAENGINE_H_ 141