Merge "Add posture support for prox sensor" into sc-v2-dev
This commit is contained in:
@@ -24,6 +24,8 @@ import android.provider.Settings;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -258,10 +260,11 @@ public class AmbientDisplayConfiguration {
|
|||||||
String defaultValue,
|
String defaultValue,
|
||||||
int posture) {
|
int posture) {
|
||||||
String sensorType = defaultValue;
|
String sensorType = defaultValue;
|
||||||
if (posture < postureMapping.length) {
|
if (postureMapping != null && posture < postureMapping.length) {
|
||||||
sensorType = postureMapping[posture];
|
sensorType = postureMapping[posture];
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "Unsupported doze posture " + posture);
|
Log.e(TAG, "Unsupported doze posture " + posture
|
||||||
|
+ " postureMapping=" + Arrays.toString(postureMapping));
|
||||||
}
|
}
|
||||||
|
|
||||||
return TextUtils.isEmpty(sensorType) ? defaultValue : sensorType;
|
return TextUtils.isEmpty(sensorType) ? defaultValue : sensorType;
|
||||||
|
|||||||
@@ -224,15 +224,23 @@
|
|||||||
display brightness, suitable to listen to while the device is asleep (e.g. during
|
display brightness, suitable to listen to while the device is asleep (e.g. during
|
||||||
always-on display) -->
|
always-on display) -->
|
||||||
<string-array name="doze_brightness_sensor_name_posture_mapping" translatable="false">
|
<string-array name="doze_brightness_sensor_name_posture_mapping" translatable="false">
|
||||||
<item></item> <!-- UNKNOWN -->
|
<!-- UNKNOWN -->
|
||||||
<item></item> <!-- CLOSED -->
|
<!-- CLOSED -->
|
||||||
<item></item> <!-- HALF_OPENED -->
|
<!-- HALF_OPENED -->
|
||||||
<item></item> <!-- OPENED -->
|
<!-- OPENED -->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Override value to use for proximity sensor. -->
|
<!-- Override value to use for proximity sensor. -->
|
||||||
<string name="proximity_sensor_type" translatable="false"></string>
|
<string name="proximity_sensor_type" translatable="false"></string>
|
||||||
|
|
||||||
|
<!-- Sensor type per posture state to use for proximity sensor -->
|
||||||
|
<string-array name="proximity_sensor_posture_mapping" translatable="false">
|
||||||
|
<!-- UNKNOWN -->
|
||||||
|
<!-- CLOSED -->
|
||||||
|
<!-- HALF_OPENED -->
|
||||||
|
<!-- OPENED -->
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<!-- If using proximity_sensor_type, specifies a threshold value to distinguish near and
|
<!-- If using proximity_sensor_type, specifies a threshold value to distinguish near and
|
||||||
far break points. A sensor value less than this is considered "near". -->
|
far break points. A sensor value less than this is considered "near". -->
|
||||||
<item name="proximity_sensor_threshold" translatable="false" format="float" type="dimen"></item>
|
<item name="proximity_sensor_threshold" translatable="false" format="float" type="dimen"></item>
|
||||||
@@ -246,6 +254,15 @@
|
|||||||
<!-- Override value to use for proximity sensor as confirmation for proximity_sensor_type. -->
|
<!-- Override value to use for proximity sensor as confirmation for proximity_sensor_type. -->
|
||||||
<string name="proximity_sensor_secondary_type" translatable="false"></string>
|
<string name="proximity_sensor_secondary_type" translatable="false"></string>
|
||||||
|
|
||||||
|
<!-- Sensor type per posture state to use for proximity sensor as a confirmation for
|
||||||
|
proximity_sensor_type. -->
|
||||||
|
<string-array name="proximity_sensor_secondary_posture_mapping" translatable="false">
|
||||||
|
<!-- UNKNOWN -->
|
||||||
|
<!-- CLOSED -->
|
||||||
|
<!-- HALF_OPENED -->
|
||||||
|
<!-- OPENED -->
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<!-- If using proximity_sensor_secondary_type, specifies a threshold value to distinguish
|
<!-- If using proximity_sensor_secondary_type, specifies a threshold value to distinguish
|
||||||
near and far break points. A sensor value less than this is considered "near". -->
|
near and far break points. A sensor value less than this is considered "near". -->
|
||||||
<item name="proximity_sensor_secondary_threshold" translatable="false" format="float"
|
<item name="proximity_sensor_secondary_threshold" translatable="false" format="float"
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
|
|||||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||||
import com.android.systemui.util.sensors.ProximitySensor;
|
import com.android.systemui.util.sensors.ProximitySensor;
|
||||||
import com.android.systemui.util.sensors.ThresholdSensor;
|
import com.android.systemui.util.sensors.ThresholdSensor;
|
||||||
|
import com.android.systemui.util.sensors.ThresholdSensorEvent;
|
||||||
import com.android.systemui.util.time.SystemClock;
|
import com.android.systemui.util.time.SystemClock;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -405,7 +406,7 @@ class FalsingCollectorImpl implements FalsingCollector {
|
|||||||
mProximitySensor.unregister(mSensorEventListener);
|
mProximitySensor.unregister(mSensorEventListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onProximityEvent(ThresholdSensor.ThresholdSensorEvent proximityEvent) {
|
private void onProximityEvent(ThresholdSensorEvent proximityEvent) {
|
||||||
// TODO: some of these classifiers might allow us to abort early, meaning we don't have to
|
// TODO: some of these classifiers might allow us to abort early, meaning we don't have to
|
||||||
// make these calls.
|
// make these calls.
|
||||||
mFalsingManager.onProximityEvent(new ProximityEventImpl(proximityEvent));
|
mFalsingManager.onProximityEvent(new ProximityEventImpl(proximityEvent));
|
||||||
@@ -423,9 +424,9 @@ class FalsingCollectorImpl implements FalsingCollector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class ProximityEventImpl implements FalsingManager.ProximityEvent {
|
private static class ProximityEventImpl implements FalsingManager.ProximityEvent {
|
||||||
private ThresholdSensor.ThresholdSensorEvent mThresholdSensorEvent;
|
private ThresholdSensorEvent mThresholdSensorEvent;
|
||||||
|
|
||||||
ProximityEventImpl(ThresholdSensor.ThresholdSensorEvent thresholdSensorEvent) {
|
ProximityEventImpl(ThresholdSensorEvent thresholdSensorEvent) {
|
||||||
mThresholdSensorEvent = thresholdSensorEvent;
|
mThresholdSensorEvent = thresholdSensorEvent;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
|
|||||||
import com.android.systemui.util.Assert;
|
import com.android.systemui.util.Assert;
|
||||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||||
import com.android.systemui.util.sensors.AsyncSensorManager;
|
import com.android.systemui.util.sensors.AsyncSensorManager;
|
||||||
|
import com.android.systemui.util.sensors.ProximityCheck;
|
||||||
import com.android.systemui.util.sensors.ProximitySensor;
|
import com.android.systemui.util.sensors.ProximitySensor;
|
||||||
import com.android.systemui.util.settings.SecureSettings;
|
import com.android.systemui.util.settings.SecureSettings;
|
||||||
import com.android.systemui.util.wakelock.WakeLock;
|
import com.android.systemui.util.wakelock.WakeLock;
|
||||||
@@ -90,7 +91,7 @@ public class DozeTriggers implements DozeMachine.Part {
|
|||||||
private final TriggerReceiver mBroadcastReceiver = new TriggerReceiver();
|
private final TriggerReceiver mBroadcastReceiver = new TriggerReceiver();
|
||||||
private final DockEventListener mDockEventListener = new DockEventListener();
|
private final DockEventListener mDockEventListener = new DockEventListener();
|
||||||
private final DockManager mDockManager;
|
private final DockManager mDockManager;
|
||||||
private final ProximitySensor.ProximityCheck mProxCheck;
|
private final ProximityCheck mProxCheck;
|
||||||
private final BroadcastDispatcher mBroadcastDispatcher;
|
private final BroadcastDispatcher mBroadcastDispatcher;
|
||||||
private final AuthController mAuthController;
|
private final AuthController mAuthController;
|
||||||
private final DelayableExecutor mMainExecutor;
|
private final DelayableExecutor mMainExecutor;
|
||||||
@@ -181,7 +182,8 @@ public class DozeTriggers implements DozeMachine.Part {
|
|||||||
AmbientDisplayConfiguration config,
|
AmbientDisplayConfiguration config,
|
||||||
DozeParameters dozeParameters, AsyncSensorManager sensorManager,
|
DozeParameters dozeParameters, AsyncSensorManager sensorManager,
|
||||||
WakeLock wakeLock, DockManager dockManager,
|
WakeLock wakeLock, DockManager dockManager,
|
||||||
ProximitySensor proximitySensor, ProximitySensor.ProximityCheck proxCheck,
|
ProximitySensor proximitySensor,
|
||||||
|
ProximityCheck proxCheck,
|
||||||
DozeLog dozeLog, BroadcastDispatcher broadcastDispatcher,
|
DozeLog dozeLog, BroadcastDispatcher broadcastDispatcher,
|
||||||
SecureSettings secureSettings, AuthController authController,
|
SecureSettings secureSettings, AuthController authController,
|
||||||
@Main DelayableExecutor mainExecutor,
|
@Main DelayableExecutor mainExecutor,
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ public interface DevicePostureController extends CallbackController<Callback> {
|
|||||||
int DEVICE_POSTURE_HALF_OPENED = 2;
|
int DEVICE_POSTURE_HALF_OPENED = 2;
|
||||||
int DEVICE_POSTURE_OPENED = 3;
|
int DEVICE_POSTURE_OPENED = 3;
|
||||||
int DEVICE_POSTURE_FLIPPED = 4;
|
int DEVICE_POSTURE_FLIPPED = 4;
|
||||||
|
int SUPPORTED_POSTURES_SIZE = DEVICE_POSTURE_FLIPPED + 1;
|
||||||
|
|
||||||
/** Return the current device posture. */
|
/** Return the current device posture. */
|
||||||
@DevicePostureInt int getDevicePosture();
|
@DevicePostureInt int getDevicePosture();
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.android.systemui.statusbar.policy.DevicePostureController;
|
||||||
|
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||||
|
import com.android.systemui.util.concurrency.Execution;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proximity sensor that changes proximity sensor usage based on the current posture.
|
||||||
|
* Posture -> prox sensor mapping can be found in SystemUI config overlays at:
|
||||||
|
* - proximity_sensor_posture_mapping
|
||||||
|
* - proximity_sensor_secondary_posture_mapping.
|
||||||
|
* where the array indices correspond to the following postures:
|
||||||
|
* [UNKNOWN, CLOSED, HALF_OPENED, OPENED]
|
||||||
|
*/
|
||||||
|
class PostureDependentProximitySensor extends ProximitySensorImpl {
|
||||||
|
private final ThresholdSensor[] mPostureToPrimaryProxSensorMap;
|
||||||
|
private final ThresholdSensor[] mPostureToSecondaryProxSensorMap;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PostureDependentProximitySensor(
|
||||||
|
@PrimaryProxSensor ThresholdSensor[] postureToPrimaryProxSensorMap,
|
||||||
|
@SecondaryProxSensor ThresholdSensor[] postureToSecondaryProxSensorMap,
|
||||||
|
@NonNull DelayableExecutor delayableExecutor,
|
||||||
|
@NonNull Execution execution,
|
||||||
|
@NonNull DevicePostureController devicePostureController
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
postureToPrimaryProxSensorMap[0],
|
||||||
|
postureToSecondaryProxSensorMap[0],
|
||||||
|
delayableExecutor,
|
||||||
|
execution
|
||||||
|
);
|
||||||
|
mPostureToPrimaryProxSensorMap = postureToPrimaryProxSensorMap;
|
||||||
|
mPostureToSecondaryProxSensorMap = postureToSecondaryProxSensorMap;
|
||||||
|
mDevicePosture = devicePostureController.getDevicePosture();
|
||||||
|
devicePostureController.addCallback(mDevicePostureCallback);
|
||||||
|
|
||||||
|
chooseSensors();
|
||||||
|
}
|
||||||
|
private void chooseSensors() {
|
||||||
|
if (mDevicePosture >= mPostureToPrimaryProxSensorMap.length
|
||||||
|
|| mDevicePosture >= mPostureToSecondaryProxSensorMap.length) {
|
||||||
|
Log.e("PostureDependentProxSensor",
|
||||||
|
"unsupported devicePosture=" + mDevicePosture);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThresholdSensor newPrimaryProx = mPostureToPrimaryProxSensorMap[mDevicePosture];
|
||||||
|
ThresholdSensor newSecondaryProx = mPostureToSecondaryProxSensorMap[mDevicePosture];
|
||||||
|
|
||||||
|
if (newPrimaryProx != mPrimaryThresholdSensor
|
||||||
|
|| newSecondaryProx != mSecondaryThresholdSensor) {
|
||||||
|
logDebug("Register new proximity sensors newPosture="
|
||||||
|
+ DevicePostureController.devicePostureToString(mDevicePosture));
|
||||||
|
unregisterInternal();
|
||||||
|
|
||||||
|
if (mPrimaryThresholdSensor != null) {
|
||||||
|
mPrimaryThresholdSensor.unregister(mPrimaryEventListener);
|
||||||
|
}
|
||||||
|
if (mSecondaryThresholdSensor != null) {
|
||||||
|
mSecondaryThresholdSensor.unregister(mSecondaryEventListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
mPrimaryThresholdSensor = newPrimaryProx;
|
||||||
|
mSecondaryThresholdSensor = newSecondaryProx;
|
||||||
|
|
||||||
|
mInitializedListeners = false;
|
||||||
|
registerInternal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final DevicePostureController.Callback mDevicePostureCallback =
|
||||||
|
posture -> {
|
||||||
|
if (mDevicePosture == posture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDevicePosture = posture;
|
||||||
|
chooseSensors();
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("{posture=%s, proximitySensor=%s}",
|
||||||
|
DevicePostureController.devicePostureToString(mDevicePosture), super.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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 com.android.systemui.dagger.qualifiers.Main;
|
||||||
|
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience class allowing for briefly checking the proximity sensor.
|
||||||
|
*/
|
||||||
|
public class ProximityCheck implements Runnable {
|
||||||
|
|
||||||
|
private final ProximitySensor mSensor;
|
||||||
|
private final DelayableExecutor mDelayableExecutor;
|
||||||
|
private List<Consumer<Boolean>> mCallbacks = new ArrayList<>();
|
||||||
|
private final ThresholdSensor.Listener mListener;
|
||||||
|
private final AtomicBoolean mRegistered = new AtomicBoolean();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ProximityCheck(
|
||||||
|
ProximitySensor sensor,
|
||||||
|
@Main DelayableExecutor delayableExecutor) {
|
||||||
|
mSensor = sensor;
|
||||||
|
mSensor.setTag("prox_check");
|
||||||
|
mDelayableExecutor = delayableExecutor;
|
||||||
|
mListener = this::onProximityEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set a descriptive tag for the sensors registration. */
|
||||||
|
public void setTag(String tag) {
|
||||||
|
mSensor.setTag(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
unregister();
|
||||||
|
onProximityEvent(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the proximity sensor, timing out if no result.
|
||||||
|
*/
|
||||||
|
public void check(long timeoutMs, Consumer<Boolean> callback) {
|
||||||
|
if (!mSensor.isLoaded()) {
|
||||||
|
callback.accept(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mCallbacks.add(callback);
|
||||||
|
if (!mRegistered.getAndSet(true)) {
|
||||||
|
mSensor.register(mListener);
|
||||||
|
mDelayableExecutor.executeDelayed(this, timeoutMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unregister() {
|
||||||
|
mSensor.unregister(mListener);
|
||||||
|
mRegistered.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onProximityEvent(ThresholdSensorEvent proximityEvent) {
|
||||||
|
mCallbacks.forEach(
|
||||||
|
booleanConsumer ->
|
||||||
|
booleanConsumer.accept(
|
||||||
|
proximityEvent == null ? null : proximityEvent.getBelow()));
|
||||||
|
mCallbacks.clear();
|
||||||
|
unregister();
|
||||||
|
mRegistered.set(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2019 The Android Open Source Project
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,149 +16,24 @@
|
|||||||
|
|
||||||
package com.android.systemui.util.sensors;
|
package com.android.systemui.util.sensors;
|
||||||
|
|
||||||
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.concurrency.DelayableExecutor;
|
|
||||||
import com.android.systemui.util.concurrency.Execution;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper around SensorManager customized for the Proximity sensor.
|
* Wrapper class for a dual ProximitySensor which supports a secondary sensor gated upon the
|
||||||
*
|
* primary).
|
||||||
* 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 implements ThresholdSensor {
|
public interface ProximitySensor extends ThresholdSensor {
|
||||||
private static final String TAG = "ProxSensor";
|
/**
|
||||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
* Returns true if we are registered with the SensorManager.
|
||||||
private static final long SECONDARY_PING_INTERVAL_MS = 5000;
|
*/
|
||||||
|
boolean isRegistered();
|
||||||
private final ThresholdSensor mPrimaryThresholdSensor;
|
|
||||||
private final ThresholdSensor mSecondaryThresholdSensor;
|
|
||||||
private final DelayableExecutor mDelayableExecutor;
|
|
||||||
private final Execution mExecution;
|
|
||||||
private final List<ThresholdSensor.Listener> mListeners = new ArrayList<>();
|
|
||||||
private String mTag = null;
|
|
||||||
@VisibleForTesting protected boolean mPaused;
|
|
||||||
private ThresholdSensorEvent mLastPrimaryEvent;
|
|
||||||
@VisibleForTesting
|
|
||||||
ThresholdSensorEvent mLastEvent;
|
|
||||||
private boolean mRegistered;
|
|
||||||
private final AtomicBoolean mAlerting = new AtomicBoolean();
|
|
||||||
private Runnable mCancelSecondaryRunnable;
|
|
||||||
private boolean mInitializedListeners = false;
|
|
||||||
private boolean mSecondarySafe = false;
|
|
||||||
|
|
||||||
private final ThresholdSensor.Listener mPrimaryEventListener = this::onPrimarySensorEvent;
|
|
||||||
|
|
||||||
private final ThresholdSensor.Listener mSecondaryEventListener =
|
|
||||||
new ThresholdSensor.Listener() {
|
|
||||||
@Override
|
|
||||||
public void onThresholdCrossed(ThresholdSensorEvent event) {
|
|
||||||
// If we no longer have a "below" signal and the secondary sensor is not
|
|
||||||
// considered "safe", then we need to turn it off.
|
|
||||||
if (!mSecondarySafe
|
|
||||||
&& (mLastPrimaryEvent == null
|
|
||||||
|| !mLastPrimaryEvent.getBelow()
|
|
||||||
|| !event.getBelow())) {
|
|
||||||
chooseSensor();
|
|
||||||
if (mLastPrimaryEvent == null || !mLastPrimaryEvent.getBelow()) {
|
|
||||||
// Only check the secondary as long as the primary thinks we're near.
|
|
||||||
if (mCancelSecondaryRunnable != null) {
|
|
||||||
mCancelSecondaryRunnable.run();
|
|
||||||
mCancelSecondaryRunnable = null;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// Check this sensor again in a moment.
|
|
||||||
mCancelSecondaryRunnable = mDelayableExecutor.executeDelayed(() -> {
|
|
||||||
// This is safe because we know that mSecondaryThresholdSensor
|
|
||||||
// is loaded, otherwise we wouldn't be here.
|
|
||||||
mPrimaryThresholdSensor.pause();
|
|
||||||
mSecondaryThresholdSensor.resume();
|
|
||||||
},
|
|
||||||
SECONDARY_PING_INTERVAL_MS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logDebug("Secondary sensor event: " + event.getBelow() + ".");
|
|
||||||
|
|
||||||
if (!mPaused) {
|
|
||||||
onSensorEvent(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public ProximitySensor(
|
|
||||||
@PrimaryProxSensor ThresholdSensor primary,
|
|
||||||
@SecondaryProxSensor ThresholdSensor secondary,
|
|
||||||
@Main DelayableExecutor delayableExecutor,
|
|
||||||
Execution execution) {
|
|
||||||
mPrimaryThresholdSensor = primary;
|
|
||||||
mSecondaryThresholdSensor = secondary;
|
|
||||||
mDelayableExecutor = delayableExecutor;
|
|
||||||
mExecution = execution;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setTag(String tag) {
|
|
||||||
mTag = tag;
|
|
||||||
mPrimaryThresholdSensor.setTag(tag + ":primary");
|
|
||||||
mSecondaryThresholdSensor.setTag(tag + ":secondary");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDelay(int delay) {
|
|
||||||
mExecution.assertIsMainThread();
|
|
||||||
mPrimaryThresholdSensor.setDelay(delay);
|
|
||||||
mSecondaryThresholdSensor.setDelay(delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregister with the {@link SensorManager} without unsetting listeners on this object.
|
* Whether the proximity sensor reports near. Can return null if no information has been
|
||||||
|
* received yet.
|
||||||
*/
|
*/
|
||||||
@Override
|
Boolean isNear();
|
||||||
public void pause() {
|
|
||||||
mExecution.assertIsMainThread();
|
|
||||||
mPaused = true;
|
|
||||||
unregisterInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Update all listeners with the last value this class received from the sensor. */
|
||||||
* Register with the {@link SensorManager}. No-op if no listeners are registered on this object.
|
void alertListeners();
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void resume() {
|
|
||||||
mExecution.assertIsMainThread();
|
|
||||||
mPaused = false;
|
|
||||||
registerInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets that it is safe to leave the secondary sensor on indefinitely.
|
* Sets that it is safe to leave the secondary sensor on indefinitely.
|
||||||
@@ -166,249 +41,5 @@ public class ProximitySensor implements ThresholdSensor {
|
|||||||
* The secondary sensor will be turned on if there are any registered listeners, regardless
|
* The secondary sensor will be turned on if there are any registered listeners, regardless
|
||||||
* of what is reported by the primary sensor.
|
* of what is reported by the primary sensor.
|
||||||
*/
|
*/
|
||||||
public void setSecondarySafe(boolean safe) {
|
void setSecondarySafe(boolean safe);
|
||||||
mSecondarySafe = mSecondaryThresholdSensor.isLoaded() && safe;
|
|
||||||
chooseSensor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if we are registered with the SensorManager.
|
|
||||||
*/
|
|
||||||
public boolean isRegistered() {
|
|
||||||
return mRegistered;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns {@code false} if a Proximity sensor is not available.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isLoaded() {
|
|
||||||
return mPrimaryThresholdSensor.isLoaded();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a listener.
|
|
||||||
*
|
|
||||||
* Registers itself with the {@link SensorManager} if this is the first listener
|
|
||||||
* added. If the ProximitySensor is paused, it will be registered when resumed.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void register(ThresholdSensor.Listener listener) {
|
|
||||||
mExecution.assertIsMainThread();
|
|
||||||
if (!isLoaded()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mListeners.contains(listener)) {
|
|
||||||
logDebug("ProxListener registered multiple times: " + listener);
|
|
||||||
} else {
|
|
||||||
mListeners.add(listener);
|
|
||||||
}
|
|
||||||
registerInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void registerInternal() {
|
|
||||||
mExecution.assertIsMainThread();
|
|
||||||
if (mRegistered || mPaused || mListeners.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!mInitializedListeners) {
|
|
||||||
mPrimaryThresholdSensor.pause();
|
|
||||||
mSecondaryThresholdSensor.pause();
|
|
||||||
mPrimaryThresholdSensor.register(mPrimaryEventListener);
|
|
||||||
mSecondaryThresholdSensor.register(mSecondaryEventListener);
|
|
||||||
mInitializedListeners = true;
|
|
||||||
}
|
|
||||||
logDebug("Registering sensor listener");
|
|
||||||
|
|
||||||
mRegistered = true;
|
|
||||||
chooseSensor();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void chooseSensor() {
|
|
||||||
mExecution.assertIsMainThread();
|
|
||||||
if (!mRegistered || mPaused || mListeners.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mSecondarySafe) {
|
|
||||||
mSecondaryThresholdSensor.resume();
|
|
||||||
mPrimaryThresholdSensor.pause();
|
|
||||||
} else {
|
|
||||||
mPrimaryThresholdSensor.resume();
|
|
||||||
mSecondaryThresholdSensor.pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a listener.
|
|
||||||
*
|
|
||||||
* If all listeners are removed from an instance of this class,
|
|
||||||
* it will unregister itself with the SensorManager.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void unregister(ThresholdSensor.Listener listener) {
|
|
||||||
mExecution.assertIsMainThread();
|
|
||||||
mListeners.remove(listener);
|
|
||||||
if (mListeners.size() == 0) {
|
|
||||||
unregisterInternal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void unregisterInternal() {
|
|
||||||
mExecution.assertIsMainThread();
|
|
||||||
if (!mRegistered) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
logDebug("unregistering sensor listener");
|
|
||||||
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 isLoaded() && mLastEvent != null ? mLastEvent.getBelow() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Update all listeners with the last value this class received from the sensor. */
|
|
||||||
public void alertListeners() {
|
|
||||||
mExecution.assertIsMainThread();
|
|
||||||
if (mAlerting.getAndSet(true)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mLastEvent != null) {
|
|
||||||
ThresholdSensorEvent lastEvent = mLastEvent; // Listeners can null out mLastEvent.
|
|
||||||
List<ThresholdSensor.Listener> listeners = new ArrayList<>(mListeners);
|
|
||||||
listeners.forEach(proximitySensorListener ->
|
|
||||||
proximitySensorListener.onThresholdCrossed(lastEvent));
|
|
||||||
}
|
|
||||||
|
|
||||||
mAlerting.set(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onPrimarySensorEvent(ThresholdSensorEvent event) {
|
|
||||||
mExecution.assertIsMainThread();
|
|
||||||
if (mLastPrimaryEvent != null && event.getBelow() == mLastPrimaryEvent.getBelow()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mLastPrimaryEvent = event;
|
|
||||||
|
|
||||||
if (mSecondarySafe && mSecondaryThresholdSensor.isLoaded()) {
|
|
||||||
logDebug("Primary sensor reported " + (event.getBelow() ? "near" : "far")
|
|
||||||
+ ". Checking secondary.");
|
|
||||||
if (mCancelSecondaryRunnable == null) {
|
|
||||||
mSecondaryThresholdSensor.resume();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (!mSecondaryThresholdSensor.isLoaded()) { // No secondary
|
|
||||||
logDebug("Primary sensor event: " + event.getBelow() + ". No secondary.");
|
|
||||||
onSensorEvent(event);
|
|
||||||
} else if (event.getBelow()) { // Covered? Check secondary.
|
|
||||||
logDebug("Primary sensor event: " + event.getBelow() + ". Checking secondary.");
|
|
||||||
if (mCancelSecondaryRunnable != null) {
|
|
||||||
mCancelSecondaryRunnable.run();
|
|
||||||
}
|
|
||||||
mSecondaryThresholdSensor.resume();
|
|
||||||
} else { // Uncovered. Report immediately.
|
|
||||||
onSensorEvent(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onSensorEvent(ThresholdSensorEvent event) {
|
|
||||||
mExecution.assertIsMainThread();
|
|
||||||
if (mLastEvent != null && event.getBelow() == mLastEvent.getBelow()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mSecondarySafe && !event.getBelow()) {
|
|
||||||
chooseSensor();
|
|
||||||
}
|
|
||||||
|
|
||||||
mLastEvent = event;
|
|
||||||
alertListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("{registered=%s, paused=%s, near=%s, primarySensor=%s, "
|
|
||||||
+ "secondarySensor=%s secondarySafe=%s}",
|
|
||||||
isRegistered(), mPaused, isNear(), mPrimaryThresholdSensor,
|
|
||||||
mSecondaryThresholdSensor, mSecondarySafe);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience class allowing for briefly checking the proximity sensor.
|
|
||||||
*/
|
|
||||||
public static class ProximityCheck implements Runnable {
|
|
||||||
|
|
||||||
private final ProximitySensor mSensor;
|
|
||||||
private final DelayableExecutor mDelayableExecutor;
|
|
||||||
private List<Consumer<Boolean>> mCallbacks = new ArrayList<>();
|
|
||||||
private final ThresholdSensor.Listener mListener;
|
|
||||||
private final AtomicBoolean mRegistered = new AtomicBoolean();
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public ProximityCheck(ProximitySensor sensor, @Main DelayableExecutor delayableExecutor) {
|
|
||||||
mSensor = sensor;
|
|
||||||
mSensor.setTag("prox_check");
|
|
||||||
mDelayableExecutor = delayableExecutor;
|
|
||||||
mListener = this::onProximityEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set a descriptive tag for the sensors registration. */
|
|
||||||
public void setTag(String tag) {
|
|
||||||
mSensor.setTag(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
unregister();
|
|
||||||
onProximityEvent(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Query the proximity sensor, timing out if no result.
|
|
||||||
*/
|
|
||||||
public void check(long timeoutMs, Consumer<Boolean> callback) {
|
|
||||||
if (!mSensor.isLoaded()) {
|
|
||||||
callback.accept(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mCallbacks.add(callback);
|
|
||||||
if (!mRegistered.getAndSet(true)) {
|
|
||||||
mSensor.register(mListener);
|
|
||||||
mDelayableExecutor.executeDelayed(this, timeoutMs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void unregister() {
|
|
||||||
mSensor.unregister(mListener);
|
|
||||||
mRegistered.set(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onProximityEvent(ThresholdSensorEvent proximityEvent) {
|
|
||||||
mCallbacks.forEach(
|
|
||||||
booleanConsumer ->
|
|
||||||
booleanConsumer.accept(
|
|
||||||
proximityEvent == null ? null : proximityEvent.getBelow()));
|
|
||||||
mCallbacks.clear();
|
|
||||||
unregister();
|
|
||||||
mRegistered.set(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logDebug(String msg) {
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d(TAG, (mTag != null ? "[" + mTag + "] " : "") + msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,360 @@
|
|||||||
|
/*
|
||||||
|
* 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.sensors;
|
||||||
|
|
||||||
|
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.statusbar.policy.DevicePostureController;
|
||||||
|
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||||
|
import com.android.systemui.util.concurrency.Execution;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
class ProximitySensorImpl implements ProximitySensor {
|
||||||
|
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;
|
||||||
|
|
||||||
|
ThresholdSensor mPrimaryThresholdSensor;
|
||||||
|
ThresholdSensor mSecondaryThresholdSensor;
|
||||||
|
private final DelayableExecutor mDelayableExecutor;
|
||||||
|
private final Execution mExecution;
|
||||||
|
private final List<ThresholdSensor.Listener> mListeners = new ArrayList<>();
|
||||||
|
private String mTag = null;
|
||||||
|
@VisibleForTesting protected boolean mPaused;
|
||||||
|
private ThresholdSensorEvent mLastPrimaryEvent;
|
||||||
|
@VisibleForTesting
|
||||||
|
ThresholdSensorEvent mLastEvent;
|
||||||
|
private boolean mRegistered;
|
||||||
|
private final AtomicBoolean mAlerting = new AtomicBoolean();
|
||||||
|
private Runnable mCancelSecondaryRunnable;
|
||||||
|
boolean mInitializedListeners = false;
|
||||||
|
private boolean mSecondarySafe = false; // safe to skip primary sensor check and use secondary
|
||||||
|
protected @DevicePostureController.DevicePostureInt int mDevicePosture;
|
||||||
|
|
||||||
|
final ThresholdSensor.Listener mPrimaryEventListener = this::onPrimarySensorEvent;
|
||||||
|
|
||||||
|
final ThresholdSensor.Listener mSecondaryEventListener =
|
||||||
|
new ThresholdSensor.Listener() {
|
||||||
|
@Override
|
||||||
|
public void onThresholdCrossed(ThresholdSensorEvent event) {
|
||||||
|
// If we no longer have a "below" signal and the secondary sensor is not
|
||||||
|
// considered "safe", then we need to turn it off.
|
||||||
|
if (!mSecondarySafe
|
||||||
|
&& (mLastPrimaryEvent == null
|
||||||
|
|| !mLastPrimaryEvent.getBelow()
|
||||||
|
|| !event.getBelow())) {
|
||||||
|
chooseSensor();
|
||||||
|
if (mLastPrimaryEvent == null || !mLastPrimaryEvent.getBelow()) {
|
||||||
|
// Only check the secondary as long as the primary thinks we're near.
|
||||||
|
if (mCancelSecondaryRunnable != null) {
|
||||||
|
mCancelSecondaryRunnable.run();
|
||||||
|
mCancelSecondaryRunnable = null;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Check this sensor again in a moment.
|
||||||
|
mCancelSecondaryRunnable = mDelayableExecutor.executeDelayed(() -> {
|
||||||
|
// This is safe because we know that mSecondaryThresholdSensor
|
||||||
|
// is loaded, otherwise we wouldn't be here.
|
||||||
|
mPrimaryThresholdSensor.pause();
|
||||||
|
mSecondaryThresholdSensor.resume();
|
||||||
|
},
|
||||||
|
SECONDARY_PING_INTERVAL_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logDebug("Secondary sensor event: " + event.getBelow() + ".");
|
||||||
|
|
||||||
|
if (!mPaused) {
|
||||||
|
onSensorEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ProximitySensorImpl(
|
||||||
|
@PrimaryProxSensor ThresholdSensor primary,
|
||||||
|
@SecondaryProxSensor ThresholdSensor secondary,
|
||||||
|
@Main DelayableExecutor delayableExecutor,
|
||||||
|
Execution execution) {
|
||||||
|
mPrimaryThresholdSensor = primary;
|
||||||
|
mSecondaryThresholdSensor = secondary;
|
||||||
|
mDelayableExecutor = delayableExecutor;
|
||||||
|
mExecution = execution;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTag(String tag) {
|
||||||
|
mTag = tag;
|
||||||
|
mPrimaryThresholdSensor.setTag(tag + ":primary");
|
||||||
|
mSecondaryThresholdSensor.setTag(tag + ":secondary");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDelay(int delay) {
|
||||||
|
mExecution.assertIsMainThread();
|
||||||
|
mPrimaryThresholdSensor.setDelay(delay);
|
||||||
|
mSecondaryThresholdSensor.setDelay(delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister with the {@link SensorManager} without unsetting listeners on this object.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void pause() {
|
||||||
|
mExecution.assertIsMainThread();
|
||||||
|
mPaused = true;
|
||||||
|
unregisterInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register with the {@link SensorManager}. No-op if no listeners are registered on this object.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void resume() {
|
||||||
|
mExecution.assertIsMainThread();
|
||||||
|
mPaused = false;
|
||||||
|
registerInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSecondarySafe(boolean safe) {
|
||||||
|
mSecondarySafe = mSecondaryThresholdSensor.isLoaded() && safe;
|
||||||
|
chooseSensor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if we are registered with the SensorManager.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isRegistered() {
|
||||||
|
return mRegistered;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code false} if a Proximity sensor is not available.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isLoaded() {
|
||||||
|
return mPrimaryThresholdSensor.isLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a listener.
|
||||||
|
*
|
||||||
|
* Registers itself with the {@link SensorManager} if this is the first listener
|
||||||
|
* added. If the ProximitySensor is paused, it will be registered when resumed.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void register(ThresholdSensor.Listener listener) {
|
||||||
|
mExecution.assertIsMainThread();
|
||||||
|
if (!isLoaded()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mListeners.contains(listener)) {
|
||||||
|
logDebug("ProxListener registered multiple times: " + listener);
|
||||||
|
} else {
|
||||||
|
mListeners.add(listener);
|
||||||
|
}
|
||||||
|
registerInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void registerInternal() {
|
||||||
|
mExecution.assertIsMainThread();
|
||||||
|
if (mRegistered || mPaused || mListeners.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mInitializedListeners) {
|
||||||
|
mPrimaryThresholdSensor.pause();
|
||||||
|
mSecondaryThresholdSensor.pause();
|
||||||
|
mPrimaryThresholdSensor.register(mPrimaryEventListener);
|
||||||
|
mSecondaryThresholdSensor.register(mSecondaryEventListener);
|
||||||
|
mInitializedListeners = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mRegistered = true;
|
||||||
|
chooseSensor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void chooseSensor() {
|
||||||
|
mExecution.assertIsMainThread();
|
||||||
|
if (!mRegistered || mPaused || mListeners.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mSecondarySafe) {
|
||||||
|
mSecondaryThresholdSensor.resume();
|
||||||
|
mPrimaryThresholdSensor.pause();
|
||||||
|
} else {
|
||||||
|
mPrimaryThresholdSensor.resume();
|
||||||
|
mSecondaryThresholdSensor.pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a listener.
|
||||||
|
*
|
||||||
|
* If all listeners are removed from an instance of this class,
|
||||||
|
* it will unregister itself with the SensorManager.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void unregister(ThresholdSensor.Listener listener) {
|
||||||
|
mExecution.assertIsMainThread();
|
||||||
|
mListeners.remove(listener);
|
||||||
|
if (mListeners.size() == 0) {
|
||||||
|
unregisterInternal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return mPrimaryThresholdSensor.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return mPrimaryThresholdSensor.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void unregisterInternal() {
|
||||||
|
mExecution.assertIsMainThread();
|
||||||
|
if (!mRegistered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logDebug("unregistering sensor listener");
|
||||||
|
mPrimaryThresholdSensor.pause();
|
||||||
|
mSecondaryThresholdSensor.pause();
|
||||||
|
if (mCancelSecondaryRunnable != null) {
|
||||||
|
mCancelSecondaryRunnable.run();
|
||||||
|
mCancelSecondaryRunnable = null;
|
||||||
|
}
|
||||||
|
mLastPrimaryEvent = null; // Forget what we know.
|
||||||
|
mLastEvent = null;
|
||||||
|
mRegistered = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean isNear() {
|
||||||
|
return isLoaded() && mLastEvent != null ? mLastEvent.getBelow() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void alertListeners() {
|
||||||
|
mExecution.assertIsMainThread();
|
||||||
|
if (mAlerting.getAndSet(true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mLastEvent != null) {
|
||||||
|
ThresholdSensorEvent lastEvent = mLastEvent; // Listeners can null out mLastEvent.
|
||||||
|
List<ThresholdSensor.Listener> listeners = new ArrayList<>(mListeners);
|
||||||
|
listeners.forEach(proximitySensorListener ->
|
||||||
|
proximitySensorListener.onThresholdCrossed(lastEvent));
|
||||||
|
}
|
||||||
|
|
||||||
|
mAlerting.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onPrimarySensorEvent(ThresholdSensorEvent event) {
|
||||||
|
mExecution.assertIsMainThread();
|
||||||
|
if (mLastPrimaryEvent != null && event.getBelow() == mLastPrimaryEvent.getBelow()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mLastPrimaryEvent = event;
|
||||||
|
|
||||||
|
if (mSecondarySafe && mSecondaryThresholdSensor.isLoaded()) {
|
||||||
|
logDebug("Primary sensor reported " + (event.getBelow() ? "near" : "far")
|
||||||
|
+ ". Checking secondary.");
|
||||||
|
if (mCancelSecondaryRunnable == null) {
|
||||||
|
mSecondaryThresholdSensor.resume();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!mSecondaryThresholdSensor.isLoaded()) { // No secondary
|
||||||
|
logDebug("Primary sensor event: " + event.getBelow() + ". No secondary.");
|
||||||
|
onSensorEvent(event);
|
||||||
|
} else if (event.getBelow()) { // Covered? Check secondary.
|
||||||
|
logDebug("Primary sensor event: " + event.getBelow() + ". Checking secondary.");
|
||||||
|
if (mCancelSecondaryRunnable != null) {
|
||||||
|
mCancelSecondaryRunnable.run();
|
||||||
|
}
|
||||||
|
mSecondaryThresholdSensor.resume();
|
||||||
|
} else { // Uncovered. Report immediately.
|
||||||
|
onSensorEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSensorEvent(ThresholdSensorEvent event) {
|
||||||
|
mExecution.assertIsMainThread();
|
||||||
|
if (mLastEvent != null && event.getBelow() == mLastEvent.getBelow()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mSecondarySafe && !event.getBelow()) {
|
||||||
|
chooseSensor();
|
||||||
|
}
|
||||||
|
|
||||||
|
mLastEvent = event;
|
||||||
|
alertListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("{registered=%s, paused=%s, near=%s, posture=%s, primarySensor=%s, "
|
||||||
|
+ "secondarySensor=%s secondarySafe=%s}",
|
||||||
|
isRegistered(), mPaused, isNear(), mDevicePosture, mPrimaryThresholdSensor,
|
||||||
|
mSecondaryThresholdSensor, mSecondarySafe);
|
||||||
|
}
|
||||||
|
|
||||||
|
void logDebug(String msg) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, (mTag != null ? "[" + mTag + "] " : "") + msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,11 +16,23 @@
|
|||||||
|
|
||||||
package com.android.systemui.util.sensors;
|
package com.android.systemui.util.sensors;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.hardware.Sensor;
|
import android.hardware.Sensor;
|
||||||
import android.hardware.SensorManager;
|
import android.hardware.SensorManager;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
|
import com.android.systemui.statusbar.policy.DevicePostureController;
|
||||||
|
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import dagger.Lazy;
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
|
|
||||||
@@ -31,8 +43,10 @@ import dagger.Provides;
|
|||||||
public class SensorModule {
|
public class SensorModule {
|
||||||
@Provides
|
@Provides
|
||||||
@PrimaryProxSensor
|
@PrimaryProxSensor
|
||||||
static ThresholdSensor providePrimaryProxSensor(SensorManager sensorManager,
|
static ThresholdSensor providePrimaryProximitySensor(
|
||||||
ThresholdSensorImpl.Builder thresholdSensorBuilder) {
|
SensorManager sensorManager,
|
||||||
|
ThresholdSensorImpl.Builder thresholdSensorBuilder
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
return thresholdSensorBuilder
|
return thresholdSensorBuilder
|
||||||
.setSensorDelay(SensorManager.SENSOR_DELAY_NORMAL)
|
.setSensorDelay(SensorManager.SENSOR_DELAY_NORMAL)
|
||||||
@@ -52,8 +66,9 @@ public class SensorModule {
|
|||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@SecondaryProxSensor
|
@SecondaryProxSensor
|
||||||
static ThresholdSensor provideSecondaryProxSensor(
|
static ThresholdSensor provideSecondaryProximitySensor(
|
||||||
ThresholdSensorImpl.Builder thresholdSensorBuilder) {
|
ThresholdSensorImpl.Builder thresholdSensorBuilder
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
return thresholdSensorBuilder
|
return thresholdSensorBuilder
|
||||||
.setSensorResourceId(R.string.proximity_sensor_secondary_type, true)
|
.setSensorResourceId(R.string.proximity_sensor_secondary_type, true)
|
||||||
@@ -64,4 +79,153 @@ public class SensorModule {
|
|||||||
return thresholdSensorBuilder.setSensor(null).setThresholdValue(0).build();
|
return thresholdSensorBuilder.setSensor(null).setThresholdValue(0).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If postures are supported on the device, returns a posture dependent proximity sensor
|
||||||
|
* which switches proximity sensors based on the current posture.
|
||||||
|
*
|
||||||
|
* If postures are not supported the regular {@link ProximitySensorImpl} will be returned.
|
||||||
|
*/
|
||||||
|
@Provides
|
||||||
|
static ProximitySensor provideProximitySensor(
|
||||||
|
@Main Resources resources,
|
||||||
|
Lazy<PostureDependentProximitySensor> postureDependentProximitySensorProvider,
|
||||||
|
Lazy<ProximitySensorImpl> proximitySensorProvider
|
||||||
|
) {
|
||||||
|
if (hasPostureSupport(
|
||||||
|
resources.getStringArray(R.array.proximity_sensor_posture_mapping))) {
|
||||||
|
return postureDependentProximitySensorProvider.get();
|
||||||
|
} else {
|
||||||
|
return proximitySensorProvider.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
static ProximityCheck provideProximityCheck(
|
||||||
|
ProximitySensor proximitySensor,
|
||||||
|
@Main DelayableExecutor delayableExecutor
|
||||||
|
) {
|
||||||
|
return new ProximityCheck(
|
||||||
|
proximitySensor,
|
||||||
|
delayableExecutor
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@PrimaryProxSensor
|
||||||
|
@NonNull
|
||||||
|
static ThresholdSensor[] providePostureToProximitySensorMapping(
|
||||||
|
ThresholdSensorImpl.BuilderFactory thresholdSensorImplBuilderFactory,
|
||||||
|
@Main Resources resources
|
||||||
|
) {
|
||||||
|
return createPostureToSensorMapping(
|
||||||
|
thresholdSensorImplBuilderFactory,
|
||||||
|
resources.getStringArray(R.array.proximity_sensor_posture_mapping),
|
||||||
|
R.dimen.proximity_sensor_threshold,
|
||||||
|
R.dimen.proximity_sensor_threshold_latch
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@SecondaryProxSensor
|
||||||
|
@NonNull
|
||||||
|
static ThresholdSensor[] providePostureToSecondaryProximitySensorMapping(
|
||||||
|
ThresholdSensorImpl.BuilderFactory thresholdSensorImplBuilderFactory,
|
||||||
|
@Main Resources resources
|
||||||
|
) {
|
||||||
|
return createPostureToSensorMapping(
|
||||||
|
thresholdSensorImplBuilderFactory,
|
||||||
|
resources.getStringArray(R.array.proximity_sensor_secondary_posture_mapping),
|
||||||
|
R.dimen.proximity_sensor_secondary_threshold,
|
||||||
|
R.dimen.proximity_sensor_secondary_threshold_latch
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds sensors to use per posture.
|
||||||
|
*
|
||||||
|
* @param sensorTypes an array where the index represents
|
||||||
|
* {@link DevicePostureController.DevicePostureInt} and the value
|
||||||
|
* at the given index is the sensorType. Empty values represent
|
||||||
|
* no sensor desired.
|
||||||
|
* @param proximitySensorThresholdResourceId resource id for the threshold for all sensor
|
||||||
|
* postures. This currently only supports one value.
|
||||||
|
* This needs to be updated in the future if postures
|
||||||
|
* use different sensors with differing thresholds.
|
||||||
|
* @param proximitySensorThresholdLatchResourceId resource id for the latch for all sensor
|
||||||
|
* postures. This currently only supports one
|
||||||
|
* value. This needs to be updated in the future
|
||||||
|
* if postures use different sensors with
|
||||||
|
* differing latches.
|
||||||
|
* @return an array where the index represents the device posture
|
||||||
|
* {@link DevicePostureController.DevicePostureInt} and the value at the index is the sensor to
|
||||||
|
* use when the device is in that posture.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
private static ThresholdSensor[] createPostureToSensorMapping(
|
||||||
|
ThresholdSensorImpl.BuilderFactory thresholdSensorImplBuilderFactory,
|
||||||
|
String[] sensorTypes,
|
||||||
|
int proximitySensorThresholdResourceId,
|
||||||
|
int proximitySensorThresholdLatchResourceId
|
||||||
|
|
||||||
|
) {
|
||||||
|
ThresholdSensor noProxSensor = thresholdSensorImplBuilderFactory
|
||||||
|
.createBuilder()
|
||||||
|
.setSensor(null).setThresholdValue(0).build();
|
||||||
|
|
||||||
|
|
||||||
|
// length and index of sensorMap correspond to DevicePostureController.DevicePostureInt:
|
||||||
|
final ThresholdSensor[] sensorMap =
|
||||||
|
new ThresholdSensor[DevicePostureController.SUPPORTED_POSTURES_SIZE];
|
||||||
|
for (int i = 0; i < DevicePostureController.SUPPORTED_POSTURES_SIZE; i++) {
|
||||||
|
sensorMap[i] = noProxSensor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasPostureSupport(sensorTypes)) {
|
||||||
|
Log.e("SensorModule", "config doesn't support postures,"
|
||||||
|
+ " but attempting to retrieve proxSensorMapping");
|
||||||
|
return sensorMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map of sensorType => Sensor, so we reuse the same sensor if it's the same between
|
||||||
|
// postures
|
||||||
|
Map<String, ThresholdSensor> typeToSensorMap = new HashMap<>();
|
||||||
|
for (int i = 0; i < sensorTypes.length; i++) {
|
||||||
|
try {
|
||||||
|
final String sensorType = sensorTypes[i];
|
||||||
|
if (typeToSensorMap.containsKey(sensorType)) {
|
||||||
|
sensorMap[i] = typeToSensorMap.get(sensorType);
|
||||||
|
} else {
|
||||||
|
sensorMap[i] = thresholdSensorImplBuilderFactory
|
||||||
|
.createBuilder()
|
||||||
|
.setSensorType(sensorTypes[i], true)
|
||||||
|
.setThresholdResourceId(proximitySensorThresholdResourceId)
|
||||||
|
.setThresholdLatchResourceId(proximitySensorThresholdLatchResourceId)
|
||||||
|
.build();
|
||||||
|
typeToSensorMap.put(sensorType, sensorMap[i]);
|
||||||
|
}
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
// do nothing, sensor at this posture is already set to noProxSensor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sensorMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if there's at least one non-empty sensor type in the given array.
|
||||||
|
*/
|
||||||
|
private static boolean hasPostureSupport(String[] postureToSensorTypeMapping) {
|
||||||
|
if (postureToSensorTypeMapping == null || postureToSensorTypeMapping.length == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String sensorType : postureToSensorTypeMapping) {
|
||||||
|
if (!TextUtils.isEmpty(sensorType)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package com.android.systemui.util.sensors;
|
package com.android.systemui.util.sensors;
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wrapper class for sensors that have a boolean state - above/below.
|
* A wrapper class for sensors that have a boolean state - above/below.
|
||||||
*/
|
*/
|
||||||
@@ -76,6 +74,16 @@ public interface ThresholdSensor {
|
|||||||
*/
|
*/
|
||||||
void unregister(Listener listener);
|
void unregister(Listener listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the sensor.
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of the sensor.
|
||||||
|
*/
|
||||||
|
String getType();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for listening to events on {@link ThresholdSensor}
|
* Interface for listening to events on {@link ThresholdSensor}
|
||||||
*/
|
*/
|
||||||
@@ -85,34 +93,4 @@ public interface ThresholdSensor {
|
|||||||
*/
|
*/
|
||||||
void onThresholdCrossed(ThresholdSensorEvent event);
|
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,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returned when the below/above state of a {@link ThresholdSensor} changes.
|
||||||
|
*/
|
||||||
|
public 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ import android.hardware.Sensor;
|
|||||||
import android.hardware.SensorEvent;
|
import android.hardware.SensorEvent;
|
||||||
import android.hardware.SensorEventListener;
|
import android.hardware.SensorEventListener;
|
||||||
import android.hardware.SensorManager;
|
import android.hardware.SensorManager;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
@@ -32,7 +33,10 @@ import java.util.List;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
class ThresholdSensorImpl implements ThresholdSensor {
|
/**
|
||||||
|
* Sensor that will only trigger beyond some lower and upper threshold.
|
||||||
|
*/
|
||||||
|
public class ThresholdSensorImpl implements ThresholdSensor {
|
||||||
private static final String TAG = "ThresholdSensor";
|
private static final String TAG = "ThresholdSensor";
|
||||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||||
|
|
||||||
@@ -198,6 +202,15 @@ class ThresholdSensorImpl implements ThresholdSensor {
|
|||||||
alertListenersInternal(belowThreshold, timestampNs);
|
alertListenersInternal(belowThreshold, timestampNs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return mSensor != null ? mSensor.getName() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return mSensor != null ? mSensor.getStringType() : null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@@ -211,7 +224,12 @@ class ThresholdSensorImpl implements ThresholdSensor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Builder {
|
/**
|
||||||
|
* Use to build a ThresholdSensor. Should only be used once per sensor built, since
|
||||||
|
* parameters are not reset after calls to build(). For ease of retrievingnew Builders, use
|
||||||
|
* {@link BuilderFactory}.
|
||||||
|
*/
|
||||||
|
public static class Builder {
|
||||||
private final Resources mResources;
|
private final Resources mResources;
|
||||||
private final AsyncSensorManager mSensorManager;
|
private final AsyncSensorManager mSensorManager;
|
||||||
private final Execution mExecution;
|
private final Execution mExecution;
|
||||||
@@ -318,7 +336,7 @@ class ThresholdSensorImpl implements ThresholdSensor {
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
Sensor findSensorByType(String sensorType, boolean requireWakeUp) {
|
Sensor findSensorByType(String sensorType, boolean requireWakeUp) {
|
||||||
if (sensorType.isEmpty()) {
|
if (TextUtils.isEmpty(sensorType)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,4 +354,29 @@ class ThresholdSensorImpl implements ThresholdSensor {
|
|||||||
return sensor;
|
return sensor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory that creates a new ThresholdSensorImpl.Builder. In general, Builders should not be
|
||||||
|
* reused after creating a ThresholdSensor or else there may be default threshold and sensor
|
||||||
|
* values set from the previous built sensor.
|
||||||
|
*/
|
||||||
|
public static class BuilderFactory {
|
||||||
|
private final Resources mResources;
|
||||||
|
private final AsyncSensorManager mSensorManager;
|
||||||
|
private final Execution mExecution;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
BuilderFactory(
|
||||||
|
@Main Resources resources,
|
||||||
|
AsyncSensorManager sensorManager,
|
||||||
|
Execution execution) {
|
||||||
|
mResources = resources;
|
||||||
|
mSensorManager = sensorManager;
|
||||||
|
mExecution = execution;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThresholdSensorImpl.Builder createBuilder() {
|
||||||
|
return new Builder(mResources, mSensorManager, mExecution);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ import com.android.systemui.util.sensors.AsyncSensorManager;
|
|||||||
import com.android.systemui.util.sensors.FakeProximitySensor;
|
import com.android.systemui.util.sensors.FakeProximitySensor;
|
||||||
import com.android.systemui.util.sensors.FakeSensorManager;
|
import com.android.systemui.util.sensors.FakeSensorManager;
|
||||||
import com.android.systemui.util.sensors.FakeThresholdSensor;
|
import com.android.systemui.util.sensors.FakeThresholdSensor;
|
||||||
import com.android.systemui.util.sensors.ProximitySensor;
|
import com.android.systemui.util.sensors.ProximityCheck;
|
||||||
|
import com.android.systemui.util.sensors.ThresholdSensorEvent;
|
||||||
import com.android.systemui.util.settings.FakeSettings;
|
import com.android.systemui.util.settings.FakeSettings;
|
||||||
import com.android.systemui.util.time.FakeSystemClock;
|
import com.android.systemui.util.time.FakeSystemClock;
|
||||||
import com.android.systemui.util.wakelock.WakeLock;
|
import com.android.systemui.util.wakelock.WakeLock;
|
||||||
@@ -80,7 +81,7 @@ public class DozeTriggersTest extends SysuiTestCase {
|
|||||||
@Mock
|
@Mock
|
||||||
private DockManager mDockManager;
|
private DockManager mDockManager;
|
||||||
@Mock
|
@Mock
|
||||||
private ProximitySensor.ProximityCheck mProximityCheck;
|
private ProximityCheck mProximityCheck;
|
||||||
@Mock
|
@Mock
|
||||||
private AuthController mAuthController;
|
private AuthController mAuthController;
|
||||||
@Mock
|
@Mock
|
||||||
@@ -136,14 +137,14 @@ public class DozeTriggersTest extends SysuiTestCase {
|
|||||||
mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
|
mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
|
||||||
clearInvocations(mMachine);
|
clearInvocations(mMachine);
|
||||||
|
|
||||||
mProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(true, 1));
|
mProximitySensor.setLastEvent(new ThresholdSensorEvent(true, 1));
|
||||||
captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */);
|
captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */);
|
||||||
mProximitySensor.alertListeners();
|
mProximitySensor.alertListeners();
|
||||||
|
|
||||||
verify(mMachine, never()).requestState(any());
|
verify(mMachine, never()).requestState(any());
|
||||||
verify(mMachine, never()).requestPulse(anyInt());
|
verify(mMachine, never()).requestPulse(anyInt());
|
||||||
|
|
||||||
mProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(false, 2));
|
mProximitySensor.setLastEvent(new ThresholdSensorEvent(false, 2));
|
||||||
mProximitySensor.alertListeners();
|
mProximitySensor.alertListeners();
|
||||||
waitForSensorManager();
|
waitForSensorManager();
|
||||||
captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */);
|
captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */);
|
||||||
|
|||||||
@@ -19,14 +19,21 @@ package com.android.systemui.util.sensors;
|
|||||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||||
import com.android.systemui.util.concurrency.FakeExecution;
|
import com.android.systemui.util.concurrency.FakeExecution;
|
||||||
|
|
||||||
public class FakeProximitySensor extends ProximitySensor {
|
public class FakeProximitySensor extends ProximitySensorImpl {
|
||||||
private boolean mAvailable;
|
private boolean mAvailable;
|
||||||
private boolean mRegistered;
|
private boolean mRegistered;
|
||||||
|
|
||||||
public FakeProximitySensor(ThresholdSensor primary, ThresholdSensor secondary,
|
public FakeProximitySensor(
|
||||||
DelayableExecutor delayableExecutor) {
|
ThresholdSensor primary,
|
||||||
super(primary, secondary == null ? new FakeThresholdSensor() : secondary,
|
ThresholdSensor secondary,
|
||||||
delayableExecutor, new FakeExecution());
|
DelayableExecutor delayableExecutor
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
primary,
|
||||||
|
secondary == null ? new FakeThresholdSensor() : secondary,
|
||||||
|
delayableExecutor,
|
||||||
|
new FakeExecution()
|
||||||
|
);
|
||||||
mAvailable = true;
|
mAvailable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,16 @@ public class FakeThresholdSensor implements ThresholdSensor {
|
|||||||
mListeners.remove(listener);
|
mListeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "FakeThresholdSensorName";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "FakeThresholdSensorType";
|
||||||
|
}
|
||||||
|
|
||||||
public void setLoaded(boolean loaded) {
|
public void setLoaded(boolean loaded) {
|
||||||
mIsLoaded = loaded;
|
mIsLoaded = loaded;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.testing.AndroidTestingRunner;
|
||||||
|
import android.testing.TestableLooper;
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import com.android.systemui.SysuiTestCase;
|
||||||
|
import com.android.systemui.statusbar.policy.DevicePostureController;
|
||||||
|
import com.android.systemui.util.concurrency.FakeExecution;
|
||||||
|
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.ArgumentCaptor;
|
||||||
|
import org.mockito.Captor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidTestingRunner.class)
|
||||||
|
@TestableLooper.RunWithLooper
|
||||||
|
public class PostureDependentProximitySensorTest extends SysuiTestCase {
|
||||||
|
@Mock private Resources mResources;
|
||||||
|
@Mock private DevicePostureController mDevicePostureController;
|
||||||
|
@Mock private AsyncSensorManager mSensorManager;
|
||||||
|
|
||||||
|
@Captor private ArgumentCaptor<DevicePostureController.Callback> mPostureListenerCaptor =
|
||||||
|
ArgumentCaptor.forClass(DevicePostureController.Callback.class);
|
||||||
|
private DevicePostureController.Callback mPostureListener;
|
||||||
|
|
||||||
|
private PostureDependentProximitySensor mProximitySensor;
|
||||||
|
private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
allowTestableLooperAsMainThread();
|
||||||
|
|
||||||
|
mProximitySensor = new PostureDependentProximitySensor(
|
||||||
|
new ThresholdSensor[DevicePostureController.SUPPORTED_POSTURES_SIZE],
|
||||||
|
new ThresholdSensor[DevicePostureController.SUPPORTED_POSTURES_SIZE],
|
||||||
|
mFakeExecutor,
|
||||||
|
new FakeExecution(),
|
||||||
|
mDevicePostureController
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostureChangeListenerAdded() {
|
||||||
|
capturePostureListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostureChangeListenerUpdatesPosture() {
|
||||||
|
// GIVEN posture listener is registered
|
||||||
|
capturePostureListener();
|
||||||
|
|
||||||
|
// WHEN the posture changes to DEVICE_POSTURE_OPENED
|
||||||
|
mPostureListener.onPostureChanged(DevicePostureController.DEVICE_POSTURE_OPENED);
|
||||||
|
|
||||||
|
// THEN device posture is updated to DEVICE_POSTURE_OPENED
|
||||||
|
assertEquals(DevicePostureController.DEVICE_POSTURE_OPENED,
|
||||||
|
mProximitySensor.mDevicePosture);
|
||||||
|
|
||||||
|
// WHEN the posture changes to DEVICE_POSTURE_CLOSED
|
||||||
|
mPostureListener.onPostureChanged(DevicePostureController.DEVICE_POSTURE_CLOSED);
|
||||||
|
|
||||||
|
// THEN device posture is updated to DEVICE_POSTURE_CLOSED
|
||||||
|
assertEquals(DevicePostureController.DEVICE_POSTURE_CLOSED,
|
||||||
|
mProximitySensor.mDevicePosture);
|
||||||
|
|
||||||
|
// WHEN the posture changes to DEVICE_POSTURE_FLIPPED
|
||||||
|
mPostureListener.onPostureChanged(DevicePostureController.DEVICE_POSTURE_FLIPPED);
|
||||||
|
|
||||||
|
// THEN device posture is updated to DEVICE_POSTURE_FLIPPED
|
||||||
|
assertEquals(DevicePostureController.DEVICE_POSTURE_FLIPPED,
|
||||||
|
mProximitySensor.mDevicePosture);
|
||||||
|
|
||||||
|
// WHEN the posture changes to DEVICE_POSTURE_HALF_OPENED
|
||||||
|
mPostureListener.onPostureChanged(DevicePostureController.DEVICE_POSTURE_HALF_OPENED);
|
||||||
|
|
||||||
|
// THEN device posture is updated to DEVICE_POSTURE_HALF_OPENED
|
||||||
|
assertEquals(DevicePostureController.DEVICE_POSTURE_HALF_OPENED,
|
||||||
|
mProximitySensor.mDevicePosture);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void capturePostureListener() {
|
||||||
|
verify(mDevicePostureController).addCallback(mPostureListenerCaptor.capture());
|
||||||
|
mPostureListener = mPostureListenerCaptor.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,7 +49,7 @@ public class ProximityCheckTest extends SysuiTestCase {
|
|||||||
|
|
||||||
private TestableCallback mTestableCallback = new TestableCallback();
|
private TestableCallback mTestableCallback = new TestableCallback();
|
||||||
|
|
||||||
private ProximitySensor.ProximityCheck mProximityCheck;
|
private ProximityCheck mProximityCheck;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
@@ -58,7 +58,7 @@ public class ProximityCheckTest extends SysuiTestCase {
|
|||||||
thresholdSensor.setLoaded(true);
|
thresholdSensor.setLoaded(true);
|
||||||
mFakeProximitySensor = new FakeProximitySensor(thresholdSensor, null, mFakeExecutor);
|
mFakeProximitySensor = new FakeProximitySensor(thresholdSensor, null, mFakeExecutor);
|
||||||
|
|
||||||
mProximityCheck = new ProximitySensor.ProximityCheck(mFakeProximitySensor, mFakeExecutor);
|
mProximityCheck = new ProximityCheck(mFakeProximitySensor, mFakeExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -67,7 +67,7 @@ public class ProximityCheckTest extends SysuiTestCase {
|
|||||||
|
|
||||||
assertNull(mTestableCallback.mLastResult);
|
assertNull(mTestableCallback.mLastResult);
|
||||||
|
|
||||||
mFakeProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(true, 0));
|
mFakeProximitySensor.setLastEvent(new ThresholdSensorEvent(true, 0));
|
||||||
mFakeProximitySensor.alertListeners();
|
mFakeProximitySensor.alertListeners();
|
||||||
|
|
||||||
assertTrue(mTestableCallback.mLastResult);
|
assertTrue(mTestableCallback.mLastResult);
|
||||||
@@ -103,7 +103,7 @@ public class ProximityCheckTest extends SysuiTestCase {
|
|||||||
|
|
||||||
mProximityCheck.check(100, mTestableCallback);
|
mProximityCheck.check(100, mTestableCallback);
|
||||||
|
|
||||||
mFakeProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(true, 0));
|
mFakeProximitySensor.setLastEvent(new ThresholdSensorEvent(true, 0));
|
||||||
mFakeProximitySensor.alertListeners();
|
mFakeProximitySensor.alertListeners();
|
||||||
|
|
||||||
assertThat(mTestableCallback.mLastResult).isNotNull();
|
assertThat(mTestableCallback.mLastResult).isNotNull();
|
||||||
@@ -123,7 +123,7 @@ public class ProximityCheckTest extends SysuiTestCase {
|
|||||||
|
|
||||||
assertNull(mTestableCallback.mLastResult);
|
assertNull(mTestableCallback.mLastResult);
|
||||||
|
|
||||||
mFakeProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(true, 0));
|
mFakeProximitySensor.setLastEvent(new ThresholdSensorEvent(true, 0));
|
||||||
mFakeProximitySensor.alertListeners();
|
mFakeProximitySensor.alertListeners();
|
||||||
|
|
||||||
assertTrue(mTestableCallback.mLastResult);
|
assertTrue(mTestableCallback.mLastResult);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ import org.mockito.MockitoAnnotations;
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner.class)
|
@RunWith(AndroidTestingRunner.class)
|
||||||
@TestableLooper.RunWithLooper
|
@TestableLooper.RunWithLooper
|
||||||
public class ProximitySensorDualTest extends SysuiTestCase {
|
public class ProximitySensorImplDualTest extends SysuiTestCase {
|
||||||
private ProximitySensor mProximitySensor;
|
private ProximitySensor mProximitySensor;
|
||||||
private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
|
private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
|
||||||
private FakeThresholdSensor mThresholdSensorPrimary;
|
private FakeThresholdSensor mThresholdSensorPrimary;
|
||||||
@@ -57,7 +57,7 @@ public class ProximitySensorDualTest extends SysuiTestCase {
|
|||||||
mThresholdSensorSecondary = new FakeThresholdSensor();
|
mThresholdSensorSecondary = new FakeThresholdSensor();
|
||||||
mThresholdSensorSecondary.setLoaded(true);
|
mThresholdSensorSecondary.setLoaded(true);
|
||||||
|
|
||||||
mProximitySensor = new ProximitySensor(
|
mProximitySensor = new ProximitySensorImpl(
|
||||||
mThresholdSensorPrimary, mThresholdSensorSecondary, mFakeExecutor,
|
mThresholdSensorPrimary, mThresholdSensorSecondary, mFakeExecutor,
|
||||||
new FakeExecution());
|
new FakeExecution());
|
||||||
}
|
}
|
||||||
@@ -430,11 +430,11 @@ public class ProximitySensorDualTest extends SysuiTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class TestableListener implements ThresholdSensor.Listener {
|
private static class TestableListener implements ThresholdSensor.Listener {
|
||||||
ThresholdSensor.ThresholdSensorEvent mLastEvent;
|
ThresholdSensorEvent mLastEvent;
|
||||||
int mCallCount = 0;
|
int mCallCount = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onThresholdCrossed(ThresholdSensor.ThresholdSensorEvent proximityEvent) {
|
public void onThresholdCrossed(ThresholdSensorEvent proximityEvent) {
|
||||||
mLastEvent = proximityEvent;
|
mLastEvent = proximityEvent;
|
||||||
mCallCount++;
|
mCallCount++;
|
||||||
}
|
}
|
||||||
@@ -42,7 +42,7 @@ import org.mockito.MockitoAnnotations;
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner.class)
|
@RunWith(AndroidTestingRunner.class)
|
||||||
@TestableLooper.RunWithLooper
|
@TestableLooper.RunWithLooper
|
||||||
public class ProximitySensorSingleTest extends SysuiTestCase {
|
public class ProximitySensorImplSingleTest extends SysuiTestCase {
|
||||||
private ProximitySensor mProximitySensor;
|
private ProximitySensor mProximitySensor;
|
||||||
private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
|
private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
|
||||||
private FakeThresholdSensor mThresholdSensor;
|
private FakeThresholdSensor mThresholdSensor;
|
||||||
@@ -54,7 +54,7 @@ public class ProximitySensorSingleTest extends SysuiTestCase {
|
|||||||
mThresholdSensor = new FakeThresholdSensor();
|
mThresholdSensor = new FakeThresholdSensor();
|
||||||
mThresholdSensor.setLoaded(true);
|
mThresholdSensor.setLoaded(true);
|
||||||
|
|
||||||
mProximitySensor = new ProximitySensor(
|
mProximitySensor = new ProximitySensorImpl(
|
||||||
mThresholdSensor, new FakeThresholdSensor(), mFakeExecutor, new FakeExecution());
|
mThresholdSensor, new FakeThresholdSensor(), mFakeExecutor, new FakeExecution());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +215,7 @@ public class ProximitySensorSingleTest extends SysuiTestCase {
|
|||||||
public void testPreventRecursiveAlert() {
|
public void testPreventRecursiveAlert() {
|
||||||
TestableListener listenerA = new TestableListener() {
|
TestableListener listenerA = new TestableListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onThresholdCrossed(ProximitySensor.ThresholdSensorEvent proximityEvent) {
|
public void onThresholdCrossed(ThresholdSensorEvent proximityEvent) {
|
||||||
super.onThresholdCrossed(proximityEvent);
|
super.onThresholdCrossed(proximityEvent);
|
||||||
if (mCallCount < 2) {
|
if (mCallCount < 2) {
|
||||||
mProximitySensor.alertListeners();
|
mProximitySensor.alertListeners();
|
||||||
@@ -231,11 +231,11 @@ public class ProximitySensorSingleTest extends SysuiTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class TestableListener implements ThresholdSensor.Listener {
|
private static class TestableListener implements ThresholdSensor.Listener {
|
||||||
ThresholdSensor.ThresholdSensorEvent mLastEvent;
|
ThresholdSensorEvent mLastEvent;
|
||||||
int mCallCount = 0;
|
int mCallCount = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onThresholdCrossed(ThresholdSensor.ThresholdSensorEvent proximityEvent) {
|
public void onThresholdCrossed(ThresholdSensorEvent proximityEvent) {
|
||||||
mLastEvent = proximityEvent;
|
mLastEvent = proximityEvent;
|
||||||
mCallCount++;
|
mCallCount++;
|
||||||
}
|
}
|
||||||
@@ -380,7 +380,7 @@ public class ThresholdSensorImplTest extends SysuiTestCase {
|
|||||||
int mCallCount;
|
int mCallCount;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onThresholdCrossed(ThresholdSensor.ThresholdSensorEvent event) {
|
public void onThresholdCrossed(ThresholdSensorEvent event) {
|
||||||
mBelow = event.getBelow();
|
mBelow = event.getBelow();
|
||||||
mTimestampNs = event.getTimestampNs();
|
mTimestampNs = event.getTimestampNs();
|
||||||
mCallCount++;
|
mCallCount++;
|
||||||
|
|||||||
Reference in New Issue
Block a user