Loading media/libmediaplayerservice/fuzzer/Android.bp 0 → 100644 +65 −0 Original line number Diff line number Diff line /* * 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. * */ cc_defaults { name: "libmediaplayerserviceFuzzer_defaults", include_dirs: [ "frameworks/av/media/libmediaplayerservice", ], static_libs: [ "libmediaplayerservice", "liblog", ], shared_libs: [ "framework-permission-aidl-cpp", "libbinder", "libcutils", "libmedia", "libstagefright", "libutils", "libstagefright_foundation", ], fuzz_config: { cc: [ "android-media-fuzzing-reports@google.com", ], componentid: 155276, }, } cc_fuzz { name: "mediarecorder_fuzzer", srcs: [ "mediarecorder_fuzzer.cpp", ], defaults: [ "libmediaplayerserviceFuzzer_defaults", ], static_libs: [ "libstagefright_rtsp", "libbase", ], shared_libs: [ "av-types-aidl-cpp", "media_permission-aidl-cpp", "libaudioclient_aidl_conversion", "libandroid_net", "libcamera_client", "libgui", "libmediametrics", ], } media/libmediaplayerservice/fuzzer/README.md 0 → 100644 +26 −0 Original line number Diff line number Diff line # Fuzzer for libmediaplayerservice ## Table of contents + [StagefrightMediaRecorder](#StagefrightMediaRecorder) # <a name="StagefrightMediaRecorder"></a> Fuzzer for StagefrightMediaRecorder StagefrightMediaRecorder supports the following parameters: 1. Output Formats (parameter name: `setOutputFormat`) 2. Audio Encoders (parameter name: `setAudioEncoder`) 3. Video Encoders (parameter name: `setVideoEncoder`) 4. Audio Sources (parameter name: `setAudioSource`) 5. Video Sources (parameter name: `setVideoSource`) 6. Microphone Direction (parameter name: `setMicrophoneDirection`) You can find the possible values in the fuzzer's source code. #### Steps to run 1. Build the fuzzer ``` $ mm -j$(nproc) mediarecorder_fuzzer ``` 2. Run on device ``` $ adb sync data $ adb shell /data/fuzz/arm64/mediarecorder_fuzzer/mediarecorder_fuzzer ``` media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp 0 → 100644 +312 −0 Original line number Diff line number Diff line /* * 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 <media/stagefright/foundation/AString.h> #include "fuzzer/FuzzedDataProvider.h" #include <StagefrightRecorder.h> #include <camera/Camera.h> #include <camera/android/hardware/ICamera.h> #include <gui/IGraphicBufferProducer.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <media/stagefright/PersistentSurface.h> #include <thread> using namespace std; using namespace android; using namespace android::hardware; constexpr video_source kSupportedVideoSources[] = {VIDEO_SOURCE_DEFAULT, VIDEO_SOURCE_CAMERA, VIDEO_SOURCE_SURFACE}; constexpr audio_source_t kSupportedAudioSources[] = { AUDIO_SOURCE_DEFAULT, AUDIO_SOURCE_MIC, AUDIO_SOURCE_VOICE_UPLINK, AUDIO_SOURCE_VOICE_DOWNLINK, AUDIO_SOURCE_VOICE_CALL, AUDIO_SOURCE_CAMCORDER, AUDIO_SOURCE_VOICE_RECOGNITION, AUDIO_SOURCE_VOICE_COMMUNICATION, AUDIO_SOURCE_REMOTE_SUBMIX, AUDIO_SOURCE_UNPROCESSED, AUDIO_SOURCE_VOICE_PERFORMANCE, AUDIO_SOURCE_ECHO_REFERENCE, AUDIO_SOURCE_FM_TUNER, AUDIO_SOURCE_HOTWORD}; constexpr audio_microphone_direction_t kSupportedMicrophoneDirections[] = { MIC_DIRECTION_UNSPECIFIED, MIC_DIRECTION_FRONT, MIC_DIRECTION_BACK, MIC_DIRECTION_EXTERNAL}; struct RecordingConfig { output_format outputFormat; audio_encoder audioEncoder; video_encoder videoEncoder; }; const struct RecordingConfig kRecordingConfigList[] = { {OUTPUT_FORMAT_AMR_NB, AUDIO_ENCODER_AMR_NB, VIDEO_ENCODER_DEFAULT}, {OUTPUT_FORMAT_AMR_WB, AUDIO_ENCODER_AMR_WB, VIDEO_ENCODER_DEFAULT}, {OUTPUT_FORMAT_AAC_ADTS, AUDIO_ENCODER_AAC, VIDEO_ENCODER_DEFAULT}, {OUTPUT_FORMAT_AAC_ADTS, AUDIO_ENCODER_HE_AAC, VIDEO_ENCODER_DEFAULT}, {OUTPUT_FORMAT_AAC_ADTS, AUDIO_ENCODER_AAC_ELD, VIDEO_ENCODER_DEFAULT}, {OUTPUT_FORMAT_OGG, AUDIO_ENCODER_OPUS, VIDEO_ENCODER_DEFAULT}, {OUTPUT_FORMAT_RTP_AVP, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_DEFAULT}, {OUTPUT_FORMAT_MPEG2TS, AUDIO_ENCODER_AAC, VIDEO_ENCODER_H264}, {OUTPUT_FORMAT_WEBM, AUDIO_ENCODER_VORBIS, VIDEO_ENCODER_VP8}, {OUTPUT_FORMAT_THREE_GPP, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_MPEG_4_SP}, {OUTPUT_FORMAT_MPEG_4, AUDIO_ENCODER_AAC, VIDEO_ENCODER_H264}, {OUTPUT_FORMAT_MPEG_4, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_MPEG_4_SP}, {OUTPUT_FORMAT_MPEG_4, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_HEVC}}; const string kParametersList[] = {"max-duration", "max-filesize", "interleave-duration-us", "param-movie-time-scale", "param-geotag-longitude", "param-geotag-latitude", "param-track-time-status", "audio-param-sampling-rate", "audio-param-encoding-bitrate", "audio-param-number-of-channels", "audio-param-time-scale", "video-param-rotation-angle-degrees", "video-param-encoding-bitrate", "video-param-bitrate-mode", "video-param-i-frames-interval", "video-param-encoder-profile", "video-param-encoder-level", "video-param-camera-id", "video-param-time-scale", "param-use-64bit-offset", "time-lapse-enable", "time-lapse-fps", "rtp-param-local-ip", "rtp-param-local-port", "rtp-param-remote-port", "rtp-param-self-id", "rtp-param-opponent-id", "rtp-param-payload-type", "rtp-param-ext-cvo-extmap", "rtp-param-ext-cvo-degrees", "video-param-request-i-frame", "rtp-param-set-socket-dscp", "rtp-param-set-socket-network"}; constexpr int32_t kMaxSleepTimeInMs = 100; constexpr int32_t kMinSleepTimeInMs = 0; constexpr int32_t kMinVideoSize = 2; constexpr int32_t kMaxVideoSize = 8192; constexpr int32_t kNumRecordMin = 1; constexpr int32_t kNumRecordMax = 10; class TestAudioDeviceCallback : public AudioSystem::AudioDeviceCallback { public: virtual ~TestAudioDeviceCallback() = default; void onAudioDeviceUpdate(audio_io_handle_t /*audioIo*/, audio_port_handle_t /*deviceId*/) override{}; }; class TestCamera : public ICamera { public: virtual ~TestCamera() = default; binder::Status disconnect() override { return binder::Status::ok(); }; status_t connect(const sp<ICameraClient> & /*client*/) override { return 0; }; status_t lock() override { return 0; }; status_t unlock() override { return 0; }; status_t setPreviewTarget(const sp<IGraphicBufferProducer> & /*bufferProducer*/) override { return 0; }; void setPreviewCallbackFlag(int /*flag*/) override{}; status_t setPreviewCallbackTarget( const sp<IGraphicBufferProducer> & /*callbackProducer*/) override { return 0; }; status_t startPreview() override { return 0; }; void stopPreview() override{}; bool previewEnabled() override { return true; }; status_t startRecording() override { return 0; }; void stopRecording() override{}; bool recordingEnabled() override { return true; }; void releaseRecordingFrame(const sp<IMemory> & /*mem*/) override{}; void releaseRecordingFrameHandle(native_handle_t * /*handle*/) override{}; void releaseRecordingFrameHandleBatch(const vector<native_handle_t *> & /*handles*/) override{}; status_t autoFocus() override { return 0; }; status_t cancelAutoFocus() override { return 0; }; status_t takePicture(int /*msgType*/) override { return 0; }; status_t setParameters(const String8 & /*params*/) override { return 0; }; String8 getParameters() const override { return String8(); }; status_t sendCommand(int32_t /*cmd*/, int32_t /*arg1*/, int32_t /*arg2*/) override { return 0; }; status_t setVideoBufferMode(int32_t /*videoBufferMode*/) override { return 0; }; status_t setVideoTarget(const sp<IGraphicBufferProducer> & /*bufferProducer*/) override { return 0; }; status_t setAudioRestriction(int32_t /*mode*/) override { return 0; }; int32_t getGlobalAudioRestriction() override { return 0; }; IBinder *onAsBinder() override { return reinterpret_cast<IBinder *>(this); }; }; class TestMediaRecorderClient : public IMediaRecorderClient { public: virtual ~TestMediaRecorderClient() = default; void notify(int /*msg*/, int /*ext1*/, int /*ext2*/) override{}; IBinder *onAsBinder() override { return reinterpret_cast<IBinder *>(this); }; }; class MediaRecorderClientFuzzer { public: MediaRecorderClientFuzzer(const uint8_t *data, size_t size); ~MediaRecorderClientFuzzer() { close(mMediaRecorderOutputFd); } void process(); private: void setConfig(); void getConfig(); void dumpInfo(); FuzzedDataProvider mFdp; unique_ptr<MediaRecorderBase> mStfRecorder = nullptr; SurfaceComposerClient mComposerClient; sp<SurfaceControl> mSurfaceControl = nullptr; sp<Surface> mSurface = nullptr; const int32_t mMediaRecorderOutputFd; }; void MediaRecorderClientFuzzer::getConfig() { int32_t max; mStfRecorder->getMaxAmplitude(&max); int32_t deviceId = mFdp.ConsumeIntegral<int32_t>(); mStfRecorder->setInputDevice(deviceId); mStfRecorder->getRoutedDeviceId(&deviceId); vector<android::media::MicrophoneInfo> activeMicrophones{}; mStfRecorder->getActiveMicrophones(&activeMicrophones); int32_t portId; mStfRecorder->getPortId(&portId); uint64_t bytes; mStfRecorder->getRtpDataUsage(&bytes); Parcel parcel; mStfRecorder->getMetrics(&parcel); sp<IGraphicBufferProducer> buffer = mStfRecorder->querySurfaceMediaSource(); } void MediaRecorderClientFuzzer::dumpInfo() { int32_t dumpFd = memfd_create("DumpFile", MFD_ALLOW_SEALING); Vector<String16> args; args.push_back(String16(mFdp.ConsumeRandomLengthString().c_str())); mStfRecorder->dump(dumpFd, args); close(dumpFd); } void MediaRecorderClientFuzzer::setConfig() { mStfRecorder->setOutputFile(mMediaRecorderOutputFd); mStfRecorder->setAudioSource(mFdp.PickValueInArray(kSupportedAudioSources)); mStfRecorder->setVideoSource(mFdp.PickValueInArray(kSupportedVideoSources)); mStfRecorder->setPreferredMicrophoneDirection( mFdp.PickValueInArray(kSupportedMicrophoneDirections)); mStfRecorder->setPrivacySensitive(mFdp.ConsumeBool()); bool isPrivacySensitive; mStfRecorder->isPrivacySensitive(&isPrivacySensitive); mStfRecorder->setVideoSize(mFdp.ConsumeIntegralInRange<int32_t>(kMinVideoSize, kMaxVideoSize), mFdp.ConsumeIntegralInRange<int32_t>(kMinVideoSize, kMaxVideoSize)); mStfRecorder->setVideoFrameRate(mFdp.ConsumeIntegral<int32_t>()); mStfRecorder->enableAudioDeviceCallback(mFdp.ConsumeBool()); mStfRecorder->setPreferredMicrophoneFieldDimension(mFdp.ConsumeFloatingPoint<float>()); mStfRecorder->setClientName(String16(mFdp.ConsumeRandomLengthString().c_str())); int32_t Idx = mFdp.ConsumeIntegralInRange<int32_t>(0, size(kRecordingConfigList) - 1); mStfRecorder->setOutputFormat(kRecordingConfigList[Idx].outputFormat); mStfRecorder->setAudioEncoder(kRecordingConfigList[Idx].audioEncoder); mStfRecorder->setVideoEncoder(kRecordingConfigList[Idx].videoEncoder); int32_t nextOutputFd = memfd_create("NextOutputFile", MFD_ALLOW_SEALING); mStfRecorder->setNextOutputFile(nextOutputFd); close(nextOutputFd); for (Idx = 0; Idx < size(kParametersList); ++Idx) { if (mFdp.ConsumeBool()) { int32_t value = mFdp.ConsumeIntegral<int32_t>(); mStfRecorder->setParameters( String8((kParametersList[Idx] + "=" + to_string(value)).c_str())); } } } MediaRecorderClientFuzzer::MediaRecorderClientFuzzer(const uint8_t *data, size_t size) : mFdp(data, size), mMediaRecorderOutputFd(memfd_create("OutputFile", MFD_ALLOW_SEALING)) { AttributionSourceState attributionSource; attributionSource.packageName = mFdp.ConsumeRandomLengthString().c_str(); attributionSource.token = sp<BBinder>::make(); mStfRecorder = make_unique<StagefrightRecorder>(attributionSource); mSurfaceControl = mComposerClient.createSurface( String8(mFdp.ConsumeRandomLengthString().c_str()), mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<int32_t>(), mFdp.ConsumeIntegral<int32_t>()); if (mSurfaceControl) { mSurface = mSurfaceControl->getSurface(); mStfRecorder->setPreviewSurface(mSurface->getIGraphicBufferProducer()); } sp<TestMediaRecorderClient> listener = sp<TestMediaRecorderClient>::make(); mStfRecorder->setListener(listener); sp<TestCamera> testCamera = sp<TestCamera>::make(); sp<Camera> camera = Camera::create(testCamera); mStfRecorder->setCamera(camera->remote(), camera->getRecordingProxy()); sp<PersistentSurface> persistentSurface = sp<PersistentSurface>::make(); mStfRecorder->setInputSurface(persistentSurface); sp<TestAudioDeviceCallback> callback = sp<TestAudioDeviceCallback>::make(); mStfRecorder->setAudioDeviceCallback(callback); } void MediaRecorderClientFuzzer::process() { setConfig(); mStfRecorder->init(); mStfRecorder->prepare(); size_t numRecord = mFdp.ConsumeIntegralInRange<size_t>(kNumRecordMin, kNumRecordMax); for (size_t Idx = 0; Idx < numRecord; ++Idx) { mStfRecorder->start(); this_thread::sleep_for(chrono::milliseconds( mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs))); mStfRecorder->pause(); this_thread::sleep_for(chrono::milliseconds( mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs))); mStfRecorder->resume(); this_thread::sleep_for(chrono::milliseconds( mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs))); mStfRecorder->stop(); } dumpInfo(); getConfig(); mStfRecorder->close(); mStfRecorder->reset(); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { MediaRecorderClientFuzzer mrcFuzzer(data, size); mrcFuzzer.process(); return 0; } Loading
media/libmediaplayerservice/fuzzer/Android.bp 0 → 100644 +65 −0 Original line number Diff line number Diff line /* * 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. * */ cc_defaults { name: "libmediaplayerserviceFuzzer_defaults", include_dirs: [ "frameworks/av/media/libmediaplayerservice", ], static_libs: [ "libmediaplayerservice", "liblog", ], shared_libs: [ "framework-permission-aidl-cpp", "libbinder", "libcutils", "libmedia", "libstagefright", "libutils", "libstagefright_foundation", ], fuzz_config: { cc: [ "android-media-fuzzing-reports@google.com", ], componentid: 155276, }, } cc_fuzz { name: "mediarecorder_fuzzer", srcs: [ "mediarecorder_fuzzer.cpp", ], defaults: [ "libmediaplayerserviceFuzzer_defaults", ], static_libs: [ "libstagefright_rtsp", "libbase", ], shared_libs: [ "av-types-aidl-cpp", "media_permission-aidl-cpp", "libaudioclient_aidl_conversion", "libandroid_net", "libcamera_client", "libgui", "libmediametrics", ], }
media/libmediaplayerservice/fuzzer/README.md 0 → 100644 +26 −0 Original line number Diff line number Diff line # Fuzzer for libmediaplayerservice ## Table of contents + [StagefrightMediaRecorder](#StagefrightMediaRecorder) # <a name="StagefrightMediaRecorder"></a> Fuzzer for StagefrightMediaRecorder StagefrightMediaRecorder supports the following parameters: 1. Output Formats (parameter name: `setOutputFormat`) 2. Audio Encoders (parameter name: `setAudioEncoder`) 3. Video Encoders (parameter name: `setVideoEncoder`) 4. Audio Sources (parameter name: `setAudioSource`) 5. Video Sources (parameter name: `setVideoSource`) 6. Microphone Direction (parameter name: `setMicrophoneDirection`) You can find the possible values in the fuzzer's source code. #### Steps to run 1. Build the fuzzer ``` $ mm -j$(nproc) mediarecorder_fuzzer ``` 2. Run on device ``` $ adb sync data $ adb shell /data/fuzz/arm64/mediarecorder_fuzzer/mediarecorder_fuzzer ```
media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp 0 → 100644 +312 −0 Original line number Diff line number Diff line /* * 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 <media/stagefright/foundation/AString.h> #include "fuzzer/FuzzedDataProvider.h" #include <StagefrightRecorder.h> #include <camera/Camera.h> #include <camera/android/hardware/ICamera.h> #include <gui/IGraphicBufferProducer.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <media/stagefright/PersistentSurface.h> #include <thread> using namespace std; using namespace android; using namespace android::hardware; constexpr video_source kSupportedVideoSources[] = {VIDEO_SOURCE_DEFAULT, VIDEO_SOURCE_CAMERA, VIDEO_SOURCE_SURFACE}; constexpr audio_source_t kSupportedAudioSources[] = { AUDIO_SOURCE_DEFAULT, AUDIO_SOURCE_MIC, AUDIO_SOURCE_VOICE_UPLINK, AUDIO_SOURCE_VOICE_DOWNLINK, AUDIO_SOURCE_VOICE_CALL, AUDIO_SOURCE_CAMCORDER, AUDIO_SOURCE_VOICE_RECOGNITION, AUDIO_SOURCE_VOICE_COMMUNICATION, AUDIO_SOURCE_REMOTE_SUBMIX, AUDIO_SOURCE_UNPROCESSED, AUDIO_SOURCE_VOICE_PERFORMANCE, AUDIO_SOURCE_ECHO_REFERENCE, AUDIO_SOURCE_FM_TUNER, AUDIO_SOURCE_HOTWORD}; constexpr audio_microphone_direction_t kSupportedMicrophoneDirections[] = { MIC_DIRECTION_UNSPECIFIED, MIC_DIRECTION_FRONT, MIC_DIRECTION_BACK, MIC_DIRECTION_EXTERNAL}; struct RecordingConfig { output_format outputFormat; audio_encoder audioEncoder; video_encoder videoEncoder; }; const struct RecordingConfig kRecordingConfigList[] = { {OUTPUT_FORMAT_AMR_NB, AUDIO_ENCODER_AMR_NB, VIDEO_ENCODER_DEFAULT}, {OUTPUT_FORMAT_AMR_WB, AUDIO_ENCODER_AMR_WB, VIDEO_ENCODER_DEFAULT}, {OUTPUT_FORMAT_AAC_ADTS, AUDIO_ENCODER_AAC, VIDEO_ENCODER_DEFAULT}, {OUTPUT_FORMAT_AAC_ADTS, AUDIO_ENCODER_HE_AAC, VIDEO_ENCODER_DEFAULT}, {OUTPUT_FORMAT_AAC_ADTS, AUDIO_ENCODER_AAC_ELD, VIDEO_ENCODER_DEFAULT}, {OUTPUT_FORMAT_OGG, AUDIO_ENCODER_OPUS, VIDEO_ENCODER_DEFAULT}, {OUTPUT_FORMAT_RTP_AVP, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_DEFAULT}, {OUTPUT_FORMAT_MPEG2TS, AUDIO_ENCODER_AAC, VIDEO_ENCODER_H264}, {OUTPUT_FORMAT_WEBM, AUDIO_ENCODER_VORBIS, VIDEO_ENCODER_VP8}, {OUTPUT_FORMAT_THREE_GPP, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_MPEG_4_SP}, {OUTPUT_FORMAT_MPEG_4, AUDIO_ENCODER_AAC, VIDEO_ENCODER_H264}, {OUTPUT_FORMAT_MPEG_4, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_MPEG_4_SP}, {OUTPUT_FORMAT_MPEG_4, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_HEVC}}; const string kParametersList[] = {"max-duration", "max-filesize", "interleave-duration-us", "param-movie-time-scale", "param-geotag-longitude", "param-geotag-latitude", "param-track-time-status", "audio-param-sampling-rate", "audio-param-encoding-bitrate", "audio-param-number-of-channels", "audio-param-time-scale", "video-param-rotation-angle-degrees", "video-param-encoding-bitrate", "video-param-bitrate-mode", "video-param-i-frames-interval", "video-param-encoder-profile", "video-param-encoder-level", "video-param-camera-id", "video-param-time-scale", "param-use-64bit-offset", "time-lapse-enable", "time-lapse-fps", "rtp-param-local-ip", "rtp-param-local-port", "rtp-param-remote-port", "rtp-param-self-id", "rtp-param-opponent-id", "rtp-param-payload-type", "rtp-param-ext-cvo-extmap", "rtp-param-ext-cvo-degrees", "video-param-request-i-frame", "rtp-param-set-socket-dscp", "rtp-param-set-socket-network"}; constexpr int32_t kMaxSleepTimeInMs = 100; constexpr int32_t kMinSleepTimeInMs = 0; constexpr int32_t kMinVideoSize = 2; constexpr int32_t kMaxVideoSize = 8192; constexpr int32_t kNumRecordMin = 1; constexpr int32_t kNumRecordMax = 10; class TestAudioDeviceCallback : public AudioSystem::AudioDeviceCallback { public: virtual ~TestAudioDeviceCallback() = default; void onAudioDeviceUpdate(audio_io_handle_t /*audioIo*/, audio_port_handle_t /*deviceId*/) override{}; }; class TestCamera : public ICamera { public: virtual ~TestCamera() = default; binder::Status disconnect() override { return binder::Status::ok(); }; status_t connect(const sp<ICameraClient> & /*client*/) override { return 0; }; status_t lock() override { return 0; }; status_t unlock() override { return 0; }; status_t setPreviewTarget(const sp<IGraphicBufferProducer> & /*bufferProducer*/) override { return 0; }; void setPreviewCallbackFlag(int /*flag*/) override{}; status_t setPreviewCallbackTarget( const sp<IGraphicBufferProducer> & /*callbackProducer*/) override { return 0; }; status_t startPreview() override { return 0; }; void stopPreview() override{}; bool previewEnabled() override { return true; }; status_t startRecording() override { return 0; }; void stopRecording() override{}; bool recordingEnabled() override { return true; }; void releaseRecordingFrame(const sp<IMemory> & /*mem*/) override{}; void releaseRecordingFrameHandle(native_handle_t * /*handle*/) override{}; void releaseRecordingFrameHandleBatch(const vector<native_handle_t *> & /*handles*/) override{}; status_t autoFocus() override { return 0; }; status_t cancelAutoFocus() override { return 0; }; status_t takePicture(int /*msgType*/) override { return 0; }; status_t setParameters(const String8 & /*params*/) override { return 0; }; String8 getParameters() const override { return String8(); }; status_t sendCommand(int32_t /*cmd*/, int32_t /*arg1*/, int32_t /*arg2*/) override { return 0; }; status_t setVideoBufferMode(int32_t /*videoBufferMode*/) override { return 0; }; status_t setVideoTarget(const sp<IGraphicBufferProducer> & /*bufferProducer*/) override { return 0; }; status_t setAudioRestriction(int32_t /*mode*/) override { return 0; }; int32_t getGlobalAudioRestriction() override { return 0; }; IBinder *onAsBinder() override { return reinterpret_cast<IBinder *>(this); }; }; class TestMediaRecorderClient : public IMediaRecorderClient { public: virtual ~TestMediaRecorderClient() = default; void notify(int /*msg*/, int /*ext1*/, int /*ext2*/) override{}; IBinder *onAsBinder() override { return reinterpret_cast<IBinder *>(this); }; }; class MediaRecorderClientFuzzer { public: MediaRecorderClientFuzzer(const uint8_t *data, size_t size); ~MediaRecorderClientFuzzer() { close(mMediaRecorderOutputFd); } void process(); private: void setConfig(); void getConfig(); void dumpInfo(); FuzzedDataProvider mFdp; unique_ptr<MediaRecorderBase> mStfRecorder = nullptr; SurfaceComposerClient mComposerClient; sp<SurfaceControl> mSurfaceControl = nullptr; sp<Surface> mSurface = nullptr; const int32_t mMediaRecorderOutputFd; }; void MediaRecorderClientFuzzer::getConfig() { int32_t max; mStfRecorder->getMaxAmplitude(&max); int32_t deviceId = mFdp.ConsumeIntegral<int32_t>(); mStfRecorder->setInputDevice(deviceId); mStfRecorder->getRoutedDeviceId(&deviceId); vector<android::media::MicrophoneInfo> activeMicrophones{}; mStfRecorder->getActiveMicrophones(&activeMicrophones); int32_t portId; mStfRecorder->getPortId(&portId); uint64_t bytes; mStfRecorder->getRtpDataUsage(&bytes); Parcel parcel; mStfRecorder->getMetrics(&parcel); sp<IGraphicBufferProducer> buffer = mStfRecorder->querySurfaceMediaSource(); } void MediaRecorderClientFuzzer::dumpInfo() { int32_t dumpFd = memfd_create("DumpFile", MFD_ALLOW_SEALING); Vector<String16> args; args.push_back(String16(mFdp.ConsumeRandomLengthString().c_str())); mStfRecorder->dump(dumpFd, args); close(dumpFd); } void MediaRecorderClientFuzzer::setConfig() { mStfRecorder->setOutputFile(mMediaRecorderOutputFd); mStfRecorder->setAudioSource(mFdp.PickValueInArray(kSupportedAudioSources)); mStfRecorder->setVideoSource(mFdp.PickValueInArray(kSupportedVideoSources)); mStfRecorder->setPreferredMicrophoneDirection( mFdp.PickValueInArray(kSupportedMicrophoneDirections)); mStfRecorder->setPrivacySensitive(mFdp.ConsumeBool()); bool isPrivacySensitive; mStfRecorder->isPrivacySensitive(&isPrivacySensitive); mStfRecorder->setVideoSize(mFdp.ConsumeIntegralInRange<int32_t>(kMinVideoSize, kMaxVideoSize), mFdp.ConsumeIntegralInRange<int32_t>(kMinVideoSize, kMaxVideoSize)); mStfRecorder->setVideoFrameRate(mFdp.ConsumeIntegral<int32_t>()); mStfRecorder->enableAudioDeviceCallback(mFdp.ConsumeBool()); mStfRecorder->setPreferredMicrophoneFieldDimension(mFdp.ConsumeFloatingPoint<float>()); mStfRecorder->setClientName(String16(mFdp.ConsumeRandomLengthString().c_str())); int32_t Idx = mFdp.ConsumeIntegralInRange<int32_t>(0, size(kRecordingConfigList) - 1); mStfRecorder->setOutputFormat(kRecordingConfigList[Idx].outputFormat); mStfRecorder->setAudioEncoder(kRecordingConfigList[Idx].audioEncoder); mStfRecorder->setVideoEncoder(kRecordingConfigList[Idx].videoEncoder); int32_t nextOutputFd = memfd_create("NextOutputFile", MFD_ALLOW_SEALING); mStfRecorder->setNextOutputFile(nextOutputFd); close(nextOutputFd); for (Idx = 0; Idx < size(kParametersList); ++Idx) { if (mFdp.ConsumeBool()) { int32_t value = mFdp.ConsumeIntegral<int32_t>(); mStfRecorder->setParameters( String8((kParametersList[Idx] + "=" + to_string(value)).c_str())); } } } MediaRecorderClientFuzzer::MediaRecorderClientFuzzer(const uint8_t *data, size_t size) : mFdp(data, size), mMediaRecorderOutputFd(memfd_create("OutputFile", MFD_ALLOW_SEALING)) { AttributionSourceState attributionSource; attributionSource.packageName = mFdp.ConsumeRandomLengthString().c_str(); attributionSource.token = sp<BBinder>::make(); mStfRecorder = make_unique<StagefrightRecorder>(attributionSource); mSurfaceControl = mComposerClient.createSurface( String8(mFdp.ConsumeRandomLengthString().c_str()), mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<int32_t>(), mFdp.ConsumeIntegral<int32_t>()); if (mSurfaceControl) { mSurface = mSurfaceControl->getSurface(); mStfRecorder->setPreviewSurface(mSurface->getIGraphicBufferProducer()); } sp<TestMediaRecorderClient> listener = sp<TestMediaRecorderClient>::make(); mStfRecorder->setListener(listener); sp<TestCamera> testCamera = sp<TestCamera>::make(); sp<Camera> camera = Camera::create(testCamera); mStfRecorder->setCamera(camera->remote(), camera->getRecordingProxy()); sp<PersistentSurface> persistentSurface = sp<PersistentSurface>::make(); mStfRecorder->setInputSurface(persistentSurface); sp<TestAudioDeviceCallback> callback = sp<TestAudioDeviceCallback>::make(); mStfRecorder->setAudioDeviceCallback(callback); } void MediaRecorderClientFuzzer::process() { setConfig(); mStfRecorder->init(); mStfRecorder->prepare(); size_t numRecord = mFdp.ConsumeIntegralInRange<size_t>(kNumRecordMin, kNumRecordMax); for (size_t Idx = 0; Idx < numRecord; ++Idx) { mStfRecorder->start(); this_thread::sleep_for(chrono::milliseconds( mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs))); mStfRecorder->pause(); this_thread::sleep_for(chrono::milliseconds( mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs))); mStfRecorder->resume(); this_thread::sleep_for(chrono::milliseconds( mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs))); mStfRecorder->stop(); } dumpInfo(); getConfig(); mStfRecorder->close(); mStfRecorder->reset(); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { MediaRecorderClientFuzzer mrcFuzzer(data, size); mrcFuzzer.process(); return 0; }