/*
 * 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.libtest;

import android.os.HandlerThread;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;

import com.android.car.vehiclenetwork.VehicleNetwork;
import com.android.car.vehiclenetwork.VehicleNetwork.SubscribeFlags;
import com.android.car.vehiclenetwork.VehicleNetwork.VehicleNetworkHalMock;
import com.android.car.vehiclenetwork.VehicleNetwork.VehicleNetworkListener;
import com.android.car.vehiclenetwork.VehicleNetworkConsts;
import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropAccess;
import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropChangeMode;
import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType;
import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleZone;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfig;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfigs;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValues;
import com.android.car.vehiclenetwork.VehiclePropConfigUtil;
import com.android.car.vehiclenetwork.VehiclePropValueUtil;

import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

@MediumTest
public class VehicleNetworkMockedTest extends AndroidTestCase {
    private static final String TAG = VehicleNetworkMockedTest.class.getSimpleName();

    private static final long TIMEOUT_MS = 1000;

    private static final int CUSTOM_PROPERTY_INT32 =
            VehicleNetworkConsts.VEHICLE_PROPERTY_CUSTOM_START;
    private static final int CUSTOM_PROPERTY_ZONED_INT32 =
            VehicleNetworkConsts.VEHICLE_PROPERTY_CUSTOM_START + 1;
    private static final int CUSTOM_PROPERTY_ZONED_INT32_VEC2 =
            VehicleNetworkConsts.VEHICLE_PROPERTY_CUSTOM_START + 2;
    private static final int CUSTOM_PROPERTY_ZONED_INT32_VEC3 =
            VehicleNetworkConsts.VEHICLE_PROPERTY_CUSTOM_START + 3;
    private static final int CUSTOM_PROPERTY_ZONED_FLOAT_VEC2 =
            VehicleNetworkConsts.VEHICLE_PROPERTY_CUSTOM_START + 4;
    private static final int CUSTOM_PROPERTY_ZONED_FLOAT_VEC3 =
            VehicleNetworkConsts.VEHICLE_PROPERTY_CUSTOM_START + 5;
    private static final int CUSTOM_PROPERTY_FLOAT_VEC2 =
            VehicleNetworkConsts.VEHICLE_PROPERTY_CUSTOM_START + 6;
    private static final int CUSTOM_PROPERTY_INT32_VEC2 =
            VehicleNetworkConsts.VEHICLE_PROPERTY_CUSTOM_START + 7;

    private final HandlerThread mHandlerThread = new HandlerThread(
            VehicleNetworkTest.class.getSimpleName());
    private VehicleNetwork mVehicleNetwork;
    private EventListener mListener = new EventListener();
    private final VehicleHalMock mVehicleHalMock = new VehicleHalMock();

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mHandlerThread.start();
        mVehicleNetwork = VehicleNetwork.createVehicleNetwork(mListener,
                mHandlerThread.getLooper());
        mVehicleHalMock.registerProperty(
                VehiclePropConfigUtil.createProperty(
                        CUSTOM_PROPERTY_INT32,
                        VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
                        VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
                        VehicleValueType.VEHICLE_VALUE_TYPE_INT32, 0x0),
                new DefaultVehiclePropertyHandler(VehiclePropValueUtil.createIntValue(
                        CUSTOM_PROPERTY_INT32, 0, 0)));
        mVehicleHalMock.registerProperty(
                VehiclePropConfigUtil.createProperty(
                        CUSTOM_PROPERTY_ZONED_INT32,
                        VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
                        VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
                        VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32, 0x0),
                new DefaultVehiclePropertyHandler(VehiclePropValueUtil.createZonedIntValue(
                        CUSTOM_PROPERTY_ZONED_INT32, VehicleZone.VEHICLE_ZONE_ROW_2_LEFT, 0, 0)));
        mVehicleHalMock.registerProperty(
                VehiclePropConfigUtil.createProperty(
                        CUSTOM_PROPERTY_ZONED_INT32_VEC2,
                        VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
                        VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
                        VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2, 0x0),
                new DefaultVehiclePropertyHandler(VehiclePropValueUtil.createZonedIntVectorValue(
                        CUSTOM_PROPERTY_ZONED_INT32_VEC2,
                        VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
                        new int[2], 0)));
        mVehicleHalMock.registerProperty(
                VehiclePropConfigUtil.createProperty(
                        CUSTOM_PROPERTY_INT32_VEC2,
                        VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
                        VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
                        VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2, 0x0),
                new DefaultVehiclePropertyHandler(VehiclePropValueUtil.createIntVectorValue(
                        CUSTOM_PROPERTY_INT32_VEC2, new int[2], 0)));
        mVehicleHalMock.registerProperty(
                VehiclePropConfigUtil.createZonedProperty(
                        CUSTOM_PROPERTY_ZONED_INT32_VEC3,
                        VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
                        VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
                        VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3,
                        VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
                        0x0),
                new DefaultVehiclePropertyHandler(VehiclePropValueUtil.createZonedIntVectorValue(
                        CUSTOM_PROPERTY_ZONED_INT32_VEC3,
                        VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
                        new int[3], 0)));
        mVehicleHalMock.registerProperty(
                VehiclePropConfigUtil.createZonedProperty(
                        CUSTOM_PROPERTY_ZONED_FLOAT_VEC2,
                        VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
                        VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
                        VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2,
                        VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
                        0x0),
                new DefaultVehiclePropertyHandler(VehiclePropValueUtil.createZonedFloatVectorValue(
                        CUSTOM_PROPERTY_ZONED_FLOAT_VEC2,
                        VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
                        new float[2], 0)));
        mVehicleHalMock.registerProperty(
                VehiclePropConfigUtil.createProperty(
                        CUSTOM_PROPERTY_FLOAT_VEC2,
                        VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
                        VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
                        VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC2, 0x0),
                new DefaultVehiclePropertyHandler(VehiclePropValueUtil.createFloatVectorValue(
                        CUSTOM_PROPERTY_FLOAT_VEC2, new float[2], 0)));
        mVehicleHalMock.registerProperty(
                VehiclePropConfigUtil.createZonedProperty(
                        CUSTOM_PROPERTY_ZONED_FLOAT_VEC3,
                        VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
                        VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
                        VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3,
                        VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
                        0x0),
                new DefaultVehiclePropertyHandler(VehiclePropValueUtil.createZonedFloatVectorValue(
                        CUSTOM_PROPERTY_ZONED_FLOAT_VEC3,
                        VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
                        new float[3], 0)));
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
        mHandlerThread.quit();
        mVehicleNetwork.stopMocking();
    }

    public void testHalRestartListening() throws Exception {
        mVehicleNetwork.startHalRestartMonitoring();
        mVehicleNetwork.startMocking(mVehicleHalMock);
        assertTrue(mListener.waitForHalRestartAndAssert(TIMEOUT_MS, true /*expectedInMocking*/));
        mVehicleNetwork.stopMocking();
        assertTrue(mListener.waitForHalRestartAndAssert(TIMEOUT_MS, false /*expectedInMocking*/));
        mVehicleNetwork.stopHalRestartMonitoring();
    }

    public void testCustomZonedIntProperties() {
        final int INT_VALUE = 10;
        final int INT_VALUE2 = 20;

        mVehicleNetwork.startMocking(mVehicleHalMock);

        mVehicleNetwork.setIntProperty(CUSTOM_PROPERTY_INT32, INT_VALUE);
        assertEquals(INT_VALUE, mVehicleNetwork.getIntProperty(CUSTOM_PROPERTY_INT32));

        mVehicleNetwork.setZonedIntProperty(CUSTOM_PROPERTY_ZONED_INT32,
                VehicleZone.VEHICLE_ZONE_ROW_2_LEFT, INT_VALUE);
        mVehicleNetwork.setZonedIntProperty(CUSTOM_PROPERTY_ZONED_INT32,
                VehicleZone.VEHICLE_ZONE_ROW_2_RIGHT, INT_VALUE2);

        assertEquals(INT_VALUE,
                mVehicleNetwork.getZonedIntProperty(CUSTOM_PROPERTY_ZONED_INT32,
                        VehicleZone.VEHICLE_ZONE_ROW_2_LEFT));
        assertEquals(INT_VALUE2,
                mVehicleNetwork.getZonedIntProperty(CUSTOM_PROPERTY_ZONED_INT32,
                        VehicleZone.VEHICLE_ZONE_ROW_2_RIGHT));
        assertEquals(INT_VALUE,
                mVehicleNetwork.getZonedIntProperty(CUSTOM_PROPERTY_ZONED_INT32,
                        VehicleZone.VEHICLE_ZONE_ROW_2_LEFT));
    }

    public void testCustomZonedIntVecProperties() {
        final int[] ZONED_INT_VALUE_LEFT = new int[] {30, 40};
        final int[] ZONED_INT_VALUE_RIGHT = new int[] {50, 60};
        final int[] ZONED_INT_VALUE_VEC3 = new int[] {30, 40, 50};

        mVehicleNetwork.startMocking(mVehicleHalMock);

        int[] actualValue = mVehicleNetwork.getZonedIntVectorProperty(
                CUSTOM_PROPERTY_ZONED_INT32_VEC2,
                VehicleZone.VEHICLE_ZONE_ROW_1_LEFT);
        // Verify the default values before calling setProperty.
        assertArrayEquals(new int[2], actualValue);
        mVehicleNetwork.setZonedIntVectorProperty(CUSTOM_PROPERTY_ZONED_INT32_VEC2,
                VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
                ZONED_INT_VALUE_LEFT);
        actualValue = mVehicleNetwork.getZonedIntVectorProperty(
                CUSTOM_PROPERTY_ZONED_INT32_VEC2,
                VehicleZone.VEHICLE_ZONE_ROW_1_LEFT);
        assertArrayEquals(ZONED_INT_VALUE_LEFT, actualValue);

        // Verify different zone for the same property
        mVehicleNetwork.setZonedIntVectorProperty(CUSTOM_PROPERTY_ZONED_INT32_VEC2,
                VehicleZone.VEHICLE_ZONE_ROW_1_RIGHT,
                ZONED_INT_VALUE_RIGHT);
        actualValue = mVehicleNetwork.getZonedIntVectorProperty(
                CUSTOM_PROPERTY_ZONED_INT32_VEC2,
                VehicleZone.VEHICLE_ZONE_ROW_1_RIGHT);
        assertArrayEquals(ZONED_INT_VALUE_RIGHT, actualValue);

        mVehicleNetwork.setZonedIntVectorProperty(CUSTOM_PROPERTY_ZONED_INT32_VEC3,
                VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
                ZONED_INT_VALUE_VEC3);
        actualValue = mVehicleNetwork.getZonedIntVectorProperty(
                CUSTOM_PROPERTY_ZONED_INT32_VEC3,
                VehicleZone.VEHICLE_ZONE_ROW_1_LEFT);
        assertArrayEquals(ZONED_INT_VALUE_VEC3, actualValue);
    }

    public void testCustomZonedFloatVecProperties() {
        final float[] ZONED_FLOAT_VALUE_LEFT = new float[] {30.1f, 40.3f};
        final float[] ZONED_FLOAT_VALUE_RIGHT = new float[] {50.5f, 60};
        final float[] ZONED_FLOAT_VALUE_VEC3 = new float[] {30, 40.3f, 50};

        mVehicleNetwork.startMocking(mVehicleHalMock);

        float[] actualValue = mVehicleNetwork.getZonedFloatVectorProperty(
                CUSTOM_PROPERTY_ZONED_FLOAT_VEC2,
                VehicleZone.VEHICLE_ZONE_ROW_1_LEFT);
        // Verify the default values before calling setProperty.
        assertArrayEquals(new float[2], actualValue);
        mVehicleNetwork.setZonedFloatVectorProperty(CUSTOM_PROPERTY_ZONED_FLOAT_VEC2,
                VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
                ZONED_FLOAT_VALUE_LEFT);
        actualValue = mVehicleNetwork.getZonedFloatVectorProperty(
                CUSTOM_PROPERTY_ZONED_FLOAT_VEC2,
                VehicleZone.VEHICLE_ZONE_ROW_1_LEFT);
        assertArrayEquals(ZONED_FLOAT_VALUE_LEFT, actualValue);

        // Verify different zone for the same property
        mVehicleNetwork.setZonedFloatVectorProperty(CUSTOM_PROPERTY_ZONED_FLOAT_VEC2,
                VehicleZone.VEHICLE_ZONE_ROW_1_RIGHT,
                ZONED_FLOAT_VALUE_RIGHT);
        actualValue = mVehicleNetwork.getZonedFloatVectorProperty(
                CUSTOM_PROPERTY_ZONED_FLOAT_VEC2,
                VehicleZone.VEHICLE_ZONE_ROW_1_RIGHT);
        assertArrayEquals(ZONED_FLOAT_VALUE_RIGHT, actualValue);

        mVehicleNetwork.setZonedFloatVectorProperty(CUSTOM_PROPERTY_ZONED_FLOAT_VEC3,
                VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
                ZONED_FLOAT_VALUE_VEC3);
        actualValue = mVehicleNetwork.getZonedFloatVectorProperty(
                CUSTOM_PROPERTY_ZONED_FLOAT_VEC3,
                VehicleZone.VEHICLE_ZONE_ROW_1_LEFT);
        assertArrayEquals(ZONED_FLOAT_VALUE_VEC3, actualValue);
    }

    public void testCustomFloatVecProperties() {
        final float[] FLOAT_VALUE = new float[] {30.1f, 40.3f};

        mVehicleNetwork.startMocking(mVehicleHalMock);

        float[] actualValue = mVehicleNetwork.getFloatVectorProperty(
                CUSTOM_PROPERTY_FLOAT_VEC2);
        // Verify the default values before calling setProperty.
        assertArrayEquals(new float[2], actualValue);
        mVehicleNetwork.setFloatVectorProperty(CUSTOM_PROPERTY_FLOAT_VEC2, FLOAT_VALUE);
        actualValue = mVehicleNetwork.getFloatVectorProperty(
                CUSTOM_PROPERTY_FLOAT_VEC2);
        assertArrayEquals(FLOAT_VALUE, actualValue);
    }

    public void testCustomIntVecProperties() {
        final int[] INT32_VALUE = new int[] {30, 40};

        mVehicleNetwork.startMocking(mVehicleHalMock);

        int[] actualValue = mVehicleNetwork.getIntVectorProperty(
                CUSTOM_PROPERTY_INT32_VEC2);
        // Verify the default values before calling setProperty.
        assertArrayEquals(new int[2], actualValue);
        mVehicleNetwork.setIntVectorProperty(CUSTOM_PROPERTY_INT32_VEC2, INT32_VALUE);
        actualValue = mVehicleNetwork.getIntVectorProperty(
                CUSTOM_PROPERTY_INT32_VEC2);
        assertArrayEquals(INT32_VALUE, actualValue);
    }

    public void testGlobalErrorListening() throws Exception {
        mVehicleNetwork.startErrorListening();
        mVehicleNetwork.startMocking(mVehicleHalMock);
        final int ERROR_CODE = 0x1;
        final int ERROR_OPERATION = 0x10;
        mVehicleNetwork.injectHalError(ERROR_CODE, 0, ERROR_OPERATION);
        assertTrue(mListener.waitForHalErrorAndAssert(TIMEOUT_MS, ERROR_CODE, 0, ERROR_OPERATION));
        mVehicleNetwork.injectHalError(ERROR_CODE, CUSTOM_PROPERTY_INT32, ERROR_OPERATION);
        assertTrue(mListener.waitForHalErrorAndAssert(TIMEOUT_MS,
                ERROR_CODE, CUSTOM_PROPERTY_INT32, ERROR_OPERATION));
        mVehicleNetwork.stopMocking();
        mVehicleNetwork.stopErrorListening();
    }

    public void testPropertyErrorListening() throws Exception {
        mVehicleNetwork.startMocking(mVehicleHalMock);
        mVehicleNetwork.subscribe(CUSTOM_PROPERTY_INT32, 0);
        final int ERROR_CODE = 0x1;
        final int ERROR_OPERATION = 0x10;
        mVehicleNetwork.injectHalError(ERROR_CODE, CUSTOM_PROPERTY_INT32, ERROR_OPERATION);
        assertTrue(mListener.waitForHalErrorAndAssert(TIMEOUT_MS,
                ERROR_CODE, CUSTOM_PROPERTY_INT32, ERROR_OPERATION));
        mVehicleNetwork.unsubscribe(CUSTOM_PROPERTY_INT32);
        mVehicleNetwork.stopMocking();
    }

    public void testSubscribe() throws Exception {
        final int PROPERTY = CUSTOM_PROPERTY_ZONED_INT32_VEC3;
        final int ZONE = VehicleZone.VEHICLE_ZONE_ROW_1_LEFT;
        final int[] VALUES = new int[] {10, 20, 30};
        mVehicleNetwork.startMocking(mVehicleHalMock);
        mVehicleNetwork.subscribe(PROPERTY, 0, ZONE);
        VehiclePropValue value = VehiclePropValueUtil.createZonedIntVectorValue(
                PROPERTY, ZONE, VALUES, 0);
        mVehicleNetwork.injectEvent(value);
        assertTrue(mListener.waitForEvent(TIMEOUT_MS, value));
        mVehicleNetwork.unsubscribe(PROPERTY);
    }

    public void testSubscribe_OnPropertySet() throws Exception {
        final int PROPERTY = CUSTOM_PROPERTY_ZONED_INT32_VEC3;
        final int ZONE = VehicleZone.VEHICLE_ZONE_ROW_1_LEFT;
        final int[] VALUES = new int[] {10, 20, 30};
        mVehicleNetwork.startMocking(mVehicleHalMock);
        mVehicleNetwork.subscribe(PROPERTY, 0, ZONE, SubscribeFlags.SET_CALL);

        mVehicleNetwork.setZonedIntVectorProperty(PROPERTY, ZONE, VALUES);

        VehiclePropValue expectedValue = VehiclePropValueUtil.createZonedIntVectorValue(
                PROPERTY, ZONE, VALUES, 0);

        assertTrue(mListener.waitForOnPropertySet(TIMEOUT_MS, expectedValue));

        mVehicleNetwork.injectEvent(expectedValue);
        // Not subscribed to HAL events. No notifications expected here.
        assertFalse(mListener.waitForEvent(TIMEOUT_MS, expectedValue));

        mVehicleNetwork.unsubscribe(PROPERTY);
    }

    public void testSubscribe_HalEventAndOnPropertySet() throws Exception {
        final int PROPERTY = CUSTOM_PROPERTY_ZONED_INT32_VEC3;
        final int ZONE = VehicleZone.VEHICLE_ZONE_ROW_1_LEFT;
        final int[] VALUES = new int[] {10, 20, 30};
        mVehicleNetwork.startMocking(mVehicleHalMock);
        mVehicleNetwork.subscribe(PROPERTY, 0, ZONE,
                SubscribeFlags.SET_CALL | SubscribeFlags.HAL_EVENT);

        mVehicleNetwork.setZonedIntVectorProperty(PROPERTY, ZONE, VALUES);

        VehiclePropValue expectedValue = VehiclePropValueUtil.createZonedIntVectorValue(
                PROPERTY, ZONE, VALUES, 0);

        assertTrue(mListener.waitForOnPropertySet(TIMEOUT_MS, expectedValue));

        mVehicleNetwork.injectEvent(expectedValue);
        assertTrue(mListener.waitForEvent(TIMEOUT_MS, expectedValue));

        mVehicleNetwork.unsubscribe(PROPERTY);
    }

    public void testGetPropertyFailsForCustom() {
        try {
            mVehicleNetwork.getProperty(CUSTOM_PROPERTY_INT32);
            fail();
        } catch (IllegalArgumentException expected) {
            // Expected.
        }
    }

    private void assertArrayEquals(int[] expected, int[] actual) {
        assertEquals(Arrays.toString(expected), Arrays.toString(actual));
    }

    private void assertArrayEquals(float[] expected, float[] actual) {
        assertEquals(Arrays.toString(expected), Arrays.toString(actual));
    }

    private class EventListener implements VehicleNetworkListener {
        boolean mInMocking;
        int mErrorCode;
        int mErrorProperty;
        int mErrorOperation;
        VehiclePropValues mValuesReceived;
        VehiclePropValue mPropertySetValue;

        private final Semaphore mRestartWait = new Semaphore(0);
        private final Semaphore mErrorWait = new Semaphore(0);
        private final Semaphore mEventWait = new Semaphore(0);
        private final Semaphore mOnPropertySetWait = new Semaphore(0);

        @Override
        public void onVehicleNetworkEvents(VehiclePropValues values) {
            Log.i(TAG, "onVehicleNetworkEvents");
            mValuesReceived = values;
            mEventWait.release();
        }

        @Override
        public void onHalError(int errorCode, int property, int operation) {
            mErrorCode = errorCode;
            mErrorProperty = property;
            mErrorOperation = operation;
            mErrorWait.release();
        }

        public boolean waitForHalErrorAndAssert(long timeoutMs, int expectedErrorCode,
                int expectedErrorProperty, int expectedErrorOperation) throws Exception {
            if (!mErrorWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
                return false;
            }
            assertEquals(expectedErrorCode, mErrorCode);
            assertEquals(expectedErrorProperty, mErrorProperty);
            assertEquals(expectedErrorOperation, mErrorOperation);
            return true;
        }

        @Override
        public void onHalRestart(boolean inMocking) {
            mInMocking = inMocking;
            mRestartWait.release();
        }

        @Override
        public void onPropertySet(VehiclePropValue value) {
            mPropertySetValue = value;
            mOnPropertySetWait.release();
        }

        public boolean waitForHalRestartAndAssert(long timeoutMs, boolean expectedInMocking)
                throws Exception {
            if (!mRestartWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
                return false;
            }
            assertEquals(expectedInMocking, mInMocking);
            return true;
        }

        public boolean waitForEvent(long timeoutMs, VehiclePropValue expected)
                throws InterruptedException {
            if (!mEventWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
                Log.w(TAG, "Timed out waiting for event.");
                return false;
            }
            assertEquals(1, mValuesReceived.getValuesCount());
            assertEquals(VehiclePropValueUtil.toString(expected),
                    VehiclePropValueUtil.toString(mValuesReceived.getValues(0)));
            return true;
        }

        public boolean waitForOnPropertySet(long timeoutMs, VehiclePropValue expected)
                throws InterruptedException {
            if (!mOnPropertySetWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
                Log.w(TAG, "Timed out waiting for onPropertySet.");
                return false;
            }
            assertEquals(VehiclePropValueUtil.toString(expected),
                    VehiclePropValueUtil.toString(mPropertySetValue));
            return true;
        }
    }

    private interface VehiclePropertyHandler {
        void onPropertySet(VehiclePropValue value);
        VehiclePropValue onPropertyGet(VehiclePropValue property);
        void onPropertySubscribe(int property, float sampleRate, int zones);
        void onPropertyUnsubscribe(int property);
    }

    private class VehicleHalMock implements VehicleNetworkHalMock {
        private LinkedList<VehiclePropConfig> mConfigs = new LinkedList<>();
        private HashMap<Integer, VehiclePropertyHandler> mHandlers = new HashMap<>();

        public synchronized void registerProperty(VehiclePropConfig config,
                VehiclePropertyHandler handler) {
            int property = config.getProp();
            mConfigs.add(config);
            mHandlers.put(property, handler);
        }

        @Override
        public synchronized VehiclePropConfigs onListProperties() {
            Log.i(TAG, "onListProperties, num properties:" + mConfigs.size());
            VehiclePropConfigs configs =
                    VehiclePropConfigs.newBuilder().addAllConfigs(mConfigs).build();
            return configs;
        }

        @Override
        public void onPropertySet(VehiclePropValue value) {
            int property = value.getProp();
            VehiclePropertyHandler handler = getPropertyHandler(property);
            if (handler == null) {
                fail("onPropertySet for unknown property " + Integer.toHexString(property));
            }
            handler.onPropertySet(value);
        }

        @Override
        public VehiclePropValue onPropertyGet(VehiclePropValue value) {
            int property = value.getProp();
            VehiclePropertyHandler handler = getPropertyHandler(property);
            if (handler == null) {
                fail("onPropertyGet for unknown property " + Integer.toHexString(property));
            }
            VehiclePropValue propValue = handler.onPropertyGet(value);
            return propValue;
        }

        @Override
        public void onPropertySubscribe(int property, float sampleRate, int zones) {
            VehiclePropertyHandler handler = getPropertyHandler(property);
            if (handler == null) {
                fail("onPropertySubscribe for unknown property " + Integer.toHexString(property));
            }
            handler.onPropertySubscribe(property, sampleRate, zones);
        }

        @Override
        public void onPropertyUnsubscribe(int property) {
            VehiclePropertyHandler handler = getPropertyHandler(property);
            if (handler == null) {
                fail("onPropertyUnsubscribe for unknown property " + Integer.toHexString(property));
            }
            handler.onPropertyUnsubscribe(property);
        }

        public synchronized VehiclePropertyHandler getPropertyHandler(int property) {
            return mHandlers.get(property);
        }
    }

    private class DefaultVehiclePropertyHandler implements VehiclePropertyHandler {
        private Map<Integer, VehiclePropValue> mZoneValueMap = new HashMap<>();

        DefaultVehiclePropertyHandler(VehiclePropValue initialValue) {
            setValue(initialValue);
        }

        @Override
        public void onPropertySet(VehiclePropValue value) {
            setValue(value);
        }

        @Override
        public synchronized VehiclePropValue onPropertyGet(VehiclePropValue property) {
            int zone = property.getZone();
            VehiclePropValue value = mZoneValueMap.get(zone);
            if (value == null) {
                Log.w(TAG, "Property not found: " + property.getProp() + ", zone: " + zone);
            }
            return value;
        }

        @Override
        public void onPropertySubscribe(int property, float sampleRate, int zones) {
            Log.i(TAG, "Property subscribed:0x" + Integer.toHexString(property) +
                    " zones:0x" + Integer.toHexString(zones));
        }

        @Override
        public void onPropertyUnsubscribe(int property) {
            // TODO Auto-generated method stub
        }

        private void setValue(VehiclePropValue value) {
            mZoneValueMap.put(value.getZone(), VehiclePropValue.newBuilder(value).build());
        }
    }
}
