implementing concurrent codec metrics

Following changes are made in this CL:
- extend IResourceManagerService interface to allow:
  - notify create/start/stop of codecs
- implement concurrent codec metrics with different
  buckets (such as different resolution, codec type)
  for all the application/process and for the system.
- push the codec concurrency metrics to statsd
- move all metrics to a different class
- update codec reported metrics with codec id

Bug: 265488359
Test: atest cts/tests/media/misc/src/android/media/misc/cts/ResourceManagerTest.java
      /data/nativetest64/ResourceManagerService_test/ResourceManagerService_test
      /data/nativetest64/ResourceObserverService_test/ResourceObserverService_test
      refactoring CL. Existing unit tests still pass.
Merged-In: Ibaa1fb9607e486f2eb79bf02d79c630e09d62b4a
Change-Id: Ibaa1fb9607e486f2eb79bf02d79c630e09d62b4a
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 5582528..803bfec 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -26,31 +26,24 @@
 #include <cutils/sched_policy.h>
 #include <dirent.h>
 #include <media/MediaResourcePolicy.h>
-#include <media/stagefright/ProcessInfo.h>
+#include <media/stagefright/foundation/ABase.h>
 #include <mediautils/BatteryNotifier.h>
+#include <mediautils/ProcessInfo.h>
 #include <mediautils/SchedulingPolicyService.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <unistd.h>
-#include <stats_media_metrics.h>
 
 #include "IMediaResourceMonitor.h"
+#include "ResourceManagerMetrics.h"
 #include "ResourceManagerService.h"
 #include "ResourceObserverService.h"
 #include "ServiceLog.h"
 
 namespace android {
 
-using stats::media_metrics::stats_write;
-using stats::media_metrics::MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED;
-using stats::media_metrics::MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_SUCCESS;
-using stats::media_metrics::\
-    MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
-using stats::media_metrics::\
-    MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
-
 //static
 std::mutex ResourceManagerService::sCookieLock;
 //static
@@ -60,8 +53,8 @@
 
 class DeathNotifier : public RefBase {
 public:
-    DeathNotifier(const std::shared_ptr<ResourceManagerService> &service, int pid,
-            int64_t clientId);
+    DeathNotifier(const std::shared_ptr<ResourceManagerService> &service,
+                  const ClientInfoParcel& clientInfo);
 
     virtual ~DeathNotifier() {}
 
@@ -71,13 +64,12 @@
 
 protected:
     std::weak_ptr<ResourceManagerService> mService;
-    int mPid;
-    int64_t mClientId;
+    const ClientInfoParcel mClientInfo;
 };
 
 DeathNotifier::DeathNotifier(const std::shared_ptr<ResourceManagerService> &service,
-        int pid, int64_t clientId)
-    : mService(service), mPid(pid), mClientId(clientId) {}
+                             const ClientInfoParcel& clientInfo)
+    : mService(service), mClientInfo(clientInfo) {}
 
 //static
 void DeathNotifier::BinderDiedCallback(void* cookie) {
@@ -104,16 +96,16 @@
         return;
     }
 
-    service->overridePid(mPid, -1);
+    service->overridePid(mClientInfo.pid, -1);
     // thiz is freed in the call below, so it must be last call referring thiz
-    ClientInfoParcel clientInfo{.pid = mPid, .id = mClientId};
-    service->removeResource(clientInfo, false /*checkValid*/);
+    service->removeResource(mClientInfo, false /*checkValid*/);
 }
 
 class OverrideProcessInfoDeathNotifier : public DeathNotifier {
 public:
     OverrideProcessInfoDeathNotifier(const std::shared_ptr<ResourceManagerService> &service,
-            int pid) : DeathNotifier(service, pid, 0) {}
+                                     const ClientInfoParcel& clientInfo)
+            : DeathNotifier(service, clientInfo) {}
 
     virtual ~OverrideProcessInfoDeathNotifier() {}
 
@@ -128,7 +120,7 @@
         return;
     }
 
-    service->removeProcessInfoOverride(mPid);
+    service->removeProcessInfoOverride(mClientInfo.pid);
 }
 
 template <typename T>
@@ -201,7 +193,11 @@
         ResourceInfo info;
         info.uid = uid;
         info.clientId = clientId;
-        info.name = name;
+        if (name.empty()) {
+            info.name = "<unknown client>";
+        } else {
+            info.name = name;
+        }
         info.client = client;
         info.cookie = 0;
         info.pendingRemoval = false;
@@ -291,10 +287,7 @@
             snprintf(buffer, SIZE, "        Id: %lld\n", (long long)infos[j].clientId);
             result.append(buffer);
 
-            std::string clientName = "<unknown client>";
-            if (infos[j].client != nullptr) {
-                clientName = infos[j].name;
-            }
+            std::string clientName = infos[j].name;
             snprintf(buffer, SIZE, "        Name: %s\n", clientName.c_str());
             result.append(buffer);
 
@@ -356,6 +349,8 @@
       mCpuBoostCount(0),
       mDeathRecipient(AIBinder_DeathRecipient_new(DeathNotifier::BinderDiedCallback)) {
     mSystemCB->noteResetVideo();
+    // Create ResourceManagerMetrics that handles all the metrics.
+    mResourceManagerMetrics = std::make_unique<ResourceManagerMetrics>(mProcessInfo);
 }
 
 //static
@@ -509,49 +504,16 @@
     }
     if (info.cookie == 0 && client != nullptr) {
         info.cookie = addCookieAndLink_l(client,
-                new DeathNotifier(ref<ResourceManagerService>(), pid, clientId));
+                new DeathNotifier(ref<ResourceManagerService>(), clientInfo));
     }
     if (mObserverService != nullptr && !resourceAdded.empty()) {
         mObserverService->onResourceAdded(uid, pid, resourceAdded);
     }
     notifyResourceGranted(pid, resources);
 
-    // Increase the instance count of the resource associated with this client.
-    increaseResourceInstanceCount(clientId, name);
-
     return Status::ok();
 }
 
-void ResourceManagerService::increaseResourceInstanceCount(int64_t clientId,
-                                                           const std::string& name) {
-    // Check whether this client has been looked into already.
-    if (mClientIdSet.find(clientId) == mClientIdSet.end()) {
-        mClientIdSet.insert(clientId);
-        // Update the resource instance count.
-        auto found = mConcurrentResourceCountMap.find(name);
-        if (found == mConcurrentResourceCountMap.end()) {
-            mConcurrentResourceCountMap[name] = 1;
-        } else {
-            found->second++;
-        }
-    }
-}
-
-void ResourceManagerService::decreaseResourceInstanceCount(int64_t clientId,
-                                                           const std::string& name) {
-    // Since this client has been removed, remove it from mClientIdSet
-    mClientIdSet.erase(clientId);
-    // Update the resource instance count also.
-    auto found = mConcurrentResourceCountMap.find(name);
-    if (found != mConcurrentResourceCountMap.end()) {
-        if (found->second == 1) {
-            mConcurrentResourceCountMap.erase(found);
-        } else {
-            found->second--;
-        }
-    }
-}
-
 Status ResourceManagerService::removeResource(const ClientInfoParcel& clientInfo,
         const std::vector<MediaResourceParcel>& resources) {
     int32_t pid = clientInfo.pid;
@@ -656,9 +618,8 @@
         onLastRemoved(it->second, info);
     }
 
-    // Since this client has been removed, decrease the corresponding
-    // resources instance count.
-    decreaseResourceInstanceCount(clientId, info.name);
+    // Since this client has been removed, update the metrics collector.
+    mResourceManagerMetrics->notifyClientReleased(clientInfo);
 
     removeCookieAndUnlink_l(info.client, info.cookie);
 
@@ -790,73 +751,19 @@
 void ResourceManagerService::pushReclaimAtom(const ClientInfoParcel& clientInfo,
                         const Vector<std::shared_ptr<IResourceManagerClient>>& clients,
                         const PidUidVector& idVector, bool reclaimed) {
-    // Construct the metrics for codec reclaim as a pushed atom.
-    // 1. Information about the requester.
-    //  - UID and the priority (oom score)
     int32_t callingPid = clientInfo.pid;
-    int32_t requesterUid = clientInfo.uid;
-    std::string clientName = clientInfo.name;
     int requesterPriority = -1;
     getPriority_l(callingPid, &requesterPriority);
+    std::vector<int> priorities;
+    priorities.push_back(requesterPriority);
 
-    //  2. Information about the codec.
-    //  - Name of the codec requested
-    //  - Number of concurrent codecs running.
-    int32_t noOfConcurrentCodecs = 0;
-    auto found = mConcurrentResourceCountMap.find(clientName);
-    if (found != mConcurrentResourceCountMap.end()) {
-        noOfConcurrentCodecs = found->second;
-    }
-
-    // 3. Information about the Reclaim:
-    // - Status of reclaim request
-    // - How many codecs are reclaimed
-    // - For each codecs reclaimed, information of the process that it belonged to:
-    //    - UID and the Priority (oom score)
-    int32_t reclaimStatus = MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_SUCCESS;
-    if (!reclaimed) {
-      if (clients.size() == 0) {
-        // No clients to reclaim from
-        reclaimStatus =
-            MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
-      } else {
-        // Couldn't reclaim resources from the clients
-        reclaimStatus =
-            MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
-      }
-    }
-    int32_t noOfCodecsReclaimed = clients.size();
-    int32_t targetIndex = 1;
-    for (const auto& id : idVector) {
-        int32_t targetUid = id.second;
+    for (PidUidVector::const_reference id : idVector) {
         int targetPriority = -1;
         getPriority_l(id.first, &targetPriority);
-        // Post the pushed atom
-        int result = stats_write(
-            MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED,
-            requesterUid,
-            requesterPriority,
-            clientName.c_str(),
-            noOfConcurrentCodecs,
-            reclaimStatus,
-            noOfCodecsReclaimed,
-            targetIndex,
-            targetUid,
-            targetPriority);
-        ALOGI("%s: Pushed MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED atom: "
-              "Requester[pid(%d): uid(%d): priority(%d)] "
-              "Codec: [%s] "
-              "No of concurrent codecs: %d "
-              "Reclaim Status: %d "
-              "No of codecs reclaimed: %d "
-              "Target[%d][pid(%d): uid(%d): priority(%d)] "
-              "Atom Size: %d",
-              __func__, callingPid, requesterUid, requesterPriority,
-              clientName.c_str(), noOfConcurrentCodecs,
-              reclaimStatus, noOfCodecsReclaimed,
-              targetIndex, id.first, targetUid, targetPriority, result);
-        targetIndex++;
+        priorities.push_back(targetPriority);
     }
+    mResourceManagerMetrics->pushReclaimAtom(clientInfo, priorities, clients,
+                                             idVector, reclaimed);
 }
 
 bool ResourceManagerService::reclaimUnconditionallyFrom(
@@ -932,6 +839,7 @@
         mOverridePidMap.erase(originalPid);
         if (newPid != -1) {
             mOverridePidMap.emplace(originalPid, newPid);
+            mResourceManagerMetrics->addPid(newPid);
         }
     }
 
@@ -965,8 +873,12 @@
         return Status::fromServiceSpecificError(BAD_VALUE);
     }
 
+    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(pid),
+                                .uid = 0,
+                                .id = 0,
+                                .name = "<unknown client>"};
     uintptr_t cookie = addCookieAndLink_l(client,
-            new OverrideProcessInfoDeathNotifier(ref<ResourceManagerService>(), pid));
+            new OverrideProcessInfoDeathNotifier(ref<ResourceManagerService>(), clientInfo));
 
     mProcessInfoOverrideMap.emplace(pid, ProcessInfoOverride{cookie, client});
 
@@ -1281,4 +1193,27 @@
     return true;
 }
 
+Status ResourceManagerService::notifyClientCreated(const ClientInfoParcel& clientInfo) {
+    mResourceManagerMetrics->notifyClientCreated(clientInfo);
+    return Status::ok();
+}
+
+Status ResourceManagerService::notifyClientStarted(const ClientConfigParcel& clientConfig) {
+    mResourceManagerMetrics->notifyClientStarted(clientConfig);
+    return Status::ok();
+}
+
+Status ResourceManagerService::notifyClientStopped(const ClientConfigParcel& clientConfig) {
+    mResourceManagerMetrics->notifyClientStopped(clientConfig);
+    return Status::ok();
+}
+
+long ResourceManagerService::getPeakConcurrentPixelCount(int pid) const {
+    return mResourceManagerMetrics->getPeakConcurrentPixelCount(pid);
+}
+
+long ResourceManagerService::getCurrentConcurrentPixelCount(int pid) const {
+    return mResourceManagerMetrics->getCurrentConcurrentPixelCount(pid);
+}
+
 } // namespace android