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