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.Sensor;
22 import android.hardware.cts.helpers.SensorStats;
23 import android.hardware.cts.helpers.TestSensorEnvironment;
24 import android.hardware.cts.helpers.TestSensorEvent;
25 
26 import java.util.LinkedList;
27 import java.util.List;
28 
29 /**
30  * A {@link ISensorVerification} which verifies that all events are received in the correct order.
31  */
32 public class EventOrderingVerification extends AbstractSensorVerification {
33     public static final String PASSED_KEY = "event_out_of_order_passed";
34 
35     // Number of indices to print in assert message before truncating
36     private static final int TRUNCATE_MESSAGE_LENGTH = 3;
37 
38     private Long mMaxTimestamp = null;
39     private final List<IndexedEventPair> mOutOfOrderEvents = new LinkedList<IndexedEventPair>();
40     private TestSensorEvent mPreviousEvent = null;
41     private int mIndex = 0;
42 
43     /**
44      * Get the default {@link EventOrderingVerification} for a sensor.
45      *
46      * @param environment the test environment
47      * @return the verification or null if the verification does not apply to the sensor.
48      */
49     @SuppressWarnings("deprecation")
getDefault(TestSensorEnvironment environment)50     public static EventOrderingVerification getDefault(TestSensorEnvironment environment) {
51         int reportingMode = environment.getSensor().getReportingMode();
52         if (reportingMode == Sensor.REPORTING_MODE_ONE_SHOT)
53             return null;
54         return new EventOrderingVerification();
55     }
56 
57     /**
58      * Verify that the events are in the correct order.  Add {@value #PASSED_KEY},
59      * {@value SensorStats#EVENT_OUT_OF_ORDER_COUNT_KEY}, and
60      * {@value SensorStats#EVENT_OUT_OF_ORDER_POSITIONS_KEY} keys to {@link SensorStats}.
61      *
62      * @throws AssertionError if the verification failed.
63      */
64     @Override
verify(TestSensorEnvironment environment, SensorStats stats)65     public void verify(TestSensorEnvironment environment, SensorStats stats) {
66         verify(stats);
67     }
68 
69     /**
70      * Visible for unit tests only.
71      */
verify(SensorStats stats)72     void verify(SensorStats stats) {
73         final int count = mOutOfOrderEvents.size();
74         stats.addValue(PASSED_KEY, count == 0);
75         stats.addValue(SensorStats.EVENT_OUT_OF_ORDER_COUNT_KEY, count);
76         stats.addValue(
77                 SensorStats.EVENT_OUT_OF_ORDER_POSITIONS_KEY,
78                 getIndexArray(mOutOfOrderEvents));
79 
80         if (count > 0) {
81             StringBuilder sb = new StringBuilder();
82             sb.append(count).append(" events out of order: ");
83             for (int i = 0; i < Math.min(count, TRUNCATE_MESSAGE_LENGTH); i++) {
84                 IndexedEventPair info = mOutOfOrderEvents.get(i);
85                 sb.append(String.format("position=%d, previous_ts=%.2fms, current_ts=%.2fms",
86                             info.index, nanosToMillis(info.previousEvent.timestamp),
87                             nanosToMillis(info.event.timestamp)));
88             }
89             if (count > TRUNCATE_MESSAGE_LENGTH) {
90                 sb.append(count - TRUNCATE_MESSAGE_LENGTH).append(" more");
91             } else {
92                 // Delete the trailing "; "
93                 sb.delete(sb.length() - 2, sb.length());
94             }
95 
96             Assert.fail(sb.toString());
97         }
98     }
99 
100     /**
101      * {@inheritDoc}
102      */
103     @Override
clone()104     public EventOrderingVerification clone() {
105         return new EventOrderingVerification();
106     }
107 
108     /**
109      * {@inheritDoc}
110      */
111     @Override
addSensorEventInternal(TestSensorEvent event)112     protected void addSensorEventInternal(TestSensorEvent event) {
113         if (mPreviousEvent == null) {
114             mMaxTimestamp = event.timestamp;
115         } else {
116             if (event.timestamp <= mMaxTimestamp) {
117                 mOutOfOrderEvents.add(new IndexedEventPair(mIndex, event, mPreviousEvent));
118             } else {
119                 mMaxTimestamp = event.timestamp;
120             }
121         }
122 
123         mPreviousEvent = event;
124         mIndex++;
125     }
126 }
127