1 /*
2 * Copyright (C) 2019 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "GCH_HidlProfiler"
19
20 #include "hidl_profiler.h"
21
22 #include <log/log.h>
23
24 #include <memory>
25 #include <mutex>
26 #include <utility>
27
28 #include "profiler.h"
29
30 namespace android {
31 namespace hardware {
32 namespace camera {
33 namespace implementation {
34 namespace {
35
36 using ::google::camera_common::Profiler;
37
38 // setprop key for profiling open/close camera
39 constexpr char kPropKeyProfileOpenClose[] =
40 "persist.vendor.camera.profiler.open_close";
41 // setprop key for profiling camera fps
42 constexpr char kPropKeyProfileFps[] = "persist.vendor.camera.profiler.fps";
43
44 constexpr char kFirstFrame[] = "First frame";
45 constexpr char kHalTotal[] = "HAL Total";
46 constexpr char kIdleString[] = "<-- IDLE -->";
47 constexpr char kOverall[] = "Overall";
48
49 class HidlProfilerImpl : public HidlProfiler {
50 public:
HidlProfilerImpl(uint32_t camera_id,int32_t latency_flag,int32_t fps_flag)51 HidlProfilerImpl(uint32_t camera_id, int32_t latency_flag, int32_t fps_flag)
52 : camera_id_string_("Cam" + std::to_string(camera_id)),
53 camera_id_(camera_id),
54 latency_flag_(latency_flag),
55 fps_flag_(fps_flag) {
56 }
57
MakeScopedProfiler(ScopedType type)58 std::unique_ptr<HidlScopedProfiler> MakeScopedProfiler(
59 ScopedType type) override {
60 std::lock_guard lock(api_mutex_);
61
62 if (type == ScopedType::kConfigureStream && fps_profiler_ == nullptr) {
63 fps_profiler_ = CreateFpsProfiler();
64 }
65
66 if (latency_profiler_ == nullptr) {
67 latency_profiler_ = CreateLatencyProfiler();
68 if (latency_profiler_ != nullptr) {
69 has_camera_open_ = false;
70 config_count_ = 0;
71 flush_count_ = 0;
72 idle_count_ = 0;
73 } else {
74 return nullptr;
75 }
76 }
77
78 IdleEndLocked();
79
80 const char* name = nullptr;
81 int32_t id = 0;
82 switch (type) {
83 case ScopedType::kOpen:
84 name = "Open";
85 has_camera_open_ = true;
86 latency_profiler_->SetUseCase(camera_id_string_ + "-Open");
87 break;
88 case ScopedType::kConfigureStream:
89 name = "ConfigureStream";
90 if (!has_camera_open_) {
91 latency_profiler_->SetUseCase(camera_id_string_ + "-Reconfiguration");
92 }
93 id = config_count_++;
94 break;
95 case ScopedType::kFlush:
96 name = "Flush";
97 latency_profiler_->SetUseCase(camera_id_string_ + "-Flush");
98 id = flush_count_++;
99 break;
100 case ScopedType::kClose:
101 name = "Close";
102 latency_profiler_->SetUseCase(camera_id_string_ + "-Close");
103 break;
104 default:
105 ALOGE("%s: Unknown type %d", __FUNCTION__, type);
106 return nullptr;
107 }
108 return std::make_unique<HidlScopedProfiler>(
109 latency_profiler_, name, id, [this, type]() {
110 std::lock_guard lock(api_mutex_);
111 if (type == ScopedType::kClose) {
112 DeleteProfilerLocked();
113 } else {
114 IdleStartLocked();
115 }
116 });
117 }
118
FirstFrameStart()119 void FirstFrameStart() override {
120 std::lock_guard lock(api_mutex_);
121 IdleEndLocked();
122 if (latency_profiler_ != nullptr) {
123 latency_profiler_->Start(kFirstFrame, Profiler::kInvalidRequestId);
124 latency_profiler_->Start(kHalTotal, Profiler::kInvalidRequestId);
125 }
126 }
127
FirstFrameEnd()128 void FirstFrameEnd() override {
129 std::lock_guard lock(api_mutex_);
130 if (latency_profiler_ != nullptr) {
131 latency_profiler_->End(kFirstFrame, Profiler::kInvalidRequestId);
132 latency_profiler_->End(kHalTotal, Profiler::kInvalidRequestId);
133 DeleteProfilerLocked();
134 }
135 }
136
ProfileFrameRate(const std::string & name)137 void ProfileFrameRate(const std::string& name) override {
138 std::lock_guard lock(api_mutex_);
139 if (fps_profiler_ != nullptr) {
140 fps_profiler_->ProfileFrameRate(name);
141 }
142 }
143
SetLatencyProfiler(std::unique_ptr<Profiler> profiler)144 void SetLatencyProfiler(std::unique_ptr<Profiler> profiler) override {
145 if (profiler == nullptr || latency_profiler_ == nullptr) {
146 return;
147 }
148 latency_profiler_ = std::move(profiler);
149 if (latency_profiler_ != nullptr) {
150 latency_profiler_->SetDumpFilePrefix(
151 "/data/vendor/camera/profiler/hidl_open_close_");
152 latency_profiler_->Start(kOverall, Profiler::kInvalidRequestId);
153 has_camera_open_ = false;
154 config_count_ = 0;
155 flush_count_ = 0;
156 idle_count_ = 0;
157 }
158 }
159
SetFpsProfiler(std::unique_ptr<Profiler> profiler)160 void SetFpsProfiler(std::unique_ptr<Profiler> profiler) override {
161 if (profiler == nullptr || fps_profiler_ == nullptr) {
162 return;
163 }
164 fps_profiler_ = std::move(profiler);
165 if (fps_profiler_ != nullptr) {
166 fps_profiler_->SetDumpFilePrefix(
167 "/data/vendor/camera/profiler/hidl_fps_");
168 }
169 }
170
171 private:
CreateLatencyProfiler()172 std::shared_ptr<Profiler> CreateLatencyProfiler() {
173 if (latency_flag_ == Profiler::SetPropFlag::kDisable) {
174 return nullptr;
175 }
176 std::shared_ptr<Profiler> profiler = Profiler::Create(latency_flag_);
177 if (profiler == nullptr) {
178 ALOGE("%s: Failed to create profiler", __FUNCTION__);
179 return nullptr;
180 }
181 profiler->SetDumpFilePrefix(
182 "/data/vendor/camera/profiler/hidl_open_close_");
183 profiler->Start(kOverall, Profiler::kInvalidRequestId);
184 return profiler;
185 }
186
CreateFpsProfiler()187 std::shared_ptr<Profiler> CreateFpsProfiler() {
188 if (fps_flag_ == Profiler::SetPropFlag::kDisable) {
189 return nullptr;
190 }
191 std::shared_ptr<Profiler> profiler = Profiler::Create(fps_flag_);
192 if (profiler == nullptr) {
193 ALOGE("%s: Failed to create profiler", __FUNCTION__);
194 return nullptr;
195 }
196 profiler->SetDumpFilePrefix("/data/vendor/camera/profiler/hidl_fps_");
197 return profiler;
198 }
199
DeleteProfilerLocked()200 void DeleteProfilerLocked() {
201 if (latency_profiler_ != nullptr) {
202 latency_profiler_->End(kOverall, Profiler::kInvalidRequestId);
203 latency_profiler_ = nullptr;
204 }
205 }
206
IdleStartLocked()207 void IdleStartLocked() {
208 if (latency_profiler_ != nullptr) {
209 latency_profiler_->Start(kIdleString, idle_count_++);
210 }
211 }
212
IdleEndLocked()213 void IdleEndLocked() {
214 if (latency_profiler_ != nullptr && idle_count_ > 0) {
215 latency_profiler_->End(kIdleString, idle_count_ - 1);
216 }
217 }
218
GetCameraId() const219 uint32_t GetCameraId() const {
220 return camera_id_;
221 }
GetLatencyFlag() const222 int32_t GetLatencyFlag() const {
223 return latency_flag_;
224 }
GetFpsFlag() const225 int32_t GetFpsFlag() const {
226 return fps_flag_;
227 }
228
229 const std::string camera_id_string_;
230 const uint32_t camera_id_;
231 const int32_t latency_flag_;
232 const int32_t fps_flag_;
233
234 // Protect all API functions mutually exclusive, all member variables should
235 // also be protected by this mutex.
236 std::mutex api_mutex_;
237 std::shared_ptr<Profiler> latency_profiler_;
238 std::shared_ptr<Profiler> fps_profiler_;
239 bool has_camera_open_;
240 uint8_t config_count_;
241 uint8_t flush_count_;
242 uint8_t idle_count_;
243 };
244
245 class HidlProfilerMock : public HidlProfiler {
MakeScopedProfiler(ScopedType)246 std::unique_ptr<HidlScopedProfiler> MakeScopedProfiler(ScopedType) override {
247 return nullptr;
248 }
249
FirstFrameStart()250 void FirstFrameStart() override {
251 }
252
FirstFrameEnd()253 void FirstFrameEnd() override {
254 }
255
ProfileFrameRate(const std::string &)256 void ProfileFrameRate(const std::string&) override {
257 }
258
SetLatencyProfiler(std::unique_ptr<google::camera_common::Profiler>)259 void SetLatencyProfiler(
260 std::unique_ptr<google::camera_common::Profiler> /* profiler */) override {
261 }
262
SetFpsProfiler(std::unique_ptr<google::camera_common::Profiler>)263 void SetFpsProfiler(
264 std::unique_ptr<google::camera_common::Profiler> /* profiler */) override {
265 }
266
GetCameraId() const267 uint32_t GetCameraId() const override {
268 return 0;
269 }
GetLatencyFlag() const270 int32_t GetLatencyFlag() const override {
271 return 0;
272 }
GetFpsFlag() const273 int32_t GetFpsFlag() const override {
274 return 0;
275 }
276 };
277
278 } // anonymous namespace
279
Create(uint32_t camera_id)280 std::shared_ptr<HidlProfiler> HidlProfiler::Create(uint32_t camera_id) {
281 int32_t latency_flag = property_get_int32(
282 kPropKeyProfileOpenClose, Profiler::SetPropFlag::kCustomProfiler);
283 int32_t fps_flag = property_get_int32(kPropKeyProfileFps,
284 Profiler::SetPropFlag::kCustomProfiler);
285 if (latency_flag == Profiler::SetPropFlag::kDisable &&
286 fps_flag == Profiler::SetPropFlag::kDisable) {
287 return std::make_shared<HidlProfilerMock>();
288 }
289 // Use stopwatch flag to print result.
290 if ((latency_flag & Profiler::SetPropFlag::kPrintBit) != 0) {
291 latency_flag |= Profiler::SetPropFlag::kStopWatch;
292 }
293 // Use interval flag to print fps instead of print on end.
294 if ((fps_flag & Profiler::SetPropFlag::kPrintBit) != 0) {
295 fps_flag |= Profiler::SetPropFlag::kPrintFpsPerIntervalBit;
296 fps_flag &= ~Profiler::SetPropFlag::kPrintBit;
297 }
298 return std::make_shared<HidlProfilerImpl>(camera_id, latency_flag, fps_flag);
299 }
300
HidlScopedProfiler(std::shared_ptr<Profiler> profiler,const std::string name,int id,std::function<void ()> end_callback)301 HidlScopedProfiler::HidlScopedProfiler(std::shared_ptr<Profiler> profiler,
302 const std::string name, int id,
303 std::function<void()> end_callback)
304 : profiler_(profiler),
305 name_(std::move(name)),
306 id_(id),
307 end_callback_(end_callback) {
308 profiler_->Start(name_, id_);
309 profiler_->Start(kHalTotal, Profiler::kInvalidRequestId);
310 }
311
~HidlScopedProfiler()312 HidlScopedProfiler::~HidlScopedProfiler() {
313 profiler_->End(kHalTotal, Profiler::kInvalidRequestId);
314 profiler_->End(name_, id_);
315 if (end_callback_) {
316 end_callback_();
317 }
318 }
319
320 } // namespace implementation
321 } // namespace camera
322 } // namespace hardware
323 } // namespace android
324