Added mediaplayer_fuzzer
Test: ./mediaplayer_fuzzer
Bug: 189053744
Change-Id: I2802f671fc4bd011e2a95cd8352a5dee656f0f1c
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index 4a1bcc1..efd08c8 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -80,3 +80,46 @@
"libdrmframework",
],
}
+
+cc_fuzz {
+ name: "mediaplayer_fuzzer",
+ srcs: [
+ "mediaplayer_fuzzer.cpp",
+ ],
+ defaults: [
+ "libmediaplayerserviceFuzzer_defaults",
+ ],
+ static_libs: [
+ "libplayerservice_datasource",
+ "libstagefright_nuplayer",
+ "libstagefright_rtsp",
+ "libstagefright_timedtext",
+ ],
+ shared_libs: [
+ "android.hardware.media.c2@1.0",
+ "android.hardware.media.omx@1.0",
+ "av-types-aidl-cpp",
+ "libaudioclient_aidl_conversion",
+ "libbase",
+ "libactivitymanager_aidl",
+ "libandroid_net",
+ "libaudioclient",
+ "libcamera_client",
+ "libcodec2_client",
+ "libcrypto",
+ "libdatasource",
+ "libdrmframework",
+ "libgui",
+ "libhidlbase",
+ "liblog",
+ "libmedia_codeclist",
+ "libmedia_omx",
+ "libmediadrm",
+ "libmediametrics",
+ "libmediautils",
+ "libmemunreachable",
+ "libnetd_client",
+ "libpowermanager",
+ "libstagefright_httplive",
+ ],
+}
diff --git a/media/libmediaplayerservice/fuzzer/README.md b/media/libmediaplayerservice/fuzzer/README.md
index 17f6713..a93c809 100644
--- a/media/libmediaplayerservice/fuzzer/README.md
+++ b/media/libmediaplayerservice/fuzzer/README.md
@@ -2,6 +2,7 @@
## Table of contents
+ [StagefrightMediaRecorder](#StagefrightMediaRecorder)
+ [StagefrightMetadataRetriever](#StagefrightMetadataRetriever)
++ [MediaPlayer](#MediaPlayer)
# <a name="StagefrightMediaRecorder"></a> Fuzzer for StagefrightMediaRecorder
@@ -49,3 +50,34 @@
$ adb sync data
$ adb shell /data/fuzz/arm64/metadataretriever_fuzzer/metadataretriever_fuzzer
```
+
+# <a name="MediaPlayer"></a> Fuzzer for MediaPlayer
+
+MediaPlayerService supports the following data sources:
+1. Url (parameter name: `url`)
+2. File descriptor (parameter name: `fd`)
+3. IStreamSource (parameter name: `source`)
+4. IDataSource (parameter name: `source`)
+5. RTP Parameters (parameter name: `rtpParams`)
+
+MediaPlayerService supports the following parameters:
+1. Audio sessions (parameter name: `audioSessionId`)
+2. Audio stretch modes (parameter name: `mStretchMode`)
+3. Audio fallback modes (parameter name: `mFallbackMode`)
+4. Media parameter keys (parameter name: `key`)
+5. Audio Stream Types (parameter name: `streamType`)
+6. Media Event Types (parameter name: `msg`)
+7. Media Info Types (parameter name: `ext1`)
+
+You can find the possible values in the fuzzer's source code.
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) mediaplayer_fuzzer
+```
+2. To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mediaplayer_fuzzer/mediaplayer_fuzzer
+```
diff --git a/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp b/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp
new file mode 100644
index 0000000..7799f44
--- /dev/null
+++ b/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2021 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.
+ *
+ */
+
+#include <MediaPlayerService.h>
+#include <camera/Camera.h>
+#include <datasource/FileSource.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+#include <media/IMediaCodecList.h>
+#include <media/IMediaHTTPService.h>
+#include <media/IMediaPlayer.h>
+#include <media/IMediaRecorder.h>
+#include <media/IRemoteDisplay.h>
+#include <media/IRemoteDisplayClient.h>
+#include <media/stagefright/RemoteDataSource.h>
+#include <media/stagefright/foundation/base64.h>
+#include <thread>
+#include "fuzzer/FuzzedDataProvider.h"
+
+constexpr int32_t kUuidSize = 16;
+constexpr int32_t kMaxSleepTimeInMs = 100;
+constexpr int32_t kMinSleepTimeInMs = 0;
+constexpr int32_t kPlayCountMin = 1;
+constexpr int32_t kPlayCountMax = 10;
+constexpr int32_t kMaxDimension = 8192;
+constexpr int32_t kMinDimension = 0;
+
+using namespace std;
+using namespace android;
+
+constexpr audio_session_t kSupportedAudioSessions[] = {
+ AUDIO_SESSION_DEVICE, AUDIO_SESSION_OUTPUT_STAGE, AUDIO_SESSION_OUTPUT_MIX};
+
+constexpr audio_timestretch_stretch_mode_t kAudioStretchModes[] = {
+ AUDIO_TIMESTRETCH_STRETCH_DEFAULT, AUDIO_TIMESTRETCH_STRETCH_VOICE};
+
+constexpr audio_timestretch_fallback_mode_t kAudioFallbackModes[] = {
+ AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT, AUDIO_TIMESTRETCH_FALLBACK_DEFAULT,
+ AUDIO_TIMESTRETCH_FALLBACK_MUTE, AUDIO_TIMESTRETCH_FALLBACK_FAIL};
+
+constexpr media_parameter_keys kMediaParamKeys[] = {
+ KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS, KEY_PARAMETER_AUDIO_CHANNEL_COUNT,
+ KEY_PARAMETER_PLAYBACK_RATE_PERMILLE, KEY_PARAMETER_AUDIO_ATTRIBUTES,
+ KEY_PARAMETER_RTP_ATTRIBUTES};
+
+constexpr audio_stream_type_t kAudioStreamTypes[] = {
+ AUDIO_STREAM_DEFAULT, AUDIO_STREAM_VOICE_CALL, AUDIO_STREAM_SYSTEM,
+ AUDIO_STREAM_RING, AUDIO_STREAM_MUSIC, AUDIO_STREAM_ALARM,
+ AUDIO_STREAM_NOTIFICATION, AUDIO_STREAM_BLUETOOTH_SCO, AUDIO_STREAM_ENFORCED_AUDIBLE,
+ AUDIO_STREAM_DTMF, AUDIO_STREAM_TTS, AUDIO_STREAM_ASSISTANT};
+
+constexpr media_event_type kMediaEventTypes[] = {MEDIA_NOP,
+ MEDIA_PREPARED,
+ MEDIA_PLAYBACK_COMPLETE,
+ MEDIA_BUFFERING_UPDATE,
+ MEDIA_SEEK_COMPLETE,
+ MEDIA_SET_VIDEO_SIZE,
+ MEDIA_STARTED,
+ MEDIA_PAUSED,
+ MEDIA_STOPPED,
+ MEDIA_SKIPPED,
+ MEDIA_NOTIFY_TIME,
+ MEDIA_TIMED_TEXT,
+ MEDIA_ERROR,
+ MEDIA_INFO,
+ MEDIA_SUBTITLE_DATA,
+ MEDIA_META_DATA,
+ MEDIA_DRM_INFO,
+ MEDIA_TIME_DISCONTINUITY,
+ MEDIA_IMS_RX_NOTICE,
+ MEDIA_AUDIO_ROUTING_CHANGED};
+
+constexpr media_info_type kMediaInfoTypes[] = {
+ MEDIA_INFO_UNKNOWN, MEDIA_INFO_STARTED_AS_NEXT,
+ MEDIA_INFO_RENDERING_START, MEDIA_INFO_VIDEO_TRACK_LAGGING,
+ MEDIA_INFO_BUFFERING_START, MEDIA_INFO_BUFFERING_END,
+ MEDIA_INFO_NETWORK_BANDWIDTH, MEDIA_INFO_BAD_INTERLEAVING,
+ MEDIA_INFO_NOT_SEEKABLE, MEDIA_INFO_METADATA_UPDATE,
+ MEDIA_INFO_PLAY_AUDIO_ERROR, MEDIA_INFO_PLAY_VIDEO_ERROR,
+ MEDIA_INFO_TIMED_TEXT_ERROR};
+
+const char *kUrlPrefix[] = {"data:", "http://", "https://", "rtsp://", "content://", "test://"};
+
+struct TestStreamSource : public IStreamSource {
+ void setListener(const sp<IStreamListener> & /*listener*/) override{};
+ void setBuffers(const Vector<sp<IMemory>> & /*buffers*/) override{};
+ void onBufferAvailable(size_t /*index*/) override{};
+ IBinder *onAsBinder() { return nullptr; };
+};
+
+class BinderDeathNotifier : public IBinder::DeathRecipient {
+ public:
+ void binderDied(const wp<IBinder> &) { abort(); }
+};
+
+class MediaPlayerServiceFuzzer {
+ public:
+ MediaPlayerServiceFuzzer(const uint8_t *data, size_t size)
+ : mFdp(data, size), mDataSourceFd(memfd_create("InputFile", MFD_ALLOW_SEALING)){};
+ ~MediaPlayerServiceFuzzer() { close(mDataSourceFd); };
+ void process(const uint8_t *data, size_t size);
+
+ private:
+ bool setDataSource(const uint8_t *data, size_t size);
+ void invokeMediaPlayer();
+ FuzzedDataProvider mFdp;
+ sp<IMediaPlayer> mMediaPlayer = nullptr;
+ sp<IMediaPlayerClient> mMediaPlayerClient = nullptr;
+ const int32_t mDataSourceFd;
+};
+
+bool MediaPlayerServiceFuzzer::setDataSource(const uint8_t *data, size_t size) {
+ status_t status = -1;
+ enum DataSourceType {http, fd, stream, file, socket, kMaxValue = socket};
+ switch (mFdp.ConsumeEnum<DataSourceType>()) {
+ case http: {
+ KeyedVector<String8, String8> headers;
+ headers.add(String8(mFdp.ConsumeRandomLengthString().c_str()),
+ String8(mFdp.ConsumeRandomLengthString().c_str()));
+
+ uint32_t dataBlobSize = mFdp.ConsumeIntegralInRange<uint16_t>(0, size);
+ vector<uint8_t> uriSuffix = mFdp.ConsumeBytes<uint8_t>(dataBlobSize);
+
+ string uri(mFdp.PickValueInArray(kUrlPrefix));
+ uri += ";base64,";
+ AString out;
+ encodeBase64(uriSuffix.data(), uriSuffix.size(), &out);
+ uri += out.c_str();
+ status = mMediaPlayer->setDataSource(nullptr /*httpService*/, uri.c_str(), &headers);
+ break;
+ }
+ case fd: {
+ write(mDataSourceFd, data, size);
+
+ status = mMediaPlayer->setDataSource(mDataSourceFd, 0, size);
+ break;
+ }
+ case stream: {
+ sp<IStreamSource> streamSource = sp<TestStreamSource>::make();
+ status = mMediaPlayer->setDataSource(streamSource);
+ break;
+ }
+ case file: {
+ write(mDataSourceFd, data, size);
+
+ sp<DataSource> dataSource = new FileSource(dup(mDataSourceFd), 0, size);
+ sp<IDataSource> iDataSource = RemoteDataSource::wrap(dataSource);
+ if (!iDataSource) {
+ return false;
+ }
+ status = mMediaPlayer->setDataSource(iDataSource);
+ break;
+ }
+ case socket: {
+ String8 rtpParams = String8(mFdp.ConsumeRandomLengthString().c_str());
+ struct sockaddr_in endpoint;
+ endpoint.sin_family = mFdp.ConsumeIntegral<unsigned short>();
+ endpoint.sin_port = mFdp.ConsumeIntegral<uint16_t>();
+ mMediaPlayer->setRetransmitEndpoint(&endpoint);
+ status = mMediaPlayer->setDataSource(rtpParams);
+ break;
+ }
+ }
+
+ if (status != 0) {
+ return false;
+ }
+ return true;
+}
+
+void MediaPlayerServiceFuzzer::invokeMediaPlayer() {
+ sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
+ String8 name = String8(mFdp.ConsumeRandomLengthString().c_str());
+ uint32_t width = mFdp.ConsumeIntegralInRange<uint32_t>(kMinDimension, kMaxDimension);
+ uint32_t height = mFdp.ConsumeIntegralInRange<uint32_t>(kMinDimension, kMaxDimension);
+ uint32_t pixelFormat = mFdp.ConsumeIntegral<int32_t>();
+ uint32_t flags = mFdp.ConsumeIntegral<int32_t>();
+ sp<SurfaceControl> surfaceControl =
+ composerClient->createSurface(name, width, height, pixelFormat, flags);
+ if (surfaceControl) {
+ sp<Surface> surface = surfaceControl->getSurface();
+ mMediaPlayer->setVideoSurfaceTexture(surface->getIGraphicBufferProducer());
+ }
+
+ BufferingSettings buffering;
+ buffering.mInitialMarkMs = mFdp.ConsumeIntegral<int32_t>();
+ buffering.mResumePlaybackMarkMs = mFdp.ConsumeIntegral<int32_t>();
+ mMediaPlayer->setBufferingSettings(buffering);
+ mMediaPlayer->getBufferingSettings(&buffering);
+
+ mMediaPlayer->prepareAsync();
+ size_t playCount = mFdp.ConsumeIntegralInRange<size_t>(kPlayCountMin, kPlayCountMax);
+ for (size_t Idx = 0; Idx < playCount; ++Idx) {
+ mMediaPlayer->start();
+ this_thread::sleep_for(chrono::milliseconds(
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs)));
+ mMediaPlayer->pause();
+ this_thread::sleep_for(chrono::milliseconds(
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs)));
+ mMediaPlayer->stop();
+ }
+ bool state;
+ mMediaPlayer->isPlaying(&state);
+
+ AudioPlaybackRate rate;
+ rate.mSpeed = mFdp.ConsumeFloatingPoint<float>();
+ rate.mPitch = mFdp.ConsumeFloatingPoint<float>();
+ rate.mStretchMode = mFdp.PickValueInArray(kAudioStretchModes);
+ rate.mFallbackMode = mFdp.PickValueInArray(kAudioFallbackModes);
+ mMediaPlayer->setPlaybackSettings(rate);
+ mMediaPlayer->getPlaybackSettings(&rate);
+
+ AVSyncSettings *avSyncSettings = new AVSyncSettings();
+ float videoFpsHint = mFdp.ConsumeFloatingPoint<float>();
+ mMediaPlayer->setSyncSettings(*avSyncSettings, videoFpsHint);
+ mMediaPlayer->getSyncSettings(avSyncSettings, &videoFpsHint);
+ delete avSyncSettings;
+
+ mMediaPlayer->seekTo(mFdp.ConsumeIntegral<int32_t>());
+
+ int32_t msec;
+ mMediaPlayer->getCurrentPosition(&msec);
+ mMediaPlayer->getDuration(&msec);
+ mMediaPlayer->reset();
+
+ mMediaPlayer->notifyAt(mFdp.ConsumeIntegral<int64_t>());
+
+ mMediaPlayer->setAudioStreamType(mFdp.PickValueInArray(kAudioStreamTypes));
+ mMediaPlayer->setLooping(mFdp.ConsumeIntegral<int32_t>());
+ float left = mFdp.ConsumeFloatingPoint<float>();
+ float right = mFdp.ConsumeFloatingPoint<float>();
+ mMediaPlayer->setVolume(left, right);
+
+ Parcel request, reply;
+ request.writeInt32(mFdp.ConsumeIntegral<int32_t>());
+ request.setDataPosition(0);
+ mMediaPlayer->invoke(request, &reply);
+
+ Parcel filter;
+ filter.writeInt32(mFdp.ConsumeIntegral<int32_t>());
+ filter.setDataPosition(0);
+ mMediaPlayer->setMetadataFilter(filter);
+
+ bool updateOnly = mFdp.ConsumeBool();
+ bool applyFilter = mFdp.ConsumeBool();
+ mMediaPlayer->getMetadata(updateOnly, applyFilter, &reply);
+ mMediaPlayer->setAuxEffectSendLevel(mFdp.ConsumeFloatingPoint<float>());
+ mMediaPlayer->attachAuxEffect(mFdp.ConsumeIntegral<int32_t>());
+
+ int32_t key = mFdp.PickValueInArray(kMediaParamKeys);
+ request.writeInt32(mFdp.ConsumeIntegral<int32_t>());
+ request.setDataPosition(0);
+ mMediaPlayer->setParameter(key, request);
+ key = mFdp.PickValueInArray(kMediaParamKeys);
+ mMediaPlayer->getParameter(key, &reply);
+
+ struct sockaddr_in endpoint;
+ mMediaPlayer->getRetransmitEndpoint(&endpoint);
+
+ AttributionSourceState attributionSource;
+ attributionSource.packageName = mFdp.ConsumeRandomLengthString().c_str();
+ attributionSource.token = sp<BBinder>::make();
+ const sp<IMediaPlayerService> mpService(IMediaDeathNotifier::getMediaPlayerService());
+ sp<IMediaPlayer> mNextMediaPlayer = mpService->create(
+ mMediaPlayerClient, mFdp.PickValueInArray(kSupportedAudioSessions), attributionSource);
+ mMediaPlayer->setNextPlayer(mNextMediaPlayer);
+
+ const sp<media::VolumeShaper::Configuration> configuration =
+ sp<media::VolumeShaper::Configuration>::make();
+ const sp<media::VolumeShaper::Operation> operation = sp<media::VolumeShaper::Operation>::make();
+ mMediaPlayer->applyVolumeShaper(configuration, operation);
+
+ mMediaPlayer->getVolumeShaperState(mFdp.ConsumeIntegral<int32_t>());
+ uint8_t uuid[kUuidSize];
+ for (int32_t index = 0; index < kUuidSize; ++index) {
+ uuid[index] = mFdp.ConsumeIntegral<uint8_t>();
+ }
+ Vector<uint8_t> drmSessionId;
+ drmSessionId.push_back(mFdp.ConsumeIntegral<uint8_t>());
+ mMediaPlayer->prepareDrm(uuid, drmSessionId);
+ mMediaPlayer->releaseDrm();
+
+ audio_port_handle_t deviceId = mFdp.ConsumeIntegral<int32_t>();
+ mMediaPlayer->setOutputDevice(deviceId);
+ mMediaPlayer->getRoutedDeviceId(&deviceId);
+
+ mMediaPlayer->enableAudioDeviceCallback(mFdp.ConsumeBool());
+
+ sp<MediaPlayer> mediaPlayer = (MediaPlayer *)mMediaPlayer.get();
+
+ int32_t msg = mFdp.PickValueInArray(kMediaEventTypes);
+ int32_t ext1 = mFdp.PickValueInArray(kMediaInfoTypes);
+ int32_t ext2 = mFdp.ConsumeIntegral<int32_t>();
+ Parcel obj;
+ obj.writeInt32(mFdp.ConsumeIntegral<int32_t>());
+ obj.setDataPosition(0);
+ mediaPlayer->notify(msg, ext1, ext2, &obj);
+
+ int32_t mediaPlayerDumpFd = memfd_create("OutputDumpFile", MFD_ALLOW_SEALING);
+ Vector<String16> args;
+ args.push_back(String16(mFdp.ConsumeRandomLengthString().c_str()));
+ mediaPlayer->dump(mediaPlayerDumpFd, args);
+ close(mediaPlayerDumpFd);
+
+ mMediaPlayer->disconnect();
+}
+
+void MediaPlayerServiceFuzzer::process(const uint8_t *data, size_t size) {
+ MediaPlayerService::instantiate();
+
+ const sp<IMediaPlayerService> mpService(IMediaDeathNotifier::getMediaPlayerService());
+ if (!mpService) {
+ return;
+ }
+
+ sp<IMediaCodecList> mediaCodecList = mpService->getCodecList();
+
+ sp<IRemoteDisplayClient> remoteDisplayClient;
+ sp<IRemoteDisplay> remoteDisplay = mpService->listenForRemoteDisplay(
+ String16(mFdp.ConsumeRandomLengthString().c_str()) /*opPackageName*/, remoteDisplayClient,
+ String8(mFdp.ConsumeRandomLengthString().c_str()) /*iface*/);
+
+ mpService->addBatteryData(mFdp.ConsumeIntegral<uint32_t>());
+ Parcel reply;
+ mpService->pullBatteryData(&reply);
+
+ sp<MediaPlayerService> mediaPlayerService = (MediaPlayerService *)mpService.get();
+ AttributionSourceState attributionSource;
+ attributionSource.packageName = mFdp.ConsumeRandomLengthString().c_str();
+ attributionSource.token = sp<BBinder>::make();
+ mMediaPlayer = mediaPlayerService->create(
+ mMediaPlayerClient, mFdp.PickValueInArray(kSupportedAudioSessions), attributionSource);
+
+ int32_t mediaPlayerServiceDumpFd = memfd_create("OutputDumpFile", MFD_ALLOW_SEALING);
+ Vector<String16> args;
+ args.push_back(String16(mFdp.ConsumeRandomLengthString().c_str()));
+ mediaPlayerService->dump(mediaPlayerServiceDumpFd, args);
+ close(mediaPlayerServiceDumpFd);
+
+ if (!mMediaPlayer) {
+ return;
+ }
+
+ if (setDataSource(data, size)) {
+ invokeMediaPlayer();
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ MediaPlayerServiceFuzzer mpsFuzzer(data, size);
+ ProcessState::self()->startThreadPool();
+ mpsFuzzer.process(data, size);
+ return 0;
+};