/*
 * Copyright (C) 2014 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.helpers;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.cts.helpers.sensoroperations.SensorOperation;

import java.util.concurrent.TimeUnit;

/**
 * A class that encapsulates base environment information for the {@link SensorOperation}.
 * The environment is self contained and carries its state around all the sensor test framework.
 */
public class TestSensorEnvironment {

    /**
     * It represents the fraction of the expected sampling frequency, at which the sensor can
     * actually produce events.
     */
    private static final float MAXIMUM_EXPECTED_SAMPLING_FREQUENCY_MULTIPLIER = 0.9f;

    private final Context mContext;
    private final Sensor mSensor;
    private final boolean mSensorMightHaveMoreListeners;
    private final int mSamplingPeriodUs;
    private final int mMaxReportLatencyUs;

    /**
     * Constructs an environment for sensor testing.
     *
     * @param context The context for the test
     * @param sensorType The type of the sensor under test
     * @param samplingPeriodUs The requested collection period for the sensor under test
     *
     * @deprecated Use variants with {@link Sensor} objects.
     */
    @Deprecated
    public TestSensorEnvironment(Context context, int sensorType, int samplingPeriodUs) {
        this(context, sensorType, false /* sensorMightHaveMoreListeners */, samplingPeriodUs);
    }

    /**
     * Constructs an environment for sensor testing.
     *
     * @param context The context for the test
     * @param sensorType The type of the sensor under test
     * @param samplingPeriodUs The requested collection period for the sensor under test
     * @param maxReportLatencyUs The requested collection report latency for the sensor under test
     *
     * @deprecated Use variants with {@link Sensor} objects.
     */
    @Deprecated
    public TestSensorEnvironment(
            Context context,
            int sensorType,
            int samplingPeriodUs,
            int maxReportLatencyUs) {
        this(context,
                sensorType,
                false /* sensorMightHaveMoreListeners */,
                samplingPeriodUs,
                maxReportLatencyUs);
    }

    /**
     * Constructs an environment for sensor testing.
     *
     * @param context The context for the test
     * @param sensorType The type of the sensor under test
     * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load
     * @param samplingPeriodUs The requested collection period for the sensor under test
     *
     * @deprecated Use variants with {@link Sensor} objects.
     */
    @Deprecated
    public TestSensorEnvironment(
            Context context,
            int sensorType,
            boolean sensorMightHaveMoreListeners,
            int samplingPeriodUs) {
        this(context,
                sensorType,
                sensorMightHaveMoreListeners,
                samplingPeriodUs,
                0 /* maxReportLatencyUs */);
    }

    /**
     * Constructs an environment for sensor testing.
     *
     * @param context The context for the test
     * @param sensorType The type of the sensor under test
     * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load
     * @param samplingPeriodUs The requested collection period for the sensor under test
     * @param maxReportLatencyUs The requested collection report latency for the sensor under test
     *
     * @deprecated Use variants with {@link Sensor} objects.
     */
    @Deprecated
    public TestSensorEnvironment(
            Context context,
            int sensorType,
            boolean sensorMightHaveMoreListeners,
            int samplingPeriodUs,
            int maxReportLatencyUs) {
        this(context,
                getSensor(context, sensorType),
                sensorMightHaveMoreListeners,
                samplingPeriodUs,
                maxReportLatencyUs);
    }

    /**
     * Constructs an environment for sensor testing.
     *
     * @param context The context for the test
     * @param sensor The sensor under test
     * @param samplingPeriodUs The requested collection period for the sensor under test
     * @param maxReportLatencyUs The requested collection report latency for the sensor under test
     */
    public TestSensorEnvironment(
            Context context,
            Sensor sensor,
            int samplingPeriodUs,
            int maxReportLatencyUs) {
        this(context,
                sensor,
                false /* sensorMightHaveMoreListeners */,
                samplingPeriodUs,
                maxReportLatencyUs);
    }

    /**
     * Constructs an environment for sensor testing.
     *
     * @param context The context for the test
     * @param sensor The sensor under test
     * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load (this
     *                                     usually implies that there are several listeners
     *                                     requesting different sampling periods)
     * @param samplingPeriodUs The requested collection period for the sensor under test
     * @param maxReportLatencyUs The requested collection report latency for the sensor under test
     */
    public TestSensorEnvironment(
            Context context,
            Sensor sensor,
            boolean sensorMightHaveMoreListeners,
            int samplingPeriodUs,
            int maxReportLatencyUs) {
        mContext = context;
        mSensor = sensor;
        mSensorMightHaveMoreListeners = sensorMightHaveMoreListeners;
        mSamplingPeriodUs = samplingPeriodUs;
        mMaxReportLatencyUs = maxReportLatencyUs;
    }

    /**
     * @return The context instance associated with the test.
     */
    public Context getContext() {
        return mContext;
    }

    /**
     * @return The sensor under test.
     */
    public Sensor getSensor() {
        return mSensor;
    }

    /**
     * @return The requested collection rate in microseconds.
     */
    public int getRequestedSamplingPeriodUs() {
        return mSamplingPeriodUs;
    }

    /**
     * @return The frequency equivalent to {@link #getRequestedSamplingPeriodUs()}.
     */
    public double getFrequencyHz() {
        return SensorCtsHelper.getFrequency(mSamplingPeriodUs, TimeUnit.MICROSECONDS);
    }

    /**
     * @return A string representing the frequency equivalent to
     * {@link #getRequestedSamplingPeriodUs()}.
     */
    public String getFrequencyString() {
        if (mSamplingPeriodUs == SensorManager.SENSOR_DELAY_FASTEST) {
            return "fastest";
        }
        return String.format("%.0fhz", getFrequencyHz());
    }

    /**
     * @return The requested collection max batch report latency in microseconds.
     */
    public int getMaxReportLatencyUs() {
        return mMaxReportLatencyUs;
    }

    /**
     * Returns {@code true} if there might be other listeners of {@link #getSensor()} requesting
     * data at different sampling rates (the rates are unknown); false otherwise.
     */
    public boolean isSensorSamplingRateOverloaded() {
        return mSensorMightHaveMoreListeners
                && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_FASTEST;
    }

    /**
     * Convert the {@link #getRequestedSamplingPeriodUs()} into delay in microseconds.
     * <p>
     * The flags SensorManager.SENSOR_DELAY_[GAME|UI|NORMAL] are not supported since the CDD does
     * not specify values for these flags. The rate is set to the max of
     * {@link Sensor#getMinDelay()} and the rate given.
     * </p>
     */
    public int getExpectedSamplingPeriodUs() {
        if (!isDelayRateTestable()) {
            throw new IllegalArgumentException("rateUs cannot be SENSOR_DELAY_[GAME|UI|NORMAL]");
        }

        int expectedSamplingPeriodUs = mSamplingPeriodUs;
        int sensorMaxDelay = mSensor.getMaxDelay();
        if (sensorMaxDelay > 0) {
            expectedSamplingPeriodUs = Math.min(expectedSamplingPeriodUs, sensorMaxDelay);
        }

        return Math.max(expectedSamplingPeriodUs, mSensor.getMinDelay());
    }

    /**
     * @return The actual sampling period at which a sensor can sample data. This value is a
     *         fraction of {@link #getExpectedSamplingPeriodUs()}.
     */
    public int getMaximumExpectedSamplingPeriodUs() {
        int expectedSamplingPeriodUs = getExpectedSamplingPeriodUs();
        return (int) (expectedSamplingPeriodUs / MAXIMUM_EXPECTED_SAMPLING_FREQUENCY_MULTIPLIER);
    }

    /**
     * @return The number of axes in the coordinate system of the sensor under test.
     */
    public int getSensorAxesCount() {
        switch (mSensor.getType()) {
            case Sensor.TYPE_GYROSCOPE:
                return 3;
            default:
                throw new IllegalStateException("Axes count needs to be defined for sensor type: "
                        + mSensor.getStringType());
        }
    }

    /**
     * Get the default sensor for a given type.
     *
     * @deprecated Used for historical reasons, sensor tests must be written around Sensor objects,
     * so all sensors of a given type are exercised.
     */
    @Deprecated
    public static Sensor getSensor(Context context, int sensorType) {
        SensorManager sensorManager =
                (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        if (sensorManager == null) {
            throw new IllegalStateException("SensorService is not present in the system.");
        }

        Sensor sensor = sensorManager.getDefaultSensor(sensorType);
        if(sensor == null) {
            throw new SensorNotSupportedException(sensorType);
        }
        return sensor;
    }

    /**
     * @return The maximum latency of a given sensor, on top of {@link #getMaxReportLatencyUs()}.
     *
     * NOTE: The latency is defined as the time between the event happens and the time the event is
     * generated.
     *
     * - At time event_time (reported in the sensor event), the physical event happens
     * - At time event_time + detection_latency, the physical event is detected and the event is
     *   saved in the hardware fifo
     * - At time event_time + detection_latency + report_latency, the event is reported through the
     *   HAL
     *
     * Soon after that, the event is piped through the framework to the application. This time may
     * vary depending on the CPU load. The time 'detection_latency' must be less than
     * {@link #getSensorMaxDetectionLatencyNs(Sensor)}, and 'report_latency' must be less than
     * {@link #getMaxReportLatencyUs()} passed through batch() at the HAL level.
     */
    // TODO: when all tests are moved to use the Sensor test framework, make this method non-static
    public static long getSensorMaxDetectionLatencyNs(Sensor sensor) {
        int reportLatencySec;
        switch (sensor.getType()) {
            case Sensor.TYPE_STEP_DETECTOR:
                reportLatencySec = 2;
                break;
            case Sensor.TYPE_STEP_COUNTER:
                reportLatencySec = 10;
                break;
            case Sensor.TYPE_SIGNIFICANT_MOTION:
                reportLatencySec = 10;
                break;
            default:
                reportLatencySec = 0;
        }
        return TimeUnit.SECONDS.toNanos(reportLatencySec);
    }

    @Override
    public String toString() {
        return String.format(
                "Sensor='%s', SamplingRateOverloaded=%s, SamplingPeriod=%sus, "
                        + "MaxReportLatency=%sus",
                mSensor,
                isSensorSamplingRateOverloaded(),
                mSamplingPeriodUs,
                mMaxReportLatencyUs);
    }

    /**
     * Return true if {@link #getRequestedSamplingPeriodUs()} is not one of
     * {@link SensorManager#SENSOR_DELAY_GAME}, {@link SensorManager#SENSOR_DELAY_UI}, or
     * {@link SensorManager#SENSOR_DELAY_NORMAL}.
     */
    private boolean isDelayRateTestable() {
        return (mSamplingPeriodUs >= 0
                && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_GAME
                && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_UI
                && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_NORMAL);
    }
}
