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
20 #include "aidl_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 AidlProfilerImpl : public AidlProfiler {
50 public:
AidlProfilerImpl(uint32_t camera_id,int32_t latency_flag,int32_t fps_flag)51 AidlProfilerImpl(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,std::unique_ptr<google::camera_common::Profiler> custom_latency_profiler,std::unique_ptr<google::camera_common::Profiler> custom_fps_profiler)58 std::unique_ptr<AidlScopedProfiler> MakeScopedProfiler(
59 ScopedType type,
60 std::unique_ptr<google::camera_common::Profiler> custom_latency_profiler,
61 std::unique_ptr<google::camera_common::Profiler> custom_fps_profiler)
62 override {
63 std::lock_guard lock(api_mutex_);
64 if (type == ScopedType::kConfigureStream && fps_profiler_ == nullptr) {
65 if (SetFpsProfiler(std::move(custom_fps_profiler)) == false) {
66 fps_profiler_ = CreateFpsProfiler();
67 }
68 }
69
70 if (latency_profiler_ == nullptr) {
71 if (SetLatencyProfiler(std::move(custom_latency_profiler)) == false) {
72 latency_profiler_ = CreateLatencyProfiler();
73 }
74 if (latency_profiler_ != nullptr) {
75 has_camera_open_ = false;
76 config_count_ = 0;
77 flush_count_ = 0;
78 idle_count_ = 0;
79 } else {
80 return nullptr;
81 }
82 }
83
84 IdleEndLocked();
85
86 const char* name = nullptr;
87 int32_t id = 0;
88 switch (type) {
89 case ScopedType::kOpen:
90 name = "Open";
91 has_camera_open_ = true;
92 latency_profiler_->SetUseCase(camera_id_string_ + "-Open");
93 break;
94 case ScopedType::kConfigureStream:
95 name = "ConfigureStream";
96 if (!has_camera_open_) {
97 latency_profiler_->SetUseCase(camera_id_string_ + "-Reconfiguration");
98 }
99 id = config_count_++;
100 break;
101 case ScopedType::kFlush:
102 name = "Flush";
103 latency_profiler_->SetUseCase(camera_id_string_ + "-Flush");
104 id = flush_count_++;
105 break;
106 case ScopedType::kClose:
107 name = "Close";
108 latency_profiler_->SetUseCase(camera_id_string_ + "-Close");
109 break;
110 default:
111 ALOGE("%s: Unknown type %d", __FUNCTION__, type);
112 return nullptr;
113 }
114 return std::make_unique<AidlScopedProfiler>(
115 latency_profiler_, name, id, [this, type]() {
116 std::lock_guard lock(api_mutex_);
117 if (type == ScopedType::kClose) {
118 DeleteProfilerLocked();
119 } else {
120 IdleStartLocked();
121 }
122 });
123 }
124
FirstFrameStart()125 void FirstFrameStart() override {
126 std::lock_guard lock(api_mutex_);
127 IdleEndLocked();
128 if (latency_profiler_ != nullptr) {
129 latency_profiler_->Start(kFirstFrame, Profiler::kInvalidRequestId);
130 latency_profiler_->Start(kHalTotal, Profiler::kInvalidRequestId);
131 }
132 }
133
FirstFrameEnd()134 void FirstFrameEnd() override {
135 std::lock_guard lock(api_mutex_);
136 if (latency_profiler_ != nullptr) {
137 latency_profiler_->End(kFirstFrame, Profiler::kInvalidRequestId);
138 latency_profiler_->End(kHalTotal, Profiler::kInvalidRequestId);
139 DeleteProfilerLocked();
140 }
141 }
142
ProfileFrameRate(const std::string & name)143 void ProfileFrameRate(const std::string& name) override {
144 std::lock_guard lock(api_mutex_);
145 if (fps_profiler_ != nullptr) {
146 fps_profiler_->ProfileFrameRate(name);
147 }
148 }
149
150 private:
CreateLatencyProfiler()151 std::shared_ptr<Profiler> CreateLatencyProfiler() {
152 if (latency_flag_ == Profiler::SetPropFlag::kDisable) {
153 return nullptr;
154 }
155 std::shared_ptr<Profiler> profiler = Profiler::Create(latency_flag_);
156 if (profiler == nullptr) {
157 ALOGE("%s: Failed to create profiler", __FUNCTION__);
158 return nullptr;
159 }
160 profiler->SetDumpFilePrefix(
161 "/data/vendor/camera/profiler/aidl_open_close_");
162 profiler->Start(kOverall, Profiler::kInvalidRequestId);
163 return profiler;
164 }
165
CreateFpsProfiler()166 std::shared_ptr<Profiler> CreateFpsProfiler() {
167 if (fps_flag_ == Profiler::SetPropFlag::kDisable) {
168 return nullptr;
169 }
170 std::shared_ptr<Profiler> profiler = Profiler::Create(fps_flag_);
171 if (profiler == nullptr) {
172 ALOGE("%s: Failed to create profiler", __FUNCTION__);
173 return nullptr;
174 }
175 profiler->SetDumpFilePrefix("/data/vendor/camera/profiler/aidl_fps_");
176 return profiler;
177 }
178
DeleteProfilerLocked()179 void DeleteProfilerLocked() {
180 if (latency_profiler_ != nullptr) {
181 latency_profiler_->End(kOverall, Profiler::kInvalidRequestId);
182 latency_profiler_ = nullptr;
183 }
184 }
185
IdleStartLocked()186 void IdleStartLocked() {
187 if (latency_profiler_ != nullptr) {
188 latency_profiler_->Start(kIdleString, idle_count_++);
189 }
190 }
191
IdleEndLocked()192 void IdleEndLocked() {
193 if (latency_profiler_ != nullptr && idle_count_ > 0) {
194 latency_profiler_->End(kIdleString, idle_count_ - 1);
195 }
196 }
197
GetCameraId() const198 uint32_t GetCameraId() const {
199 return camera_id_;
200 }
GetLatencyFlag() const201 int32_t GetLatencyFlag() const {
202 return latency_flag_;
203 }
GetFpsFlag() const204 int32_t GetFpsFlag() const {
205 return fps_flag_;
206 }
207
SetLatencyProfiler(std::unique_ptr<Profiler> profiler)208 bool SetLatencyProfiler(std::unique_ptr<Profiler> profiler) {
209 if (profiler == nullptr) {
210 return false;
211 }
212 latency_profiler_ = std::move(profiler);
213 if (latency_profiler_ != nullptr) {
214 latency_profiler_->SetDumpFilePrefix(
215 "/data/vendor/camera/profiler/aidl_open_close_");
216 latency_profiler_->Start(kOverall, Profiler::kInvalidRequestId);
217 return true;
218 }
219 return false;
220 }
221
SetFpsProfiler(std::unique_ptr<Profiler> profiler)222 bool SetFpsProfiler(std::unique_ptr<Profiler> profiler) {
223 if (profiler == nullptr) {
224 return false;
225 }
226 fps_profiler_ = std::move(profiler);
227 if (fps_profiler_ != nullptr) {
228 fps_profiler_->SetDumpFilePrefix(
229 "/data/vendor/camera/profiler/aidl_fps_");
230 return true;
231 }
232 return false;
233 }
234
235 const std::string camera_id_string_;
236 const uint32_t camera_id_;
237 const int32_t latency_flag_;
238 const int32_t fps_flag_;
239
240 // Protect all API functions mutually exclusive, all member variables should
241 // also be protected by this mutex.
242 std::mutex api_mutex_;
243 std::shared_ptr<Profiler> latency_profiler_;
244 std::shared_ptr<Profiler> fps_profiler_;
245 bool has_camera_open_;
246 uint8_t config_count_;
247 uint8_t flush_count_;
248 uint8_t idle_count_;
249 };
250
251 class AidlProfilerMock : public AidlProfiler {
MakeScopedProfiler(ScopedType,std::unique_ptr<google::camera_common::Profiler>,std::unique_ptr<google::camera_common::Profiler>)252 std::unique_ptr<AidlScopedProfiler> MakeScopedProfiler(
253 ScopedType, std::unique_ptr<google::camera_common::Profiler>,
254 std::unique_ptr<google::camera_common::Profiler>) override {
255 return nullptr;
256 }
257
FirstFrameStart()258 void FirstFrameStart() override{};
FirstFrameEnd()259 void FirstFrameEnd() override{};
ProfileFrameRate(const std::string &)260 void ProfileFrameRate(const std::string&) override{};
261
GetCameraId() const262 uint32_t GetCameraId() const override {
263 return 0;
264 }
GetLatencyFlag() const265 int32_t GetLatencyFlag() const override {
266 return 0;
267 }
GetFpsFlag() const268 int32_t GetFpsFlag() const override {
269 return 0;
270 }
271 };
272
273 } // anonymous namespace
274
Create(uint32_t camera_id)275 std::shared_ptr<AidlProfiler> AidlProfiler::Create(uint32_t camera_id) {
276 int32_t latency_flag = property_get_int32(
277 kPropKeyProfileOpenClose, Profiler::SetPropFlag::kCustomProfiler);
278 int32_t fps_flag = property_get_int32(kPropKeyProfileFps,
279 Profiler::SetPropFlag::kCustomProfiler);
280 if (latency_flag == Profiler::SetPropFlag::kDisable &&
281 fps_flag == Profiler::SetPropFlag::kDisable) {
282 return std::make_shared<AidlProfilerMock>();
283 }
284 // Use stopwatch flag to print result.
285 if ((latency_flag & Profiler::SetPropFlag::kPrintBit) != 0) {
286 latency_flag |= Profiler::SetPropFlag::kStopWatch;
287 }
288 // Use interval flag to print fps instead of print on end.
289 if ((fps_flag & Profiler::SetPropFlag::kPrintBit) != 0) {
290 fps_flag |= Profiler::SetPropFlag::kPrintFpsPerIntervalBit;
291 fps_flag &= ~Profiler::SetPropFlag::kPrintBit;
292 }
293 return std::make_shared<AidlProfilerImpl>(camera_id, latency_flag, fps_flag);
294 }
295
AidlScopedProfiler(std::shared_ptr<Profiler> profiler,const std::string name,int id,std::function<void ()> end_callback)296 AidlScopedProfiler::AidlScopedProfiler(std::shared_ptr<Profiler> profiler,
297 const std::string name, int id,
298 std::function<void()> end_callback)
299 : profiler_(profiler),
300 name_(std::move(name)),
301 id_(id),
302 end_callback_(end_callback) {
303 profiler_->Start(name_, id_);
304 profiler_->Start(kHalTotal, Profiler::kInvalidRequestId);
305 }
306
~AidlScopedProfiler()307 AidlScopedProfiler::~AidlScopedProfiler() {
308 profiler_->End(kHalTotal, Profiler::kInvalidRequestId);
309 profiler_->End(name_, id_);
310 if (end_callback_) {
311 end_callback_();
312 }
313 }
314
315 } // namespace implementation
316 } // namespace camera
317 } // namespace hardware
318 } // namespace android
319