1 /* 2 * Copyright (C) 2022 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 17 #pragma once 18 19 #include <array> 20 #include <ostream> 21 22 #include "IFilesystem.h" 23 #include "ITimeSource.h" 24 #include "Model.h" 25 #include "RealFilesystem.h" 26 #include "TimeSource.h" 27 28 namespace aidl { 29 namespace google { 30 namespace hardware { 31 namespace power { 32 namespace impl { 33 namespace pixel { 34 35 // Kernel <-> Userspace ABI for CPU features. See kernel/sched/acpu.c. 36 // Contains CPU statistics for a single CPU. The kernel reports an `acpu_stats` struct for each CPU 37 // on the system. 38 struct acpu_stats { 39 // Sum of the CPU frequencies that the CPU used, multiplied by how much time was spent in each 40 // frequency. Measured in ns*KHz. E.g.: 41 // 10ns at 100MHz, 2ns at 50MHz = 10*100,000 + 2*50,000 = 1,100,000 42 // This is used to calculate the average frequency the CPU was running at between two times: 43 // (new.weighted_sum_freq - old.weighted_sum_freq) / elapsed_time_ns 44 uint64_t weighted_sum_freq; 45 // The total time (in nanoseconds) that the CPU was idle. 46 // This is ued to calculate the percent of time the CPU was idle between two times: 47 // (new.total_idle_time_ns - old.total_idle_time_ns) / elapsed_time_ns 48 uint64_t total_idle_time_ns; 49 }; 50 51 class KernelCpuFeatureReader { 52 public: KernelCpuFeatureReader()53 KernelCpuFeatureReader() 54 : mFilesystem(std::make_unique<RealFilesystem>()), 55 mTimeSource(std::make_unique<TimeSource>()) {} KernelCpuFeatureReader(std::unique_ptr<IFilesystem> filesystem,std::unique_ptr<ITimeSource> timeSource)56 KernelCpuFeatureReader(std::unique_ptr<IFilesystem> filesystem, 57 std::unique_ptr<ITimeSource> timeSource) 58 : mFilesystem(std::move(filesystem)), mTimeSource(std::move(timeSource)) {} 59 60 bool Init(); 61 bool GetRecentCpuFeatures(std::array<double, NUM_CPU_POLICIES> *cpuPolicyAverageFrequencyHz, 62 std::array<double, NUM_CPU_CORES> *cpuCoreIdleTimesPercentage); 63 void DumpToStream(std::ostream &stream) const; 64 65 private: 66 const std::unique_ptr<IFilesystem> mFilesystem; 67 const std::unique_ptr<ITimeSource> mTimeSource; 68 // We only open the stats file once and reuse the file descriptor. We find this reduces 69 // ReadStats runtime by 2x. 70 std::unique_ptr<std::istream> mStatsFile; 71 std::array<acpu_stats, NUM_CPU_CORES> mPreviousStats; 72 std::chrono::nanoseconds mPreviousReadTime; 73 bool OpenStatsFile(std::unique_ptr<std::istream> *file); 74 bool ReadStats(std::array<acpu_stats, NUM_CPU_CORES> *stats, 75 std::chrono::nanoseconds *readTime); 76 }; 77 78 } // namespace pixel 79 } // namespace impl 80 } // namespace power 81 } // namespace hardware 82 } // namespace google 83 } // namespace aidl 84