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 com.android.compatibility.common.util.ApiLevelUtil; 22 23 import android.os.Build; 24 import android.hardware.Sensor; 25 import android.hardware.SensorEvent; 26 import android.hardware.cts.helpers.SensorStats; 27 import android.hardware.cts.helpers.TestSensorEnvironment; 28 import android.hardware.cts.helpers.TestSensorEvent; 29 import android.os.SystemClock; 30 31 import java.util.concurrent.TimeUnit; 32 33 /** 34 * A {@link ISensorVerification} which verifies if the collected sensor events have any obvious 35 * problems, such as no sample, wrong sensor type, etc. 36 */ 37 public class EventBasicVerification extends AbstractSensorVerification { 38 39 public static final String PASSED_KEY = "event_basic_passed"; 40 // allowed time from registration to sensor start sampling 41 private static final long ALLOWED_SENSOR_START_DELAY_US = 42 TimeUnit.MILLISECONDS.toMicros(1000); 43 44 // allowed time for entire sensor system to send sample to test app 45 private static final long ALLOWED_SENSOR_EVENT_LATENCY_US = 46 TimeUnit.MILLISECONDS.toMicros(1000); 47 48 // mercy added for recently added test. remove this mercy factor for next letter release. 49 private final float NUM_EVENT_MERCY_FACTOR; // 0~1, 0 means most strict 50 51 private final long mExpectedMinNumEvent; 52 private final Object mSensor; 53 private long mNumEvent; 54 private boolean mWrongSensorObserved; 55 56 /** 57 * Constructs an instance of {@link EventBasicVerification}. 58 * 59 * @param maximumSynchronizationErrorNs The valid threshold for timestamp synchronization. 60 * @param reportLatencyNs The latency on which batching events are received 61 */ 62 public EventBasicVerification( 63 long expectedMinNumEvent, 64 Sensor sensor) { 65 mExpectedMinNumEvent = expectedMinNumEvent; 66 mSensor = sensor; 67 68 mNumEvent = 0; 69 mWrongSensorObserved = false; 70 71 if (ApiLevelUtil.isAfter(Build.VERSION_CODES.M)) { 72 NUM_EVENT_MERCY_FACTOR = 0; 73 } else { 74 NUM_EVENT_MERCY_FACTOR = 0.3f; 75 } 76 } 77 78 /** 79 * Gets a default {@link EventBasicVerification}. 80 * 81 * @param environment The test environment 82 * @return The verification or null if the verification is not supported in the given 83 * environment. 84 */ 85 public static EventBasicVerification getDefault( 86 TestSensorEnvironment environment, 87 long testDurationUs) { 88 89 // The calculation is still OK if sampleUs is not the actual sensor hardware 90 // sample period since the actual sample period by definition only goes smaller, which 91 // result in more samples. 92 long sampleUs = environment.getExpectedSamplingPeriodUs(); 93 94 long askedBatchUs = environment.getMaxReportLatencyUs(); 95 96 long reservedFifoUs = sampleUs * environment.getSensor().getFifoReservedEventCount(); //>=0 97 98 // max() prevent loop-hole if HAL specify smaller max fifo than reserved fifo. 99 long maximumFifoUs = Math.max( 100 sampleUs * environment.getSensor().getFifoMaxEventCount(), reservedFifoUs); //>=0 101 102 long effectiveDurationUs = Math.max(testDurationUs - 103 Math.max(ALLOWED_SENSOR_START_DELAY_US, environment.getAllowedSensorStartDelay()) - 104 ALLOWED_SENSOR_EVENT_LATENCY_US, 0); 105 106 boolean isSingleSensorTest = !environment.isIntegrationTest(); 107 108 long expectedMinUs; 109 if (isSingleSensorTest) { 110 // When the sensor under test is the only one active, max fifo size is assumed to be 111 // available. 112 long expectedBatchUs = Math.min(maximumFifoUs, askedBatchUs); 113 if (expectedBatchUs > 0) { 114 // This sensor should be running in batching mode. 115 expectedMinUs = 116 effectiveDurationUs / expectedBatchUs * expectedBatchUs 117 - expectedBatchUs / 5; 118 } else { 119 // streaming, allow actual rate to be as slow as 80% of the asked rate. 120 expectedMinUs = effectiveDurationUs * 4 / 5; 121 } 122 } else { 123 // More convoluted case. Batch size can vary from reserved fifo length to max fifo size. 124 long minBatchUs = Math.min(reservedFifoUs, askedBatchUs); 125 long maxBatchUs = Math.min(maximumFifoUs, askedBatchUs); 126 127 // The worst scenario happens when the sensor batch time being just above half of the 128 // test time, then the test can only receive one batch which halves the expected number 129 // of samples. The expected number of samples received have a lower bound like the 130 // figure below. 131 // 132 // expected samples 133 // ^ 134 // | ______ 135 // |\ / 136 // | \ / 137 // | \ / 138 // | \ / 139 // | \ / 140 // | \ / 141 // | \/ 142 // | 143 // | 144 // | 145 // | 146 // +------------+-----------+-------> actual batch size in time 147 // 0 1/2*testDuration testDuration 148 // 149 long worstBatchUs = effectiveDurationUs / 2 + 1; 150 if ((minBatchUs > worstBatchUs) == (maxBatchUs > worstBatchUs)) { 151 // same side 152 double ratio = Math.min(Math.abs(worstBatchUs - minBatchUs), 153 Math.abs(worstBatchUs - maxBatchUs)) / (double)worstBatchUs; 154 expectedMinUs = (long)((ratio + 1) / 2 * testDurationUs) * 4 / 5; 155 } else { 156 // the worst case is possible 157 expectedMinUs = worstBatchUs * 4 / 5; 158 } 159 } 160 long expectedMinNumEvent = expectedMinUs/sampleUs; 161 162 return new EventBasicVerification(expectedMinNumEvent, environment.getSensor()); 163 } 164 165 @Override 166 public void verify(TestSensorEnvironment environment, SensorStats stats) { 167 verify(stats); 168 } 169 170 /* visible to unit test */ 171 void verify(SensorStats stats) { 172 173 stats.addValue(SensorStats.EVENT_COUNT_KEY, mNumEvent); 174 stats.addValue(SensorStats.EVENT_COUNT_EXPECTED_KEY, mExpectedMinNumEvent); 175 stats.addValue(SensorStats.WRONG_SENSOR_KEY, mWrongSensorObserved); 176 177 boolean enoughSample = mNumEvent >= mExpectedMinNumEvent * ( 1 - NUM_EVENT_MERCY_FACTOR ); 178 boolean noWrongSensor = !mWrongSensorObserved; 179 180 boolean success = enoughSample && noWrongSensor; 181 stats.addValue(PASSED_KEY, success); 182 183 if (!success) { 184 Assert.fail(String.format("Failed due to (%s%s)", 185 enoughSample?"":"insufficient events " + mNumEvent + "/" + 186 mExpectedMinNumEvent + ", ", 187 noWrongSensor?"":"wrong sensor observed, ")); 188 } 189 } 190 191 /** 192 * {@inheritDoc} 193 */ 194 @Override 195 public EventBasicVerification clone() { 196 return new EventBasicVerification( mExpectedMinNumEvent, (Sensor)mSensor ); 197 } 198 199 /** 200 * {@inheritDoc} 201 */ 202 @Override 203 protected void addSensorEventInternal(TestSensorEvent event) { 204 if (event.sensor == mSensor) { 205 ++mNumEvent; 206 } else { 207 mWrongSensorObserved = true; 208 } 209 } 210 211 } 212