/*
 * Copyright (C) 2008 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.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorEventListener2;
import android.hardware.SensorManager;
import android.hardware.TriggerEvent;
import android.hardware.TriggerEventListener;
import android.hardware.cts.helpers.SensorCtsHelper;
import android.hardware.cts.helpers.SensorNotSupportedException;
import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
import android.hardware.cts.helpers.TestSensorEnvironment;
import android.hardware.cts.helpers.TestSensorEventListener;
import android.hardware.cts.helpers.TestSensorManager;
import android.hardware.cts.helpers.sensoroperations.ParallelSensorOperation;
import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
import android.hardware.cts.helpers.sensorverification.ContinuousEventSanitizedVerification;
import android.hardware.cts.helpers.sensorverification.EventGapVerification;
import android.hardware.cts.helpers.sensorverification.EventOrderingVerification;
import android.hardware.cts.helpers.sensorverification.EventTimestampSynchronizationVerification;
import android.os.Build.VERSION_CODES;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.PowerManager;
import android.os.SystemClock;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.Presubmit;
import android.util.Log;

import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.PropertyUtil;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;

import junit.framework.Assert;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class SensorTest extends SensorTestCase {
    private static final String TAG = "SensorTest";

    // Test only SDK defined sensors. Any sensors with type > 100 are ignored.
    private static final int MAX_OFFICIAL_ANDROID_SENSOR_TYPE = 100;

    private PowerManager.WakeLock mWakeLock;
    private SensorManager mSensorManager;
    private TestSensorManager mTestSensorManager;
    private NullTriggerEventListener mNullTriggerEventListener;
    private NullSensorEventListener mNullSensorEventListener;
    private Sensor mTriggerSensor;
    private List<Sensor> mSensorList;
    private List<Sensor> mAndroidSensorList;

    @Override
    protected void setUp() throws Exception {
        Context context = getContext();
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);

        mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        mNullTriggerEventListener = new NullTriggerEventListener();
        mNullSensorEventListener = new NullSensorEventListener();

        mSensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
        assertNotNull("SensorList was null.", mSensorList);
        if (mSensorList.isEmpty()) {
            // several devices will not have sensors, so we need to skip the tests in those cases
            throw new SensorTestStateNotSupportedException(
                    "Sensors are not available in the system.");
        }

        mAndroidSensorList = new ArrayList<>();
        for (Sensor s : mSensorList) {
            if (s.getType() < Sensor.TYPE_DEVICE_PRIVATE_BASE &&
                    (!context.getPackageManager().isInstantApp() || s.getType() != Sensor.TYPE_HEART_RATE)) {
                mAndroidSensorList.add(s);
            }
        }

        mWakeLock.acquire();
    }

    @Override
    protected void tearDown() {
        if (mSensorManager != null) {
            // SensorManager will check listener and status, so just unregister listener
            mSensorManager.unregisterListener(mNullSensorEventListener);
            if (mTriggerSensor != null) {
                mSensorManager.cancelTriggerSensor(mNullTriggerEventListener, mTriggerSensor);
                mTriggerSensor = null;
            }
        }

        if (mTestSensorManager != null) {
            mTestSensorManager.unregisterListener();
            mTestSensorManager = null;
        }

        if (mWakeLock != null && mWakeLock.isHeld()) {
            mWakeLock.release();
        }
    }

    /**
     * testSensorOperations
     *
     * Because we can't know every sensors unit details, so we can't assert
     * get values with specified values.
     */
    @CddTest(requirement = "7.3.1/C-2-1")
    public void testSensorOperations_accelerometer() {
        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        boolean hasAccelerometer = getContext().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_SENSOR_ACCELEROMETER);
        // accelerometer sensor is optional
        if (hasAccelerometer) {
            assertNotNull(sensor);
            assertEquals(Sensor.TYPE_ACCELEROMETER, sensor.getType());
            assertSensorValues(sensor);
        } else {
            assertNull(sensor);
        }
    }

    public void testSensorOperations_stepCounter() {
        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
        boolean hasStepCounter = getContext().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_SENSOR_STEP_COUNTER);
        // stepcounter sensor is optional
        if (hasStepCounter) {
            assertNotNull(sensor);
            assertEquals(Sensor.TYPE_STEP_COUNTER, sensor.getType());
            assertSensorValues(sensor);
        } else {
            assertNull(sensor);
        }
    }

    public void testSensorOperations_stepDetector() {
        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
        boolean hasStepDetector = getContext().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_SENSOR_STEP_DETECTOR);
        // stepdetector sensor is optional
        if (hasStepDetector) {
            assertNotNull(sensor);
            assertEquals(Sensor.TYPE_STEP_DETECTOR, sensor.getType());
            assertSensorValues(sensor);
        } else {
            assertNull(sensor);
        }
    }

    public void testSensorOperations_magneticField() {
        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        boolean hasCompass = getContext().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_SENSOR_COMPASS);
        // compass sensor is optional
        if (hasCompass) {
            assertNotNull(sensor);
            assertEquals(Sensor.TYPE_MAGNETIC_FIELD, sensor.getType());
            assertSensorValues(sensor);
        } else {
            assertNull(sensor);
        }
    }

    @CddTest(requirement = "7.3.4/C-2-1")
    public void testSensorOperations_gyroscope() {
        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
        boolean hasGyroscope = getContext().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_SENSOR_GYROSCOPE);
        // gyroscope sensor is optional
        if (hasGyroscope) {
            assertNotNull(sensor);
            assertEquals(Sensor.TYPE_GYROSCOPE, sensor.getType());
            assertSensorValues(sensor);
        } else {
            assertNull(sensor);
        }
    }

    public void testSensorOperations_pressure() {
        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
        boolean hasPressure = getContext().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_SENSOR_BAROMETER);
        // pressure sensor is optional
        if (hasPressure) {
            assertNotNull(sensor);
            assertEquals(Sensor.TYPE_PRESSURE, sensor.getType());
            assertSensorValues(sensor);
        } else {
            assertNull(sensor);
        }
    }

    @SuppressWarnings("deprecation")
    public void testSensorOperations_orientation() {
        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
        // Note: orientation sensor is deprecated.
        if (sensor != null) {
            assertEquals(Sensor.TYPE_ORIENTATION, sensor.getType());
            assertSensorValues(sensor);
        }
    }

    @SuppressWarnings("deprecation")
    public void testSensorOperations_temperature() {
        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_TEMPERATURE);
        // temperature sensor is optional
        if (sensor != null) {
            assertEquals(Sensor.TYPE_TEMPERATURE, sensor.getType());
            assertSensorValues(sensor);
        }
    }

    public void testSensorOperations_hingeAngle() {
        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HINGE_ANGLE);
        boolean hasHingeAngle = getContext().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_SENSOR_HINGE_ANGLE);

        if (hasHingeAngle) {
            assertNotNull(sensor);
            assertEquals(Sensor.TYPE_HINGE_ANGLE, sensor.getType());
            assertSensorValues(sensor);
            assertTrue("Max range must not be larger than 360. Range=" + sensor.getMaximumRange()
                + " " + sensor.getName(), sensor.getMaximumRange() <= 360);
        } else {
            assertNull(sensor);
        }
    }

    @CddTest(requirement = "7.3.1/C-3-1")
    public void testSensorOperations_accelerometerLimitedAxes() {
        validateLimitedAxesImuSensorType(Sensor.TYPE_ACCELEROMETER_LIMITED_AXES,
                PackageManager.FEATURE_SENSOR_ACCELEROMETER_LIMITED_AXES);
    }

    public void testSensorOperations_gyroscopeLimitedAxes() {
        validateLimitedAxesImuSensorType(Sensor.TYPE_GYROSCOPE_LIMITED_AXES,
                PackageManager.FEATURE_SENSOR_GYROSCOPE_LIMITED_AXES);
    }

    @CddTest(requirement = "7.3.4/C-3-1")
    public void testSensorOperations_accelerometerLimitedAxesUncalibrated() {
        validateLimitedAxesImuSensorType(Sensor.TYPE_ACCELEROMETER_LIMITED_AXES_UNCALIBRATED,
                PackageManager.FEATURE_SENSOR_ACCELEROMETER_LIMITED_AXES_UNCALIBRATED);
    }

    public void testSensorOperations_gyroscopeLimitedAxesUncalibrated() {
        validateLimitedAxesImuSensorType(Sensor.TYPE_GYROSCOPE_LIMITED_AXES_UNCALIBRATED,
                PackageManager.FEATURE_SENSOR_GYROSCOPE_LIMITED_AXES_UNCALIBRATED);
    }

    private void validateLimitedAxesImuSensorType(int sensorType, String systemFeature) {
        Sensor sensor = mSensorManager.getDefaultSensor(sensorType);
        boolean hasSensorFeature = getContext().getPackageManager().hasSystemFeature(systemFeature);
        if (hasSensorFeature) {
            assertNotNull(sensor);
            assertEquals(sensorType, sensor.getType());
            assertSensorValues(sensor);
        } else {
            assertNull(sensor);
        }
    }

    public void testSensorOperations_heading() {
        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEADING);
        boolean hasHeadingSensor = getContext().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_SENSOR_HEADING);
        boolean isAutomotive = mContext.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_AUTOMOTIVE);
        if (isAutomotive && hasHeadingSensor) {
            assertNotNull(sensor);
            assertEquals(Sensor.TYPE_HEADING, sensor.getType());
            assertSensorValues(sensor);
            assertTrue("Max range must not be greater or equal to 360. Range="
                    + sensor.getMaximumRange() + " " + sensor.getName(),
                    sensor.getMaximumRange() < 360);
        } else if (isAutomotive) {
            assertNull(sensor);
        } else {
            // There isn't good test coverage for heading, particularly for non-automotive devices.
            // So if a non-automotive device wants to implement this, requirements for the sensor
            // and how to test for those requirements should be re-discussed.
            assertNull("If the heading sensor is being implemented on a non-automotive device, "
                    + "the team would love to hear from you. Please reach out!", sensor);
        }
    }

    @AppModeFull(reason = "Instant apps cannot access body sensors")
    public void testBodySensorOperations() {
        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
        boolean hasHeartRate = getContext().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_SENSOR_HEART_RATE);
        // heartrate sensor is optional
        if (hasHeartRate) {
            assertEquals(Sensor.TYPE_HEART_RATE, sensor.getType());
            assertSensorValues(sensor);
        } else {
            assertNull(sensor);
        }
    }

    private void assertAllSensorsNameUniqueness() {
        Multimap<Integer, String> sensorTypeNameMap = ArrayListMultimap.create();

        for (Sensor sensor : mSensorList) {
            assertFalse("Duplicate sensor name " + sensor.getName() + " for type " + sensor.getType(),
                        sensorTypeNameMap.containsEntry(sensor.getType(), sensor.getName()));
            sensorTypeNameMap.put(sensor.getType(), sensor.getName());
        }
    }

    public void testValuesForAllSensors() {
        for (Sensor sensor : mSensorList) {
            assertSensorValues(sensor);
        }
        assertAllSensorsNameUniqueness();
    }

    private void hasOnlyOneWakeUpSensorOrEmpty(List<Sensor> sensors) {
        if (sensors == null || sensors.isEmpty()) return;
        if (sensors.size() > 1) {
            fail("More than one " + sensors.get(0).getName() + " defined.");
            return;
        }
        assertTrue(sensors.get(0).getName() + " defined as non-wake-up sensor",
                sensors.get(0).isWakeUpSensor());
    }

    private void hasDefaultWakeupSensorOrEmpty(int sensorType, String sensorName) {
        Sensor sensor = mSensorManager.getDefaultSensor(sensorType);
        if (sensor == null) return;

        assertTrue("Default " + sensorName + " sensor is not a wake-up sensor", sensor.isWakeUpSensor());
    }

    // Some sensors like proximity, significant motion etc. are defined as wake-up sensors by
    // default. Check if the wake-up flag is set correctly.
    @Presubmit
    public void testWakeUpFlags() {
        final int TYPE_WAKE_GESTURE = 23;
        final int TYPE_GLANCE_GESTURE = 24;
        final int TYPE_PICK_UP_GESTURE = 25;

        hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(Sensor.TYPE_SIGNIFICANT_MOTION));
        hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_WAKE_GESTURE));
        hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_GLANCE_GESTURE));
        hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_PICK_UP_GESTURE));

        hasDefaultWakeupSensorOrEmpty(Sensor.TYPE_PROXIMITY, "proximity");
        hasDefaultWakeupSensorOrEmpty(Sensor.TYPE_HINGE_ANGLE, "hinge");
    }

    public void testGetDefaultSensorWithWakeUpFlag() {
        // With wake-up flags set to false, the sensor returned should be a non wake-up sensor.
        for (Sensor sensor : mSensorList) {
            Sensor curr_sensor = mSensorManager.getDefaultSensor(sensor.getType(), false);
            if (curr_sensor != null) {
                assertFalse("getDefaultSensor wakeup=false returns a wake-up sensor" +
                        curr_sensor.getName(),
                        curr_sensor.isWakeUpSensor());
            }

            curr_sensor = mSensorManager.getDefaultSensor(sensor.getType(), true);
            if (curr_sensor != null) {
                assertTrue("getDefaultSensor wake-up returns non wake sensor" +
                        curr_sensor.getName(),
                        curr_sensor.isWakeUpSensor());
            }
        }
    }

    @Presubmit
    public void testSensorStringTypes() {
        for (Sensor sensor : mSensorList) {
            if (sensor.getType() < MAX_OFFICIAL_ANDROID_SENSOR_TYPE &&
                    !sensor.getStringType().startsWith("android.sensor.")) {
                fail("StringType not set correctly for android defined sensor " +
                        sensor.getName() + " " + sensor.getStringType());
            }
        }
    }

    public void testRequestTriggerWithNonTriggerSensor() {
        mTriggerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        if (mTriggerSensor == null) {
            throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER);
        }
        boolean  result =
            mSensorManager.requestTriggerSensor(mNullTriggerEventListener, mTriggerSensor);
        assertFalse(result);
    }

    public void testCancelTriggerWithNonTriggerSensor() {
        mTriggerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        if (mTriggerSensor == null) {
            throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER);
        }
        boolean result =
            mSensorManager.cancelTriggerSensor(mNullTriggerEventListener, mTriggerSensor);
        assertFalse(result);
    }

    public void testRegisterWithTriggerSensor() {
        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
        if (sensor == null) {
            throw new SensorNotSupportedException(Sensor.TYPE_SIGNIFICANT_MOTION);
        }
        boolean result = mSensorManager.registerListener(
                mNullSensorEventListener,
                sensor,
                SensorManager.SENSOR_DELAY_NORMAL);
        assertFalse(result);
    }

    public void testRegisterTwiceWithSameSensor() {
        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        if (sensor == null) {
            throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER);
        }

        boolean result = mSensorManager.registerListener(mNullSensorEventListener, sensor,
                SensorManager.SENSOR_DELAY_NORMAL);
        assertTrue(result);

        result = mSensorManager.registerListener(mNullSensorEventListener, sensor,
                SensorManager.SENSOR_DELAY_NORMAL);
        assertFalse(result);
    }

    /**
     * Verifies that if the UID is idle the continuous events are being reported
     * but sanitized - all events are the same as the first one delivered except
     * for their timestamps. From the point of view of an idle app these events are
     * being properly generated but the sensor reading does not change - privacy.
     */
    // TODO: remove when parametrized tests are supported and EventTimestampSynchronization
    public void testSanitizedContinuousEventsUidIdle() throws Exception {
        ArrayList<Throwable> errorsFound = new ArrayList<>();
        for (Sensor sensor : mAndroidSensorList) {
            // If the UID is active no sanitization should be performed
            verifyLongActivation(sensor, 0 /* maxReportLatencyUs */,
                    5 /* duration */, TimeUnit.SECONDS, "continuous event",
                    false /* sanitized */, errorsFound);
            verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10),
                    5 /* duration */, TimeUnit.SECONDS, "continuous event",
                    false /* sanitized */, errorsFound);

            // If the UID is idle sanitization should be performed

            SensorCtsHelper.makeMyPackageIdle();
            try {
                verifyLongActivation(sensor, 0 /* maxReportLatencyUs */,
                        5 /* duration */, TimeUnit.SECONDS, "continuous event",
                        true /* sanitized */, errorsFound);
                verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10),
                        5 /* duration */, TimeUnit.SECONDS, "continuous event",
                        true /* sanitized */, errorsFound);
            } finally {
                SensorCtsHelper.makeMyPackageActive();
            }

            // If the UID is active no sanitization should be performed
            verifyLongActivation(sensor, 0 /* maxReportLatencyUs */,
                    5 /* duration */, TimeUnit.SECONDS, "continuous event",
                    false /* sanitized */, errorsFound);
            verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10),
                    5 /* duration */, TimeUnit.SECONDS, "continuous event",
                    false /* sanitized */, errorsFound);
        }
        assertOnErrors(errorsFound);
    }

    // TODO: remove when parametrized tests are supported and EventTimestampSynchronization
    //       verification is added to default verifications
    public void testSensorTimeStamps() throws Exception {
        ArrayList<Throwable> errorsFound = new ArrayList<>();
        for (Sensor sensor : mAndroidSensorList) {
            // test both continuous and batching mode sensors
            verifyLongActivation(sensor, 0 /* maxReportLatencyUs */,
                    20 /* duration */, TimeUnit.SECONDS, "timestamp", false
                    /* sanitized */, errorsFound);
            verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10),
                    20 /* duration */, TimeUnit.SECONDS, "timestamp",
                    false /* sanitized */, errorsFound);
        }
        assertOnErrors(errorsFound);
    }

    // TODO: remove when parameterized tests are supported (see SensorBatchingTests.java)
    public void testBatchAndFlush() throws Exception {
        SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
        ArrayList<Throwable> errorsFound = new ArrayList<>();
        for (Sensor sensor : mAndroidSensorList) {
            verifyRegisterListenerCallFlush(sensor, null /* handler */, errorsFound,
                    false /* flushWhileIdle */);
        }
        assertOnErrors(errorsFound);
    }

    /**
     * Verifies that if the UID is idle flush events are reported. Since
     * these events have no payload with private data they are working as
     * for a non-idle UID.
     */
    // TODO: remove when parametized tests are supported and EventTimestampSynchronization
    public void testBatchAndFlushUidIdle() throws Exception {
        SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
        ArrayList<Throwable> errorsFound = new ArrayList<>();
        for (Sensor sensor : mAndroidSensorList) {
            verifyRegisterListenerCallFlush(sensor, null /* handler */, errorsFound,
                    true /* flushWhileIdle */);
        }
        assertOnErrors(errorsFound);
    }

    /**
     * Verifies that sensor events arrive in the given message queue (Handler).
     */
    public void testBatchAndFlushWithHandler() throws Exception {
        SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
        Sensor sensor = null;
        for (Sensor s : mAndroidSensorList) {
            if (s.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
                sensor = s;
                break;
            }
        }
        if (sensor == null) {
            throw new SensorTestStateNotSupportedException(
                    "There are no Continuous sensors in the device.");
        }

        TestSensorEnvironment environment = new TestSensorEnvironment(
                getContext(),
                sensor,
                SensorManager.SENSOR_DELAY_FASTEST,
                (int) TimeUnit.SECONDS.toMicros(5));
        mTestSensorManager = new TestSensorManager(environment);

        HandlerThread handlerThread = new HandlerThread("sensorThread");
        handlerThread.start();
        Handler handler = new Handler(handlerThread.getLooper());
        TestSensorEventListener listener = new TestSensorEventListener(environment, handler);

        CountDownLatch eventLatch = mTestSensorManager.registerListener(listener, 1);
        listener.waitForEvents(eventLatch, 1, true);
        CountDownLatch flushLatch = mTestSensorManager.requestFlush();
        listener.waitForFlushComplete(flushLatch, true);
        listener.assertEventsReceivedInHandler();
    }

    /**
     *  Explicit testing the SensorManager.registerListener(SensorEventListener, Sensor, int, int).
     */
    public void testBatchAndFlushUseDefaultHandler() throws Exception {
        SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
        Sensor sensor = null;
        for (Sensor s : mAndroidSensorList) {
            if (s.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
                sensor = s;
                break;
            }
        }
        if (sensor == null) {
            throw new SensorTestStateNotSupportedException(
                    "There are no Continuous sensors in the device.");
        }

        TestSensorEnvironment environment = new TestSensorEnvironment(
                getContext(),
                sensor,
                SensorManager.SENSOR_DELAY_FASTEST,
                (int) TimeUnit.SECONDS.toMicros(5));
        mTestSensorManager = new TestSensorManager(environment);

        TestSensorEventListener listener = new TestSensorEventListener(environment, null);

        // specifyHandler <= false, use the SensorManager API without Handler parameter
        CountDownLatch eventLatch = mTestSensorManager.registerListener(listener, 1, false);
        listener.waitForEvents(eventLatch, 1, true);
        CountDownLatch flushLatch = mTestSensorManager.requestFlush();
        listener.waitForFlushComplete(flushLatch, true);
        listener.assertEventsReceivedInHandler();
    }

    // TODO: after L release move to SensorBatchingTests and run in all sensors with default
    //       verifications enabled
    public void testBatchAndFlushWithMultipleSensors() throws Exception {
        SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
        final int maxSensors = 3;
        final int maxReportLatencyUs = (int) TimeUnit.SECONDS.toMicros(10);
        List<Sensor> sensorsToTest = new ArrayList<Sensor>();
        for (Sensor sensor : mAndroidSensorList) {
            if (sensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
                sensorsToTest.add(sensor);
                if (sensorsToTest.size()  == maxSensors) break;
            }
        }
        final int numSensorsToTest = sensorsToTest.size();
        if (numSensorsToTest == 0) {
            return;
        }

        StringBuilder builder = new StringBuilder();
        ParallelSensorOperation parallelSensorOperation = new ParallelSensorOperation();
        for (Sensor sensor : sensorsToTest) {
            TestSensorEnvironment environment = new TestSensorEnvironment(
                    getContext(),
                    sensor,
                    shouldEmulateSensorUnderLoad(),
                    SensorManager.SENSOR_DELAY_FASTEST,
                    maxReportLatencyUs);
            FlushExecutor executor = new FlushExecutor(environment, 500 /* eventCount */,
                    false /* flushWhileIdle */);
            parallelSensorOperation.add(new TestSensorOperation(environment, executor));
            builder.append(sensor.getName()).append(", ");
        }

        Log.i(TAG, "Testing batch/flush for sensors: " + builder);
        parallelSensorOperation.execute(getCurrentTestNode());
    }

    private void assertSensorValues(Sensor sensor) {
        assertTrue("Max range must be positive. Range=" + sensor.getMaximumRange()
                + " " + sensor.getName(), sensor.getMaximumRange() >= 0);
        assertTrue("Max power must be positive. Power=" + sensor.getPower() + " " +
                sensor.getName(), sensor.getPower() >= 0);

        // Only assert sensor resolution is non-zero for official sensor types since that's what's
        // required by the CDD.
        if (sensor.getType() < MAX_OFFICIAL_ANDROID_SENSOR_TYPE) {
            assertTrue("Max resolution must be non-zero and positive. Resolution=" + sensor.getResolution() +
                    " " + sensor.getName(), sensor.getResolution() > 0);
        } else {
            assertTrue("Max resolution must be positive. Resolution=" + sensor.getResolution() +
                    " " + sensor.getName(), sensor.getResolution() >= 0);
        }

        boolean hasHifiSensors = getContext().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_HIFI_SENSORS);
        if (SensorCtsHelper.hasMaxResolutionRequirement(sensor, hasHifiSensors)) {
            float maxResolution = SensorCtsHelper.getRequiredMaxResolutionForSensor(sensor);
            assertTrue("Resolution must be <= " + maxResolution + ". Resolution=" +
                    sensor.getResolution() + " " + sensor.getName(),
                    sensor.getResolution() <= maxResolution);
        }

        // The minimum resolution requirement was introduced to the CDD in R so
        // it's only possible to assert compliance for devices that release with
        // R or later.
        if (PropertyUtil.getFirstApiLevel() >= VERSION_CODES.R &&
                SensorCtsHelper.hasMinResolutionRequirement(sensor)) {
            float minResolution = SensorCtsHelper.getRequiredMinResolutionForSensor(sensor);
            assertTrue("Resolution must be >= " + minResolution + ". Resolution =" +
                    sensor.getResolution() + " " + sensor.getName(),
                    sensor.getResolution() >= minResolution);
        }

        assertNotNull("Vendor name must not be null " + sensor.getName(), sensor.getVendor());
        assertTrue("Version must be positive version=" + sensor.getVersion() + " " +
                sensor.getName(), sensor.getVersion() > 0);
        int fifoMaxEventCount = sensor.getFifoMaxEventCount();
        int fifoReservedEventCount = sensor.getFifoReservedEventCount();
        assertTrue(fifoMaxEventCount >= 0);
        assertTrue(fifoReservedEventCount >= 0);
        assertTrue(fifoReservedEventCount <= fifoMaxEventCount);
        if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
            assertTrue("One shot sensors should have zero FIFO Size " + sensor.getName(),
                    sensor.getFifoMaxEventCount() == 0);
            assertTrue("One shot sensors should have zero FIFO Size "  + sensor.getName(),
                    sensor.getFifoReservedEventCount() == 0);
        }
    }

    @SuppressWarnings("deprecation")
    public void testLegacySensorOperations() {
        final SensorManager mSensorManager =
                (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);

        // We expect the set of sensors reported by the new and legacy APIs to be consistent.
        int sensors = 0;
        if (mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
            sensors |= SensorManager.SENSOR_ACCELEROMETER;
        }
        if (mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) {
            sensors |= SensorManager.SENSOR_MAGNETIC_FIELD;
        }
        if (mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION) != null) {
            sensors |= SensorManager.SENSOR_ORIENTATION | SensorManager.SENSOR_ORIENTATION_RAW;
        }
        assertEquals(sensors, mSensorManager.getSensors());
    }

    /**
     * Verifies that a continuous sensor produces events that have timestamps synchronized with
     * {@link SystemClock#elapsedRealtimeNanos()} and that the events are sanitized/non-sanitized.
     */
    private void verifyLongActivation(
            Sensor sensor,
            int maxReportLatencyUs,
            long duration,
            TimeUnit durationTimeUnit,
            String testType,
            boolean sanitized,
            ArrayList<Throwable> errorsFound) throws InterruptedException {
        if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
            return;
        }

        try {
            TestSensorEnvironment environment = new TestSensorEnvironment(
                    getContext(),
                    sensor,
                    shouldEmulateSensorUnderLoad(),
                    SensorManager.SENSOR_DELAY_FASTEST,
                    maxReportLatencyUs);
            TestSensorOperation operation = TestSensorOperation.createOperation(
                    environment, duration, durationTimeUnit);
            if (sanitized) {
                final long verificationDelayNano = TimeUnit.NANOSECONDS.convert(
                        maxReportLatencyUs, TimeUnit.MICROSECONDS) * 2;
                operation.addVerification(ContinuousEventSanitizedVerification
                        .getDefault(environment, verificationDelayNano));
            } else {
                operation.addVerification(EventGapVerification.getDefault(environment));
                operation.addVerification(EventOrderingVerification.getDefault(environment));
                operation.addVerification(EventTimestampSynchronizationVerification
                        .getDefault(environment));
            }
            Log.i(TAG, "Running " + testType + " test on: " + sensor.getName());
            operation.execute(getCurrentTestNode());
        } catch (InterruptedException e) {
            // propagate so the test can stop
            throw e;
        } catch (Throwable e) {
            errorsFound.add(e);
            Log.e(TAG, e.getMessage());
        }
    }

    /**
     * Verifies that a client can listen for events, and that
     * {@link SensorManager#flush(SensorEventListener)} will trigger the appropriate notification
     * for {@link SensorEventListener2#onFlushCompleted(Sensor)}.
     */
    private void verifyRegisterListenerCallFlush(
            Sensor sensor,
            Handler handler,
            ArrayList<Throwable> errorsFound,
            boolean flushWhileIdle)
            throws InterruptedException {
        if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
            return;
        }

        try {
            TestSensorEnvironment environment = new TestSensorEnvironment(
                    getContext(),
                    sensor,
                    shouldEmulateSensorUnderLoad(),
                    SensorManager.SENSOR_DELAY_FASTEST,
                    (int) TimeUnit.SECONDS.toMicros(10));
            FlushExecutor executor = new FlushExecutor(environment, 500 /* eventCount */,
                    flushWhileIdle);
            TestSensorOperation operation = new TestSensorOperation(environment, executor, handler);

            Log.i(TAG, "Running flush test on: " + sensor.getName());
            operation.execute(getCurrentTestNode());
        } catch (InterruptedException e) {
            // propagate so the test can stop
            throw e;
        } catch (Throwable e) {
            errorsFound.add(e);
            Log.e(TAG, e.getMessage());
        }
    }

    private void assertOnErrors(List<Throwable> errorsFound) {
        if (!errorsFound.isEmpty()) {
            StringBuilder builder = new StringBuilder();
            for (Throwable error : errorsFound) {
                builder.append(error.getMessage()).append("\n");
            }
            Assert.fail(builder.toString());
        }
    }

    /**
     * A delegate that drives the execution of Batch/Flush tests.
     * It performs several operations in order:
     * - registration
     * - for continuous sensors it first ensures that the FIFO is filled
     *      - if events do not arrive on time, an assert will be triggered
     * - requests flush of sensor data
     * - waits for {@link SensorEventListener2#onFlushCompleted(Sensor)}
     *      - if the event does not arrive, an assert will be triggered
     */
    private class FlushExecutor implements TestSensorOperation.Executor {
        private final TestSensorEnvironment mEnvironment;
        private final int mEventCount;
        private final boolean mFlushWhileIdle;

        public FlushExecutor(TestSensorEnvironment environment, int eventCount,
                boolean flushWhileIdle) {
            mEnvironment = environment;
            mEventCount = eventCount;
            mFlushWhileIdle = flushWhileIdle;
        }

        /**
         * Consider only continuous mode sensors for testing register listener.
         *
         * For on-change sensors, we only use
         * {@link TestSensorManager#registerListener(TestSensorEventListener)} to associate the
         * listener with the sensor. So that {@link TestSensorManager#requestFlush()} can be
         * invoked on it.
         */
        @Override
        public void execute(TestSensorManager sensorManager, TestSensorEventListener listener)
                throws Exception {
            int sensorReportingMode = mEnvironment.getSensor().getReportingMode();
            try {
                CountDownLatch eventLatch = sensorManager.registerListener(listener, mEventCount);
                if (sensorReportingMode == Sensor.REPORTING_MODE_CONTINUOUS) {
                    listener.waitForEvents(eventLatch, mEventCount, true);
                }
                if (mFlushWhileIdle) {
                    SensorCtsHelper.makeMyPackageIdle();
                    sensorManager.assertFlushFail();
                } else {
                    CountDownLatch flushLatch = sensorManager.requestFlush();
                    listener.waitForFlushComplete(flushLatch, true);
                }
            } finally {
                sensorManager.unregisterListener();
                if (mFlushWhileIdle) {
                    SensorCtsHelper.makeMyPackageActive();
                }
            }
        }
    }

    private class NullTriggerEventListener extends TriggerEventListener {
        @Override
        public void onTrigger(TriggerEvent event) {}
    }

    private class NullSensorEventListener implements SensorEventListener {
        @Override
        public void onSensorChanged(SensorEvent event) {}

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {}
    }

}
