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