/*
 * Copyright (C) 2013 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 android.hardware.cts;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.cts.helpers.SensorStats;
import android.hardware.cts.helpers.TestSensorEnvironment;
import android.hardware.cts.helpers.sensoroperations.ParallelSensorOperation;
import android.hardware.cts.helpers.sensoroperations.RepeatingSensorOperation;
import android.hardware.cts.helpers.sensoroperations.SequentialSensorOperation;
import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
import android.hardware.cts.helpers.sensorverification.EventOrderingVerification;

import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * Set of tests that verifies proper interaction of the sensors in the platform.
 *
 * To execute these test cases, the following command can be used:
 *      $ adb shell am instrument -e class android.hardware.cts.SensorIntegrationTests \
 *          -w com.android.cts.hardware/android.test.InstrumentationCtsTestRunner
 */
public class SensorIntegrationTests extends SensorTestCase {
    private static final String TAG = "SensorIntegrationTests";

    /**
     * This test focuses in the interaction of continuous and batching clients for the same Sensor
     * under test. The verification ensures that sensor clients can interact with the System and
     * not affect other clients in the way.
     *
     * The test verifies for each client that the a set of sampled data arrives in order. However
     * each client in the test has different set of parameters that represent different types of
     * clients in the real world.
     *
     * A test failure might indicate that the HAL implementation does not respect the assumption
     * that the sensors must be independent. Activating one sensor should not cause another sensor
     * to deactivate or to change behavior.
     * It is however, acceptable that when a client is activated at a higher sampling rate, it would
     * cause other clients to receive data at a faster sampling rate. A client causing other clients
     * to receive data at a lower sampling rate is, however, not acceptable.
     *
     * The assertion associated with the test failure provides:
     * - the thread id on which the failure occurred
     * - the sensor type and sensor handle that caused the failure
     * - the event that caused the issue
     * It is important to look at the internals of the Sensor HAL to identify how the interaction
     * of several clients can lead to the failing state.
     */
    public void testSensorsWithSeveralClients() throws Throwable {
        final int ITERATIONS = 50;
        final int MAX_REPORTING_LATENCY_US = (int) TimeUnit.SECONDS.toMicros(5);
        final Context context = getContext();

        int sensorTypes[] = {
                Sensor.TYPE_ACCELEROMETER,
                Sensor.TYPE_MAGNETIC_FIELD,
                Sensor.TYPE_GYROSCOPE };

        ParallelSensorOperation operation = new ParallelSensorOperation();
        for(int sensorType : sensorTypes) {
            TestSensorEnvironment environment = new TestSensorEnvironment(
                    context,
                    sensorType,
                    shouldEmulateSensorUnderLoad(),
                    SensorManager.SENSOR_DELAY_FASTEST);
            TestSensorOperation continuousOperation =
                    TestSensorOperation.createOperation(environment, 100 /* eventCount */);
            continuousOperation.addVerification(new EventOrderingVerification());
            operation.add(new RepeatingSensorOperation(continuousOperation, ITERATIONS));

            Sensor sensor = TestSensorEnvironment.getSensor(context, sensorType);
            TestSensorEnvironment batchingEnvironment = new TestSensorEnvironment(
                    context,
                    sensorType,
                    shouldEmulateSensorUnderLoad(),
                    sensor.getMinDelay(),
                    MAX_REPORTING_LATENCY_US);
            TestSensorOperation batchingOperation =
                    TestSensorOperation.createOperation(batchingEnvironment, 100 /* eventCount */);
            batchingOperation.addVerification(new EventOrderingVerification());
            operation.add(new RepeatingSensorOperation(batchingOperation, ITERATIONS));
        }
        operation.execute();
        operation.getStats().log(TAG);
    }

    /**
     * This test focuses in the interaction of several sensor Clients. The test characterizes by
     * using clients for different Sensors under Test that vary the sampling rates and report
     * latencies for the requests.
     * The verification ensures that the sensor clients can vary the parameters of their requests
     * without affecting other clients.
     *
     * The test verifies for each client that a set of sampled data arrives in order. However each
     * client in the test has different set of parameters that represent different types of clients
     * in the real world.
     *
     * The test can be susceptible to issues when several clients interacting with the system
     * actually affect the operation of other clients.
     *
     * The assertion associated with the test failure provides:
     * - the thread id on which the failure occurred
     * - the sensor type and sensor handle that caused the failure
     * - the event that caused the issue
     * It is important to look at the internals of the Sensor HAL to identify how the interaction
     * of several clients can lead to the failing state.
     */
    public void testSensorsMovingRates() throws Throwable {
        // use at least two instances to ensure more than one client of any given sensor is in play
        final int INSTANCES_TO_USE = 5;
        final int ITERATIONS_TO_EXECUTE = 100;

        ParallelSensorOperation operation = new ParallelSensorOperation();
        int sensorTypes[] = {
                Sensor.TYPE_ACCELEROMETER,
                Sensor.TYPE_MAGNETIC_FIELD,
                Sensor.TYPE_GYROSCOPE };

        Context context = getContext();
        for(int sensorType : sensorTypes) {
            for(int instance = 0; instance < INSTANCES_TO_USE; ++instance) {
                SequentialSensorOperation sequentialOperation = new SequentialSensorOperation();
                for(int iteration = 0; iteration < ITERATIONS_TO_EXECUTE; ++iteration) {
                    TestSensorEnvironment environment = new TestSensorEnvironment(
                            context,
                            sensorType,
                            shouldEmulateSensorUnderLoad(),
                            generateSamplingRateInUs(sensorType),
                            generateReportLatencyInUs());
                    TestSensorOperation sensorOperation =
                            TestSensorOperation.createOperation(environment, 100 /* eventCount */);
                    sensorOperation.addVerification(new EventOrderingVerification());
                    sequentialOperation.add(sensorOperation);
                }
                operation.add(sequentialOperation);
            }
        }

        operation.execute();
        operation.getStats().log(TAG);
    }

    /**
     * Regress:
     * - b/10641388
     */

    public void testAccelerometerAccelerometerStopping()  throws Throwable {
        verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER);
    }

    public void testAccelerometerGyroscopeStopping()  throws Throwable {
        verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_GYROSCOPE);
    }

    public void testAccelerometerMagneticFieldStopping()  throws Throwable {
        verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_MAGNETIC_FIELD);
    }

    public void testGyroscopeAccelerometerStopping()  throws Throwable {
        verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_ACCELEROMETER);
    }

    public void testGyroscopeGyroscopeStopping()  throws Throwable {
        verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_GYROSCOPE);
    }

    public void testGyroscopeMagneticFieldStopping()  throws Throwable {
        verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_MAGNETIC_FIELD);
    }

    public void testMagneticFieldAccelerometerStopping()  throws Throwable {
        verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_ACCELEROMETER);
    }

    public void testMagneticFieldGyroscopeStopping()  throws Throwable {
        verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_GYROSCOPE);
    }

    public void testMagneticFieldMagneticFieldStopping()  throws Throwable {
        verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD);
    }

    /**
     * This test verifies that starting/stopping a particular Sensor client in the System does not
     * affect other sensor clients.
     * the test is used to validate that starting/stopping operations are independent on several
     * sensor clients.
     *
     * The test verifies for each client that the a set of sampled data arrives in order. However
     * each client in the test has different set of parameters that represent different types of
     * clients in the real world.
     *
     * The test can be susceptible to issues when several clients interacting with the system
     * actually affect the operation of other clients.
     *
     * The assertion associated with the test failure provides:
     * - the thread id on which the failure occurred
     * - the sensor type and sensor handle that caused the failure
     * - the event that caused the issue
     * It is important to look at the internals of the Sensor HAL to identify how the interaction
     * of several clients can lead to the failing state.
     */
    public void verifySensorStoppingInteraction(
            int sensorTypeTestee,
            int sensorTypeTester) throws Throwable {
        Context context = getContext();

        TestSensorEnvironment testerEnvironment = new TestSensorEnvironment(
                context,
                sensorTypeTester,
                shouldEmulateSensorUnderLoad(),
                SensorManager.SENSOR_DELAY_FASTEST);
        TestSensorOperation tester =
                TestSensorOperation.createOperation(testerEnvironment, 100 /* event count */);
        tester.addVerification(new EventOrderingVerification());

        TestSensorEnvironment testeeEnvironment = new TestSensorEnvironment(
                context,
                sensorTypeTestee,
                shouldEmulateSensorUnderLoad(),
                SensorManager.SENSOR_DELAY_FASTEST);
        TestSensorOperation testee =
                TestSensorOperation.createOperation(testeeEnvironment, 100 /* event count */);
        testee.addVerification(new EventOrderingVerification());

        ParallelSensorOperation operation = new ParallelSensorOperation();
        operation.add(tester, testee);
        operation.execute();
        operation.getStats().log(TAG);

        testee = testee.clone();
        testee.execute();
        testee.getStats().log(TAG);
    }

    /**
     * Private helpers.
     */
    private final Random mGenerator = new Random();

    private int generateSamplingRateInUs(int sensorType) {
        int rate;
        switch(mGenerator.nextInt(5)) {
            case 0:
                rate = SensorManager.SENSOR_DELAY_FASTEST;
                break;
            default:
                Sensor sensor = TestSensorEnvironment.getSensor(getContext(), sensorType);
                int maxSamplingRate = sensor.getMinDelay();
                rate = maxSamplingRate * mGenerator.nextInt(10);
        }
        return rate;
    }

    private int generateReportLatencyInUs() {
        long reportLatencyUs = TimeUnit.SECONDS.toMicros(mGenerator.nextInt(5) + 1);
        return (int) reportLatencyUs;
    }
}
