1 /*
2 * Copyright (C) 2016 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 #include "VtsHidlHalReplayer.h"
17
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <fstream>
21 #include <iostream>
22 #include <string>
23
24 #include <android-base/logging.h>
25 #include <google/protobuf/io/zero_copy_stream_impl.h>
26 #include <google/protobuf/text_format.h>
27
28 #include "VtsProfilingUtil.h"
29 #include "driver_base/DriverBase.h"
30 #include "utils/InterfaceSpecUtil.h"
31 #include "utils/StringUtil.h"
32
33 using namespace std;
34
35 static constexpr const char* kErrorString = "error";
36 static constexpr const char* kVoidString = "void";
37 static constexpr const int kInvalidDriverId = -1;
38
39 namespace android {
40 namespace vts {
41
ListTestServices(const string & trace_file)42 void VtsHidlHalReplayer::ListTestServices(const string& trace_file) {
43 // Parse the trace file to get the sequence of function calls.
44 int fd = open(trace_file.c_str(), O_RDONLY);
45 if (fd < 0) {
46 LOG(ERROR) << "Can not open trace file: " << trace_file
47 << " error: " << std::strerror(errno);
48 return;
49 }
50
51 google::protobuf::io::FileInputStream input(fd);
52
53 VtsProfilingRecord msg;
54 set<string> registeredHalServices;
55 while (readOneDelimited(&msg, &input)) {
56 string package_name = msg.package();
57 int version_major = msg.version_major();
58 int version_minor = msg.version_minor();
59 // for backward compatibility, some previous testcases don't
60 // specify major and minor versions separately, manually parse it
61 if (version_major == -1 && version_minor == -1) {
62 string version_str = GetVersionString(msg.version());
63 version_major = GetVersionMajor(version_str);
64 version_minor = GetVersionMinor(version_str);
65 }
66 string interface_name = msg.interface();
67 string service_fq_name = GetInterfaceFQName(package_name, version_major,
68 version_minor, interface_name);
69 registeredHalServices.insert(service_fq_name);
70 msg.Clear();
71 }
72 for (const string& service : registeredHalServices) {
73 cout << "hal_service: " << service << endl;
74 }
75 }
76
ReplayTrace(const string & trace_file,map<string,string> & hal_service_instances)77 bool VtsHidlHalReplayer::ReplayTrace(
78 const string& trace_file, map<string, string>& hal_service_instances) {
79 // Parse the trace file to get the sequence of function calls.
80 int fd = open(trace_file.c_str(), O_RDONLY);
81 if (fd < 0) {
82 LOG(ERROR) << "Can not open trace file: " << trace_file
83 << "error: " << std::strerror(errno);
84 return false;
85 }
86
87 google::protobuf::io::FileInputStream input(fd);
88
89 VtsProfilingRecord call_msg;
90 VtsProfilingRecord expected_result_msg;
91 while (readOneDelimited(&call_msg, &input) &&
92 readOneDelimited(&expected_result_msg, &input)) {
93 if (call_msg.event() != InstrumentationEventType::SERVER_API_ENTRY &&
94 call_msg.event() != InstrumentationEventType::CLIENT_API_ENTRY &&
95 call_msg.event() != InstrumentationEventType::SYNC_CALLBACK_ENTRY &&
96 call_msg.event() != InstrumentationEventType::ASYNC_CALLBACK_ENTRY &&
97 call_msg.event() != InstrumentationEventType::PASSTHROUGH_ENTRY) {
98 LOG(WARNING) << "Expected a call message but got message with event: "
99 << call_msg.event();
100 continue;
101 }
102 if (expected_result_msg.event() !=
103 InstrumentationEventType::SERVER_API_EXIT &&
104 expected_result_msg.event() !=
105 InstrumentationEventType::CLIENT_API_EXIT &&
106 expected_result_msg.event() !=
107 InstrumentationEventType::SYNC_CALLBACK_EXIT &&
108 expected_result_msg.event() !=
109 InstrumentationEventType::ASYNC_CALLBACK_EXIT &&
110 expected_result_msg.event() !=
111 InstrumentationEventType::PASSTHROUGH_EXIT) {
112 LOG(WARNING) << "Expected a result message but got message with event: "
113 << call_msg.event();
114 continue;
115 }
116
117 string package_name = call_msg.package();
118 int version_major = call_msg.version_major();
119 int version_minor = call_msg.version_minor();
120 // for backward compatibility, some previous testcases don't
121 // specify major and minor versions separately, manually parse it
122 if (version_major == -1 && version_minor == -1) {
123 string version_str = std::to_string(call_msg.version());
124 version_major = GetVersionMajor(version_str);
125 version_minor = GetVersionMinor(version_str);
126 }
127 string interface_name = call_msg.interface();
128 string instance_name = GetInterfaceFQName(package_name, version_major,
129 version_minor, interface_name);
130 string hal_service_name = "default";
131
132 if (hal_service_instances.find(instance_name) ==
133 hal_service_instances.end()) {
134 LOG(WARNING) << "Does not find service name for " << instance_name
135 << "; this could be a nested interface.";
136 } else {
137 hal_service_name = hal_service_instances[instance_name];
138 }
139
140 cout << "Replay function: " << call_msg.func_msg().name() << endl;
141 LOG(DEBUG) << "Replay function: " << call_msg.func_msg().DebugString();
142
143 int32_t driver_id = driver_manager_->GetDriverIdForHidlHalInterface(
144 package_name, version_major, version_minor, interface_name,
145 hal_service_name);
146 if (driver_id == kInvalidDriverId) {
147 LOG(ERROR) << "Couldn't get a driver base class";
148 return false;
149 }
150
151 vts::FunctionCallMessage func_call_msg;
152 func_call_msg.set_component_class(HAL_HIDL);
153 func_call_msg.set_hal_driver_id(driver_id);
154 *func_call_msg.mutable_api() = call_msg.func_msg();
155 const string& result = driver_manager_->CallFunction(&func_call_msg);
156 if (result == kVoidString || result == kErrorString) {
157 LOG(ERROR) << "Replay function fail. Failed function call: "
158 << func_call_msg.DebugString();
159 return false;
160 }
161 vts::FunctionSpecificationMessage result_msg;
162 if (!google::protobuf::TextFormat::ParseFromString(result, &result_msg)) {
163 LOG(ERROR) << "Failed to parse result msg.";
164 return false;
165 }
166 if (!driver_manager_->VerifyResults(
167 driver_id, expected_result_msg.func_msg(), result_msg)) {
168 // Verification is not strict, i.e. if fail, output error message and
169 // continue the process.
170 LOG(WARNING) << "Verification fail. Expected: "
171 << expected_result_msg.func_msg().DebugString()
172 << " Actual: " << result_msg.DebugString();
173 }
174 call_msg.Clear();
175 expected_result_msg.Clear();
176 }
177 return true;
178 }
179
180 } // namespace vts
181 } // namespace android
182