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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import android.car.Car;
import android.car.hardware.CarSensorEvent;
import android.car.hardware.CarSensorManager;
import android.hardware.automotive.vehicle.V2_0.VehicleGear;
import android.hardware.automotive.vehicle.V2_0.VehicleIgnitionState;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.os.SystemClock;
import android.util.Log;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.MediumTest;

import com.android.car.vehiclehal.VehiclePropValueBuilder;

import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * Test the public entry points for the CarSensorManager
 */
@RunWith(AndroidJUnit4.class)
@MediumTest
public class CarSensorManagerTest extends MockedCarTestBase {
    private static final String TAG = CarSensorManagerTest.class.getSimpleName();

    private CarSensorManager mCarSensorManager;

    @Override
    protected synchronized void configureMockedHal() {
        addProperty(VehicleProperty.NIGHT_MODE,
                VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE)
                        .addIntValue(0)
                        .build());
        addProperty(VehicleProperty.PERF_VEHICLE_SPEED,
                VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED)
                        .addFloatValue(0f)
                        .build());
        addProperty(VehicleProperty.FUEL_LEVEL,
                VehiclePropValueBuilder.newBuilder(VehicleProperty.FUEL_LEVEL)
                        .addFloatValue(20000)  // ml
                        .build());
        addProperty(VehicleProperty.PARKING_BRAKE_ON,
                VehiclePropValueBuilder.newBuilder(VehicleProperty.PARKING_BRAKE_ON)
                        .setBooleanValue(true)
                        .build());
        addProperty(VehicleProperty.CURRENT_GEAR,
                VehiclePropValueBuilder.newBuilder(VehicleProperty.CURRENT_GEAR)
                        .addIntValue(0)
                        .build());
        addProperty(VehicleProperty.GEAR_SELECTION,
                VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION)
                        .addIntValue(0)
                        .build());
        addProperty(VehicleProperty.IGNITION_STATE,
                VehiclePropValueBuilder.newBuilder(VehicleProperty.IGNITION_STATE)
                        .addIntValue(CarSensorEvent.IGNITION_STATE_ACC)
                        .build());
    }

    @Override
    public void setUp() throws Exception {
        super.setUp();
        // Start the HAL layer and set up the sensor manager service
        mCarSensorManager = (CarSensorManager) getCar().getCarManager(Car.SENSOR_SERVICE);
    }

    /**
     * Test single sensor availability entry point
     * @throws Exception
     */
    @Test
    public void testSensorAvailability() throws Exception {
        // NOTE:  Update this test if/when the reserved values put into use.  For now, we
        //        expect them to never be supported.
        assertFalse(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_RESERVED1));
        assertFalse(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_RESERVED13));
        assertFalse(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_RESERVED21));

        // We expect these sensors to always be available
        assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_CAR_SPEED));
        assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_FUEL_LEVEL));
        assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_PARKING_BRAKE));
        assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_GEAR));
        assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_NIGHT));
        assertTrue(mCarSensorManager.isSensorSupported(
                CarSensorManager.SENSOR_TYPE_IGNITION_STATE));
    }

    /**
     * Test sensor enumeration entry point
     * @throws Exception
     */
    @Test
    public void testSensorEnumeration() throws Exception {
        int[] supportedSensors = mCarSensorManager.getSupportedSensors();
        assertNotNull(supportedSensors);

        Log.i(TAG, "Found " + supportedSensors.length + " supported sensors.");

        // Unfortunately, we don't have a definitive range for legal sensor values,
        // so we have set a "reasonable" range here.  The ending value, in particular,
        // will need to be updated if/when new sensor types are allowed.
        // Here we are ensuring that all the enumerated sensors also return supported.
        for (int candidate = 0; candidate <= CarSensorManager.SENSOR_TYPE_RESERVED21; ++candidate) {
            boolean supported = mCarSensorManager.isSensorSupported(candidate);
            boolean found = false;
            for (int sensor : supportedSensors) {
                if (candidate == sensor) {
                    found = true;
                    Log.i(TAG, "Sensor type " + sensor + " is supported.");
                    break;
                }
            }

            // Make sure the individual query on a sensor type is consistent
            assertEquals(found, supported);
        }
    }

    /**
     * Test sensor notification registration, delivery, and unregistration
     * @throws Exception
     */
    @Test
    public void testEvents() throws Exception {
        // Set up our listener callback
        SensorListener listener = new SensorListener();
        mCarSensorManager.registerListener(listener,
                CarSensorManager.SENSOR_TYPE_PARKING_BRAKE,
                CarSensorManager.SENSOR_RATE_FASTEST);

        VehiclePropValue value;
        CarSensorEvent event;
        CarSensorEvent.ParkingBrakeData data = null;

        // Clear event generated by registerCallback()
        listener.waitForSensorChange();
        listener.reset();

        // Set the value TRUE and wait for the event to arrive
        getMockedVehicleHal().injectEvent(
                VehiclePropValueBuilder.newBuilder(VehicleProperty.PARKING_BRAKE_ON)
                        .setBooleanValue(true)
                        .setTimestamp(51L)
                        .build(), true);
        assertTrue(listener.waitForSensorChange(51L));

        // Ensure we got the expected event
        assertEquals(listener.getLastEvent().sensorType,
                CarSensorManager.SENSOR_TYPE_PARKING_BRAKE);

        // Ensure we got the expected value in our callback
        data = listener.getLastEvent().getParkingBrakeData(data);
        Log.d(TAG, "Parking: " + data.isEngaged + " at " + data.timestamp);
        assertTrue(data.isEngaged);

        // Ensure we have the expected value in the sensor manager's cache
        event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_PARKING_BRAKE);
        assertNotNull(event);
        data = event.getParkingBrakeData(data);
        assertEquals("Unexpected event timestamp", data.timestamp, 51);
        assertTrue("Unexpected value", data.isEngaged);

        listener.reset();
        // Set the value FALSE
        getMockedVehicleHal().injectEvent(
                VehiclePropValueBuilder.newBuilder(VehicleProperty.PARKING_BRAKE_ON)
                        .setTimestamp(1001)
                        .setBooleanValue(false)
                        .build(), true);
        assertTrue(listener.waitForSensorChange(1001));

        // Ensure we got the expected event
        assertEquals(listener.getLastEvent().sensorType,
                CarSensorManager.SENSOR_TYPE_PARKING_BRAKE);

        // Ensure we got the expected value in our callback
        data = listener.getLastEvent().getParkingBrakeData(data);
        assertEquals("Unexpected event timestamp", 1001, data.timestamp);
        assertFalse("Unexpected value", data.isEngaged);

        // Ensure we have the expected value in the sensor manager's cache
        event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_PARKING_BRAKE);
        assertNotNull(event);
        data = event.getParkingBrakeData(data);
        assertFalse(data.isEngaged);

        // Unregister our handler (from all sensor types)
        mCarSensorManager.unregisterListener(listener);

        listener.reset();
        // Set the value TRUE again
        value = VehiclePropValueBuilder.newBuilder(VehicleProperty.PARKING_BRAKE_ON)
                .setTimestamp(2001)
                .setBooleanValue(true)
                .build();
        getMockedVehicleHal().injectEvent(value, true);

        // Ensure we did not get a callback (should timeout)
        Log.i(TAG, "waiting for unexpected callback -- should timeout.");
        assertFalse(listener.waitForSensorChange(2001));

        // Despite us not having a callback registered, the Sensor Manager should see the update
        event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_PARKING_BRAKE);
        assertNotNull(event);
        data = event.getParkingBrakeData(data);
        assertEquals("Unexpected event timestamp", data.timestamp, 2001);
        assertTrue("Unexpected value", data.isEngaged);
    }

    @Test
    public void testIgnitionState() {
        CarSensorEvent event = mCarSensorManager.getLatestSensorEvent(
                CarSensorManager.SENSOR_TYPE_IGNITION_STATE);
        assertNotNull(event);
        assertEquals(CarSensorEvent.IGNITION_STATE_ACC, event.intValues[0]);
    }

    @Test
    public void testIgnitionEvents() throws Exception {
        SensorListener listener = new SensorListener();
        mCarSensorManager.registerListener(listener, CarSensorManager.SENSOR_TYPE_IGNITION_STATE,
                CarSensorManager.SENSOR_RATE_NORMAL);
        // Clear event generated by registerCallback()
        listener.waitForSensorChange();

        // Mapping of HAL -> Manager ignition states.
        int[] ignitionStates = new int[] {
                VehicleIgnitionState.UNDEFINED, CarSensorEvent.IGNITION_STATE_UNDEFINED,
                VehicleIgnitionState.LOCK, CarSensorEvent.IGNITION_STATE_LOCK,
                VehicleIgnitionState.OFF, CarSensorEvent.IGNITION_STATE_OFF,
                VehicleIgnitionState.ACC, CarSensorEvent.IGNITION_STATE_ACC,
                VehicleIgnitionState.ON, CarSensorEvent.IGNITION_STATE_ON,
                VehicleIgnitionState.START, CarSensorEvent.IGNITION_STATE_START,
                VehicleIgnitionState.ON, CarSensorEvent.IGNITION_STATE_ON,
                VehicleIgnitionState.LOCK, CarSensorEvent.IGNITION_STATE_LOCK,
        };

        for (int i = 0; i < ignitionStates.length; i += 2) {
            injectIgnitionStateAndAssert(listener, ignitionStates[i], ignitionStates[i + 1]);
        }
    }

    private void injectIgnitionStateAndAssert(SensorListener listener, int halIgnitionState,
            int mgrIgnitionState) throws Exception{
        listener.reset();
        long time = SystemClock.elapsedRealtimeNanos();
        getMockedVehicleHal().injectEvent(
                VehiclePropValueBuilder.newBuilder(VehicleProperty.IGNITION_STATE)
                        .addIntValue(halIgnitionState)
                        .setTimestamp(time)
                        .build(), true);
        assertTrue(listener.waitForSensorChange(time));

        CarSensorEvent eventReceived = listener.getLastEvent();
        assertEquals(CarSensorManager.SENSOR_TYPE_IGNITION_STATE, eventReceived.sensorType);
        assertEquals(mgrIgnitionState, eventReceived.intValues[0]);
    }

    @Test
    public void testGear() throws Exception {
        SensorListener listener = new SensorListener();

        mCarSensorManager.registerListener(listener, CarSensorManager.SENSOR_TYPE_GEAR,
                CarSensorManager.SENSOR_RATE_NORMAL);

        // Clear event generated by registerCallback()
        listener.waitForSensorChange();

        // Mapping of HAL -> Manager gear selection states.
        int[] gears = new int[] {
                VehicleGear.GEAR_PARK, CarSensorEvent.GEAR_PARK,
                VehicleGear.GEAR_DRIVE, CarSensorEvent.GEAR_DRIVE,
                VehicleGear.GEAR_NEUTRAL, CarSensorEvent.GEAR_NEUTRAL,
                VehicleGear.GEAR_REVERSE, CarSensorEvent.GEAR_REVERSE,
                VehicleGear.GEAR_1, CarSensorEvent.GEAR_FIRST,
                VehicleGear.GEAR_2, CarSensorEvent.GEAR_SECOND,
                VehicleGear.GEAR_3, CarSensorEvent.GEAR_THIRD,
                VehicleGear.GEAR_4, CarSensorEvent.GEAR_FOURTH,
                VehicleGear.GEAR_5, CarSensorEvent.GEAR_FIFTH,
                VehicleGear.GEAR_6, CarSensorEvent.GEAR_SIXTH,
                VehicleGear.GEAR_7, CarSensorEvent.GEAR_SEVENTH,
                VehicleGear.GEAR_8, CarSensorEvent.GEAR_EIGHTH,
                VehicleGear.GEAR_9, CarSensorEvent.GEAR_NINTH,
        };

        for (int i = 0; i < gears.length; i += 2) {
            injectGearEventAndAssert(listener, gears[i], gears[i + 1]);
        }
    }

    private void injectGearEventAndAssert(SensorListener listener, int halValue,
            int carSensorValue) throws Exception {
        listener.reset();
        long time = SystemClock.elapsedRealtimeNanos();
        getMockedVehicleHal().injectEvent(
                VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION)
                        .addIntValue(halValue)
                        .setTimestamp(time)
                        .build(), true);
        assertTrue(listener.waitForSensorChange(time));
        CarSensorEvent event = mCarSensorManager.getLatestSensorEvent(
                CarSensorManager.SENSOR_TYPE_GEAR);
        assertNotNull(event);
        assertEquals(carSensorValue, event.intValues[0]);
    }

    /**
     * Test sensor multiple liseners notification registration, delivery and unregistration.
     * @throws Exception
     */
    @Test
    public void testEventsWithMultipleListeners() throws Exception {
        // Set up our listeners callback
        SensorListener listener1 = new SensorListener();
        SensorListener listener2 = new SensorListener();
        SensorListener listener3 = new SensorListener();

        mCarSensorManager.registerListener(listener1,
                CarSensorManager.SENSOR_TYPE_NIGHT,
                CarSensorManager.SENSOR_RATE_NORMAL);

        mCarSensorManager.registerListener(listener2,
                CarSensorManager.SENSOR_TYPE_NIGHT,
                CarSensorManager.SENSOR_RATE_NORMAL);

        mCarSensorManager.registerListener(listener3,
                CarSensorManager.SENSOR_TYPE_NIGHT,
                CarSensorManager.SENSOR_RATE_FASTEST);

        CarSensorEvent.NightData data = null;
        VehiclePropValue value;
        CarSensorEvent event;

        // Clear event generated by registerCallback()
        listener1.waitForSensorChange();
        listener2.waitForSensorChange();
        listener3.waitForSensorChange();
        listener1.reset();
        listener2.reset();
        listener3.reset();

        // Set the value TRUE and wait for the event to arrive
        value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE)
                .setTimestamp(1001L)
                .setBooleanValue(true)
                .build();
        getMockedVehicleHal().injectEvent(value, true);

        assertTrue(listener1.waitForSensorChange(1001L));
        assertTrue(listener2.waitForSensorChange(1001L));
        assertTrue(listener3.waitForSensorChange(1001L));

        // Ensure we got the expected event
        assertEquals(listener1.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT);
        assertEquals(listener2.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT);
        assertEquals(listener3.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT);

        // Ensure we got the expected value in our callback
        data = listener1.getLastEvent().getNightData(data);
        Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp);
        assertTrue(data.isNightMode);

        data = listener2.getLastEvent().getNightData(data);
        Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp);
        assertTrue(data.isNightMode);

        data = listener3.getLastEvent().getNightData(data);
        Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp);
        assertTrue(data.isNightMode);

        // Ensure we have the expected value in the sensor manager's cache
        event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT);
        data = event.getNightData(data);
        assertEquals("Unexpected event timestamp", 1001, data.timestamp);
        assertTrue("Unexpected value", data.isNightMode);

        listener1.reset();
        listener2.reset();
        listener3.reset();
        // Set the value FALSE
        value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE)
                .setTimestamp(2001)
                .setBooleanValue(false)
                .build();
        getMockedVehicleHal().injectEvent(value, true);
        assertTrue(listener1.waitForSensorChange(2001));
        assertTrue(listener2.waitForSensorChange(2001));
        assertTrue(listener3.waitForSensorChange(2001));

        // Ensure we got the expected event
        assertEquals(listener1.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT);
        assertEquals(listener2.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT);
        assertEquals(listener3.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT);

        // Ensure we got the expected value in our callback
        data = listener1.getLastEvent().getNightData(data);
        assertEquals("Unexpected event timestamp", 2001, data.timestamp);
        assertFalse("Unexpected value", data.isNightMode);

        data = listener2.getLastEvent().getNightData(data);
        assertEquals("Unexpected event timestamp", 2001, data.timestamp);
        assertFalse("Unexpected value", data.isNightMode);

        data = listener3.getLastEvent().getNightData(data);
        assertEquals("Unexpected event timestamp", 2001, data.timestamp);
        assertFalse("Unexpected value", data.isNightMode);

        // Ensure we have the expected value in the sensor manager's cache
        event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT);
        data = event.getNightData(data);
        assertFalse(data.isNightMode);

        Log.d(TAG, "Unregistering listener3");
        listener1.reset();
        listener2.reset();
        listener3.reset();
        mCarSensorManager.unregisterListener(listener3);
        Log.d(TAG, "Rate changed - expect sensor restart and change event sent.");
        value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE)
                .setTimestamp(3002)
                .setBooleanValue(false)
                .build();
        getMockedVehicleHal().injectEvent(value, true);
        assertTrue(listener1.waitForSensorChange());
        assertTrue(listener2.waitForSensorChange());
        assertFalse(listener3.waitForSensorChange());
        listener1.reset();
        listener2.reset();
        listener3.reset();
        // Set the value TRUE again
        value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE)
                .setTimestamp()
                .setBooleanValue(true)
                .build();
        getMockedVehicleHal().injectEvent(value, true);

        assertTrue(listener1.waitForSensorChange());
        assertTrue(listener2.waitForSensorChange());
        listener1.reset();
        listener2.reset();

        // Ensure we did not get a callback (should timeout)
        Log.i(TAG, "waiting for unexpected callback -- should timeout.");
        assertFalse(listener3.waitForSensorChange());

        Log.d(TAG, "Unregistering listener2");
        mCarSensorManager.unregisterListener(listener2);

        Log.d(TAG, "Rate did nor change - dont expect sensor restart and change event sent.");
        assertFalse(listener1.waitForSensorChange());
        assertFalse(listener2.waitForSensorChange());
        assertFalse(listener3.waitForSensorChange());
    }


    /**
     * Callback function we register for sensor update notifications.
     * This tracks the number of times it has been called via the mAvailable semaphore,
     * and keeps a reference to the most recent event delivered.
     */
    class SensorListener implements CarSensorManager.OnSensorChangedListener {
        private final Object mSync = new Object();

        private CarSensorEvent mLastEvent = null;

        CarSensorEvent getLastEvent() {
            return mLastEvent;
        }

        void reset() {
            synchronized (mSync) {
                mLastEvent = null;
            }
        }

        boolean waitForSensorChange() throws InterruptedException {
            return waitForSensorChange(0);
        }

        // Returns True to indicate receipt of a sensor event.  False indicates a timeout.
        boolean waitForSensorChange(long eventTimeStamp) throws InterruptedException {
            long start = SystemClock.elapsedRealtime();
            boolean matchTimeStamp = eventTimeStamp != 0;
            synchronized (mSync) {
                Log.d(TAG, "waitForSensorChange, mLastEvent: " + mLastEvent);
                while ((mLastEvent == null
                        || (matchTimeStamp && mLastEvent.timestamp != eventTimeStamp))
                        && (start + SHORT_WAIT_TIMEOUT_MS > SystemClock.elapsedRealtime())) {
                    mSync.wait(10L);
                }
                return mLastEvent != null &&
                        (!matchTimeStamp || mLastEvent.timestamp == eventTimeStamp);
            }
        }

        @Override
        public void onSensorChanged(CarSensorEvent event) {
            Log.d(TAG, "onSensorChanged, event: " + event);
            synchronized (mSync) {
                // We're going to hold a reference to this object
                mLastEvent = event;
                mSync.notify();
            }
        }
    }

}
