/*
 * 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.
 */
package com.android.car.vehiclenetwork;

import static com.android.car.vehiclenetwork.VehiclePropValueUtil.getVectorLength;
import static com.android.car.vehiclenetwork.VehiclePropValueUtil.isCustomProperty;
import static com.android.car.vehiclenetwork.VehiclePropValueUtil.toFloatArray;
import static com.android.car.vehiclenetwork.VehiclePropValueUtil.toIntArray;

import android.annotation.IntDef;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.util.Log;

import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfigs;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValues;
import com.android.internal.annotations.GuardedBy;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;

/**
 * System API to access Vehicle network. This is only for system services and applications should
 * not use this. All APIs will fail with security error if normal app tries this.
 */
public class VehicleNetwork {
    /**
     * Listener for VNS events.
     */
    public interface VehicleNetworkListener {
        /**
         * Notify HAL events. This requires subscribing the property
         */
        void onVehicleNetworkEvents(VehiclePropValues values);
        void onHalError(int errorCode, int property, int operation);
        void onHalRestart(boolean inMocking);
        void onPropertySet(VehiclePropValue value);
    }

    public interface VehicleNetworkHalMock {
        VehiclePropConfigs onListProperties();
        void onPropertySet(VehiclePropValue value);
        VehiclePropValue onPropertyGet(VehiclePropValue value);
        void onPropertySubscribe(int property, float sampleRate, int zones);
        void onPropertyUnsubscribe(int property);
    }

    /**
     * Flags to be used in #subscribe(int, float, int, int).
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
            SubscribeFlags.HAL_EVENT,
            SubscribeFlags.SET_CALL,
            SubscribeFlags.DEFAULT,
    })
    public @interface SubscribeFlags {
        int HAL_EVENT = 0x1;
        int SET_CALL = 0x2;
        int DEFAULT = HAL_EVENT;
    }

    private static final String TAG = VehicleNetwork.class.getSimpleName();

    private final IVehicleNetwork mService;
    private final VehicleNetworkListener mListener;
    private final IVehicleNetworkListenerImpl mVehicleNetworkListener;
    private final EventHandler mEventHandler;

    @GuardedBy("this")
    private VehicleNetworkHalMock mHalMock;
    private IVehicleNetworkHalMock mHalMockImpl;

    private static final int VNS_CONNECT_MAX_RETRY = 10;
    private static final long VNS_RETRY_WAIT_TIME_MS = 1000;
    private static final int NO_ZONE = -1;

    /**
     * Factory method to create VehicleNetwork
     *
     * @param listener listener for listening events
     * @param looper Looper to dispatch listener events
     */
    public static VehicleNetwork createVehicleNetwork(VehicleNetworkListener listener,
            Looper looper) {
        int retryCount = 0;
        IVehicleNetwork service = null;
        while (true) {
            service = IVehicleNetwork.Stub.asInterface(ServiceManager.getService(
                    IVehicleNetwork.class.getCanonicalName()));
            if (service != null) {
                break;
            }
            retryCount++;
            if (retryCount > VNS_CONNECT_MAX_RETRY) {
                break;
            }
            try {
                Thread.sleep(VNS_RETRY_WAIT_TIME_MS);
            } catch (InterruptedException e) {
                //ignore
            }
        }
        if (service == null) {
            throw new RuntimeException("Vehicle network service not available:" +
                    IVehicleNetwork.class.getCanonicalName());
        }
        return new VehicleNetwork(service, listener, looper);
    }

    private VehicleNetwork(IVehicleNetwork service, VehicleNetworkListener listener,
            Looper looper) {
        mService = service;
        mListener = listener;
        mEventHandler = new EventHandler(looper);
        mVehicleNetworkListener = new IVehicleNetworkListenerImpl(this);
    }

    /**
     * List all properties from vehicle HAL
     *
     * @return all properties
     */
    public VehiclePropConfigs listProperties() {
        return listProperties(0 /* all */);
    }

    /**
     * Return configuration information of single property
     *
     * @param property vehicle property number defined in {@link VehicleNetworkConsts}. 0 has has
     * special meaning of list all properties.
     * @return null if given property does not exist.
     */
    public VehiclePropConfigs listProperties(int property) {
        try {
            VehiclePropConfigsParcelable parcelable = mService.listProperties(property);
            if (parcelable != null) {
                return parcelable.configs;
            }
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
        return null;
    }

    /**
     * Set property which will lead into writing the value to vehicle HAL.
     *
     * @throws IllegalArgumentException If value set has wrong value like wrong valueType, wrong
     * data, and etc.
     */
    public void setProperty(VehiclePropValue value)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValueParcelable parcelable = new VehiclePropValueParcelable(value);
        try {
            mService.setProperty(parcelable);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    /**
     * Set integer type property
     *
     * @throws IllegalArgumentException For type mismatch (=the property is not int type)
     */
    public void setIntProperty(int property, int value)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValue v = VehiclePropValueUtil.createIntValue(property, value, 0);
        setProperty(v);
    }

    /**
     * Set int vector type property. Length of passed values should match with vector length.
     */
    public void setIntVectorProperty(int property, int[] values)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValue v = VehiclePropValueUtil.createIntVectorValue(property, values, 0);
        setProperty(v);
    }

    /**
     * Set long type property.
     */
    public void setLongProperty(int property, long value)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValue v = VehiclePropValueUtil.createLongValue(property, value, 0);
        setProperty(v);
    }

    /**
     * Set float type property.
     */
    public void setFloatProperty(int property, float value)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValue v = VehiclePropValueUtil.createFloatValue(property, value, 0);
        setProperty(v);
    }

    /**
     * Set float vector type property. Length of values should match with vector length.
     */
    public void setFloatVectorProperty(int property, float[] values)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValue v = VehiclePropValueUtil.createFloatVectorValue(property, values, 0);
        setProperty(v);
    }

    /**
     * Set zoned boolean type property
     *
     * @throws IllegalArgumentException For type mismatch (=the property is not boolean type)
     */
    public void setBooleanProperty(int property, boolean value)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValue v = VehiclePropValueUtil.createBooleanValue(property, value, 0);
        setProperty(v);
    }

    public void setStringProperty(int property, String value)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValue v = VehiclePropValueUtil.createStringValue(property, value, 0);
        setProperty(v);
    }

    /**
     * Set zoned boolean type property
     *
     * @throws IllegalArgumentException For type mismatch (=the property is not boolean type)
     */
    public void setZonedBooleanProperty(int property, int zone, boolean value)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValue v = VehiclePropValueUtil.createZonedBooleanValue(property, zone, value, 0);
        setProperty(v);
    }

    /**
     * Set zoned float type property
     *
     * @throws IllegalArgumentException For type mismatch (=the property is not float type)
     */
    public void setZonedFloatProperty(int property, int zone, float value)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValue v = VehiclePropValueUtil.createZonedFloatValue(property, zone, value, 0);
        setProperty(v);
    }

    /**
     * Set zoned integer type property
     *
     * @throws IllegalArgumentException For type mismatch (=the property is not int type)
     */
    public void setZonedIntProperty(int property, int zone, int value)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValue v = VehiclePropValueUtil.createZonedIntValue(property, zone, value, 0);
        setProperty(v);
    }

    /**
     * Set zoned int vector type property. Length of passed values should match with vector length.
     */
    public void setZonedIntVectorProperty(int property, int zone, int[] values)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValue v = VehiclePropValueUtil
                .createZonedIntVectorValue(property, zone, values, 0);
        setProperty(v);
    }

    /**
     * Set zoned float vector type property. Length of passed values should match with vector
     * length.
     */
    public void setZonedFloatVectorProperty(int property, int zone, float[] values)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValue v = VehiclePropValueUtil
                .createZonedFloatVectorValue(property, zone, values, 0);
        setProperty(v);
    }

    /**
     * Get property. This can be used for a property which does not require any other data.
     */
    public VehiclePropValue getProperty(int property) throws IllegalArgumentException,
            ServiceSpecificException {
        int valueType = VehicleNetworkConsts.getVehicleValueType(property);
        if (valueType == 0) {
            throw new IllegalArgumentException("Data type is unknown for property: " + property);
        }
        VehiclePropValue value = VehiclePropValueUtil.createBuilder(property, valueType, 0).build();
        return getProperty(value);
    }

    /**
     * Generic get method for any type of property. Some property may require setting data portion
     * as get may return different result depending on the data set.
     */
    public VehiclePropValue getProperty(VehiclePropValue value) throws IllegalArgumentException,
            ServiceSpecificException {
        VehiclePropValueParcelable parcelable = new VehiclePropValueParcelable(value);
        try {
            VehiclePropValueParcelable resParcelable = mService.getProperty(parcelable);
            if (resParcelable != null) {
                return resParcelable.value;
            }
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
        return null;
    }

    /**
     * Get int type property.
     */
    public int getIntProperty(int property) throws IllegalArgumentException,
            ServiceSpecificException {
        VehiclePropValue v = getProperty(
                property, NO_ZONE, VehicleValueType.VEHICLE_VALUE_TYPE_INT32);
        if (v.getInt32ValuesCount() != 1) {
            throw new IllegalStateException();
        }
        return v.getInt32Values(0);
    }

    /**
     * Get zoned int type property.
     */
    public int getZonedIntProperty(int property, int zone) throws IllegalArgumentException,
            ServiceSpecificException {
        VehiclePropValue v = getProperty(
                property, zone, VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32);
        if (v.getInt32ValuesCount() != 1) {
            throw new IllegalStateException();
        }
        return v.getInt32Values(0);
    }

    /**
     * Get int vector type property. Length of values should match vector length.
     */
    public int[] getIntVectorProperty(int property) throws IllegalArgumentException,
            ServiceSpecificException {
        VehiclePropValue v = getProperty(
                property, NO_ZONE, VehicleValueType.VEHICLE_VALUE_TYPE_INT32);
        assertVectorLength(v.getInt32ValuesCount(), property, v.getValueType());
        return toIntArray(v.getInt32ValuesList());
    }

    /**
     * Get zoned int vector type property. Length of values should match vector length.
     */
    public int[] getZonedIntVectorProperty(int property, int zone)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValue v = getProperty(
                property, zone, VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32);
        assertVectorLength(v.getInt32ValuesCount(), property, v.getValueType());
        return toIntArray(v.getInt32ValuesList());
    }

    /**
     * Get float type property.
     */
    public float getFloatProperty(int property) throws IllegalArgumentException,
            ServiceSpecificException {
        VehiclePropValue v = getProperty(
                property, NO_ZONE, VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT);
        if (v.getFloatValuesCount() != 1) {
            throw new IllegalStateException();
        }
        return v.getFloatValues(0);
    }

    /**
     * Get float vector type property. Length of values should match vector's length.
     */
    public float[] getFloatVectorProperty(int property) throws IllegalArgumentException,
            ServiceSpecificException {
        VehiclePropValue v = getProperty(
                property, NO_ZONE, VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT);
        assertVectorLength(v.getFloatValuesCount(), property, v.getValueType());
        return toFloatArray(v.getFloatValuesList());
    }

    /**
     * Get zoned float vector type property. Length of values should match vector's length.
     */
    public float[] getZonedFloatVectorProperty(int property, int zone)
            throws IllegalArgumentException, ServiceSpecificException {
        VehiclePropValue v = getProperty(property, zone,
                VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT);
        assertVectorLength(v.getFloatValuesCount(), property, v.getValueType());
        return toFloatArray(v.getFloatValuesList());
    }

    /**
     * Get long type property.
     */
    public long getLongProperty(int property) throws IllegalArgumentException,
            ServiceSpecificException {
        VehiclePropValue v = getProperty(
                property, NO_ZONE, VehicleValueType.VEHICLE_VALUE_TYPE_INT64);
        return v.getInt64Value();
    }

    /**
     * Get string type property.
     */
    public String getStringProperty(int property) throws IllegalArgumentException,
            ServiceSpecificException {
        VehiclePropValue v = getProperty(
                property, NO_ZONE, VehicleValueType.VEHICLE_VALUE_TYPE_STRING);
        return v.getStringValue();
    }

    /**
     * Subscribe given property with given sample rate.
     */
    public void subscribe(int property, float sampleRate) throws IllegalArgumentException {
        subscribe(property, sampleRate, 0);
    }

    /**
     * Subscribe given property with given sample rate and zones.
     */
    public void subscribe(int property, float sampleRate, int zones)
            throws IllegalArgumentException {
        try {
            mService.subscribe(mVehicleNetworkListener, property, sampleRate, zones,
                    SubscribeFlags.DEFAULT);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    /**
     * Subscribe given property with given sample rate, zones and flags.
     */
    @SuppressWarnings("ResourceType")
    public void subscribe(int property, float sampleRate, int zones, @SubscribeFlags int flags)
            throws IllegalArgumentException {
        try {
            mService.subscribe(mVehicleNetworkListener, property, sampleRate, zones, flags);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    /**
     * Stop subscribing the property.
     */
    public void unsubscribe(int property) {
        try {
            mService.unsubscribe(mVehicleNetworkListener, property);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    /**
     * Inject given value to all clients subscribing the property. This is for testing.
     */
    public synchronized void injectEvent(VehiclePropValue value) {
        try {
            mService.injectEvent(new VehiclePropValueParcelable(value));
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    /**
     * Start mocking of vehicle HAL. For testing only.
     */
    public synchronized void startMocking(VehicleNetworkHalMock mock) {
        mHalMock = mock;
        mHalMockImpl = new IVehicleNetworkHalMockImpl(this);
        try {
            mService.startMocking(mHalMockImpl);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    /**
     * Stop mocking of vehicle HAL. For testing only.
     */
    public synchronized void stopMocking() {
        if (mHalMockImpl == null) {
            return;
        }
        try {
            mService.stopMocking(mHalMockImpl);
        } catch (RemoteException e) {
            handleRemoteException(e);
        } finally {
            mHalMock = null;
            mHalMockImpl = null;
        }
    }

    /**
     * Start mocking of vehicle HAL. For testing only.
     */
    public synchronized void startMocking(IVehicleNetworkHalMock mock) {
        mHalMock = null;
        mHalMockImpl = mock;
        try {
            mService.startMocking(mHalMockImpl);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    /**
     * Stop mocking of vehicle HAL. For testing only.
     */
    public synchronized void stopMocking(IVehicleNetworkHalMock mock) {
        if (mock.asBinder() != mHalMockImpl.asBinder()) {
            return;
        }
        try {
            mService.stopMocking(mHalMockImpl);
        } catch (RemoteException e) {
            handleRemoteException(e);
        } finally {
            mHalMock = null;
            mHalMockImpl = null;
        }
    }

    public synchronized void injectHalError(int errorCode, int property, int operation) {
        try {
            mService.injectHalError(errorCode, property, operation);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    public synchronized void startErrorListening() {
        try {
            mService.startErrorListening(mVehicleNetworkListener);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    public synchronized void stopErrorListening() {
        try {
            mService.stopErrorListening(mVehicleNetworkListener);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    public synchronized void startHalRestartMonitoring() {
        try {
            mService.startHalRestartMonitoring(mVehicleNetworkListener);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    public synchronized void stopHalRestartMonitoring() {
        try {
            mService.stopHalRestartMonitoring(mVehicleNetworkListener);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    private synchronized VehicleNetworkHalMock getHalMock() {
        return mHalMock;
    }

    private void handleRemoteException(RemoteException e) {
        throw new RuntimeException("Vehicle network service not working ", e);
    }

    private void handleVehicleNetworkEvents(VehiclePropValues values) {
        mListener.onVehicleNetworkEvents(values);
    }

    private void handleHalError(int errorCode, int property, int operation) {
        mListener.onHalError(errorCode, property, operation);
    }

    private void handleHalRestart(boolean inMocking) {
        mListener.onHalRestart(inMocking);
    }

    private void handleOnPropertySet(VehiclePropValue value) {
        mListener.onPropertySet(value);
    }

    private class EventHandler extends Handler {

        private static final int MSG_EVENTS = 0;
        private static final int MSG_HAL_ERROR = 1;
        private static final int MSG_HAL_RESTART = 2;
        private static final int MSG_ON_PROPERTY_SET = 3;

        private EventHandler(Looper looper) {
            super(looper);
        }

        private void notifyEvents(VehiclePropValues values) {
            Message msg = obtainMessage(MSG_EVENTS, values);
            sendMessage(msg);
        }

        private void notifyHalError(int errorCode, int property, int operation) {
            Message msg = obtainMessage(MSG_HAL_ERROR, errorCode, property, operation);
            sendMessage(msg);
        }

        private void notifyHalRestart(boolean inMocking) {
            Message msg = obtainMessage(MSG_HAL_RESTART, inMocking ? 1 : 0, 0);
            sendMessage(msg);
        }

        private void notifyPropertySet(VehiclePropValue value) {
            Message msg = obtainMessage(MSG_ON_PROPERTY_SET, value);
            sendMessage(msg);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_EVENTS:
                    handleVehicleNetworkEvents((VehiclePropValues) msg.obj);
                    break;
                case MSG_HAL_ERROR:
                    handleHalError(msg.arg1, msg.arg2, (Integer) msg.obj);
                    break;
                case MSG_HAL_RESTART:
                    handleHalRestart(msg.arg1 == 1);
                    break;
                case MSG_ON_PROPERTY_SET:
                    handleOnPropertySet((VehiclePropValue) msg.obj);
                default:
                    Log.w(TAG, "Unknown message:" + msg.what, new RuntimeException());
                    break;
            }
        }
    }

    private static class IVehicleNetworkListenerImpl extends IVehicleNetworkListener.Stub {

        private final WeakReference<VehicleNetwork> mVehicleNetwork;

        private IVehicleNetworkListenerImpl(VehicleNetwork vehicleNetwork) {
            mVehicleNetwork = new WeakReference<>(vehicleNetwork);
        }

        @Override
        public void onVehicleNetworkEvents(VehiclePropValuesParcelable values) {
            VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
            if (vehicleNetwork != null) {
                vehicleNetwork.mEventHandler.notifyEvents(values.values);
            }
        }

        @Override
        public void onPropertySet(VehiclePropValueParcelable value) {
            VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
            if (vehicleNetwork != null) {
                vehicleNetwork.mEventHandler.notifyPropertySet(value.value);
            }
        }

        @Override
        public void onHalError(int errorCode, int property, int operation) {
            VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
            if (vehicleNetwork != null) {
                vehicleNetwork.mEventHandler.notifyHalError(errorCode, property, operation);
            }
        }

        @Override
        public void onHalRestart(boolean inMocking) {
            VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
            if (vehicleNetwork != null) {
                vehicleNetwork.mEventHandler.notifyHalRestart(inMocking);
            }
        }
    }

    private static class IVehicleNetworkHalMockImpl extends IVehicleNetworkHalMock.Stub {
        private final WeakReference<VehicleNetwork> mVehicleNetwork;

        private IVehicleNetworkHalMockImpl(VehicleNetwork vehicleNewotk) {
            mVehicleNetwork = new WeakReference<>(vehicleNewotk);
        }

        @Override
        public VehiclePropConfigsParcelable onListProperties() {
            VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
            if (vehicleNetwork == null) {
                return null;
            }
            VehiclePropConfigs configs = vehicleNetwork.getHalMock().onListProperties();
            return new VehiclePropConfigsParcelable(configs);
        }

        @Override
        public void onPropertySet(VehiclePropValueParcelable value) {
            VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
            if (vehicleNetwork == null) {
                return;
            }
            vehicleNetwork.getHalMock().onPropertySet(value.value);
        }

        @Override
        public VehiclePropValueParcelable onPropertyGet(VehiclePropValueParcelable value) {
            VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
            if (vehicleNetwork == null) {
                return null;
            }
            VehiclePropValue resValue = vehicleNetwork.getHalMock().onPropertyGet(value.value);
            return new VehiclePropValueParcelable(resValue);
        }

        @Override
        public void onPropertySubscribe(int property, float sampleRate, int zones) {
            VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
            if (vehicleNetwork == null) {
                return;
            }
            vehicleNetwork.getHalMock().onPropertySubscribe(property, sampleRate, zones);
        }

        @Override
        public void onPropertyUnsubscribe(int property) {
            VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
            if (vehicleNetwork == null) {
                return;
            }
            vehicleNetwork.getHalMock().onPropertyUnsubscribe(property);
        }
    }

    private VehiclePropValue getProperty(int property, int zone, int customPropetyDataType) {
        boolean isCustom = isCustomProperty(property);
        int valueType = isCustom
                ? customPropetyDataType
                : VehicleNetworkConsts.getVehicleValueType(property);

        VehiclePropValue.Builder valuePrototypeBuilder =
                VehiclePropValueUtil.createBuilder(property, valueType, 0);

        if (zone != NO_ZONE) {
            valuePrototypeBuilder.setZone(zone);
        }

        VehiclePropValue v = getProperty(valuePrototypeBuilder.build());
        if (v == null) {
            // if property is invalid, IllegalArgumentException should have been thrown
            // from getProperty.
            throw new IllegalStateException();
        }

        if (!isCustom && v.getValueType() != valueType) {
            throw new IllegalArgumentException(
                    "Unexpected type for property 0x" + Integer.toHexString(property) +
                    " got:0x" + Integer.toHexString(v.getValueType())
                    + ", expecting:0x" + Integer.toHexString(valueType));
        }
        return v;
    }

    private void assertVectorLength(int actual, int property, int valueType) {
        int expectedLen = getVectorLength(valueType);
        if (expectedLen != actual) {
            throw new IllegalStateException("Invalid array size for property: " + property
                    + ". Expected: " + expectedLen
                    + ", actual: " + actual);
        }
    }
}
