1 #pragma once 2 /* 3 * Copyright (C) 2016 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #include <deque> 19 #include <mutex> 20 #include <set> 21 22 #include <android-base/thread_annotations.h> 23 24 #include "common/libs/time/monotonic_time.h" 25 26 #include "guest/hals/hwcomposer/common/base_composer.h" 27 #include "guest/hals/hwcomposer/common/hwcomposer.h" 28 29 namespace cuttlefish { 30 31 class CompositionData { 32 public: CompositionData(cuttlefish::time::MonotonicTimePoint time_point,int num_prepares,int num_layers,int num_hwcomposited_layers,cuttlefish::time::Nanoseconds prepare_time,cuttlefish::time::Nanoseconds set_calls_time)33 CompositionData(cuttlefish::time::MonotonicTimePoint time_point, int num_prepares, 34 int num_layers, int num_hwcomposited_layers, 35 cuttlefish::time::Nanoseconds prepare_time, 36 cuttlefish::time::Nanoseconds set_calls_time) 37 : time_point_(time_point), 38 num_prepare_calls_(num_prepares), 39 num_layers_(num_layers), 40 num_hwcomposited_layers_(num_hwcomposited_layers), 41 prepare_time_(prepare_time), 42 set_calls_time_(set_calls_time) {} 43 time_point()44 cuttlefish::time::MonotonicTimePoint time_point() const { return time_point_; } 45 num_prepare_calls()46 int num_prepare_calls() const { return num_prepare_calls_; } 47 num_layers()48 int num_layers() const { return num_layers_; } 49 num_hwcomposited_layers()50 int num_hwcomposited_layers() const { return num_hwcomposited_layers_; } 51 prepare_time()52 cuttlefish::time::Nanoseconds prepare_time() const { return prepare_time_; } 53 set_calls_time()54 cuttlefish::time::Nanoseconds set_calls_time() const { return set_calls_time_; } 55 56 private: 57 cuttlefish::time::MonotonicTimePoint time_point_; 58 int num_prepare_calls_; 59 int num_layers_; 60 int num_hwcomposited_layers_; 61 cuttlefish::time::Nanoseconds prepare_time_; 62 cuttlefish::time::Nanoseconds set_calls_time_; 63 }; 64 65 struct HWCCompositionStats { 66 cuttlefish::time::MonotonicTimePoint prepare_start; 67 cuttlefish::time::MonotonicTimePoint prepare_end; 68 cuttlefish::time::MonotonicTimePoint set_start; 69 cuttlefish::time::MonotonicTimePoint set_end; 70 cuttlefish::time::MonotonicTimePoint last_vsync; 71 // There may be more than one call to prepare, the timestamps are with regards 72 // to the last one (the one that precedes the set call) 73 int num_prepare_calls; 74 int num_layers; 75 // The number of layers composed by the hwcomposer 76 int num_hwc_layers; 77 }; 78 79 class StatsKeeper { 80 public: 81 // The timespan parameter indicates for how long we keep stats about the past 82 // compositions. 83 StatsKeeper(cuttlefish::time::TimeDifference timespan, int64_t vsync_base, 84 int32_t vsync_period); 85 StatsKeeper(); 86 ~StatsKeeper(); 87 88 // Record the time at which a call to prepare was made, takes the number of 89 // layers received (excluding the framebuffer) as a parameter. 90 void RecordPrepareStart(int num_layers); 91 // Record the time at which a call to prepare (was about to) returned, takes 92 // the number of layers marked for hardware composition as a parameter. 93 void RecordPrepareEnd(int num_hwcomposited_layers); 94 void RecordSetStart(); 95 void RecordSetEnd() EXCLUDES(mutex_); 96 97 void GetLastCompositionStats(CompositionStats* stats_p); 98 99 // Calls to this function are synchronized with calls to 'RecordSetEnd' with a 100 // mutex. The other Record* functions do not need such synchronization because 101 // they access last_* variables only, which are not read by 'Dump'. 102 void SynchronizedDump(char* buffer, int buffer_size) const EXCLUDES(mutex_); 103 104 private: 105 cuttlefish::time::TimeDifference period_length_; 106 107 // Base and period of the VSYNC signal, allows to accurately calculate the 108 // time of the last vsync broadcast. 109 int64_t vsync_base_; 110 int32_t vsync_period_; 111 // Data collected about ongoing composition. These variables are not accessed 112 // from Dump(), so they don't need to be guarded by a mutex. 113 HWCCompositionStats last_composition_stats_; 114 115 // Aggregated performance data collected from past compositions. These 116 // variables are modified when a composition is completed and when old 117 // compositions need to be discarded in RecordSetEnd(), and is accessed from 118 // Dump(). Non-aggregated data is kept in the raw_composition_data_ deque to 119 // be able to discard old values from the aggregated data. 120 int num_layers_ GUARDED_BY(mutex_); 121 int num_hwcomposited_layers_ GUARDED_BY(mutex_); 122 int num_prepare_calls_ GUARDED_BY(mutex_); 123 int num_set_calls_ GUARDED_BY(mutex_); 124 cuttlefish::time::Nanoseconds prepare_call_total_time_ GUARDED_BY(mutex_); 125 cuttlefish::time::Nanoseconds set_call_total_time_ GUARDED_BY(mutex_); 126 // These are kept in multisets to be able to calculate mins and maxs of 127 // changing sets of (not necessarily different) values. 128 std::multiset<int> prepare_calls_per_set_calls_ GUARDED_BY(mutex_); 129 std::multiset<int> layers_per_compositions_ GUARDED_BY(mutex_); 130 std::multiset<cuttlefish::time::Nanoseconds> prepare_call_times_ GUARDED_BY(mutex_); 131 std::multiset<cuttlefish::time::Nanoseconds> set_call_times_ GUARDED_BY(mutex_); 132 std::multiset<int64_t> set_call_times_per_hwcomposited_layer_ns_ 133 GUARDED_BY(mutex_); 134 135 // Time-ordered list of compositions, used to update the global aggregated 136 // performance data when old compositions fall out of the period of interest. 137 std::deque<CompositionData> raw_composition_data_ GUARDED_BY(mutex_); 138 139 // TODO(jemoreira): Add min/max/average composition times per layer area units 140 141 std::deque<std::pair<int64_t, int64_t> > composition_areas GUARDED_BY(mutex_); 142 int64_t total_layers_area GUARDED_BY(mutex_); 143 int64_t total_invisible_area GUARDED_BY(mutex_); 144 145 // Controls access to data from past compositions. 146 mutable std::mutex mutex_; 147 }; 148 149 class WrappedScreenView : public ScreenView { 150 public: WrappedScreenView(std::unique_ptr<ScreenView> screen_view,std::function<void (CompositionStats *)> stats_getter)151 WrappedScreenView(std::unique_ptr<ScreenView> screen_view, 152 std::function<void(CompositionStats*)> stats_getter) 153 : screen_view_(std::move(screen_view)), stats_getter_(stats_getter) {} 154 virtual ~WrappedScreenView() = default; 155 Broadcast(int buffer_id,const CompositionStats *)156 void Broadcast(int buffer_id, const CompositionStats*) override { 157 // The composer object in stats_keeper produces null stats, use the ones 158 // provided by the stats_keeper instead. 159 CompositionStats stats; 160 stats_getter_(&stats); 161 return screen_view_->Broadcast(buffer_id, &stats); 162 } 163 GetBuffer(int buffer_id)164 void* GetBuffer(int buffer_id) override { 165 return screen_view_->GetBuffer(buffer_id); 166 } 167 x_res()168 int32_t x_res() const override { return screen_view_->x_res(); } 169 y_res()170 int32_t y_res() const override { return screen_view_->y_res(); } 171 dpi()172 int32_t dpi() const override { return screen_view_->dpi(); } 173 refresh_rate()174 int32_t refresh_rate() const override { return screen_view_->refresh_rate(); } 175 num_buffers()176 int num_buffers() const override { return screen_view_->num_buffers(); } 177 178 private: 179 std::unique_ptr<ScreenView> screen_view_; 180 std::function<void(CompositionStats*)> stats_getter_; 181 }; 182 183 template <class Composer> 184 class StatsKeepingComposer : public BaseComposer { 185 public: 186 // Keep stats from the last 10 seconds. StatsKeepingComposer(int64_t vsync_base_timestamp,std::unique_ptr<ScreenView> screen_view)187 StatsKeepingComposer(int64_t vsync_base_timestamp, 188 std::unique_ptr<ScreenView> screen_view) 189 : composer_(std::unique_ptr<ScreenView>( 190 new WrappedScreenView(std::move(screen_view), 191 [this](CompositionStats* stats) { 192 FinalizeStatsAndGet(stats); 193 }))), 194 stats_keeper_(cuttlefish::time::TimeDifference(cuttlefish::time::Seconds(10), 1), 195 vsync_base_timestamp, 1e9 / composer_.refresh_rate()) {} 196 virtual ~StatsKeepingComposer() = default; 197 PrepareLayers(size_t num_layers,hwc_layer_1_t * layers)198 int PrepareLayers(size_t num_layers, hwc_layer_1_t* layers) override { 199 stats_keeper_.RecordPrepareStart(num_layers); 200 int num_hwc_layers = composer_.PrepareLayers(num_layers, layers); 201 stats_keeper_.RecordPrepareEnd(num_hwc_layers); 202 return num_hwc_layers; 203 } 204 SetLayers(size_t num_layers,hwc_layer_1_t * layers)205 int SetLayers(size_t num_layers, hwc_layer_1_t* layers) override { 206 stats_keeper_.RecordSetStart(); 207 return composer_.SetLayers(num_layers, layers); 208 } 209 Dump(char * buff,int buff_len)210 void Dump(char* buff, int buff_len) override { 211 stats_keeper_.SynchronizedDump(buff, buff_len); 212 } 213 FinalizeStatsAndGet(CompositionStats * stats)214 void FinalizeStatsAndGet(CompositionStats* stats) { 215 stats_keeper_.RecordSetEnd(); 216 stats_keeper_.GetLastCompositionStats(stats); 217 } 218 219 private: 220 Composer composer_; 221 StatsKeeper stats_keeper_; 222 }; 223 224 } // namespace cuttlefish 225