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
gugelfrei
Chong Zhang 6 years ago
parent 1cdd674121
commit 79d2b28f3a

@ -29,7 +29,8 @@ public:
kUnspecified = 0,
kSecureCodec,
kNonSecureCodec,
kGraphicMemory
kGraphicMemory,
kCpuBoost,
};
enum SubType {

@ -523,6 +523,7 @@ MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid)
mDequeueOutputReplyID(0),
mHaveInputSurface(false),
mHavePendingInputBuffers(false),
mCpuBoostRequested(false),
mLatencyUnknown(0) {
if (uid == kNoUid) {
mUid = IPCThreadState::self()->getCallingUid();
@ -1638,6 +1639,31 @@ void MediaCodec::requestActivityNotification(const sp<AMessage> &notify) {
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 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
}
}
requestCpuBoostIfNeeded();
if (mFlags & kFlagIsEncoder) {
// Before we announce the format change we should
// collect codec specific data and amend the output

@ -369,6 +369,7 @@ private:
bool mHaveInputSurface;
bool mHavePendingInputBuffers;
bool mCpuBoostRequested;
std::shared_ptr<BufferChannelBase> mBufferChannel;
@ -425,6 +426,7 @@ private:
uint64_t getGraphicBufferSize();
void addResource(MediaResource::Type type, MediaResource::SubType subtype, uint64_t value);
void requestCpuBoostIfNeeded();
bool hasPendingBuffer(int portIndex);
bool hasPendingBuffer();

@ -25,6 +25,7 @@ namespace android {
// 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 @@ public:
}
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 @@ status_t BnSchedulingPolicyService::onTransact(
{
switch (code) {
case REQUEST_PRIORITY_TRANSACTION:
case REQUEST_CPUSET_BOOST:
// Not reached
return NO_ERROR;
break;

@ -29,6 +29,7 @@ public:
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>

@ -59,4 +59,31 @@ int requestPriority(pid_t pid, pid_t tid, int32_t prio, bool isForApp, bool asyn
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

@ -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 @@ namespace android {
// 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

@ -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 @@ static ResourceInfo& getResourceInfoForEdit(
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 @@ ResourceManagerService::ResourceManagerService(sp<ProcessInfoInterface> processI
: mProcessInfo(processInfo),
mServiceLog(new ServiceLog()),
mSupportsMultipleSecureCodecs(true),
mSupportsSecureWithNonSecureCodec(true) {}
mSupportsSecureWithNonSecureCodec(true),
mCpuBoostCount(0) {}
ResourceManagerService::~ResourceManagerService() {}
@ -239,6 +242,19 @@ void ResourceManagerService::addResource(
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 @@ void ResourceManagerService::removeResource(int pid, int64_t clientId, bool chec
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;

@ -38,6 +38,7 @@ struct ResourceInfo {
sp<IResourceManagerClient> client;
sp<IBinder::DeathRecipient> deathNotifier;
Vector<MediaResource> resources;
bool cpuBoost;
};
typedef Vector<ResourceInfo> ResourceInfos;
@ -112,6 +113,7 @@ private:
PidResourceInfosMap mMap;
bool mSupportsMultipleSecureCodecs;
bool mSupportsSecureWithNonSecureCodec;
int32_t mCpuBoostCount;
};
// ----------------------------------------------------------------------------

Loading…
Cancel
Save