blob: e9eebe25d8e213348224e4300d551381a086a028 [file] [log] [blame]
/*
* 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<fail>(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<fail>(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<fail>(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<fail>(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