1 /* 2 * Copyright (C) 2016 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; 18 19 import android.content.Context; 20 import android.hardware.Sensor; 21 import android.hardware.SensorAdditionalInfo; 22 import android.hardware.SensorEventCallback; 23 import android.hardware.SensorManager; 24 import android.hardware.cts.helpers.SensorCtsHelper; 25 import android.util.Log; 26 import android.content.pm.PackageManager; 27 28 import java.lang.Math; 29 import java.util.ArrayList; 30 import java.util.List; 31 import java.util.concurrent.CountDownLatch; 32 import java.util.concurrent.TimeUnit; 33 34 /** 35 * Checks Sensor Additional Information feature functionality. 36 */ 37 public class SensorAdditionalInfoTest extends SensorTestCase { 38 private static final String TAG = "SensorAdditionalInfoTest"; 39 private static final int ALLOWED_ADDITIONAL_INFO_DELIVER_SEC = 3; 40 private static final int REST_PERIOD_BEFORE_TEST_SEC = 3; 41 private static final double EPSILON = 1E-6; 42 43 private SensorManager mSensorManager; 44 45 @Override 46 protected void setUp() throws Exception { 47 mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); 48 } 49 50 public void testSensorAdditionalInfo() { 51 if (mSensorManager == null) { 52 return; 53 } 54 55 List<Sensor> list = mSensorManager.getSensorList(Sensor.TYPE_ALL); 56 List<String> errors = new ArrayList<String>(); 57 for (Sensor s : list) { 58 // skip vendor sensor types, one-shot and on-change sensors. 59 if (s.getType() >= Sensor.TYPE_DEVICE_PRIVATE_BASE || 60 s.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT || 61 s.getReportingMode() == Sensor.REPORTING_MODE_ON_CHANGE) { 62 continue; 63 } 64 65 if (!s.isAdditionalInfoSupported()) { 66 // check SensorAdditionalInfo is supported for Automotive sensors. 67 if (getContext().getPackageManager().hasSystemFeature( 68 PackageManager.FEATURE_AUTOMOTIVE)) { 69 errors.add("Sensor: " + s.getName() + 70 ", error: AdditionalSensorInfo not supported for Automotive sensor."); 71 } 72 continue; 73 } 74 75 try { 76 runSensorAdditionalInfoTest(s); 77 } catch (AssertionError e) { 78 errors.add("Sensor: " + s.getName() + ", error: " + e.getMessage()); 79 } 80 } 81 if (errors.size() > 0) { 82 StringBuilder sb = new StringBuilder(); 83 sb.append("Failed for following reasons: ["); 84 int i = 0; 85 for (String error : errors) { 86 sb.append(String.format("%d. %s; ", i++, error)); 87 } 88 sb.append("]"); 89 fail(sb.toString()); 90 } 91 } 92 93 private void runSensorAdditionalInfoTest(Sensor s) throws AssertionError { 94 waitBeforeTestStarts(); 95 96 AdditionalInfoVerifier verifier = new AdditionalInfoVerifier(s); 97 verifier.reset(false /*flushPending*/); 98 99 assertTrue(String.format("Register sensor listener for %s failed.", s.getName()), 100 mSensorManager.registerListener(verifier, s, SensorManager.SENSOR_DELAY_NORMAL)); 101 try { 102 assertTrue("Missing additional info at registration: (" + verifier.getState() + ")", 103 verifier.verify()); 104 105 assertFalse("Duplicate TYPE_FRAME_BEGIN at: (" + 106 verifier.getState() + ")", verifier.beginFrameDuplicate()); 107 108 if (verifier.internalTemperature()) { 109 assertFalse("Duplicate TYPE_INTERNAL_TEMPERATURE at: (" + 110 verifier.getState() + ")", verifier.internalTemperatureDuplicate()); 111 } 112 113 if (verifier.sampling()) { 114 assertFalse("Duplicate TYPE_SAMPLING_TEMPERATURE at: (" + 115 verifier.getState() + ")", verifier.samplingDuplicate()); 116 } 117 118 // verify TYPE_SENSOR_PLACEMENT for Automotive. 119 if (getContext().getPackageManager(). 120 hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { 121 assertTrue("Missing TYPE_SENSOR_PLACEMENT at: (" + verifier.getState() + ")", 122 verifier.sensorPlacement()); 123 124 } 125 if(verifier.sensorPlacement()) { 126 assertFalse("Duplicate TYPE_SENSOR_PLACEMENT at: (" + 127 verifier.getState() + ")", verifier.sensorPlacementDuplicate()); 128 129 assertTrue("Incorrect size of TYPE_SENSOR_PLACEMENT at: (" + 130 verifier.getState() + ")", verifier.sensorPlacementSizeValid()); 131 132 if (verifier.sensorPlacementSizeValid()) { 133 assertTrue("Incorrect rotation matrix of TYPE_SENSOR_PLACEMENT at: (" + 134 verifier.getState() + ")", verifier.sensorPlacementRotationValid()); 135 } 136 } 137 138 if (verifier.untrackedDelay()) { 139 assertFalse("Duplicate TYPE_UNTRACKED_DELAY at: (" + 140 verifier.getState() + ")", verifier.untrackedDelayDuplicate()); 141 } 142 143 if (verifier.vec3Calibration()) { 144 assertFalse("Duplicate TYPE_VEC3_CALIBRATION at: (" + 145 verifier.getState() + ")", verifier.vec3CalibrationDuplicate()); 146 } 147 148 verifier.reset(true /*flushPending*/); 149 assertTrue("Flush sensor failed.", mSensorManager.flush(verifier)); 150 assertTrue("Missing additional info after flushing: (" + verifier.getState() + ")", 151 verifier.verify()); 152 } finally { 153 mSensorManager.unregisterListener(verifier); 154 } 155 } 156 157 private void waitBeforeTestStarts() { 158 // wait for sensor system to come to a rest after previous test to avoid flakiness. 159 try { 160 SensorCtsHelper.sleep(REST_PERIOD_BEFORE_TEST_SEC, TimeUnit.SECONDS); 161 } catch (InterruptedException e) { 162 Thread.currentThread().interrupt(); 163 } 164 } 165 166 private class AdditionalInfoVerifier extends SensorEventCallback { 167 private boolean mBeginFrame = false; 168 private boolean mBeginFrameDuplicate = false; 169 private boolean mEndFrame = false; 170 private boolean mFlushPending = false; 171 private boolean mInternalTemperature = false; 172 private boolean mInternalTemperatureDuplicate = false; 173 private boolean mSampling = false; 174 private boolean mSamplingDuplicate = false; 175 private boolean mSensorPlacement = false; 176 private boolean mSensorPlacementDuplicate = false; 177 private boolean mIsSensorPlacementSizeValid = false; 178 private boolean mIsSensorPlacementRotationValid = false; 179 private boolean mUntrackedDelay = false; 180 private boolean mUntrackedDelayDuplicate = false; 181 private boolean mVec3Calibration = false; 182 private boolean mVec3CalibrationDuplicate = false; 183 private CountDownLatch mDone; 184 private final Sensor mSensor; 185 186 public AdditionalInfoVerifier(Sensor s) { 187 mSensor = s; 188 } 189 190 @Override 191 public void onFlushCompleted(Sensor sensor) { 192 if (sensor == mSensor) { 193 mFlushPending = false; 194 } 195 } 196 197 @Override 198 public void onSensorAdditionalInfo(SensorAdditionalInfo info) { 199 if (info.sensor == mSensor && !mFlushPending) { 200 if (info.type == SensorAdditionalInfo.TYPE_FRAME_BEGIN) { 201 if (mBeginFrame) { 202 mBeginFrameDuplicate = true; 203 return; 204 } 205 mBeginFrame = true; 206 } else if (mBeginFrame && 207 info.type == SensorAdditionalInfo.TYPE_INTERNAL_TEMPERATURE) { 208 if (mInternalTemperature) { 209 mInternalTemperatureDuplicate = true; 210 return; 211 } 212 mInternalTemperature = true; 213 } else if (mBeginFrame && info.type == SensorAdditionalInfo.TYPE_SAMPLING) { 214 if (mSampling) { 215 mSamplingDuplicate = true; 216 return; 217 } 218 mSampling = true; 219 } else if (mBeginFrame && info.type == SensorAdditionalInfo.TYPE_SENSOR_PLACEMENT) { 220 if (mSensorPlacement) { 221 mSensorPlacementDuplicate = true; 222 return; 223 } 224 mSensorPlacement = true; 225 verifySensorPlacementData(info.floatValues); 226 } else if (mBeginFrame && info.type == SensorAdditionalInfo.TYPE_UNTRACKED_DELAY) { 227 if (mUntrackedDelay) { 228 mUntrackedDelayDuplicate = true; 229 return; 230 } 231 mUntrackedDelay = true; 232 } else if (mBeginFrame && info.type == SensorAdditionalInfo.TYPE_VEC3_CALIBRATION) { 233 if (mVec3Calibration) { 234 mVec3CalibrationDuplicate = true; 235 return; 236 } 237 mVec3Calibration = true; 238 } else if (info.type == SensorAdditionalInfo.TYPE_FRAME_END && mBeginFrame) { 239 mEndFrame = true; 240 mDone.countDown(); 241 } 242 } 243 } 244 245 public void reset(boolean flushPending) { 246 mFlushPending = flushPending; 247 mBeginFrame = false; 248 mEndFrame = false; 249 mSensorPlacement = false; 250 mDone = new CountDownLatch(1); 251 } 252 253 public boolean verify() { 254 boolean ret; 255 try { 256 ret = mDone.await(ALLOWED_ADDITIONAL_INFO_DELIVER_SEC, TimeUnit.SECONDS); 257 } catch (InterruptedException e) { 258 ret = false; 259 } 260 return ret; 261 } 262 263 public String getState() { 264 return "fp=" + mFlushPending +", b=" + mBeginFrame + ", e=" + mEndFrame; 265 } 266 267 // Checks sensor placement data length and determinant of rotation matrix is 1. 268 private void verifySensorPlacementData(float[] m) { 269 if(m.length != 12) { 270 mIsSensorPlacementSizeValid = false; 271 return; 272 } 273 mIsSensorPlacementSizeValid = true; 274 double determinant = m[0] * (m[5] * m[10] - m[6] * m[9] ) - 275 m[1] * (m[4] * m[10] - m[6] * m[8] ) + 276 m[2] * (m[4] * m[9] - m[5] * m[8] ); 277 mIsSensorPlacementRotationValid = (Math.abs(determinant - 1) < EPSILON); 278 } 279 280 public boolean beginFrameDuplicate() { 281 return mBeginFrameDuplicate; 282 } 283 284 public boolean internalTemperature() { 285 return mInternalTemperature; 286 } 287 public boolean internalTemperatureDuplicate() { 288 return mInternalTemperatureDuplicate; 289 } 290 291 public boolean sampling() { 292 return mSampling; 293 } 294 public boolean samplingDuplicate() { 295 return mSamplingDuplicate; 296 } 297 298 public boolean sensorPlacement() { 299 return mSensorPlacement; 300 } 301 public boolean sensorPlacementDuplicate() { 302 return mSensorPlacementDuplicate; 303 } 304 public boolean sensorPlacementSizeValid() { 305 return mIsSensorPlacementSizeValid; 306 } 307 public boolean sensorPlacementRotationValid() { 308 return mIsSensorPlacementRotationValid; 309 } 310 311 public boolean untrackedDelay() { 312 return mUntrackedDelay; 313 } 314 public boolean untrackedDelayDuplicate() { 315 return mUntrackedDelayDuplicate; 316 } 317 318 public boolean vec3Calibration() { 319 return mVec3Calibration; 320 } 321 public boolean vec3CalibrationDuplicate() { 322 return mVec3CalibrationDuplicate; 323 } 324 } 325 } 326