Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd726805 authored by Chong Zhang's avatar Chong Zhang
Browse files

Add more testing for ResourceManagerService

Refactor the calls to other system services to an interface
to allow more testing.

Add test for callbacks to BatteryStatsService and
SchedulingPolicyService.

bug: 138381810
bug: 139440234
test: presubmit
Change-Id: I04408ad5a126e9f4083b5806b228449cb432acf6
parent 6c2b3146
Loading
Loading
Loading
Loading
+35 −7
Original line number Diff line number Diff line
@@ -200,16 +200,44 @@ status_t ResourceManagerService::dump(int fd, const Vector<String16>& /* args */
    return OK;
}

struct SystemCallbackImpl :
        public ResourceManagerService::SystemCallbackInterface {
    SystemCallbackImpl() {}

    virtual void noteStartVideo(int uid) override {
        BatteryNotifier::getInstance().noteStartVideo(uid);
    }
    virtual void noteStopVideo(int uid) override {
        BatteryNotifier::getInstance().noteStopVideo(uid);
    }
    virtual void noteResetVideo() override {
        BatteryNotifier::getInstance().noteResetVideo();
    }
    virtual bool requestCpusetBoost(
            bool enable, const sp<IInterface> &client) override {
        return android::requestCpusetBoost(enable, client);
    }

protected:
    virtual ~SystemCallbackImpl() {}

private:
    DISALLOW_EVIL_CONSTRUCTORS(SystemCallbackImpl);
};

ResourceManagerService::ResourceManagerService()
    : ResourceManagerService(new ProcessInfo()) {}
    : ResourceManagerService(new ProcessInfo(), new SystemCallbackImpl()) {}

ResourceManagerService::ResourceManagerService(sp<ProcessInfoInterface> processInfo)
ResourceManagerService::ResourceManagerService(
        const sp<ProcessInfoInterface> &processInfo,
        const sp<SystemCallbackInterface> &systemResource)
    : mProcessInfo(processInfo),
      mSystemCB(systemResource),
      mServiceLog(new ServiceLog()),
      mSupportsMultipleSecureCodecs(true),
      mSupportsSecureWithNonSecureCodec(true),
      mCpuBoostCount(0) {
    BatteryNotifier::getInstance().noteResetVideo();
    mSystemCB->noteResetVideo();
}

ResourceManagerService::~ResourceManagerService() {}
@@ -238,13 +266,13 @@ void ResourceManagerService::onFirstAdded(
        // 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) {
        if (mSystemCB->requestCpusetBoost(true, this) != OK) {
            ALOGW("couldn't request cpuset boost");
        }
        mCpuBoostCount++;
    } else if (resource.mType == MediaResource::kBattery
            && resource.mSubType == MediaResource::kVideoCodec) {
        BatteryNotifier::getInstance().noteStartVideo(clientInfo.uid);
        mSystemCB->noteStartVideo(clientInfo.uid);
    }
}

@@ -254,11 +282,11 @@ void ResourceManagerService::onLastRemoved(
            && resource.mSubType == MediaResource::kUnspecifiedSubType
            && mCpuBoostCount > 0) {
        if (--mCpuBoostCount == 0) {
            requestCpusetBoost(false, this);
            mSystemCB->requestCpusetBoost(false, this);
        }
    } else if (resource.mType == MediaResource::kBattery
            && resource.mSubType == MediaResource::kVideoCodec) {
        BatteryNotifier::getInstance().noteStopVideo(clientInfo.uid);
        mSystemCB->noteStopVideo(clientInfo.uid);
    }
}

+12 −1
Original line number Diff line number Diff line
@@ -51,12 +51,22 @@ class ResourceManagerService
      public BnResourceManagerService
{
public:
    struct SystemCallbackInterface : public RefBase {
        virtual void noteStartVideo(int uid) = 0;
        virtual void noteStopVideo(int uid) = 0;
        virtual void noteResetVideo() = 0;
        virtual bool requestCpusetBoost(
                bool enable, const sp<IInterface> &client) = 0;
    };

    static char const *getServiceName() { return "media.resource_manager"; }

    virtual status_t dump(int fd, const Vector<String16>& args);

    ResourceManagerService();
    explicit ResourceManagerService(sp<ProcessInfoInterface> processInfo);
    explicit ResourceManagerService(
            const sp<ProcessInfoInterface> &processInfo,
            const sp<SystemCallbackInterface> &systemResource);

    // IResourceManagerService interface
    virtual void config(const Vector<MediaResourcePolicy> &policies);
@@ -118,6 +128,7 @@ private:

    mutable Mutex mLock;
    sp<ProcessInfoInterface> mProcessInfo;
    sp<SystemCallbackInterface> mSystemCB;
    sp<ServiceLog> mServiceLog;
    PidResourceInfosMap mMap;
    bool mSupportsMultipleSecureCodecs;
+150 −1
Original line number Diff line number Diff line
@@ -52,6 +52,62 @@ private:
    DISALLOW_EVIL_CONSTRUCTORS(TestProcessInfo);
};

struct TestSystemCallback :
        public ResourceManagerService::SystemCallbackInterface {
    TestSystemCallback() :
        mLastEvent({EventType::INVALID, 0}), mEventCount(0) {}

    enum EventType {
        INVALID          = -1,
        VIDEO_ON         = 0,
        VIDEO_OFF        = 1,
        VIDEO_RESET      = 2,
        CPUSET_ENABLE    = 3,
        CPUSET_DISABLE   = 4,
    };

    struct EventEntry {
        EventType type;
        int arg;
    };

    virtual void noteStartVideo(int uid) override {
        mLastEvent = {EventType::VIDEO_ON, uid};
        mEventCount++;
    }

    virtual void noteStopVideo(int uid) override {
        mLastEvent = {EventType::VIDEO_OFF, uid};
        mEventCount++;
    }

    virtual void noteResetVideo() override {
        mLastEvent = {EventType::VIDEO_RESET, 0};
        mEventCount++;
    }

    virtual bool requestCpusetBoost(
            bool enable, const sp<IInterface> &/*client*/) override {
        mLastEvent = {enable ? EventType::CPUSET_ENABLE : EventType::CPUSET_DISABLE, 0};
        mEventCount++;
        return true;
    }

    size_t eventCount() { return mEventCount; }
    EventType lastEventType() { return mLastEvent.type; }
    EventEntry lastEvent() { return mLastEvent; }

protected:
    virtual ~TestSystemCallback() {}

private:
    EventEntry mLastEvent;
    size_t mEventCount;

    DISALLOW_EVIL_CONSTRUCTORS(TestSystemCallback);
};


struct TestClient : public BnResourceManagerClient {
    TestClient(int pid, sp<ResourceManagerService> service)
        : mReclaimed(false), mPid(pid), mService(service) {}
@@ -95,10 +151,17 @@ static const int kLowPriorityPid = 40;
static const int kMidPriorityPid = 25;
static const int kHighPriorityPid = 10;

using EventType = TestSystemCallback::EventType;
using EventEntry = TestSystemCallback::EventEntry;
bool operator== (const EventEntry& lhs, const EventEntry& rhs) {
    return lhs.type == rhs.type && lhs.arg == rhs.arg;
}

class ResourceManagerServiceTest : public ::testing::Test {
public:
    ResourceManagerServiceTest()
        : mService(new ResourceManagerService(new TestProcessInfo)),
        : mSystemCB(new TestSystemCallback()),
          mService(new ResourceManagerService(new TestProcessInfo, mSystemCB)),
          mTestClient1(new TestClient(kTestPid1, mService)),
          mTestClient2(new TestClient(kTestPid2, mService)),
          mTestClient3(new TestClient(kTestPid2, mService)) {
@@ -578,6 +641,84 @@ protected:
        EXPECT_TRUE(mService->isCallingPriorityHigher_l(99, 100));
    }

    void testBatteryStats() {
        // reset should always be called when ResourceManagerService is created (restarted)
        EXPECT_EQ(1u, mSystemCB->eventCount());
        EXPECT_EQ(EventType::VIDEO_RESET, mSystemCB->lastEventType());

        // new client request should cause VIDEO_ON
        Vector<MediaResource> resources1;
        resources1.push_back(MediaResource(MediaResource::kBattery, MediaResource::kVideoCodec, 1));
        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
        EXPECT_EQ(2u, mSystemCB->eventCount());
        EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid1}), mSystemCB->lastEvent());

        // each client should only cause 1 VIDEO_ON
        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
        EXPECT_EQ(2u, mSystemCB->eventCount());

        // new client request should cause VIDEO_ON
        Vector<MediaResource> resources2;
        resources2.push_back(MediaResource(MediaResource::kBattery, MediaResource::kVideoCodec, 2));
        mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
        EXPECT_EQ(3u, mSystemCB->eventCount());
        EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid2}), mSystemCB->lastEvent());

        // partially remove mTestClient1's request, shouldn't be any VIDEO_OFF
        mService->removeResource(kTestPid1, getId(mTestClient1), resources1);
        EXPECT_EQ(3u, mSystemCB->eventCount());

        // remove mTestClient1's request, should be VIDEO_OFF for kTestUid1
        // (use resource2 to test removing more instances than previously requested)
        mService->removeResource(kTestPid1, getId(mTestClient1), resources2);
        EXPECT_EQ(4u, mSystemCB->eventCount());
        EXPECT_EQ(EventEntry({EventType::VIDEO_OFF, kTestUid1}), mSystemCB->lastEvent());

        // remove mTestClient2, should be VIDEO_OFF for kTestUid2
        mService->removeClient(kTestPid2, getId(mTestClient2));
        EXPECT_EQ(5u, mSystemCB->eventCount());
        EXPECT_EQ(EventEntry({EventType::VIDEO_OFF, kTestUid2}), mSystemCB->lastEvent());
    }

    void testCpusetBoost() {
        // reset should always be called when ResourceManagerService is created (restarted)
        EXPECT_EQ(1u, mSystemCB->eventCount());
        EXPECT_EQ(EventType::VIDEO_RESET, mSystemCB->lastEventType());

        // new client request should cause CPUSET_ENABLE
        Vector<MediaResource> resources1;
        resources1.push_back(MediaResource(MediaResource::kCpuBoost, 1));
        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
        EXPECT_EQ(2u, mSystemCB->eventCount());
        EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());

        // each client should only cause 1 CPUSET_ENABLE
        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
        EXPECT_EQ(2u, mSystemCB->eventCount());

        // new client request should cause CPUSET_ENABLE
        Vector<MediaResource> resources2;
        resources2.push_back(MediaResource(MediaResource::kCpuBoost, 2));
        mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
        EXPECT_EQ(3u, mSystemCB->eventCount());
        EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());

        // remove mTestClient2 should not cause CPUSET_DISABLE, mTestClient1 still active
        mService->removeClient(kTestPid2, getId(mTestClient2));
        EXPECT_EQ(3u, mSystemCB->eventCount());

        // remove 1 cpuboost from mTestClient1, should not be CPUSET_DISABLE (still 1 left)
        mService->removeResource(kTestPid1, getId(mTestClient1), resources1);
        EXPECT_EQ(3u, mSystemCB->eventCount());

        // remove 2 cpuboost from mTestClient1, should be CPUSET_DISABLE
        // (use resource2 to test removing more than previously requested)
        mService->removeResource(kTestPid1, getId(mTestClient1), resources2);
        EXPECT_EQ(4u, mSystemCB->eventCount());
        EXPECT_EQ(EventType::CPUSET_DISABLE, mSystemCB->lastEventType());
    }

    sp<TestSystemCallback> mSystemCB;
    sp<ResourceManagerService> mService;
    sp<IResourceManagerClient> mTestClient1;
    sp<IResourceManagerClient> mTestClient2;
@@ -629,4 +770,12 @@ TEST_F(ResourceManagerServiceTest, isCallingPriorityHigher_l) {
    testIsCallingPriorityHigher();
}

TEST_F(ResourceManagerServiceTest, testBatteryStats) {
    testBatteryStats();
}

TEST_F(ResourceManagerServiceTest, testCpusetBoost) {
    testCpusetBoost();
}

} // namespace android