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