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 <fcntl.h> 20 #include <fstream> 21 #include <string> 22 23 #include <android-base/logging.h> 24 #include <google/protobuf/text_format.h> 25 26 #include "VtsProfilingUtil.h" 27 #include "test/vts/proto/VtsDriverControlMessage.pb.h" 28 #include "test/vts/proto/VtsProfilingMessage.pb.h" 29 30 using namespace std; 31 32 namespace android { 33 namespace vts { 34 35 const int VtsProfilingInterface::kProfilingPointEntry = 1; 36 const int VtsProfilingInterface::kProfilingPointCallback = 2; 37 const int VtsProfilingInterface::kProfilingPointExit = 3; 38 39 VtsProfilingInterface::VtsProfilingInterface(const string& trace_file_path) 40 : trace_file_path_(trace_file_path), 41 trace_output_(nullptr), 42 initialized_(false) {} 43 44 VtsProfilingInterface::~VtsProfilingInterface() { 45 if (trace_output_) { 46 trace_output_->Close(); 47 } 48 } 49 50 static int64_t NanoTime() { 51 std::chrono::nanoseconds duration( 52 std::chrono::steady_clock::now().time_since_epoch()); 53 return static_cast<int64_t>(duration.count()); 54 } 55 56 VtsProfilingInterface& VtsProfilingInterface::getInstance( 57 const string& trace_file_path) { 58 static VtsProfilingInterface instance(trace_file_path); 59 return instance; 60 } 61 62 void VtsProfilingInterface::Init() { 63 if (initialized_) return; 64 65 // Attach device info and timestamp for the trace file. 66 char build_number[PROPERTY_VALUE_MAX]; 67 char device_id[PROPERTY_VALUE_MAX]; 68 char product_name[PROPERTY_VALUE_MAX]; 69 property_get("ro.build.version.incremental", build_number, "unknown_build"); 70 property_get("ro.serialno", device_id, "unknown_device"); 71 property_get("ro.build.product", product_name, "unknown_product"); 72 73 string file_path = trace_file_path_ + "_" + string(product_name) + "_" + 74 string(device_id) + "_" + string(build_number) + "_" + 75 to_string(NanoTime()) + ".vts.trace"; 76 77 LOG(INFO) << "Creating new profiler instance with file path: " << file_path; 78 int fd = open(file_path.c_str(), O_RDWR | O_CREAT | O_EXCL, 79 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 80 if (fd < 0) { 81 LOG(ERROR) << "Can not open trace file: " << file_path 82 << " error: " << std::strerror(errno); 83 return; 84 } 85 trace_output_.reset(new google::protobuf::io::FileOutputStream(fd)); 86 initialized_ = true; 87 } 88 89 bool VtsProfilingInterface::AddTraceEvent( 90 android::hardware::details::HidlInstrumentor::InstrumentationEvent event, 91 const char* package, const char* version, const char* interface, 92 const FunctionSpecificationMessage& message) { 93 if (!initialized_) { 94 LOG(ERROR) << "Profiler not initialized. "; 95 return false; 96 } 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 107 // Write the record string to trace file. 108 mutex_.lock(); 109 if (!writeOneDelimited(record, trace_output_.get())) { 110 LOG(ERROR) << "Failed to write record"; 111 } 112 if (!trace_output_->Flush()) { 113 LOG(ERROR) << "Failed to flush: " << std::strerror(errno); 114 } 115 mutex_.unlock(); 116 117 return true; 118 } 119 120 } // namespace vts 121 } // namespace android 122