/*
 * Copyright (C) 2015 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.
 */

#define LOG_TAG "VehicleNetwork"

#include <memory>
#include <string.h>

#include <binder/IPCThreadState.h>
#include <binder/Status.h>

#include <utils/Log.h>

#include <IVehicleNetwork.h>
#include <VehicleNetworkProto.pb.h>

#include "BinderUtil.h"
#include "VehicleNetworkProtoUtil.h"

namespace android {

enum {
    LIST_PROPERTIES = IBinder::FIRST_CALL_TRANSACTION,
    SET_PROPERTY,
    GET_PROPERTY,
    SUBSCRIBE,
    UNSUBSCRIBE,
    INJECT_EVENT,
    START_MOCKING,
    STOP_MOCKING,
    INJECT_HAL_ERROR,
    START_ERROR_LISTENING,
    STOP_ERROR_LISTENING,
    START_HAL_RESTART_MONITORING,
    STOP_HAL_RESTART_MONITORING
};

// ----------------------------------------------------------------------------

const char IVehicleNetwork::SERVICE_NAME[] = "com.android.car.vehiclenetwork.IVehicleNetwork";

// ----------------------------------------------------------------------------

class BpVehicleNetwork : public BpInterface<IVehicleNetwork> {
public:
    explicit BpVehicleNetwork(const sp<IBinder> & impl)
        : BpInterface<IVehicleNetwork>(impl) {
    }

    virtual sp<VehiclePropertiesHolder> listProperties(int32_t property) {
        sp<VehiclePropertiesHolder> holder;
        Parcel data, reply;
        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
        data.writeInt32(property);
        status_t status = remote()->transact(LIST_PROPERTIES, data, &reply);
        if (status == NO_ERROR) {
            reply.readExceptionCode(); // for compatibility with java
            if (reply.readInt32() == 0) { // no result
                return holder;
            }
            ReadableBlobHolder blob(new Parcel::ReadableBlob());
            if (blob.blob == NULL) {
                ALOGE("listProperties, no memory");
                return holder;
            }
            int32_t size = reply.readInt32();
            if (size < 0) {
                ALOGE("listProperties, bad blob size %d", size);
                return holder;
            }
            status = reply.readBlob(size, blob.blob);
            if (status != NO_ERROR) {
                ALOGE("listProperties, cannot read blob %d", status);
                return holder;
            }
            std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
            if (configs.get() == NULL) {
                return holder;
            }
            if(!configs->ParseFromArray(blob.blob->data(), size)) {
                ALOGE("listProperties, cannot parse reply");
                return holder;
            }
            holder = new VehiclePropertiesHolder();
            ASSERT_OR_HANDLE_NO_MEMORY(holder.get(), return);
            status = VehicleNetworkProtoUtil::fromVehiclePropConfigs(*configs.get(),
                    holder->getList());
            if (status != NO_ERROR) {
                ALOGE("listProperties, cannot convert VehiclePropConfigs %d", status);
                return holder;
            }

        }
        return holder;
    }

    virtual status_t setProperty(const vehicle_prop_value_t& value) {
        Parcel data, reply;
        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
        status_t status = VehiclePropValueBinderUtil::writeToParcel(data, value);
        if (status != NO_ERROR) {
            return status;
        }
        status = remote()->transact(SET_PROPERTY, data, &reply);
        if (status == NO_ERROR) {
            int32_t exceptionCode = reply.readExceptionCode();
            if (exceptionCode != NO_ERROR) {
                if (exceptionCode == binder::Status::EX_SERVICE_SPECIFIC) {
                    return -EAGAIN;
                } else if (exceptionCode == binder::Status::EX_ILLEGAL_STATE) {
                    return -ESHUTDOWN;
                }
                return exceptionCode;
            }
        }
        return status;
    }

    virtual status_t getProperty(vehicle_prop_value_t* value) {
        Parcel data, reply;
        if (value == NULL) {
            return BAD_VALUE;
        }
        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
        status_t status = VehiclePropValueBinderUtil::writeToParcel(data, *value);
        if (status != NO_ERROR) {
            ALOGE("getProperty, cannot write");
            return status;
        }
        status = remote()->transact(GET_PROPERTY, data, &reply);
        if (status == NO_ERROR) {
            int32_t exceptionCode = reply.readExceptionCode();
            if (exceptionCode != NO_ERROR) {
                if (exceptionCode == binder::Status::EX_SERVICE_SPECIFIC) {
                    return -EAGAIN;
                } else if (exceptionCode == binder::Status::EX_ILLEGAL_STATE) {
                    return -ESHUTDOWN;
                }
                return exceptionCode;
            }
            status = VehiclePropValueBinderUtil::readFromParcel(reply, value);
        }
        return status;
    }

    virtual status_t subscribe(const sp<IVehicleNetworkListener> &listener, int32_t property,
                float sampleRate, int32_t zones, int32_t flags) {
        Parcel data, reply;
        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(listener));
        data.writeInt32(property);
        data.writeFloat(sampleRate);
        data.writeInt32(zones);
        data.writeInt32(flags);
        status_t status = remote()->transact(SUBSCRIBE, data, &reply);
        return status;
    }

    virtual void unsubscribe(const sp<IVehicleNetworkListener> &listener, int32_t property) {
        Parcel data, reply;
        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(listener));
        data.writeInt32(property);
        status_t status = remote()->transact(UNSUBSCRIBE, data, &reply);
        if (status != NO_ERROR) {
            ALOGI("unsubscribing property %d failed %d", property, status);
        }
    }

    virtual status_t injectEvent(const vehicle_prop_value_t& value) {
        Parcel data, reply;
        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
        data.writeInt32(1); // 0 means no value. For compatibility with aidl based code.
        std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
        ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
        VehicleNetworkProtoUtil::toVehiclePropValue(value, *v.get());
        int size = v->ByteSize();
        WritableBlobHolder blob(new Parcel::WritableBlob());
        ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
        data.writeInt32(size);
        data.writeBlob(size, false, blob.blob);
        v->SerializeToArray(blob.blob->data(), size);
        status_t status = remote()->transact(INJECT_EVENT, data, &reply);
        return status;
    }

    virtual status_t startMocking(const sp<IVehicleNetworkHalMock>& mock) {
        Parcel data, reply;
        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(mock));
        status_t status = remote()->transact(START_MOCKING, data, &reply);
        return status;
    }

    virtual void stopMocking(const sp<IVehicleNetworkHalMock>& mock) {
        Parcel data, reply;
        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(mock));
        status_t status = remote()->transact(STOP_MOCKING, data, &reply);
        if (status != NO_ERROR) {
            ALOGI("stop mocking failed %d", status);
        }
    }

    status_t injectHalError(int32_t errorCode, int32_t property, int32_t operation) {
        Parcel data, reply;
        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
        data.writeInt32(errorCode);
        data.writeInt32(property);
        data.writeInt32(operation);
        status_t status = remote()->transact(INJECT_HAL_ERROR, data, &reply);
        return status;
    }

    virtual status_t startErrorListening(const sp<IVehicleNetworkListener> &listener) {
        Parcel data, reply;
        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(listener));
        status_t status = remote()->transact(START_ERROR_LISTENING, data, &reply);
        return status;
    }

    virtual void stopErrorListening(const sp<IVehicleNetworkListener> &listener) {
        Parcel data, reply;
        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(listener));
        status_t status = remote()->transact(STOP_ERROR_LISTENING, data, &reply);
        if (status != NO_ERROR) {
            ALOGI("stopErrorListening %d", status);
        }
    }

    virtual status_t startHalRestartMonitoring(const sp<IVehicleNetworkListener> &listener) {
        Parcel data, reply;
        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(listener));
        status_t status = remote()->transact(START_HAL_RESTART_MONITORING, data, &reply);
        return status;
    }

    virtual void stopHalRestartMonitoring(const sp<IVehicleNetworkListener> &listener) {
        Parcel data, reply;
        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(listener));
        status_t status = remote()->transact(STOP_HAL_RESTART_MONITORING, data, &reply);
        if (status != NO_ERROR) {
            ALOGI("stopHalRestartMonitoring %d", status);
        }
    }
};

IMPLEMENT_META_INTERFACE(VehicleNetwork, IVehicleNetwork::SERVICE_NAME);

// ----------------------------------------------------------------------

status_t BnVehicleNetwork::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
        uint32_t flags) {
    status_t r;
    switch (code) {
        case LIST_PROPERTIES: {
            CHECK_INTERFACE(IVehicleNetwork, data, reply);
            if (!isOperationAllowed(0, false)) {
                return PERMISSION_DENIED;
            }
            int32_t property = data.readInt32();
            sp<VehiclePropertiesHolder> holder = listProperties(property);
            if (holder.get() == NULL) { // given property not found
                BinderUtil::fillObjectResultReply(reply, false /* isValid */);
                return NO_ERROR;
            }
            std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
            ASSERT_OR_HANDLE_NO_MEMORY(configs.get(), return NO_MEMORY);
            VehicleNetworkProtoUtil::toVehiclePropConfigs(holder->getList(), *configs.get());
            int size = configs->ByteSize();
            WritableBlobHolder blob(new Parcel::WritableBlob());
            ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
            BinderUtil::fillObjectResultReply(reply, true);
            reply->writeInt32(size);
            reply->writeBlob(size, false, blob.blob);
            configs->SerializeToArray(blob.blob->data(), size);
            return NO_ERROR;
        } break;
        case SET_PROPERTY: {
            CHECK_INTERFACE(IVehicleNetwork, data, reply);
            ScopedVehiclePropValue value;
            r = VehiclePropValueBinderUtil::readFromParcel(data, &value.value,
                    false /* deleteMembers */);
            if (r != NO_ERROR) {
                return r;
            }
            if (!isOperationAllowed(value.value.prop, true)) {
                return PERMISSION_DENIED;
            }
            r = setProperty(value.value);
            if (r == NO_ERROR) {
                reply->writeNoException();
            } else if (r == -EAGAIN) {
                // this should be handled specially to throw ServiceSpecificException in java.
                reply->writeInt32(binder::Status::EX_SERVICE_SPECIFIC);
                return NO_ERROR;
            } else if (r == -ESHUTDOWN) {
                // this should be handled specially to throw IllegalStateException in java.
                reply->writeInt32(binder::Status::EX_ILLEGAL_STATE);
                return NO_ERROR;
            }
            return r;
        } break;
        case GET_PROPERTY: {
            CHECK_INTERFACE(IVehicleNetwork, data, reply);
            vehicle_prop_value_t value;
            memset(&value, 0, sizeof(value));
            r = VehiclePropValueBinderUtil::readFromParcel(data, &value,
                    false /* deleteMembers */, true /*canIgnoreNoData*/);
            if (r != NO_ERROR) {
                ALOGE("getProperty cannot read %d", r);
                return r;
            }
            if (!isOperationAllowed(value.prop, false)) {
                return PERMISSION_DENIED;
            }
            r = getProperty(&value);
            if (r == NO_ERROR) {
                // If int32 or float value is out of range, throw an exception:
                switch (value.value_type) {
                case VEHICLE_VALUE_TYPE_INT32:
                case VEHICLE_VALUE_TYPE_ZONED_INT32:
                    if (value.value.int32_value == VEHICLE_INT_OUT_OF_RANGE_OFF) {
                        // this should be handled specially to throw IllegalStateException in java.
                        reply->writeInt32(binder::Status::EX_ILLEGAL_STATE);
                        return NO_ERROR;
                    }
                    break;
                case VEHICLE_VALUE_TYPE_FLOAT:
                case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
                    if (value.value.float_value == VEHICLE_FLOAT_OUT_OF_RANGE_OFF) {
                        // this should be handled specially to throw IllegalStateException in java.
                        reply->writeInt32(binder::Status::EX_ILLEGAL_STATE);
                        return NO_ERROR;
                    }
                    break;
                }
                reply->writeNoException();
                r = VehiclePropValueBinderUtil::writeToParcel(*reply, value);
                releaseMemoryFromGet(&value);
            } else if (r == -EAGAIN) {
                // this should be handled specially to throw ServiceSpecificException in java.
                reply->writeInt32(binder::Status::EX_SERVICE_SPECIFIC);
                return NO_ERROR;
            }
            return r;
        } break;
        case SUBSCRIBE: {
            CHECK_INTERFACE(IVehicleNetwork, data, reply);
            sp<IVehicleNetworkListener> listener =
                    interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
            int32_t property = data.readInt32();
            if (!isOperationAllowed(property, false)) {
                return PERMISSION_DENIED;
            }
            float sampleRate = data.readFloat();
            int32_t zones = data.readInt32();
            int32_t flags = data.readInt32();
            r = subscribe(listener, property, sampleRate, zones, flags);
            BinderUtil::fillNoResultReply(reply);
            return r;
        } break;
        case UNSUBSCRIBE: {
            CHECK_INTERFACE(IVehicleNetwork, data, reply);
            sp<IVehicleNetworkListener> listener =
                    interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
            int32_t property = data.readInt32();
            if (!isOperationAllowed(property, false)) {
                return PERMISSION_DENIED;
            }
            unsubscribe(listener, property);
            BinderUtil::fillNoResultReply(reply);
            return NO_ERROR;
        } break;
        case INJECT_EVENT: {
            CHECK_INTERFACE(IVehicleNetwork, data, reply);
            if (data.readInt32() == 0) { // java side allows passing null with this.
                return BAD_VALUE;
            }
            if (!isOperationAllowed(0, true)) {
                return PERMISSION_DENIED;
            }
            ScopedVehiclePropValue value;
            ReadableBlobHolder blob(new Parcel::ReadableBlob());
            ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
            int32_t size = data.readInt32();
            if (size < 0) {
                ALOGE("injectEvent:service, bad blob size %d", size);
                return BAD_VALUE;
            }
            r = data.readBlob(size, blob.blob);
            if (r != NO_ERROR) {
                ALOGE("injectEvent:service, cannot read blob");
                return r;
            }
            std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
            ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
            if (!v->ParseFromArray(blob.blob->data(), size)) {
                ALOGE("injectEvent:service, cannot parse data");
                return BAD_VALUE;
            }
            r = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), value.value);
            if (r != NO_ERROR) {
                ALOGE("injectEvent:service, cannot convert data");
                return BAD_VALUE;
            }
            r = injectEvent(value.value);
            BinderUtil::fillNoResultReply(reply);
            return r;
        } break;
        case START_MOCKING: {
            if (!isOperationAllowed(0, true)) {
                return PERMISSION_DENIED;
            }
            CHECK_INTERFACE(IVehicleNetwork, data, reply);
            sp<IVehicleNetworkHalMock> mock =
                    interface_cast<IVehicleNetworkHalMock>(data.readStrongBinder());
            r = startMocking(mock);
            BinderUtil::fillNoResultReply(reply);
            return r;
        } break;
        case STOP_MOCKING: {
            if (!isOperationAllowed(0, true)) {
                return PERMISSION_DENIED;
            }
            CHECK_INTERFACE(IVehicleNetwork, data, reply);
            sp<IVehicleNetworkHalMock> mock =
                    interface_cast<IVehicleNetworkHalMock>(data.readStrongBinder());
            stopMocking(mock);
            BinderUtil::fillNoResultReply(reply);
            return NO_ERROR;
        } break;
        case INJECT_HAL_ERROR: {
            if (!isOperationAllowed(0, true)) {
                return PERMISSION_DENIED;
            }
            CHECK_INTERFACE(IVehicleNetwork, data, reply);
            int32_t errorCode = data.readInt32();
            int32_t property = data.readInt32();
            int32_t operation = data.readInt32();
            r = injectHalError(errorCode, property, operation);
            BinderUtil::fillNoResultReply(reply);
            return r;
        } break;
        case START_ERROR_LISTENING: {
            if (!isOperationAllowed(0, false)) {
                return PERMISSION_DENIED;
            }
            CHECK_INTERFACE(IVehicleNetwork, data, reply);
            sp<IVehicleNetworkListener> listener =
                    interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
            r = startErrorListening(listener);
            BinderUtil::fillNoResultReply(reply);
            return r;
        } break;
        case STOP_ERROR_LISTENING: {
            if (!isOperationAllowed(0, false)) {
                return PERMISSION_DENIED;
            }
            CHECK_INTERFACE(IVehicleNetwork, data, reply);
            sp<IVehicleNetworkListener> listener =
                    interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
            stopErrorListening(listener);
            BinderUtil::fillNoResultReply(reply);
            return NO_ERROR;
        } break;
        case START_HAL_RESTART_MONITORING: {
            if (!isOperationAllowed(0, false)) {
                return PERMISSION_DENIED;
            }
            CHECK_INTERFACE(IVehicleNetwork, data, reply);
            sp<IVehicleNetworkListener> listener =
                    interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
            r = startHalRestartMonitoring(listener);
            BinderUtil::fillNoResultReply(reply);
            return r;
        } break;
        case STOP_HAL_RESTART_MONITORING: {
            if (!isOperationAllowed(0, false)) {
                return PERMISSION_DENIED;
            }
            CHECK_INTERFACE(IVehicleNetwork, data, reply);
            sp<IVehicleNetworkListener> listener =
                    interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
            stopHalRestartMonitoring(listener);
            BinderUtil::fillNoResultReply(reply);
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

}; // namespace android
