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