/*
 * 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::MicrophoneInfoFw> 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;
}
