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

Commit 182b06a0 authored by Chong Zhang's avatar Chong Zhang
Browse files

transcoding: instantiate job scheduler with dummy hooks

Instantiate job scheduler with dummy hooks for transcoder
and procInfo to allow more unit testing.

bug: 145233472
test: mediatranscodingservice_tests
Change-Id: I99754d724164c453623fb00affddefca5c84c26c
parent 6d58e4b1
Loading
Loading
Loading
Loading
+47 −13
Original line number Diff line number Diff line
@@ -16,9 +16,12 @@

//#define LOG_NDEBUG 0
#define LOG_TAG "MediaTranscodingService"
#include <MediaTranscodingService.h>
#include "MediaTranscodingService.h"

#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <media/TranscodingClientManager.h>
#include <media/TranscodingJobScheduler.h>
#include <private/android_filesystem_config.h>
#include <utils/Log.h>
#include <utils/Vector.h>
@@ -45,8 +48,41 @@ static bool isTrustedCallingUid(uid_t uid) {
    }
}

// DummyTranscoder and DummyProcessInfo are currently used to instantiate
// MediaTranscodingService on service side for testing, so that we could
// actually test the IPC calls of MediaTranscodingService to expose some
// issues that's observable only over IPC.
class DummyTranscoder : public TranscoderInterface {
    void start(int64_t clientId, int32_t jobId) override {
        (void)clientId;
        (void)jobId;
    }
    void pause(int64_t clientId, int32_t jobId) override {
        (void)clientId;
        (void)jobId;
    }
    void resume(int64_t clientId, int32_t jobId) override {
        (void)clientId;
        (void)jobId;
    }
};

class DummyProcessInfo : public ProcessInfoInterface {
    bool isProcessOnTop(int32_t pid) override {
        (void)pid;
        return true;
    }
};

MediaTranscodingService::MediaTranscodingService()
      : mTranscodingClientManager(TranscodingClientManager::getInstance()) {
      : MediaTranscodingService(std::make_shared<DummyTranscoder>(),
                                std::make_shared<DummyProcessInfo>()) {}

MediaTranscodingService::MediaTranscodingService(
        const std::shared_ptr<TranscoderInterface>& transcoder,
        const std::shared_ptr<ProcessInfoInterface>& procInfo)
      : mJobScheduler(new TranscodingJobScheduler(transcoder, procInfo)),
        mClientManager(new TranscodingClientManager(mJobScheduler)) {
    ALOGV("MediaTranscodingService is created");
}

@@ -64,7 +100,7 @@ binder_status_t MediaTranscodingService::dump(int fd, const char** /*args*/, uin
    write(fd, result.string(), result.size());

    Vector<String16> args;
    mTranscodingClientManager.dumpAllClients(fd, args);
    mClientManager->dumpAllClients(fd, args);
    return OK;
}

@@ -80,13 +116,11 @@ void MediaTranscodingService::instantiate() {
}

Status MediaTranscodingService::registerClient(
        const std::shared_ptr<ITranscodingClientListener>& in_listener,
        const std::string& in_clientName,
        const std::string& in_opPackageName,
        int32_t in_clientUid, int32_t in_clientPid,
        std::shared_ptr<ITranscodingClient>* _aidl_return) {
    if (in_listener == nullptr) {
        ALOGE("Client listener can not be null");
        const std::shared_ptr<ITranscodingClientCallback>& in_callback,
        const std::string& in_clientName, const std::string& in_opPackageName, int32_t in_clientUid,
        int32_t in_clientPid, std::shared_ptr<ITranscodingClient>* _aidl_return) {
    if (in_callback == nullptr) {
        ALOGE("Client callback can not be null");
        *_aidl_return = nullptr;
        return Status::fromServiceSpecificError(ERROR_ILLEGAL_ARGUMENT);
    }
@@ -127,8 +161,8 @@ Status MediaTranscodingService::registerClient(
    // Creates the client and uses its process id as client id.
    std::shared_ptr<ITranscodingClient> newClient;

    status_t err = mTranscodingClientManager.addClient(in_listener,
            in_clientPid, in_clientUid, in_clientName, in_opPackageName, &newClient);
    status_t err = mClientManager->addClient(in_callback, in_clientPid, in_clientUid, in_clientName,
                                             in_opPackageName, &newClient);
    if (err != OK) {
        *_aidl_return = nullptr;
        return STATUS_ERROR_FMT(err, "Failed to add client to TranscodingClientManager");
@@ -140,7 +174,7 @@ Status MediaTranscodingService::registerClient(

Status MediaTranscodingService::getNumOfClients(int32_t* _aidl_return) {
    ALOGD("MediaTranscodingService::getNumOfClients");
    *_aidl_return = mTranscodingClientManager.getNumOfClients();
    *_aidl_return = mClientManager->getNumOfClients();
    return Status::ok();
}

+14 −11
Original line number Diff line number Diff line
@@ -19,16 +19,19 @@

#include <aidl/android/media/BnMediaTranscodingService.h>
#include <binder/IServiceManager.h>
#include <media/TranscodingClientManager.h>

namespace android {

using Status = ::ndk::ScopedAStatus;
using ::aidl::android::media::BnMediaTranscodingService;
using ::aidl::android::media::ITranscodingClient;
using ::aidl::android::media::ITranscodingClientListener;
using ::aidl::android::media::ITranscodingClientCallback;
using ::aidl::android::media::TranscodingJobParcel;
using ::aidl::android::media::TranscodingRequestParcel;
class TranscodingClientManager;
class TranscodingJobScheduler;
class TranscoderInterface;
class ProcessInfoInterface;

class MediaTranscodingService : public BnMediaTranscodingService {
public:
@@ -36,30 +39,30 @@ public:
    static constexpr int32_t kInvalidClientId = -1;

    MediaTranscodingService();
    MediaTranscodingService(const std::shared_ptr<TranscoderInterface>& transcoder,
                            const std::shared_ptr<ProcessInfoInterface>& procInfo);
    virtual ~MediaTranscodingService();

    static void instantiate();

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

    Status registerClient(
            const std::shared_ptr<ITranscodingClientListener>& in_listener,
            const std::string& in_clientName,
            const std::string& in_opPackageName,
    Status registerClient(const std::shared_ptr<ITranscodingClientCallback>& in_callback,
                          const std::string& in_clientName, const std::string& in_opPackageName,
                          int32_t in_clientUid, int32_t in_clientPid,
                          std::shared_ptr<ITranscodingClient>* _aidl_return) override;

    Status getNumOfClients(int32_t* _aidl_return) override;

    virtual inline binder_status_t dump(
            int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/);
    virtual inline binder_status_t dump(int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/);

private:
    friend class MediaTranscodingServiceTest;

    mutable std::mutex mServiceLock;

    TranscodingClientManager& mTranscodingClientManager;
    std::shared_ptr<TranscodingJobScheduler> mJobScheduler;
    std::shared_ptr<TranscodingClientManager> mClientManager;
};

}  // namespace android
+2 −1
Original line number Diff line number Diff line
@@ -20,4 +20,5 @@ adb root && adb wait-for-device remount && adb sync
echo "========================================"

echo "testing mediatranscodingservice"
adb shell /data/nativetest64/mediatranscodingservice_tests/mediatranscodingservice_tests
#adb shell /data/nativetest64/mediatranscodingservice_tests/mediatranscodingservice_tests
adb shell /data/nativetest/mediatranscodingservice_tests/mediatranscodingservice_tests
+159 −103
Original line number Diff line number Diff line
@@ -19,10 +19,12 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaTranscodingServiceTest"

#include <aidl/android/media/BnTranscodingClientListener.h>
#include <aidl/android/media/BnTranscodingClientCallback.h>
#include <aidl/android/media/IMediaTranscodingService.h>
#include <aidl/android/media/ITranscodingClient.h>
#include <aidl/android/media/ITranscodingClientListener.h>
#include <aidl/android/media/ITranscodingClientCallback.h>
#include <aidl/android/media/TranscodingJobParcel.h>
#include <aidl/android/media/TranscodingRequestParcel.h>
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <android/binder_ibinder_jni.h>
@@ -39,31 +41,28 @@ namespace android {
namespace media {

using Status = ::ndk::ScopedAStatus;
using aidl::android::media::BnTranscodingClientListener;
using aidl::android::media::ITranscodingClient;
using aidl::android::media::ITranscodingClientListener;
using aidl::android::media::BnTranscodingClientCallback;
using aidl::android::media::IMediaTranscodingService;
using aidl::android::media::ITranscodingClient;
using aidl::android::media::ITranscodingClientCallback;
using aidl::android::media::TranscodingJobParcel;
using aidl::android::media::TranscodingRequestParcel;

// Note that -1 is valid and means using calling pid/uid for the service. But only privilege caller could
// use them. This test is not a privilege caller.
constexpr int32_t kInvalidClientPid = -5;
constexpr int32_t kInvalidClientUid = -5;
constexpr const char* kInvalidClientName = "";
constexpr const char* kInvalidClientOpPackageName = "";

constexpr int32_t kClientUseCallingPid = -1;
constexpr int32_t kClientUseCallingUid = -1;
constexpr int32_t kClientUseCallingPid = IMediaTranscodingService::USE_CALLING_PID;
constexpr int32_t kClientUseCallingUid = IMediaTranscodingService::USE_CALLING_UID;
constexpr const char* kClientName = "TestClient";
constexpr const char* kClientOpPackageName = "TestClientPackage";

struct TestClient : public BnTranscodingClientListener {
    TestClient() {
        ALOGD("TestClient Created");
    }
struct TestClient : public BnTranscodingClientCallback {
    TestClient() { ALOGD("TestClient Created"); }

    virtual ~TestClient() {
        ALOGI("TestClient destroyed");
    }
    virtual ~TestClient() { ALOGI("TestClient destroyed"); }

    Status onTranscodingFinished(
            int32_t /* in_jobId */,
@@ -89,13 +88,9 @@ struct TestClient : public BnTranscodingClientListener {

class MediaTranscodingServiceTest : public ::testing::Test {
public:
    MediaTranscodingServiceTest() {
        ALOGD("MediaTranscodingServiceTest created");
    }
    MediaTranscodingServiceTest() { ALOGD("MediaTranscodingServiceTest created"); }

    ~MediaTranscodingServiceTest() {
        ALOGD("MediaTranscodingingServiceTest destroyed");
    }
    ~MediaTranscodingServiceTest() { ALOGD("MediaTranscodingingServiceTest destroyed"); }

    void SetUp() override {
        ::ndk::SpAIBinder binder(AServiceManager_getService("media.transcoding"));
@@ -104,24 +99,68 @@ public:
            ALOGE("Failed to connect to the media.trascoding service.");
            return;
        }
        mClientListener = ::ndk::SharedRefBase::make<TestClient>();
        mClientListener2 = ::ndk::SharedRefBase::make<TestClient>();
        mClientListener3 = ::ndk::SharedRefBase::make<TestClient>();
        mClientCallback = ::ndk::SharedRefBase::make<TestClient>();
        mClientCallback2 = ::ndk::SharedRefBase::make<TestClient>();
        mClientCallback3 = ::ndk::SharedRefBase::make<TestClient>();
    }

    void registerMultipleClients() {
        // Register 3 clients.
        Status status =
                mService->registerClient(mClientCallback, kClientName, kClientOpPackageName,
                                         kClientUseCallingUid, kClientUseCallingPid, &mClient1);
        EXPECT_TRUE(status.isOk());
        EXPECT_TRUE(mClient1 != nullptr);

        status = mService->registerClient(mClientCallback2, kClientName, kClientOpPackageName,
                                          kClientUseCallingUid, kClientUseCallingPid, &mClient2);
        EXPECT_TRUE(status.isOk());
        EXPECT_TRUE(mClient2 != nullptr);

        status = mService->registerClient(mClientCallback3, kClientName, kClientOpPackageName,
                                          kClientUseCallingUid, kClientUseCallingPid, &mClient3);
        EXPECT_TRUE(status.isOk());
        EXPECT_TRUE(mClient3 != nullptr);

        // Check the number of clients.
        int32_t numOfClients;
        status = mService->getNumOfClients(&numOfClients);
        EXPECT_TRUE(status.isOk());
        EXPECT_EQ(3, numOfClients);
    }

    void unregisterMultipleClients() {
        // Unregister the clients.
        Status status = mClient1->unregister();
        EXPECT_TRUE(status.isOk());

        status = mClient2->unregister();
        EXPECT_TRUE(status.isOk());

        status = mClient3->unregister();
        EXPECT_TRUE(status.isOk());

        // Check the number of clients.
        int32_t numOfClients;
        status = mService->getNumOfClients(&numOfClients);
        EXPECT_TRUE(status.isOk());
        EXPECT_EQ(0, numOfClients);
    }

    std::shared_ptr<IMediaTranscodingService> mService;
    std::shared_ptr<ITranscodingClientListener> mClientListener;
    std::shared_ptr<ITranscodingClientListener> mClientListener2;
    std::shared_ptr<ITranscodingClientListener> mClientListener3;
    std::shared_ptr<ITranscodingClientCallback> mClientCallback;
    std::shared_ptr<ITranscodingClientCallback> mClientCallback2;
    std::shared_ptr<ITranscodingClientCallback> mClientCallback3;
    std::shared_ptr<ITranscodingClient> mClient1;
    std::shared_ptr<ITranscodingClient> mClient2;
    std::shared_ptr<ITranscodingClient> mClient3;
};


TEST_F(MediaTranscodingServiceTest, TestRegisterNullClient) {
    std::shared_ptr<ITranscodingClient> client;

    // Register the client with null listener
    Status status = mService->registerClient(
            nullptr, kClientName, kClientOpPackageName,
    // Register the client with null callback.
    Status status = mService->registerClient(nullptr, kClientName, kClientOpPackageName,
                                             kClientUseCallingUid, kClientUseCallingPid, &client);
    EXPECT_FALSE(status.isOk());
}
@@ -130,29 +169,18 @@ TEST_F(MediaTranscodingServiceTest, TestRegisterClientWithInvalidClientPid) {
    std::shared_ptr<ITranscodingClient> client;

    // Register the client with the service.
    Status status = mService->registerClient(
            mClientListener, kClientName, kClientOpPackageName,
    Status status = mService->registerClient(mClientCallback, kClientName, kClientOpPackageName,
                                             kClientUseCallingUid, kInvalidClientPid, &client);
    EXPECT_FALSE(status.isOk());
}

TEST_F(MediaTranscodingServiceTest, TestRegisterClientWithInvalidClientUid) {
    std::shared_ptr<ITranscodingClient> client;

    // Register the client with the service.
    Status status = mService->registerClient(
            mClientListener, kClientName, kClientOpPackageName,
            kInvalidClientUid, kClientUseCallingPid, &client);
    EXPECT_FALSE(status.isOk());
}

TEST_F(MediaTranscodingServiceTest, TestRegisterClientWithInvalidClientName) {
    std::shared_ptr<ITranscodingClient> client;

    // Register the client with the service.
    Status status = mService->registerClient(
            mClientListener, kInvalidClientName, kInvalidClientOpPackageName,
            kClientUseCallingUid, kClientUseCallingPid, &client);
    Status status = mService->registerClient(mClientCallback, kInvalidClientName,
                                             kInvalidClientOpPackageName, kClientUseCallingUid,
                                             kClientUseCallingPid, &client);
    EXPECT_FALSE(status.isOk());
}

@@ -160,8 +188,8 @@ TEST_F(MediaTranscodingServiceTest, TestRegisterClientWithInvalidClientPackageNa
    std::shared_ptr<ITranscodingClient> client;

    // Register the client with the service.
    Status status = mService->registerClient(
            mClientListener, kClientName, kInvalidClientOpPackageName,
    Status status =
            mService->registerClient(mClientCallback, kClientName, kInvalidClientOpPackageName,
                                     kClientUseCallingUid, kClientUseCallingPid, &client);
    EXPECT_FALSE(status.isOk());
}
@@ -169,8 +197,7 @@ TEST_F(MediaTranscodingServiceTest, TestRegisterClientWithInvalidClientPackageNa
TEST_F(MediaTranscodingServiceTest, TestRegisterOneClient) {
    std::shared_ptr<ITranscodingClient> client;

    Status status = mService->registerClient(
            mClientListener, kClientName, kClientOpPackageName,
    Status status = mService->registerClient(mClientCallback, kClientName, kClientOpPackageName,
                                             kClientUseCallingUid, kClientUseCallingPid, &client);
    EXPECT_TRUE(status.isOk());

@@ -196,8 +223,7 @@ TEST_F(MediaTranscodingServiceTest, TestRegisterOneClient) {
TEST_F(MediaTranscodingServiceTest, TestRegisterClientTwice) {
    std::shared_ptr<ITranscodingClient> client;

    Status status = mService->registerClient(
            mClientListener, kClientName, kClientOpPackageName,
    Status status = mService->registerClient(mClientCallback, kClientName, kClientOpPackageName,
                                             kClientUseCallingUid, kClientUseCallingPid, &client);
    EXPECT_TRUE(status.isOk());

@@ -206,8 +232,7 @@ TEST_F(MediaTranscodingServiceTest, TestRegisterClientTwice) {

    // Register the client again and expects failure.
    std::shared_ptr<ITranscodingClient> client1;
    status = mService->registerClient(
            mClientListener, kClientName, kClientOpPackageName,
    status = mService->registerClient(mClientCallback, kClientName, kClientOpPackageName,
                                      kClientUseCallingUid, kClientUseCallingPid, &client1);
    EXPECT_FALSE(status.isOk());

@@ -217,49 +242,80 @@ TEST_F(MediaTranscodingServiceTest, TestRegisterClientTwice) {
}

TEST_F(MediaTranscodingServiceTest, TestRegisterMultipleClients) {
    std::shared_ptr<ITranscodingClient> client1;
    std::shared_ptr<ITranscodingClient> client2;
    std::shared_ptr<ITranscodingClient> client3;

    // Register 3 clients.
    Status status = mService->registerClient(
            mClientListener, kClientName, kClientOpPackageName,
            kClientUseCallingUid, kClientUseCallingPid, &client1);
    EXPECT_TRUE(status.isOk());
    EXPECT_TRUE(client1 != nullptr);

    status = mService->registerClient(
            mClientListener2, kClientName, kClientOpPackageName,
            kClientUseCallingUid, kClientUseCallingPid, &client2);
    EXPECT_TRUE(status.isOk());
    EXPECT_TRUE(client2 != nullptr);

    status = mService->registerClient(
            mClientListener3, kClientName, kClientOpPackageName,
            kClientUseCallingUid, kClientUseCallingPid, &client3);
    EXPECT_TRUE(status.isOk());
    EXPECT_TRUE(client3 != nullptr);

    // Check the number of clients.
    int32_t numOfClients;
    status = mService->getNumOfClients(&numOfClients);
    EXPECT_TRUE(status.isOk());
    EXPECT_EQ(3, numOfClients);

    // Unregister the clients.
    status = client1->unregister();
    EXPECT_TRUE(status.isOk());

    status = client2->unregister();
    EXPECT_TRUE(status.isOk());

    status = client3->unregister();
    EXPECT_TRUE(status.isOk());
    registerMultipleClients();
    unregisterMultipleClients();
}

    // Check the number of clients.
    status = mService->getNumOfClients(&numOfClients);
    EXPECT_TRUE(status.isOk());
    EXPECT_EQ(0, numOfClients);
TEST_F(MediaTranscodingServiceTest, TestSubmitCancelGetJobs) {
    registerMultipleClients();

    // Test jobId assignment.
    TranscodingRequestParcel request;
    request.fileName = "test_file_0";
    TranscodingJobParcel job;
    bool result;
    EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
    EXPECT_TRUE(result);
    EXPECT_EQ(job.jobId, 0);

    request.fileName = "test_file_1";
    EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
    EXPECT_TRUE(result);
    EXPECT_EQ(job.jobId, 1);

    request.fileName = "test_file_2";
    EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
    EXPECT_TRUE(result);
    EXPECT_EQ(job.jobId, 2);

    // Test submit bad request (no valid fileName) fails.
    TranscodingRequestParcel badRequest;
    EXPECT_TRUE(mClient1->submitRequest(badRequest, &job, &result).isOk());
    EXPECT_FALSE(result);

    // Test get jobs by id.
    EXPECT_TRUE(mClient1->getJobWithId(2, &job, &result).isOk());
    EXPECT_EQ(job.jobId, 2);
    EXPECT_EQ(job.request.fileName, "test_file_2");
    EXPECT_TRUE(result);

    // Test get jobs by invalid id fails.
    EXPECT_TRUE(mClient1->getJobWithId(100, &job, &result).isOk());
    EXPECT_FALSE(result);

    // Test cancel non-existent job fail.
    EXPECT_TRUE(mClient2->cancelJob(100, &result).isOk());
    EXPECT_FALSE(result);

    // Test cancel valid jobId in arbitrary order.
    EXPECT_TRUE(mClient1->cancelJob(2, &result).isOk());
    EXPECT_TRUE(result);

    EXPECT_TRUE(mClient1->cancelJob(0, &result).isOk());
    EXPECT_TRUE(result);

    EXPECT_TRUE(mClient1->cancelJob(1, &result).isOk());
    EXPECT_TRUE(result);

    // Test cancel job again fails.
    EXPECT_TRUE(mClient1->cancelJob(1, &result).isOk());
    EXPECT_FALSE(result);

    // Test get job after cancel fails.
    EXPECT_TRUE(mClient1->getJobWithId(2, &job, &result).isOk());
    EXPECT_FALSE(result);

    // Test jobId independence for each client.
    EXPECT_TRUE(mClient2->submitRequest(request, &job, &result).isOk());
    EXPECT_TRUE(result);
    EXPECT_EQ(job.jobId, 0);

    EXPECT_TRUE(mClient2->submitRequest(request, &job, &result).isOk());
    EXPECT_TRUE(result);
    EXPECT_EQ(job.jobId, 1);

    unregisterMultipleClients();
}

}  // namespace media
}  // namespace android