Merge "Add latching threshold for ThresholdSensorImpl" into rvc-d1-dev am: d4fd553c18

Change-Id: I4801d2ad1b79e05af0f4f159ce1066a25f86b291
This commit is contained in:
Dave Mankoff
2020-04-29 21:17:42 +00:00
committed by Automerger Merge Worker
4 changed files with 124 additions and 13 deletions

View File

@@ -205,14 +205,26 @@
far break points. A sensor value less than this is considered "near". -->
<item name="proximity_sensor_threshold" translatable="false" format="float" type="dimen"></item>
<!-- If using proximity_sensor_type, specifies a threshold value to distinguish near and
far break points. A sensor value more than this is considered "far". If not set,
proximity_sensor_threshold is used. This allows one to implement a latching mechanism for
noisy sensors. -->
<item name="proximity_sensor_threshold_latch" translatable="false" format="float" type="dimen"></item>
<!-- Override value to use for proximity sensor as confirmation for proximity_sensor_type. -->
<string name="proximity_sensor_secondary_type" translatable="false"></string>
<!-- If using proximity_sensor_confirmation_type, specifies a threshold value to distinguish
<!-- If using proximity_sensor_secondary_type, specifies a threshold value to distinguish
near and far break points. A sensor value less than this is considered "near". -->
<item name="proximity_sensor_secondary_threshold" translatable="false" format="float"
type="dimen"></item>
<!-- If using proximity_sensor_secondary_type, specifies a threshold value to distinguish near and
far break points. A sensor value more than this is considered "far". If not set,
proximity_sensor_secondary_threshold is used. This allows one to implement a latching
mechanism for noisy sensors. -->
<item name="proximity_sensor_secondary_threshold_latch" translatable="false" format="float" type="dimen"></item>
<!-- Doze: pulse parameter - how long does it take to fade in? -->
<integer name="doze_pulse_duration_in">130</integer>

View File

@@ -38,6 +38,7 @@ public class SensorModule {
.setSensorDelay(SensorManager.SENSOR_DELAY_NORMAL)
.setSensorResourceId(R.string.proximity_sensor_type)
.setThresholdResourceId(R.dimen.proximity_sensor_threshold)
.setThresholdLatchResourceId(R.dimen.proximity_sensor_threshold_latch)
.build();
} catch (IllegalStateException e) {
Sensor defaultSensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
@@ -56,6 +57,7 @@ public class SensorModule {
return thresholdSensorBuilder
.setSensorResourceId(R.string.proximity_sensor_secondary_type)
.setThresholdResourceId(R.dimen.proximity_sensor_secondary_threshold)
.setThresholdLatchResourceId(R.dimen.proximity_sensor_secondary_threshold_latch)
.build();
} catch (IllegalStateException e) {
return thresholdSensorBuilder.setSensor(null).setThresholdValue(0).build();

View File

@@ -44,14 +44,16 @@ class ThresholdSensorImpl implements ThresholdSensor {
private List<Listener> mListeners = new ArrayList<>();
private Boolean mLastBelow;
private String mTag;
private final float mThresholdLatch;
private int mSensorDelay;
private SensorEventListener mSensorEventListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
boolean below = event.values[0] < mThreshold;
boolean above = event.values[0] > mThresholdLatch;
logDebug("Sensor value: " + event.values[0]);
onSensorEvent(below, event.timestamp);
onSensorEvent(below, above, event.timestamp);
}
@Override
@@ -60,10 +62,11 @@ class ThresholdSensorImpl implements ThresholdSensor {
};
private ThresholdSensorImpl(AsyncSensorManager sensorManager,
Sensor sensor, float threshold, int sensorDelay) {
Sensor sensor, float threshold, float thresholdLatch, int sensorDelay) {
mSensorManager = sensorManager;
mSensor = sensor;
mThreshold = threshold;
mThresholdLatch = thresholdLatch;
mSensorDelay = sensorDelay;
}
@@ -165,13 +168,32 @@ class ThresholdSensorImpl implements ThresholdSensor {
mLastBelow = null; // Forget what we know.
}
private void onSensorEvent(boolean below, long timestampNs) {
/**
* Call when the sensor reports a new value.
*
* Separate below-threshold and above-thresholds are specified. this allows latching behavior,
* where a different threshold can be specified for triggering the sensor depending on if it's
* going from above to below or below to above. To outside listeners of this class, the class
* still appears entirely binary.
*/
private void onSensorEvent(boolean belowThreshold, boolean aboveThreshold, long timestampNs) {
Assert.isMainThread();
if (!mRegistered || mLastBelow != null && mLastBelow == below) {
if (!mRegistered) {
return;
}
mLastBelow = below;
alertListenersInternal(below, timestampNs);
if (mLastBelow != null) {
// If we last reported below and are not yet above, change nothing.
if (mLastBelow && !aboveThreshold) {
return;
}
// If we last reported above and are not yet below, change nothing.
if (!mLastBelow && !belowThreshold) {
return;
}
}
mLastBelow = belowThreshold;
logDebug("Alerting below: " + belowThreshold);
alertListenersInternal(belowThreshold, timestampNs);
}
@@ -192,9 +214,11 @@ class ThresholdSensorImpl implements ThresholdSensor {
private final AsyncSensorManager mSensorManager;
private int mSensorDelay = SensorManager.SENSOR_DELAY_NORMAL;;
private float mThresholdValue;
private float mThresholdLatchValue;
private Sensor mSensor;
private boolean mSensorSet;
private boolean mThresholdSet;
private boolean mThresholdLatchValueSet;
@Inject
Builder(@Main Resources resources, AsyncSensorManager sensorManager) {
@@ -222,6 +246,15 @@ class ThresholdSensorImpl implements ThresholdSensor {
return this;
}
Builder setThresholdLatchResourceId(int thresholdLatchResourceId) {
try {
setThresholdLatchValue(mResources.getFloat(thresholdLatchResourceId));
} catch (Resources.NotFoundException e) {
// no-op
}
return this;
}
Builder setSensorType(String sensorType) {
Sensor sensor = findSensorByType(sensorType);
if (sensor != null) {
@@ -233,6 +266,15 @@ class ThresholdSensorImpl implements ThresholdSensor {
Builder setThresholdValue(float thresholdValue) {
mThresholdValue = thresholdValue;
mThresholdSet = true;
if (!mThresholdLatchValueSet) {
mThresholdLatchValue = mThresholdValue;
}
return this;
}
Builder setThresholdLatchValue(float thresholdLatchValue) {
mThresholdLatchValue = thresholdLatchValue;
mThresholdLatchValueSet = true;
return this;
}
@@ -254,8 +296,13 @@ class ThresholdSensorImpl implements ThresholdSensor {
throw new IllegalStateException("A threshold was not successfully set.");
}
if (mThresholdValue > mThresholdLatchValue) {
throw new IllegalStateException(
"Threshold must be less than or equal to Threshold Latch");
}
return new ThresholdSensorImpl(
mSensorManager, mSensor, mThresholdValue, mSensorDelay);
mSensorManager, mSensor, mThresholdValue, mThresholdLatchValue, mSensorDelay);
}
private Sensor findSensorByType(String sensorType) {

View File

@@ -37,19 +37,21 @@ import org.junit.runner.RunWith;
public class ThresholdSensorImplTest extends SysuiTestCase {
private ThresholdSensorImpl mThresholdSensor;
private FakeSensorManager mSensorManager;
private AsyncSensorManager mAsyncSensorManager;
private FakeSensorManager.FakeProximitySensor mFakeProximitySensor;
@Before
public void setUp() throws Exception {
allowTestableLooperAsMainThread();
FakeSensorManager sensorManager = new FakeSensorManager(getContext());
mSensorManager = new FakeSensorManager(getContext());
AsyncSensorManager asyncSensorManager = new AsyncSensorManager(
sensorManager, null, new Handler());
mAsyncSensorManager = new AsyncSensorManager(
mSensorManager, null, new Handler());
mFakeProximitySensor = sensorManager.getFakeProximitySensor();
mFakeProximitySensor = mSensorManager.getFakeProximitySensor();
ThresholdSensorImpl.Builder thresholdSensorBuilder = new ThresholdSensorImpl.Builder(
null, asyncSensorManager);
null, mAsyncSensorManager);
mThresholdSensor = (ThresholdSensorImpl) thresholdSensorBuilder
.setSensor(mFakeProximitySensor.getSensor())
.setThresholdValue(mFakeProximitySensor.getSensor().getMaximumRange())
@@ -226,6 +228,54 @@ public class ThresholdSensorImplTest extends SysuiTestCase {
waitForSensorManager();
}
@Test
public void testHysteresis() {
float lowValue = 10f;
float highValue = 100f;
FakeSensorManager.FakeGenericSensor sensor = mSensorManager.getFakeLightSensor();
ThresholdSensorImpl.Builder thresholdSensorBuilder = new ThresholdSensorImpl.Builder(
null, mAsyncSensorManager);
ThresholdSensorImpl thresholdSensor = (ThresholdSensorImpl) thresholdSensorBuilder
.setSensor(sensor.getSensor())
.setThresholdValue(lowValue)
.setThresholdLatchValue(highValue)
.build();
TestableListener listener = new TestableListener();
assertFalse(thresholdSensor.isRegistered());
thresholdSensor.register(listener);
waitForSensorManager();
assertTrue(thresholdSensor.isRegistered());
assertEquals(0, listener.mCallCount);
sensor.sendSensorEvent(lowValue - 1);
assertTrue(listener.mBelow);
assertEquals(1, listener.mCallCount);
sensor.sendSensorEvent(lowValue + 1);
assertTrue(listener.mBelow);
assertEquals(1, listener.mCallCount);
sensor.sendSensorEvent(highValue + 1);
assertFalse(listener.mBelow);
assertEquals(2, listener.mCallCount);
sensor.sendSensorEvent(highValue - 1);
assertFalse(listener.mBelow);
assertEquals(2, listener.mCallCount);
sensor.sendSensorEvent(lowValue - 1);
assertTrue(listener.mBelow);
assertEquals(3, listener.mCallCount);
}
@Test
public void testAlertAfterPause() {
TestableListener listener = new TestableListener();