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_TrackedProfiler"
19 #include "tracked_profiler.h"
20
21 #include <log/log.h>
22
23 #include <cstdint>
24 #include <memory>
25 #include <mutex>
26
27 #include "aidl_profiler.h"
28 #include "profiler.h"
29 #include "profiler_util.h"
30
31 namespace android {
32 namespace google_camera_hal {
33
34 using ::google::camera_common::Profiler;
35
SetUseCase(std::string name)36 void TrackedProfiler::SetUseCase(std::string name) {
37 profiler_->SetUseCase(name);
38 }
39
ShouldDelete(EventType incoming)40 bool TrackedProfiler::ShouldDelete(EventType incoming) {
41 if (incoming == EventType::kOpen &&
42 (state_ == EventType::kConfigureStream || state_ == EventType::kOpen)) {
43 return true;
44 }
45 if (state_ == EventType::kFirstFrameEnd || state_ == EventType::kClose) {
46 return true;
47 }
48 return false;
49 }
50
UpdateStateLocked(EventType incoming)51 void TrackedProfiler::UpdateStateLocked(EventType incoming) {
52 state_ = incoming;
53 }
54
AcceptNextState(EventType incoming)55 std::unique_ptr<AidlScopedProfiler> TrackedProfiler::AcceptNextState(
56 EventType incoming) {
57 std::lock_guard<std::mutex> lock(tracked_api_mutex_);
58 int32_t id = 0;
59 switch (state_) {
60 case (EventType::kNone):
61 if (incoming == EventType::kOpen) {
62 SetUseCase(camera_id_string_ + "-Open");
63 break;
64 } else if (incoming == EventType::kFlush) {
65 break;
66 }
67 return nullptr;
68 case (EventType::kOpen):
69 if (incoming == EventType::kConfigureStream) {
70 break;
71 }
72 return nullptr;
73 case (EventType::kConfigureStream):
74 if (incoming == EventType::kConfigureStream ||
75 incoming == EventType::kFirstFrameStart) {
76 break;
77 }
78 return nullptr;
79 case (EventType::kFirstFrameStart):
80 if (incoming == EventType::kFirstFrameEnd) {
81 break;
82 }
83 return nullptr;
84 case (EventType::kFlush):
85 if (incoming == EventType::kFlush || incoming == EventType::kClose) {
86 SetUseCase(camera_id_string_ + "-Close");
87 break;
88 }
89 if (incoming == EventType::kConfigureStream) {
90 SetUseCase(camera_id_string_ + "-Reconfiguration");
91 break;
92 }
93 return nullptr;
94 case (EventType::kClose):
95 return nullptr;
96 case (EventType::kFirstFrameEnd):
97 ALOGE("%s: Warning: Operation %s should have already been deleted.",
98 __FUNCTION__, EventTypeToString(state_).c_str());
99 return nullptr;
100 }
101 UpdateStateLocked(incoming);
102 IdleEndLocked();
103 if (incoming == EventType::kConfigureStream) {
104 id = config_count_++;
105 } else if (incoming == EventType::kFlush) {
106 id = flush_count_++;
107 }
108
109 return std::make_unique<AidlScopedProfiler>(
110 profiler_, EventTypeToString(incoming), id, [this, incoming]() {
111 if (incoming == EventType::kClose) {
112 DeleteProfiler();
113 } else {
114 IdleStart();
115 }
116 });
117 }
118
AcceptFirstFrameStart()119 bool TrackedProfiler::AcceptFirstFrameStart() {
120 std::lock_guard<std::mutex> lock(tracked_api_mutex_);
121 if (state_ == EventType::kConfigureStream) {
122 UpdateStateLocked(EventType::kFirstFrameStart);
123 IdleEndLocked();
124 profiler_->Start(kFirstFrame, Profiler::kInvalidRequestId);
125 profiler_->Start(kHalTotal, Profiler::kInvalidRequestId);
126 return true;
127 }
128 return false;
129 }
130
AcceptFirstFrameEnd()131 bool TrackedProfiler::AcceptFirstFrameEnd() {
132 std::lock_guard<std::mutex> lock(tracked_api_mutex_);
133 if (state_ == EventType::kFirstFrameStart) {
134 UpdateStateLocked(EventType::kFirstFrameEnd);
135 profiler_->End(kFirstFrame, Profiler::kInvalidRequestId);
136 profiler_->End(kHalTotal, Profiler::kInvalidRequestId);
137 DeleteProfilerLocked();
138 return true;
139 }
140 return false;
141 }
142
DeleteProfilerLocked()143 void TrackedProfiler::DeleteProfilerLocked() {
144 if (profiler_ != nullptr) {
145 profiler_->End(kOverall, Profiler::kInvalidRequestId);
146 profiler_ = nullptr; // Deletes the camera_latency_profiler, causing it
147 // to write the data to the Camer latency analyzer
148 }
149 }
150
DeleteProfiler()151 void TrackedProfiler::DeleteProfiler() {
152 std::lock_guard<std::mutex> lock(tracked_api_mutex_);
153 DeleteProfilerLocked();
154 }
155
IdleStartLocked()156 void TrackedProfiler::IdleStartLocked() {
157 if (idle_start_count_ > idle_end_count_) {
158 ALOGE("%s: Error: Starting another idle before previous finished.",
159 __FUNCTION__);
160 } else if (idle_start_count_ < idle_end_count_) {
161 ALOGE("%s: Error: More idles have finished than have started.",
162 __FUNCTION__);
163 }
164 if (profiler_ != nullptr) {
165 profiler_->Start(kIdleString, idle_start_count_++);
166 }
167 }
168
IdleStart()169 void TrackedProfiler::IdleStart() {
170 std::lock_guard<std::mutex> lock(tracked_api_mutex_);
171 IdleStartLocked();
172 }
173
IdleEndLocked()174 void TrackedProfiler::IdleEndLocked() {
175 if (profiler_ != nullptr && idle_start_count_ - 1 == idle_end_count_) {
176 profiler_->End(kIdleString, idle_end_count_++);
177 }
178 }
179
180 } // namespace google_camera_hal
181 } // namespace android