Home | History | Annotate | Download | only in cts
      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