From 3b285d600d8ab23b9b661658e571c9524eff2a99 Mon Sep 17 00:00:00 2001 From: hkuang Date: Thu, 4 Jun 2020 15:01:27 -0700 Subject: [PATCH] Transcoding: Test api with actual service. Also adding the new start/pause/resume handling in client callback. Bug: 145628554 Test: Build Change-Id: Ie059a57b4d2552067df0cecb512e1fbabc683037 --- .../android/media/MediaTranscodeManager.java | 33 +++- .../MediaTranscodeManagerTest.java | 162 ++++++++++++++++++ ...iaTranscodeManagerWithMockServiceTest.java | 9 +- .../MediaTranscodingTestRunner.java | 1 + 4 files changed, 194 insertions(+), 11 deletions(-) create mode 100644 media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java diff --git a/media/java/android/media/MediaTranscodeManager.java b/media/java/android/media/MediaTranscodeManager.java index b8679085e55ef..5017018b21a62 100644 --- a/media/java/android/media/MediaTranscodeManager.java +++ b/media/java/android/media/MediaTranscodeManager.java @@ -260,6 +260,21 @@ public final class MediaTranscodeManager { return null; } + @Override + public void onTranscodingStarted(int jobId) throws RemoteException { + + } + + @Override + public void onTranscodingPaused(int jobId) throws RemoteException { + + } + + @Override + public void onTranscodingResumed(int jobId) throws RemoteException { + + } + @Override public void onTranscodingFinished(int jobId, TranscodingResultParcel result) throws RemoteException { @@ -306,6 +321,7 @@ public final class MediaTranscodeManager { } } + public static final class TranscodingRequest { /** Uri of the source media file. */ private @NonNull Uri mSourceUri; @@ -344,7 +360,7 @@ public final class MediaTranscodeManager { private @Nullable MediaFormat mImageFormat = null; @VisibleForTesting - private int mProcessingDelayMs = 0; + private TranscodingTestConfig mTestConfig = null; private TranscodingRequest(Builder b) { mSourceUri = b.mSourceUri; @@ -354,7 +370,7 @@ public final class MediaTranscodeManager { mVideoTrackFormat = b.mVideoTrackFormat; mAudioTrackFormat = b.mAudioTrackFormat; mImageFormat = b.mImageFormat; - mProcessingDelayMs = b.mProcessingDelayMs; + mTestConfig = b.mTestConfig; } /** Return the type of the transcoding. */ @@ -397,10 +413,9 @@ public final class MediaTranscodeManager { parcel.transcodingType = mType; parcel.sourceFilePath = mSourceUri.getPath(); parcel.destinationFilePath = mDestinationUri.getPath(); - if (mProcessingDelayMs != 0) { + if (mTestConfig != null) { parcel.isForTesting = true; - parcel.testConfig = new TranscodingTestConfig(); - parcel.testConfig.processingDelayMs = mProcessingDelayMs; + parcel.testConfig = mTestConfig; } return parcel; } @@ -417,7 +432,7 @@ public final class MediaTranscodeManager { private @Nullable MediaFormat mVideoTrackFormat; private @Nullable MediaFormat mAudioTrackFormat; private @Nullable MediaFormat mImageFormat; - private int mProcessingDelayMs = 0; + private TranscodingTestConfig mTestConfig; /** * Specifies the uri of source media file. @@ -525,12 +540,12 @@ public final class MediaTranscodeManager { /** * Sets the delay in processing this request. - * @param processingDelayMs delay in milliseconds. + * @param config test config. * @return The same builder instance. */ @VisibleForTesting - public Builder setProcessingDelayMs(int processingDelayMs) { - mProcessingDelayMs = processingDelayMs; + public Builder setTestConfig(TranscodingTestConfig config) { + mTestConfig = config; return this; } diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java new file mode 100644 index 0000000000000..5b43906cc5544 --- /dev/null +++ b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2020 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. + */ + +package com.android.mediatranscodingtest; + +import android.content.ContentResolver; +import android.content.Context; +import android.media.MediaFormat; +import android.media.MediaTranscodeManager; +import android.media.MediaTranscodeManager.TranscodingJob; +import android.media.MediaTranscodeManager.TranscodingRequest; +import android.media.TranscodingTestConfig; +import android.net.Uri; +import android.test.ActivityInstrumentationTestCase2; +import android.util.Log; + +import org.junit.Test; + +import java.io.File; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +/* + * Functional tests for MediaTranscodeManager in the media framework. + * The test uses actual media.Transcoding service as backend to fully + * test the API functionality. + * + * To run this test suite: + make frameworks/base/media/tests/MediaTranscodingTest + make mediatranscodingtest + + adb install -r testcases/mediatranscodingtest/arm64/mediatranscodingtest.apk + + adb shell am instrument -e class \ + com.android.mediatranscodingtest.MediaTranscodeManagerTest \ + -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner + * + */ +public class MediaTranscodeManagerTest + extends ActivityInstrumentationTestCase2 { + private static final String TAG = "MediaTranscodeManagerTest"; + /** The time to wait for the transcode operation to complete before failing the test. */ + private static final int TRANSCODE_TIMEOUT_SECONDS = 2; + private Context mContext; + private MediaTranscodeManager mMediaTranscodeManager = null; + private Uri mSourceHEVCVideoUri = null; + private Uri mDestinationUri = null; + + // Setting for transcoding to H.264. + private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC; + private static final int BIT_RATE = 2000000; // 2Mbps + private static final int WIDTH = 1920; + private static final int HEIGHT = 1080; + + public MediaTranscodeManagerTest() { + super("com.android.MediaTranscodeManagerTest", MediaTranscodingTest.class); + } + + + private static Uri resourceToUri(Context context, int resId) { + Uri uri = new Uri.Builder() + .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) + .authority(context.getResources().getResourcePackageName(resId)) + .appendPath(context.getResources().getResourceTypeName(resId)) + .appendPath(context.getResources().getResourceEntryName(resId)) + .build(); + return uri; + } + + private static Uri generateNewUri(Context context, String filename) { + File outFile = new File(context.getExternalCacheDir(), filename); + return Uri.fromFile(outFile); + } + + // Generates a invalid uri which will let the mock service return transcoding failure. + private static Uri generateInvalidTranscodingUri(Context context) { + File outFile = new File(context.getExternalCacheDir(), "InvalidUri.mp4"); + return Uri.fromFile(outFile); + } + + /** + * Creates a MediaFormat with the basic set of values. + */ + private static MediaFormat createMediaFormat() { + MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, WIDTH, HEIGHT); + format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE); + return format; + } + + @Override + public void setUp() throws Exception { + Log.d(TAG, "setUp"); + super.setUp(); + mContext = getInstrumentation().getContext(); + mMediaTranscodeManager = MediaTranscodeManager.getInstance(mContext); + assertNotNull(mMediaTranscodeManager); + + // Setup source HEVC file uri. + mSourceHEVCVideoUri = resourceToUri(mContext, R.raw.VideoOnlyHEVC); + + // Setup destination file. + mDestinationUri = generateNewUri(mContext, "transcoded.mp4"); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public void testTranscodingOneVideo() throws Exception { + Log.d(TAG, "Starting: testMediaTranscodeManager"); + + Semaphore transcodeCompleteSemaphore = new Semaphore(0); + TranscodingTestConfig testConfig = new TranscodingTestConfig(); + testConfig.passThroughMode = true; + testConfig.processingTotalTimeMs = 300; // minimum time spent on transcoding. + + TranscodingRequest request = + new TranscodingRequest.Builder() + .setSourceUri(mSourceHEVCVideoUri) + .setDestinationUri(mDestinationUri) + .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO) + .setPriority(MediaTranscodeManager.PRIORITY_REALTIME) + .setVideoTrackFormat(createMediaFormat()) + .setTestConfig(testConfig) + .build(); + Executor listenerExecutor = Executors.newSingleThreadExecutor(); + + TranscodingJob job = mMediaTranscodeManager.enqueueRequest(request, listenerExecutor, + transcodingJob -> { + Log.d(TAG, "Transcoding completed with result: " + transcodingJob.getResult()); + assertEquals(transcodingJob.getResult(), TranscodingJob.RESULT_SUCCESS); + transcodeCompleteSemaphore.release(); + }); + assertNotNull(job); + + if (job != null) { + Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to complete."); + boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire( + TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS); + assertTrue("Transcode failed to complete in time.", finishedOnTime); + } + } + +} + diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerWithMockServiceTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerWithMockServiceTest.java index 00f8a9edf3d4b..8b7f665779917 100644 --- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerWithMockServiceTest.java +++ b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerWithMockServiceTest.java @@ -30,6 +30,7 @@ import android.media.MediaTranscodeManager.TranscodingRequest; import android.media.TranscodingJobParcel; import android.media.TranscodingRequestParcel; import android.media.TranscodingResultParcel; +import android.media.TranscodingTestConfig; import android.net.Uri; import android.os.RemoteException; import android.test.ActivityInstrumentationTestCase2; @@ -144,7 +145,7 @@ public class MediaTranscodeManagerWithMockServiceTest new ProcessingJobRunnable(callback, outjob, mPendingTranscodingJobs), inRequest.testConfig == null ? 0 - : inRequest.testConfig.processingDelayMs, + : inRequest.testConfig.processingTotalTimeMs, TimeUnit.MILLISECONDS); mPendingTranscodingJobs.put(outjob.jobId, transcodingFuture); } catch (RejectedExecutionException e) { @@ -353,6 +354,10 @@ public class MediaTranscodeManagerWithMockServiceTest Log.d(TAG, "Starting: testMediaTranscodeManager"); Semaphore transcodeCompleteSemaphore = new Semaphore(0); + TranscodingTestConfig testConfig = new TranscodingTestConfig(); + testConfig.passThroughMode = true; + testConfig.processingTotalTimeMs = 300; // minimum time spent on transcoding. + TranscodingRequest request = new TranscodingRequest.Builder() .setSourceUri(mSourceHEVCVideoUri) @@ -360,7 +365,7 @@ public class MediaTranscodeManagerWithMockServiceTest .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO) .setPriority(MediaTranscodeManager.PRIORITY_REALTIME) .setVideoTrackFormat(createMediaFormat()) - .setProcessingDelayMs(300 /* delayMs */) + .setTestConfig(testConfig) .build(); Executor listenerExecutor = Executors.newSingleThreadExecutor(); diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java index af0a754c89db8..3b044c7e37075 100644 --- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java +++ b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java @@ -36,6 +36,7 @@ public class MediaTranscodingTestRunner extends InstrumentationTestRunner { @Override public TestSuite getAllTests() { TestSuite suite = new InstrumentationTestSuite(this); + suite.addTestSuite(MediaTranscodeManagerTest.class); suite.addTestSuite(MediaTranscodeManagerWithMockServiceTest.class); return suite; }