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
diff --git a/services/mediatranscoding/MediaTranscodingService.cpp b/services/mediatranscoding/MediaTranscodingService.cpp
index b441449..0289613 100644
--- a/services/mediatranscoding/MediaTranscodingService.cpp
+++ b/services/mediatranscoding/MediaTranscodingService.cpp
@@ -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 @@
     }
 }
 
+// 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 @@
     write(fd, result.string(), result.size());
 
     Vector<String16> args;
-    mTranscodingClientManager.dumpAllClients(fd, args);
+    mClientManager->dumpAllClients(fd, args);
     return OK;
 }
 
@@ -80,13 +116,11 @@
 }
 
 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 @@
     // 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::getNumOfClients(int32_t* _aidl_return) {
     ALOGD("MediaTranscodingService::getNumOfClients");
-    *_aidl_return = mTranscodingClientManager.getNumOfClients();
+    *_aidl_return = mClientManager->getNumOfClients();
     return Status::ok();
 }
 
diff --git a/services/mediatranscoding/MediaTranscodingService.h b/services/mediatranscoding/MediaTranscodingService.h
index 785bc4d..36db9b3 100644
--- a/services/mediatranscoding/MediaTranscodingService.h
+++ b/services/mediatranscoding/MediaTranscodingService.h
@@ -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 @@
     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,
-            int32_t in_clientUid, int32_t in_clientPid,
-            std::shared_ptr<ITranscodingClient>* _aidl_return) override;
+    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
diff --git a/services/mediatranscoding/tests/build_and_run_all_unit_tests.sh b/services/mediatranscoding/tests/build_and_run_all_unit_tests.sh
index bcdc7f7..ce017d7 100644
--- a/services/mediatranscoding/tests/build_and_run_all_unit_tests.sh
+++ b/services/mediatranscoding/tests/build_and_run_all_unit_tests.sh
@@ -20,4 +20,5 @@
 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
diff --git a/services/mediatranscoding/tests/mediatranscodingservice_tests.cpp b/services/mediatranscoding/tests/mediatranscodingservice_tests.cpp
index accfd03..351f830 100644
--- a/services/mediatranscoding/tests/mediatranscodingservice_tests.cpp
+++ b/services/mediatranscoding/tests/mediatranscodingservice_tests.cpp
@@ -14,15 +14,17 @@
  * limitations under the License.
  */
 
-// Unit Test for MediaTranscoding Service.
+// Unit Test for MediaTranscodingService.
 
 //#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 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 @@
 
 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,25 +99,69 @@
             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,
-            kClientUseCallingUid, kClientUseCallingPid, &client);
+    // Register the client with null callback.
+    Status status = mService->registerClient(nullptr, kClientName, kClientOpPackageName,
+                                             kClientUseCallingUid, kClientUseCallingPid, &client);
     EXPECT_FALSE(status.isOk());
 }
 
@@ -130,19 +169,8 @@
     std::shared_ptr<ITranscodingClient> client;
 
     // Register the client with the service.
-    Status status = mService->registerClient(
-            mClientListener, 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);
+    Status status = mService->registerClient(mClientCallback, kClientName, kClientOpPackageName,
+                                             kClientUseCallingUid, kInvalidClientPid, &client);
     EXPECT_FALSE(status.isOk());
 }
 
@@ -150,9 +178,9 @@
     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,18 +188,17 @@
     std::shared_ptr<ITranscodingClient> client;
 
     // Register the client with the service.
-    Status status = mService->registerClient(
-            mClientListener, kClientName, kInvalidClientOpPackageName,
-            kClientUseCallingUid, kClientUseCallingPid, &client);
+    Status status =
+            mService->registerClient(mClientCallback, kClientName, kInvalidClientOpPackageName,
+                                     kClientUseCallingUid, kClientUseCallingPid, &client);
     EXPECT_FALSE(status.isOk());
 }
 
 TEST_F(MediaTranscodingServiceTest, TestRegisterOneClient) {
     std::shared_ptr<ITranscodingClient> client;
 
-    Status status = mService->registerClient(
-            mClientListener, kClientName, kClientOpPackageName,
-            kClientUseCallingUid, kClientUseCallingPid, &client);
+    Status status = mService->registerClient(mClientCallback, kClientName, kClientOpPackageName,
+                                             kClientUseCallingUid, kClientUseCallingPid, &client);
     EXPECT_TRUE(status.isOk());
 
     // Validate the client.
@@ -196,9 +223,8 @@
 TEST_F(MediaTranscodingServiceTest, TestRegisterClientTwice) {
     std::shared_ptr<ITranscodingClient> client;
 
-    Status status = mService->registerClient(
-            mClientListener, kClientName, kClientOpPackageName,
-            kClientUseCallingUid, kClientUseCallingPid, &client);
+    Status status = mService->registerClient(mClientCallback, kClientName, kClientOpPackageName,
+                                             kClientUseCallingUid, kClientUseCallingPid, &client);
     EXPECT_TRUE(status.isOk());
 
     // Validate the client.
@@ -206,9 +232,8 @@
 
     // Register the client again and expects failure.
     std::shared_ptr<ITranscodingClient> client1;
-    status = mService->registerClient(
-            mClientListener, kClientName, kClientOpPackageName,
-            kClientUseCallingUid, kClientUseCallingPid, &client1);
+    status = mService->registerClient(mClientCallback, kClientName, kClientOpPackageName,
+                                      kClientUseCallingUid, kClientUseCallingPid, &client1);
     EXPECT_FALSE(status.isOk());
 
     // Unregister the client.
@@ -217,49 +242,80 @@
 }
 
 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());
-
-    // Check the number of clients.
-    status = mService->getNumOfClients(&numOfClients);
-    EXPECT_TRUE(status.isOk());
-    EXPECT_EQ(0, numOfClients);
+    registerMultipleClients();
+    unregisterMultipleClients();
 }
+
+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