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 // #define LOG_NDEBUG 0
18 #define LOG_TAG "GCH_AidlProfiler"
19 #include "aidl_profiler.h"
20
21 #include <log/log.h>
22
23 #include <algorithm>
24 #include <cstdint>
25 #include <memory>
26 #include <mutex>
27 #include <utility>
28 #include <vector>
29
30 #include "profiler.h"
31 #include "profiler_util.h"
32 #include "tracked_profiler.h"
33
34 namespace android {
35 namespace google_camera_hal {
36 namespace {
37
38 using ::google::camera_common::Profiler;
39
40 // setprop key for profiling open/close camera
41 constexpr char kPropKeyProfileOpenClose[] =
42 "persist.vendor.camera.profiler.open_close";
43 // setprop key for profiling camera fps
44 constexpr char kPropKeyProfileFps[] = "persist.vendor.camera.profiler.fps";
45 constexpr char kPropKeyProfileReprocess[] =
46 "persist.vendor.camera.profiler.reprocess";
47
48 constexpr char kReprocess[] = "Reprocess Frame ";
49
50 class AidlProfilerImpl : public AidlProfiler {
51 public:
AidlProfilerImpl(uint32_t camera_id,int32_t latency_flag,int32_t fps_flag,int32_t reprocess_latency_flag)52 AidlProfilerImpl(uint32_t camera_id, int32_t latency_flag, int32_t fps_flag,
53 int32_t reprocess_latency_flag)
54 : camera_id_string_("Cam" + std::to_string(camera_id)),
55 camera_id_(camera_id),
56 latency_flag_(latency_flag),
57 fps_flag_(fps_flag),
58 reprocess_latency_flag_(reprocess_latency_flag) {
59 }
60
MakeScopedProfiler(EventType type,std::unique_ptr<google::camera_common::Profiler> custom_latency_profiler,std::unique_ptr<google::camera_common::Profiler> custom_fps_profiler)61 std::unique_ptr<AidlScopedProfiler> MakeScopedProfiler(
62 EventType type,
63 std::unique_ptr<google::camera_common::Profiler> custom_latency_profiler,
64 std::unique_ptr<google::camera_common::Profiler> custom_fps_profiler)
65 override {
66 /*
67 * Makes a ScopedProfiler to help profile the corresponding event type. If
68 * profiling an open, close, or reconfiguration operation, function checks
69 * to see if the event can be used as a continuation of a previous operation
70 */
71 std::lock_guard lock(api_mutex_);
72 if (type == EventType::kConfigureStream && fps_profiler_ == nullptr) {
73 if (SetFpsProfiler(std::move(custom_fps_profiler)) == false) {
74 fps_profiler_ = CreateFpsProfiler();
75 }
76 }
77
78 latency_profilers_.erase(
79 std::remove_if(latency_profilers_.begin(), latency_profilers_.end(),
80 [type](const auto& profiler) {
81 return profiler->ShouldDelete(type);
82 }),
83 latency_profilers_.end());
84
85 for (auto rprofiler = latency_profilers_.rbegin();
86 rprofiler != latency_profilers_.rend(); ++rprofiler) {
87 if (std::unique_ptr<AidlScopedProfiler> ret =
88 (*rprofiler)->AcceptNextState(type);
89 ret != nullptr) {
90 return ret;
91 }
92 }
93
94 if (int size = latency_profilers_.size(); size > 2) {
95 ALOGE("%s: Too many overlapping operations (have: %d). Will not profile.",
96 __FUNCTION__, size);
97 return nullptr;
98 }
99
100 if (type == EventType::kOpen || type == EventType::kFlush) {
101 if (SetOrCreateTrackedProfiler(std::move(custom_latency_profiler),
102 camera_id_string_)) {
103 return latency_profilers_.back()->AcceptNextState(type);
104 } else {
105 return nullptr;
106 }
107 }
108 ALOGE("%s: Could not find an operation for incoming event: %s",
109 __FUNCTION__, EventTypeToString(type).c_str());
110 return nullptr;
111 }
112
FirstFrameStart()113 void FirstFrameStart() override {
114 std::lock_guard lock(api_mutex_);
115 for (auto rprofiler = latency_profilers_.rbegin();
116 rprofiler != latency_profilers_.rend(); ++rprofiler) {
117 if ((*rprofiler)->AcceptFirstFrameStart()) {
118 return;
119 }
120 }
121 ALOGE("%s: Error: no profiler accepted First Frame Start", __FUNCTION__);
122 }
123
FirstFrameEnd()124 void FirstFrameEnd() override {
125 std::lock_guard lock(api_mutex_);
126 for (auto rprofiler = latency_profilers_.rbegin();
127 rprofiler != latency_profilers_.rend(); ++rprofiler) {
128 if ((*rprofiler)->AcceptFirstFrameEnd()) {
129 latency_profilers_.erase(std::next(rprofiler).base());
130 return;
131 }
132 }
133 ALOGE("%s: Error: no profiler accepted First Frame End", __FUNCTION__);
134 }
135
ReprocessingRequestStart(std::unique_ptr<Profiler> custom_reprocessing_profiler,int32_t id)136 void ReprocessingRequestStart(
137 std::unique_ptr<Profiler> custom_reprocessing_profiler,
138 int32_t id) override {
139 std::lock_guard lock(api_mutex_);
140 if (reprocessing_profiler_ == nullptr) {
141 if (!SetReprocessingProfiler(std::move(custom_reprocessing_profiler))) {
142 reprocessing_profiler_ = CreateReprocessingProfiler();
143 }
144 reprocessing_profiler_->SetUseCase(camera_id_string_ + "-Reprocess");
145 open_reprocessing_frames_count_ = 0;
146 }
147 if (reprocessing_profiler_ != nullptr) {
148 reprocessing_profiler_->Start(kReprocess + std::to_string(id),
149 Profiler::kInvalidRequestId);
150 open_reprocessing_frames_count_++;
151 }
152 }
153
ReprocessingResultEnd(int32_t id)154 void ReprocessingResultEnd(int32_t id) override {
155 std::lock_guard lock(api_mutex_);
156 if (reprocessing_profiler_ != nullptr) {
157 reprocessing_profiler_->End(kReprocess + std::to_string(id),
158 Profiler::kInvalidRequestId);
159 if (--open_reprocessing_frames_count_ <= 0) {
160 reprocessing_profiler_ = nullptr;
161 }
162 }
163 }
164
ProfileFrameRate(const std::string & name)165 void ProfileFrameRate(const std::string& name) override {
166 std::lock_guard lock(api_mutex_);
167 if (fps_profiler_ != nullptr) {
168 fps_profiler_->ProfileFrameRate(name);
169 }
170 }
171
172 private:
CreateLatencyProfiler()173 std::shared_ptr<Profiler> CreateLatencyProfiler() {
174 if (latency_flag_ == Profiler::SetPropFlag::kDisable) {
175 return nullptr;
176 }
177 std::shared_ptr<Profiler> profiler = Profiler::Create(latency_flag_);
178 if (profiler == nullptr) {
179 ALOGE("%s: Failed to create profiler", __FUNCTION__);
180 return nullptr;
181 }
182 profiler->SetDumpFilePrefix(
183 "/data/vendor/camera/profiler/aidl_open_close_");
184 profiler->Start(kOverall, Profiler::kInvalidRequestId);
185 return profiler;
186 }
187
SetOrCreateTrackedProfiler(std::unique_ptr<Profiler> profiler,std::string camera_id_string)188 bool SetOrCreateTrackedProfiler(std::unique_ptr<Profiler> profiler,
189 std::string camera_id_string) {
190 if (profiler == nullptr) {
191 std::shared_ptr<Profiler> latency_profiler_ = CreateLatencyProfiler();
192 if (latency_profiler_ == nullptr) {
193 return false;
194 }
195 latency_profilers_.emplace_back(std::make_shared<TrackedProfiler>(
196 latency_profiler_, camera_id_string, EventType::kNone));
197 } else {
198 profiler->SetDumpFilePrefix(
199 "/data/vendor/camera/profiler/aidl_open_close_");
200 profiler->Start(kOverall, Profiler::kInvalidRequestId);
201 latency_profilers_.emplace_back(std::make_shared<TrackedProfiler>(
202 std::move(profiler), camera_id_string, EventType::kNone));
203 }
204 return true;
205 }
206
CreateFpsProfiler()207 std::shared_ptr<Profiler> CreateFpsProfiler() {
208 if (fps_flag_ == Profiler::SetPropFlag::kDisable) {
209 return nullptr;
210 }
211 std::shared_ptr<Profiler> profiler = Profiler::Create(fps_flag_);
212 if (profiler == nullptr) {
213 ALOGE("%s: Failed to create profiler", __FUNCTION__);
214 return nullptr;
215 }
216 profiler->SetDumpFilePrefix("/data/vendor/camera/profiler/aidl_fps_");
217 return profiler;
218 }
219
CreateReprocessingProfiler()220 std::shared_ptr<Profiler> CreateReprocessingProfiler() {
221 if (reprocess_latency_flag_ == Profiler::SetPropFlag::kDisable) {
222 return nullptr;
223 }
224 std::shared_ptr<Profiler> profiler = Profiler::Create(latency_flag_);
225 if (profiler == nullptr) {
226 ALOGE("%s: Failed to create profiler", __FUNCTION__);
227 return nullptr;
228 }
229 profiler->SetDumpFilePrefix("/data/vendor/camera/profiler/aidl_reprocess_");
230 return profiler;
231 }
232
GetCameraId() const233 uint32_t GetCameraId() const {
234 return camera_id_;
235 }
GetLatencyFlag() const236 int32_t GetLatencyFlag() const {
237 return latency_flag_;
238 }
GetFpsFlag() const239 int32_t GetFpsFlag() const {
240 return fps_flag_;
241 }
GetReprocessLatencyFlag() const242 int32_t GetReprocessLatencyFlag() const {
243 return reprocess_latency_flag_;
244 }
245
SetFpsProfiler(std::unique_ptr<Profiler> profiler)246 bool SetFpsProfiler(std::unique_ptr<Profiler> profiler) {
247 if (profiler == nullptr) {
248 return false;
249 }
250 fps_profiler_ = std::move(profiler);
251 if (fps_profiler_ != nullptr) {
252 fps_profiler_->SetDumpFilePrefix(
253 "/data/vendor/camera/profiler/aidl_fps_");
254 return true;
255 }
256 return false;
257 }
258
SetReprocessingProfiler(std::unique_ptr<Profiler> profiler)259 bool SetReprocessingProfiler(std::unique_ptr<Profiler> profiler) {
260 if (profiler == nullptr) {
261 return false;
262 }
263 reprocessing_profiler_ = std::move(profiler);
264 open_reprocessing_frames_count_ = 0;
265 if (reprocessing_profiler_ != nullptr) {
266 reprocessing_profiler_->SetDumpFilePrefix(
267 "data/vendor/camera/profiler/aidl_reprocess_");
268 return true;
269 }
270 return false;
271 }
272
273 // Protect all API functions mutually exclusive, all member variables should
274 // also be protected by this mutex.
275 std::mutex api_mutex_;
276 std::vector<std::shared_ptr<TrackedProfiler>> latency_profilers_;
277 std::shared_ptr<Profiler> fps_profiler_;
278 std::shared_ptr<Profiler> reprocessing_profiler_;
279
280 const std::string camera_id_string_;
281 const uint32_t camera_id_;
282 const int32_t latency_flag_;
283 const int32_t fps_flag_;
284 const int32_t reprocess_latency_flag_;
285
286 int32_t open_reprocessing_frames_count_;
287 };
288
289 class AidlProfilerMock : public AidlProfiler {
MakeScopedProfiler(EventType,std::unique_ptr<google::camera_common::Profiler>,std::unique_ptr<google::camera_common::Profiler>)290 std::unique_ptr<AidlScopedProfiler> MakeScopedProfiler(
291 EventType, std::unique_ptr<google::camera_common::Profiler>,
292 std::unique_ptr<google::camera_common::Profiler>) override {
293 return nullptr;
294 }
295
FirstFrameStart()296 void FirstFrameStart() override{};
FirstFrameEnd()297 void FirstFrameEnd() override{};
ProfileFrameRate(const std::string &)298 void ProfileFrameRate(const std::string&) override{};
ReprocessingRequestStart(std::unique_ptr<Profiler>,int32_t)299 void ReprocessingRequestStart(std::unique_ptr<Profiler>, int32_t) override{};
ReprocessingResultEnd(int32_t)300 void ReprocessingResultEnd(int32_t) override{};
301
GetCameraId() const302 uint32_t GetCameraId() const override {
303 return 0;
304 }
GetLatencyFlag() const305 int32_t GetLatencyFlag() const override {
306 return 0;
307 }
GetFpsFlag() const308 int32_t GetFpsFlag() const override {
309 return 0;
310 }
GetReprocessLatencyFlag() const311 int32_t GetReprocessLatencyFlag() const override {
312 return 0;
313 }
314 };
315
316 } // anonymous namespace
317
Create(uint32_t camera_id)318 std::shared_ptr<AidlProfiler> AidlProfiler::Create(uint32_t camera_id) {
319 int32_t latency_flag = property_get_int32(
320 kPropKeyProfileOpenClose, Profiler::SetPropFlag::kCustomProfiler);
321 int32_t fps_flag = property_get_int32(kPropKeyProfileFps,
322 Profiler::SetPropFlag::kCustomProfiler);
323 int32_t reprocess_latency_flag = property_get_int32(
324 kPropKeyProfileReprocess, Profiler::SetPropFlag::kCustomProfiler);
325
326 if (latency_flag == Profiler::SetPropFlag::kDisable &&
327 fps_flag == Profiler::SetPropFlag::kDisable &&
328 reprocess_latency_flag == Profiler::SetPropFlag::kDisable) {
329 return std::make_shared<AidlProfilerMock>();
330 }
331 // Use stopwatch flag to print result.
332 if ((latency_flag & Profiler::SetPropFlag::kPrintBit) != 0) {
333 latency_flag |= Profiler::SetPropFlag::kStopWatch;
334 }
335 if ((reprocess_latency_flag & Profiler::SetPropFlag::kPrintBit) != 0) {
336 reprocess_latency_flag |= Profiler::SetPropFlag::kStopWatch;
337 }
338 // Use interval flag to print fps instead of print on end.
339 if ((fps_flag & Profiler::SetPropFlag::kPrintBit) != 0) {
340 fps_flag |= Profiler::SetPropFlag::kPrintFpsPerIntervalBit;
341 fps_flag &= ~Profiler::SetPropFlag::kPrintBit;
342 }
343 return std::make_shared<AidlProfilerImpl>(camera_id, latency_flag, fps_flag,
344 reprocess_latency_flag);
345 }
346
AidlScopedProfiler(std::shared_ptr<Profiler> profiler,const std::string name,int id,std::function<void ()> end_callback)347 AidlScopedProfiler::AidlScopedProfiler(std::shared_ptr<Profiler> profiler,
348 const std::string name, int id,
349 std::function<void()> end_callback)
350 : profiler_(profiler),
351 name_(std::move(name)),
352 id_(id),
353 end_callback_(end_callback) {
354 profiler_->Start(name_, id_);
355 profiler_->Start(kHalTotal, Profiler::kInvalidRequestId);
356 }
357
~AidlScopedProfiler()358 AidlScopedProfiler::~AidlScopedProfiler() {
359 profiler_->End(kHalTotal, Profiler::kInvalidRequestId);
360 profiler_->End(name_, id_);
361 if (end_callback_) {
362 end_callback_();
363 }
364 }
365
366 } // namespace google_camera_hal
367 } // namespace android
368