您的位置:首页 > 移动开发 > Android开发

Android CTS Verifier Sensor Test Cases (7)

2016-09-21 14:35 585 查看
6. CTS Sensor Tests

CTS Sensor Tests 会测试 HAL 上报的 SensorList 结构体中所包含的信息和对这些 sensor 进行基本的操作是否符合 Android 要求。

SensorList 结构体定义见 sensor_t 下面看两个例子:

/* Accelerometer SensorList Structure */
{
// Sensor name
name: "Accelerometer",
// Vendor name
vendor: "Company Name",
// Sensor Version
version: 1.0,
// Sensor handle for HAL internal usage
handle: SENSORS_ACCELERATION_HANDLE,
// Sensor type for Android offical usage
type: SENSOR_TYPE_ACCELEROMETER,
// Maximum 4G range
maxRange: 4.0f * 9.805,
// Sensitivity = Range / Bitwidth
resolution: 4.0f * 9.805 / 2^16,
// Power consumption in mA from datasheet
power: 0.1f,
// Maximum Output data rate: 200Hz/5ms
minDelay: 5000,
// No hardware FIFO support
fifoReservedEventCount: 0,
// No hardware FIFO support
fifoMaxEventCount: 0,
// Sensor string
stringType: SENSOR_STRING_TYPE_ACCELEROMETER,
// no permission is required
requiredPermission: "",
// Minimum output data rate: 5Hz/200ms
maxDelay: 200000,
// report mode: continuous
flags: SENSOR_FLAG_CONTINUOUS_MODE,
reserved: {}
},
/* Step Counter Sensor structure */
{
name: "Step Counter",
vendor: "Company Name",
version: 1.0,
handle: SENSORS_STEP_COUNTER_HANDLE,
type: SENSOR_TYPE_STEP_COUNTER,
maxRange: 10000.0f,
resolution: 1.0f,
power: 2.03f,
minDelay: 0,
fifoReservedEventCount: 0,
fifoMaxEventCount: 0,
stringType: SENSOR_STRING_TYPE_STEP_COUNTER,
requiredPermission: "",
maxDelay: 1000000,
flags: SENSOR_FLAG_ON_CHANGE_MODE,
reserved: {}
},


CTS 会检查 SensorList 结构体里面各项的值是否符合 Android 定义。

private void assertSensorValues(Sensor sensor) {
/* range 必须是正数 */
assertTrue("Max range must be positive. Range=" + sensor.getMaximumRange()
+ " " + sensor.getName(), sensor.getMaximumRange() >= 0);
/* power 必须是正数 */
assertTrue("Max power must be positive. Power=" + sensor.getPower() + " " + sensor.getName(), sensor.getPower() >= 0);
/* resolution 必须是正数 */
assertTrue("Max resolution must be positive. Resolution=" + sensor.getResolution() + " " + sensor.getName(), sensor.getResolution() >= 0);
/* vendor name 不能个为空 */
assertNotNull("Vendor name must not be null " + sensor.getName(), sensor.getVendor());
/* Version 必须是正数 */
assertTrue("Version must be positive version=" + sensor.getVersion() + " " + sensor.getName(), sensor.getVersion() > 0);
int fifoMaxEventCount = sensor.getFifoMaxEventCount();
int fifoReservedEventCount = sensor.getFifoReservedEventCount();
/* fifoMaxEventCount 和 fifoReservedEventCount 必须大于或等于0,且fifoMaxEventCount 要大于或等于fifoReservedEventCount */
assertTrue(fifoMaxEventCount >= 0);
assertTrue(fifoReservedEventCount >= 0);
assertTrue(fifoReservedEventCount <= fifoMaxEventCount);
/* one shot类型的 sensor, fifoMaxEventCount 和 fifoReservedEventCount 都必须为0 */
if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
assertTrue("One shot sensors should have zero FIFO Size " + sensor.getName(),
sensor.getFifoMaxEventCount() == 0);
assertTrue("One shot sensors should have zero FIFO Size "  + sensor.getName(),
sensor.getFifoReservedEventCount() == 0);
}
}


public class SensorTest extends SensorTestCase {
private static final String TAG = "SensorTest";
/* 自定义的 sensor 类型不在 SensorTest 测试范围内 */
// Test only SDK defined sensors. Any sensors with type > 100 are ignored.
private static final int MAX_OFFICIAL_ANDROID_SENSOR_TYPE = 100;

...
/* 检查 Acceleromter 的 type */
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
boolean hasAccelerometer = getContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_SENSOR_ACCELEROMETER);
// accelerometer sensor is optional
if (hasAccelerometer) {
assertEquals(Sensor.TYPE_ACCELEROMETER, sensor.getType());
assertSensorValues(sensor);
} else {
assertNull(sensor);
}
/* 检查 Step Counter, Step Detector, Heart Rate, Magnetic Field, Orientation, Temperature  */
...

/* 检查 sensorlist 中所有的sensor 的结构体中的值是否合法 */
mSensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
public void testValuesForAllSensors() {
for (Sensor sensor : mSensorList) {
assertSensorValues(sensor);
e6ce
}
}

/* 有些 sensor 只有wakeup类型 */
// Some sensors like proximity, significant motion etc. are defined as wake-up sensors by
// default. Check if the wake-up flag is set correctly.
public void testWakeUpFlags() {
final int TYPE_WAKE_GESTURE = 23;
final int TYPE_GLANCE_GESTURE = 24;
final int TYPE_PICK_UP_GESTURE = 25;
/* 下面这几个sensor 的 flag 必须定义成 wakeup */
hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(Sensor.TYPE_SIGNIFICANT_MOTION));
hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_WAKE_GESTURE));
hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_GLANCE_GESTURE));
hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_PICK_UP_GESTURE));
List<Sensor> proximity_sensors = mSensorManager.getSensorList(Sensor.TYPE_PROXIMITY);
if (proximity_sensors.isEmpty()) return;
boolean hasWakeUpProximitySensor = false;
for (Sensor sensor : proximity_sensors) {
if (sensor.isWakeUpSensor()) {
hasWakeUpProximitySensor = true;
break;
}
}
assertTrue("No wake-up proximity sensors implemented", hasWakeUpProximitySensor);
}

/* 如果 flag 不是 wake up, 则不能是 wakeup sensor */
public void testGetDefaultSensorWithWakeUpFlag() {
// With wake-up flags set to false, the sensor returned should be a non wake-up sensor.
for (Sensor sensor : mSensorList) {
Sensor curr_sensor = mSensorManager.getDefaultSensor(sensor.getType(), false);
if (curr_sensor != null) {
assertFalse("getDefaultSensor wakeup=false returns a wake-up sensor" +
curr_sensor.getName(),
curr_sensor.isWakeUpSensor());
}
curr_sensor = mSensorManager.getDefaultSensor(sensor.getType(), true);
if (curr_sensor != null) {
assertTrue("getDefaultSensor wake-up returns non wake sensor" +
curr_sensor.getName(),
curr_sensor.isWakeUpSensor());
}
}
}


具体的测试项:

1) testBatchAndFlush

public void testBatchAndFlush() throws Exception {
// TODO - replace this constant once method to do so is made available
final int SENSOR_TYPE_DEVICE_PRIVATE_BASE = 0x10000;
SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
ArrayList<Throwable> errorsFound = new ArrayList<>();
/* 遍历测试 SensorList 中所有的 sensor */
for (Sensor sensor : mSensorList) {
if (sensor.getType() < SENSOR_TYPE_DEVICE_PRIVATE_BASE) {
verifyRegisterListenerCallFlush(sensor, null /* handler */, errorsFound);
}
}
assertOnErrors(errorsFound);
}
...
private void verifyRegisterListenerCallFlush()
throws InterruptedException {
if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
/* 如果 sensor 是 one shot 类型,则不支持flush,返回成功 */
return;
}
...
测试实际执行代码:
/* 注册 listener,只检测 continuous 类型的 sensor:
* 检测FIFO是否填充,如果规定时间内没有收到数据,assert;如果数据正常,再请求 flush;如果等待 flush complete 超时,也会assert */
if (sensorReportingMode == Sensor.REPORTING_MODE_CONTINUOUS) {
listener.waitForEvents(eventLatch, mEventCount, true);
}
CountDownLatch flushLatch = sensorManager.requestFlush();
listener.waitForFlushComplete(flushLatch, true);


2) testBatchAndFlushWithHandler

跟1) testBatchAndFlush 不同之处是它有 hander
/* 看下面代码,有 hander 就会申请一个 wakeLock,既这个测试中系统不会睡眠 */
public TestSensorEventListener(TestSensorEnvironment environment) {
this(environment, null /* handler */);
}
public TestSensorEventListener(TestSensorEnvironment environment, Handler handler) {
mEnvironment = environment;
mHandler = handler;
PowerManager pm = (PowerManager) environment.getContext().getSystemService(
Context.POWER_SERVICE);
mTestSensorEventListenerWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"TestSensorEventListenerWakeLock");
}


3)testBatchAndFlushWithMultipleSensors

跟前两个比,多了个并行操作。同时测试多个 sensor 的 BatchAndFlush
ParallelSensorOperation parallelSensorOperation = new ParallelSensorOperation();


4) testLegacySensorOperations

测试 Accelerometer , Magnetic Field, Orientation sensor 是否符合 Android 定义。


5) testCancelTriggerWithNonTriggerSensor, testGetDefaultSensorWithWakeUpFlag, testRegisterWithTriggerSensor, testRegisterTwiceWithSameSensor, testRequestTriggerWithNonTriggerSensor,testSensorStringTypes, 这个几个测试项一般不容易报错,如果报错,检查你的sensorList结构体内容是否按照 android 定义写的。

6) testSensorOperations

测试 Accelerometer, Step Counter, Step Detector, Heart Reate, Magnetic Field, Orientation, Temperature 是否符合 Android 定义。

有一种情况会报错,HAL少报了前面提到的几个 sensor 的某个, 而测试环境中却认为有这个 sensor。检查 HAL 的实现和测试环境的要求不一致在哪里。



7)testSensorTimeStamps

CTS Sensor Test 里最重要的,也是最容易出错的一项测试。

public void testSensorTimeStamps() throws Exception {
    ArrayList<Throwable> errorsFound = new ArrayList<>();
 for (Sensor sensor : mSensorList) {
// test both continuous and batching mode sensors
verifyLongActivation(sensor, 0 /* maxReportLatencyUs */, errorsFound);
verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10), errorsFound);
}
assertOnErrors(errorsFound);
}
/* 包含三项时间戳测试:数据时间间隔 EventGapVerification, 顺序 EventOrderingVerification, 同步EventTimestampSynchronizationVer*/
private void verifyLongActivation(
 operation.addVerification(EventGapVerification.getDefault(environment));
operation.addVerification(EventOrderingVerification.getDefault(environment));
   operation.addVerification(EventTimestampSynchronizationVerification.getDefault(environment));


如果数据 Output Data Rate不稳定,某两个数据时间戳之间的 gap 大于要求,则报错:

// Number of event gaps to tolerate is 2% of total number of events received rounded up to next

// integer or 20, whichever is smaller.

private static final int EVENT_GAP_THRESHOLD_MAX = 20;

private static final double EVENT_GAP_TOLERANCE = 0.02;

EventOrderingVerification

检查 HAL 上报的数据顺序是否错乱,通过验证时间戳是否有回调。

void verify(SensorStats stats) {
final int count = mOutOfOrderEvents.size();
stats.addValue(PASSED_KEY, count == 0);
stats.addValue(SensorStats.EVENT_OUT_OF_ORDER_COUNT_KEY, count);
stats.addValue(
SensorStats.EVENT_OUT_OF_ORDER_POSITIONS_KEY,
getIndexArray(mOutOfOrderEvents));
if (count > 0) {
StringBuilder sb = new StringBuilder();
sb.append(count).append(" events out of order: ");
for (int i = 0; i < Math.min(count, TRUNCATE_MESSAGE_LENGTH); i++) {
IndexedEventPair info = mOutOfOrderEvents.get(i);
sb.append(String.format("position=%d, previous_ts=%.2fms, current_ts=%.2fms",
info.index, nanosToMillis(info.previousEvent.timestamp),
nanosToMillis(info.event.timestamp)));
}
if (count > TRUNCATE_MESSAGE_LENGTH) {
sb.append(count - TRUNCATE_MESSAGE_LENGTH).append(" more");
} else {
// Delete the trailing "; "
sb.delete(sb.length() - 2, sb.length());
}
Assert.fail(sb.toString());
}
}


EventTimestampSynchronizationVerication

时间戳同步验证,HAL 上报数据自带的时间戳跟系统收到数据时的时间戳之间的differ是否在规定范围内

TestSensorEvent event = mCollectedEvents.get(i);
long eventTimestampNs = event.timestamp;
long receivedTimestampNs = event.receivedTimestamp;
long upperThresholdNs = receivedTimestampNs;
long lowerThresholdNs = receivedTimestampNs - mMaximumSynchronizationErrorNs
- mExpectedSyncLatencyNs;
if (eventTimestampNs < lowerThresholdNs || eventTimestampNs > upperThresholdNs) {
if (failures.size() < TRUNCATE_MESSAGE_LENGTH) {
builder.append("position=").append(i);
builder.append(", timestamp=").append(String.format("%.2fms",
nanosToMillis(eventTimestampNs)));
builder.append(", expected=[").append(String.format("%.2fms",
nanosToMillis(lowerThresholdNs)));
builder.append(", ").append(String.format("%.2f]ms; ",
nanosToMillis(upperThresholdNs)));
}
failures.add(new IndexedEvent(i, event));
}
}


总结:

这个测试项很容易出错,HAL/Driver 开发者需要确保

1)SensorList的准确性;

2)data quality: ODR 稳定,顺序,同步;

SensorTest.java

EventGapVerification.java

EventOrderingVerification.java

EventTimestampSynchronizationVerification.java
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息