blob: cd0093703c9cb67d6ec18e37451cdeb6e37e1c19 [file] [log] [blame]
Girish1f002cf2023-02-17 00:36:29 +00001/*
2**
3** Copyright 2023, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "ResourceManagerMetrics"
20#include <utils/Log.h>
21#include <mediautils/ProcessInfo.h>
22
23#include <stats_media_metrics.h>
24
25#include "UidObserver.h"
26#include "ResourceManagerMetrics.h"
27
28#include <cmath>
29#include <sstream>
30
31namespace android {
32
33using stats::media_metrics::stats_write;
34using stats::media_metrics::MEDIA_CODEC_STARTED;
35using stats::media_metrics::MEDIA_CODEC_STOPPED;
36// Disabling this for now.
37#ifdef ENABLE_MEDIA_CODEC_CONCURRENT_USAGE_REPORTED
38using stats::media_metrics::MEDIA_CODEC_CONCURRENT_USAGE_REPORTED;
39#endif
40using stats::media_metrics::MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED;
41using stats::media_metrics::MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_SUCCESS;
42using stats::media_metrics::\
43 MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
44using stats::media_metrics::\
45 MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
Girisha2b88282024-02-07 22:50:13 +000046using stats::media_metrics::MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_UNSPECIFIED;
47using stats::media_metrics::MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_AUDIO;
48using stats::media_metrics::MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_VIDEO;
49using stats::media_metrics::MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_IMAGE;
50
51// Map MediaResourceSubType to stats::media_metrics::CodecType
52inline int32_t getMetricsCodecType(MediaResourceSubType codecType) {
53 switch (codecType) {
54 case MediaResourceSubType::kHwAudioCodec:
55 case MediaResourceSubType::kSwAudioCodec:
56 return MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_AUDIO;
57 case MediaResourceSubType::kHwVideoCodec:
58 case MediaResourceSubType::kSwVideoCodec:
59 return MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_VIDEO;
60 case MediaResourceSubType::kHwImageCodec:
61 case MediaResourceSubType::kSwImageCodec:
62 return MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_IMAGE;
63 case MediaResourceSubType::kUnspecifiedSubType:
64 return MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_UNSPECIFIED;
65 }
66 return MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_UNSPECIFIED;
67}
Girish1f002cf2023-02-17 00:36:29 +000068
69inline const char* getCodecType(MediaResourceSubType codecType) {
70 switch (codecType) {
Girisha5a2d672023-09-20 18:40:20 +000071 case MediaResourceSubType::kHwAudioCodec: return "Hw Audio";
72 case MediaResourceSubType::kSwAudioCodec: return "Sw Audio";
73 case MediaResourceSubType::kHwVideoCodec: return "Hw Video";
74 case MediaResourceSubType::kSwVideoCodec: return "Sw Video";
75 case MediaResourceSubType::kHwImageCodec: return "Hw Image";
76 case MediaResourceSubType::kSwImageCodec: return "Sw Image";
Girish1f002cf2023-02-17 00:36:29 +000077 case MediaResourceSubType::kUnspecifiedSubType:
78 default:
79 return "Unspecified";
80 }
81 return "Unspecified";
82}
83
Girisha5a2d672023-09-20 18:40:20 +000084inline bool isHardwareCodec(MediaResourceSubType codecType) {
85 return (codecType == MediaResourceSubType::kHwAudioCodec ||
86 codecType == MediaResourceSubType::kHwVideoCodec ||
87 codecType == MediaResourceSubType::kHwImageCodec);
88}
89
90static CodecBucket getCodecBucket(bool isEncoder, MediaResourceSubType codecType) {
91 switch (codecType) {
92 case MediaResourceSubType::kHwAudioCodec:
93 return isEncoder? HwAudioEncoder : HwAudioDecoder;
94 case MediaResourceSubType::kSwAudioCodec:
95 return isEncoder? SwAudioEncoder : SwAudioDecoder;
96 case MediaResourceSubType::kHwVideoCodec:
97 return isEncoder? HwVideoEncoder : HwVideoDecoder;
98 case MediaResourceSubType::kSwVideoCodec:
99 return isEncoder? SwVideoEncoder : SwVideoDecoder;
100 case MediaResourceSubType::kHwImageCodec:
101 return isEncoder? HwImageEncoder : HwImageDecoder;
102 case MediaResourceSubType::kSwImageCodec:
103 return isEncoder? SwImageEncoder : SwImageDecoder;
104 case MediaResourceSubType::kUnspecifiedSubType:
105 default:
106 return CodecBucketUnspecified;
Girish1f002cf2023-02-17 00:36:29 +0000107 }
108
109 return CodecBucketUnspecified;
110}
111
112static bool getLogMessage(int hwCount, int swCount, std::stringstream& logMsg) {
113 bool update = false;
114 logMsg.clear();
115
116 if (hwCount > 0) {
117 logMsg << " HW: " << hwCount;
118 update = true;
119 }
120 if (swCount > 0) {
121 logMsg << " SW: " << swCount;
122 update = true;
123 }
124
125 if (update) {
126 logMsg << " ] ";
127 }
128 return update;
129}
130
131ResourceManagerMetrics::ResourceManagerMetrics(const sp<ProcessInfoInterface>& processInfo) {
132 // Create a process termination watcher, with 5seconds of polling frequency.
133 mUidObserver = sp<UidObserver>::make(processInfo,
134 [this] (int32_t pid, uid_t uid) {
135 onProcessTerminated(pid, uid);
136 });
137 mUidObserver->start();
138}
139
140ResourceManagerMetrics::~ResourceManagerMetrics() {
141 mUidObserver->stop();
142}
143
144void ResourceManagerMetrics::addPid(int pid, uid_t uid) {
145 if (uid != 0) {
146 std::scoped_lock lock(mLock);
147 mUidObserver->add(pid, uid);
148 }
149}
150
151void ResourceManagerMetrics::notifyClientCreated(const ClientInfoParcel& clientInfo) {
152 std::scoped_lock lock(mLock);
153 // Update the resource instance count.
154 std::map<std::string, int>::iterator found = mConcurrentResourceCountMap.find(clientInfo.name);
155 if (found == mConcurrentResourceCountMap.end()) {
156 mConcurrentResourceCountMap[clientInfo.name] = 1;
157 } else {
158 found->second++;
159 }
160}
161
162void ResourceManagerMetrics::notifyClientReleased(const ClientInfoParcel& clientInfo) {
163 bool stopCalled = true;
Girishc9637682023-03-23 23:33:32 +0000164 ClientConfigParcel clientConfig;
Girish1f002cf2023-02-17 00:36:29 +0000165 {
166 std::scoped_lock lock(mLock);
Girishc9637682023-03-23 23:33:32 +0000167 ClientConfigMap::iterator found = mClientConfigMap.find(clientInfo.id);
Girish1f002cf2023-02-17 00:36:29 +0000168 if (found != mClientConfigMap.end()) {
169 // Release is called without Stop!
170 stopCalled = false;
Girishc9637682023-03-23 23:33:32 +0000171 clientConfig = found->second;
172 // Update the timestamp for stopping the codec.
173 clientConfig.timeStamp = systemTime(SYSTEM_TIME_MONOTONIC) / 1000LL;
Girish1f002cf2023-02-17 00:36:29 +0000174 }
175 }
176 if (!stopCalled) {
177 // call Stop to update the metrics.
Girishc9637682023-03-23 23:33:32 +0000178 notifyClientStopped(clientConfig);
Girish1f002cf2023-02-17 00:36:29 +0000179 }
180 {
181 std::scoped_lock lock(mLock);
182 // Update the resource instance count also.
183 std::map<std::string, int>::iterator found =
184 mConcurrentResourceCountMap.find(clientInfo.name);
185 if (found != mConcurrentResourceCountMap.end()) {
186 if (found->second > 0) {
187 found->second--;
188 }
189 }
190 }
191}
192
Girishde8eb592023-04-13 18:49:17 +0000193void ResourceManagerMetrics::notifyClientConfigChanged(const ClientConfigParcel& clientConfig) {
194 std::scoped_lock lock(mLock);
195 ClientConfigMap::iterator entry = mClientConfigMap.find(clientConfig.clientInfo.id);
196 if (entry != mClientConfigMap.end() &&
Girisha5a2d672023-09-20 18:40:20 +0000197 (clientConfig.codecType == MediaResourceSubType::kHwVideoCodec ||
198 clientConfig.codecType == MediaResourceSubType::kSwVideoCodec ||
199 clientConfig.codecType == MediaResourceSubType::kHwImageCodec ||
200 clientConfig.codecType == MediaResourceSubType::kSwImageCodec)) {
Girishde8eb592023-04-13 18:49:17 +0000201 int pid = clientConfig.clientInfo.pid;
202 // Update the pixel count for this process
203 updatePixelCount(pid, clientConfig.width * (long)clientConfig.height,
204 entry->second.width * (long)entry->second.height);
205 // Update the resolution in the record.
206 entry->second.width = clientConfig.width;
207 entry->second.height = clientConfig.height;
208 }
209}
210
Girish1f002cf2023-02-17 00:36:29 +0000211void ResourceManagerMetrics::notifyClientStarted(const ClientConfigParcel& clientConfig) {
212 std::scoped_lock lock(mLock);
213 int pid = clientConfig.clientInfo.pid;
214 // We need to observer this process.
215 mUidObserver->add(pid, clientConfig.clientInfo.uid);
216
217 // Update the client config for thic client.
218 mClientConfigMap[clientConfig.clientInfo.id] = clientConfig;
219
220 // Update the concurrent codec count for this process.
Girisha5a2d672023-09-20 18:40:20 +0000221 CodecBucket codecBucket = getCodecBucket(clientConfig.isEncoder, clientConfig.codecType);
Girish1f002cf2023-02-17 00:36:29 +0000222 increaseConcurrentCodecs(pid, codecBucket);
223
Girisha5a2d672023-09-20 18:40:20 +0000224 if (clientConfig.codecType == MediaResourceSubType::kHwVideoCodec ||
225 clientConfig.codecType == MediaResourceSubType::kSwVideoCodec ||
226 clientConfig.codecType == MediaResourceSubType::kHwImageCodec ||
227 clientConfig.codecType == MediaResourceSubType::kSwImageCodec) {
Girish1f002cf2023-02-17 00:36:29 +0000228 // Update the pixel count for this process
229 increasePixelCount(pid, clientConfig.width * (long)clientConfig.height);
230 }
231
232 // System concurrent codec usage
Girishde8eb592023-04-13 18:49:17 +0000233 int systemConcurrentCodecs = mConcurrentCodecsMap[codecBucket];
Girish1f002cf2023-02-17 00:36:29 +0000234 // Process/Application concurrent codec usage for this type of codec
Girishde8eb592023-04-13 18:49:17 +0000235 const ConcurrentCodecs& concurrentCodecs = mProcessConcurrentCodecsMap[pid];
236 int appConcurrentCodecs = concurrentCodecs.mCurrent[codecBucket];
237 int hwVideoCodecs = concurrentCodecs.mHWVideoCodecs;
238 int swVideoCodecs = concurrentCodecs.mSWVideoCodecs;
239 int videoCodecs = concurrentCodecs.mVideoCodecs;
240 int audioCodecs = concurrentCodecs.mAudioCodecs;
241 int imageCodecs = concurrentCodecs.mImageCodecs;
Girish1f002cf2023-02-17 00:36:29 +0000242 // Process/Application's current pixel count.
243 long pixelCount = 0;
244 std::map<int32_t, PixelCount>::iterator it = mProcessPixelsMap.find(pid);
245 if (it != mProcessPixelsMap.end()) {
246 pixelCount = it->second.mCurrent;
247 }
248
249 int result = stats_write(
250 MEDIA_CODEC_STARTED,
251 clientConfig.clientInfo.uid,
252 clientConfig.id,
253 clientConfig.clientInfo.name.c_str(),
Girisha2b88282024-02-07 22:50:13 +0000254 getMetricsCodecType(clientConfig.codecType),
Girish1f002cf2023-02-17 00:36:29 +0000255 clientConfig.isEncoder,
Girisha5a2d672023-09-20 18:40:20 +0000256 isHardwareCodec(clientConfig.codecType),
Girish1f002cf2023-02-17 00:36:29 +0000257 clientConfig.width, clientConfig.height,
Girishde8eb592023-04-13 18:49:17 +0000258 systemConcurrentCodecs,
259 appConcurrentCodecs,
260 pixelCount,
261 hwVideoCodecs,
262 swVideoCodecs,
263 videoCodecs,
264 audioCodecs,
265 imageCodecs);
Girish1f002cf2023-02-17 00:36:29 +0000266
267 ALOGV("%s: Pushed MEDIA_CODEC_STARTED atom: "
268 "Process[pid(%d): uid(%d)] "
Girisha5a2d672023-09-20 18:40:20 +0000269 "Codec: [%s: %ju] is %s %s "
Girish1f002cf2023-02-17 00:36:29 +0000270 "Timestamp: %jd "
271 "Resolution: %d x %d "
272 "ConcurrentCodec[%d]={System: %d App: %d} "
Girishde8eb592023-04-13 18:49:17 +0000273 "AppConcurrentCodecs{Video: %d(HW[%d] SW[%d]) Audio: %d Image: %d} "
Girish1f002cf2023-02-17 00:36:29 +0000274 "result: %d",
275 __func__,
276 pid, clientConfig.clientInfo.uid,
277 clientConfig.clientInfo.name.c_str(),
278 clientConfig.id,
Girish1f002cf2023-02-17 00:36:29 +0000279 getCodecType(clientConfig.codecType),
280 clientConfig.isEncoder? "encoder" : "decoder",
281 clientConfig.timeStamp,
282 clientConfig.width, clientConfig.height,
Girishde8eb592023-04-13 18:49:17 +0000283 codecBucket, systemConcurrentCodecs, appConcurrentCodecs,
284 videoCodecs, hwVideoCodecs, swVideoCodecs, audioCodecs, imageCodecs,
Girish1f002cf2023-02-17 00:36:29 +0000285 result);
286}
287
288void ResourceManagerMetrics::notifyClientStopped(const ClientConfigParcel& clientConfig) {
289 std::scoped_lock lock(mLock);
290 int pid = clientConfig.clientInfo.pid;
291 // Update the concurrent codec count for this process.
Girisha5a2d672023-09-20 18:40:20 +0000292 CodecBucket codecBucket = getCodecBucket(clientConfig.isEncoder, clientConfig.codecType);
Girish1f002cf2023-02-17 00:36:29 +0000293 decreaseConcurrentCodecs(pid, codecBucket);
294
Girisha5a2d672023-09-20 18:40:20 +0000295 if (clientConfig.codecType == MediaResourceSubType::kHwVideoCodec ||
296 clientConfig.codecType == MediaResourceSubType::kSwVideoCodec ||
297 clientConfig.codecType == MediaResourceSubType::kHwImageCodec ||
298 clientConfig.codecType == MediaResourceSubType::kSwImageCodec) {
Girish1f002cf2023-02-17 00:36:29 +0000299 // Update the pixel count for this process
300 decreasePixelCount(pid, clientConfig.width * (long)clientConfig.height);
301 }
302
303 // System concurrent codec usage
Girishde8eb592023-04-13 18:49:17 +0000304 int systemConcurrentCodecs = mConcurrentCodecsMap[codecBucket];
Girish1f002cf2023-02-17 00:36:29 +0000305 // Process/Application concurrent codec usage for this type of codec
Girishde8eb592023-04-13 18:49:17 +0000306 int appConcurrentCodecs = 0;
Girish1f002cf2023-02-17 00:36:29 +0000307 std::map<int32_t, ConcurrentCodecs>::iterator found = mProcessConcurrentCodecsMap.find(pid);
308 if (found != mProcessConcurrentCodecsMap.end()) {
Girishde8eb592023-04-13 18:49:17 +0000309 appConcurrentCodecs = found->second.mCurrent[codecBucket];
Girish1f002cf2023-02-17 00:36:29 +0000310 }
311 // Process/Application's current pixel count.
312 long pixelCount = 0;
313 std::map<int32_t, PixelCount>::iterator it = mProcessPixelsMap.find(pid);
314 if (it != mProcessPixelsMap.end()) {
315 pixelCount = it->second.mCurrent;
316 }
317
318 // calculate the usageTime as:
319 // MediaCodecStopped.clientConfig.timeStamp -
320 // MediaCodecStarted.clientConfig.timeStamp
321 int64_t usageTime = 0;
322 ClientConfigMap::iterator entry = mClientConfigMap.find(clientConfig.clientInfo.id);
323 if (entry != mClientConfigMap.end()) {
324 usageTime = clientConfig.timeStamp - entry->second.timeStamp;
325 // And we can erase this config now.
326 mClientConfigMap.erase(entry);
327 } else {
328 ALOGW("%s: Start Config is missing!", __func__);
329 }
330
331 int result = stats_write(
332 MEDIA_CODEC_STOPPED,
333 clientConfig.clientInfo.uid,
334 clientConfig.id,
335 clientConfig.clientInfo.name.c_str(),
Girisha2b88282024-02-07 22:50:13 +0000336 getMetricsCodecType(clientConfig.codecType),
Girish1f002cf2023-02-17 00:36:29 +0000337 clientConfig.isEncoder,
Girisha5a2d672023-09-20 18:40:20 +0000338 isHardwareCodec(clientConfig.codecType),
Girish1f002cf2023-02-17 00:36:29 +0000339 clientConfig.width, clientConfig.height,
Girishde8eb592023-04-13 18:49:17 +0000340 systemConcurrentCodecs,
341 appConcurrentCodecs,
Girish1f002cf2023-02-17 00:36:29 +0000342 pixelCount,
343 usageTime);
344 ALOGV("%s: Pushed MEDIA_CODEC_STOPPED atom: "
345 "Process[pid(%d): uid(%d)] "
Girisha5a2d672023-09-20 18:40:20 +0000346 "Codec: [%s: %ju] is %s %s "
Girish1f002cf2023-02-17 00:36:29 +0000347 "Timestamp: %jd Usage time: %jd "
348 "Resolution: %d x %d "
349 "ConcurrentCodec[%d]={System: %d App: %d} "
350 "result: %d",
351 __func__,
352 pid, clientConfig.clientInfo.uid,
353 clientConfig.clientInfo.name.c_str(),
354 clientConfig.id,
Girish1f002cf2023-02-17 00:36:29 +0000355 getCodecType(clientConfig.codecType),
356 clientConfig.isEncoder? "encoder" : "decoder",
357 clientConfig.timeStamp, usageTime,
358 clientConfig.width, clientConfig.height,
Girishde8eb592023-04-13 18:49:17 +0000359 codecBucket, systemConcurrentCodecs, appConcurrentCodecs,
Girish1f002cf2023-02-17 00:36:29 +0000360 result);
361}
362
363void ResourceManagerMetrics::onProcessTerminated(int32_t pid, uid_t uid) {
364 std::scoped_lock lock(mLock);
365 // post MediaCodecConcurrentUsageReported for this terminated pid.
366 pushConcurrentUsageReport(pid, uid);
367}
368
369void ResourceManagerMetrics::pushConcurrentUsageReport(int32_t pid, uid_t uid) {
370 // Process/Application peak concurrent codec usage
371 std::map<int32_t, ConcurrentCodecs>::iterator found = mProcessConcurrentCodecsMap.find(pid);
372 if (found == mProcessConcurrentCodecsMap.end()) {
373 ALOGI("%s: No MEDIA_CODEC_CONCURRENT_USAGE_REPORTED atom Entry for: "
374 "Application[pid(%d): uid(%d)]", __func__, pid, uid);
375 return;
376 }
377 const ConcurrentCodecsMap& codecsMap = found->second.mPeak;
378 int peakHwAudioEncoderCount = codecsMap[HwAudioEncoder];
379 int peakHwAudioDecoderCount = codecsMap[HwAudioDecoder];
380 int peakHwVideoEncoderCount = codecsMap[HwVideoEncoder];
381 int peakHwVideoDecoderCount = codecsMap[HwVideoDecoder];
382 int peakHwImageEncoderCount = codecsMap[HwImageEncoder];
383 int peakHwImageDecoderCount = codecsMap[HwImageDecoder];
384 int peakSwAudioEncoderCount = codecsMap[SwAudioEncoder];
385 int peakSwAudioDecoderCount = codecsMap[SwAudioDecoder];
386 int peakSwVideoEncoderCount = codecsMap[SwVideoEncoder];
387 int peakSwVideoDecoderCount = codecsMap[SwVideoDecoder];
388 int peakSwImageEncoderCount = codecsMap[SwImageEncoder];
389 int peakSwImageDecoderCount = codecsMap[SwImageDecoder];
390
391 long peakPixels = 0;
392 std::map<int32_t, PixelCount>::iterator it = mProcessPixelsMap.find(pid);
393 if (it == mProcessPixelsMap.end()) {
394 ALOGI("%s: No Video Codec Entry for Application[pid(%d): uid(%d)]",
395 __func__, pid, uid);
396 } else {
397 peakPixels = it->second.mPeak;
398 }
399 std::string peakPixelsLog("Peak Pixels: " + std::to_string(peakPixels));
400
401 std::stringstream peakCodecLog;
402 peakCodecLog << "Peak { ";
403 std::stringstream logMsg;
404 if (getLogMessage(peakHwAudioEncoderCount, peakSwAudioEncoderCount, logMsg)) {
405 peakCodecLog << "AudioEnc[" << logMsg.str();
406 }
407 if (getLogMessage(peakHwAudioDecoderCount, peakSwAudioDecoderCount, logMsg)) {
408 peakCodecLog << "AudioDec[" << logMsg.str();
409 }
410 if (getLogMessage(peakHwVideoEncoderCount, peakSwVideoEncoderCount, logMsg)) {
411 peakCodecLog << "VideoEnc[" << logMsg.str();
412 }
413 if (getLogMessage(peakHwVideoDecoderCount, peakSwVideoDecoderCount, logMsg)) {
414 peakCodecLog << "VideoDec[" << logMsg.str();
415 }
416 if (getLogMessage(peakHwImageEncoderCount, peakSwImageEncoderCount, logMsg)) {
417 peakCodecLog << "ImageEnc[" << logMsg.str();
418 }
419 if (getLogMessage(peakHwImageDecoderCount, peakSwImageDecoderCount, logMsg)) {
420 peakCodecLog << "ImageDec[" << logMsg.str();
421 }
422 peakCodecLog << "}";
423
424#ifdef ENABLE_MEDIA_CODEC_CONCURRENT_USAGE_REPORTED
425 int result = stats_write(
426 MEDIA_CODEC_CONCURRENT_USAGE_REPORTED,
427 uid,
428 peakHwVideoDecoderCount,
429 peakHwVideoEncoderCount,
430 peakSwVideoDecoderCount,
431 peakSwVideoEncoderCount,
432 peakHwAudioDecoderCount,
433 peakHwAudioEncoderCount,
434 peakSwAudioDecoderCount,
435 peakSwAudioEncoderCount,
436 peakHwImageDecoderCount,
437 peakHwImageEncoderCount,
438 peakSwImageDecoderCount,
439 peakSwImageEncoderCount,
440 peakPixels);
441 ALOGI("%s: Pushed MEDIA_CODEC_CONCURRENT_USAGE_REPORTED atom: "
442 "Process[pid(%d): uid(%d)] %s %s result: %d",
443 __func__, pid, uid, peakCodecLog.str().c_str(), peakPixelsLog.c_str(), result);
444#else
445 ALOGI("%s: Concurrent Codec Usage Report for the Process[pid(%d): uid(%d)] is %s %s",
446 __func__, pid, uid, peakCodecLog.str().c_str(), peakPixelsLog.c_str());
447#endif
448}
449
Girishe7b338f2024-02-08 22:03:51 +0000450inline void pushReclaimStats(int32_t callingPid,
451 int32_t requesterUid,
452 int requesterPriority,
453 const std::string& clientName,
454 int32_t noOfConcurrentCodecs,
455 int32_t reclaimStatus,
456 int32_t noOfCodecsReclaimed = 0,
457 int32_t targetIndex = -1,
458 int32_t targetClientPid = -1,
459 int32_t targetClientUid = -1,
460 int32_t targetPriority = -1) {
461 // Post the pushed atom
462 int result = stats_write(
463 MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED,
464 requesterUid,
465 requesterPriority,
466 clientName.c_str(),
467 noOfConcurrentCodecs,
468 reclaimStatus,
469 noOfCodecsReclaimed,
470 targetIndex,
471 targetClientUid,
472 targetPriority);
473 ALOGI("%s: Pushed MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED atom: "
474 "Requester[pid(%d): uid(%d): priority(%d)] "
475 "Codec: [%s] "
476 "No of concurrent codecs: %d "
477 "Reclaim Status: %d "
478 "No of codecs reclaimed: %d "
479 "Target[%d][pid(%d): uid(%d): priority(%d)] result: %d",
480 __func__, callingPid, requesterUid, requesterPriority,
481 clientName.c_str(), noOfConcurrentCodecs,
482 reclaimStatus, noOfCodecsReclaimed,
483 targetIndex, targetClientPid, targetClientUid, targetPriority, result);
484}
485
Girish1f002cf2023-02-17 00:36:29 +0000486void ResourceManagerMetrics::pushReclaimAtom(const ClientInfoParcel& clientInfo,
Girish56fda312023-10-12 21:32:35 +0000487 const std::vector<int>& priorities,
488 const std::vector<ClientInfo>& targetClients,
489 bool reclaimed) {
Girish1f002cf2023-02-17 00:36:29 +0000490 // Construct the metrics for codec reclaim as a pushed atom.
491 // 1. Information about the requester.
492 // - UID and the priority (oom score)
493 int32_t callingPid = clientInfo.pid;
494 int32_t requesterUid = clientInfo.uid;
495 std::string clientName = clientInfo.name;
496 int requesterPriority = priorities[0];
497
498 // 2. Information about the codec.
499 // - Name of the codec requested
500 // - Number of concurrent codecs running.
501 int32_t noOfConcurrentCodecs = 0;
502 std::map<std::string, int>::iterator found = mConcurrentResourceCountMap.find(clientName);
503 if (found != mConcurrentResourceCountMap.end()) {
504 noOfConcurrentCodecs = found->second;
505 }
506
507 // 3. Information about the Reclaim:
508 // - Status of reclaim request
509 // - How many codecs are reclaimed
510 // - For each codecs reclaimed, information of the process that it belonged to:
511 // - UID and the Priority (oom score)
512 int32_t reclaimStatus = MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_SUCCESS;
513 if (!reclaimed) {
Girish56fda312023-10-12 21:32:35 +0000514 if (targetClients.size() == 0) {
Girish1f002cf2023-02-17 00:36:29 +0000515 // No clients to reclaim from
516 reclaimStatus =
517 MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
518 } else {
519 // Couldn't reclaim resources from the clients
520 reclaimStatus =
521 MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
522 }
523 }
Girishe7b338f2024-02-08 22:03:51 +0000524
525 if (targetClients.empty()) {
526 // Push the reclaim atom to stats.
527 pushReclaimStats(callingPid,
528 requesterUid,
529 requesterPriority,
530 clientName,
531 noOfConcurrentCodecs,
532 reclaimStatus);
533 return;
534 }
535
Girish56fda312023-10-12 21:32:35 +0000536 int32_t noOfCodecsReclaimed = targetClients.size();
Girish1f002cf2023-02-17 00:36:29 +0000537 int32_t targetIndex = 1;
Girish56fda312023-10-12 21:32:35 +0000538 for (const ClientInfo& targetClient : targetClients) {
Girish1f002cf2023-02-17 00:36:29 +0000539 int targetPriority = priorities[targetIndex];
Girishe7b338f2024-02-08 22:03:51 +0000540 // Push the reclaim atom to stats.
541 pushReclaimStats(callingPid,
542 requesterUid,
543 requesterPriority,
544 clientName,
545 noOfConcurrentCodecs,
546 reclaimStatus,
547 noOfCodecsReclaimed,
548 targetIndex,
549 targetClient.mPid,
550 targetClient.mUid,
551 targetPriority);
Girish1f002cf2023-02-17 00:36:29 +0000552 targetIndex++;
553 }
554}
555
556void ResourceManagerMetrics::increaseConcurrentCodecs(int32_t pid,
557 CodecBucket codecBucket) {
558 // Increase the codec usage across the system.
559 mConcurrentCodecsMap[codecBucket]++;
560
561 // Now update the codec usage for this (pid) process.
562 std::map<int32_t, ConcurrentCodecs>::iterator found = mProcessConcurrentCodecsMap.find(pid);
563 if (found == mProcessConcurrentCodecsMap.end()) {
564 ConcurrentCodecs codecs;
565 codecs.mCurrent[codecBucket] = 1;
566 codecs.mPeak[codecBucket] = 1;
Girishde8eb592023-04-13 18:49:17 +0000567 auto added = mProcessConcurrentCodecsMap.emplace(pid, codecs);
568 found = added.first;
Girish1f002cf2023-02-17 00:36:29 +0000569 } else {
570 found->second.mCurrent[codecBucket]++;
571 // Check if it's the peak count for this slot.
572 if (found->second.mPeak[codecBucket] < found->second.mCurrent[codecBucket]) {
573 found->second.mPeak[codecBucket] = found->second.mCurrent[codecBucket];
574 }
575 }
Girishde8eb592023-04-13 18:49:17 +0000576
577 switch (codecBucket) {
578 case HwVideoEncoder:
579 case HwVideoDecoder:
580 case SwVideoEncoder:
581 case SwVideoDecoder:
582 if (codecBucket == HwVideoEncoder || codecBucket == HwVideoDecoder) {
583 found->second.mHWVideoCodecs++;
584 } else {
585 found->second.mSWVideoCodecs++;
586 }
587 found->second.mVideoCodecs++;
588 break;
589 case HwAudioEncoder:
590 case HwAudioDecoder:
591 case SwAudioEncoder:
592 case SwAudioDecoder:
593 found->second.mAudioCodecs++;
594 break;
595 case HwImageEncoder:
596 case HwImageDecoder:
597 case SwImageEncoder:
598 case SwImageDecoder:
599 found->second.mImageCodecs++;
600 break;
601 default:
602 break;
603 }
Girish1f002cf2023-02-17 00:36:29 +0000604}
605
606void ResourceManagerMetrics::decreaseConcurrentCodecs(int32_t pid,
607 CodecBucket codecBucket) {
608 // Decrease the codec usage across the system.
609 if (mConcurrentCodecsMap[codecBucket] > 0) {
610 mConcurrentCodecsMap[codecBucket]--;
611 }
612
613 // Now update the codec usage for this (pid) process.
614 std::map<int32_t, ConcurrentCodecs>::iterator found = mProcessConcurrentCodecsMap.find(pid);
615 if (found != mProcessConcurrentCodecsMap.end()) {
616 if (found->second.mCurrent[codecBucket] > 0) {
617 found->second.mCurrent[codecBucket]--;
618 }
Girishde8eb592023-04-13 18:49:17 +0000619
620 switch (codecBucket) {
621 case HwVideoEncoder:
622 case HwVideoDecoder:
623 case SwVideoEncoder:
624 case SwVideoDecoder:
625 if (codecBucket == HwVideoEncoder || codecBucket == HwVideoDecoder) {
626 found->second.mHWVideoCodecs--;
627 } else {
628 found->second.mSWVideoCodecs--;
629 }
630 found->second.mVideoCodecs--;
631 break;
632 case HwAudioEncoder:
633 case HwAudioDecoder:
634 case SwAudioEncoder:
635 case SwAudioDecoder:
636 found->second.mAudioCodecs--;
637 break;
638 case HwImageEncoder:
639 case HwImageDecoder:
640 case SwImageEncoder:
641 case SwImageDecoder:
642 found->second.mImageCodecs--;
643 break;
644 default:
645 break;
646 }
Girish1f002cf2023-02-17 00:36:29 +0000647 }
648}
649
650void ResourceManagerMetrics::increasePixelCount(int32_t pid, long pixels) {
651 // Now update the current pixel usage for this (pid) process.
652 std::map<int32_t, PixelCount>::iterator found = mProcessPixelsMap.find(pid);
653 if (found == mProcessPixelsMap.end()) {
654 PixelCount pixelCount {pixels, pixels};
655 mProcessPixelsMap.emplace(pid, pixelCount);
656 } else {
657 if (__builtin_add_overflow(found->second.mCurrent, pixels, &found->second.mCurrent)) {
658 ALOGI("Pixel Count overflow");
659 return;
660 }
661 // Check if it's the peak count for this slot.
662 if (found->second.mPeak < found->second.mCurrent) {
663 found->second.mPeak = found->second.mCurrent;
664 }
665 }
666}
667
Girishde8eb592023-04-13 18:49:17 +0000668void ResourceManagerMetrics::updatePixelCount(int32_t pid, long newPixels, long lastPixels) {
669 // Since there is change in resolution, decrease it by last pixels and
670 // increase it by new pixels.
671 decreasePixelCount(pid, lastPixels);
672 increasePixelCount(pid, newPixels);
673}
674
Girish1f002cf2023-02-17 00:36:29 +0000675void ResourceManagerMetrics::decreasePixelCount(int32_t pid, long pixels) {
676 // Now update the current pixel usage for this (pid) process.
677 std::map<int32_t, PixelCount>::iterator found = mProcessPixelsMap.find(pid);
678 if (found != mProcessPixelsMap.end()) {
679 if (found->second.mCurrent < pixels) {
680 found->second.mCurrent = 0;
681 } else {
682 if (__builtin_sub_overflow(found->second.mCurrent, pixels, &found->second.mCurrent)) {
683 ALOGI("Pixel Count overflow");
684 return;
685 }
686 }
687 }
688}
689
690long ResourceManagerMetrics::getPeakConcurrentPixelCount(int pid) const {
691 std::map<int32_t, PixelCount>::const_iterator found = mProcessPixelsMap.find(pid);
692 if (found != mProcessPixelsMap.end()) {
693 return found->second.mPeak;
694 }
695
696 return 0;
697}
698
699long ResourceManagerMetrics::getCurrentConcurrentPixelCount(int pid) const {
700 std::map<int32_t, PixelCount>::const_iterator found = mProcessPixelsMap.find(pid);
701 if (found != mProcessPixelsMap.end()) {
702 return found->second.mCurrent;
703 }
704
705 return 0;
706}
707
708} // namespace android