/* * Copyright 2016 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. */ #define LOG_TAG "VtsAgentRequestHandler" #include "AgentRequestHandler.h" #include #include #include #include #include #include "BinderClientToDriver.h" #include "SocketClientToDriver.h" #include "SocketServerForDriver.h" #include "test/vts/proto/AndroidSystemControlMessage.pb.h" #include "test/vts/proto/VtsDriverControlMessage.pb.h" #include "test/vts/proto/VtsResourceControllerMessage.pb.h" using namespace std; using namespace google::protobuf; namespace android { namespace vts { bool AgentRequestHandler::ListHals(const RepeatedPtrField& base_paths) { AndroidSystemControlResponseMessage response_msg; ResponseCode result = FAIL; for (const string& path : base_paths) { LOG(DEBUG) << "open a dir " << path; DIR* dp; if (!(dp = opendir(path.c_str()))) { LOG(ERROR) << "Error(" << errno << ") opening " << path; continue; } struct dirent* dirp; int len; while ((dirp = readdir(dp)) != NULL) { len = strlen(dirp->d_name); if (len > 3 && !strcmp(&dirp->d_name[len - 3], ".so")) { string found_path = path + "/" + string(dirp->d_name); LOG(INFO) << "found " << found_path; response_msg.add_file_names(found_path); result = SUCCESS; } } closedir(dp); } response_msg.set_response_code(result); return VtsSocketSendMessage(response_msg); } bool AgentRequestHandler::SetHostInfo(const int callback_port) { callback_port_ = callback_port; AndroidSystemControlResponseMessage response_msg; response_msg.set_response_code(SUCCESS); return VtsSocketSendMessage(response_msg); } bool AgentRequestHandler::CheckDriverService(const string& service_name, bool* live) { AndroidSystemControlResponseMessage response_msg; #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket if (IsDriverRunning(service_name, 10)) { #else // binder sp binder = GetBinderClient(service_name); if (binder.get()) { #endif if (live) *live = true; response_msg.set_response_code(SUCCESS); response_msg.set_reason("found the service"); LOG(DEBUG) << "set service_name " << service_name; service_name_ = service_name; } else { if (live) *live = false; response_msg.set_response_code(FAIL); response_msg.set_reason("service not found"); } return VtsSocketSendMessage(response_msg); } static const char kUnixSocketNamePrefixForCallbackServer[] = "/data/local/tmp/vts_agent_callback"; bool AgentRequestHandler::LaunchDriverService( const AndroidSystemControlCommandMessage& command_msg) { int driver_type = command_msg.driver_type(); const string& service_name = command_msg.service_name(); const string& file_path = command_msg.file_path(); int target_class = command_msg.target_class(); int target_type = command_msg.target_type(); int target_version_major = command_msg.target_version_major(); int target_version_minor = command_msg.target_version_minor(); const string& target_package = command_msg.target_package(); const string& target_component_name = command_msg.target_component_name(); const string& module_name = command_msg.module_name(); const string& hw_binder_service_name = command_msg.hw_binder_service_name(); int bits = command_msg.bits(); const string& test_hal_flag = command_msg.is_test_hal() ? "TREBLE_TESTING_OVERRIDE=true " : ""; LOG(DEBUG) << "file_path=" << file_path; ResponseCode result = FAIL; // TODO: shall check whether there's a service with the same name and return // success immediately if exists. AndroidSystemControlResponseMessage response_msg; // deletes the service file if exists before starting to launch a driver. string socket_port_flie_path = GetSocketPortFilePath(service_name); struct stat file_stat; if (stat(socket_port_flie_path.c_str(), &file_stat) == 0 // file exists && remove(socket_port_flie_path.c_str()) == -1) { LOG(ERROR) << socket_port_flie_path << " delete error"; response_msg.set_reason("service file already exists."); } else { pid_t pid = fork(); if (pid == 0) { // child Close(); string driver_binary_path; char* cmd = NULL; if (driver_type == VTS_DRIVER_TYPE_HAL_CONVENTIONAL || driver_type == VTS_DRIVER_TYPE_HAL_LEGACY || driver_type == VTS_DRIVER_TYPE_HAL_HIDL) { // TODO: check whether the port is available and handle if fails. static int port = 0; string callback_socket_name(kUnixSocketNamePrefixForCallbackServer); callback_socket_name += to_string(port++); LOG(INFO) << "callback_socket_name: " << callback_socket_name; StartSocketServerForDriver(callback_socket_name, -1); if (bits == 32) { driver_binary_path = driver_hal_binary32_; } else { driver_binary_path = driver_hal_binary64_; } size_t offset = driver_binary_path.find_last_of("/"); string ld_dir_path = driver_binary_path.substr(0, offset); if (driver_hal_spec_dir_path_.length() < 1) { #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket asprintf(&cmd, "%sLD_LIBRARY_PATH=%s:$LD_LIBRARY_PATH %s " "--server_socket_path=%s " "--callback_socket_name=%s", test_hal_flag.c_str(), ld_dir_path.c_str(), driver_binary_path.c_str(), socket_port_flie_path.c_str(), callback_socket_name.c_str()); #else // binder asprintf(&cmd, "LD_LIBRARY_PATH=%s:$LD_LIBRARY_PATH %s " "--service_name=%s " "--callback_socket_name=%s", ld_dir_path.c_str(), driver_binary_path.c_str(), service_name.c_str(), callback_socket_name.c_str()); #endif } else { #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket asprintf(&cmd, "%sLD_LIBRARY_PATH=%s:$LD_LIBRARY_PATH %s " "--server_socket_path=%s " "--spec_dir_path=%s --callback_socket_name=%s", test_hal_flag.c_str(), ld_dir_path.c_str(), driver_binary_path.c_str(), socket_port_flie_path.c_str(), driver_hal_spec_dir_path_.c_str(), callback_socket_name.c_str()); #else // binder asprintf(&cmd, "LD_LIBRARY_PATH=%s:$LD_LIBRARY_PATH %s " "--service_name=%s " "--spec_dir_path=%s --callback_socket_name=%s", ld_dir_path.c_str(), driver_binary_path.c_str(), service_name.c_str(), driver_hal_spec_dir_path_.c_str(), callback_socket_name.c_str()); #endif } } else if (driver_type == VTS_DRIVER_TYPE_SHELL) { if (bits == 32) { driver_binary_path = driver_shell_binary32_; } else { driver_binary_path = driver_shell_binary64_; } size_t offset = driver_binary_path.find_last_of("/"); string ld_dir_path = driver_binary_path.substr(0, offset); #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket asprintf( &cmd, "LD_LIBRARY_PATH=%s:$LD_LIBRARY_PATH %s --server_socket_path=%s", ld_dir_path.c_str(), driver_binary_path.c_str(), socket_port_flie_path.c_str()); #else // binder LOG(ERROR) << "No binder implementation available."; exit(-1); #endif } else { LOG(ERROR) << "Unsupported driver type."; } if (cmd) { LOG(INFO) << "Launch a driver - " << cmd; system(cmd); LOG(INFO) << "driver exits"; free(cmd); } exit(0); } else if (pid > 0) { for (int attempt = 0; attempt < 10; attempt++) { sleep(1); if (IsDriverRunning(service_name, 10)) { result = SUCCESS; break; } } if (result) { // TODO: use an attribute (client) of a newly defined class. #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket VtsDriverSocketClient* client = android::vts::GetDriverSocketClient(service_name); if (!client) { #else // binder android::sp client = android::vts::GetBinderClient(service_name); if (!client.get()) { #endif response_msg.set_response_code(FAIL); response_msg.set_reason("Failed to start a driver."); // TODO: kill the driver? return VtsSocketSendMessage(response_msg); } if (driver_type == VTS_DRIVER_TYPE_HAL_CONVENTIONAL || driver_type == VTS_DRIVER_TYPE_HAL_LEGACY || driver_type == VTS_DRIVER_TYPE_HAL_HIDL) { LOG(DEBUG) << "LoadHal " << module_name; int32_t driver_id = client->LoadHal( file_path, target_class, target_type, target_version_major, target_version_minor, target_package, target_component_name, hw_binder_service_name, module_name); if (driver_id == -1) { response_msg.set_response_code(FAIL); response_msg.set_reason("Failed to load the selected HAL."); } else { response_msg.set_response_code(SUCCESS); response_msg.set_result(to_string(driver_id)); response_msg.set_reason("Loaded the selected HAL."); LOG(DEBUG) << "set service_name " << service_name; service_name_ = service_name; } } else if (driver_type == VTS_DRIVER_TYPE_SHELL) { response_msg.set_response_code(SUCCESS); response_msg.set_reason("Loaded the shell driver."); LOG(DEBUG) << "set service_name " << service_name; service_name_ = service_name; } #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket driver_client_ = client; #endif return VtsSocketSendMessage(response_msg); } } response_msg.set_reason( "Failed to fork a child process to start a driver."); } response_msg.set_response_code(FAIL); LOG(ERROR) << "Can't fork a child process to run the vts_hal_driver."; return VtsSocketSendMessage(response_msg); } bool AgentRequestHandler::ReadSpecification( const AndroidSystemControlCommandMessage& command_message) { #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket VtsDriverSocketClient* client = driver_client_; if (!client) { #else // binder android::sp client = android::vts::GetBinderClient(service_name_); if (!client.get()) { #endif return false; } const string& result = client->ReadSpecification( command_message.service_name(), command_message.target_class(), command_message.target_type(), command_message.target_version_major(), command_message.target_version_minor(), command_message.target_package()); return SendApiResult("ReadSpecification", result); } bool AgentRequestHandler::ListApis() { // TODO: use an attribute (client) of a newly defined class. #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket VtsDriverSocketClient* client = driver_client_; if (!client) { #else // binder android::sp client = android::vts::GetBinderClient(service_name_); if (!client.get()) { #endif return false; } return SendApiResult("GetAttribute", "", client->GetFunctions()); } bool AgentRequestHandler::CallApi(const string& call_payload, const string& uid) { #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket VtsDriverSocketClient* client = driver_client_; if (!client) { #else // binder // TODO: use an attribute (client) of a newly defined class. android::sp client = android::vts::GetBinderClient(service_name_); if (!client.get()) { #endif return false; } return SendApiResult("Call", client->Call(call_payload, uid)); } bool AgentRequestHandler::GetAttribute(const string& payload) { #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket VtsDriverSocketClient* client = driver_client_; if (!client) { #else // binder // TODO: use an attribute (client) of a newly defined class. android::sp client = android::vts::GetBinderClient(service_name_); if (!client.get()) { #endif return false; } return SendApiResult("GetAttribute", client->GetAttribute(payload)); } bool AgentRequestHandler::SendApiResult(const string& func_name, const string& result, const string& spec) { AndroidSystemControlResponseMessage response_msg; if (result.size() > 0 || spec.size() > 0) { LOG(DEBUG) << "Call: success"; response_msg.set_response_code(SUCCESS); if (result.size() > 0) { response_msg.set_result(result); } if (spec.size() > 0) { response_msg.set_spec(spec); } } else { LOG(ERROR) << "Call: fail"; response_msg.set_response_code(FAIL); response_msg.set_reason("Failed to call api function: " + func_name); } return VtsSocketSendMessage(response_msg); } bool AgentRequestHandler::DefaultResponse() { AndroidSystemControlResponseMessage response_msg; response_msg.set_response_code(SUCCESS); response_msg.set_reason("an example reason here"); return VtsSocketSendMessage(response_msg); } bool AgentRequestHandler::ExecuteShellCommand( const AndroidSystemControlCommandMessage& command_message) { #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket VtsDriverSocketClient* client = driver_client_; if (!client) { #else // binder LOG(ERROR) << " binder not supported."; { #endif return false; } auto result_message = client->ExecuteShellCommand(command_message.shell_command()); AndroidSystemControlResponseMessage response_msg; if (result_message) { CreateSystemControlResponseFromDriverControlResponse(*result_message, &response_msg); } else { LOG(ERROR) << "ExecuteShellCommand: failed to call the api"; response_msg.set_response_code(FAIL); response_msg.set_reason("Failed to call the api."); } return VtsSocketSendMessage(response_msg); } void AgentRequestHandler::CreateSystemControlResponseFromDriverControlResponse( const VtsDriverControlResponseMessage& driver_control_response_message, AndroidSystemControlResponseMessage* system_control_response_message) { if (driver_control_response_message.response_code() == VTS_DRIVER_RESPONSE_SUCCESS) { LOG(DEBUG) << "ExecuteShellCommand: shell driver reported success"; system_control_response_message->set_response_code(SUCCESS); } else if (driver_control_response_message.response_code() == VTS_DRIVER_RESPONSE_FAIL) { LOG(ERROR) << "ExecuteShellCommand: shell driver reported fail"; system_control_response_message->set_response_code(FAIL); } else if (driver_control_response_message.response_code() == UNKNOWN_VTS_DRIVER_RESPONSE_CODE) { LOG(ERROR) << "ExecuteShellCommand: shell driver reported unknown"; system_control_response_message->set_response_code(UNKNOWN_RESPONSE_CODE); } for (const auto& log_stdout : driver_control_response_message.stdout()) { system_control_response_message->add_stdout(log_stdout); } for (const auto& log_stderr : driver_control_response_message.stderr()) { system_control_response_message->add_stderr(log_stderr); } for (const auto& exit_code : driver_control_response_message.exit_code()) { system_control_response_message->add_exit_code(exit_code); } } bool AgentRequestHandler::ProcessFmqCommand( const AndroidSystemControlCommandMessage& command_msg) { #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket VtsDriverSocketClient* client = driver_client_; if (!client) { #else // binder android::sp client = android::vts::GetBinderClient(service_name_); if (!client.get()) { #endif LOG(ERROR) << "Driver socket client is uninitialized."; return false; } AndroidSystemControlResponseMessage response_msg; FmqResponseMessage* fmq_response = response_msg.mutable_fmq_response(); FmqRequestMessage fmq_request = command_msg.fmq_request(); // send the request message bool success = client->ProcessFmqCommand(fmq_request, fmq_response); // prepare for response back to host if (success) { response_msg.set_response_code(SUCCESS); } else { response_msg.set_response_code(FAIL); response_msg.set_reason("Failed to call api to process FMQ command."); } return VtsSocketSendMessage(response_msg); } bool AgentRequestHandler::ProcessHidlMemoryCommand( const AndroidSystemControlCommandMessage& command_msg) { #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket VtsDriverSocketClient* client = driver_client_; if (!client) { #else // binder android::sp client = android::vts::GetBinderClient(service_name_); if (!client.get()) { #endif LOG(ERROR) << "Driver socket client is uninitialized."; return false; } AndroidSystemControlResponseMessage response_msg; HidlMemoryResponseMessage* hidl_memory_response = response_msg.mutable_hidl_memory_response(); HidlMemoryRequestMessage hidl_memory_request = command_msg.hidl_memory_request(); // send the request message bool success = client->ProcessHidlMemoryCommand(hidl_memory_request, hidl_memory_response); // prepare for response back to host if (success) { response_msg.set_response_code(SUCCESS); } else { response_msg.set_response_code(FAIL); response_msg.set_reason( "Failed to call api to process hidl_memory command."); } return VtsSocketSendMessage(response_msg); } bool AgentRequestHandler::ProcessHidlHandleCommand( const AndroidSystemControlCommandMessage& command_msg) { #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket VtsDriverSocketClient* client = driver_client_; if (!client) { #else // binder android::sp client = android::vts::GetBinderClient(service_name_); if (!client.get()) { #endif LOG(ERROR) << "Driver socket client is uninitialized."; return false; } AndroidSystemControlResponseMessage response_msg; HidlHandleResponseMessage* hidl_handle_response = response_msg.mutable_hidl_handle_response(); HidlHandleRequestMessage hidl_handle_request = command_msg.hidl_handle_request(); // send the request message bool success = client->ProcessHidlHandleCommand(hidl_handle_request, hidl_handle_response); // prepare for response back to host if (success) { response_msg.set_response_code(SUCCESS); } else { response_msg.set_response_code(FAIL); response_msg.set_reason( "Failed to call api to process hidl_handle command."); } return VtsSocketSendMessage(response_msg); } bool AgentRequestHandler::ProcessOneCommand() { AndroidSystemControlCommandMessage command_msg; if (!VtsSocketRecvMessage(&command_msg)) return false; LOG(DEBUG) << "command_type = " << command_msg.command_type(); switch (command_msg.command_type()) { case LIST_HALS: return ListHals(command_msg.paths()); case SET_HOST_INFO: return SetHostInfo(command_msg.callback_port()); case CHECK_DRIVER_SERVICE: return CheckDriverService(command_msg.service_name(), NULL); case LAUNCH_DRIVER_SERVICE: return LaunchDriverService(command_msg); case VTS_AGENT_COMMAND_READ_SPECIFICATION: return ReadSpecification(command_msg); case LIST_APIS: return ListApis(); case CALL_API: return CallApi(command_msg.arg(), command_msg.driver_caller_uid()); case VTS_AGENT_COMMAND_GET_ATTRIBUTE: return GetAttribute(command_msg.arg()); // for shell driver case VTS_AGENT_COMMAND_EXECUTE_SHELL_COMMAND: ExecuteShellCommand(command_msg); return true; case VTS_FMQ_COMMAND: return ProcessFmqCommand(command_msg); case VTS_HIDL_MEMORY_COMMAND: return ProcessHidlMemoryCommand(command_msg); case VTS_HIDL_HANDLE_COMMAND: return ProcessHidlHandleCommand(command_msg); default: LOG(ERROR) << " ERROR unknown command " << command_msg.command_type(); return DefaultResponse(); } } } // namespace vts } // namespace android