Loading packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +10 −3 Original line number Diff line number Diff line Loading @@ -34,8 +34,8 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.FalsingPlugin; import com.android.systemui.plugins.PluginListener; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.util.AsyncSensorManager; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.ProximitySensor; import java.io.PrintWriter; Loading @@ -51,6 +51,9 @@ import javax.inject.Singleton; @Singleton public class FalsingManagerProxy implements FalsingManager { private static final String PROXIMITY_SENSOR_TAG = "FalsingManager"; private final ProximitySensor mProximitySensor; private FalsingManager mInternalFalsingManager; private DeviceConfig.OnPropertiesChangedListener mDeviceConfigListener; private final DeviceConfigProxy mDeviceConfig; Loading @@ -58,7 +61,11 @@ public class FalsingManagerProxy implements FalsingManager { @Inject FalsingManagerProxy(Context context, PluginManager pluginManager, @Named(MAIN_HANDLER_NAME) Handler handler, DeviceConfigProxy deviceConfig) { @Named(MAIN_HANDLER_NAME) Handler handler, ProximitySensor proximitySensor, DeviceConfigProxy deviceConfig) { mProximitySensor = proximitySensor; mProximitySensor.setTag(PROXIMITY_SENSOR_TAG); mDeviceConfig = deviceConfig; mDeviceConfigListener = properties -> onDeviceConfigPropertiesChanged(context, properties.getNamespace()); Loading Loading @@ -113,8 +120,8 @@ public class FalsingManagerProxy implements FalsingManager { } else { mInternalFalsingManager = new BrightLineFalsingManager( new FalsingDataProvider(context.getResources().getDisplayMetrics()), Dependency.get(AsyncSensorManager.class), Dependency.get(KeyguardUpdateMonitor.class), mProximitySensor, mDeviceConfig ); } Loading packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java +9 −37 Original line number Diff line number Diff line Loading @@ -19,10 +19,6 @@ package com.android.systemui.classifier.brightline; import static com.android.systemui.classifier.FalsingManagerImpl.FALSING_REMAIN_LOCKED; import static com.android.systemui.classifier.FalsingManagerImpl.FALSING_SUCCESS; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.biometrics.BiometricSourceType; import android.net.Uri; import android.util.Log; Loading @@ -34,12 +30,11 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.classifier.Classifier; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.ProximitySensor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * FalsingManager designed to make clear why a touch was rejected. Loading @@ -49,9 +44,9 @@ public class BrightLineFalsingManager implements FalsingManager { static final boolean DEBUG = false; private static final String TAG = "FalsingManagerPlugin"; private final SensorManager mSensorManager; private final FalsingDataProvider mDataProvider; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final ProximitySensor mProximitySensor; private boolean mSessionStarted; private MetricsLogger mMetricsLogger; private int mIsFalseTouchCalls; Loading @@ -59,20 +54,9 @@ public class BrightLineFalsingManager implements FalsingManager { private boolean mScreenOn; private boolean mJustUnlockedWithFace; private final ExecutorService mBackgroundExecutor = Executors.newSingleThreadExecutor(); private final List<FalsingClassifier> mClassifiers; private SensorEventListener mSensorEventListener = new SensorEventListener() { @Override public synchronized void onSensorChanged(SensorEvent event) { onSensorEvent(event); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }; private ProximitySensor.ProximitySensorListener mSensorEventListener = this::onProximityEvent; private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback = new KeyguardUpdateMonitorCallback() { Loading @@ -88,12 +72,12 @@ public class BrightLineFalsingManager implements FalsingManager { public BrightLineFalsingManager( FalsingDataProvider falsingDataProvider, SensorManager sensorManager, KeyguardUpdateMonitor keyguardUpdateMonitor, ProximitySensor proximitySensor, DeviceConfigProxy deviceConfigProxy) { mKeyguardUpdateMonitor = keyguardUpdateMonitor; mDataProvider = falsingDataProvider; mSensorManager = sensorManager; mProximitySensor = proximitySensor; mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback); mMetricsLogger = new MetricsLogger(); Loading @@ -111,24 +95,12 @@ public class BrightLineFalsingManager implements FalsingManager { } private void registerSensors() { Sensor s = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); if (s != null) { // This can be expensive, and doesn't need to happen on the main thread. mBackgroundExecutor.submit(() -> { logDebug("registering sensor listener"); mSensorManager.registerListener( mSensorEventListener, s, SensorManager.SENSOR_DELAY_GAME); }); } mProximitySensor.register(mSensorEventListener); } private void unregisterSensors() { // This can be expensive, and doesn't need to happen on the main thread. mBackgroundExecutor.submit(() -> { logDebug("unregistering sensor listener"); mSensorManager.unregisterListener(mSensorEventListener); }); mProximitySensor.unregister(mSensorEventListener); } private void sessionStart() { Loading Loading @@ -190,10 +162,10 @@ public class BrightLineFalsingManager implements FalsingManager { mClassifiers.forEach((classifier) -> classifier.onTouchEvent(motionEvent)); } private void onSensorEvent(SensorEvent sensorEvent) { private void onProximityEvent(ProximitySensor.ProximityEvent 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.onSensorEvent(sensorEvent)); mClassifiers.forEach((classifier) -> classifier.onProximityEvent(proximityEvent)); } @Override Loading packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingClassifier.java +3 −3 Original line number Diff line number Diff line Loading @@ -16,10 +16,10 @@ package com.android.systemui.classifier.brightline; import android.hardware.SensorEvent; import android.view.MotionEvent; import com.android.systemui.classifier.Classifier; import com.android.systemui.util.ProximitySensor; import java.util.List; Loading Loading @@ -98,9 +98,9 @@ abstract class FalsingClassifier { void onTouchEvent(MotionEvent motionEvent) {}; /** * Called whenever a SensorEvent occurs, specifically the ProximitySensor. * Called when a ProximityEvent occurs (change in near/far). */ void onSensorEvent(SensorEvent sensorEvent) {}; void onProximityEvent(ProximitySensor.ProximityEvent proximityEvent) {}; /** * The phone screen has turned on and we need to begin falsing detection. Loading packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java +7 −10 Original line number Diff line number Diff line Loading @@ -19,12 +19,11 @@ package com.android.systemui.classifier.brightline; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD; import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.provider.DeviceConfig; import android.view.MotionEvent; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.ProximitySensor; /** Loading Loading @@ -99,14 +98,12 @@ class ProximityClassifier extends FalsingClassifier { } @Override public void onSensorEvent(SensorEvent sensorEvent) { if (sensorEvent.sensor.getType() == Sensor.TYPE_PROXIMITY) { logDebug("Sensor is: " + (sensorEvent.values[0] < sensorEvent.sensor.getMaximumRange()) + " at time " + sensorEvent.timestamp); update( sensorEvent.values[0] < sensorEvent.sensor.getMaximumRange(), sensorEvent.timestamp); } public void onProximityEvent( ProximitySensor.ProximityEvent proximityEvent) { boolean near = proximityEvent.getNear(); long timestampNs = proximityEvent.getTimestampNs(); logDebug("Sensor is: " + near + " at time " + timestampNs); update(near, timestampNs); } @Override Loading packages/SystemUI/src/com/android/systemui/util/ProximitySensor.java 0 → 100644 +186 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.util.Log; import com.android.systemui.R; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; /** * Simple wrapper around SensorManager customized for the Proximity sensor. */ public class ProximitySensor { private static final String TAG = "ProxSensor"; private static final boolean DEBUG = false; private final Sensor mSensor; private final AsyncSensorManager mSensorManager; private final boolean mUsingBrightnessSensor; private final float mMaxRange; private SensorEventListener mSensorEventListener = new SensorEventListener() { @Override public synchronized void onSensorChanged(SensorEvent event) { onSensorEvent(event); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }; private boolean mNear; private List<ProximitySensorListener> mListeners = new ArrayList<>(); private String mTag = null; @Inject public ProximitySensor(Context context, AsyncSensorManager sensorManager) { mSensorManager = sensorManager; Sensor sensor = findBrightnessSensor(context, sensorManager); if (sensor == null) { mUsingBrightnessSensor = false; sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); } else { mUsingBrightnessSensor = true; } mSensor = sensor; if (mSensor != null) { mMaxRange = mSensor.getMaximumRange(); } else { mMaxRange = 0; } } public void setTag(String tag) { mTag = tag; } private Sensor findBrightnessSensor(Context context, SensorManager sensorManager) { String sensorType = context.getString(R.string.doze_brightness_sensor_type); List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL); Sensor sensor = null; for (Sensor s : sensorList) { if (sensorType.equals(s.getStringType())) { sensor = s; break; } } return sensor; } /** * Returns {@code false} if a Proximity sensor is not available. */ public boolean getSensorAvailable() { return mSensor != null; } /** * Add a listener. * * Registers itself with the {@link SensorManager} if this is the first listener * added. */ public boolean register(ProximitySensorListener listener) { if (!getSensorAvailable()) { return false; } logDebug("using brightness sensor? " + mUsingBrightnessSensor); mListeners.add(listener); if (mListeners.size() == 1) { logDebug("registering sensor listener"); mSensorManager.registerListener( mSensorEventListener, mSensor, SensorManager.SENSOR_DELAY_GAME); } return true; } /** * Remove a listener. * * If all listeners are removed from an instance of this class, * it will unregister itself with the SensorManager. */ public void unregister(ProximitySensorListener listener) { mListeners.remove(listener); if (mListeners.size() == 0) { logDebug("unregistering sensor listener"); mSensorManager.unregisterListener(mSensorEventListener); } } public boolean isNear() { return getSensorAvailable() && mNear; } private void onSensorEvent(SensorEvent event) { boolean near = event.values[0] < mMaxRange; if (mUsingBrightnessSensor) { near = event.values[0] == 0; } mNear = near; mListeners.forEach(proximitySensorListener -> proximitySensorListener.onProximitySensorEvent( new ProximityEvent(mNear, event.timestamp))); } /** Implement to be notified of ProximityEvents. */ public interface ProximitySensorListener { /** Called when the ProximitySensor changes. */ void onProximitySensorEvent(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; } } private void logDebug(String msg) { if (DEBUG) { Log.d(TAG, (mTag != null ? "[" + mTag + "] " : "") + msg); } } } Loading
packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +10 −3 Original line number Diff line number Diff line Loading @@ -34,8 +34,8 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.FalsingPlugin; import com.android.systemui.plugins.PluginListener; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.util.AsyncSensorManager; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.ProximitySensor; import java.io.PrintWriter; Loading @@ -51,6 +51,9 @@ import javax.inject.Singleton; @Singleton public class FalsingManagerProxy implements FalsingManager { private static final String PROXIMITY_SENSOR_TAG = "FalsingManager"; private final ProximitySensor mProximitySensor; private FalsingManager mInternalFalsingManager; private DeviceConfig.OnPropertiesChangedListener mDeviceConfigListener; private final DeviceConfigProxy mDeviceConfig; Loading @@ -58,7 +61,11 @@ public class FalsingManagerProxy implements FalsingManager { @Inject FalsingManagerProxy(Context context, PluginManager pluginManager, @Named(MAIN_HANDLER_NAME) Handler handler, DeviceConfigProxy deviceConfig) { @Named(MAIN_HANDLER_NAME) Handler handler, ProximitySensor proximitySensor, DeviceConfigProxy deviceConfig) { mProximitySensor = proximitySensor; mProximitySensor.setTag(PROXIMITY_SENSOR_TAG); mDeviceConfig = deviceConfig; mDeviceConfigListener = properties -> onDeviceConfigPropertiesChanged(context, properties.getNamespace()); Loading Loading @@ -113,8 +120,8 @@ public class FalsingManagerProxy implements FalsingManager { } else { mInternalFalsingManager = new BrightLineFalsingManager( new FalsingDataProvider(context.getResources().getDisplayMetrics()), Dependency.get(AsyncSensorManager.class), Dependency.get(KeyguardUpdateMonitor.class), mProximitySensor, mDeviceConfig ); } Loading
packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java +9 −37 Original line number Diff line number Diff line Loading @@ -19,10 +19,6 @@ package com.android.systemui.classifier.brightline; import static com.android.systemui.classifier.FalsingManagerImpl.FALSING_REMAIN_LOCKED; import static com.android.systemui.classifier.FalsingManagerImpl.FALSING_SUCCESS; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.biometrics.BiometricSourceType; import android.net.Uri; import android.util.Log; Loading @@ -34,12 +30,11 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.classifier.Classifier; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.ProximitySensor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * FalsingManager designed to make clear why a touch was rejected. Loading @@ -49,9 +44,9 @@ public class BrightLineFalsingManager implements FalsingManager { static final boolean DEBUG = false; private static final String TAG = "FalsingManagerPlugin"; private final SensorManager mSensorManager; private final FalsingDataProvider mDataProvider; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final ProximitySensor mProximitySensor; private boolean mSessionStarted; private MetricsLogger mMetricsLogger; private int mIsFalseTouchCalls; Loading @@ -59,20 +54,9 @@ public class BrightLineFalsingManager implements FalsingManager { private boolean mScreenOn; private boolean mJustUnlockedWithFace; private final ExecutorService mBackgroundExecutor = Executors.newSingleThreadExecutor(); private final List<FalsingClassifier> mClassifiers; private SensorEventListener mSensorEventListener = new SensorEventListener() { @Override public synchronized void onSensorChanged(SensorEvent event) { onSensorEvent(event); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }; private ProximitySensor.ProximitySensorListener mSensorEventListener = this::onProximityEvent; private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback = new KeyguardUpdateMonitorCallback() { Loading @@ -88,12 +72,12 @@ public class BrightLineFalsingManager implements FalsingManager { public BrightLineFalsingManager( FalsingDataProvider falsingDataProvider, SensorManager sensorManager, KeyguardUpdateMonitor keyguardUpdateMonitor, ProximitySensor proximitySensor, DeviceConfigProxy deviceConfigProxy) { mKeyguardUpdateMonitor = keyguardUpdateMonitor; mDataProvider = falsingDataProvider; mSensorManager = sensorManager; mProximitySensor = proximitySensor; mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback); mMetricsLogger = new MetricsLogger(); Loading @@ -111,24 +95,12 @@ public class BrightLineFalsingManager implements FalsingManager { } private void registerSensors() { Sensor s = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); if (s != null) { // This can be expensive, and doesn't need to happen on the main thread. mBackgroundExecutor.submit(() -> { logDebug("registering sensor listener"); mSensorManager.registerListener( mSensorEventListener, s, SensorManager.SENSOR_DELAY_GAME); }); } mProximitySensor.register(mSensorEventListener); } private void unregisterSensors() { // This can be expensive, and doesn't need to happen on the main thread. mBackgroundExecutor.submit(() -> { logDebug("unregistering sensor listener"); mSensorManager.unregisterListener(mSensorEventListener); }); mProximitySensor.unregister(mSensorEventListener); } private void sessionStart() { Loading Loading @@ -190,10 +162,10 @@ public class BrightLineFalsingManager implements FalsingManager { mClassifiers.forEach((classifier) -> classifier.onTouchEvent(motionEvent)); } private void onSensorEvent(SensorEvent sensorEvent) { private void onProximityEvent(ProximitySensor.ProximityEvent 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.onSensorEvent(sensorEvent)); mClassifiers.forEach((classifier) -> classifier.onProximityEvent(proximityEvent)); } @Override Loading
packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingClassifier.java +3 −3 Original line number Diff line number Diff line Loading @@ -16,10 +16,10 @@ package com.android.systemui.classifier.brightline; import android.hardware.SensorEvent; import android.view.MotionEvent; import com.android.systemui.classifier.Classifier; import com.android.systemui.util.ProximitySensor; import java.util.List; Loading Loading @@ -98,9 +98,9 @@ abstract class FalsingClassifier { void onTouchEvent(MotionEvent motionEvent) {}; /** * Called whenever a SensorEvent occurs, specifically the ProximitySensor. * Called when a ProximityEvent occurs (change in near/far). */ void onSensorEvent(SensorEvent sensorEvent) {}; void onProximityEvent(ProximitySensor.ProximityEvent proximityEvent) {}; /** * The phone screen has turned on and we need to begin falsing detection. Loading
packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java +7 −10 Original line number Diff line number Diff line Loading @@ -19,12 +19,11 @@ package com.android.systemui.classifier.brightline; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD; import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.provider.DeviceConfig; import android.view.MotionEvent; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.ProximitySensor; /** Loading Loading @@ -99,14 +98,12 @@ class ProximityClassifier extends FalsingClassifier { } @Override public void onSensorEvent(SensorEvent sensorEvent) { if (sensorEvent.sensor.getType() == Sensor.TYPE_PROXIMITY) { logDebug("Sensor is: " + (sensorEvent.values[0] < sensorEvent.sensor.getMaximumRange()) + " at time " + sensorEvent.timestamp); update( sensorEvent.values[0] < sensorEvent.sensor.getMaximumRange(), sensorEvent.timestamp); } public void onProximityEvent( ProximitySensor.ProximityEvent proximityEvent) { boolean near = proximityEvent.getNear(); long timestampNs = proximityEvent.getTimestampNs(); logDebug("Sensor is: " + near + " at time " + timestampNs); update(near, timestampNs); } @Override Loading
packages/SystemUI/src/com/android/systemui/util/ProximitySensor.java 0 → 100644 +186 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.util.Log; import com.android.systemui.R; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; /** * Simple wrapper around SensorManager customized for the Proximity sensor. */ public class ProximitySensor { private static final String TAG = "ProxSensor"; private static final boolean DEBUG = false; private final Sensor mSensor; private final AsyncSensorManager mSensorManager; private final boolean mUsingBrightnessSensor; private final float mMaxRange; private SensorEventListener mSensorEventListener = new SensorEventListener() { @Override public synchronized void onSensorChanged(SensorEvent event) { onSensorEvent(event); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }; private boolean mNear; private List<ProximitySensorListener> mListeners = new ArrayList<>(); private String mTag = null; @Inject public ProximitySensor(Context context, AsyncSensorManager sensorManager) { mSensorManager = sensorManager; Sensor sensor = findBrightnessSensor(context, sensorManager); if (sensor == null) { mUsingBrightnessSensor = false; sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); } else { mUsingBrightnessSensor = true; } mSensor = sensor; if (mSensor != null) { mMaxRange = mSensor.getMaximumRange(); } else { mMaxRange = 0; } } public void setTag(String tag) { mTag = tag; } private Sensor findBrightnessSensor(Context context, SensorManager sensorManager) { String sensorType = context.getString(R.string.doze_brightness_sensor_type); List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL); Sensor sensor = null; for (Sensor s : sensorList) { if (sensorType.equals(s.getStringType())) { sensor = s; break; } } return sensor; } /** * Returns {@code false} if a Proximity sensor is not available. */ public boolean getSensorAvailable() { return mSensor != null; } /** * Add a listener. * * Registers itself with the {@link SensorManager} if this is the first listener * added. */ public boolean register(ProximitySensorListener listener) { if (!getSensorAvailable()) { return false; } logDebug("using brightness sensor? " + mUsingBrightnessSensor); mListeners.add(listener); if (mListeners.size() == 1) { logDebug("registering sensor listener"); mSensorManager.registerListener( mSensorEventListener, mSensor, SensorManager.SENSOR_DELAY_GAME); } return true; } /** * Remove a listener. * * If all listeners are removed from an instance of this class, * it will unregister itself with the SensorManager. */ public void unregister(ProximitySensorListener listener) { mListeners.remove(listener); if (mListeners.size() == 0) { logDebug("unregistering sensor listener"); mSensorManager.unregisterListener(mSensorEventListener); } } public boolean isNear() { return getSensorAvailable() && mNear; } private void onSensorEvent(SensorEvent event) { boolean near = event.values[0] < mMaxRange; if (mUsingBrightnessSensor) { near = event.values[0] == 0; } mNear = near; mListeners.forEach(proximitySensorListener -> proximitySensorListener.onProximitySensorEvent( new ProximityEvent(mNear, event.timestamp))); } /** Implement to be notified of ProximityEvents. */ public interface ProximitySensorListener { /** Called when the ProximitySensor changes. */ void onProximitySensorEvent(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; } } private void logDebug(String msg) { if (DEBUG) { Log.d(TAG, (mTag != null ? "[" + mTag + "] " : "") + msg); } } }