Home | History | Annotate | Download | only in sensorverification
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 
     17 package android.hardware.cts.helpers.sensorverification;
     18 
     19 import junit.framework.Assert;
     20 
     21 import android.hardware.SensorEvent;
     22 import android.hardware.cts.helpers.SensorStats;
     23 import android.hardware.cts.helpers.TestSensorEnvironment;
     24 import android.hardware.cts.helpers.TestSensorEvent;
     25 import android.os.SystemClock;
     26 
     27 import java.util.ArrayList;
     28 import java.util.List;
     29 import java.util.concurrent.TimeUnit;
     30 
     31 /**
     32  * A {@link ISensorVerification} which verifies that the timestamp of the {@link SensorEvent} is
     33  * synchronized with {@link SystemClock#elapsedRealtimeNanos()}, based on a given threshold.
     34  */
     35 public class EventTimestampSynchronizationVerification extends AbstractSensorVerification {
     36     public static final String PASSED_KEY = "timestamp_synchronization_passed";
     37 
     38     // number of indices to print in assertion message before truncating
     39     private static final int TRUNCATE_MESSAGE_LENGTH = 3;
     40 
     41     private static final long DEFAULT_THRESHOLD_NS = TimeUnit.MILLISECONDS.toNanos(500);
     42 
     43     private final ArrayList<TestSensorEvent> mCollectedEvents = new ArrayList<TestSensorEvent>();
     44 
     45     private final long mMaximumSynchronizationErrorNs;
     46     private final long mReportLatencyNs;
     47 
     48     /**
     49      * Constructs an instance of {@link EventTimestampSynchronizationVerification}.
     50      *
     51      * @param maximumSynchronizationErrorNs The valid threshold for timestamp synchronization.
     52      * @param reportLatencyNs The latency on which batching events are received
     53      */
     54     public EventTimestampSynchronizationVerification(
     55             long maximumSynchronizationErrorNs,
     56             long reportLatencyNs) {
     57         mMaximumSynchronizationErrorNs = maximumSynchronizationErrorNs;
     58         mReportLatencyNs = reportLatencyNs;
     59     }
     60 
     61     /**
     62      * Gets a default {@link EventTimestampSynchronizationVerification}.
     63      *
     64      * @param environment The test environment
     65      * @return The verification or null if the verification is not supported in the given
     66      *         environment.
     67      */
     68     public static EventTimestampSynchronizationVerification getDefault(
     69             TestSensorEnvironment environment) {
     70         int reportLatencyUs = environment.getMaxReportLatencyUs();
     71         int fifoMaxEventCount = environment.getSensor().getFifoMaxEventCount();
     72         if (fifoMaxEventCount > 0) {
     73             int fifoBasedReportLatencyUs =
     74                     fifoMaxEventCount * environment.getMaximumExpectedSamplingPeriodUs();
     75             reportLatencyUs = Math.min(reportLatencyUs, fifoBasedReportLatencyUs);
     76 
     77         }
     78         long reportLatencyNs = TimeUnit.MICROSECONDS.toNanos(reportLatencyUs);
     79         return new EventTimestampSynchronizationVerification(DEFAULT_THRESHOLD_NS, reportLatencyNs);
     80     }
     81 
     82     @Override
     83     public void verify(TestSensorEnvironment environment, SensorStats stats) {
     84         StringBuilder errorMessageBuilder =
     85                 new StringBuilder(" event timestamp synchronization failures: ");
     86         List<IndexedEvent> failures = verifyTimestampSynchronization(errorMessageBuilder);
     87 
     88         int failuresCount = failures.size();
     89         stats.addValue(SensorStats.EVENT_TIME_SYNCHRONIZATION_COUNT_KEY, failuresCount);
     90         stats.addValue(
     91                 SensorStats.EVENT_TIME_SYNCHRONIZATION_POSITIONS_KEY,
     92                 getIndexArray(failures));
     93 
     94         boolean success = failures.isEmpty();
     95         stats.addValue(PASSED_KEY, success);
     96         errorMessageBuilder.insert(0, failuresCount);
     97         Assert.assertTrue(errorMessageBuilder.toString(), success);
     98     }
     99 
    100     /**
    101      * {@inheritDoc}
    102      */
    103     @Override
    104     public EventTimestampSynchronizationVerification clone() {
    105         return new EventTimestampSynchronizationVerification(
    106                 mMaximumSynchronizationErrorNs,
    107                 mReportLatencyNs);
    108     }
    109 
    110     /**
    111      * {@inheritDoc}
    112      */
    113     @Override
    114     protected void addSensorEventInternal(TestSensorEvent event) {
    115         mCollectedEvents.add(event);
    116     }
    117 
    118     /**
    119      * Verifies timestamp synchronization for all sensor events.
    120      * The verification accounts for a lower and upper threshold, such thresholds are adjusted for
    121      * batching cases.
    122      *
    123      * @param builder A string builder to store error messaged found in the collected sensor events.
    124      * @return A list of events tha failed the verification.
    125      */
    126     private List<IndexedEvent> verifyTimestampSynchronization(StringBuilder builder) {
    127         int collectedEventsCount = mCollectedEvents.size();
    128         ArrayList<IndexedEvent> failures = new ArrayList<IndexedEvent>();
    129 
    130         for (int i = 0; i < collectedEventsCount; ++i) {
    131             TestSensorEvent event = mCollectedEvents.get(i);
    132             long eventTimestampNs = event.timestamp;
    133             long receivedTimestampNs = event.receivedTimestamp;
    134             long upperThresholdNs = receivedTimestampNs;
    135             long lowerThresholdNs = receivedTimestampNs - mMaximumSynchronizationErrorNs
    136                     - mReportLatencyNs;
    137 
    138             if (eventTimestampNs < lowerThresholdNs || eventTimestampNs > upperThresholdNs) {
    139                 if (failures.size() < TRUNCATE_MESSAGE_LENGTH) {
    140                     builder.append("position=").append(i);
    141                     builder.append(", timestamp=").append(eventTimestampNs).append("ns");
    142                     builder.append(", expected=[").append(lowerThresholdNs);
    143                     builder.append(", ").append(upperThresholdNs).append("]ns; ");
    144                 }
    145                 failures.add(new IndexedEvent(i, event));
    146             }
    147         }
    148         if (failures.size() >= TRUNCATE_MESSAGE_LENGTH) {
    149             builder.append("more; ");
    150         }
    151         return failures;
    152     }
    153 }
    154