/*
 * Copyright 2019 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.
 */

#ifndef OBOE_AAUDIO_EXTENSIONS_H
#define OBOE_AAUDIO_EXTENSIONS_H

#include <dlfcn.h>
#include <stdint.h>

#include <sys/system_properties.h>

#include "common/OboeDebug.h"
#include "oboe/Oboe.h"
#include "AAudioLoader.h"

namespace oboe {

#define LIB_AAUDIO_NAME          "libaaudio.so"
#define FUNCTION_IS_MMAP         "AAudioStream_isMMapUsed"
#define FUNCTION_SET_MMAP_POLICY "AAudio_setMMapPolicy"
#define FUNCTION_GET_MMAP_POLICY "AAudio_getMMapPolicy"

#define AAUDIO_ERROR_UNAVAILABLE  static_cast<aaudio_result_t>(Result::ErrorUnavailable)

typedef struct AAudioStreamStruct         AAudioStream;

/**
 * Call some AAudio test routines that are not part of the normal API.
 */
class AAudioExtensions {
public:
    AAudioExtensions() {
        int32_t policy = getIntegerProperty("aaudio.mmap_policy", 0);
        mMMapSupported = isPolicyEnabled(policy);

        policy = getIntegerProperty("aaudio.mmap_exclusive_policy", 0);
        mMMapExclusiveSupported = isPolicyEnabled(policy);
    }

    static bool isPolicyEnabled(int32_t policy) {
        return (policy == AAUDIO_POLICY_AUTO || policy == AAUDIO_POLICY_ALWAYS);
    }

    static AAudioExtensions &getInstance() {
        static AAudioExtensions instance;
        return instance;
    }

    bool isMMapUsed(oboe::AudioStream *oboeStream) {
        AAudioStream *aaudioStream = (AAudioStream *) oboeStream->getUnderlyingStream();
        return isMMapUsed(aaudioStream);
    }

    bool isMMapUsed(AAudioStream *aaudioStream) {
        if (loadSymbols()) return false;
        if (mAAudioStream_isMMap == nullptr) return false;
        return mAAudioStream_isMMap(aaudioStream);
    }

    /**
     * Controls whether the MMAP data path can be selected when opening a stream.
     * It has no effect after the stream has been opened.
     * It only affects the application that calls it. Other apps are not affected.
     *
     * @param enabled
     * @return 0 or a negative error code
     */
    int32_t setMMapEnabled(bool enabled) {
        if (loadSymbols()) return AAUDIO_ERROR_UNAVAILABLE;
        if (mAAudio_setMMapPolicy == nullptr) return false;
        return mAAudio_setMMapPolicy(enabled ? AAUDIO_POLICY_AUTO : AAUDIO_POLICY_NEVER);
    }

    bool isMMapEnabled() {
        if (loadSymbols()) return false;
        if (mAAudio_getMMapPolicy == nullptr) return false;
        int32_t policy = mAAudio_getMMapPolicy();
        return isPolicyEnabled(policy);
    }

    bool isMMapSupported() {
        return mMMapSupported;
    }

    bool isMMapExclusiveSupported() {
        return mMMapExclusiveSupported;
    }

private:

    enum {
        AAUDIO_POLICY_NEVER = 1,
        AAUDIO_POLICY_AUTO,
        AAUDIO_POLICY_ALWAYS
    };
    typedef int32_t aaudio_policy_t;

    int getIntegerProperty(const char *name, int defaultValue) {
        int result = defaultValue;
        char valueText[PROP_VALUE_MAX] = {0};
        if (__system_property_get(name, valueText) != 0) {
            result = atoi(valueText);
        }
        return result;
    }

    /**
     * Load the function pointers.
     * This can be called multiple times.
     * It should only be called from one thread.
     *
     * @return 0 if successful or negative error.
     */
    aaudio_result_t loadSymbols() {
        if (mAAudio_getMMapPolicy != nullptr) {
            return 0;
        }

        void *libHandle = AAudioLoader::getInstance()->getLibHandle();
        if (libHandle == nullptr) {
            LOGI("%s() could not find " LIB_AAUDIO_NAME, __func__);
            return AAUDIO_ERROR_UNAVAILABLE;
        }

        mAAudioStream_isMMap = (bool (*)(AAudioStream *stream))
                dlsym(libHandle, FUNCTION_IS_MMAP);
        if (mAAudioStream_isMMap == nullptr) {
            LOGI("%s() could not find " FUNCTION_IS_MMAP, __func__);
            return AAUDIO_ERROR_UNAVAILABLE;
        }

        mAAudio_setMMapPolicy = (int32_t (*)(aaudio_policy_t policy))
                dlsym(libHandle, FUNCTION_SET_MMAP_POLICY);
        if (mAAudio_setMMapPolicy == nullptr) {
            LOGI("%s() could not find " FUNCTION_SET_MMAP_POLICY, __func__);
            return AAUDIO_ERROR_UNAVAILABLE;
        }

        mAAudio_getMMapPolicy = (aaudio_policy_t (*)())
                dlsym(libHandle, FUNCTION_GET_MMAP_POLICY);
        if (mAAudio_getMMapPolicy == nullptr) {
            LOGI("%s() could not find " FUNCTION_GET_MMAP_POLICY, __func__);
            return AAUDIO_ERROR_UNAVAILABLE;
        }

        return 0;
    }

    bool      mMMapSupported = false;
    bool      mMMapExclusiveSupported = false;

    bool    (*mAAudioStream_isMMap)(AAudioStream *stream) = nullptr;
    int32_t (*mAAudio_setMMapPolicy)(aaudio_policy_t policy) = nullptr;
    aaudio_policy_t (*mAAudio_getMMapPolicy)() = nullptr;
};

} // namespace oboe

#endif //OBOE_AAUDIO_EXTENSIONS_H
