• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
31 namespace android {
32 
33 using stats::media_metrics::stats_write;
34 using stats::media_metrics::MEDIA_CODEC_STARTED;
35 using stats::media_metrics::MEDIA_CODEC_STOPPED;
36 // Disabling this for now.
37 #ifdef ENABLE_MEDIA_CODEC_CONCURRENT_USAGE_REPORTED
38 using stats::media_metrics::MEDIA_CODEC_CONCURRENT_USAGE_REPORTED;
39 #endif
40 using stats::media_metrics::MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED;
41 using stats::media_metrics::MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_SUCCESS;
42 using stats::media_metrics::\
43     MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
44 using stats::media_metrics::\
45     MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
46 
getCodecType(MediaResourceSubType codecType)47 inline const char* getCodecType(MediaResourceSubType codecType) {
48     switch (codecType) {
49         case MediaResourceSubType::kAudioCodec:         return "Audio";
50         case MediaResourceSubType::kVideoCodec:         return "Video";
51         case MediaResourceSubType::kImageCodec:         return "Image";
52         case MediaResourceSubType::kUnspecifiedSubType:
53         default:
54                                                         return "Unspecified";
55     }
56     return "Unspecified";
57 }
58 
getCodecBucket(bool isHardware,bool isEncoder,MediaResourceSubType codecType)59 static CodecBucket getCodecBucket(bool isHardware,
60                                   bool isEncoder,
61                                   MediaResourceSubType codecType) {
62     if (isHardware) {
63         switch (codecType) {
64             case MediaResourceSubType::kAudioCodec:
65                 if (isEncoder) return HwAudioEncoder;
66                 return HwAudioDecoder;
67             case MediaResourceSubType::kVideoCodec:
68                 if (isEncoder) return HwVideoEncoder;
69                 return HwVideoDecoder;
70             case MediaResourceSubType::kImageCodec:
71                 if (isEncoder) return HwImageEncoder;
72                 return HwImageDecoder;
73             case MediaResourceSubType::kUnspecifiedSubType:
74             default:
75                 return CodecBucketUnspecified;
76         }
77     } else {
78         switch (codecType) {
79             case MediaResourceSubType::kAudioCodec:
80                 if (isEncoder) return SwAudioEncoder;
81                 return SwAudioDecoder;
82             case MediaResourceSubType::kVideoCodec:
83                 if (isEncoder) return SwVideoEncoder;
84                 return SwVideoDecoder;
85             case MediaResourceSubType::kImageCodec:
86                 if (isEncoder) return SwImageEncoder;
87                 return SwImageDecoder;
88             case MediaResourceSubType::kUnspecifiedSubType:
89             default:
90                 return CodecBucketUnspecified;
91         }
92     }
93 
94     return CodecBucketUnspecified;
95 }
96 
getLogMessage(int hwCount,int swCount,std::stringstream & logMsg)97 static bool getLogMessage(int hwCount, int swCount, std::stringstream& logMsg) {
98     bool update = false;
99     logMsg.clear();
100 
101     if (hwCount > 0) {
102         logMsg << " HW: " << hwCount;
103         update = true;
104     }
105     if (swCount > 0) {
106         logMsg << " SW: " << swCount;
107         update = true;
108     }
109 
110     if (update) {
111         logMsg << " ] ";
112     }
113     return update;
114 }
115 
ResourceManagerMetrics(const sp<ProcessInfoInterface> & processInfo)116 ResourceManagerMetrics::ResourceManagerMetrics(const sp<ProcessInfoInterface>& processInfo) {
117     // Create a process termination watcher, with 5seconds of polling frequency.
118     mUidObserver = sp<UidObserver>::make(processInfo,
119         [this] (int32_t pid, uid_t uid) {
120             onProcessTerminated(pid, uid);
121         });
122     mUidObserver->start();
123 }
124 
~ResourceManagerMetrics()125 ResourceManagerMetrics::~ResourceManagerMetrics() {
126     mUidObserver->stop();
127 }
128 
addPid(int pid,uid_t uid)129 void ResourceManagerMetrics::addPid(int pid, uid_t uid) {
130     if (uid != 0) {
131         std::scoped_lock lock(mLock);
132         mUidObserver->add(pid, uid);
133     }
134 }
135 
notifyClientCreated(const ClientInfoParcel & clientInfo)136 void ResourceManagerMetrics::notifyClientCreated(const ClientInfoParcel& clientInfo) {
137     std::scoped_lock lock(mLock);
138     // Update the resource instance count.
139     std::map<std::string, int>::iterator found = mConcurrentResourceCountMap.find(clientInfo.name);
140     if (found == mConcurrentResourceCountMap.end()) {
141         mConcurrentResourceCountMap[clientInfo.name] = 1;
142     } else {
143         found->second++;
144     }
145 }
146 
notifyClientReleased(const ClientInfoParcel & clientInfo)147 void ResourceManagerMetrics::notifyClientReleased(const ClientInfoParcel& clientInfo) {
148     bool stopCalled = true;
149     ClientConfigParcel clientConfig;
150     {
151         std::scoped_lock lock(mLock);
152         ClientConfigMap::iterator found = mClientConfigMap.find(clientInfo.id);
153         if (found != mClientConfigMap.end()) {
154             // Release is called without Stop!
155             stopCalled = false;
156             clientConfig = found->second;
157             // Update the timestamp for stopping the codec.
158             clientConfig.timeStamp = systemTime(SYSTEM_TIME_MONOTONIC) / 1000LL;
159         }
160     }
161     if (!stopCalled) {
162         // call Stop to update the metrics.
163         notifyClientStopped(clientConfig);
164     }
165     {
166         std::scoped_lock lock(mLock);
167         // Update the resource instance count also.
168         std::map<std::string, int>::iterator found =
169             mConcurrentResourceCountMap.find(clientInfo.name);
170         if (found != mConcurrentResourceCountMap.end()) {
171             if (found->second > 0) {
172                 found->second--;
173             }
174         }
175     }
176 }
177 
notifyClientConfigChanged(const ClientConfigParcel & clientConfig)178 void ResourceManagerMetrics::notifyClientConfigChanged(const ClientConfigParcel& clientConfig) {
179     std::scoped_lock lock(mLock);
180     ClientConfigMap::iterator entry = mClientConfigMap.find(clientConfig.clientInfo.id);
181     if (entry != mClientConfigMap.end() &&
182         (clientConfig.codecType == MediaResourceSubType::kVideoCodec ||
183         clientConfig.codecType == MediaResourceSubType::kImageCodec)) {
184         int pid = clientConfig.clientInfo.pid;
185         // Update the pixel count for this process
186         updatePixelCount(pid, clientConfig.width * (long)clientConfig.height,
187                          entry->second.width * (long)entry->second.height);
188         // Update the resolution in the record.
189         entry->second.width = clientConfig.width;
190         entry->second.height = clientConfig.height;
191     }
192 }
193 
notifyClientStarted(const ClientConfigParcel & clientConfig)194 void ResourceManagerMetrics::notifyClientStarted(const ClientConfigParcel& clientConfig) {
195     std::scoped_lock lock(mLock);
196     int pid = clientConfig.clientInfo.pid;
197     // We need to observer this process.
198     mUidObserver->add(pid, clientConfig.clientInfo.uid);
199 
200     // Update the client config for thic client.
201     mClientConfigMap[clientConfig.clientInfo.id] = clientConfig;
202 
203     // Update the concurrent codec count for this process.
204     CodecBucket codecBucket = getCodecBucket(clientConfig.isHardware,
205                                              clientConfig.isEncoder,
206                                              clientConfig.codecType);
207     increaseConcurrentCodecs(pid, codecBucket);
208 
209     if (clientConfig.codecType == MediaResourceSubType::kVideoCodec ||
210         clientConfig.codecType == MediaResourceSubType::kImageCodec) {
211         // Update the pixel count for this process
212         increasePixelCount(pid, clientConfig.width * (long)clientConfig.height);
213     }
214 
215     // System concurrent codec usage
216     int systemConcurrentCodecs = mConcurrentCodecsMap[codecBucket];
217     // Process/Application concurrent codec usage for this type of codec
218     const ConcurrentCodecs& concurrentCodecs = mProcessConcurrentCodecsMap[pid];
219     int appConcurrentCodecs = concurrentCodecs.mCurrent[codecBucket];
220     int hwVideoCodecs = concurrentCodecs.mHWVideoCodecs;
221     int swVideoCodecs = concurrentCodecs.mSWVideoCodecs;
222     int videoCodecs = concurrentCodecs.mVideoCodecs;
223     int audioCodecs = concurrentCodecs.mAudioCodecs;
224     int imageCodecs = concurrentCodecs.mImageCodecs;
225     // Process/Application's current pixel count.
226     long pixelCount = 0;
227     std::map<int32_t, PixelCount>::iterator it = mProcessPixelsMap.find(pid);
228     if (it != mProcessPixelsMap.end()) {
229         pixelCount = it->second.mCurrent;
230     }
231 
232     int result = stats_write(
233          MEDIA_CODEC_STARTED,
234          clientConfig.clientInfo.uid,
235          clientConfig.id,
236          clientConfig.clientInfo.name.c_str(),
237          static_cast<int32_t>(clientConfig.codecType),
238          clientConfig.isEncoder,
239          clientConfig.isHardware,
240          clientConfig.width, clientConfig.height,
241          systemConcurrentCodecs,
242          appConcurrentCodecs,
243          pixelCount,
244          hwVideoCodecs,
245          swVideoCodecs,
246          videoCodecs,
247          audioCodecs,
248          imageCodecs);
249 
250     ALOGV("%s: Pushed MEDIA_CODEC_STARTED atom: "
251           "Process[pid(%d): uid(%d)] "
252           "Codec: [%s: %ju] is %s %s %s "
253           "Timestamp: %jd "
254           "Resolution: %d x %d "
255           "ConcurrentCodec[%d]={System: %d App: %d} "
256           "AppConcurrentCodecs{Video: %d(HW[%d] SW[%d]) Audio: %d Image: %d} "
257           "result: %d",
258           __func__,
259           pid, clientConfig.clientInfo.uid,
260           clientConfig.clientInfo.name.c_str(),
261           clientConfig.id,
262           clientConfig.isHardware? "hardware" : "software",
263           getCodecType(clientConfig.codecType),
264           clientConfig.isEncoder? "encoder" : "decoder",
265           clientConfig.timeStamp,
266           clientConfig.width, clientConfig.height,
267           codecBucket, systemConcurrentCodecs, appConcurrentCodecs,
268           videoCodecs, hwVideoCodecs, swVideoCodecs, audioCodecs, imageCodecs,
269           result);
270 }
271 
notifyClientStopped(const ClientConfigParcel & clientConfig)272 void ResourceManagerMetrics::notifyClientStopped(const ClientConfigParcel& clientConfig) {
273     std::scoped_lock lock(mLock);
274     int pid = clientConfig.clientInfo.pid;
275     // Update the concurrent codec count for this process.
276     CodecBucket codecBucket = getCodecBucket(clientConfig.isHardware,
277                                              clientConfig.isEncoder,
278                                              clientConfig.codecType);
279     decreaseConcurrentCodecs(pid, codecBucket);
280 
281     if (clientConfig.codecType == MediaResourceSubType::kVideoCodec ||
282         clientConfig.codecType == MediaResourceSubType::kImageCodec) {
283         // Update the pixel count for this process
284         decreasePixelCount(pid, clientConfig.width * (long)clientConfig.height);
285     }
286 
287     // System concurrent codec usage
288     int systemConcurrentCodecs = mConcurrentCodecsMap[codecBucket];
289     // Process/Application concurrent codec usage for this type of codec
290     int appConcurrentCodecs = 0;
291     std::map<int32_t, ConcurrentCodecs>::iterator found = mProcessConcurrentCodecsMap.find(pid);
292     if (found != mProcessConcurrentCodecsMap.end()) {
293         appConcurrentCodecs = found->second.mCurrent[codecBucket];
294     }
295     // Process/Application's current pixel count.
296     long pixelCount = 0;
297     std::map<int32_t, PixelCount>::iterator it = mProcessPixelsMap.find(pid);
298     if (it != mProcessPixelsMap.end()) {
299         pixelCount = it->second.mCurrent;
300     }
301 
302     // calculate the usageTime as:
303     //  MediaCodecStopped.clientConfig.timeStamp -
304     //  MediaCodecStarted.clientConfig.timeStamp
305     int64_t usageTime = 0;
306     ClientConfigMap::iterator entry = mClientConfigMap.find(clientConfig.clientInfo.id);
307     if (entry != mClientConfigMap.end()) {
308         usageTime = clientConfig.timeStamp - entry->second.timeStamp;
309         // And we can erase this config now.
310         mClientConfigMap.erase(entry);
311     } else {
312         ALOGW("%s: Start Config is missing!", __func__);
313     }
314 
315      int result = stats_write(
316          MEDIA_CODEC_STOPPED,
317          clientConfig.clientInfo.uid,
318          clientConfig.id,
319          clientConfig.clientInfo.name.c_str(),
320          static_cast<int32_t>(clientConfig.codecType),
321          clientConfig.isEncoder,
322          clientConfig.isHardware,
323          clientConfig.width, clientConfig.height,
324          systemConcurrentCodecs,
325          appConcurrentCodecs,
326          pixelCount,
327          usageTime);
328     ALOGV("%s: Pushed MEDIA_CODEC_STOPPED atom: "
329           "Process[pid(%d): uid(%d)] "
330           "Codec: [%s: %ju] is %s %s %s "
331           "Timestamp: %jd Usage time: %jd "
332           "Resolution: %d x %d "
333           "ConcurrentCodec[%d]={System: %d App: %d} "
334           "result: %d",
335           __func__,
336           pid, clientConfig.clientInfo.uid,
337           clientConfig.clientInfo.name.c_str(),
338           clientConfig.id,
339           clientConfig.isHardware? "hardware" : "software",
340           getCodecType(clientConfig.codecType),
341           clientConfig.isEncoder? "encoder" : "decoder",
342           clientConfig.timeStamp, usageTime,
343           clientConfig.width, clientConfig.height,
344           codecBucket, systemConcurrentCodecs, appConcurrentCodecs,
345           result);
346 }
347 
onProcessTerminated(int32_t pid,uid_t uid)348 void ResourceManagerMetrics::onProcessTerminated(int32_t pid, uid_t uid) {
349     std::scoped_lock lock(mLock);
350     // post MediaCodecConcurrentUsageReported for this terminated pid.
351     pushConcurrentUsageReport(pid, uid);
352 }
353 
pushConcurrentUsageReport(int32_t pid,uid_t uid)354 void ResourceManagerMetrics::pushConcurrentUsageReport(int32_t pid, uid_t uid) {
355     // Process/Application peak concurrent codec usage
356     std::map<int32_t, ConcurrentCodecs>::iterator found = mProcessConcurrentCodecsMap.find(pid);
357     if (found == mProcessConcurrentCodecsMap.end()) {
358         ALOGI("%s: No MEDIA_CODEC_CONCURRENT_USAGE_REPORTED atom Entry for: "
359               "Application[pid(%d): uid(%d)]", __func__, pid, uid);
360         return;
361     }
362     const ConcurrentCodecsMap& codecsMap = found->second.mPeak;
363     int peakHwAudioEncoderCount = codecsMap[HwAudioEncoder];
364     int peakHwAudioDecoderCount = codecsMap[HwAudioDecoder];
365     int peakHwVideoEncoderCount = codecsMap[HwVideoEncoder];
366     int peakHwVideoDecoderCount = codecsMap[HwVideoDecoder];
367     int peakHwImageEncoderCount = codecsMap[HwImageEncoder];
368     int peakHwImageDecoderCount = codecsMap[HwImageDecoder];
369     int peakSwAudioEncoderCount = codecsMap[SwAudioEncoder];
370     int peakSwAudioDecoderCount = codecsMap[SwAudioDecoder];
371     int peakSwVideoEncoderCount = codecsMap[SwVideoEncoder];
372     int peakSwVideoDecoderCount = codecsMap[SwVideoDecoder];
373     int peakSwImageEncoderCount = codecsMap[SwImageEncoder];
374     int peakSwImageDecoderCount = codecsMap[SwImageDecoder];
375 
376     long peakPixels = 0;
377     std::map<int32_t, PixelCount>::iterator it = mProcessPixelsMap.find(pid);
378     if (it == mProcessPixelsMap.end()) {
379         ALOGI("%s: No Video Codec Entry for Application[pid(%d): uid(%d)]",
380               __func__, pid, uid);
381     } else {
382         peakPixels = it->second.mPeak;
383     }
384     std::string peakPixelsLog("Peak Pixels: " + std::to_string(peakPixels));
385 
386     std::stringstream peakCodecLog;
387     peakCodecLog << "Peak { ";
388     std::stringstream logMsg;
389     if (getLogMessage(peakHwAudioEncoderCount, peakSwAudioEncoderCount, logMsg)) {
390         peakCodecLog << "AudioEnc[" << logMsg.str();
391     }
392     if (getLogMessage(peakHwAudioDecoderCount, peakSwAudioDecoderCount, logMsg)) {
393         peakCodecLog << "AudioDec[" << logMsg.str();
394     }
395     if (getLogMessage(peakHwVideoEncoderCount, peakSwVideoEncoderCount, logMsg)) {
396         peakCodecLog << "VideoEnc[" << logMsg.str();
397     }
398     if (getLogMessage(peakHwVideoDecoderCount, peakSwVideoDecoderCount, logMsg)) {
399         peakCodecLog << "VideoDec[" << logMsg.str();
400     }
401     if (getLogMessage(peakHwImageEncoderCount, peakSwImageEncoderCount, logMsg)) {
402         peakCodecLog << "ImageEnc[" << logMsg.str();
403     }
404     if (getLogMessage(peakHwImageDecoderCount, peakSwImageDecoderCount, logMsg)) {
405         peakCodecLog << "ImageDec[" << logMsg.str();
406     }
407     peakCodecLog << "}";
408 
409 #ifdef ENABLE_MEDIA_CODEC_CONCURRENT_USAGE_REPORTED
410     int result = stats_write(
411         MEDIA_CODEC_CONCURRENT_USAGE_REPORTED,
412         uid,
413         peakHwVideoDecoderCount,
414         peakHwVideoEncoderCount,
415         peakSwVideoDecoderCount,
416         peakSwVideoEncoderCount,
417         peakHwAudioDecoderCount,
418         peakHwAudioEncoderCount,
419         peakSwAudioDecoderCount,
420         peakSwAudioEncoderCount,
421         peakHwImageDecoderCount,
422         peakHwImageEncoderCount,
423         peakSwImageDecoderCount,
424         peakSwImageEncoderCount,
425         peakPixels);
426     ALOGI("%s: Pushed MEDIA_CODEC_CONCURRENT_USAGE_REPORTED atom: "
427           "Process[pid(%d): uid(%d)] %s %s result: %d",
428           __func__, pid, uid, peakCodecLog.str().c_str(), peakPixelsLog.c_str(), result);
429 #else
430     ALOGI("%s: Concurrent Codec Usage Report for the Process[pid(%d): uid(%d)] is %s %s",
431           __func__, pid, uid, peakCodecLog.str().c_str(), peakPixelsLog.c_str());
432 #endif
433 }
434 
pushReclaimAtom(const ClientInfoParcel & clientInfo,const std::vector<int> & priorities,const Vector<std::shared_ptr<IResourceManagerClient>> & clients,const PidUidVector & idList,bool reclaimed)435 void ResourceManagerMetrics::pushReclaimAtom(const ClientInfoParcel& clientInfo,
436                         const std::vector<int>& priorities,
437                         const Vector<std::shared_ptr<IResourceManagerClient>>& clients,
438                         const PidUidVector& idList, bool reclaimed) {
439     // Construct the metrics for codec reclaim as a pushed atom.
440     // 1. Information about the requester.
441     //  - UID and the priority (oom score)
442     int32_t callingPid = clientInfo.pid;
443     int32_t requesterUid = clientInfo.uid;
444     std::string clientName = clientInfo.name;
445     int requesterPriority = priorities[0];
446 
447     //  2. Information about the codec.
448     //  - Name of the codec requested
449     //  - Number of concurrent codecs running.
450     int32_t noOfConcurrentCodecs = 0;
451     std::map<std::string, int>::iterator found = mConcurrentResourceCountMap.find(clientName);
452     if (found != mConcurrentResourceCountMap.end()) {
453         noOfConcurrentCodecs = found->second;
454     }
455 
456     // 3. Information about the Reclaim:
457     // - Status of reclaim request
458     // - How many codecs are reclaimed
459     // - For each codecs reclaimed, information of the process that it belonged to:
460     //    - UID and the Priority (oom score)
461     int32_t reclaimStatus = MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_SUCCESS;
462     if (!reclaimed) {
463       if (clients.size() == 0) {
464         // No clients to reclaim from
465         reclaimStatus =
466             MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
467       } else {
468         // Couldn't reclaim resources from the clients
469         reclaimStatus =
470             MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
471       }
472     }
473     int32_t noOfCodecsReclaimed = clients.size();
474     int32_t targetIndex = 1;
475     for (PidUidVector::const_reference id : idList) {
476         int32_t targetUid = id.second;
477         int targetPriority = priorities[targetIndex];
478         // Post the pushed atom
479         int result = stats_write(
480             MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED,
481             requesterUid,
482             requesterPriority,
483             clientName.c_str(),
484             noOfConcurrentCodecs,
485             reclaimStatus,
486             noOfCodecsReclaimed,
487             targetIndex,
488             targetUid,
489             targetPriority);
490         ALOGI("%s: Pushed MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED atom: "
491               "Requester[pid(%d): uid(%d): priority(%d)] "
492               "Codec: [%s] "
493               "No of concurrent codecs: %d "
494               "Reclaim Status: %d "
495               "No of codecs reclaimed: %d "
496               "Target[%d][pid(%d): uid(%d): priority(%d)] result: %d",
497               __func__, callingPid, requesterUid, requesterPriority,
498               clientName.c_str(), noOfConcurrentCodecs,
499               reclaimStatus, noOfCodecsReclaimed,
500               targetIndex, id.first, targetUid, targetPriority, result);
501         targetIndex++;
502     }
503 }
504 
increaseConcurrentCodecs(int32_t pid,CodecBucket codecBucket)505 void ResourceManagerMetrics::increaseConcurrentCodecs(int32_t pid,
506                                                       CodecBucket codecBucket) {
507     // Increase the codec usage across the system.
508     mConcurrentCodecsMap[codecBucket]++;
509 
510     // Now update the codec usage for this (pid) process.
511     std::map<int32_t, ConcurrentCodecs>::iterator found = mProcessConcurrentCodecsMap.find(pid);
512     if (found == mProcessConcurrentCodecsMap.end()) {
513         ConcurrentCodecs codecs;
514         codecs.mCurrent[codecBucket] = 1;
515         codecs.mPeak[codecBucket] = 1;
516         auto added = mProcessConcurrentCodecsMap.emplace(pid, codecs);
517         found = added.first;
518     } else {
519         found->second.mCurrent[codecBucket]++;
520         // Check if it's the peak count for this slot.
521         if (found->second.mPeak[codecBucket] < found->second.mCurrent[codecBucket]) {
522             found->second.mPeak[codecBucket] = found->second.mCurrent[codecBucket];
523         }
524     }
525 
526     switch (codecBucket) {
527         case HwVideoEncoder:
528         case HwVideoDecoder:
529         case SwVideoEncoder:
530         case SwVideoDecoder:
531             if (codecBucket == HwVideoEncoder || codecBucket == HwVideoDecoder) {
532                 found->second.mHWVideoCodecs++;
533             } else {
534                 found->second.mSWVideoCodecs++;
535             }
536             found->second.mVideoCodecs++;
537             break;
538         case HwAudioEncoder:
539         case HwAudioDecoder:
540         case SwAudioEncoder:
541         case SwAudioDecoder:
542             found->second.mAudioCodecs++;
543             break;
544         case HwImageEncoder:
545         case HwImageDecoder:
546         case SwImageEncoder:
547         case SwImageDecoder:
548             found->second.mImageCodecs++;
549             break;
550         default:
551             break;
552     }
553 }
554 
decreaseConcurrentCodecs(int32_t pid,CodecBucket codecBucket)555 void ResourceManagerMetrics::decreaseConcurrentCodecs(int32_t pid,
556                                                       CodecBucket codecBucket) {
557     // Decrease the codec usage across the system.
558     if (mConcurrentCodecsMap[codecBucket] > 0) {
559         mConcurrentCodecsMap[codecBucket]--;
560     }
561 
562     // Now update the codec usage for this (pid) process.
563     std::map<int32_t, ConcurrentCodecs>::iterator found = mProcessConcurrentCodecsMap.find(pid);
564     if (found != mProcessConcurrentCodecsMap.end()) {
565         if (found->second.mCurrent[codecBucket] > 0) {
566             found->second.mCurrent[codecBucket]--;
567         }
568 
569         switch (codecBucket) {
570             case HwVideoEncoder:
571             case HwVideoDecoder:
572             case SwVideoEncoder:
573             case SwVideoDecoder:
574                 if (codecBucket == HwVideoEncoder || codecBucket == HwVideoDecoder) {
575                     found->second.mHWVideoCodecs--;
576                 } else {
577                     found->second.mSWVideoCodecs--;
578                 }
579                 found->second.mVideoCodecs--;
580                 break;
581             case HwAudioEncoder:
582             case HwAudioDecoder:
583             case SwAudioEncoder:
584             case SwAudioDecoder:
585                 found->second.mAudioCodecs--;
586                 break;
587             case HwImageEncoder:
588             case HwImageDecoder:
589             case SwImageEncoder:
590             case SwImageDecoder:
591                 found->second.mImageCodecs--;
592                 break;
593             default:
594                 break;
595         }
596     }
597 }
598 
increasePixelCount(int32_t pid,long pixels)599 void ResourceManagerMetrics::increasePixelCount(int32_t pid, long pixels) {
600     // Now update the current pixel usage for this (pid) process.
601     std::map<int32_t, PixelCount>::iterator found = mProcessPixelsMap.find(pid);
602     if (found == mProcessPixelsMap.end()) {
603         PixelCount pixelCount {pixels, pixels};
604         mProcessPixelsMap.emplace(pid, pixelCount);
605     } else {
606         if (__builtin_add_overflow(found->second.mCurrent, pixels, &found->second.mCurrent)) {
607             ALOGI("Pixel Count overflow");
608             return;
609         }
610         // Check if it's the peak count for this slot.
611         if (found->second.mPeak < found->second.mCurrent) {
612             found->second.mPeak = found->second.mCurrent;
613         }
614     }
615 }
616 
updatePixelCount(int32_t pid,long newPixels,long lastPixels)617 void ResourceManagerMetrics::updatePixelCount(int32_t pid, long newPixels, long lastPixels) {
618     // Since there is change in resolution, decrease it by last pixels and
619     // increase it by new pixels.
620     decreasePixelCount(pid, lastPixels);
621     increasePixelCount(pid, newPixels);
622 }
623 
decreasePixelCount(int32_t pid,long pixels)624 void ResourceManagerMetrics::decreasePixelCount(int32_t pid, long pixels) {
625     // Now update the current pixel usage for this (pid) process.
626     std::map<int32_t, PixelCount>::iterator found = mProcessPixelsMap.find(pid);
627     if (found != mProcessPixelsMap.end()) {
628         if (found->second.mCurrent < pixels) {
629             found->second.mCurrent = 0;
630         } else {
631             if (__builtin_sub_overflow(found->second.mCurrent, pixels, &found->second.mCurrent)) {
632                 ALOGI("Pixel Count overflow");
633                 return;
634             }
635         }
636     }
637 }
638 
getPeakConcurrentPixelCount(int pid) const639 long ResourceManagerMetrics::getPeakConcurrentPixelCount(int pid) const {
640     std::map<int32_t, PixelCount>::const_iterator found = mProcessPixelsMap.find(pid);
641     if (found != mProcessPixelsMap.end()) {
642         return found->second.mPeak;
643     }
644 
645     return 0;
646 }
647 
getCurrentConcurrentPixelCount(int pid) const648 long ResourceManagerMetrics::getCurrentConcurrentPixelCount(int pid) const {
649     std::map<int32_t, PixelCount>::const_iterator found = mProcessPixelsMap.find(pid);
650     if (found != mProcessPixelsMap.end()) {
651         return found->second.mCurrent;
652     }
653 
654     return 0;
655 }
656 
657 } // namespace android
658