1 /* 2 * Copyright 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 "VtsProfilingInterface.h" 17 18 #include <cutils/properties.h> 19 #include <fstream> 20 #include <string> 21 22 #include <android-base/logging.h> 23 #include <google/protobuf/text_format.h> 24 25 #include "test/vts/proto/VtsDriverControlMessage.pb.h" 26 #include "test/vts/proto/VtsProfilingMessage.pb.h" 27 28 using namespace std; 29 30 namespace android { 31 namespace vts { 32 33 const int VtsProfilingInterface::kProfilingPointEntry = 1; 34 const int VtsProfilingInterface::kProfilingPointCallback = 2; 35 const int VtsProfilingInterface::kProfilingPointExit = 3; 36 37 VtsProfilingInterface::VtsProfilingInterface(const string& trace_file_path) 38 : trace_file_path_(trace_file_path), 39 trace_output_(nullptr), 40 initialized_(false) { 41 } 42 43 VtsProfilingInterface::~VtsProfilingInterface() { 44 if (trace_output_) { 45 trace_output_.close(); 46 } 47 } 48 49 static int64_t NanoTime() { 50 std::chrono::nanoseconds duration( 51 std::chrono::steady_clock::now().time_since_epoch()); 52 return static_cast<int64_t>(duration.count()); 53 } 54 55 VtsProfilingInterface& VtsProfilingInterface::getInstance( 56 const string& trace_file_path) { 57 static VtsProfilingInterface instance(trace_file_path); 58 return instance; 59 } 60 61 void VtsProfilingInterface::Init() { 62 if (initialized_) return; 63 64 // Attach device info and timestamp for the trace file. 65 char build_number[PROPERTY_VALUE_MAX]; 66 char device_id[PROPERTY_VALUE_MAX]; 67 char product_name[PROPERTY_VALUE_MAX]; 68 property_get("ro.build.version.incremental", build_number, "unknown_build"); 69 property_get("ro.serialno", device_id, "unknown_device"); 70 property_get("ro.build.product", product_name, "unknown_product"); 71 72 string file_path = trace_file_path_ + "_" + string(product_name) + "_" 73 + string(device_id) + "_" + string(build_number) + "_" 74 + to_string(NanoTime()) + ".vts.trace"; 75 76 LOG(INFO) << "Creating new profiler instance with file path: " << file_path; 77 trace_output_ = std::ofstream(file_path, std::fstream::out); 78 if (!trace_output_) { 79 LOG(ERROR) << "Can not open trace file: " << file_path << ": " 80 << std::strerror(errno); 81 initialized_ = false; 82 return; 83 } 84 initialized_ = true; 85 } 86 87 bool VtsProfilingInterface::AddTraceEvent( 88 android::hardware::details::HidlInstrumentor::InstrumentationEvent event, 89 const char* package, const char* version, const char* interface, 90 const FunctionSpecificationMessage& message) { 91 if (!initialized_) { 92 LOG(ERROR) << "Profiler not initialized. "; 93 return false; 94 } 95 if (stop_trace_recording_) 96 return true; 97 98 // Build the VTSProfilingRecord and print it to string. 99 VtsProfilingRecord record; 100 record.set_timestamp(NanoTime()); 101 record.set_event((InstrumentationEventType)static_cast<int>(event)); 102 record.set_package(package); 103 record.set_version(stof(version)); 104 record.set_interface(interface); 105 *record.mutable_func_msg() = message; 106 string record_str; 107 if (!google::protobuf::TextFormat::PrintToString(record, &record_str)) { 108 LOG(ERROR) << "Can't print the message"; 109 return false; 110 } 111 112 // Write the record string to trace file. 113 mutex_.lock(); 114 if ((static_cast<std::string::size_type>(trace_output_.tellp()) 115 + record_str.size()) > kTraceFileSizeLimit 116 && (static_cast<std::string::size_type>(trace_output_.tellp()) 117 + record_str.size()) >= record_str.size()) { 118 LOG(WARNING) << "Trace file too big, stop recording the trace"; 119 trace_output_.close(); 120 stop_trace_recording_ = true; 121 } 122 if (!stop_trace_recording_) { 123 trace_output_ << record_str << "\n"; 124 trace_output_.flush(); 125 } 126 mutex_.unlock(); 127 128 return true; 129 } 130 131 } // namespace vts 132 } // namespace android 133