/* * Copyright (C) 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. */ #include "VtsHidlHalReplayer.h" #include <fcntl.h> #include <unistd.h> #include <fstream> #include <iostream> #include <string> #include <android-base/logging.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/text_format.h> #include "VtsProfilingUtil.h" #include "driver_base/DriverBase.h" #include "utils/InterfaceSpecUtil.h" #include "utils/StringUtil.h" using namespace std; static constexpr const char* kErrorString = "error"; static constexpr const char* kVoidString = "void"; static constexpr const int kInvalidDriverId = -1; namespace android { namespace vts { void VtsHidlHalReplayer::ListTestServices(const string& trace_file) { // Parse the trace file to get the sequence of function calls. int fd = open(trace_file.c_str(), O_RDONLY); if (fd < 0) { LOG(ERROR) << "Can not open trace file: " << trace_file << " error: " << std::strerror(errno); return; } google::protobuf::io::FileInputStream input(fd); VtsProfilingRecord msg; set<string> registeredHalServices; while (readOneDelimited(&msg, &input)) { string package_name = msg.package(); float version = msg.version(); string interface_name = msg.interface(); string service_fq_name = GetInterfaceFQName(package_name, version, interface_name); registeredHalServices.insert(service_fq_name); } for (string service : registeredHalServices) { cout << "hal_service: " << service << endl; } } bool VtsHidlHalReplayer::ReplayTrace( const string& trace_file, map<string, string>& hal_service_instances) { // Parse the trace file to get the sequence of function calls. int fd = open(trace_file.c_str(), O_RDONLY); if (fd < 0) { LOG(ERROR) << "Can not open trace file: " << trace_file << "error: " << std::strerror(errno); return false; } google::protobuf::io::FileInputStream input(fd); VtsProfilingRecord call_msg; VtsProfilingRecord expected_result_msg; while (readOneDelimited(&call_msg, &input) && readOneDelimited(&expected_result_msg, &input)) { if (call_msg.event() != InstrumentationEventType::SERVER_API_ENTRY && call_msg.event() != InstrumentationEventType::CLIENT_API_ENTRY && call_msg.event() != InstrumentationEventType::SYNC_CALLBACK_ENTRY && call_msg.event() != InstrumentationEventType::ASYNC_CALLBACK_ENTRY && call_msg.event() != InstrumentationEventType::PASSTHROUGH_ENTRY) { LOG(WARNING) << "Expected a call message but got message with event: " << call_msg.event(); continue; } if (expected_result_msg.event() != InstrumentationEventType::SERVER_API_EXIT && expected_result_msg.event() != InstrumentationEventType::CLIENT_API_EXIT && expected_result_msg.event() != InstrumentationEventType::SYNC_CALLBACK_EXIT && expected_result_msg.event() != InstrumentationEventType::ASYNC_CALLBACK_EXIT && expected_result_msg.event() != InstrumentationEventType::PASSTHROUGH_EXIT) { LOG(WARNING) << "Expected a result message but got message with event: " << call_msg.event(); continue; } string package_name = call_msg.package(); float version = call_msg.version(); string interface_name = call_msg.interface(); string instance_name = GetInterfaceFQName(package_name, version, interface_name); string hal_service_name = "default"; if (hal_service_instances.find(instance_name) == hal_service_instances.end()) { LOG(WARNING) << "Does not find service name for " << instance_name << "; this could be a nested interface."; } else { hal_service_name = hal_service_instances[instance_name]; } cout << "Replay function: " << call_msg.func_msg().name() << endl; LOG(DEBUG) << "Replay function: " << call_msg.func_msg().DebugString(); int32_t driver_id = driver_manager_->GetDriverIdForHidlHalInterface( package_name, version, interface_name, hal_service_name); if (driver_id == kInvalidDriverId) { LOG(ERROR) << "Couldn't get a driver base class"; return false; } vts::FunctionCallMessage func_call_msg; func_call_msg.set_component_class(HAL_HIDL); func_call_msg.set_hal_driver_id(driver_id); *func_call_msg.mutable_api() = call_msg.func_msg(); const string& result = driver_manager_->CallFunction(&func_call_msg); if (result == kVoidString || result == kErrorString) { LOG(ERROR) << "Replay function fail. Failed function call: " << func_call_msg.DebugString(); return false; } vts::FunctionSpecificationMessage result_msg; if (!google::protobuf::TextFormat::ParseFromString(result, &result_msg)) { LOG(ERROR) << "Failed to parse result msg."; return false; } if (!driver_manager_->VerifyResults( driver_id, expected_result_msg.func_msg(), result_msg)) { // Verification is not strict, i.e. if fail, output error message and // continue the process. LOG(WARNING) << "Verification fail. Expected: " << expected_result_msg.func_msg().DebugString() << " Actual: " << result_msg.DebugString(); } call_msg.Clear(); expected_result_msg.Clear(); } return true; } } // namespace vts } // namespace android