TimeStats.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. /*
  2. * Copyright 2018 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. #undef LOG_TAG
  17. #define LOG_TAG "TimeStats"
  18. #define ATRACE_TAG ATRACE_TAG_GRAPHICS
  19. #include "TimeStats.h"
  20. #include <android-base/stringprintf.h>
  21. #include <log/log.h>
  22. #include <utils/String8.h>
  23. #include <utils/Timers.h>
  24. #include <utils/Trace.h>
  25. #include <algorithm>
  26. #include <regex>
  27. namespace android {
  28. namespace impl {
  29. void TimeStats::parseArgs(bool asProto, const Vector<String16>& args, std::string& result) {
  30. ATRACE_CALL();
  31. std::unordered_map<std::string, int32_t> argsMap;
  32. for (size_t index = 0; index < args.size(); ++index) {
  33. argsMap[std::string(String8(args[index]).c_str())] = index;
  34. }
  35. if (argsMap.count("-disable")) {
  36. disable();
  37. }
  38. if (argsMap.count("-dump")) {
  39. std::optional<uint32_t> maxLayers = std::nullopt;
  40. auto iter = argsMap.find("-maxlayers");
  41. if (iter != argsMap.end() && iter->second + 1 < static_cast<int32_t>(args.size())) {
  42. int64_t value = strtol(String8(args[iter->second + 1]).c_str(), nullptr, 10);
  43. value = std::clamp(value, int64_t(0), int64_t(UINT32_MAX));
  44. maxLayers = static_cast<uint32_t>(value);
  45. }
  46. dump(asProto, maxLayers, result);
  47. }
  48. if (argsMap.count("-clear")) {
  49. clear();
  50. }
  51. if (argsMap.count("-enable")) {
  52. enable();
  53. }
  54. }
  55. std::string TimeStats::miniDump() {
  56. ATRACE_CALL();
  57. std::string result = "TimeStats miniDump:\n";
  58. std::lock_guard<std::mutex> lock(mMutex);
  59. android::base::StringAppendF(&result, "Number of tracked layers is %zu\n",
  60. mTimeStatsTracker.size());
  61. return result;
  62. }
  63. void TimeStats::incrementTotalFrames() {
  64. if (!mEnabled.load()) return;
  65. ATRACE_CALL();
  66. std::lock_guard<std::mutex> lock(mMutex);
  67. mTimeStats.totalFrames++;
  68. }
  69. void TimeStats::incrementMissedFrames() {
  70. if (!mEnabled.load()) return;
  71. ATRACE_CALL();
  72. std::lock_guard<std::mutex> lock(mMutex);
  73. mTimeStats.missedFrames++;
  74. }
  75. void TimeStats::incrementClientCompositionFrames() {
  76. if (!mEnabled.load()) return;
  77. ATRACE_CALL();
  78. std::lock_guard<std::mutex> lock(mMutex);
  79. mTimeStats.clientCompositionFrames++;
  80. }
  81. bool TimeStats::recordReadyLocked(int32_t layerID, TimeRecord* timeRecord) {
  82. if (!timeRecord->ready) {
  83. ALOGV("[%d]-[%" PRIu64 "]-presentFence is still not received", layerID,
  84. timeRecord->frameTime.frameNumber);
  85. return false;
  86. }
  87. if (timeRecord->acquireFence != nullptr) {
  88. if (timeRecord->acquireFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) {
  89. return false;
  90. }
  91. if (timeRecord->acquireFence->getSignalTime() != Fence::SIGNAL_TIME_INVALID) {
  92. timeRecord->frameTime.acquireTime = timeRecord->acquireFence->getSignalTime();
  93. timeRecord->acquireFence = nullptr;
  94. } else {
  95. ALOGV("[%d]-[%" PRIu64 "]-acquireFence signal time is invalid", layerID,
  96. timeRecord->frameTime.frameNumber);
  97. }
  98. }
  99. if (timeRecord->presentFence != nullptr) {
  100. if (timeRecord->presentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) {
  101. return false;
  102. }
  103. if (timeRecord->presentFence->getSignalTime() != Fence::SIGNAL_TIME_INVALID) {
  104. timeRecord->frameTime.presentTime = timeRecord->presentFence->getSignalTime();
  105. timeRecord->presentFence = nullptr;
  106. } else {
  107. ALOGV("[%d]-[%" PRIu64 "]-presentFence signal time invalid", layerID,
  108. timeRecord->frameTime.frameNumber);
  109. }
  110. }
  111. return true;
  112. }
  113. static int32_t msBetween(nsecs_t start, nsecs_t end) {
  114. int64_t delta = (end - start) / 1000000;
  115. delta = std::clamp(delta, int64_t(INT32_MIN), int64_t(INT32_MAX));
  116. return static_cast<int32_t>(delta);
  117. }
  118. // This regular expression captures the following for instance:
  119. // StatusBar in StatusBar#0
  120. // com.appname in com.appname/com.appname.activity#0
  121. // com.appname in SurfaceView - com.appname/com.appname.activity#0
  122. static const std::regex packageNameRegex("(?:SurfaceView[-\\s\\t]+)?([^/]+).*#\\d+");
  123. static std::string getPackageName(const std::string& layerName) {
  124. std::smatch match;
  125. if (std::regex_match(layerName.begin(), layerName.end(), match, packageNameRegex)) {
  126. // There must be a match for group 1 otherwise the whole string is not
  127. // matched and the above will return false
  128. return match[1];
  129. }
  130. return "";
  131. }
  132. void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerID) {
  133. ATRACE_CALL();
  134. LayerRecord& layerRecord = mTimeStatsTracker[layerID];
  135. TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord;
  136. std::deque<TimeRecord>& timeRecords = layerRecord.timeRecords;
  137. while (!timeRecords.empty()) {
  138. if (!recordReadyLocked(layerID, &timeRecords[0])) break;
  139. ALOGV("[%d]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerID,
  140. timeRecords[0].frameTime.frameNumber, timeRecords[0].frameTime.presentTime);
  141. const std::string& layerName = layerRecord.layerName;
  142. if (prevTimeRecord.ready) {
  143. if (!mTimeStats.stats.count(layerName)) {
  144. mTimeStats.stats[layerName].layerName = layerName;
  145. mTimeStats.stats[layerName].packageName = getPackageName(layerName);
  146. }
  147. TimeStatsHelper::TimeStatsLayer& timeStatsLayer = mTimeStats.stats[layerName];
  148. timeStatsLayer.totalFrames++;
  149. timeStatsLayer.droppedFrames += layerRecord.droppedFrames;
  150. layerRecord.droppedFrames = 0;
  151. const int32_t postToAcquireMs = msBetween(timeRecords[0].frameTime.postTime,
  152. timeRecords[0].frameTime.acquireTime);
  153. ALOGV("[%d]-[%" PRIu64 "]-post2acquire[%d]", layerID,
  154. timeRecords[0].frameTime.frameNumber, postToAcquireMs);
  155. timeStatsLayer.deltas["post2acquire"].insert(postToAcquireMs);
  156. const int32_t postToPresentMs = msBetween(timeRecords[0].frameTime.postTime,
  157. timeRecords[0].frameTime.presentTime);
  158. ALOGV("[%d]-[%" PRIu64 "]-post2present[%d]", layerID,
  159. timeRecords[0].frameTime.frameNumber, postToPresentMs);
  160. timeStatsLayer.deltas["post2present"].insert(postToPresentMs);
  161. const int32_t acquireToPresentMs = msBetween(timeRecords[0].frameTime.acquireTime,
  162. timeRecords[0].frameTime.presentTime);
  163. ALOGV("[%d]-[%" PRIu64 "]-acquire2present[%d]", layerID,
  164. timeRecords[0].frameTime.frameNumber, acquireToPresentMs);
  165. timeStatsLayer.deltas["acquire2present"].insert(acquireToPresentMs);
  166. const int32_t latchToPresentMs = msBetween(timeRecords[0].frameTime.latchTime,
  167. timeRecords[0].frameTime.presentTime);
  168. ALOGV("[%d]-[%" PRIu64 "]-latch2present[%d]", layerID,
  169. timeRecords[0].frameTime.frameNumber, latchToPresentMs);
  170. timeStatsLayer.deltas["latch2present"].insert(latchToPresentMs);
  171. const int32_t desiredToPresentMs = msBetween(timeRecords[0].frameTime.desiredTime,
  172. timeRecords[0].frameTime.presentTime);
  173. ALOGV("[%d]-[%" PRIu64 "]-desired2present[%d]", layerID,
  174. timeRecords[0].frameTime.frameNumber, desiredToPresentMs);
  175. timeStatsLayer.deltas["desired2present"].insert(desiredToPresentMs);
  176. const int32_t presentToPresentMs = msBetween(prevTimeRecord.frameTime.presentTime,
  177. timeRecords[0].frameTime.presentTime);
  178. ALOGV("[%d]-[%" PRIu64 "]-present2present[%d]", layerID,
  179. timeRecords[0].frameTime.frameNumber, presentToPresentMs);
  180. timeStatsLayer.deltas["present2present"].insert(presentToPresentMs);
  181. }
  182. // Output additional trace points to track frame time.
  183. ATRACE_INT64(("TimeStats-Post - " + layerName).c_str(), timeRecords[0].frameTime.postTime);
  184. ATRACE_INT64(("TimeStats-Acquire - " + layerName).c_str(),
  185. timeRecords[0].frameTime.acquireTime);
  186. ATRACE_INT64(("TimeStats-Latch - " + layerName).c_str(),
  187. timeRecords[0].frameTime.latchTime);
  188. ATRACE_INT64(("TimeStats-Desired - " + layerName).c_str(),
  189. timeRecords[0].frameTime.desiredTime);
  190. ATRACE_INT64(("TimeStats-Present - " + layerName).c_str(),
  191. timeRecords[0].frameTime.presentTime);
  192. prevTimeRecord = timeRecords[0];
  193. timeRecords.pop_front();
  194. layerRecord.waitData--;
  195. }
  196. }
  197. // This regular expression captures the following layer names for instance:
  198. // 1) StatusBat#0
  199. // 2) NavigationBar#1
  200. // 3) co(m).*#0
  201. // 4) SurfaceView - co(m).*#0
  202. // Using [-\\s\t]+ for the conjunction part between SurfaceView and co(m).*
  203. // is a bit more robust in case there's a slight change.
  204. // The layer name would only consist of . / $ _ 0-9 a-z A-Z in most cases.
  205. static const std::regex layerNameRegex(
  206. "(((SurfaceView[-\\s\\t]+)?com?\\.[./$\\w]+)|((Status|Navigation)Bar))#\\d+");
  207. static bool layerNameIsValid(const std::string& layerName) {
  208. return std::regex_match(layerName.begin(), layerName.end(), layerNameRegex);
  209. }
  210. void TimeStats::setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName,
  211. nsecs_t postTime) {
  212. if (!mEnabled.load()) return;
  213. ATRACE_CALL();
  214. ALOGV("[%d]-[%" PRIu64 "]-[%s]-PostTime[%" PRId64 "]", layerID, frameNumber, layerName.c_str(),
  215. postTime);
  216. std::lock_guard<std::mutex> lock(mMutex);
  217. if (!mTimeStatsTracker.count(layerID) && mTimeStatsTracker.size() < MAX_NUM_LAYER_RECORDS &&
  218. layerNameIsValid(layerName)) {
  219. mTimeStatsTracker[layerID].layerName = layerName;
  220. }
  221. if (!mTimeStatsTracker.count(layerID)) return;
  222. LayerRecord& layerRecord = mTimeStatsTracker[layerID];
  223. if (layerRecord.timeRecords.size() == MAX_NUM_TIME_RECORDS) {
  224. ALOGE("[%d]-[%s]-timeRecords is at its maximum size[%zu]. Ignore this when unittesting.",
  225. layerID, layerRecord.layerName.c_str(), MAX_NUM_TIME_RECORDS);
  226. mTimeStatsTracker.erase(layerID);
  227. return;
  228. }
  229. // For most media content, the acquireFence is invalid because the buffer is
  230. // ready at the queueBuffer stage. In this case, acquireTime should be given
  231. // a default value as postTime.
  232. TimeRecord timeRecord = {
  233. .frameTime =
  234. {
  235. .frameNumber = frameNumber,
  236. .postTime = postTime,
  237. .latchTime = postTime,
  238. .acquireTime = postTime,
  239. .desiredTime = postTime,
  240. },
  241. };
  242. layerRecord.timeRecords.push_back(timeRecord);
  243. if (layerRecord.waitData < 0 ||
  244. layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
  245. layerRecord.waitData = layerRecord.timeRecords.size() - 1;
  246. }
  247. void TimeStats::setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) {
  248. if (!mEnabled.load()) return;
  249. ATRACE_CALL();
  250. ALOGV("[%d]-[%" PRIu64 "]-LatchTime[%" PRId64 "]", layerID, frameNumber, latchTime);
  251. std::lock_guard<std::mutex> lock(mMutex);
  252. if (!mTimeStatsTracker.count(layerID)) return;
  253. LayerRecord& layerRecord = mTimeStatsTracker[layerID];
  254. if (layerRecord.waitData < 0 ||
  255. layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
  256. return;
  257. TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
  258. if (timeRecord.frameTime.frameNumber == frameNumber) {
  259. timeRecord.frameTime.latchTime = latchTime;
  260. }
  261. }
  262. void TimeStats::setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) {
  263. if (!mEnabled.load()) return;
  264. ATRACE_CALL();
  265. ALOGV("[%d]-[%" PRIu64 "]-DesiredTime[%" PRId64 "]", layerID, frameNumber, desiredTime);
  266. std::lock_guard<std::mutex> lock(mMutex);
  267. if (!mTimeStatsTracker.count(layerID)) return;
  268. LayerRecord& layerRecord = mTimeStatsTracker[layerID];
  269. if (layerRecord.waitData < 0 ||
  270. layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
  271. return;
  272. TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
  273. if (timeRecord.frameTime.frameNumber == frameNumber) {
  274. timeRecord.frameTime.desiredTime = desiredTime;
  275. }
  276. }
  277. void TimeStats::setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) {
  278. if (!mEnabled.load()) return;
  279. ATRACE_CALL();
  280. ALOGV("[%d]-[%" PRIu64 "]-AcquireTime[%" PRId64 "]", layerID, frameNumber, acquireTime);
  281. std::lock_guard<std::mutex> lock(mMutex);
  282. if (!mTimeStatsTracker.count(layerID)) return;
  283. LayerRecord& layerRecord = mTimeStatsTracker[layerID];
  284. if (layerRecord.waitData < 0 ||
  285. layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
  286. return;
  287. TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
  288. if (timeRecord.frameTime.frameNumber == frameNumber) {
  289. timeRecord.frameTime.acquireTime = acquireTime;
  290. }
  291. }
  292. void TimeStats::setAcquireFence(int32_t layerID, uint64_t frameNumber,
  293. const std::shared_ptr<FenceTime>& acquireFence) {
  294. if (!mEnabled.load()) return;
  295. ATRACE_CALL();
  296. ALOGV("[%d]-[%" PRIu64 "]-AcquireFenceTime[%" PRId64 "]", layerID, frameNumber,
  297. acquireFence->getSignalTime());
  298. std::lock_guard<std::mutex> lock(mMutex);
  299. if (!mTimeStatsTracker.count(layerID)) return;
  300. LayerRecord& layerRecord = mTimeStatsTracker[layerID];
  301. if (layerRecord.waitData < 0 ||
  302. layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
  303. return;
  304. TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
  305. if (timeRecord.frameTime.frameNumber == frameNumber) {
  306. timeRecord.acquireFence = acquireFence;
  307. }
  308. }
  309. void TimeStats::setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) {
  310. if (!mEnabled.load()) return;
  311. ATRACE_CALL();
  312. ALOGV("[%d]-[%" PRIu64 "]-PresentTime[%" PRId64 "]", layerID, frameNumber, presentTime);
  313. std::lock_guard<std::mutex> lock(mMutex);
  314. if (!mTimeStatsTracker.count(layerID)) return;
  315. LayerRecord& layerRecord = mTimeStatsTracker[layerID];
  316. if (layerRecord.waitData < 0 ||
  317. layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
  318. return;
  319. TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
  320. if (timeRecord.frameTime.frameNumber == frameNumber) {
  321. timeRecord.frameTime.presentTime = presentTime;
  322. timeRecord.ready = true;
  323. layerRecord.waitData++;
  324. }
  325. flushAvailableRecordsToStatsLocked(layerID);
  326. }
  327. void TimeStats::setPresentFence(int32_t layerID, uint64_t frameNumber,
  328. const std::shared_ptr<FenceTime>& presentFence) {
  329. if (!mEnabled.load()) return;
  330. ATRACE_CALL();
  331. ALOGV("[%d]-[%" PRIu64 "]-PresentFenceTime[%" PRId64 "]", layerID, frameNumber,
  332. presentFence->getSignalTime());
  333. std::lock_guard<std::mutex> lock(mMutex);
  334. if (!mTimeStatsTracker.count(layerID)) return;
  335. LayerRecord& layerRecord = mTimeStatsTracker[layerID];
  336. if (layerRecord.waitData < 0 ||
  337. layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
  338. return;
  339. TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
  340. if (timeRecord.frameTime.frameNumber == frameNumber) {
  341. timeRecord.presentFence = presentFence;
  342. timeRecord.ready = true;
  343. layerRecord.waitData++;
  344. }
  345. flushAvailableRecordsToStatsLocked(layerID);
  346. }
  347. void TimeStats::onDestroy(int32_t layerID) {
  348. if (!mEnabled.load()) return;
  349. ATRACE_CALL();
  350. ALOGV("[%d]-onDestroy", layerID);
  351. std::lock_guard<std::mutex> lock(mMutex);
  352. if (!mTimeStatsTracker.count(layerID)) return;
  353. mTimeStatsTracker.erase(layerID);
  354. }
  355. void TimeStats::removeTimeRecord(int32_t layerID, uint64_t frameNumber) {
  356. if (!mEnabled.load()) return;
  357. ATRACE_CALL();
  358. ALOGV("[%d]-[%" PRIu64 "]-removeTimeRecord", layerID, frameNumber);
  359. std::lock_guard<std::mutex> lock(mMutex);
  360. if (!mTimeStatsTracker.count(layerID)) return;
  361. LayerRecord& layerRecord = mTimeStatsTracker[layerID];
  362. size_t removeAt = 0;
  363. for (const TimeRecord& record : layerRecord.timeRecords) {
  364. if (record.frameTime.frameNumber == frameNumber) break;
  365. removeAt++;
  366. }
  367. if (removeAt == layerRecord.timeRecords.size()) return;
  368. layerRecord.timeRecords.erase(layerRecord.timeRecords.begin() + removeAt);
  369. if (layerRecord.waitData > static_cast<int32_t>(removeAt)) {
  370. layerRecord.waitData--;
  371. }
  372. layerRecord.droppedFrames++;
  373. }
  374. void TimeStats::flushPowerTimeLocked() {
  375. if (!mEnabled.load()) return;
  376. nsecs_t curTime = systemTime();
  377. // elapsedTime is in milliseconds.
  378. int64_t elapsedTime = (curTime - mPowerTime.prevTime) / 1000000;
  379. switch (mPowerTime.powerMode) {
  380. case HWC_POWER_MODE_NORMAL:
  381. mTimeStats.displayOnTime += elapsedTime;
  382. break;
  383. case HWC_POWER_MODE_OFF:
  384. case HWC_POWER_MODE_DOZE:
  385. case HWC_POWER_MODE_DOZE_SUSPEND:
  386. default:
  387. break;
  388. }
  389. mPowerTime.prevTime = curTime;
  390. }
  391. void TimeStats::setPowerMode(int32_t powerMode) {
  392. if (!mEnabled.load()) {
  393. std::lock_guard<std::mutex> lock(mMutex);
  394. mPowerTime.powerMode = powerMode;
  395. return;
  396. }
  397. std::lock_guard<std::mutex> lock(mMutex);
  398. if (powerMode == mPowerTime.powerMode) return;
  399. flushPowerTimeLocked();
  400. mPowerTime.powerMode = powerMode;
  401. }
  402. void TimeStats::recordRefreshRate(uint32_t fps, nsecs_t duration) {
  403. std::lock_guard<std::mutex> lock(mMutex);
  404. if (mTimeStats.refreshRateStats.count(fps)) {
  405. mTimeStats.refreshRateStats[fps] += duration;
  406. } else {
  407. mTimeStats.refreshRateStats.insert({fps, duration});
  408. }
  409. }
  410. void TimeStats::flushAvailableGlobalRecordsToStatsLocked() {
  411. ATRACE_CALL();
  412. while (!mGlobalRecord.presentFences.empty()) {
  413. const nsecs_t curPresentTime = mGlobalRecord.presentFences.front()->getSignalTime();
  414. if (curPresentTime == Fence::SIGNAL_TIME_PENDING) break;
  415. if (curPresentTime == Fence::SIGNAL_TIME_INVALID) {
  416. ALOGE("GlobalPresentFence is invalid!");
  417. mGlobalRecord.prevPresentTime = 0;
  418. mGlobalRecord.presentFences.pop_front();
  419. continue;
  420. }
  421. ALOGV("GlobalPresentFenceTime[%" PRId64 "]",
  422. mGlobalRecord.presentFences.front()->getSignalTime());
  423. if (mGlobalRecord.prevPresentTime != 0) {
  424. const int32_t presentToPresentMs =
  425. msBetween(mGlobalRecord.prevPresentTime, curPresentTime);
  426. ALOGV("Global present2present[%d] prev[%" PRId64 "] curr[%" PRId64 "]",
  427. presentToPresentMs, mGlobalRecord.prevPresentTime, curPresentTime);
  428. mTimeStats.presentToPresent.insert(presentToPresentMs);
  429. }
  430. mGlobalRecord.prevPresentTime = curPresentTime;
  431. mGlobalRecord.presentFences.pop_front();
  432. }
  433. }
  434. void TimeStats::setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) {
  435. if (!mEnabled.load()) return;
  436. ATRACE_CALL();
  437. std::lock_guard<std::mutex> lock(mMutex);
  438. if (presentFence == nullptr || !presentFence->isValid()) {
  439. mGlobalRecord.prevPresentTime = 0;
  440. return;
  441. }
  442. if (mPowerTime.powerMode != HWC_POWER_MODE_NORMAL) {
  443. // Try flushing the last present fence on HWC_POWER_MODE_NORMAL.
  444. flushAvailableGlobalRecordsToStatsLocked();
  445. mGlobalRecord.presentFences.clear();
  446. mGlobalRecord.prevPresentTime = 0;
  447. return;
  448. }
  449. if (mGlobalRecord.presentFences.size() == MAX_NUM_TIME_RECORDS) {
  450. // The front presentFence must be trapped in pending status in this
  451. // case. Try dequeuing the front one to recover.
  452. ALOGE("GlobalPresentFences is already at its maximum size[%zu]", MAX_NUM_TIME_RECORDS);
  453. mGlobalRecord.prevPresentTime = 0;
  454. mGlobalRecord.presentFences.pop_front();
  455. }
  456. mGlobalRecord.presentFences.emplace_back(presentFence);
  457. flushAvailableGlobalRecordsToStatsLocked();
  458. }
  459. void TimeStats::enable() {
  460. if (mEnabled.load()) return;
  461. ATRACE_CALL();
  462. std::lock_guard<std::mutex> lock(mMutex);
  463. mEnabled.store(true);
  464. mTimeStats.statsStart = static_cast<int64_t>(std::time(0));
  465. mPowerTime.prevTime = systemTime();
  466. ALOGD("Enabled");
  467. }
  468. void TimeStats::disable() {
  469. if (!mEnabled.load()) return;
  470. ATRACE_CALL();
  471. std::lock_guard<std::mutex> lock(mMutex);
  472. flushPowerTimeLocked();
  473. mEnabled.store(false);
  474. mTimeStats.statsEnd = static_cast<int64_t>(std::time(0));
  475. ALOGD("Disabled");
  476. }
  477. void TimeStats::clear() {
  478. ATRACE_CALL();
  479. std::lock_guard<std::mutex> lock(mMutex);
  480. mTimeStatsTracker.clear();
  481. mTimeStats.stats.clear();
  482. mTimeStats.statsStart = (mEnabled.load() ? static_cast<int64_t>(std::time(0)) : 0);
  483. mTimeStats.statsEnd = 0;
  484. mTimeStats.totalFrames = 0;
  485. mTimeStats.missedFrames = 0;
  486. mTimeStats.clientCompositionFrames = 0;
  487. mTimeStats.displayOnTime = 0;
  488. mTimeStats.presentToPresent.hist.clear();
  489. mTimeStats.refreshRateStats.clear();
  490. mPowerTime.prevTime = systemTime();
  491. mGlobalRecord.prevPresentTime = 0;
  492. mGlobalRecord.presentFences.clear();
  493. ALOGD("Cleared");
  494. }
  495. bool TimeStats::isEnabled() {
  496. return mEnabled.load();
  497. }
  498. void TimeStats::dump(bool asProto, std::optional<uint32_t> maxLayers, std::string& result) {
  499. ATRACE_CALL();
  500. std::lock_guard<std::mutex> lock(mMutex);
  501. if (mTimeStats.statsStart == 0) {
  502. return;
  503. }
  504. mTimeStats.statsEnd = static_cast<int64_t>(std::time(0));
  505. flushPowerTimeLocked();
  506. if (asProto) {
  507. ALOGD("Dumping TimeStats as proto");
  508. SFTimeStatsGlobalProto timeStatsProto = mTimeStats.toProto(maxLayers);
  509. result.append(timeStatsProto.SerializeAsString().c_str(), timeStatsProto.ByteSize());
  510. } else {
  511. ALOGD("Dumping TimeStats as text");
  512. result.append(mTimeStats.toString(maxLayers));
  513. result.append("\n");
  514. }
  515. }
  516. } // namespace impl
  517. } // namespace android