/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // Unit Test for MediaTranscodingService. //#define LOG_NDEBUG 0 #define LOG_TAG "MediaTranscodingServiceRealTest" #include "MediaTranscodingServiceTestHelper.h" /* * Tests media transcoding service with real transcoder. * * Uses the same test assets as the MediaTranscoder unit tests. Before running the test, * please make sure to push the test assets to /sdcard: * * adb push $TOP/frameworks/av/media/libmediatranscoding/transcoder/tests/assets /data/local/tmp/TranscodingTestAssets */ namespace android { namespace media { constexpr int64_t kPaddingUs = 1000000; constexpr int64_t kSessionWithPaddingUs = 10000000 + kPaddingUs; constexpr int32_t kBitRate = 8 * 1000 * 1000; // 8Mbs constexpr const char* kShortSrcPath = "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4"; constexpr const char* kLongSrcPath = "/data/local/tmp/TranscodingTestAssets/longtest_15s.mp4"; #define OUTPATH(name) "/data/local/tmp/MediaTranscodingService_" #name ".MP4" class MediaTranscodingServiceRealTest : public MediaTranscodingServiceTestBase { public: MediaTranscodingServiceRealTest() { ALOGI("MediaTranscodingServiceResourceTest created"); } virtual ~MediaTranscodingServiceRealTest() { ALOGI("MediaTranscodingServiceResourceTest destroyed"); } }; TEST_F(MediaTranscodingServiceRealTest, TestInvalidSource) { registerMultipleClients(); const char* srcPath = "bad_file_uri"; const char* dstPath = prepareOutputFile(OUTPATH(TestInvalidSource)); // Submit one session. EXPECT_TRUE( mClient1->submit(0, srcPath, dstPath, TranscodingSessionPriority::kNormal, kBitRate)); // Check expected error. EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Failed(CLIENT(1), 0)); EXPECT_EQ(mClient1->getLastError(), TranscodingErrorCode::kErrorIO); unregisterMultipleClients(); } TEST_F(MediaTranscodingServiceRealTest, TestPassthru) { registerMultipleClients(); const char* dstPath = prepareOutputFile(OUTPATH(TestPassthru)); // Submit one session. EXPECT_TRUE(mClient1->submit(0, kShortSrcPath, dstPath)); // Wait for session to finish. EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0)); EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 0)); unregisterMultipleClients(); } TEST_F(MediaTranscodingServiceRealTest, TestTranscodeVideo) { registerMultipleClients(); const char* dstPath = prepareOutputFile(OUTPATH(TestTranscodeVideo)); // Submit one session. EXPECT_TRUE(mClient1->submit(0, kShortSrcPath, dstPath, TranscodingSessionPriority::kNormal, kBitRate)); // Wait for session to finish. EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0)); EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 0)); unregisterMultipleClients(); } TEST_F(MediaTranscodingServiceRealTest, TestTranscodeVideoProgress) { registerMultipleClients(); const char* dstPath = prepareOutputFile(OUTPATH(TestTranscodeVideoProgress)); // Submit one session. EXPECT_TRUE(mClient1->submit(0, kLongSrcPath, dstPath, TranscodingSessionPriority::kNormal, kBitRate)); // Wait for session to finish. EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0)); EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 0)); // Check the progress update messages are received. For this clip (around ~15 second long), // expect at least 10 updates, and the last update should be 100. int lastProgress; EXPECT_GE(mClient1->getUpdateCount(&lastProgress), 10); EXPECT_EQ(lastProgress, 100); unregisterMultipleClients(); } /* * Test cancel immediately after start. */ TEST_F(MediaTranscodingServiceRealTest, TestCancelImmediately) { registerMultipleClients(); const char* srcPath0 = kLongSrcPath; const char* srcPath1 = kShortSrcPath; const char* dstPath0 = prepareOutputFile(OUTPATH(TestCancelImmediately_Session0)); const char* dstPath1 = prepareOutputFile(OUTPATH(TestCancelImmediately_Session1)); // Submit one session, should start immediately. EXPECT_TRUE( mClient1->submit(0, srcPath0, dstPath0, TranscodingSessionPriority::kNormal, kBitRate)); EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0)); EXPECT_TRUE(mClient1->getSession(0, srcPath0, dstPath0)); // Test cancel session immediately, getSession should fail after cancel. EXPECT_TRUE(mClient1->cancel(0)); EXPECT_TRUE(mClient1->getSession(0, "", "")); // Submit new session, new session should start immediately and finish. EXPECT_TRUE( mClient1->submit(1, srcPath1, dstPath1, TranscodingSessionPriority::kNormal, kBitRate)); EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 1)); EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 1)); unregisterMultipleClients(); } /* * Test cancel in the middle of transcoding. */ TEST_F(MediaTranscodingServiceRealTest, TestCancelWhileRunning) { registerMultipleClients(); const char* srcPath0 = kLongSrcPath; const char* srcPath1 = kShortSrcPath; const char* dstPath0 = prepareOutputFile(OUTPATH(TestCancelWhileRunning_Session0)); const char* dstPath1 = prepareOutputFile(OUTPATH(TestCancelWhileRunning_Session1)); // Submit two sessions, session 0 should start immediately, session 1 should be queued. EXPECT_TRUE( mClient1->submit(0, srcPath0, dstPath0, TranscodingSessionPriority::kNormal, kBitRate)); EXPECT_TRUE( mClient1->submit(1, srcPath1, dstPath1, TranscodingSessionPriority::kNormal, kBitRate)); EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0)); EXPECT_TRUE(mClient1->getSession(0, srcPath0, dstPath0)); EXPECT_TRUE(mClient1->getSession(1, srcPath1, dstPath1)); // Session 0 (longtest) shouldn't finish in 1 seconds. EXPECT_EQ(mClient1->pop(1000000), EventTracker::NoEvent); // Now cancel session 0. Session 1 should start immediately and finish. EXPECT_TRUE(mClient1->cancel(0)); EXPECT_TRUE(mClient1->getSession(0, "", "")); EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 1)); EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 1)); unregisterMultipleClients(); } TEST_F(MediaTranscodingServiceRealTest, TestPauseResumeSingleClient) { registerMultipleClients(); const char* srcPath0 = kLongSrcPath; const char* srcPath1 = kShortSrcPath; const char* dstPath0 = prepareOutputFile(OUTPATH(TestPauseResumeSingleClient_Session0)); const char* dstPath1 = prepareOutputFile(OUTPATH(TestPauseResumeSingleClient_Session1)); // Submit one offline session, should start immediately. EXPECT_TRUE(mClient1->submit(0, srcPath0, dstPath0, TranscodingSessionPriority::kUnspecified, kBitRate)); EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0)); // Test get session after starts. EXPECT_TRUE(mClient1->getSession(0, srcPath0, dstPath0)); // Submit one realtime session. EXPECT_TRUE( mClient1->submit(1, srcPath1, dstPath1, TranscodingSessionPriority::kNormal, kBitRate)); // Offline session should pause. EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Pause(CLIENT(1), 0)); EXPECT_TRUE(mClient1->getSession(0, srcPath0, dstPath0)); // Realtime session should start immediately, and run to finish. EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 1)); EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 1)); // Test get session after finish fails. EXPECT_TRUE(mClient1->getSession(1, "", "")); // Then offline session should resume. EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Resume(CLIENT(1), 0)); // Test get session after resume. EXPECT_TRUE(mClient1->getSession(0, srcPath0, dstPath0)); // Offline session should finish. EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 0)); // Test get session after finish fails. EXPECT_TRUE(mClient1->getSession(0, "", "")); unregisterMultipleClients(); } /* * Basic test for pause/resume with two clients, with one session each. * Top app's session should preempt the other app's session. */ TEST_F(MediaTranscodingServiceRealTest, TestPauseResumeMultiClients) { ALOGD("TestPauseResumeMultiClients starting..."); dismissKeyguard(); stopAppPackages(); registerMultipleClients(); const char* srcPath0 = kLongSrcPath; const char* srcPath1 = kShortSrcPath; const char* dstPath0 = prepareOutputFile(OUTPATH(TestPauseResumeMultiClients_Client0)); const char* dstPath1 = prepareOutputFile(OUTPATH(TestPauseResumeMultiClients_Client1)); ALOGD("Moving app A to top..."); EXPECT_TRUE(ShellHelper::Start(kClientPackageA, kTestActivityName)); // Submit session to Client1. ALOGD("Submitting session to client1 (app A) ..."); EXPECT_TRUE( mClient1->submit(0, srcPath0, dstPath0, TranscodingSessionPriority::kNormal, kBitRate)); // Client1's session should start immediately. EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0)); ALOGD("Moving app B to top..."); EXPECT_TRUE(ShellHelper::Start(kClientPackageB, kTestActivityName)); // Client1's session should continue to run, since Client2 (app B) doesn't have any session. EXPECT_EQ(mClient1->pop(1000000), EventTracker::NoEvent); // Submit session to Client2. ALOGD("Submitting session to client2 (app B) ..."); EXPECT_TRUE( mClient2->submit(0, srcPath1, dstPath1, TranscodingSessionPriority::kNormal, kBitRate)); // Client1's session should pause, client2's session should start. EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Pause(CLIENT(1), 0)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Start(CLIENT(2), 0)); // Client2's session should finish, then Client1's session should resume. EXPECT_EQ(mClient2->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(2), 0)); EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Resume(CLIENT(1), 0)); // Client1's session should finish. EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 0)); unregisterMultipleClients(); stopAppPackages(); ALOGD("TestPauseResumeMultiClients finished."); } TEST_F(MediaTranscodingServiceRealTest, TestUidGoneForeground) { ALOGD("TestUidGoneForeground starting..."); dismissKeyguard(); stopAppPackages(); registerMultipleClients(); const char* dstPath0 = prepareOutputFile(OUTPATH(TestUidGoneForegroundSession0)); const char* dstPath1 = prepareOutputFile(OUTPATH(TestUidGoneForegroundSession1)); // Test kill foreground app, using only 1 uid. ALOGD("Moving app A to top..."); EXPECT_TRUE(ShellHelper::Start(kClientPackageA, kTestActivityName)); // Submit sessions to Client1 (app A). ALOGD("Submitting sessions to client1 (app A) ..."); EXPECT_TRUE(mClient1->submit(0, kLongSrcPath, dstPath0, TranscodingSessionPriority::kNormal, kBitRate)); EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0)); EXPECT_TRUE(mClient1->submit(1, kLongSrcPath, dstPath1, TranscodingSessionPriority::kNormal, kBitRate)); EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::NoEvent); // Kill app A, expect to see A's session pause followed by B's session start, // then A's session cancelled with error code kUidGoneCancelled. EXPECT_TRUE(ShellHelper::Stop(kClientPackageA)); EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Failed(CLIENT(1), 0)); EXPECT_EQ(mClient1->getLastError(), TranscodingErrorCode::kUidGoneCancelled); EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Failed(CLIENT(1), 1)); EXPECT_EQ(mClient1->getLastError(), TranscodingErrorCode::kUidGoneCancelled); unregisterMultipleClients(); stopAppPackages(); ALOGD("TestUidGoneForeground finished."); } TEST_F(MediaTranscodingServiceRealTest, TestUidGoneForegroundMultiUids) { ALOGD("TestUidGoneForegroundMultiUids starting..."); dismissKeyguard(); stopAppPackages(); registerMultipleClients(); const char* dstPath0 = prepareOutputFile(OUTPATH(TestUidGoneForegroundSession0)); const char* dstPath1 = prepareOutputFile(OUTPATH(TestUidGoneForegroundSession1)); // Test kill foreground app, using two uids. ALOGD("Moving app B to top..."); EXPECT_TRUE(ShellHelper::Start(kClientPackageB, kTestActivityName)); EXPECT_TRUE(mClient2->submit(0, kLongSrcPath, dstPath0, TranscodingSessionPriority::kNormal, kBitRate)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Start(CLIENT(2), 0)); EXPECT_TRUE(mClient2->submit(1, kLongSrcPath, dstPath1, TranscodingSessionPriority::kNormal, kBitRate)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::NoEvent); // Make app A also requesting session 1. EXPECT_TRUE(mClient2->addClientUid(1, mClient1->mClientUid)); ALOGD("Moving app A to top..."); EXPECT_TRUE(ShellHelper::Start(kClientPackageA, kTestActivityName)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Pause(CLIENT(2), 0)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Start(CLIENT(2), 1)); // Kill app A, CLIENT(2)'s session 1 should continue because it's also requested by app B. EXPECT_TRUE(ShellHelper::Stop(kClientPackageA)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::NoEvent); // Kill app B, sessions should be cancelled. EXPECT_TRUE(ShellHelper::Stop(kClientPackageB)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Failed(CLIENT(2), 0)); EXPECT_EQ(mClient2->getLastError(), TranscodingErrorCode::kUidGoneCancelled); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Failed(CLIENT(2), 1)); EXPECT_EQ(mClient2->getLastError(), TranscodingErrorCode::kUidGoneCancelled); unregisterMultipleClients(); stopAppPackages(); ALOGD("TestUidGoneForegroundMultiUids finished."); } TEST_F(MediaTranscodingServiceRealTest, TestUidGoneBackground) { ALOGD("TestUidGoneBackground starting..."); dismissKeyguard(); stopAppPackages(); registerMultipleClients(); const char* dstPath0 = prepareOutputFile(OUTPATH(TestUidGoneForegroundSession0)); const char* dstPath1 = prepareOutputFile(OUTPATH(TestUidGoneForegroundSession1)); // Test kill background app, using two uids. ALOGD("Moving app B to top..."); EXPECT_TRUE(ShellHelper::Start(kClientPackageB, kTestActivityName)); EXPECT_TRUE(mClient2->submit(0, kLongSrcPath, dstPath0, TranscodingSessionPriority::kNormal, kBitRate)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Start(CLIENT(2), 0)); EXPECT_TRUE(mClient2->submit(1, kLongSrcPath, dstPath1, TranscodingSessionPriority::kNormal, kBitRate)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::NoEvent); ALOGD("Moving app A to top..."); EXPECT_TRUE(ShellHelper::Start(kClientPackageA, kTestActivityName)); EXPECT_TRUE(mClient1->submit(0, kLongSrcPath, dstPath0, TranscodingSessionPriority::kNormal, kBitRate)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Pause(CLIENT(2), 0)); EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0)); // Kill app B, all its sessions should be cancelled. EXPECT_TRUE(ShellHelper::Stop(kClientPackageB)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Failed(CLIENT(2), 0)); EXPECT_EQ(mClient2->getLastError(), TranscodingErrorCode::kUidGoneCancelled); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Failed(CLIENT(2), 1)); EXPECT_EQ(mClient2->getLastError(), TranscodingErrorCode::kUidGoneCancelled); unregisterMultipleClients(); stopAppPackages(); ALOGD("TestUidGoneBackground finished."); } TEST_F(MediaTranscodingServiceRealTest, TestUidGoneBackgroundMultiUids) { ALOGD("TestUidGoneBackgroundMultiUids starting..."); dismissKeyguard(); stopAppPackages(); registerMultipleClients(); const char* dstPath0 = prepareOutputFile(OUTPATH(TestUidGoneForegroundSession0)); const char* dstPath1 = prepareOutputFile(OUTPATH(TestUidGoneForegroundSession1)); // Test kill background app, using two uids. ALOGD("Moving app B to top..."); EXPECT_TRUE(ShellHelper::Start(kClientPackageB, kTestActivityName)); EXPECT_TRUE(mClient2->submit(0, kLongSrcPath, dstPath0, TranscodingSessionPriority::kNormal, kBitRate)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Start(CLIENT(2), 0)); EXPECT_TRUE(mClient2->submit(1, kLongSrcPath, dstPath1, TranscodingSessionPriority::kNormal, kBitRate)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::NoEvent); // Make app A also requesting session 1. EXPECT_TRUE(mClient2->addClientUid(1, mClient1->mClientUid)); ALOGD("Moving app A to top..."); EXPECT_TRUE(ShellHelper::Start(kClientPackageA, kTestActivityName)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Pause(CLIENT(2), 0)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Start(CLIENT(2), 1)); // Kill app B, CLIENT(2)'s session 1 should continue to run, session 0 on // the other hand should be cancelled. EXPECT_TRUE(ShellHelper::Stop(kClientPackageB)); EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Failed(CLIENT(2), 0)); EXPECT_EQ(mClient2->getLastError(), TranscodingErrorCode::kUidGoneCancelled); unregisterMultipleClients(); stopAppPackages(); ALOGD("TestUidGoneBackgroundMultiUids finished."); } } // namespace media } // namespace android