/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 & /*listener*/) override{}; void setBuffers(const Vector> & /*buffers*/) override{}; void onBufferAvailable(size_t /*index*/) override{}; IBinder *onAsBinder() { return nullptr; }; }; struct TestMediaHTTPConnection : public MediaHTTPConnection { public: TestMediaHTTPConnection() {} virtual ~TestMediaHTTPConnection() {} virtual bool connect(const char* /*uri*/, const KeyedVector* /*headers*/) { return true; } virtual void disconnect() { return; } virtual ssize_t readAt(off64_t /*offset*/, void* /*data*/, size_t size) { return size; } virtual off64_t getSize() { return 0; } virtual status_t getMIMEType(String8* /*mimeType*/) { return NO_ERROR; } virtual status_t getUri(String8* /*uri*/) { return NO_ERROR; } private: DISALLOW_EVIL_CONSTRUCTORS(TestMediaHTTPConnection); }; struct TestMediaHTTPService : public BnInterface { public: TestMediaHTTPService() {} ~TestMediaHTTPService(){}; virtual sp makeHTTPConnection() { mMediaHTTPConnection = sp::make(); return mMediaHTTPConnection; } private: sp mMediaHTTPConnection = nullptr; DISALLOW_EVIL_CONSTRUCTORS(TestMediaHTTPService); }; class BinderDeathNotifier : public IBinder::DeathRecipient { public: void binderDied(const wp &) { 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 mMediaPlayer = nullptr; sp 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()) { case http: { KeyedVector headers; headers.add(String8(mFdp.ConsumeRandomLengthString().c_str()), String8(mFdp.ConsumeRandomLengthString().c_str())); uint32_t dataBlobSize = mFdp.ConsumeIntegralInRange(0, size); vector uriSuffix = mFdp.ConsumeBytes(dataBlobSize); string uri(mFdp.PickValueInArray(kUrlPrefix)); uri += ";base64,"; AString out; encodeBase64(uriSuffix.data(), uriSuffix.size(), &out); uri += out.c_str(); sp testService = sp::make(); status = mMediaPlayer->setDataSource(testService /*httpService*/, uri.c_str(), &headers); break; } case fd: { write(mDataSourceFd, data, size); status = mMediaPlayer->setDataSource(mDataSourceFd, 0, size); break; } case stream: { sp streamSource = sp::make(); status = mMediaPlayer->setDataSource(streamSource); break; } case file: { write(mDataSourceFd, data, size); sp dataSource = new FileSource(dup(mDataSourceFd), 0, size); sp 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(); endpoint.sin_port = mFdp.ConsumeIntegral(); mMediaPlayer->setRetransmitEndpoint(&endpoint); status = mMediaPlayer->setDataSource(rtpParams); break; } } if (status != 0) { return false; } return true; } void MediaPlayerServiceFuzzer::invokeMediaPlayer() { sp composerClient = new SurfaceComposerClient; String8 name = String8(mFdp.ConsumeRandomLengthString().c_str()); uint32_t width = mFdp.ConsumeIntegralInRange(kMinDimension, kMaxDimension); uint32_t height = mFdp.ConsumeIntegralInRange(kMinDimension, kMaxDimension); uint32_t pixelFormat = mFdp.ConsumeIntegral(); uint32_t flags = mFdp.ConsumeIntegral(); sp surfaceControl = composerClient->createSurface(name, width, height, pixelFormat, flags); if (surfaceControl) { sp surface = surfaceControl->getSurface(); mMediaPlayer->setVideoSurfaceTexture(surface->getIGraphicBufferProducer()); } BufferingSettings buffering; buffering.mInitialMarkMs = mFdp.ConsumeIntegral(); buffering.mResumePlaybackMarkMs = mFdp.ConsumeIntegral(); mMediaPlayer->setBufferingSettings(buffering); mMediaPlayer->getBufferingSettings(&buffering); mMediaPlayer->prepareAsync(); size_t playCount = mFdp.ConsumeIntegralInRange(kPlayCountMin, kPlayCountMax); for (size_t Idx = 0; Idx < playCount; ++Idx) { mMediaPlayer->start(); this_thread::sleep_for(chrono::milliseconds( mFdp.ConsumeIntegralInRange(kMinSleepTimeInMs, kMaxSleepTimeInMs))); mMediaPlayer->pause(); this_thread::sleep_for(chrono::milliseconds( mFdp.ConsumeIntegralInRange(kMinSleepTimeInMs, kMaxSleepTimeInMs))); mMediaPlayer->stop(); } bool state; mMediaPlayer->isPlaying(&state); AudioPlaybackRate rate; rate.mSpeed = mFdp.ConsumeFloatingPoint(); rate.mPitch = mFdp.ConsumeFloatingPoint(); rate.mStretchMode = mFdp.PickValueInArray(kAudioStretchModes); rate.mFallbackMode = mFdp.PickValueInArray(kAudioFallbackModes); mMediaPlayer->setPlaybackSettings(rate); mMediaPlayer->getPlaybackSettings(&rate); AVSyncSettings *avSyncSettings = new AVSyncSettings(); float videoFpsHint = mFdp.ConsumeFloatingPoint(); mMediaPlayer->setSyncSettings(*avSyncSettings, videoFpsHint); mMediaPlayer->getSyncSettings(avSyncSettings, &videoFpsHint); delete avSyncSettings; mMediaPlayer->seekTo(mFdp.ConsumeIntegral()); int32_t msec; mMediaPlayer->getCurrentPosition(&msec); mMediaPlayer->getDuration(&msec); mMediaPlayer->reset(); mMediaPlayer->notifyAt(mFdp.ConsumeIntegral()); mMediaPlayer->setAudioStreamType(mFdp.PickValueInArray(kAudioStreamTypes)); mMediaPlayer->setLooping(mFdp.ConsumeIntegral()); float left = mFdp.ConsumeFloatingPoint(); float right = mFdp.ConsumeFloatingPoint(); mMediaPlayer->setVolume(left, right); Parcel request, reply; request.writeInt32(mFdp.ConsumeIntegral()); request.setDataPosition(0); mMediaPlayer->invoke(request, &reply); Parcel filter; filter.writeInt32(mFdp.ConsumeIntegral()); filter.setDataPosition(0); mMediaPlayer->setMetadataFilter(filter); bool updateOnly = mFdp.ConsumeBool(); bool applyFilter = mFdp.ConsumeBool(); mMediaPlayer->getMetadata(updateOnly, applyFilter, &reply); mMediaPlayer->setAuxEffectSendLevel(mFdp.ConsumeFloatingPoint()); mMediaPlayer->attachAuxEffect(mFdp.ConsumeIntegral()); int32_t key = mFdp.PickValueInArray(kMediaParamKeys); request.writeInt32(mFdp.ConsumeIntegral()); 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::make(); const sp mpService(IMediaDeathNotifier::getMediaPlayerService()); sp mNextMediaPlayer = mpService->create( mMediaPlayerClient, mFdp.PickValueInArray(kSupportedAudioSessions), attributionSource); mMediaPlayer->setNextPlayer(mNextMediaPlayer); const sp configuration = sp::make(); const sp operation = sp::make(); mMediaPlayer->applyVolumeShaper(configuration, operation); mMediaPlayer->getVolumeShaperState(mFdp.ConsumeIntegral()); uint8_t uuid[kUuidSize]; for (int32_t index = 0; index < kUuidSize; ++index) { uuid[index] = mFdp.ConsumeIntegral(); } Vector drmSessionId; drmSessionId.push_back(mFdp.ConsumeIntegral()); mMediaPlayer->prepareDrm(uuid, drmSessionId); mMediaPlayer->releaseDrm(); audio_port_handle_t deviceId = mFdp.ConsumeIntegral(); mMediaPlayer->setOutputDevice(deviceId); mMediaPlayer->getRoutedDeviceId(&deviceId); mMediaPlayer->enableAudioDeviceCallback(mFdp.ConsumeBool()); sp mediaPlayer = (MediaPlayer *)mMediaPlayer.get(); int32_t msg = mFdp.PickValueInArray(kMediaEventTypes); int32_t ext1 = mFdp.PickValueInArray(kMediaInfoTypes); int32_t ext2 = mFdp.ConsumeIntegral(); Parcel obj; obj.writeInt32(mFdp.ConsumeIntegral()); obj.setDataPosition(0); mediaPlayer->notify(msg, ext1, ext2, &obj); int32_t mediaPlayerDumpFd = memfd_create("OutputDumpFile", MFD_ALLOW_SEALING); Vector 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 mpService(IMediaDeathNotifier::getMediaPlayerService()); if (!mpService) { return; } sp mediaCodecList = mpService->getCodecList(); sp remoteDisplayClient; sp remoteDisplay = mpService->listenForRemoteDisplay( String16(mFdp.ConsumeRandomLengthString().c_str()) /*opPackageName*/, remoteDisplayClient, String8(mFdp.ConsumeRandomLengthString().c_str()) /*iface*/); mpService->addBatteryData(mFdp.ConsumeIntegral()); Parcel reply; mpService->pullBatteryData(&reply); sp mediaPlayerService = (MediaPlayerService *)mpService.get(); AttributionSourceState attributionSource; attributionSource.packageName = mFdp.ConsumeRandomLengthString().c_str(); attributionSource.token = sp::make(); mMediaPlayer = mediaPlayerService->create( mMediaPlayerClient, mFdp.PickValueInArray(kSupportedAudioSessions), attributionSource); int32_t mediaPlayerServiceDumpFd = memfd_create("OutputDumpFile", MFD_ALLOW_SEALING); Vector 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; };