Merge "RESTRICT AUTOMERGE ProximitySensor now supports dual-sensor approach." into rvc-d1-dev
This commit is contained in:
@@ -205,6 +205,14 @@
|
||||
far break points. A sensor value less than this is considered "near". -->
|
||||
<item name="proximity_sensor_threshold" 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
|
||||
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>
|
||||
|
||||
<!-- Doze: pulse parameter - how long does it take to fade in? -->
|
||||
<integer name="doze_pulse_duration_in">130</integer>
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable {
|
||||
mUiBgExecutor = uiBgExecutor;
|
||||
mStatusBarStateController = statusBarStateController;
|
||||
mProximitySensor.setTag(PROXIMITY_SENSOR_TAG);
|
||||
mProximitySensor.setSensorDelay(SensorManager.SENSOR_DELAY_GAME);
|
||||
mProximitySensor.setDelay(SensorManager.SENSOR_DELAY_GAME);
|
||||
mDeviceConfig = deviceConfig;
|
||||
mDeviceConfigListener =
|
||||
properties -> onDeviceConfigPropertiesChanged(context, properties.getNamespace());
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.util.DeviceConfigProxy;
|
||||
import com.android.systemui.util.sensors.ProximitySensor;
|
||||
import com.android.systemui.util.sensors.ThresholdSensor;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayDeque;
|
||||
@@ -76,7 +77,7 @@ public class BrightLineFalsingManager implements FalsingManager {
|
||||
|
||||
private final List<FalsingClassifier> mClassifiers;
|
||||
|
||||
private ProximitySensor.ProximitySensorListener mSensorEventListener = this::onProximityEvent;
|
||||
private ThresholdSensor.Listener mSensorEventListener = this::onProximityEvent;
|
||||
|
||||
private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
|
||||
new KeyguardUpdateMonitorCallback() {
|
||||
@@ -240,7 +241,7 @@ public class BrightLineFalsingManager implements FalsingManager {
|
||||
mClassifiers.forEach((classifier) -> classifier.onTouchEvent(motionEvent));
|
||||
}
|
||||
|
||||
private void onProximityEvent(ProximitySensor.ProximityEvent proximityEvent) {
|
||||
private void onProximityEvent(ThresholdSensor.ThresholdSensorEvent proximityEvent) {
|
||||
// TODO: some of these classifiers might allow us to abort early, meaning we don't have to
|
||||
// make these calls.
|
||||
mClassifiers.forEach((classifier) -> classifier.onProximityEvent(proximityEvent));
|
||||
|
||||
@@ -96,7 +96,7 @@ abstract class FalsingClassifier {
|
||||
/**
|
||||
* Called when a ProximityEvent occurs (change in near/far).
|
||||
*/
|
||||
void onProximityEvent(ProximitySensor.ProximityEvent proximityEvent) {};
|
||||
void onProximityEvent(ProximitySensor.ThresholdSensorEvent proximityEvent) {};
|
||||
|
||||
/**
|
||||
* The phone screen has turned on and we need to begin falsing detection.
|
||||
|
||||
@@ -101,8 +101,8 @@ class ProximityClassifier extends FalsingClassifier {
|
||||
|
||||
@Override
|
||||
public void onProximityEvent(
|
||||
ProximitySensor.ProximityEvent proximityEvent) {
|
||||
boolean near = proximityEvent.getNear();
|
||||
ProximitySensor.ThresholdSensorEvent proximityEvent) {
|
||||
boolean near = proximityEvent.getBelow();
|
||||
long timestampNs = proximityEvent.getTimestampNs();
|
||||
logDebug("Sensor is: " + near + " at time " + timestampNs);
|
||||
update(near, timestampNs);
|
||||
|
||||
@@ -36,6 +36,7 @@ import android.content.pm.LauncherApps;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ShortcutManager;
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.SensorManager;
|
||||
import android.hardware.SensorPrivacyManager;
|
||||
import android.media.AudioManager;
|
||||
import android.net.ConnectivityManager;
|
||||
@@ -240,6 +241,12 @@ public class SystemServicesModule {
|
||||
return context.getResources();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static SensorManager providesSensorManager(Context context) {
|
||||
return context.getSystemService(SensorManager.class);
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
static SensorPrivacyManager provideSensorPrivacyManager(Context context) {
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
|
||||
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||
import com.android.systemui.util.concurrency.ConcurrencyModule;
|
||||
import com.android.systemui.util.sensors.AsyncSensorManager;
|
||||
import com.android.systemui.util.sensors.SensorModule;
|
||||
import com.android.systemui.util.time.SystemClock;
|
||||
import com.android.systemui.util.time.SystemClockImpl;
|
||||
|
||||
@@ -62,7 +63,8 @@ import dagger.Provides;
|
||||
ConcurrencyModule.class,
|
||||
LogModule.class,
|
||||
PeopleHubModule.class,
|
||||
SettingsModule.class
|
||||
SensorModule.class,
|
||||
SettingsModule.class,
|
||||
},
|
||||
subcomponents = {StatusBarComponent.class,
|
||||
NotificationRowComponent.class,
|
||||
|
||||
@@ -81,7 +81,8 @@ public class DozeSensors {
|
||||
|
||||
public DozeSensors(Context context, AlarmManager alarmManager, AsyncSensorManager sensorManager,
|
||||
DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
|
||||
Callback callback, Consumer<Boolean> proxCallback, DozeLog dozeLog) {
|
||||
Callback callback, Consumer<Boolean> proxCallback, DozeLog dozeLog,
|
||||
ProximitySensor proximitySensor) {
|
||||
mContext = context;
|
||||
mAlarmManager = alarmManager;
|
||||
mSensorManager = sensorManager;
|
||||
@@ -153,12 +154,12 @@ public class DozeSensors {
|
||||
dozeLog),
|
||||
};
|
||||
|
||||
mProximitySensor = new ProximitySensor(context.getResources(), sensorManager);
|
||||
mProximitySensor = proximitySensor;
|
||||
setProxListening(false); // Don't immediately start listening when we register.
|
||||
mProximitySensor.register(
|
||||
proximityEvent -> {
|
||||
if (proximityEvent != null) {
|
||||
mProxCallback.accept(!proximityEvent.getNear());
|
||||
mProxCallback.accept(!proximityEvent.getBelow());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -92,8 +92,8 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
AlarmManager alarmManager, AmbientDisplayConfiguration config,
|
||||
DozeParameters dozeParameters, AsyncSensorManager sensorManager, Handler handler,
|
||||
WakeLock wakeLock, boolean allowPulseTriggers, DockManager dockManager,
|
||||
ProximitySensor proximitySensor,
|
||||
DozeLog dozeLog, BroadcastDispatcher broadcastDispatcher) {
|
||||
ProximitySensor proximitySensor, DozeLog dozeLog,
|
||||
BroadcastDispatcher broadcastDispatcher) {
|
||||
mContext = context;
|
||||
mMachine = machine;
|
||||
mDozeHost = dozeHost;
|
||||
@@ -103,7 +103,8 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
mWakeLock = wakeLock;
|
||||
mAllowPulseTriggers = allowPulseTriggers;
|
||||
mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters,
|
||||
config, wakeLock, this::onSensor, this::onProximityFar, dozeLog);
|
||||
config, wakeLock, this::onSensor, this::onProximityFar, dozeLog,
|
||||
proximitySensor);
|
||||
mUiModeManager = mContext.getSystemService(UiModeManager.class);
|
||||
mDockManager = dockManager;
|
||||
mProxCheck = new ProximitySensor.ProximityCheck(proximitySensor, handler);
|
||||
|
||||
@@ -60,8 +60,8 @@ public class AsyncSensorManager extends SensorManager
|
||||
private final List<SensorManagerPlugin> mPlugins;
|
||||
|
||||
@Inject
|
||||
public AsyncSensorManager(Context context, PluginManager pluginManager) {
|
||||
this(context.getSystemService(SensorManager.class), pluginManager, null);
|
||||
public AsyncSensorManager(SensorManager sensorManager, PluginManager pluginManager) {
|
||||
this(sensorManager, pluginManager, null);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.util.sensors;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
@Qualifier
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@interface PrimaryProxSensor {
|
||||
}
|
||||
@@ -16,92 +16,119 @@
|
||||
|
||||
package com.android.systemui.util.sensors;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.util.Assert;
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Simple wrapper around SensorManager customized for the Proximity sensor.
|
||||
* Wrapper around SensorManager customized for the Proximity sensor.
|
||||
*
|
||||
* The ProximitySensor supports the concept of a primary and a
|
||||
* secondary hardware sensor. The primary sensor is used for a first
|
||||
* pass check if the phone covered. When triggered, it then checks
|
||||
* the secondary sensor for confirmation (if there is one). It does
|
||||
* not send a proximity event until the secondary sensor confirms (or
|
||||
* rejects) the reading. The secondary sensor is, in fact, the source
|
||||
* of truth.
|
||||
*
|
||||
* This is necessary as sometimes keeping the secondary sensor on for
|
||||
* extends periods is undesirable. It may, however, result in increased
|
||||
* latency for proximity readings.
|
||||
*
|
||||
* Phones should configure this via a config.xml overlay. If no
|
||||
* proximity sensor is set (primary or secondary) we fall back to the
|
||||
* default Sensor.TYPE_PROXIMITY. If proximity_sensor_type is set in
|
||||
* config.xml, that will be used as the primary sensor. If
|
||||
* proximity_sensor_secondary_type is set, that will function as the
|
||||
* secondary sensor. If no secondary is set, only the primary will be
|
||||
* used.
|
||||
*/
|
||||
public class ProximitySensor {
|
||||
public class ProximitySensor implements ThresholdSensor {
|
||||
private static final String TAG = "ProxSensor";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
private static final long SECONDARY_PING_INTERVAL_MS = 5000;
|
||||
|
||||
private final Sensor mSensor;
|
||||
private final AsyncSensorManager mSensorManager;
|
||||
private final float mThreshold;
|
||||
private List<ProximitySensorListener> mListeners = new ArrayList<>();
|
||||
private final ThresholdSensor mPrimaryThresholdSensor;
|
||||
private final ThresholdSensor mSecondaryThresholdSensor;
|
||||
private final DelayableExecutor mDelayableExecutor;
|
||||
private final List<ThresholdSensor.Listener> mListeners = new ArrayList<>();
|
||||
private String mTag = null;
|
||||
@VisibleForTesting ProximityEvent mLastEvent;
|
||||
private int mSensorDelay = SensorManager.SENSOR_DELAY_NORMAL;
|
||||
private ThresholdSensorEvent mLastPrimaryEvent;
|
||||
@VisibleForTesting
|
||||
ThresholdSensorEvent mLastEvent;
|
||||
private boolean mPaused;
|
||||
private boolean mRegistered;
|
||||
private Runnable mCancelSecondaryRunnable;
|
||||
private boolean mInitializedListeners = false;
|
||||
|
||||
private SensorEventListener mSensorEventListener = new SensorEventListener() {
|
||||
private ThresholdSensor.Listener mPrimaryEventListener = new ThresholdSensor.Listener() {
|
||||
@Override
|
||||
public synchronized void onSensorChanged(SensorEvent event) {
|
||||
onSensorEvent(event);
|
||||
public void onThresholdCrossed(ThresholdSensorEvent event) {
|
||||
onPrimarySensorEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
private ThresholdSensor.Listener mSecondaryEventListener = new ThresholdSensor.Listener() {
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
public void onThresholdCrossed(ThresholdSensorEvent event) {
|
||||
// This sensor should only be used briefly. Turn it off as soon as we get a reading.
|
||||
mSecondaryThresholdSensor.pause();
|
||||
|
||||
// Only check the secondary as long as the primary thinks we're near.
|
||||
if (!mLastPrimaryEvent.getBelow()) {
|
||||
mCancelSecondaryRunnable = null;
|
||||
return;
|
||||
}
|
||||
logDebug("Secondary sensor event: " + event.getBelow() + ".");
|
||||
|
||||
onSensorEvent(event);
|
||||
|
||||
// Check this sensor again in a moment.
|
||||
mCancelSecondaryRunnable = mDelayableExecutor.executeDelayed(
|
||||
mSecondaryThresholdSensor::resume, SECONDARY_PING_INTERVAL_MS);
|
||||
}
|
||||
};
|
||||
|
||||
@Inject
|
||||
public ProximitySensor(@Main Resources resources,
|
||||
AsyncSensorManager sensorManager) {
|
||||
mSensorManager = sensorManager;
|
||||
|
||||
Sensor sensor = findCustomProxSensor(resources);
|
||||
float threshold = 0;
|
||||
if (sensor != null) {
|
||||
try {
|
||||
threshold = getCustomProxThreshold(resources);
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "Can not load custom proximity sensor.", e);
|
||||
sensor = null;
|
||||
}
|
||||
}
|
||||
if (sensor == null) {
|
||||
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
|
||||
if (sensor != null) {
|
||||
threshold = sensor.getMaximumRange();
|
||||
}
|
||||
}
|
||||
|
||||
mThreshold = threshold;
|
||||
|
||||
mSensor = sensor;
|
||||
public ProximitySensor(@PrimaryProxSensor ThresholdSensor primary,
|
||||
@SecondaryProxSensor ThresholdSensor secondary,
|
||||
@Main DelayableExecutor delayableExecutor) {
|
||||
mPrimaryThresholdSensor = primary;
|
||||
mSecondaryThresholdSensor = secondary;
|
||||
mDelayableExecutor = delayableExecutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTag(String tag) {
|
||||
mTag = tag;
|
||||
mPrimaryThresholdSensor.setTag(tag + ":primary");
|
||||
mSecondaryThresholdSensor.setTag(tag + ":secondary");
|
||||
}
|
||||
|
||||
public void setSensorDelay(int sensorDelay) {
|
||||
mSensorDelay = sensorDelay;
|
||||
@Override
|
||||
public void setDelay(int delay) {
|
||||
Assert.isMainThread();
|
||||
mPrimaryThresholdSensor.setDelay(delay);
|
||||
mSecondaryThresholdSensor.setDelay(delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister with the {@link SensorManager} without unsetting listeners on this object.
|
||||
*/
|
||||
@Override
|
||||
public void pause() {
|
||||
Assert.isMainThread();
|
||||
mPaused = true;
|
||||
unregisterInternal();
|
||||
}
|
||||
@@ -109,41 +136,13 @@ public class ProximitySensor {
|
||||
/**
|
||||
* Register with the {@link SensorManager}. No-op if no listeners are registered on this object.
|
||||
*/
|
||||
@Override
|
||||
public void resume() {
|
||||
Assert.isMainThread();
|
||||
mPaused = false;
|
||||
registerInternal();
|
||||
}
|
||||
/**
|
||||
* Returns a brightness sensor that can be used for proximity purposes.
|
||||
*/
|
||||
private Sensor findCustomProxSensor(Resources resources) {
|
||||
String sensorType = resources.getString(R.string.proximity_sensor_type);
|
||||
if (sensorType.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
|
||||
Sensor sensor = null;
|
||||
for (Sensor s : sensorList) {
|
||||
if (sensorType.equals(s.getStringType())) {
|
||||
sensor = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return sensor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a threshold value that can be used along with {@link #findCustomProxSensor}
|
||||
*/
|
||||
private float getCustomProxThreshold(Resources resources) {
|
||||
try {
|
||||
return resources.getFloat(R.dimen.proximity_sensor_threshold);
|
||||
} catch (Resources.NotFoundException e) {
|
||||
throw new IllegalStateException("R.dimen.proximity_sensor_threshold must be set.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we are registered with the SensorManager.
|
||||
@@ -155,38 +154,46 @@ public class ProximitySensor {
|
||||
/**
|
||||
* Returns {@code false} if a Proximity sensor is not available.
|
||||
*/
|
||||
public boolean getSensorAvailable() {
|
||||
return mSensor != null;
|
||||
@Override
|
||||
public boolean isLoaded() {
|
||||
return mPrimaryThresholdSensor.isLoaded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener.
|
||||
*
|
||||
* Registers itself with the {@link SensorManager} if this is the first listener
|
||||
* added. If a cool down is currently running, the sensor will be registered when it is over.
|
||||
* added. If the ProximitySensor is paused, it will be registered when resumed.
|
||||
*/
|
||||
public boolean register(ProximitySensorListener listener) {
|
||||
if (!getSensorAvailable()) {
|
||||
return false;
|
||||
@Override
|
||||
public void register(ThresholdSensor.Listener listener) {
|
||||
Assert.isMainThread();
|
||||
if (!isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mListeners.contains(listener)) {
|
||||
Log.d(TAG, "ProxListener registered multiple times: " + listener);
|
||||
logDebug("ProxListener registered multiple times: " + listener);
|
||||
} else {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
registerInternal();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void registerInternal() {
|
||||
Assert.isMainThread();
|
||||
if (mRegistered || mPaused || mListeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!mInitializedListeners) {
|
||||
mPrimaryThresholdSensor.register(mPrimaryEventListener);
|
||||
mSecondaryThresholdSensor.pause();
|
||||
mSecondaryThresholdSensor.register(mSecondaryEventListener);
|
||||
mInitializedListeners = true;
|
||||
}
|
||||
logDebug("Registering sensor listener");
|
||||
mPrimaryThresholdSensor.resume();
|
||||
mRegistered = true;
|
||||
mSensorManager.registerListener(mSensorEventListener, mSensor, mSensorDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,7 +202,9 @@ public class ProximitySensor {
|
||||
* If all listeners are removed from an instance of this class,
|
||||
* it will unregister itself with the SensorManager.
|
||||
*/
|
||||
public void unregister(ProximitySensorListener listener) {
|
||||
@Override
|
||||
public void unregister(ThresholdSensor.Listener listener) {
|
||||
Assert.isMainThread();
|
||||
mListeners.remove(listener);
|
||||
if (mListeners.size() == 0) {
|
||||
unregisterInternal();
|
||||
@@ -203,34 +212,77 @@ public class ProximitySensor {
|
||||
}
|
||||
|
||||
protected void unregisterInternal() {
|
||||
Assert.isMainThread();
|
||||
if (!mRegistered) {
|
||||
return;
|
||||
}
|
||||
logDebug("unregistering sensor listener");
|
||||
mSensorManager.unregisterListener(mSensorEventListener);
|
||||
mPrimaryThresholdSensor.pause();
|
||||
mSecondaryThresholdSensor.pause();
|
||||
if (mCancelSecondaryRunnable != null) {
|
||||
mCancelSecondaryRunnable.run();
|
||||
mCancelSecondaryRunnable = null;
|
||||
}
|
||||
mLastPrimaryEvent = null; // Forget what we know.
|
||||
mLastEvent = null;
|
||||
mRegistered = false;
|
||||
}
|
||||
|
||||
public Boolean isNear() {
|
||||
return getSensorAvailable() && mLastEvent != null ? mLastEvent.getNear() : null;
|
||||
return isLoaded() && mLastEvent != null ? mLastEvent.getBelow() : null;
|
||||
}
|
||||
|
||||
/** Update all listeners with the last value this class received from the sensor. */
|
||||
public void alertListeners() {
|
||||
mListeners.forEach(proximitySensorListener ->
|
||||
proximitySensorListener.onSensorEvent(mLastEvent));
|
||||
Assert.isMainThread();
|
||||
if (mLastEvent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<ThresholdSensor.Listener> listeners = new ArrayList<>(mListeners);
|
||||
listeners.forEach(proximitySensorListener ->
|
||||
proximitySensorListener.onThresholdCrossed(mLastEvent));
|
||||
}
|
||||
|
||||
private void onSensorEvent(SensorEvent event) {
|
||||
boolean near = event.values[0] < mThreshold;
|
||||
mLastEvent = new ProximityEvent(near, event.timestamp);
|
||||
private void onPrimarySensorEvent(ThresholdSensorEvent event) {
|
||||
Assert.isMainThread();
|
||||
if (mLastPrimaryEvent != null && event.getBelow() == mLastPrimaryEvent.getBelow()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mLastPrimaryEvent = event;
|
||||
|
||||
if (event.getBelow() && mSecondaryThresholdSensor.isLoaded()) {
|
||||
logDebug("Primary sensor is near. Checking secondary.");
|
||||
if (mCancelSecondaryRunnable == null) {
|
||||
mSecondaryThresholdSensor.resume();
|
||||
}
|
||||
} else {
|
||||
if (!mSecondaryThresholdSensor.isLoaded()) {
|
||||
logDebug("Primary sensor event: " + event.getBelow() + ". No secondary.");
|
||||
} else {
|
||||
logDebug("Primary sensor event: " + event.getBelow() + ".");
|
||||
}
|
||||
onSensorEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
private void onSensorEvent(ThresholdSensorEvent event) {
|
||||
Assert.isMainThread();
|
||||
if (mLastEvent != null && event.getBelow() == mLastEvent.getBelow()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mLastEvent = event;
|
||||
alertListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("{registered=%s, paused=%s, near=%s, sensor=%s}",
|
||||
isRegistered(), mPaused, isNear(), mSensor);
|
||||
return String.format("{registered=%s, paused=%s, near=%s, primarySensor=%s, "
|
||||
+ "secondarySensor=%s}",
|
||||
isRegistered(), mPaused, isNear(), mPrimaryThresholdSensor,
|
||||
mSecondaryThresholdSensor);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,11 +300,11 @@ public class ProximitySensor {
|
||||
mSensor.setTag("prox_check");
|
||||
mHandler = handler;
|
||||
mSensor.pause();
|
||||
ProximitySensorListener listener = proximityEvent -> {
|
||||
ThresholdSensor.Listener listener = proximityEvent -> {
|
||||
mCallbacks.forEach(
|
||||
booleanConsumer ->
|
||||
booleanConsumer.accept(
|
||||
proximityEvent == null ? null : proximityEvent.getNear()));
|
||||
proximityEvent == null ? null : proximityEvent.getBelow()));
|
||||
mCallbacks.clear();
|
||||
mSensor.pause();
|
||||
};
|
||||
@@ -274,7 +326,7 @@ public class ProximitySensor {
|
||||
* Query the proximity sensor, timing out if no result.
|
||||
*/
|
||||
public void check(long timeoutMs, Consumer<Boolean> callback) {
|
||||
if (!mSensor.getSensorAvailable()) {
|
||||
if (!mSensor.isLoaded()) {
|
||||
callback.accept(null);
|
||||
}
|
||||
mCallbacks.add(callback);
|
||||
@@ -285,43 +337,6 @@ public class ProximitySensor {
|
||||
}
|
||||
}
|
||||
|
||||
/** Implement to be notified of ProximityEvents. */
|
||||
public interface ProximitySensorListener {
|
||||
/** Called when the ProximitySensor changes. */
|
||||
void onSensorEvent(ProximityEvent proximityEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returned when the near/far state of a {@link ProximitySensor} changes.
|
||||
*/
|
||||
public static class ProximityEvent {
|
||||
private final boolean mNear;
|
||||
private final long mTimestampNs;
|
||||
|
||||
public ProximityEvent(boolean near, long timestampNs) {
|
||||
mNear = near;
|
||||
mTimestampNs = timestampNs;
|
||||
}
|
||||
|
||||
public boolean getNear() {
|
||||
return mNear;
|
||||
}
|
||||
|
||||
public long getTimestampNs() {
|
||||
return mTimestampNs;
|
||||
}
|
||||
|
||||
public long getTimestampMs() {
|
||||
return mTimestampNs / 1000000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format((Locale) null, "{near=%s, timestamp_ns=%d}", mNear, mTimestampNs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void logDebug(String msg) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, (mTag != null ? "[" + mTag + "] " : "") + msg);
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.util.sensors;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
@Qualifier
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@interface SecondaryProxSensor {
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.util.sensors;
|
||||
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorManager;
|
||||
|
||||
import com.android.systemui.R;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
/**
|
||||
* Dagger module for Sensor related classes.
|
||||
*/
|
||||
@Module
|
||||
public class SensorModule {
|
||||
@Provides
|
||||
@PrimaryProxSensor
|
||||
static ThresholdSensor providePrimaryProxSensor(SensorManager sensorManager,
|
||||
ThresholdSensorImpl.Builder thresholdSensorBuilder) {
|
||||
try {
|
||||
return thresholdSensorBuilder
|
||||
.setSensorDelay(SensorManager.SENSOR_DELAY_NORMAL)
|
||||
.setSensorResourceId(R.string.proximity_sensor_type)
|
||||
.setThresholdResourceId(R.dimen.proximity_sensor_threshold)
|
||||
.build();
|
||||
} catch (IllegalStateException e) {
|
||||
Sensor defaultSensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
|
||||
return thresholdSensorBuilder
|
||||
.setSensor(defaultSensor)
|
||||
.setThresholdValue(defaultSensor.getMaximumRange())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
@SecondaryProxSensor
|
||||
static ThresholdSensor provideSecondaryProxSensor(
|
||||
ThresholdSensorImpl.Builder thresholdSensorBuilder) {
|
||||
try {
|
||||
return thresholdSensorBuilder
|
||||
.setSensorResourceId(R.string.proximity_sensor_secondary_type)
|
||||
.setThresholdResourceId(R.dimen.proximity_sensor_secondary_threshold)
|
||||
.build();
|
||||
} catch (IllegalStateException e) {
|
||||
return thresholdSensorBuilder.setSensor(null).setThresholdValue(0).build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.util.sensors;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* A wrapper class for sensors that have a boolean state - above/below.
|
||||
*/
|
||||
public interface ThresholdSensor {
|
||||
/**
|
||||
* Optional label to use for logging.
|
||||
*
|
||||
* This should be set to something meaningful by owner of the instance.
|
||||
*/
|
||||
void setTag(String tag);
|
||||
|
||||
/**
|
||||
* Change the delay used when registering the sensor.
|
||||
*
|
||||
* If the sensor is already registered, this should cause it to re-register with the new
|
||||
* delay.
|
||||
*/
|
||||
void setDelay(int delay);
|
||||
|
||||
/**
|
||||
* True if this sensor successfully loads and can be listened to.
|
||||
*/
|
||||
boolean isLoaded();
|
||||
|
||||
/**
|
||||
* Registers with the sensor and calls the supplied callback on value change.
|
||||
*
|
||||
* If this instance is paused, the listener will be recorded, but no registration with
|
||||
* the underlying physical sensor will occur until {@link #resume()} is called.
|
||||
*
|
||||
* @see #unregister(Listener)
|
||||
*/
|
||||
void register(Listener listener);
|
||||
|
||||
/**
|
||||
* Unregisters from the physical sensor without removing any supplied listeners.
|
||||
*
|
||||
* No events will be sent to listeners as long as this sensor is paused.
|
||||
*
|
||||
* @see #resume()
|
||||
* @see #unregister(Listener)
|
||||
*/
|
||||
void pause();
|
||||
|
||||
/**
|
||||
* Resumes listening to the physical sensor after previously pausing.
|
||||
*
|
||||
* @see #pause()
|
||||
*/
|
||||
void resume();
|
||||
|
||||
/**
|
||||
* Unregister a listener with the sensor.
|
||||
*
|
||||
* @see #register(Listener)
|
||||
*/
|
||||
void unregister(Listener listener);
|
||||
|
||||
/**
|
||||
* Interface for listening to events on {@link ThresholdSensor}
|
||||
*/
|
||||
interface Listener {
|
||||
/**
|
||||
* Called whenever the threshold for the registered sensor is crossed.
|
||||
*/
|
||||
void onThresholdCrossed(ThresholdSensorEvent event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returned when the below/above state of a {@link ThresholdSensor} changes.
|
||||
*/
|
||||
class ThresholdSensorEvent {
|
||||
private final boolean mBelow;
|
||||
private final long mTimestampNs;
|
||||
|
||||
public ThresholdSensorEvent(boolean below, long timestampNs) {
|
||||
mBelow = below;
|
||||
mTimestampNs = timestampNs;
|
||||
}
|
||||
|
||||
public boolean getBelow() {
|
||||
return mBelow;
|
||||
}
|
||||
|
||||
public long getTimestampNs() {
|
||||
return mTimestampNs;
|
||||
}
|
||||
|
||||
public long getTimestampMs() {
|
||||
return mTimestampNs / 1000000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format((Locale) null, "{near=%s, timestamp_ns=%d}", mBelow, mTimestampNs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.util.sensors;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.util.Assert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
class ThresholdSensorImpl implements ThresholdSensor {
|
||||
private static final String TAG = "ThresholdSensor";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
private final AsyncSensorManager mSensorManager;
|
||||
private final Sensor mSensor;
|
||||
private final float mThreshold;
|
||||
private boolean mRegistered;
|
||||
private boolean mPaused;
|
||||
private List<Listener> mListeners = new ArrayList<>();
|
||||
private Boolean mLastBelow;
|
||||
private String mTag;
|
||||
private int mSensorDelay;
|
||||
|
||||
private SensorEventListener mSensorEventListener = new SensorEventListener() {
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
boolean below = event.values[0] < mThreshold;
|
||||
logDebug("Sensor value: " + event.values[0]);
|
||||
onSensorEvent(below, event.timestamp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
}
|
||||
};
|
||||
|
||||
private ThresholdSensorImpl(AsyncSensorManager sensorManager,
|
||||
Sensor sensor, float threshold, int sensorDelay) {
|
||||
mSensorManager = sensorManager;
|
||||
mSensor = sensor;
|
||||
mThreshold = threshold;
|
||||
mSensorDelay = sensorDelay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTag(String tag) {
|
||||
mTag = tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDelay(int delay) {
|
||||
if (delay == mSensorDelay) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSensorDelay = delay;
|
||||
if (isLoaded()) {
|
||||
unregisterInternal();
|
||||
registerInternal();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoaded() {
|
||||
return mSensor != null;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isRegistered() {
|
||||
return mRegistered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the listener with the sensor.
|
||||
*
|
||||
* Multiple listeners are not supported at this time.
|
||||
*
|
||||
* Returns true if the listener was successfully registered. False otherwise.
|
||||
*/
|
||||
@Override
|
||||
public void register(Listener listener) {
|
||||
Assert.isMainThread();
|
||||
if (!mListeners.contains(listener)) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
registerInternal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister(Listener listener) {
|
||||
Assert.isMainThread();
|
||||
mListeners.remove(listener);
|
||||
unregisterInternal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister with the {@link SensorManager} without unsetting listeners on this object.
|
||||
*/
|
||||
@Override
|
||||
public void pause() {
|
||||
Assert.isMainThread();
|
||||
mPaused = true;
|
||||
unregisterInternal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register with the {@link SensorManager}. No-op if no listeners are registered on this object.
|
||||
*/
|
||||
@Override
|
||||
public void resume() {
|
||||
Assert.isMainThread();
|
||||
mPaused = false;
|
||||
registerInternal();
|
||||
}
|
||||
|
||||
private void alertListenersInternal(boolean below, long timestampNs) {
|
||||
List<Listener> listeners = new ArrayList<>(mListeners);
|
||||
listeners.forEach(listener ->
|
||||
listener.onThresholdCrossed(new ThresholdSensorEvent(below, timestampNs)));
|
||||
}
|
||||
|
||||
private void registerInternal() {
|
||||
Assert.isMainThread();
|
||||
if (mRegistered || mPaused || mListeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
logDebug("Registering sensor listener");
|
||||
mSensorManager.registerListener(mSensorEventListener, mSensor, mSensorDelay);
|
||||
mRegistered = true;
|
||||
}
|
||||
|
||||
private void unregisterInternal() {
|
||||
Assert.isMainThread();
|
||||
if (!mRegistered) {
|
||||
return;
|
||||
}
|
||||
logDebug("Unregister sensor listener");
|
||||
mSensorManager.unregisterListener(mSensorEventListener);
|
||||
mRegistered = false;
|
||||
mLastBelow = null; // Forget what we know.
|
||||
}
|
||||
|
||||
private void onSensorEvent(boolean below, long timestampNs) {
|
||||
Assert.isMainThread();
|
||||
if (mLastBelow != null && mLastBelow == below) {
|
||||
return;
|
||||
}
|
||||
mLastBelow = below;
|
||||
alertListenersInternal(below, timestampNs);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("{registered=%s, paused=%s, threshold=%s, sensor=%s}",
|
||||
isLoaded(), mRegistered, mPaused, mThreshold, mSensor);
|
||||
}
|
||||
|
||||
private void logDebug(String msg) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, (mTag != null ? "[" + mTag + "] " : "") + msg);
|
||||
}
|
||||
}
|
||||
|
||||
static class Builder {
|
||||
private final Resources mResources;
|
||||
private final AsyncSensorManager mSensorManager;
|
||||
private int mSensorDelay = SensorManager.SENSOR_DELAY_NORMAL;;
|
||||
private float mThresholdValue;
|
||||
private Sensor mSensor;
|
||||
private boolean mSensorSet;
|
||||
private boolean mThresholdSet;
|
||||
|
||||
@Inject
|
||||
Builder(@Main Resources resources, AsyncSensorManager sensorManager) {
|
||||
mResources = resources;
|
||||
mSensorManager = sensorManager;
|
||||
}
|
||||
|
||||
|
||||
Builder setSensorDelay(int sensorDelay) {
|
||||
mSensorDelay = sensorDelay;
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder setSensorResourceId(int sensorResourceId) {
|
||||
setSensorType(mResources.getString(sensorResourceId));
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder setThresholdResourceId(int thresholdResourceId) {
|
||||
try {
|
||||
setThresholdValue(mResources.getFloat(thresholdResourceId));
|
||||
} catch (Resources.NotFoundException e) {
|
||||
// no-op
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder setSensorType(String sensorType) {
|
||||
Sensor sensor = findSensorByType(sensorType);
|
||||
if (sensor != null) {
|
||||
setSensor(sensor);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder setThresholdValue(float thresholdValue) {
|
||||
mThresholdValue = thresholdValue;
|
||||
mThresholdSet = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder setSensor(Sensor sensor) {
|
||||
mSensor = sensor;
|
||||
mSensorSet = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ThresholdSensor} backed by a {@link ThresholdSensorImpl}.
|
||||
*/
|
||||
public ThresholdSensor build() {
|
||||
if (!mSensorSet) {
|
||||
throw new IllegalStateException("A sensor was not successfully set.");
|
||||
}
|
||||
|
||||
if (!mThresholdSet) {
|
||||
throw new IllegalStateException("A threshold was not successfully set.");
|
||||
}
|
||||
|
||||
return new ThresholdSensorImpl(
|
||||
mSensorManager, mSensor, mThresholdValue, mSensorDelay);
|
||||
}
|
||||
|
||||
private Sensor findSensorByType(String sensorType) {
|
||||
if (sensorType.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
|
||||
Sensor sensor = null;
|
||||
for (Sensor s : sensorList) {
|
||||
if (sensorType.equals(s.getStringType())) {
|
||||
sensor = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return sensor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
import com.android.systemui.util.DeviceConfigProxy;
|
||||
import com.android.systemui.util.DeviceConfigProxyFake;
|
||||
import com.android.systemui.util.sensors.ProximitySensor;
|
||||
import com.android.systemui.util.sensors.ThresholdSensor;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -77,7 +78,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void testRegisterSensor() {
|
||||
mFalsingManager.onScreenTurningOn();
|
||||
verify(mProximitySensor).register(any(ProximitySensor.ProximitySensorListener.class));
|
||||
verify(mProximitySensor).register(any(ThresholdSensor.Listener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -85,7 +86,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
|
||||
mFalsingManager.onScreenTurningOn();
|
||||
reset(mProximitySensor);
|
||||
mFalsingManager.onScreenOff();
|
||||
verify(mProximitySensor).unregister(any(ProximitySensor.ProximitySensorListener.class));
|
||||
verify(mProximitySensor).unregister(any(ThresholdSensor.Listener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -93,9 +94,9 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
|
||||
mFalsingManager.onScreenTurningOn();
|
||||
reset(mProximitySensor);
|
||||
mFalsingManager.setQsExpanded(true);
|
||||
verify(mProximitySensor).unregister(any(ProximitySensor.ProximitySensorListener.class));
|
||||
verify(mProximitySensor).unregister(any(ThresholdSensor.Listener.class));
|
||||
mFalsingManager.setQsExpanded(false);
|
||||
verify(mProximitySensor).register(any(ProximitySensor.ProximitySensorListener.class));
|
||||
verify(mProximitySensor).register(any(ThresholdSensor.Listener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -103,9 +104,9 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
|
||||
mFalsingManager.onScreenTurningOn();
|
||||
reset(mProximitySensor);
|
||||
mFalsingManager.onBouncerShown();
|
||||
verify(mProximitySensor).unregister(any(ProximitySensor.ProximitySensorListener.class));
|
||||
verify(mProximitySensor).unregister(any(ThresholdSensor.Listener.class));
|
||||
mFalsingManager.onBouncerHidden();
|
||||
verify(mProximitySensor).register(any(ProximitySensor.ProximitySensorListener.class));
|
||||
verify(mProximitySensor).register(any(ThresholdSensor.Listener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -113,6 +114,6 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
|
||||
mFalsingManager.onScreenTurningOn();
|
||||
reset(mProximitySensor);
|
||||
mStatusBarStateController.setState(StatusBarState.SHADE);
|
||||
verify(mProximitySensor).unregister(any(ProximitySensor.ProximitySensorListener.class));
|
||||
verify(mProximitySensor).unregister(any(ThresholdSensor.Listener.class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,8 @@ public class ProximityClassifierTest extends ClassifierTest {
|
||||
motionEvent.recycle();
|
||||
}
|
||||
|
||||
private ProximitySensor.ProximityEvent createSensorEvent(boolean covered, long timestampMs) {
|
||||
return new ProximitySensor.ProximityEvent(covered, timestampMs * NS_PER_MS);
|
||||
private ProximitySensor.ThresholdSensorEvent createSensorEvent(
|
||||
boolean covered, long timestampMs) {
|
||||
return new ProximitySensor.ThresholdSensorEvent(covered, timestampMs * NS_PER_MS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import com.android.systemui.doze.DozeSensors.TriggerSensor;
|
||||
import com.android.systemui.plugins.SensorManagerPlugin;
|
||||
import com.android.systemui.statusbar.phone.DozeParameters;
|
||||
import com.android.systemui.util.sensors.AsyncSensorManager;
|
||||
import com.android.systemui.util.sensors.ProximitySensor;
|
||||
import com.android.systemui.util.wakelock.WakeLock;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -83,6 +84,9 @@ public class DozeSensorsTest extends SysuiTestCase {
|
||||
private DozeLog mDozeLog;
|
||||
@Mock
|
||||
private Sensor mProximitySensor;
|
||||
@Mock
|
||||
private ProximitySensor mMockProxSensor;
|
||||
|
||||
private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener;
|
||||
private TestableLooper mTestableLooper;
|
||||
private DozeSensors mDozeSensors;
|
||||
@@ -104,9 +108,9 @@ public class DozeSensorsTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void testRegisterProx() {
|
||||
// We should not register with the sensor manager initially.
|
||||
verify(mSensorManager, never()).registerListener(any(), any(Sensor.class), anyInt());
|
||||
verify(mMockProxSensor).pause();
|
||||
mDozeSensors.setProxListening(true);
|
||||
verify(mSensorManager).registerListener(any(), any(Sensor.class), anyInt());
|
||||
verify(mMockProxSensor).resume();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -162,7 +166,8 @@ public class DozeSensorsTest extends SysuiTestCase {
|
||||
|
||||
TestableDozeSensors() {
|
||||
super(getContext(), mAlarmManager, mSensorManager, mDozeParameters,
|
||||
mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog);
|
||||
mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog,
|
||||
mMockProxSensor);
|
||||
for (TriggerSensor sensor : mSensors) {
|
||||
if (sensor instanceof PluginSensor
|
||||
&& ((PluginSensor) sensor).mPluginSensor.getType()
|
||||
|
||||
@@ -42,10 +42,13 @@ import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
import com.android.systemui.statusbar.phone.DozeParameters;
|
||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||
import com.android.systemui.util.sensors.AsyncSensorManager;
|
||||
import com.android.systemui.util.sensors.FakeProximitySensor;
|
||||
import com.android.systemui.util.sensors.FakeSensorManager;
|
||||
import com.android.systemui.util.sensors.FakeThresholdSensor;
|
||||
import com.android.systemui.util.sensors.ProximitySensor;
|
||||
import com.android.systemui.util.time.FakeSystemClock;
|
||||
import com.android.systemui.util.wakelock.WakeLock;
|
||||
import com.android.systemui.util.wakelock.WakeLockFake;
|
||||
|
||||
@@ -71,10 +74,12 @@ public class DozeTriggersTest extends SysuiTestCase {
|
||||
private BroadcastDispatcher mBroadcastDispatcher;
|
||||
@Mock
|
||||
private DockManager mDockManager;
|
||||
|
||||
private DozeTriggers mTriggers;
|
||||
private FakeSensorManager mSensors;
|
||||
private Sensor mTapSensor;
|
||||
private FakeProximitySensor mProximitySensor;
|
||||
private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@@ -86,7 +91,10 @@ public class DozeTriggersTest extends SysuiTestCase {
|
||||
WakeLock wakeLock = new WakeLockFake();
|
||||
AsyncSensorManager asyncSensorManager =
|
||||
new AsyncSensorManager(mSensors, null, new Handler());
|
||||
mProximitySensor = new FakeProximitySensor(getContext().getResources(), asyncSensorManager);
|
||||
|
||||
FakeThresholdSensor thresholdSensor = new FakeThresholdSensor();
|
||||
thresholdSensor.setLoaded(true);
|
||||
mProximitySensor = new FakeProximitySensor(thresholdSensor, null, mExecutor);
|
||||
|
||||
mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager, config, parameters,
|
||||
asyncSensorManager, Handler.createAsync(Looper.myLooper()), wakeLock, true,
|
||||
@@ -104,17 +112,17 @@ public class DozeTriggersTest extends SysuiTestCase {
|
||||
mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
|
||||
clearInvocations(mMachine);
|
||||
|
||||
mProximitySensor.setLastEvent(new ProximitySensor.ProximityEvent(true, 1));
|
||||
mProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(true, 1));
|
||||
captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */);
|
||||
mProximitySensor.alertListeners();
|
||||
|
||||
verify(mMachine, never()).requestState(any());
|
||||
verify(mMachine, never()).requestPulse(anyInt());
|
||||
|
||||
captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */);
|
||||
waitForSensorManager();
|
||||
mProximitySensor.setLastEvent(new ProximitySensor.ProximityEvent(false, 2));
|
||||
mProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(false, 2));
|
||||
mProximitySensor.alertListeners();
|
||||
waitForSensorManager();
|
||||
captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */);
|
||||
|
||||
verify(mMachine).requestPulse(anyInt());
|
||||
}
|
||||
|
||||
@@ -16,13 +16,15 @@
|
||||
|
||||
package com.android.systemui.util.sensors;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||
|
||||
public class FakeProximitySensor extends ProximitySensor {
|
||||
private boolean mAvailable;
|
||||
|
||||
public FakeProximitySensor(Resources resources, AsyncSensorManager sensorManager) {
|
||||
super(resources, sensorManager);
|
||||
public FakeProximitySensor(ThresholdSensor primary, ThresholdSensor secondary,
|
||||
DelayableExecutor delayableExecutor) {
|
||||
super(primary, secondary == null ? new FakeThresholdSensor() : secondary,
|
||||
delayableExecutor);
|
||||
mAvailable = true;
|
||||
}
|
||||
|
||||
@@ -30,12 +32,12 @@ public class FakeProximitySensor extends ProximitySensor {
|
||||
mAvailable = available;
|
||||
}
|
||||
|
||||
public void setLastEvent(ProximityEvent event) {
|
||||
public void setLastEvent(ThresholdSensorEvent event) {
|
||||
mLastEvent = event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getSensorAvailable() {
|
||||
public boolean isLoaded() {
|
||||
return mAvailable;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.util.sensors;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FakeThresholdSensor implements ThresholdSensor {
|
||||
private boolean mIsLoaded;
|
||||
private boolean mPaused;
|
||||
private List<Listener> mListeners = new ArrayList<>();
|
||||
|
||||
public FakeThresholdSensor() {
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDelay(int delay) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoaded() {
|
||||
return mIsLoaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
mPaused = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resume() {
|
||||
mPaused = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(ThresholdSensor.Listener listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister(ThresholdSensor.Listener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void setLoaded(boolean loaded) {
|
||||
mIsLoaded = loaded;
|
||||
}
|
||||
|
||||
void triggerEvent(boolean below, long timestampNs) {
|
||||
if (!mPaused) {
|
||||
for (Listener listener : mListeners) {
|
||||
listener.onThresholdCrossed(new ThresholdSensorEvent(below, timestampNs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isPaused() {
|
||||
return mPaused;
|
||||
}
|
||||
|
||||
int getNumListeners() {
|
||||
return mListeners.size();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.util.sensors;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||
import com.android.systemui.util.time.FakeSystemClock;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class ProximitySensorDualTest extends SysuiTestCase {
|
||||
private ProximitySensor mProximitySensor;
|
||||
private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
|
||||
private FakeThresholdSensor mThresholdSensorPrimary;
|
||||
private FakeThresholdSensor mThresholdSensorSecondary;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
allowTestableLooperAsMainThread();
|
||||
mThresholdSensorPrimary = new FakeThresholdSensor();
|
||||
mThresholdSensorPrimary.setLoaded(true);
|
||||
mThresholdSensorSecondary = new FakeThresholdSensor();
|
||||
mThresholdSensorSecondary.setLoaded(true);
|
||||
|
||||
mProximitySensor = new ProximitySensor(
|
||||
mThresholdSensorPrimary, mThresholdSensorSecondary, mFakeExecutor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleListener() {
|
||||
TestableListener listener = new TestableListener();
|
||||
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
mProximitySensor.register(listener);
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertFalse(mThresholdSensorPrimary.isPaused());
|
||||
assertTrue(mThresholdSensorSecondary.isPaused());
|
||||
assertNull(listener.mLastEvent);
|
||||
assertEquals(0, listener.mCallCount);
|
||||
|
||||
// Trigger second sensor. Nothing should happen yet.
|
||||
mThresholdSensorSecondary.triggerEvent(true, 0);
|
||||
assertFalse(mThresholdSensorPrimary.isPaused());
|
||||
assertTrue(mThresholdSensorSecondary.isPaused());
|
||||
assertNull(listener.mLastEvent);
|
||||
assertEquals(0, listener.mCallCount);
|
||||
|
||||
// Trigger first sensor. Our second sensor is now registered.
|
||||
mThresholdSensorPrimary.triggerEvent(true, 0);
|
||||
assertFalse(mThresholdSensorPrimary.isPaused());
|
||||
assertFalse(mThresholdSensorSecondary.isPaused());
|
||||
assertNull(listener.mLastEvent);
|
||||
assertEquals(0, listener.mCallCount);
|
||||
|
||||
// Trigger second sensor.
|
||||
mThresholdSensorSecondary.triggerEvent(true, 0);
|
||||
assertFalse(mThresholdSensorPrimary.isPaused());
|
||||
assertTrue(mThresholdSensorSecondary.isPaused());
|
||||
assertTrue(listener.mLastEvent.getBelow());
|
||||
assertEquals(1, listener.mCallCount);
|
||||
assertTrue(mThresholdSensorSecondary.isPaused());
|
||||
|
||||
mProximitySensor.unregister(listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecondaryPausing() {
|
||||
TestableListener listener = new TestableListener();
|
||||
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
mProximitySensor.register(listener);
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertNull(listener.mLastEvent);
|
||||
assertEquals(0, listener.mCallCount);
|
||||
|
||||
// Trigger first sensor. Our second sensor is now registered.
|
||||
mThresholdSensorPrimary.triggerEvent(true, 0);
|
||||
assertNull(listener.mLastEvent);
|
||||
assertEquals(0, listener.mCallCount);
|
||||
|
||||
// Trigger second sensor.
|
||||
mThresholdSensorSecondary.triggerEvent(true, 0);
|
||||
assertTrue(listener.mLastEvent.getBelow());
|
||||
assertEquals(1, listener.mCallCount);
|
||||
assertTrue(mThresholdSensorSecondary.isPaused());
|
||||
|
||||
// Advance time. Second sensor should resume.
|
||||
mFakeExecutor.advanceClockToNext();
|
||||
mFakeExecutor.runNextReady();
|
||||
assertFalse(mThresholdSensorSecondary.isPaused());
|
||||
|
||||
// Triggering should pause again.
|
||||
mThresholdSensorSecondary.triggerEvent(false, 0);
|
||||
assertFalse(listener.mLastEvent.getBelow());
|
||||
assertEquals(2, listener.mCallCount);
|
||||
assertTrue(mThresholdSensorSecondary.isPaused());
|
||||
|
||||
mProximitySensor.unregister(listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnregister() {
|
||||
TestableListener listener = new TestableListener();
|
||||
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
mProximitySensor.register(listener);
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertFalse(mThresholdSensorPrimary.isPaused());
|
||||
assertTrue(mThresholdSensorSecondary.isPaused());
|
||||
assertNull(listener.mLastEvent);
|
||||
|
||||
mThresholdSensorPrimary.triggerEvent(true, 0);
|
||||
mThresholdSensorSecondary.triggerEvent(true, 0);
|
||||
assertFalse(mThresholdSensorPrimary.isPaused());
|
||||
assertTrue(mThresholdSensorSecondary.isPaused());
|
||||
assertTrue(listener.mLastEvent.getBelow());
|
||||
assertEquals(1, listener.mCallCount);
|
||||
|
||||
mProximitySensor.unregister(listener);
|
||||
assertTrue(mThresholdSensorPrimary.isPaused());
|
||||
assertTrue(mThresholdSensorSecondary.isPaused());
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPauseAndResume() {
|
||||
TestableListener listener = new TestableListener();
|
||||
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
mProximitySensor.register(listener);
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertNull(listener.mLastEvent);
|
||||
|
||||
mThresholdSensorPrimary.triggerEvent(true, 0);
|
||||
mThresholdSensorSecondary.triggerEvent(true, 0);
|
||||
assertFalse(mThresholdSensorPrimary.isPaused());
|
||||
assertTrue(mThresholdSensorSecondary.isPaused());
|
||||
assertTrue(listener.mLastEvent.getBelow());
|
||||
assertEquals(1, listener.mCallCount);
|
||||
|
||||
mProximitySensor.pause();
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
assertTrue(mThresholdSensorPrimary.isPaused());
|
||||
assertTrue(mThresholdSensorSecondary.isPaused());
|
||||
|
||||
// More events do nothing when paused.
|
||||
mThresholdSensorSecondary.triggerEvent(false, 1);
|
||||
assertTrue(listener.mLastEvent.getBelow());
|
||||
assertEquals(1, listener.mCallCount);
|
||||
|
||||
mProximitySensor.resume();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
// Still matches our previous call
|
||||
assertTrue(listener.mLastEvent.getBelow());
|
||||
assertEquals(1, listener.mCallCount);
|
||||
|
||||
// Need to trigger the primary sensor before the secondary re-registers itself.
|
||||
mThresholdSensorPrimary.triggerEvent(true, 3);
|
||||
mThresholdSensorSecondary.triggerEvent(false, 3);
|
||||
assertFalse(mThresholdSensorPrimary.isPaused());
|
||||
assertTrue(mThresholdSensorSecondary.isPaused());
|
||||
assertFalse(listener.mLastEvent.getBelow());
|
||||
assertEquals(2, listener.mCallCount);
|
||||
|
||||
mProximitySensor.unregister(listener);
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrimarySecondaryDisagreement() {
|
||||
TestableListener listener = new TestableListener();
|
||||
|
||||
mProximitySensor.register(listener);
|
||||
assertFalse(mThresholdSensorPrimary.isPaused());
|
||||
assertTrue(mThresholdSensorSecondary.isPaused());
|
||||
assertNull(listener.mLastEvent);
|
||||
assertEquals(0, listener.mCallCount);
|
||||
|
||||
// Trigger our sensors with different values. Secondary overrides primary.
|
||||
mThresholdSensorPrimary.triggerEvent(true, 0);
|
||||
assertNull(listener.mLastEvent);
|
||||
assertEquals(0, listener.mCallCount);
|
||||
mThresholdSensorSecondary.triggerEvent(false, 0);
|
||||
assertFalse(listener.mLastEvent.getBelow());
|
||||
assertEquals(1, listener.mCallCount);
|
||||
|
||||
mThresholdSensorSecondary.resume();
|
||||
mThresholdSensorSecondary.triggerEvent(true, 0);
|
||||
assertTrue(listener.mLastEvent.getBelow());
|
||||
assertEquals(2, listener.mCallCount);
|
||||
|
||||
mThresholdSensorSecondary.resume();
|
||||
mThresholdSensorSecondary.triggerEvent(false, 0);
|
||||
assertFalse(listener.mLastEvent.getBelow());
|
||||
assertEquals(3, listener.mCallCount);
|
||||
|
||||
mProximitySensor.unregister(listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrimaryCancelsSecondary() {
|
||||
TestableListener listener = new TestableListener();
|
||||
|
||||
mProximitySensor.register(listener);
|
||||
assertFalse(mThresholdSensorPrimary.isPaused());
|
||||
assertTrue(mThresholdSensorSecondary.isPaused());
|
||||
assertNull(listener.mLastEvent);
|
||||
assertEquals(0, listener.mCallCount);
|
||||
|
||||
mThresholdSensorPrimary.triggerEvent(true, 0);
|
||||
assertNull(listener.mLastEvent);
|
||||
assertEquals(0, listener.mCallCount);
|
||||
mThresholdSensorSecondary.triggerEvent(true, 0);
|
||||
assertTrue(listener.mLastEvent.getBelow());
|
||||
assertEquals(1, listener.mCallCount);
|
||||
|
||||
// When the primary reports false, the secondary is no longer needed. We get an immediate
|
||||
// report.
|
||||
mThresholdSensorPrimary.triggerEvent(false, 1);
|
||||
assertFalse(listener.mLastEvent.getBelow());
|
||||
assertEquals(2, listener.mCallCount);
|
||||
|
||||
// The secondary is now ignored. No more work is scheduled.
|
||||
mFakeExecutor.advanceClockToNext();
|
||||
mFakeExecutor.runNextReady();
|
||||
mThresholdSensorSecondary.triggerEvent(true, 0);
|
||||
assertFalse(listener.mLastEvent.getBelow());
|
||||
assertEquals(2, listener.mCallCount);
|
||||
assertEquals(0, mFakeExecutor.numPending());
|
||||
|
||||
mProximitySensor.unregister(listener);
|
||||
}
|
||||
|
||||
private static class TestableListener implements ThresholdSensor.Listener {
|
||||
ThresholdSensor.ThresholdSensorEvent mLastEvent;
|
||||
int mCallCount = 0;
|
||||
|
||||
@Override
|
||||
public void onThresholdCrossed(ThresholdSensor.ThresholdSensorEvent proximityEvent) {
|
||||
mLastEvent = proximityEvent;
|
||||
mCallCount++;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -21,33 +21,40 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||
import com.android.systemui.util.time.FakeSystemClock;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
/**
|
||||
* Tests for ProximitySensor that rely on a single hardware sensor.
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class ProximitySensorTest extends SysuiTestCase {
|
||||
|
||||
public class ProximitySensorSingleTest extends SysuiTestCase {
|
||||
private ProximitySensor mProximitySensor;
|
||||
private FakeSensorManager.FakeProximitySensor mFakeProximitySensor;
|
||||
private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
|
||||
private FakeThresholdSensor mThresholdSensor;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
FakeSensorManager sensorManager = new FakeSensorManager(getContext());
|
||||
AsyncSensorManager asyncSensorManager = new AsyncSensorManager(
|
||||
sensorManager, null, new Handler());
|
||||
mFakeProximitySensor = sensorManager.getFakeProximitySensor();
|
||||
mProximitySensor = new ProximitySensor(getContext().getResources(), asyncSensorManager);
|
||||
MockitoAnnotations.initMocks(this);
|
||||
allowTestableLooperAsMainThread();
|
||||
mThresholdSensor = new FakeThresholdSensor();
|
||||
mThresholdSensor.setLoaded(true);
|
||||
|
||||
mProximitySensor = new ProximitySensor(
|
||||
mThresholdSensor, new FakeThresholdSensor(), mFakeExecutor);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -56,19 +63,17 @@ public class ProximitySensorTest extends SysuiTestCase {
|
||||
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
mProximitySensor.register(listener);
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertNull(listener.mLastEvent);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 1);
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertTrue(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 2);
|
||||
mThresholdSensor.triggerEvent(false, 0);
|
||||
assertFalse(listener.mLastEvent.getBelow());
|
||||
assertEquals(1, listener.mCallCount);
|
||||
mThresholdSensor.triggerEvent(true, 0);
|
||||
assertTrue(listener.mLastEvent.getBelow());
|
||||
assertEquals(2, listener.mCallCount);
|
||||
|
||||
mProximitySensor.unregister(listener);
|
||||
waitForSensorManager();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -79,28 +84,25 @@ public class ProximitySensorTest extends SysuiTestCase {
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
|
||||
mProximitySensor.register(listenerA);
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
mProximitySensor.register(listenerB);
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertNull(listenerA.mLastEvent);
|
||||
assertNull(listenerB.mLastEvent);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listenerA.mLastEvent.getNear());
|
||||
assertFalse(listenerB.mLastEvent.getNear());
|
||||
assertEquals(listenerA.mCallCount, 1);
|
||||
assertEquals(listenerB.mCallCount, 1);
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertTrue(listenerA.mLastEvent.getNear());
|
||||
assertTrue(listenerB.mLastEvent.getNear());
|
||||
assertEquals(listenerA.mCallCount, 2);
|
||||
assertEquals(listenerB.mCallCount, 2);
|
||||
mThresholdSensor.triggerEvent(false, 0);
|
||||
assertFalse(listenerA.mLastEvent.getBelow());
|
||||
assertFalse(listenerB.mLastEvent.getBelow());
|
||||
assertEquals(1, listenerA.mCallCount);
|
||||
assertEquals(1, listenerB.mCallCount);
|
||||
mThresholdSensor.triggerEvent(true, 1);
|
||||
assertTrue(listenerA.mLastEvent.getBelow());
|
||||
assertTrue(listenerB.mLastEvent.getBelow());
|
||||
assertEquals(2, listenerA.mCallCount);
|
||||
assertEquals(2, listenerB.mCallCount);
|
||||
|
||||
mProximitySensor.unregister(listenerA);
|
||||
mProximitySensor.unregister(listenerB);
|
||||
waitForSensorManager();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -110,22 +112,19 @@ public class ProximitySensorTest extends SysuiTestCase {
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
|
||||
mProximitySensor.register(listenerA);
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
mProximitySensor.register(listenerA);
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertNull(listenerA.mLastEvent);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listenerA.mLastEvent.getNear());
|
||||
assertEquals(listenerA.mCallCount, 1);
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertTrue(listenerA.mLastEvent.getNear());
|
||||
assertEquals(listenerA.mCallCount, 2);
|
||||
mThresholdSensor.triggerEvent(false, 0);
|
||||
assertFalse(listenerA.mLastEvent.getBelow());
|
||||
assertEquals(1, listenerA.mCallCount);
|
||||
mThresholdSensor.triggerEvent(true, 1);
|
||||
assertTrue(listenerA.mLastEvent.getBelow());
|
||||
assertEquals(2, listenerA.mCallCount);
|
||||
|
||||
mProximitySensor.unregister(listenerA);
|
||||
waitForSensorManager();
|
||||
}
|
||||
@Test
|
||||
public void testUnregister() {
|
||||
@@ -133,16 +132,14 @@ public class ProximitySensorTest extends SysuiTestCase {
|
||||
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
mProximitySensor.register(listener);
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertNull(listener.mLastEvent);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 1);
|
||||
mThresholdSensor.triggerEvent(false, 0);
|
||||
assertFalse(listener.mLastEvent.getBelow());
|
||||
assertEquals(1, listener.mCallCount);
|
||||
|
||||
mProximitySensor.unregister(listener);
|
||||
waitForSensorManager();
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
}
|
||||
|
||||
@@ -152,39 +149,35 @@ public class ProximitySensorTest extends SysuiTestCase {
|
||||
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
mProximitySensor.register(listener);
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertNull(listener.mLastEvent);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 1);
|
||||
mThresholdSensor.triggerEvent(false, 0);
|
||||
assertFalse(listener.mLastEvent.getBelow());
|
||||
assertEquals(1, listener.mCallCount);
|
||||
|
||||
mProximitySensor.pause();
|
||||
waitForSensorManager();
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
|
||||
// More events do nothing when paused.
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 1);
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertFalse(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 1);
|
||||
mThresholdSensor.triggerEvent(false, 1);
|
||||
assertFalse(listener.mLastEvent.getBelow());
|
||||
assertEquals(1, listener.mCallCount);
|
||||
mThresholdSensor.triggerEvent(true, 2);
|
||||
assertFalse(listener.mLastEvent.getBelow());
|
||||
assertEquals(1, listener.mCallCount);
|
||||
|
||||
mProximitySensor.resume();
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
// Still matches our previous call
|
||||
assertFalse(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 1);
|
||||
assertFalse(listener.mLastEvent.getBelow());
|
||||
assertEquals(1, listener.mCallCount);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 2);
|
||||
mThresholdSensor.triggerEvent(true, 3);
|
||||
assertTrue(listener.mLastEvent.getBelow());
|
||||
assertEquals(2, listener.mCallCount);
|
||||
|
||||
mProximitySensor.unregister(listener);
|
||||
waitForSensorManager();
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
}
|
||||
|
||||
@@ -197,46 +190,35 @@ public class ProximitySensorTest extends SysuiTestCase {
|
||||
|
||||
mProximitySensor.register(listenerA);
|
||||
mProximitySensor.register(listenerB);
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertNull(listenerA.mLastEvent);
|
||||
assertNull(listenerB.mLastEvent);
|
||||
|
||||
mProximitySensor.alertListeners();
|
||||
assertNull(listenerA.mLastEvent);
|
||||
assertEquals(listenerA.mCallCount, 1);
|
||||
assertEquals(0, listenerA.mCallCount);
|
||||
assertNull(listenerB.mLastEvent);
|
||||
assertEquals(listenerB.mCallCount, 1);
|
||||
assertEquals(0, listenerB.mCallCount);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertTrue(listenerA.mLastEvent.getNear());
|
||||
assertEquals(listenerA.mCallCount, 2);
|
||||
assertTrue(listenerB.mLastEvent.getNear());
|
||||
assertEquals(listenerB.mCallCount, 2);
|
||||
mThresholdSensor.triggerEvent(true, 0);
|
||||
assertTrue(listenerA.mLastEvent.getBelow());
|
||||
assertEquals(1, listenerA.mCallCount);
|
||||
assertTrue(listenerB.mLastEvent.getBelow());
|
||||
assertEquals(1, listenerB.mCallCount);
|
||||
|
||||
mProximitySensor.unregister(listenerA);
|
||||
mProximitySensor.unregister(listenerB);
|
||||
waitForSensorManager();
|
||||
}
|
||||
|
||||
class TestableListener implements ProximitySensor.ProximitySensorListener {
|
||||
ProximitySensor.ProximityEvent mLastEvent;
|
||||
private static class TestableListener implements ThresholdSensor.Listener {
|
||||
ThresholdSensor.ThresholdSensorEvent mLastEvent;
|
||||
int mCallCount = 0;
|
||||
|
||||
@Override
|
||||
public void onSensorEvent(ProximitySensor.ProximityEvent proximityEvent) {
|
||||
public void onThresholdCrossed(ThresholdSensor.ThresholdSensorEvent proximityEvent) {
|
||||
mLastEvent = proximityEvent;
|
||||
mCallCount++;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
mLastEvent = null;
|
||||
mCallCount = 0;
|
||||
}
|
||||
};
|
||||
|
||||
private void waitForSensorManager() {
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.util.sensors;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class ThresholdSensorImplTest extends SysuiTestCase {
|
||||
|
||||
private ThresholdSensorImpl mThresholdSensor;
|
||||
private FakeSensorManager.FakeProximitySensor mFakeProximitySensor;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
allowTestableLooperAsMainThread();
|
||||
FakeSensorManager sensorManager = new FakeSensorManager(getContext());
|
||||
|
||||
AsyncSensorManager asyncSensorManager = new AsyncSensorManager(
|
||||
sensorManager, null, new Handler());
|
||||
|
||||
mFakeProximitySensor = sensorManager.getFakeProximitySensor();
|
||||
ThresholdSensorImpl.Builder thresholdSensorBuilder = new ThresholdSensorImpl.Builder(
|
||||
null, asyncSensorManager);
|
||||
mThresholdSensor = (ThresholdSensorImpl) thresholdSensorBuilder
|
||||
.setSensor(mFakeProximitySensor.getSensor())
|
||||
.setThresholdValue(mFakeProximitySensor.getSensor().getMaximumRange())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleListener() {
|
||||
TestableListener listener = new TestableListener();
|
||||
|
||||
assertFalse(mThresholdSensor.isRegistered());
|
||||
mThresholdSensor.register(listener);
|
||||
waitForSensorManager();
|
||||
assertTrue(mThresholdSensor.isRegistered());
|
||||
assertEquals(0, listener.mCallCount);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listener.mBelow);
|
||||
assertEquals(1, listener.mCallCount);
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertTrue(listener.mBelow);
|
||||
assertEquals(2, listener.mCallCount);
|
||||
|
||||
mThresholdSensor.unregister(listener);
|
||||
waitForSensorManager();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiListener() {
|
||||
TestableListener listenerA = new TestableListener();
|
||||
TestableListener listenerB = new TestableListener();
|
||||
|
||||
assertFalse(mThresholdSensor.isRegistered());
|
||||
|
||||
mThresholdSensor.register(listenerA);
|
||||
waitForSensorManager();
|
||||
assertTrue(mThresholdSensor.isRegistered());
|
||||
mThresholdSensor.register(listenerB);
|
||||
waitForSensorManager();
|
||||
assertTrue(mThresholdSensor.isRegistered());
|
||||
assertEquals(0, listenerA.mCallCount);
|
||||
assertEquals(0, listenerB.mCallCount);
|
||||
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listenerA.mBelow);
|
||||
assertFalse(listenerB.mBelow);
|
||||
assertEquals(1, listenerA.mCallCount);
|
||||
assertEquals(1, listenerB.mCallCount);
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertTrue(listenerA.mBelow);
|
||||
assertTrue(listenerB.mBelow);
|
||||
assertEquals(2, listenerA.mCallCount);
|
||||
assertEquals(2, listenerB.mCallCount);
|
||||
|
||||
mThresholdSensor.unregister(listenerA);
|
||||
mThresholdSensor.unregister(listenerB);
|
||||
waitForSensorManager();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDuplicateListener() {
|
||||
TestableListener listenerA = new TestableListener();
|
||||
|
||||
assertFalse(mThresholdSensor.isRegistered());
|
||||
|
||||
mThresholdSensor.register(listenerA);
|
||||
waitForSensorManager();
|
||||
assertTrue(mThresholdSensor.isRegistered());
|
||||
mThresholdSensor.register(listenerA);
|
||||
waitForSensorManager();
|
||||
assertTrue(mThresholdSensor.isRegistered());
|
||||
assertEquals(0, listenerA.mCallCount);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listenerA.mBelow);
|
||||
assertEquals(1, listenerA.mCallCount);
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertTrue(listenerA.mBelow);
|
||||
assertEquals(2, listenerA.mCallCount);
|
||||
|
||||
mThresholdSensor.unregister(listenerA);
|
||||
waitForSensorManager();
|
||||
}
|
||||
@Test
|
||||
public void testUnregister() {
|
||||
TestableListener listener = new TestableListener();
|
||||
|
||||
assertFalse(mThresholdSensor.isRegistered());
|
||||
mThresholdSensor.register(listener);
|
||||
waitForSensorManager();
|
||||
assertTrue(mThresholdSensor.isRegistered());
|
||||
assertEquals(0, listener.mCallCount);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listener.mBelow);
|
||||
assertEquals(1, listener.mCallCount);
|
||||
|
||||
mThresholdSensor.unregister(listener);
|
||||
waitForSensorManager();
|
||||
assertFalse(mThresholdSensor.isRegistered());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPauseAndResume() {
|
||||
TestableListener listener = new TestableListener();
|
||||
|
||||
assertFalse(mThresholdSensor.isRegistered());
|
||||
mThresholdSensor.register(listener);
|
||||
waitForSensorManager();
|
||||
assertTrue(mThresholdSensor.isRegistered());
|
||||
assertEquals(0, listener.mCallCount);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listener.mBelow);
|
||||
assertEquals(1, listener.mCallCount);
|
||||
|
||||
mThresholdSensor.pause();
|
||||
waitForSensorManager();
|
||||
assertFalse(mThresholdSensor.isRegistered());
|
||||
|
||||
// More events do nothing when paused.
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listener.mBelow);
|
||||
assertEquals(1, listener.mCallCount);
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertFalse(listener.mBelow);
|
||||
assertEquals(1, listener.mCallCount);
|
||||
|
||||
mThresholdSensor.resume();
|
||||
waitForSensorManager();
|
||||
assertTrue(mThresholdSensor.isRegistered());
|
||||
// Still matches our previous call
|
||||
assertFalse(listener.mBelow);
|
||||
assertEquals(1, listener.mCallCount);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertTrue(listener.mBelow);
|
||||
assertEquals(2, listener.mCallCount);
|
||||
|
||||
mThresholdSensor.unregister(listener);
|
||||
waitForSensorManager();
|
||||
assertFalse(mThresholdSensor.isRegistered());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlertListeners() {
|
||||
TestableListener listenerA = new TestableListener();
|
||||
TestableListener listenerB = new TestableListener();
|
||||
|
||||
assertFalse(mThresholdSensor.isRegistered());
|
||||
|
||||
mThresholdSensor.register(listenerA);
|
||||
mThresholdSensor.register(listenerB);
|
||||
waitForSensorManager();
|
||||
assertTrue(mThresholdSensor.isRegistered());
|
||||
assertEquals(0, listenerA.mCallCount);
|
||||
assertEquals(0, listenerB.mCallCount);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listenerA.mBelow);
|
||||
assertEquals(1, listenerA.mCallCount);
|
||||
assertFalse(listenerB.mBelow);
|
||||
assertEquals(1, listenerB.mCallCount);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertTrue(listenerA.mBelow);
|
||||
assertEquals(2, listenerA.mCallCount);
|
||||
assertTrue(listenerB.mBelow);
|
||||
assertEquals(2, listenerB.mCallCount);
|
||||
|
||||
mThresholdSensor.unregister(listenerA);
|
||||
mThresholdSensor.unregister(listenerB);
|
||||
waitForSensorManager();
|
||||
}
|
||||
|
||||
static class TestableListener implements ThresholdSensor.Listener {
|
||||
boolean mBelow;
|
||||
long mTimestampNs;
|
||||
int mCallCount;
|
||||
|
||||
@Override
|
||||
public void onThresholdCrossed(ThresholdSensor.ThresholdSensorEvent event) {
|
||||
mBelow = event.getBelow();
|
||||
mTimestampNs = event.getTimestampNs();
|
||||
mCallCount++;
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForSensorManager() {
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user