blob: af85772f164182739f8bec6db7b83359b1d1529b [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;
46
47inline const char* getCodecType(MediaResourceSubType codecType) {
48 switch (codecType) {
Girisha5a2d672023-09-20 18:40:20 +000049 case MediaResourceSubType::kHwAudioCodec: return "Hw Audio";
50 case MediaResourceSubType::kSwAudioCodec: return "Sw Audio";
51 case MediaResourceSubType::kHwVideoCodec: return "Hw Video";
52 case MediaResourceSubType::kSwVideoCodec: return "Sw Video";
53 case MediaResourceSubType::kHwImageCodec: return "Hw Image";
54 case MediaResourceSubType::kSwImageCodec: return "Sw Image";
Girish1f002cf2023-02-17 00:36:29 +000055 case MediaResourceSubType::kUnspecifiedSubType:
56 default:
57 return "Unspecified";
58 }
59 return "Unspecified";
60}
61
Girisha5a2d672023-09-20 18:40:20 +000062inline bool isHardwareCodec(MediaResourceSubType codecType) {
63 return (codecType == MediaResourceSubType::kHwAudioCodec ||
64 codecType == MediaResourceSubType::kHwVideoCodec ||
65 codecType == MediaResourceSubType::kHwImageCodec);
66}
67
68static CodecBucket getCodecBucket(bool isEncoder, MediaResourceSubType codecType) {
69 switch (codecType) {
70 case MediaResourceSubType::kHwAudioCodec:
71 return isEncoder? HwAudioEncoder : HwAudioDecoder;
72 case MediaResourceSubType::kSwAudioCodec:
73 return isEncoder? SwAudioEncoder : SwAudioDecoder;
74 case MediaResourceSubType::kHwVideoCodec:
75 return isEncoder? HwVideoEncoder : HwVideoDecoder;
76 case MediaResourceSubType::kSwVideoCodec:
77 return isEncoder? SwVideoEncoder : SwVideoDecoder;
78 case MediaResourceSubType::kHwImageCodec:
79 return isEncoder? HwImageEncoder : HwImageDecoder;
80 case MediaResourceSubType::kSwImageCodec:
81 return isEncoder? SwImageEncoder : SwImageDecoder;
82 case MediaResourceSubType::kUnspecifiedSubType:
83 default:
84 return CodecBucketUnspecified;
Girish1f002cf2023-02-17 00:36:29 +000085 }
86
87 return CodecBucketUnspecified;
88}
89
90static bool getLogMessage(int hwCount, int swCount, std::stringstream& logMsg) {
91 bool update = false;
92 logMsg.clear();
93
94 if (hwCount > 0) {
95 logMsg << " HW: " << hwCount;
96 update = true;
97 }
98 if (swCount > 0) {
99 logMsg << " SW: " << swCount;
100 update = true;
101 }
102
103 if (update) {
104 logMsg << " ] ";
105 }
106 return update;
107}
108
109ResourceManagerMetrics::ResourceManagerMetrics(const sp<ProcessInfoInterface>& processInfo) {
110 // Create a process termination watcher, with 5seconds of polling frequency.
111 mUidObserver = sp<UidObserver>::make(processInfo,
112 [this] (int32_t pid, uid_t uid) {
113 onProcessTerminated(pid, uid);
114 });
115 mUidObserver->start();
116}
117
118ResourceManagerMetrics::~ResourceManagerMetrics() {
119 mUidObserver->stop();
120}
121
122void ResourceManagerMetrics::addPid(int pid, uid_t uid) {
123 if (uid != 0) {
124 std::scoped_lock lock(mLock);
125 mUidObserver->add(pid, uid);
126 }
127}
128
129void ResourceManagerMetrics::notifyClientCreated(const ClientInfoParcel& clientInfo) {
130 std::scoped_lock lock(mLock);
131 // Update the resource instance count.
132 std::map<std::string, int>::iterator found = mConcurrentResourceCountMap.find(clientInfo.name);
133 if (found == mConcurrentResourceCountMap.end()) {
134 mConcurrentResourceCountMap[clientInfo.name] = 1;
135 } else {
136 found->second++;
137 }
138}
139
140void ResourceManagerMetrics::notifyClientReleased(const ClientInfoParcel& clientInfo) {
141 bool stopCalled = true;
Girishc9637682023-03-23 23:33:32 +0000142 ClientConfigParcel clientConfig;
Girish1f002cf2023-02-17 00:36:29 +0000143 {
144 std::scoped_lock lock(mLock);
Girishc9637682023-03-23 23:33:32 +0000145 ClientConfigMap::iterator found = mClientConfigMap.find(clientInfo.id);
Girish1f002cf2023-02-17 00:36:29 +0000146 if (found != mClientConfigMap.end()) {
147 // Release is called without Stop!
148 stopCalled = false;
Girishc9637682023-03-23 23:33:32 +0000149 clientConfig = found->second;
150 // Update the timestamp for stopping the codec.
151 clientConfig.timeStamp = systemTime(SYSTEM_TIME_MONOTONIC) / 1000LL;
Girish1f002cf2023-02-17 00:36:29 +0000152 }
153 }
154 if (!stopCalled) {
155 // call Stop to update the metrics.
Girishc9637682023-03-23 23:33:32 +0000156 notifyClientStopped(clientConfig);
Girish1f002cf2023-02-17 00:36:29 +0000157 }
158 {
159 std::scoped_lock lock(mLock);
160 // Update the resource instance count also.
161 std::map<std::string, int>::iterator found =
162 mConcurrentResourceCountMap.find(clientInfo.name);
163 if (found != mConcurrentResourceCountMap.end()) {
164 if (found->second > 0) {
165 found->second--;
166 }
167 }
168 }
169}
170
Girishde8eb592023-04-13 18:49:17 +0000171void ResourceManagerMetrics::notifyClientConfigChanged(const ClientConfigParcel& clientConfig) {
172 std::scoped_lock lock(mLock);
173 ClientConfigMap::iterator entry = mClientConfigMap.find(clientConfig.clientInfo.id);
174 if (entry != mClientConfigMap.end() &&
Girisha5a2d672023-09-20 18:40:20 +0000175 (clientConfig.codecType == MediaResourceSubType::kHwVideoCodec ||
176 clientConfig.codecType == MediaResourceSubType::kSwVideoCodec ||
177 clientConfig.codecType == MediaResourceSubType::kHwImageCodec ||
178 clientConfig.codecType == MediaResourceSubType::kSwImageCodec)) {
Girishde8eb592023-04-13 18:49:17 +0000179 int pid = clientConfig.clientInfo.pid;
180 // Update the pixel count for this process
181 updatePixelCount(pid, clientConfig.width * (long)clientConfig.height,
182 entry->second.width * (long)entry->second.height);
183 // Update the resolution in the record.
184 entry->second.width = clientConfig.width;
185 entry->second.height = clientConfig.height;
186 }
187}
188
Girish1f002cf2023-02-17 00:36:29 +0000189void ResourceManagerMetrics::notifyClientStarted(const ClientConfigParcel& clientConfig) {
190 std::scoped_lock lock(mLock);
191 int pid = clientConfig.clientInfo.pid;
192 // We need to observer this process.
193 mUidObserver->add(pid, clientConfig.clientInfo.uid);
194
195 // Update the client config for thic client.
196 mClientConfigMap[clientConfig.clientInfo.id] = clientConfig;
197
198 // Update the concurrent codec count for this process.
Girisha5a2d672023-09-20 18:40:20 +0000199 CodecBucket codecBucket = getCodecBucket(clientConfig.isEncoder, clientConfig.codecType);
Girish1f002cf2023-02-17 00:36:29 +0000200 increaseConcurrentCodecs(pid, codecBucket);
201
Girisha5a2d672023-09-20 18:40:20 +0000202 if (clientConfig.codecType == MediaResourceSubType::kHwVideoCodec ||
203 clientConfig.codecType == MediaResourceSubType::kSwVideoCodec ||
204 clientConfig.codecType == MediaResourceSubType::kHwImageCodec ||
205 clientConfig.codecType == MediaResourceSubType::kSwImageCodec) {
Girish1f002cf2023-02-17 00:36:29 +0000206 // Update the pixel count for this process
207 increasePixelCount(pid, clientConfig.width * (long)clientConfig.height);
208 }
209
210 // System concurrent codec usage
Girishde8eb592023-04-13 18:49:17 +0000211 int systemConcurrentCodecs = mConcurrentCodecsMap[codecBucket];
Girish1f002cf2023-02-17 00:36:29 +0000212 // Process/Application concurrent codec usage for this type of codec
Girishde8eb592023-04-13 18:49:17 +0000213 const ConcurrentCodecs& concurrentCodecs = mProcessConcurrentCodecsMap[pid];
214 int appConcurrentCodecs = concurrentCodecs.mCurrent[codecBucket];
215 int hwVideoCodecs = concurrentCodecs.mHWVideoCodecs;
216 int swVideoCodecs = concurrentCodecs.mSWVideoCodecs;
217 int videoCodecs = concurrentCodecs.mVideoCodecs;
218 int audioCodecs = concurrentCodecs.mAudioCodecs;
219 int imageCodecs = concurrentCodecs.mImageCodecs;
Girish1f002cf2023-02-17 00:36:29 +0000220 // Process/Application's current pixel count.
221 long pixelCount = 0;
222 std::map<int32_t, PixelCount>::iterator it = mProcessPixelsMap.find(pid);
223 if (it != mProcessPixelsMap.end()) {
224 pixelCount = it->second.mCurrent;
225 }
226
227 int result = stats_write(
228 MEDIA_CODEC_STARTED,
229 clientConfig.clientInfo.uid,
230 clientConfig.id,
231 clientConfig.clientInfo.name.c_str(),
232 static_cast<int32_t>(clientConfig.codecType),
233 clientConfig.isEncoder,
Girisha5a2d672023-09-20 18:40:20 +0000234 isHardwareCodec(clientConfig.codecType),
Girish1f002cf2023-02-17 00:36:29 +0000235 clientConfig.width, clientConfig.height,
Girishde8eb592023-04-13 18:49:17 +0000236 systemConcurrentCodecs,
237 appConcurrentCodecs,
238 pixelCount,
239 hwVideoCodecs,
240 swVideoCodecs,
241 videoCodecs,
242 audioCodecs,
243 imageCodecs);
Girish1f002cf2023-02-17 00:36:29 +0000244
245 ALOGV("%s: Pushed MEDIA_CODEC_STARTED atom: "
246 "Process[pid(%d): uid(%d)] "
Girisha5a2d672023-09-20 18:40:20 +0000247 "Codec: [%s: %ju] is %s %s "
Girish1f002cf2023-02-17 00:36:29 +0000248 "Timestamp: %jd "
249 "Resolution: %d x %d "
250 "ConcurrentCodec[%d]={System: %d App: %d} "
Girishde8eb592023-04-13 18:49:17 +0000251 "AppConcurrentCodecs{Video: %d(HW[%d] SW[%d]) Audio: %d Image: %d} "
Girish1f002cf2023-02-17 00:36:29 +0000252 "result: %d",
253 __func__,
254 pid, clientConfig.clientInfo.uid,
255 clientConfig.clientInfo.name.c_str(),
256 clientConfig.id,
Girish1f002cf2023-02-17 00:36:29 +0000257 getCodecType(clientConfig.codecType),
258 clientConfig.isEncoder? "encoder" : "decoder",
259 clientConfig.timeStamp,
260 clientConfig.width, clientConfig.height,
Girishde8eb592023-04-13 18:49:17 +0000261 codecBucket, systemConcurrentCodecs, appConcurrentCodecs,
262 videoCodecs, hwVideoCodecs, swVideoCodecs, audioCodecs, imageCodecs,
Girish1f002cf2023-02-17 00:36:29 +0000263 result);
264}
265
266void ResourceManagerMetrics::notifyClientStopped(const ClientConfigParcel& clientConfig) {
267 std::scoped_lock lock(mLock);
268 int pid = clientConfig.clientInfo.pid;
269 // Update the concurrent codec count for this process.
Girisha5a2d672023-09-20 18:40:20 +0000270 CodecBucket codecBucket = getCodecBucket(clientConfig.isEncoder, clientConfig.codecType);
Girish1f002cf2023-02-17 00:36:29 +0000271 decreaseConcurrentCodecs(pid, codecBucket);
272
Girisha5a2d672023-09-20 18:40:20 +0000273 if (clientConfig.codecType == MediaResourceSubType::kHwVideoCodec ||
274 clientConfig.codecType == MediaResourceSubType::kSwVideoCodec ||
275 clientConfig.codecType == MediaResourceSubType::kHwImageCodec ||
276 clientConfig.codecType == MediaResourceSubType::kSwImageCodec) {
Girish1f002cf2023-02-17 00:36:29 +0000277 // Update the pixel count for this process
278 decreasePixelCount(pid, clientConfig.width * (long)clientConfig.height);
279 }
280
281 // System concurrent codec usage
Girishde8eb592023-04-13 18:49:17 +0000282 int systemConcurrentCodecs = mConcurrentCodecsMap[codecBucket];
Girish1f002cf2023-02-17 00:36:29 +0000283 // Process/Application concurrent codec usage for this type of codec
Girishde8eb592023-04-13 18:49:17 +0000284 int appConcurrentCodecs = 0;
Girish1f002cf2023-02-17 00:36:29 +0000285 std::map<int32_t, ConcurrentCodecs>::iterator found = mProcessConcurrentCodecsMap.find(pid);
286 if (found != mProcessConcurrentCodecsMap.end()) {
Girishde8eb592023-04-13 18:49:17 +0000287 appConcurrentCodecs = found->second.mCurrent[codecBucket];
Girish1f002cf2023-02-17 00:36:29 +0000288 }
289 // Process/Application's current pixel count.
290 long pixelCount = 0;
291 std::map<int32_t, PixelCount>::iterator it = mProcessPixelsMap.find(pid);
292 if (it != mProcessPixelsMap.end()) {
293 pixelCount = it->second.mCurrent;
294 }
295
296 // calculate the usageTime as:
297 // MediaCodecStopped.clientConfig.timeStamp -
298 // MediaCodecStarted.clientConfig.timeStamp
299 int64_t usageTime = 0;
300 ClientConfigMap::iterator entry = mClientConfigMap.find(clientConfig.clientInfo.id);
301 if (entry != mClientConfigMap.end()) {
302 usageTime = clientConfig.timeStamp - entry->second.timeStamp;
303 // And we can erase this config now.
304 mClientConfigMap.erase(entry);
305 } else {
306 ALOGW("%s: Start Config is missing!", __func__);
307 }
308
309 int result = stats_write(
310 MEDIA_CODEC_STOPPED,
311 clientConfig.clientInfo.uid,
312 clientConfig.id,
313 clientConfig.clientInfo.name.c_str(),
314 static_cast<int32_t>(clientConfig.codecType),
315 clientConfig.isEncoder,
Girisha5a2d672023-09-20 18:40:20 +0000316 isHardwareCodec(clientConfig.codecType),
Girish1f002cf2023-02-17 00:36:29 +0000317 clientConfig.width, clientConfig.height,
Girishde8eb592023-04-13 18:49:17 +0000318 systemConcurrentCodecs,
319 appConcurrentCodecs,
Girish1f002cf2023-02-17 00:36:29 +0000320 pixelCount,
321 usageTime);
322 ALOGV("%s: Pushed MEDIA_CODEC_STOPPED atom: "
323 "Process[pid(%d): uid(%d)] "
Girisha5a2d672023-09-20 18:40:20 +0000324 "Codec: [%s: %ju] is %s %s "
Girish1f002cf2023-02-17 00:36:29 +0000325 "Timestamp: %jd Usage time: %jd "
326 "Resolution: %d x %d "
327 "ConcurrentCodec[%d]={System: %d App: %d} "
328 "result: %d",
329 __func__,
330 pid, clientConfig.clientInfo.uid,
331 clientConfig.clientInfo.name.c_str(),
332 clientConfig.id,
Girish1f002cf2023-02-17 00:36:29 +0000333 getCodecType(clientConfig.codecType),
334 clientConfig.isEncoder? "encoder" : "decoder",
335 clientConfig.timeStamp, usageTime,
336 clientConfig.width, clientConfig.height,
Girishde8eb592023-04-13 18:49:17 +0000337 codecBucket, systemConcurrentCodecs, appConcurrentCodecs,
Girish1f002cf2023-02-17 00:36:29 +0000338 result);
339}
340
341void ResourceManagerMetrics::onProcessTerminated(int32_t pid, uid_t uid) {
342 std::scoped_lock lock(mLock);
343 // post MediaCodecConcurrentUsageReported for this terminated pid.
344 pushConcurrentUsageReport(pid, uid);
345}
346
347void ResourceManagerMetrics::pushConcurrentUsageReport(int32_t pid, uid_t uid) {
348 // Process/Application peak concurrent codec usage
349 std::map<int32_t, ConcurrentCodecs>::iterator found = mProcessConcurrentCodecsMap.find(pid);
350 if (found == mProcessConcurrentCodecsMap.end()) {
351 ALOGI("%s: No MEDIA_CODEC_CONCURRENT_USAGE_REPORTED atom Entry for: "
352 "Application[pid(%d): uid(%d)]", __func__, pid, uid);
353 return;
354 }
355 const ConcurrentCodecsMap& codecsMap = found->second.mPeak;
356 int peakHwAudioEncoderCount = codecsMap[HwAudioEncoder];
357 int peakHwAudioDecoderCount = codecsMap[HwAudioDecoder];
358 int peakHwVideoEncoderCount = codecsMap[HwVideoEncoder];
359 int peakHwVideoDecoderCount = codecsMap[HwVideoDecoder];
360 int peakHwImageEncoderCount = codecsMap[HwImageEncoder];
361 int peakHwImageDecoderCount = codecsMap[HwImageDecoder];
362 int peakSwAudioEncoderCount = codecsMap[SwAudioEncoder];
363 int peakSwAudioDecoderCount = codecsMap[SwAudioDecoder];
364 int peakSwVideoEncoderCount = codecsMap[SwVideoEncoder];
365 int peakSwVideoDecoderCount = codecsMap[SwVideoDecoder];
366 int peakSwImageEncoderCount = codecsMap[SwImageEncoder];
367 int peakSwImageDecoderCount = codecsMap[SwImageDecoder];
368
369 long peakPixels = 0;
370 std::map<int32_t, PixelCount>::iterator it = mProcessPixelsMap.find(pid);
371 if (it == mProcessPixelsMap.end()) {
372 ALOGI("%s: No Video Codec Entry for Application[pid(%d): uid(%d)]",
373 __func__, pid, uid);
374 } else {
375 peakPixels = it->second.mPeak;
376 }
377 std::string peakPixelsLog("Peak Pixels: " + std::to_string(peakPixels));
378
379 std::stringstream peakCodecLog;
380 peakCodecLog << "Peak { ";
381 std::stringstream logMsg;
382 if (getLogMessage(peakHwAudioEncoderCount, peakSwAudioEncoderCount, logMsg)) {
383 peakCodecLog << "AudioEnc[" << logMsg.str();
384 }
385 if (getLogMessage(peakHwAudioDecoderCount, peakSwAudioDecoderCount, logMsg)) {
386 peakCodecLog << "AudioDec[" << logMsg.str();
387 }
388 if (getLogMessage(peakHwVideoEncoderCount, peakSwVideoEncoderCount, logMsg)) {
389 peakCodecLog << "VideoEnc[" << logMsg.str();
390 }
391 if (getLogMessage(peakHwVideoDecoderCount, peakSwVideoDecoderCount, logMsg)) {
392 peakCodecLog << "VideoDec[" << logMsg.str();
393 }
394 if (getLogMessage(peakHwImageEncoderCount, peakSwImageEncoderCount, logMsg)) {
395 peakCodecLog << "ImageEnc[" << logMsg.str();
396 }
397 if (getLogMessage(peakHwImageDecoderCount, peakSwImageDecoderCount, logMsg)) {
398 peakCodecLog << "ImageDec[" << logMsg.str();
399 }
400 peakCodecLog << "}";
401
402#ifdef ENABLE_MEDIA_CODEC_CONCURRENT_USAGE_REPORTED
403 int result = stats_write(
404 MEDIA_CODEC_CONCURRENT_USAGE_REPORTED,
405 uid,
406 peakHwVideoDecoderCount,
407 peakHwVideoEncoderCount,
408 peakSwVideoDecoderCount,
409 peakSwVideoEncoderCount,
410 peakHwAudioDecoderCount,
411 peakHwAudioEncoderCount,
412 peakSwAudioDecoderCount,
413 peakSwAudioEncoderCount,
414 peakHwImageDecoderCount,
415 peakHwImageEncoderCount,
416 peakSwImageDecoderCount,
417 peakSwImageEncoderCount,
418 peakPixels);
419 ALOGI("%s: Pushed MEDIA_CODEC_CONCURRENT_USAGE_REPORTED atom: "
420 "Process[pid(%d): uid(%d)] %s %s result: %d",
421 __func__, pid, uid, peakCodecLog.str().c_str(), peakPixelsLog.c_str(), result);
422#else
423 ALOGI("%s: Concurrent Codec Usage Report for the Process[pid(%d): uid(%d)] is %s %s",
424 __func__, pid, uid, peakCodecLog.str().c_str(), peakPixelsLog.c_str());
425#endif
426}
427
428void ResourceManagerMetrics::pushReclaimAtom(const ClientInfoParcel& clientInfo,
Girish56fda312023-10-12 21:32:35 +0000429 const std::vector<int>& priorities,
430 const std::vector<ClientInfo>& targetClients,
431 bool reclaimed) {
Girish1f002cf2023-02-17 00:36:29 +0000432 // Construct the metrics for codec reclaim as a pushed atom.
433 // 1. Information about the requester.
434 // - UID and the priority (oom score)
435 int32_t callingPid = clientInfo.pid;
436 int32_t requesterUid = clientInfo.uid;
437 std::string clientName = clientInfo.name;
438 int requesterPriority = priorities[0];
439
440 // 2. Information about the codec.
441 // - Name of the codec requested
442 // - Number of concurrent codecs running.
443 int32_t noOfConcurrentCodecs = 0;
444 std::map<std::string, int>::iterator found = mConcurrentResourceCountMap.find(clientName);
445 if (found != mConcurrentResourceCountMap.end()) {
446 noOfConcurrentCodecs = found->second;
447 }
448
449 // 3. Information about the Reclaim:
450 // - Status of reclaim request
451 // - How many codecs are reclaimed
452 // - For each codecs reclaimed, information of the process that it belonged to:
453 // - UID and the Priority (oom score)
454 int32_t reclaimStatus = MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_SUCCESS;
455 if (!reclaimed) {
Girish56fda312023-10-12 21:32:35 +0000456 if (targetClients.size() == 0) {
Girish1f002cf2023-02-17 00:36:29 +0000457 // No clients to reclaim from
458 reclaimStatus =
459 MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
460 } else {
461 // Couldn't reclaim resources from the clients
462 reclaimStatus =
463 MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
464 }
465 }
Girish56fda312023-10-12 21:32:35 +0000466 int32_t noOfCodecsReclaimed = targetClients.size();
Girish1f002cf2023-02-17 00:36:29 +0000467 int32_t targetIndex = 1;
Girish56fda312023-10-12 21:32:35 +0000468 for (const ClientInfo& targetClient : targetClients) {
Girish1f002cf2023-02-17 00:36:29 +0000469 int targetPriority = priorities[targetIndex];
470 // Post the pushed atom
471 int result = stats_write(
472 MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED,
473 requesterUid,
474 requesterPriority,
475 clientName.c_str(),
476 noOfConcurrentCodecs,
477 reclaimStatus,
478 noOfCodecsReclaimed,
479 targetIndex,
Girish56fda312023-10-12 21:32:35 +0000480 targetClient.mUid,
Girish1f002cf2023-02-17 00:36:29 +0000481 targetPriority);
482 ALOGI("%s: Pushed MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED atom: "
483 "Requester[pid(%d): uid(%d): priority(%d)] "
484 "Codec: [%s] "
485 "No of concurrent codecs: %d "
486 "Reclaim Status: %d "
487 "No of codecs reclaimed: %d "
488 "Target[%d][pid(%d): uid(%d): priority(%d)] result: %d",
489 __func__, callingPid, requesterUid, requesterPriority,
490 clientName.c_str(), noOfConcurrentCodecs,
491 reclaimStatus, noOfCodecsReclaimed,
Girish56fda312023-10-12 21:32:35 +0000492 targetIndex, targetClient.mPid, targetClient.mUid, targetPriority, result);
Girish1f002cf2023-02-17 00:36:29 +0000493 targetIndex++;
494 }
495}
496
497void ResourceManagerMetrics::increaseConcurrentCodecs(int32_t pid,
498 CodecBucket codecBucket) {
499 // Increase the codec usage across the system.
500 mConcurrentCodecsMap[codecBucket]++;
501
502 // Now update the codec usage for this (pid) process.
503 std::map<int32_t, ConcurrentCodecs>::iterator found = mProcessConcurrentCodecsMap.find(pid);
504 if (found == mProcessConcurrentCodecsMap.end()) {
505 ConcurrentCodecs codecs;
506 codecs.mCurrent[codecBucket] = 1;
507 codecs.mPeak[codecBucket] = 1;
Girishde8eb592023-04-13 18:49:17 +0000508 auto added = mProcessConcurrentCodecsMap.emplace(pid, codecs);
509 found = added.first;
Girish1f002cf2023-02-17 00:36:29 +0000510 } else {
511 found->second.mCurrent[codecBucket]++;
512 // Check if it's the peak count for this slot.
513 if (found->second.mPeak[codecBucket] < found->second.mCurrent[codecBucket]) {
514 found->second.mPeak[codecBucket] = found->second.mCurrent[codecBucket];
515 }
516 }
Girishde8eb592023-04-13 18:49:17 +0000517
518 switch (codecBucket) {
519 case HwVideoEncoder:
520 case HwVideoDecoder:
521 case SwVideoEncoder:
522 case SwVideoDecoder:
523 if (codecBucket == HwVideoEncoder || codecBucket == HwVideoDecoder) {
524 found->second.mHWVideoCodecs++;
525 } else {
526 found->second.mSWVideoCodecs++;
527 }
528 found->second.mVideoCodecs++;
529 break;
530 case HwAudioEncoder:
531 case HwAudioDecoder:
532 case SwAudioEncoder:
533 case SwAudioDecoder:
534 found->second.mAudioCodecs++;
535 break;
536 case HwImageEncoder:
537 case HwImageDecoder:
538 case SwImageEncoder:
539 case SwImageDecoder:
540 found->second.mImageCodecs++;
541 break;
542 default:
543 break;
544 }
Girish1f002cf2023-02-17 00:36:29 +0000545}
546
547void ResourceManagerMetrics::decreaseConcurrentCodecs(int32_t pid,
548 CodecBucket codecBucket) {
549 // Decrease the codec usage across the system.
550 if (mConcurrentCodecsMap[codecBucket] > 0) {
551 mConcurrentCodecsMap[codecBucket]--;
552 }
553
554 // Now update the codec usage for this (pid) process.
555 std::map<int32_t, ConcurrentCodecs>::iterator found = mProcessConcurrentCodecsMap.find(pid);
556 if (found != mProcessConcurrentCodecsMap.end()) {
557 if (found->second.mCurrent[codecBucket] > 0) {
558 found->second.mCurrent[codecBucket]--;
559 }
Girishde8eb592023-04-13 18:49:17 +0000560
561 switch (codecBucket) {
562 case HwVideoEncoder:
563 case HwVideoDecoder:
564 case SwVideoEncoder:
565 case SwVideoDecoder:
566 if (codecBucket == HwVideoEncoder || codecBucket == HwVideoDecoder) {
567 found->second.mHWVideoCodecs--;
568 } else {
569 found->second.mSWVideoCodecs--;
570 }
571 found->second.mVideoCodecs--;
572 break;
573 case HwAudioEncoder:
574 case HwAudioDecoder:
575 case SwAudioEncoder:
576 case SwAudioDecoder:
577 found->second.mAudioCodecs--;
578 break;
579 case HwImageEncoder:
580 case HwImageDecoder:
581 case SwImageEncoder:
582 case SwImageDecoder:
583 found->second.mImageCodecs--;
584 break;
585 default:
586 break;
587 }
Girish1f002cf2023-02-17 00:36:29 +0000588 }
589}
590
591void ResourceManagerMetrics::increasePixelCount(int32_t pid, long pixels) {
592 // Now update the current pixel usage for this (pid) process.
593 std::map<int32_t, PixelCount>::iterator found = mProcessPixelsMap.find(pid);
594 if (found == mProcessPixelsMap.end()) {
595 PixelCount pixelCount {pixels, pixels};
596 mProcessPixelsMap.emplace(pid, pixelCount);
597 } else {
598 if (__builtin_add_overflow(found->second.mCurrent, pixels, &found->second.mCurrent)) {
599 ALOGI("Pixel Count overflow");
600 return;
601 }
602 // Check if it's the peak count for this slot.
603 if (found->second.mPeak < found->second.mCurrent) {
604 found->second.mPeak = found->second.mCurrent;
605 }
606 }
607}
608
Girishde8eb592023-04-13 18:49:17 +0000609void ResourceManagerMetrics::updatePixelCount(int32_t pid, long newPixels, long lastPixels) {
610 // Since there is change in resolution, decrease it by last pixels and
611 // increase it by new pixels.
612 decreasePixelCount(pid, lastPixels);
613 increasePixelCount(pid, newPixels);
614}
615
Girish1f002cf2023-02-17 00:36:29 +0000616void ResourceManagerMetrics::decreasePixelCount(int32_t pid, long pixels) {
617 // Now update the current pixel usage for this (pid) process.
618 std::map<int32_t, PixelCount>::iterator found = mProcessPixelsMap.find(pid);
619 if (found != mProcessPixelsMap.end()) {
620 if (found->second.mCurrent < pixels) {
621 found->second.mCurrent = 0;
622 } else {
623 if (__builtin_sub_overflow(found->second.mCurrent, pixels, &found->second.mCurrent)) {
624 ALOGI("Pixel Count overflow");
625 return;
626 }
627 }
628 }
629}
630
631long ResourceManagerMetrics::getPeakConcurrentPixelCount(int pid) const {
632 std::map<int32_t, PixelCount>::const_iterator found = mProcessPixelsMap.find(pid);
633 if (found != mProcessPixelsMap.end()) {
634 return found->second.mPeak;
635 }
636
637 return 0;
638}
639
640long ResourceManagerMetrics::getCurrentConcurrentPixelCount(int pid) const {
641 std::map<int32_t, PixelCount>::const_iterator found = mProcessPixelsMap.find(pid);
642 if (found != mProcessPixelsMap.end()) {
643 return found->second.mCurrent;
644 }
645
646 return 0;
647}
648
649} // namespace android