Request cpuset change for 1080p HDR using soft decoder

Keep track of cpuset change requests in ResourceManagerService,
and request changing of cpuset via SchedulingPolicyService.

Bug: 72841545

Test:

1)Using modified Youtube/Exoplayer (that uses softMediaCodec
to decode VP9 profile2), manually verify the following:

- media.codec is put into top-app cpuset playing VP9 1080p HDR
- media.codec is put back into foreground after done
- media.codec stays in foreground cpuset playing other content
- kill the app process, verify media.codec is put back to
  foreground until new instances request top-app
- kill mediaserver process, verify media.codec is put back to
  foreground until new instances request top-app
- kill media.codec process, starting playback again, verify new
  media.codec's cpuset can be changed correctly
- kill system_server process (using 'adb shell stop &&
  adb shell start'), verify media.codec is put back to
  foreground. Restart playback and verify the cpuset can be
  changed correctly.

2) CTS post submit tests

Change-Id: Iba50ede1c08b695821fe4f56dbfc5694eab54e7b
diff --git a/media/libmedia/include/media/MediaResource.h b/media/libmedia/include/media/MediaResource.h
index 1957a45..e1fdb9b 100644
--- a/media/libmedia/include/media/MediaResource.h
+++ b/media/libmedia/include/media/MediaResource.h
@@ -29,7 +29,8 @@
         kUnspecified = 0,
         kSecureCodec,
         kNonSecureCodec,
-        kGraphicMemory
+        kGraphicMemory,
+        kCpuBoost,
     };
 
     enum SubType {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index f25d1f1..23bee49 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -523,6 +523,7 @@
       mDequeueOutputReplyID(0),
       mHaveInputSurface(false),
       mHavePendingInputBuffers(false),
+      mCpuBoostRequested(false),
       mLatencyUnknown(0) {
     if (uid == kNoUid) {
         mUid = IPCThreadState::self()->getCallingUid();
@@ -1638,6 +1639,31 @@
     msg->post();
 }
 
+void MediaCodec::requestCpuBoostIfNeeded() {
+    if (mCpuBoostRequested) {
+        return;
+    }
+    int32_t colorFormat;
+    if (mSoftRenderer != NULL
+            && mOutputFormat->contains("hdr-static-info")
+            && mOutputFormat->findInt32("color-format", &colorFormat)
+            && (colorFormat == OMX_COLOR_FormatYUV420Planar16)) {
+        int32_t left, top, right, bottom, width, height;
+        int64_t totalPixel = 0;
+        if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
+            totalPixel = (right - left + 1) * (bottom - top + 1);
+        } else if (mOutputFormat->findInt32("width", &width)
+                && mOutputFormat->findInt32("height", &height)) {
+            totalPixel = width * height;
+        }
+        if (totalPixel >= 1920 * 1080) {
+            addResource(MediaResource::kCpuBoost,
+                    MediaResource::kUnspecifiedSubType, 1);
+            mCpuBoostRequested = true;
+        }
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 void MediaCodec::cancelPendingDequeueOperations() {
@@ -2160,6 +2186,8 @@
                             }
                         }
 
+                        requestCpuBoostIfNeeded();
+
                         if (mFlags & kFlagIsEncoder) {
                             // Before we announce the format change we should
                             // collect codec specific data and amend the output
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 48a1224..67808f1 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -369,6 +369,7 @@
 
     bool mHaveInputSurface;
     bool mHavePendingInputBuffers;
+    bool mCpuBoostRequested;
 
     std::shared_ptr<BufferChannelBase> mBufferChannel;
 
@@ -425,6 +426,7 @@
 
     uint64_t getGraphicBufferSize();
     void addResource(MediaResource::Type type, MediaResource::SubType subtype, uint64_t value);
+    void requestCpuBoostIfNeeded();
 
     bool hasPendingBuffer(int portIndex);
     bool hasPendingBuffer();
diff --git a/media/utils/ISchedulingPolicyService.cpp b/media/utils/ISchedulingPolicyService.cpp
index 22fbc97..b210404 100644
--- a/media/utils/ISchedulingPolicyService.cpp
+++ b/media/utils/ISchedulingPolicyService.cpp
@@ -25,6 +25,7 @@
 // Keep in sync with frameworks/base/core/java/android/os/ISchedulingPolicyService.aidl
 enum {
     REQUEST_PRIORITY_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+    REQUEST_CPUSET_BOOST,
 };
 
 // ----------------------------------------------------------------------
@@ -60,6 +61,23 @@
         }
         return reply.readInt32();
     }
+
+    virtual int requestCpusetBoost(bool enable, const sp<IInterface>& client)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISchedulingPolicyService::getInterfaceDescriptor());
+        data.writeInt32(enable);
+        data.writeStrongBinder(IInterface::asBinder(client));
+        status_t status = remote()->transact(REQUEST_CPUSET_BOOST, data, &reply, 0);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        // fail on exception: force binder reconnection
+        if (reply.readExceptionCode() != 0) {
+            return DEAD_OBJECT;
+        }
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(SchedulingPolicyService, "android.os.ISchedulingPolicyService");
@@ -71,6 +89,7 @@
 {
     switch (code) {
     case REQUEST_PRIORITY_TRANSACTION:
+    case REQUEST_CPUSET_BOOST:
         // Not reached
         return NO_ERROR;
         break;
diff --git a/media/utils/ISchedulingPolicyService.h b/media/utils/ISchedulingPolicyService.h
index 1015677..e4f7c0d 100644
--- a/media/utils/ISchedulingPolicyService.h
+++ b/media/utils/ISchedulingPolicyService.h
@@ -29,6 +29,7 @@
     virtual int         requestPriority(/*pid_t*/int32_t pid, /*pid_t*/int32_t tid,
                                         int32_t prio, bool isForApp, bool asynchronous) = 0;
 
+    virtual int         requestCpusetBoost(bool enable, const sp<IInterface>& client) = 0;
 };
 
 class BnSchedulingPolicyService : public BnInterface<ISchedulingPolicyService>
diff --git a/media/utils/SchedulingPolicyService.cpp b/media/utils/SchedulingPolicyService.cpp
index d7055ef..4e9792f 100644
--- a/media/utils/SchedulingPolicyService.cpp
+++ b/media/utils/SchedulingPolicyService.cpp
@@ -59,4 +59,31 @@
     return ret;
 }
 
+int requestCpusetBoost(bool enable, const sp<IInterface> &client)
+{
+    int ret;
+    sMutex.lock();
+    sp<ISchedulingPolicyService> sps = sSchedulingPolicyService;
+    sMutex.unlock();
+    if (sps == 0) {
+        sp<IBinder> binder = defaultServiceManager()->checkService(_scheduling_policy);
+        if (binder == 0) {
+            return DEAD_OBJECT;
+        }
+        sps = interface_cast<ISchedulingPolicyService>(binder);
+        sMutex.lock();
+        sSchedulingPolicyService = sps;
+        sMutex.unlock();
+    }
+    ret = sps->requestCpusetBoost(enable, client);
+    if (ret != DEAD_OBJECT) {
+        return ret;
+    }
+    ALOGW("SchedulingPolicyService died");
+    sMutex.lock();
+    sSchedulingPolicyService.clear();
+    sMutex.unlock();
+    return ret;
+}
+
 }   // namespace android
diff --git a/media/utils/include/mediautils/SchedulingPolicyService.h b/media/utils/include/mediautils/SchedulingPolicyService.h
index 47d8734..a33539f 100644
--- a/media/utils/include/mediautils/SchedulingPolicyService.h
+++ b/media/utils/include/mediautils/SchedulingPolicyService.h
@@ -17,8 +17,11 @@
 #ifndef _ANDROID_SCHEDULING_POLICY_SERVICE_H
 #define _ANDROID_SCHEDULING_POLICY_SERVICE_H
 
+#include <utils/RefBase.h>
+
 namespace android {
 
+class IInterface;
 // Request elevated priority for thread tid, whose thread group leader must be pid.
 // The priority parameter is currently restricted to either 1 or 2.
 // The asynchronous parameter should be 'true' to return immediately,
@@ -26,6 +29,14 @@
 // The default value 'false' means to return after request has been enqueued and executed.
 int requestPriority(pid_t pid, pid_t tid, int32_t prio, bool isForApp, bool asynchronous = false);
 
+// Request to move media.codec process between SP_FOREGROUND and SP_TOP_APP.
+// When 'enable' is 'true', server will attempt to move media.codec process
+// from SP_FOREGROUND into SP_TOP_APP cpuset. A valid 'client' must be provided
+// for the server to receive death notifications. When 'enable' is 'false', server
+// will attempt to move media.codec process back to the original cpuset, and
+// 'client' is ignored in this case.
+int requestCpusetBoost(bool enable, const sp<IInterface> &client);
+
 }   // namespace android
 
 #endif  // _ANDROID_SCHEDULING_POLICY_SERVICE_H
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 78bb587..28bfd3f 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -31,7 +31,8 @@
 
 #include "ResourceManagerService.h"
 #include "ServiceLog.h"
-
+#include "mediautils/SchedulingPolicyService.h"
+#include <cutils/sched_policy.h>
 namespace android {
 
 namespace {
@@ -111,6 +112,7 @@
     ResourceInfo info;
     info.clientId = clientId;
     info.client = client;
+    info.cpuBoost = false;
     infos.push_back(info);
     return infos.editItemAt(infos.size() - 1);
 }
@@ -201,7 +203,8 @@
     : mProcessInfo(processInfo),
       mServiceLog(new ServiceLog()),
       mSupportsMultipleSecureCodecs(true),
-      mSupportsSecureWithNonSecureCodec(true) {}
+      mSupportsSecureWithNonSecureCodec(true),
+      mCpuBoostCount(0) {}
 
 ResourceManagerService::~ResourceManagerService() {}
 
@@ -239,6 +242,19 @@
     ResourceInfo& info = getResourceInfoForEdit(clientId, client, infos);
     // TODO: do the merge instead of append.
     info.resources.appendVector(resources);
+
+    for (size_t i = 0; i < resources.size(); ++i) {
+        if (resources[i].mType == MediaResource::kCpuBoost && !info.cpuBoost) {
+            info.cpuBoost = true;
+            // Request it on every new instance of kCpuBoost, as the media.codec
+            // could have died, if we only do it the first time subsequent instances
+            // never gets the boost.
+            if (requestCpusetBoost(true, this) != OK) {
+                ALOGW("couldn't request cpuset boost");
+            }
+            mCpuBoostCount++;
+        }
+    }
     if (info.deathNotifier == nullptr) {
         info.deathNotifier = new DeathNotifier(this, pid, clientId);
         IInterface::asBinder(client)->linkToDeath(info.deathNotifier);
@@ -270,6 +286,11 @@
     ResourceInfos &infos = mMap.editValueAt(index);
     for (size_t j = 0; j < infos.size(); ++j) {
         if (infos[j].clientId == clientId) {
+            if (infos[j].cpuBoost && mCpuBoostCount > 0) {
+                if (--mCpuBoostCount == 0) {
+                    requestCpusetBoost(false, this);
+                }
+            }
             IInterface::asBinder(infos[j].client)->unlinkToDeath(infos[j].deathNotifier);
             j = infos.removeAt(j);
             found = true;
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index 9e97ac0..82d2a0b 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -38,6 +38,7 @@
     sp<IResourceManagerClient> client;
     sp<IBinder::DeathRecipient> deathNotifier;
     Vector<MediaResource> resources;
+    bool cpuBoost;
 };
 
 typedef Vector<ResourceInfo> ResourceInfos;
@@ -112,6 +113,7 @@
     PidResourceInfosMap mMap;
     bool mSupportsMultipleSecureCodecs;
     bool mSupportsSecureWithNonSecureCodec;
+    int32_t mCpuBoostCount;
 };
 
 // ----------------------------------------------------------------------------