/*
* Copyright (c) 2013-2014, 2016, 2018-2020, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*    * Redistributions of source code must retain the above copyright
*      notice, this list of conditions and the following disclaimer.
*    * Redistributions in binary form must reproduce the above
*      copyright notice, this list of conditions and the following
*      disclaimer in the documentation and/or other materials provided
*      with the distribution.
*    * Neither the name of The Linux Foundation. nor the names of its
*      contributors may be used to endorse or promote products derived
*      from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Changes from Qualcomm Innovation Center are provided under the following license:
*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*
*     * Redistributions in binary form must reproduce the above
*       copyright notice, this list of conditions and the following
*       disclaimer in the documentation and/or other materials provided
*       with the distribution.
*
*     * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
*       contributors may be used to endorse or promote products derived
*       from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <display_config.h>
#include <QServiceUtils.h>
#include <qd_utils.h>

using namespace android;
using namespace qService;

namespace qdutils {

//=============================================================================
// The functions below run in the client process and wherever necessary
// do a binder call to HWC to get/set data.

int isExternalConnected(void) {
    return FAILED_TRANSACTION;
}

int getDisplayAttributes(int /* dpy */, DisplayAttributes_t& /* dpyattr */) {
    return FAILED_TRANSACTION;
}

int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect) {
    status_t err = (status_t) FAILED_TRANSACTION;
    sp<IQService> binder = getBinder();
    Parcel inParcel, outParcel;
    inParcel.writeInt32(dpy);
    if(binder != nullptr) {
        err = binder->dispatch(IQService::GET_DISPLAY_VISIBLE_REGION,
                &inParcel, &outParcel);
    }
    if(!err) {
        rect.left = outParcel.readInt32();
        rect.top = outParcel.readInt32();
        rect.right = outParcel.readInt32();
        rect.bottom = outParcel.readInt32();
    } else {
        ALOGE("%s: Failed to getVisibleRegion for dpy =%d: err = %d",
              __FUNCTION__, dpy, err);
    }
    return err;
}

int setSecondaryDisplayStatus(int dpy, uint32_t status) {
    status_t err = (status_t) FAILED_TRANSACTION;
    sp<IQService> binder = getBinder();
    Parcel inParcel, outParcel;
    inParcel.writeInt32(dpy);
    inParcel.writeInt32(status);

    if(binder != nullptr) {
        err = binder->dispatch(IQService::SET_SECONDARY_DISPLAY_STATUS,
                &inParcel, &outParcel);
    }
    if(err)
        ALOGE("%s: Failed for dpy %d status = %d err=%d", __FUNCTION__, dpy,
                                                        status, err);

    return err;
}

int configureDynRefreshRate(uint32_t op, uint32_t refreshRate) {
    status_t err = (status_t) FAILED_TRANSACTION;
    sp<IQService> binder = getBinder();
    Parcel inParcel, outParcel;
    inParcel.writeInt32(op);
    inParcel.writeInt32(refreshRate);

    if(binder != nullptr) {
        err = binder->dispatch(IQService::CONFIGURE_DYN_REFRESH_RATE,
                               &inParcel, &outParcel);
    }

    if(err)
        ALOGE("%s: Failed setting op %d err=%d", __FUNCTION__, op, err);

    return err;
}

int getConfigCount(int /*dpy*/) {
    int numConfigs = -1;
    sp<IQService> binder = getBinder();
    if(binder != nullptr) {
        Parcel inParcel, outParcel;
        inParcel.writeInt32(DISPLAY_PRIMARY);
        status_t err = binder->dispatch(IQService::GET_CONFIG_COUNT,
                &inParcel, &outParcel);
        if(!err) {
            numConfigs = outParcel.readInt32();
            ALOGI("%s() Received num configs %d", __FUNCTION__, numConfigs);
        } else {
            ALOGE("%s() failed with err %d", __FUNCTION__, err);
        }
    }
    return numConfigs;
}

int getActiveConfig(int dpy) {
    int configIndex = -1;
    sp<IQService> binder = getBinder();
    if(binder != nullptr) {
        Parcel inParcel, outParcel;
        inParcel.writeInt32(dpy);
        status_t err = binder->dispatch(IQService::GET_ACTIVE_CONFIG,
                &inParcel, &outParcel);
        if(!err) {
            configIndex = outParcel.readInt32();
            ALOGI("%s() Received active config index %d", __FUNCTION__,
                    configIndex);
        } else {
            ALOGE("%s() failed with err %d", __FUNCTION__, err);
        }
    }
    return configIndex;
}

int setActiveConfig(int configIndex, int /*dpy*/) {
    status_t err = (status_t) FAILED_TRANSACTION;
    sp<IQService> binder = getBinder();
    if(binder != nullptr) {
        Parcel inParcel, outParcel;
        inParcel.writeInt32(configIndex);
        inParcel.writeInt32(DISPLAY_PRIMARY);
        err = binder->dispatch(IQService::SET_ACTIVE_CONFIG,
                &inParcel, &outParcel);
        if(!err) {
            ALOGI("%s() Successfully set active config index %d", __FUNCTION__,
                    configIndex);
        } else {
            ALOGE("%s() failed with err %d", __FUNCTION__, err);
        }
    }
    return err;
}

DisplayAttributes getDisplayAttributes(int configIndex, int dpy) {
    DisplayAttributes dpyattr = {};
    sp<IQService> binder = getBinder();
    if(binder != nullptr) {
        Parcel inParcel, outParcel;
        inParcel.writeInt32(configIndex);
        inParcel.writeInt32(dpy);
        status_t err = binder->dispatch(
                IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG, &inParcel,
                &outParcel);
        if(!err) {
            dpyattr.vsync_period = outParcel.readInt32();
            dpyattr.xres = outParcel.readInt32();
            dpyattr.yres = outParcel.readInt32();
            dpyattr.xdpi = outParcel.readFloat();
            dpyattr.ydpi = outParcel.readFloat();
            dpyattr.panel_type = outParcel.readInt32();
            dpyattr.is_yuv = outParcel.readInt32();
            ALOGI("%s() Received attrs for index %d: xres %d, yres %d",
                    __FUNCTION__, configIndex, dpyattr.xres, dpyattr.yres);
        } else {
            ALOGE("%s() failed with err %d", __FUNCTION__, err);
        }
    }
    return dpyattr;
}

int setPanelMode(int mode) {
    status_t err = (status_t) FAILED_TRANSACTION;
    sp<IQService> binder = getBinder();
    if(binder != nullptr) {
        Parcel inParcel, outParcel;
        inParcel.writeInt32(mode);
        err = binder->dispatch(IQService::SET_DISPLAY_MODE,
                               &inParcel, &outParcel);
        if(!err) {
            ALOGI("%s() Successfully set the display mode to %d", __FUNCTION__,
                  mode);
        } else {
            ALOGE("%s() failed with err %d", __FUNCTION__, err);
        }
    }
    return err;
}

int setPanelBrightness(int level) {
    status_t err = (status_t) FAILED_TRANSACTION;
    sp<IQService> binder = getBinder();
    Parcel inParcel, outParcel;

    if(binder != nullptr) {
        inParcel.writeInt32(level);
        status_t err = binder->dispatch(IQService::SET_PANEL_BRIGHTNESS,
                &inParcel, &outParcel);
        if(err) {
            ALOGE("%s() failed with err %d", __FUNCTION__, err);
        }
    }
    return err;
}

int getPanelBrightness() {
    int panel_brightness = -1;
    sp<IQService> binder = getBinder();
    Parcel inParcel, outParcel;

    if(binder != nullptr) {
        status_t err = binder->dispatch(IQService::GET_PANEL_BRIGHTNESS,
                &inParcel, &outParcel);
        if(!err) {
            panel_brightness = outParcel.readInt32();
            ALOGI("%s() Current panel brightness value %d", __FUNCTION__,
                    panel_brightness);
        } else {
            ALOGE("%s() failed with err %d", __FUNCTION__, err);
        }
    }
    return panel_brightness;
}

int setDsiClk(int dpy, uint64_t bitClk) {
    status_t err = (status_t) FAILED_TRANSACTION;
    sp<IQService> binder = getBinder();
    Parcel inParcel, outParcel;

    if(binder != nullptr) {
        inParcel.writeInt32(dpy);
        inParcel.writeUint64(bitClk);
        status_t err = binder->dispatch(IQService::SET_DSI_CLK, &inParcel, &outParcel);
        if(err) {
            ALOGE("%s() failed with err %d", __FUNCTION__, err);
        }
    }
    return err;
}

uint64_t getDsiClk(int dpy) {
    uint64_t dsi_clk = 0;
    sp<IQService> binder = getBinder();
    Parcel inParcel, outParcel;

    if(binder != nullptr) {
        inParcel.writeInt32(dpy);
        status_t err = binder->dispatch(IQService::GET_DSI_CLK, &inParcel, &outParcel);
        if(!err) {
            dsi_clk = outParcel.readUint64();
        } else {
            ALOGE("%s() failed with err %d", __FUNCTION__, err);
        }
    }
    return dsi_clk;
}

int getSupportedBitClk(int dpy, std::vector<uint64_t>& bit_rates) {
    sp<IQService> binder = getBinder();
    Parcel inParcel, outParcel;

    if(binder != nullptr) {
        inParcel.writeInt32(dpy);
        status_t err = binder->dispatch(IQService::GET_SUPPORTED_DSI_CLK, &inParcel, &outParcel);
        if(err) {
            ALOGE("%s() failed with err %d", __FUNCTION__, err);
            return err;
        }
    }

    int32_t clk_levels = outParcel.readInt32();
    while (clk_levels > 0) {
      bit_rates.push_back(outParcel.readUint64());
      clk_levels--;
    }
    return 0;
}

int setPanelLuminanceAttributes(int dpy, float min_lum, float max_lum) {
    status_t err = (status_t) FAILED_TRANSACTION;
    sp<IQService> binder = getBinder();
    Parcel inParcel, outParcel;

    if(binder != nullptr) {
        inParcel.writeInt32(dpy);
        inParcel.writeFloat(min_lum);
        inParcel.writeFloat(max_lum);
        status_t err = binder->dispatch(IQService::SET_PANEL_LUMINANCE, &inParcel, &outParcel);
        if(err) {
            ALOGE("%s() failed with err %d", __FUNCTION__, err);
        }
    }
    return err;
}

int GetDisplayPortId(int dpy, int *port_id) {
    if (!port_id) {
        return -EINVAL;
    }
    status_t err = (status_t) FAILED_TRANSACTION;
    sp<IQService> binder = getBinder();
    Parcel inParcel, outParcel;
    if(binder != nullptr && binder.get() != nullptr) {
        inParcel.writeInt32(dpy);
        err = binder->dispatch(IQService::GET_DISPLAY_PORT_ID, &inParcel, &outParcel);
        if(err) {
            ALOGE("%s() failed with err %d", __FUNCTION__, err);
            return err;
        }
        *port_id = outParcel.readInt32();
    }
    return err;
}

}// namespace

// ----------------------------------------------------------------------------
// Functions for linking dynamically to libqdutils
// ----------------------------------------------------------------------------
extern "C" int minHdcpEncryptionLevelChanged(int dpy, int min_enc_level) {
    status_t err = (status_t) FAILED_TRANSACTION;
    sp<IQService> binder = getBinder();
    Parcel inParcel, outParcel;
    inParcel.writeInt32(dpy);
    inParcel.writeInt32(min_enc_level);

    if(binder != nullptr) {
        err = binder->dispatch(IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED,
                &inParcel, &outParcel);
    }

    if(err) {
        ALOGE("%s: Failed for dpy %d err=%d", __FUNCTION__, dpy, err);
    } else {
        err = outParcel.readInt32();
    }

    return err;
}

extern "C" int refreshScreen(int dpy) {
    int ret = 0;
    ret = screenRefresh(dpy);
    return ret;
}

extern "C" int controlPartialUpdate(int dpy, int mode) {
    status_t err = (status_t) FAILED_TRANSACTION;
    sp<IQService> binder = getBinder();
    if(binder != nullptr) {
        Parcel inParcel, outParcel;
        inParcel.writeInt32(dpy);
        inParcel.writeInt32(mode);
        err = binder->dispatch(IQService::CONTROL_PARTIAL_UPDATE, &inParcel, &outParcel);
        if(err != 0) {
            ALOGE_IF(getBinder(), "%s() failed with err %d", __FUNCTION__, err);
        } else {
            return outParcel.readInt32();
        }
    }

    return err;
}

// returns 0 if composer is up
extern "C" int waitForComposerInit() {
    int status = false;
    sp<IQService> binder = getBinder();
    if (binder == nullptr) {
        sleep(2);
        binder = getBinder();
    }

    if (binder != nullptr) {
        Parcel inParcel, outParcel;
        binder->dispatch(IQService::GET_COMPOSER_STATUS, &inParcel, &outParcel);
        status = !!outParcel.readInt32();
        if (!status) {
            sleep(2);
            binder->dispatch(IQService::GET_COMPOSER_STATUS, &inParcel, &outParcel);
            status = !!outParcel.readInt32();
        }
    }

    return !status;
}

extern "C" int waitForComposerInitPerf() {
    int status = false;
    sp<IQService> binder = getBinder();
    if (binder != nullptr) {
        Parcel inParcel, outParcel;
        binder->dispatch(IQService::GET_COMPOSER_STATUS, &inParcel, &outParcel);
        status = !!outParcel.readInt32();
    }

    return !status;
}
