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 
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.concurrent.CountDownLatch;
30 import java.util.concurrent.TimeUnit;
31 
32 /**
33  * Checks Sensor Additional Information feature functionality.
34  */
35 public class SensorAdditionalInfoTest extends SensorTestCase {
36     private static final String TAG = "SensorAdditionalInfoTest";
37     private static final int ALLOWED_ADDITIONAL_INFO_DELIVER_SEC = 3;
38     private static final int REST_PERIOD_BEFORE_TEST_SEC = 3;
39 
40     private SensorManager mSensorManager;
41 
42     @Override
setUp()43     protected void setUp() throws Exception {
44         mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
45     }
46 
testSensorAdditionalInfo()47     public void testSensorAdditionalInfo() {
48         if (mSensorManager == null) {
49             return;
50         }
51 
52         List<Sensor> list = mSensorManager.getSensorList(Sensor.TYPE_ALL);
53         List<String> errors = new ArrayList<String>();
54         for (Sensor s : list) {
55             // skip vendor sensor types and those that do not support additional info
56             // one-shot and on-change sensors are not supported as well
57             if (s.getType() >= Sensor.TYPE_DEVICE_PRIVATE_BASE ||
58                     !s.isAdditionalInfoSupported() ||
59                     s.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT ||
60                     s.getReportingMode() == Sensor.REPORTING_MODE_ON_CHANGE) {
61                 continue;
62             }
63             try {
64                 runSensorAdditionalInfoTest(s);
65             } catch (AssertionError e) {
66                 errors.add("Sensor: " + s.getName() + ", error: " + e.getMessage());
67             }
68         }
69         if (errors.size() > 0) {
70             StringBuilder sb = new StringBuilder();
71             sb.append("Failed for following reasons: [");
72             int i = 0;
73             for (String error : errors) {
74                 sb.append(String.format("%d. %s; ", i++, error));
75             }
76             sb.append("]");
77             fail(sb.toString());
78         }
79     }
80 
runSensorAdditionalInfoTest(Sensor s)81     private void runSensorAdditionalInfoTest(Sensor s) throws AssertionError {
82         waitBeforeTestStarts();
83 
84         AdditionalInfoVerifier verifier = new AdditionalInfoVerifier(s);
85         verifier.reset(false /*flushPending*/);
86 
87         assertTrue(String.format("Register sensor listener for %s failed.", s.getName()),
88                 mSensorManager.registerListener(verifier, s, SensorManager.SENSOR_DELAY_NORMAL));
89         try {
90             assertTrue("Missing additional info at registration: (" + verifier.getState() + ")",
91                     verifier.verify());
92 
93             verifier.reset(true /*flushPending*/);
94             assertTrue("Flush sensor failed.", mSensorManager.flush(verifier));
95             assertTrue("Missing additional info after flushing: (" + verifier.getState() + ")",
96                     verifier.verify());
97         } finally {
98             mSensorManager.unregisterListener(verifier);
99         }
100     }
101 
waitBeforeTestStarts()102     private void waitBeforeTestStarts() {
103         // wait for sensor system to come to a rest after previous test to avoid flakiness.
104         try {
105             SensorCtsHelper.sleep(REST_PERIOD_BEFORE_TEST_SEC, TimeUnit.SECONDS);
106         } catch (InterruptedException e) {
107             Thread.currentThread().interrupt();
108         }
109     }
110 
111     private class AdditionalInfoVerifier extends SensorEventCallback {
112         private boolean mBeginFrame = false;
113         private boolean mEndFrame = false;
114         private boolean mFlushPending = false;
115         private CountDownLatch mDone;
116         private final Sensor mSensor;
117 
AdditionalInfoVerifier(Sensor s)118         public AdditionalInfoVerifier(Sensor s) {
119             mSensor = s;
120         }
121 
122         @Override
onFlushCompleted(Sensor sensor)123         public void onFlushCompleted(Sensor sensor) {
124             if (sensor == mSensor) {
125                 mFlushPending = false;
126             }
127         }
128 
129         @Override
onSensorAdditionalInfo(SensorAdditionalInfo info)130         public void onSensorAdditionalInfo(SensorAdditionalInfo info) {
131             if (info.sensor == mSensor && !mFlushPending) {
132                 if (info.type == SensorAdditionalInfo.TYPE_FRAME_BEGIN) {
133                     mBeginFrame = true;
134                 } else if (info.type == SensorAdditionalInfo.TYPE_FRAME_END && mBeginFrame) {
135                     mEndFrame = true;
136                     mDone.countDown();
137                 }
138             }
139         }
140 
reset(boolean flushPending)141         public void reset(boolean flushPending) {
142             mFlushPending = flushPending;
143             mBeginFrame = false;
144             mEndFrame = false;
145             mDone = new CountDownLatch(1);
146         }
147 
verify()148         public boolean verify() {
149             boolean ret;
150             try {
151                 ret = mDone.await(ALLOWED_ADDITIONAL_INFO_DELIVER_SEC, TimeUnit.SECONDS);
152             } catch (InterruptedException e) {
153                 ret = false;
154             }
155             return ret;
156         }
157 
getState()158         public String getState() {
159             return "fp=" + mFlushPending +", b=" + mBeginFrame + ", e=" + mEndFrame;
160         }
161     }
162 }
163 
164