Merge changes from topic "b140270231-prox-sensor"
* changes: Remove SensorRateLimiter, as it should be unnecessary. Make DozeSensors, DozeTriggers use ProximitySensor
This commit is contained in:
@@ -22,7 +22,7 @@ import com.android.systemui.plugins.annotations.ProvidesInterface;
|
||||
|
||||
/**
|
||||
* Allows for additional sensors to be retrieved from
|
||||
* {@link com.android.systemui.util.AsyncSensorManager}.
|
||||
* {@link com.android.systemui.util.sensors.AsyncSensorManager}.
|
||||
*/
|
||||
@ProvidesInterface(action = SensorManagerPlugin.ACTION, version = SensorManagerPlugin.VERSION)
|
||||
public interface SensorManagerPlugin extends Plugin {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package com.android.systemui;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.INotificationManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.hardware.SensorPrivacyManager;
|
||||
@@ -110,10 +111,10 @@ import com.android.systemui.statusbar.policy.UserSwitcherController;
|
||||
import com.android.systemui.statusbar.policy.ZenModeController;
|
||||
import com.android.systemui.tuner.TunablePadding.TunablePaddingService;
|
||||
import com.android.systemui.tuner.TunerService;
|
||||
import com.android.systemui.util.AsyncSensorManager;
|
||||
import com.android.systemui.util.leak.GarbageMonitor;
|
||||
import com.android.systemui.util.leak.LeakDetector;
|
||||
import com.android.systemui.util.leak.LeakReporter;
|
||||
import com.android.systemui.util.sensors.AsyncSensorManager;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -314,6 +315,7 @@ public class Dependency {
|
||||
@Inject Lazy<INotificationManager> mINotificationManager;
|
||||
@Inject Lazy<FalsingManager> mFalsingManager;
|
||||
@Inject Lazy<SysUiState> mSysUiStateFlagsContainer;
|
||||
@Inject Lazy<AlarmManager> mAlarmManager;
|
||||
|
||||
@Inject
|
||||
public Dependency() {
|
||||
@@ -508,6 +510,7 @@ public class Dependency {
|
||||
mProviders.put(INotificationManager.class, mINotificationManager::get);
|
||||
mProviders.put(FalsingManager.class, mFalsingManager::get);
|
||||
mProviders.put(SysUiState.class, mSysUiStateFlagsContainer::get);
|
||||
mProviders.put(AlarmManager.class, mAlarmManager::get);
|
||||
|
||||
// TODO(b/118592525): to support multi-display , we start to add something which is
|
||||
// per-display, while others may be global. I think it's time to add
|
||||
|
||||
@@ -23,6 +23,7 @@ import static com.android.systemui.Dependency.MAIN_LOOPER_NAME;
|
||||
import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.INotificationManager;
|
||||
import android.content.Context;
|
||||
import android.hardware.SensorPrivacyManager;
|
||||
@@ -230,4 +231,11 @@ public class DependencyProvider {
|
||||
@Named(MAIN_HANDLER_NAME) Handler mainHandler) {
|
||||
return new DeviceProvisionedControllerImpl(context, mainHandler);
|
||||
}
|
||||
|
||||
/** */
|
||||
@Singleton
|
||||
@Provides
|
||||
public AlarmManager provideAlarmManager(Context context) {
|
||||
return context.getSystemService(AlarmManager.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import com.android.systemui.assist.AssistModule;
|
||||
import com.android.systemui.model.SysUiState;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.statusbar.phone.KeyguardLiftController;
|
||||
import com.android.systemui.util.AsyncSensorManager;
|
||||
import com.android.systemui.util.sensors.AsyncSensorManager;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ import com.android.systemui.plugins.FalsingManager;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.util.AsyncSensorManager;
|
||||
import com.android.systemui.util.sensors.AsyncSensorManager;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHT
|
||||
import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.SensorManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.provider.DeviceConfig;
|
||||
@@ -35,7 +36,7 @@ import com.android.systemui.plugins.FalsingPlugin;
|
||||
import com.android.systemui.plugins.PluginListener;
|
||||
import com.android.systemui.shared.plugins.PluginManager;
|
||||
import com.android.systemui.util.DeviceConfigProxy;
|
||||
import com.android.systemui.util.ProximitySensor;
|
||||
import com.android.systemui.util.sensors.ProximitySensor;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
@@ -66,6 +67,7 @@ public class FalsingManagerProxy implements FalsingManager {
|
||||
DeviceConfigProxy deviceConfig) {
|
||||
mProximitySensor = proximitySensor;
|
||||
mProximitySensor.setTag(PROXIMITY_SENSOR_TAG);
|
||||
mProximitySensor.setSensorDelay(SensorManager.SENSOR_DELAY_GAME);
|
||||
mDeviceConfig = deviceConfig;
|
||||
mDeviceConfigListener =
|
||||
properties -> onDeviceConfigPropertiesChanged(context, properties.getNamespace());
|
||||
|
||||
@@ -30,7 +30,7 @@ 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 com.android.systemui.util.sensors.ProximitySensor;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.android.systemui.classifier.brightline;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.systemui.classifier.Classifier;
|
||||
import com.android.systemui.util.ProximitySensor;
|
||||
import com.android.systemui.util.sensors.ProximitySensor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import android.provider.DeviceConfig;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.systemui.util.DeviceConfigProxy;
|
||||
import com.android.systemui.util.ProximitySensor;
|
||||
import com.android.systemui.util.sensors.ProximitySensor;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,7 +33,7 @@ import com.android.systemui.keyguard.WakefulnessLifecycle;
|
||||
import com.android.systemui.plugins.FalsingManager;
|
||||
import com.android.systemui.statusbar.phone.BiometricUnlockController;
|
||||
import com.android.systemui.statusbar.phone.DozeParameters;
|
||||
import com.android.systemui.util.AsyncSensorManager;
|
||||
import com.android.systemui.util.sensors.AsyncSensorManager;
|
||||
import com.android.systemui.util.wakelock.DelayedWakeLock;
|
||||
import com.android.systemui.util.wakelock.WakeLock;
|
||||
|
||||
@@ -45,7 +45,7 @@ public class DozeFactory {
|
||||
/** Creates a DozeMachine with its parts for {@code dozeService}. */
|
||||
public DozeMachine assembleMachine(DozeService dozeService, FalsingManager falsingManager) {
|
||||
Context context = dozeService;
|
||||
SensorManager sensorManager = Dependency.get(AsyncSensorManager.class);
|
||||
AsyncSensorManager sensorManager = Dependency.get(AsyncSensorManager.class);
|
||||
AlarmManager alarmManager = context.getSystemService(AlarmManager.class);
|
||||
DockManager dockManager = Dependency.get(DockManager.class);
|
||||
WakefulnessLifecycle wakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
|
||||
@@ -91,7 +91,7 @@ public class DozeFactory {
|
||||
params.getPolicy());
|
||||
}
|
||||
|
||||
private DozeTriggers createDozeTriggers(Context context, SensorManager sensorManager,
|
||||
private DozeTriggers createDozeTriggers(Context context, AsyncSensorManager sensorManager,
|
||||
DozeHost host, AlarmManager alarmManager, AmbientDisplayConfiguration config,
|
||||
DozeParameters params, Handler handler, WakeLock wakeLock, DozeMachine machine,
|
||||
DockManager dockManager) {
|
||||
|
||||
@@ -26,7 +26,6 @@ import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.hardware.TriggerEvent;
|
||||
import android.hardware.TriggerEventListener;
|
||||
@@ -43,11 +42,12 @@ import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.plugins.SensorManagerPlugin;
|
||||
import com.android.systemui.shared.plugins.PluginManager;
|
||||
import com.android.systemui.statusbar.phone.DozeParameters;
|
||||
import com.android.systemui.util.AlarmTimeout;
|
||||
import com.android.systemui.util.AsyncSensorManager;
|
||||
import com.android.systemui.util.sensors.AsyncSensorManager;
|
||||
import com.android.systemui.util.sensors.ProximitySensor;
|
||||
import com.android.systemui.util.wakelock.WakeLock;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -62,7 +62,7 @@ public class DozeSensors {
|
||||
|
||||
private final Context mContext;
|
||||
private final AlarmManager mAlarmManager;
|
||||
private final SensorManager mSensorManager;
|
||||
private final AsyncSensorManager mSensorManager;
|
||||
private final ContentResolver mResolver;
|
||||
private final TriggerSensor mPickupSensor;
|
||||
private final DozeParameters mDozeParameters;
|
||||
@@ -74,13 +74,13 @@ public class DozeSensors {
|
||||
protected TriggerSensor[] mSensors;
|
||||
|
||||
private final Handler mHandler = new Handler();
|
||||
private final ProxSensor mProxSensor;
|
||||
private final ProximitySensor mProximitySensor;
|
||||
private long mDebounceFrom;
|
||||
private boolean mSettingRegistered;
|
||||
private boolean mListening;
|
||||
private boolean mPaused;
|
||||
|
||||
public DozeSensors(Context context, AlarmManager alarmManager, SensorManager sensorManager,
|
||||
public DozeSensors(Context context, AlarmManager alarmManager, AsyncSensorManager sensorManager,
|
||||
DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
|
||||
Callback callback, Consumer<Boolean> proxCallback, AlwaysOnDisplayPolicy policy) {
|
||||
mContext = context;
|
||||
@@ -91,6 +91,7 @@ public class DozeSensors {
|
||||
mWakeLock = wakeLock;
|
||||
mProxCallback = proxCallback;
|
||||
mResolver = mContext.getContentResolver();
|
||||
mCallback = callback;
|
||||
|
||||
boolean alwaysOn = mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT);
|
||||
mSensors = new TriggerSensor[] {
|
||||
@@ -146,8 +147,11 @@ public class DozeSensors {
|
||||
false /* touchscreen */, mConfig.getWakeLockScreenDebounce()),
|
||||
};
|
||||
|
||||
mProxSensor = new ProxSensor(policy);
|
||||
mCallback = callback;
|
||||
mProximitySensor = new ProximitySensor(
|
||||
context, sensorManager, Dependency.get(PluginManager.class));
|
||||
|
||||
mProximitySensor.register(
|
||||
proximityEvent -> mProxCallback.accept(!proximityEvent.getNear()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,7 +240,15 @@ public class DozeSensors {
|
||||
}
|
||||
|
||||
public void setProxListening(boolean listen) {
|
||||
mProxSensor.setRequested(listen);
|
||||
if (mProximitySensor.isRegistered() && listen) {
|
||||
mProximitySensor.alertListeners();
|
||||
} else {
|
||||
if (listen) {
|
||||
mProximitySensor.resume();
|
||||
} else {
|
||||
mProximitySensor.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
|
||||
@@ -267,115 +279,16 @@ public class DozeSensors {
|
||||
/** Dump current state */
|
||||
public void dump(PrintWriter pw) {
|
||||
for (TriggerSensor s : mSensors) {
|
||||
pw.print(" Sensor: "); pw.println(s.toString());
|
||||
pw.println(" Sensor: " + s.toString());
|
||||
}
|
||||
pw.print(" ProxSensor: "); pw.println(mProxSensor.toString());
|
||||
pw.println(" ProxSensor: " + mProximitySensor.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if prox is currently far, false if near or null if unknown.
|
||||
* @return true if prox is currently near, false if far or null if unknown.
|
||||
*/
|
||||
public Boolean isProximityCurrentlyFar() {
|
||||
return mProxSensor.mCurrentlyFar;
|
||||
}
|
||||
|
||||
private class ProxSensor implements SensorEventListener {
|
||||
|
||||
boolean mRequested;
|
||||
boolean mRegistered;
|
||||
Boolean mCurrentlyFar;
|
||||
long mLastNear;
|
||||
final AlarmTimeout mCooldownTimer;
|
||||
final AlwaysOnDisplayPolicy mPolicy;
|
||||
final Sensor mSensor;
|
||||
final boolean mUsingBrightnessSensor;
|
||||
|
||||
public ProxSensor(AlwaysOnDisplayPolicy policy) {
|
||||
mPolicy = policy;
|
||||
mCooldownTimer = new AlarmTimeout(mAlarmManager, this::updateRegistered,
|
||||
"prox_cooldown", mHandler);
|
||||
|
||||
// The default prox sensor can be noisy, so let's use a prox gated brightness sensor
|
||||
// if available.
|
||||
Sensor sensor = DozeSensors.findSensorWithType(mSensorManager,
|
||||
mContext.getString(R.string.doze_brightness_sensor_type));
|
||||
mUsingBrightnessSensor = sensor != null;
|
||||
if (sensor == null) {
|
||||
sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
|
||||
}
|
||||
mSensor = sensor;
|
||||
}
|
||||
|
||||
void setRequested(boolean requested) {
|
||||
if (mRequested == requested) {
|
||||
// Send an update even if we don't re-register.
|
||||
mHandler.post(() -> {
|
||||
if (mCurrentlyFar != null) {
|
||||
mProxCallback.accept(mCurrentlyFar);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
mRequested = requested;
|
||||
updateRegistered();
|
||||
}
|
||||
|
||||
private void updateRegistered() {
|
||||
setRegistered(mRequested && !mCooldownTimer.isScheduled());
|
||||
}
|
||||
|
||||
private void setRegistered(boolean register) {
|
||||
if (mRegistered == register) {
|
||||
return;
|
||||
}
|
||||
if (register) {
|
||||
mRegistered = mSensorManager.registerListener(this, mSensor,
|
||||
SensorManager.SENSOR_DELAY_NORMAL, mHandler);
|
||||
} else {
|
||||
mSensorManager.unregisterListener(this);
|
||||
mRegistered = false;
|
||||
mCurrentlyFar = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSensorChanged(android.hardware.SensorEvent event) {
|
||||
if (DEBUG) Log.d(TAG, "onSensorChanged " + event);
|
||||
|
||||
if (mUsingBrightnessSensor) {
|
||||
// The custom brightness sensor is gated by the proximity sensor and will return 0
|
||||
// whenever prox is covered.
|
||||
mCurrentlyFar = event.values[0] > 0;
|
||||
} else {
|
||||
mCurrentlyFar = event.values[0] >= event.sensor.getMaximumRange();
|
||||
}
|
||||
mProxCallback.accept(mCurrentlyFar);
|
||||
|
||||
long now = SystemClock.elapsedRealtime();
|
||||
if (mCurrentlyFar == null) {
|
||||
// Sensor has been unregistered by the proxCallback. Do nothing.
|
||||
} else if (!mCurrentlyFar) {
|
||||
mLastNear = now;
|
||||
} else if (mCurrentlyFar && now - mLastNear < mPolicy.proxCooldownTriggerMs) {
|
||||
// If the last near was very recent, we might be using more power for prox
|
||||
// wakeups than we're saving from turning of the screen. Instead, turn it off
|
||||
// for a while.
|
||||
mCooldownTimer.schedule(mPolicy.proxCooldownPeriodMs,
|
||||
AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
|
||||
updateRegistered();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("{registered=%s, requested=%s, coolingDown=%s, currentlyFar=%s,"
|
||||
+ " sensor=%s}", mRegistered, mRequested, mCooldownTimer.isScheduled(),
|
||||
mCurrentlyFar, mSensor);
|
||||
}
|
||||
public Boolean isProximityCurrentlyNear() {
|
||||
return mProximitySensor.isNear();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -24,10 +24,6 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Configuration;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.hardware.display.AmbientDisplayConfiguration;
|
||||
import android.metrics.LogMaker;
|
||||
import android.os.Handler;
|
||||
@@ -39,16 +35,16 @@ import android.util.Log;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
import com.android.systemui.statusbar.phone.DozeParameters;
|
||||
import com.android.systemui.util.Assert;
|
||||
import com.android.systemui.util.sensors.AsyncSensorManager;
|
||||
import com.android.systemui.util.sensors.ProximitySensor;
|
||||
import com.android.systemui.util.wakelock.WakeLock;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Handles triggers for ambient state changes.
|
||||
@@ -67,13 +63,15 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
*/
|
||||
private static boolean sWakeDisplaySensorState = true;
|
||||
|
||||
private static final int PROXIMITY_TIMEOUT_DELAY_MS = 500;
|
||||
|
||||
private final Context mContext;
|
||||
private final DozeMachine mMachine;
|
||||
private final DozeSensors mDozeSensors;
|
||||
private final DozeHost mDozeHost;
|
||||
private final AmbientDisplayConfiguration mConfig;
|
||||
private final DozeParameters mDozeParameters;
|
||||
private final SensorManager mSensorManager;
|
||||
private final AsyncSensorManager mSensorManager;
|
||||
private final Handler mHandler;
|
||||
private final WakeLock mWakeLock;
|
||||
private final boolean mAllowPulseTriggers;
|
||||
@@ -81,6 +79,7 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
private final TriggerReceiver mBroadcastReceiver = new TriggerReceiver();
|
||||
private final DockEventListener mDockEventListener = new DockEventListener();
|
||||
private final DockManager mDockManager;
|
||||
private final ProximitySensor.ProximityCheck mProxCheck;
|
||||
|
||||
private long mNotificationPulseTime;
|
||||
private boolean mPulsePending;
|
||||
@@ -89,7 +88,7 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
|
||||
public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
|
||||
AlarmManager alarmManager, AmbientDisplayConfiguration config,
|
||||
DozeParameters dozeParameters, SensorManager sensorManager, Handler handler,
|
||||
DozeParameters dozeParameters, AsyncSensorManager sensorManager, Handler handler,
|
||||
WakeLock wakeLock, boolean allowPulseTriggers, DockManager dockManager) {
|
||||
mContext = context;
|
||||
mMachine = machine;
|
||||
@@ -105,6 +104,9 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
dozeParameters.getPolicy());
|
||||
mUiModeManager = mContext.getSystemService(UiModeManager.class);
|
||||
mDockManager = dockManager;
|
||||
mProxCheck = new ProximitySensor.ProximityCheck(
|
||||
new ProximitySensor(mContext, mSensorManager, null),
|
||||
mHandler);
|
||||
}
|
||||
|
||||
private void onNotification(Runnable onPulseSuppressedListener) {
|
||||
@@ -134,25 +136,27 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
}
|
||||
}
|
||||
|
||||
private void proximityCheckThenCall(IntConsumer callback,
|
||||
private void proximityCheckThenCall(Consumer<Boolean> callback,
|
||||
boolean alreadyPerformedProxCheck,
|
||||
int reason) {
|
||||
Boolean cachedProxFar = mDozeSensors.isProximityCurrentlyFar();
|
||||
Boolean cachedProxNear = mDozeSensors.isProximityCurrentlyNear();
|
||||
if (alreadyPerformedProxCheck) {
|
||||
callback.accept(ProximityCheck.RESULT_NOT_CHECKED);
|
||||
} else if (cachedProxFar != null) {
|
||||
callback.accept(cachedProxFar ? ProximityCheck.RESULT_FAR : ProximityCheck.RESULT_NEAR);
|
||||
callback.accept(null);
|
||||
} else if (cachedProxNear != null) {
|
||||
callback.accept(cachedProxNear);
|
||||
} else {
|
||||
final long start = SystemClock.uptimeMillis();
|
||||
new ProximityCheck() {
|
||||
@Override
|
||||
public void onProximityResult(int result) {
|
||||
final long end = SystemClock.uptimeMillis();
|
||||
DozeLog.traceProximityResult(mContext, result == RESULT_NEAR,
|
||||
end - start, reason);
|
||||
callback.accept(result);
|
||||
}
|
||||
}.check();
|
||||
mProxCheck.check(PROXIMITY_TIMEOUT_DELAY_MS, near -> {
|
||||
final long end = SystemClock.uptimeMillis();
|
||||
DozeLog.traceProximityResult(
|
||||
mContext,
|
||||
near == null ? false : near,
|
||||
end - start,
|
||||
reason);
|
||||
callback.accept(near);
|
||||
mWakeLock.release(TAG);
|
||||
});
|
||||
mWakeLock.acquire(TAG);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +182,7 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
}
|
||||
} else {
|
||||
proximityCheckThenCall((result) -> {
|
||||
if (result == ProximityCheck.RESULT_NEAR) {
|
||||
if (result) {
|
||||
// In pocket, drop event.
|
||||
return;
|
||||
}
|
||||
@@ -267,7 +271,7 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
|
||||
if (wake) {
|
||||
proximityCheckThenCall((result) -> {
|
||||
if (result == ProximityCheck.RESULT_NEAR) {
|
||||
if (result) {
|
||||
// In pocket, drop event.
|
||||
return;
|
||||
}
|
||||
@@ -376,7 +380,7 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
|
||||
mPulsePending = true;
|
||||
proximityCheckThenCall((result) -> {
|
||||
if (result == ProximityCheck.RESULT_NEAR) {
|
||||
if (result) {
|
||||
// in pocket, abort pulse
|
||||
DozeLog.tracePulseDropped(mContext, "inPocket");
|
||||
mPulsePending = false;
|
||||
@@ -412,104 +416,11 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
pw.print(" notificationPulseTime=");
|
||||
pw.println(Formatter.formatShortElapsedTime(mContext, mNotificationPulseTime));
|
||||
|
||||
pw.print(" pulsePending="); pw.println(mPulsePending);
|
||||
pw.println(" pulsePending=" + mPulsePending);
|
||||
pw.println("DozeSensors:");
|
||||
mDozeSensors.dump(pw);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DozeSensors.ProxSensor
|
||||
*/
|
||||
private abstract class ProximityCheck implements SensorEventListener, Runnable {
|
||||
private static final int TIMEOUT_DELAY_MS = 500;
|
||||
|
||||
protected static final int RESULT_UNKNOWN = 0;
|
||||
protected static final int RESULT_NEAR = 1;
|
||||
protected static final int RESULT_FAR = 2;
|
||||
protected static final int RESULT_NOT_CHECKED = 3;
|
||||
|
||||
private boolean mRegistered;
|
||||
private boolean mFinished;
|
||||
private float mMaxRange;
|
||||
private boolean mUsingBrightnessSensor;
|
||||
|
||||
protected abstract void onProximityResult(int result);
|
||||
|
||||
public void check() {
|
||||
Preconditions.checkState(!mFinished && !mRegistered);
|
||||
Sensor sensor = DozeSensors.findSensorWithType(mSensorManager,
|
||||
mContext.getString(R.string.doze_brightness_sensor_type));
|
||||
mUsingBrightnessSensor = sensor != null;
|
||||
if (sensor == null) {
|
||||
sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
|
||||
}
|
||||
if (sensor == null) {
|
||||
if (DozeMachine.DEBUG) Log.d(TAG, "ProxCheck: No sensor found");
|
||||
finishWithResult(RESULT_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
mDozeSensors.setDisableSensorsInterferingWithProximity(true);
|
||||
|
||||
mMaxRange = sensor.getMaximumRange();
|
||||
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, 0,
|
||||
mHandler);
|
||||
mHandler.postDelayed(this, TIMEOUT_DELAY_MS);
|
||||
mWakeLock.acquire(TAG);
|
||||
mRegistered = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DozeSensors.ProxSensor#onSensorChanged(SensorEvent)
|
||||
*/
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
if (event.values.length == 0) {
|
||||
if (DozeMachine.DEBUG) Log.d(TAG, "ProxCheck: Event has no values!");
|
||||
finishWithResult(RESULT_UNKNOWN);
|
||||
} else {
|
||||
if (DozeMachine.DEBUG) {
|
||||
Log.d(TAG, "ProxCheck: Event: value=" + event.values[0] + " max=" + mMaxRange);
|
||||
}
|
||||
final boolean isNear;
|
||||
if (mUsingBrightnessSensor) {
|
||||
// The custom brightness sensor is gated by the proximity sensor and will
|
||||
// return 0 whenever prox is covered.
|
||||
isNear = event.values[0] == 0;
|
||||
} else {
|
||||
isNear = event.values[0] < mMaxRange;
|
||||
}
|
||||
finishWithResult(isNear ? RESULT_NEAR : RESULT_FAR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (DozeMachine.DEBUG) Log.d(TAG, "ProxCheck: No event received before timeout");
|
||||
finishWithResult(RESULT_UNKNOWN);
|
||||
}
|
||||
|
||||
private void finishWithResult(int result) {
|
||||
if (mFinished) return;
|
||||
boolean wasRegistered = mRegistered;
|
||||
if (mRegistered) {
|
||||
mHandler.removeCallbacks(this);
|
||||
mSensorManager.unregisterListener(this);
|
||||
mDozeSensors.setDisableSensorsInterferingWithProximity(false);
|
||||
mRegistered = false;
|
||||
}
|
||||
onProximityResult(result);
|
||||
if (wasRegistered) {
|
||||
mWakeLock.release(TAG);
|
||||
}
|
||||
mFinished = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
private class TriggerReceiver extends BroadcastReceiver {
|
||||
private boolean mRegistered;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback
|
||||
import com.android.systemui.Dependency
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||
import com.android.systemui.util.Assert
|
||||
import com.android.systemui.util.AsyncSensorManager
|
||||
import com.android.systemui.util.sensors.AsyncSensorManager
|
||||
|
||||
class KeyguardLiftController constructor(
|
||||
private val statusBarStateController: StatusBarStateController,
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
* 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.util;
|
||||
package com.android.systemui.util.sensors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.HardwareBuffer;
|
||||
@@ -56,23 +56,31 @@ public class AsyncSensorManager extends SensorManager
|
||||
|
||||
private final SensorManager mInner;
|
||||
private final List<Sensor> mSensorCache;
|
||||
private final HandlerThread mHandlerThread = new HandlerThread("async_sensor");
|
||||
@VisibleForTesting final Handler mHandler;
|
||||
private final Handler mHandler;
|
||||
private final List<SensorManagerPlugin> mPlugins;
|
||||
|
||||
@Inject
|
||||
public AsyncSensorManager(Context context, PluginManager pluginManager) {
|
||||
this(context.getSystemService(SensorManager.class), pluginManager);
|
||||
this(context.getSystemService(SensorManager.class), pluginManager, null);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
AsyncSensorManager(SensorManager sensorManager, PluginManager pluginManager) {
|
||||
public AsyncSensorManager(
|
||||
SensorManager sensorManager, PluginManager pluginManager, Handler handler) {
|
||||
mInner = sensorManager;
|
||||
mHandlerThread.start();
|
||||
mHandler = new Handler(mHandlerThread.getLooper());
|
||||
if (handler == null) {
|
||||
HandlerThread handlerThread = new HandlerThread("async_sensor");
|
||||
handlerThread.start();
|
||||
mHandler = new Handler(handlerThread.getLooper());
|
||||
} else {
|
||||
mHandler = handler;
|
||||
}
|
||||
mSensorCache = mInner.getSensorList(Sensor.TYPE_ALL);
|
||||
mPlugins = new ArrayList<>();
|
||||
pluginManager.addPluginListener(this, SensorManagerPlugin.class, true /* allowMultiple */);
|
||||
if (pluginManager != null) {
|
||||
pluginManager.addPluginListener(this, SensorManagerPlugin.class,
|
||||
true /* allowMultiple */);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* 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.content.Context;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.shared.plugins.PluginManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Simple wrapper around SensorManager customized for the Proximity sensor.
|
||||
*/
|
||||
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 List<ProximitySensorListener> mListeners = new ArrayList<>();
|
||||
private String mTag = null;
|
||||
private ProximityEvent mLastEvent;
|
||||
private int mSensorDelay = SensorManager.SENSOR_DELAY_NORMAL;
|
||||
private boolean mPaused;
|
||||
private boolean mRegistered;
|
||||
|
||||
private SensorEventListener mSensorEventListener = new SensorEventListener() {
|
||||
@Override
|
||||
public synchronized void onSensorChanged(SensorEvent event) {
|
||||
onSensorEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
}
|
||||
};
|
||||
|
||||
@Inject
|
||||
public ProximitySensor(
|
||||
Context context, AsyncSensorManager sensorManager, PluginManager pluginManager) {
|
||||
mSensorManager = sensorManager;
|
||||
Sensor sensor = findBrightnessSensor(context);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public void setSensorDelay(int sensorDelay) {
|
||||
mSensorDelay = sensorDelay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister with the {@link SensorManager} without unsetting listeners on this object.
|
||||
*/
|
||||
public void pause() {
|
||||
mPaused = true;
|
||||
unregisterInternal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register with the {@link SensorManager}. No-op if no listeners are registered on this object.
|
||||
*/
|
||||
public void resume() {
|
||||
mPaused = false;
|
||||
registerInternal();
|
||||
}
|
||||
|
||||
private Sensor findBrightnessSensor(Context context) {
|
||||
String sensorType = context.getString(R.string.doze_brightness_sensor_type);
|
||||
List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
|
||||
Sensor sensor = null;
|
||||
for (Sensor s : sensorList) {
|
||||
if (sensorType.equals(s.getStringType())) {
|
||||
sensor = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return sensor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we are registered with the SensorManager.
|
||||
*/
|
||||
public boolean isRegistered() {
|
||||
return mRegistered;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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. If a cool down is currently running, the sensor will be registered when it is over.
|
||||
*/
|
||||
public boolean register(ProximitySensorListener listener) {
|
||||
if (!getSensorAvailable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
logDebug("Using brightness sensor? " + mUsingBrightnessSensor);
|
||||
mListeners.add(listener);
|
||||
registerInternal();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void registerInternal() {
|
||||
if (mRegistered || mPaused || mListeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
logDebug("Registering sensor listener");
|
||||
mRegistered = true;
|
||||
mSensorManager.registerListener(mSensorEventListener, mSensor, mSensorDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
unregisterInternal();
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterInternal() {
|
||||
if (!mRegistered) {
|
||||
return;
|
||||
}
|
||||
logDebug("unregistering sensor listener");
|
||||
mSensorManager.unregisterListener(mSensorEventListener);
|
||||
mRegistered = false;
|
||||
}
|
||||
|
||||
public Boolean isNear() {
|
||||
return getSensorAvailable() && mLastEvent != null ? mLastEvent.getNear() : null;
|
||||
}
|
||||
|
||||
/** Update all listeners with the last value this class received from the sensor. */
|
||||
public void alertListeners() {
|
||||
mListeners.forEach(proximitySensorListener ->
|
||||
proximitySensorListener.onSensorEvent(mLastEvent));
|
||||
}
|
||||
|
||||
private void onSensorEvent(SensorEvent event) {
|
||||
boolean near = event.values[0] < mMaxRange;
|
||||
if (mUsingBrightnessSensor) {
|
||||
near = event.values[0] == 0;
|
||||
}
|
||||
mLastEvent = new ProximityEvent(near, event.timestamp);
|
||||
alertListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("{registered=%s, paused=%s, near=%s, sensor=%s}",
|
||||
isRegistered(), mPaused, isNear(), mSensor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience class allowing for briefly checking the proximity sensor.
|
||||
*/
|
||||
public static class ProximityCheck implements Runnable {
|
||||
|
||||
private final ProximitySensor mSensor;
|
||||
private final Handler mHandler;
|
||||
private List<Consumer<Boolean>> mCallbacks = new ArrayList<>();
|
||||
|
||||
@Inject
|
||||
public ProximityCheck(ProximitySensor sensor, Handler handler) {
|
||||
mSensor = sensor;
|
||||
mSensor.setTag("prox_check");
|
||||
mHandler = handler;
|
||||
mSensor.pause();
|
||||
ProximitySensorListener listener = proximityEvent -> {
|
||||
mCallbacks.forEach(
|
||||
booleanConsumer ->
|
||||
booleanConsumer.accept(
|
||||
proximityEvent == null ? null : proximityEvent.getNear()));
|
||||
mCallbacks.clear();
|
||||
mSensor.pause();
|
||||
};
|
||||
mSensor.register(listener);
|
||||
}
|
||||
|
||||
/** Set a descriptive tag for the sensors registration. */
|
||||
public void setTag(String tag) {
|
||||
mSensor.setTag(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mSensor.pause();
|
||||
mSensor.alertListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the proximity sensor, timing out if no result.
|
||||
*/
|
||||
public void check(long timeoutMs, Consumer<Boolean> callback) {
|
||||
if (!mSensor.getSensorAvailable()) {
|
||||
callback.accept(null);
|
||||
}
|
||||
mCallbacks.add(callback);
|
||||
if (!mSensor.isRegistered()) {
|
||||
mSensor.resume();
|
||||
mHandler.postDelayed(this, timeoutMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Implement to be notified of ProximityEvents. */
|
||||
public interface ProximitySensorListener {
|
||||
/** Called when the ProximitySensor changes. */
|
||||
void onSensorEvent(ProximityEvent proximityEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returned when the near/far state of a {@link ProximitySensor} changes.
|
||||
*/
|
||||
public static class ProximityEvent {
|
||||
private final boolean mNear;
|
||||
private final long mTimestampNs;
|
||||
|
||||
public ProximityEvent(boolean near, long timestampNs) {
|
||||
mNear = near;
|
||||
mTimestampNs = timestampNs;
|
||||
}
|
||||
|
||||
public boolean getNear() {
|
||||
return mNear;
|
||||
}
|
||||
|
||||
public long getTimestampNs() {
|
||||
return mTimestampNs;
|
||||
}
|
||||
|
||||
public long getTimestampMs() {
|
||||
return mTimestampNs / 1000000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format((Locale) null, "{near=%s, timestamp_ns=%d}", mNear, mTimestampNs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void logDebug(String msg) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, (mTag != null ? "[" + mTag + "] " : "") + msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ import com.android.systemui.classifier.brightline.BrightLineFalsingManager;
|
||||
import com.android.systemui.shared.plugins.PluginManager;
|
||||
import com.android.systemui.util.DeviceConfigProxy;
|
||||
import com.android.systemui.util.DeviceConfigProxyFake;
|
||||
import com.android.systemui.util.ProximitySensor;
|
||||
import com.android.systemui.util.sensors.ProximitySensor;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
@@ -30,7 +30,7 @@ import android.view.MotionEvent;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.util.DeviceConfigProxyFake;
|
||||
import com.android.systemui.util.ProximitySensor;
|
||||
import com.android.systemui.util.sensors.ProximitySensor;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
@@ -24,7 +24,7 @@ import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.withSettings;
|
||||
|
||||
import com.android.systemui.statusbar.phone.DozeParameters;
|
||||
import com.android.systemui.utils.hardware.FakeSensorManager;
|
||||
import com.android.systemui.util.sensors.FakeSensorManager;
|
||||
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.MockSettings;
|
||||
|
||||
@@ -40,7 +40,7 @@ import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.utils.hardware.FakeSensorManager;
|
||||
import com.android.systemui.util.sensors.FakeSensorManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -44,7 +44,7 @@ import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.doze.DozeSensors.TriggerSensor;
|
||||
import com.android.systemui.plugins.SensorManagerPlugin;
|
||||
import com.android.systemui.statusbar.phone.DozeParameters;
|
||||
import com.android.systemui.util.AsyncSensorManager;
|
||||
import com.android.systemui.util.sensors.AsyncSensorManager;
|
||||
import com.android.systemui.util.wakelock.WakeLock;
|
||||
|
||||
import org.junit.Before;
|
||||
|
||||
@@ -32,6 +32,7 @@ import android.hardware.display.AmbientDisplayConfiguration;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.testing.TestableLooper.RunWithLooper;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -39,9 +40,10 @@ import androidx.test.filters.SmallTest;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
import com.android.systemui.statusbar.phone.DozeParameters;
|
||||
import com.android.systemui.util.sensors.AsyncSensorManager;
|
||||
import com.android.systemui.util.sensors.FakeSensorManager;
|
||||
import com.android.systemui.util.wakelock.WakeLock;
|
||||
import com.android.systemui.util.wakelock.WakeLockFake;
|
||||
import com.android.systemui.utils.hardware.FakeSensorManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
@@ -55,12 +57,8 @@ public class DozeTriggersTest extends SysuiTestCase {
|
||||
private DozeTriggers mTriggers;
|
||||
private DozeMachine mMachine;
|
||||
private DozeHostFake mHost;
|
||||
private AmbientDisplayConfiguration mConfig;
|
||||
private DozeParameters mParameters;
|
||||
private FakeSensorManager mSensors;
|
||||
private Sensor mTapSensor;
|
||||
private WakeLock mWakeLock;
|
||||
private AlarmManager mAlarmManager;
|
||||
private DockManager mDockManagerFake;
|
||||
|
||||
@BeforeClass
|
||||
@@ -72,18 +70,21 @@ public class DozeTriggersTest extends SysuiTestCase {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mMachine = mock(DozeMachine.class);
|
||||
mAlarmManager = mock(AlarmManager.class);
|
||||
AlarmManager alarmManager = mock(AlarmManager.class);
|
||||
mHost = spy(new DozeHostFake());
|
||||
mConfig = DozeConfigurationUtil.createMockConfig();
|
||||
mParameters = DozeConfigurationUtil.createMockParameters();
|
||||
AmbientDisplayConfiguration config = DozeConfigurationUtil.createMockConfig();
|
||||
DozeParameters parameters = DozeConfigurationUtil.createMockParameters();
|
||||
mSensors = spy(new FakeSensorManager(mContext));
|
||||
mTapSensor = mSensors.getFakeTapSensor().getSensor();
|
||||
mWakeLock = new WakeLockFake();
|
||||
WakeLock wakeLock = new WakeLockFake();
|
||||
mDockManagerFake = mock(DockManager.class);
|
||||
AsyncSensorManager asyncSensorManager =
|
||||
new AsyncSensorManager(mSensors, null, new Handler());
|
||||
|
||||
mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager, mConfig, mParameters,
|
||||
mSensors, Handler.createAsync(Looper.myLooper()), mWakeLock, true,
|
||||
mTriggers = new DozeTriggers(mContext, mMachine, mHost, alarmManager, config, parameters,
|
||||
asyncSensorManager, Handler.createAsync(Looper.myLooper()), wakeLock, true,
|
||||
mDockManagerFake);
|
||||
waitForSensorManager();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -95,13 +96,14 @@ public class DozeTriggersTest extends SysuiTestCase {
|
||||
clearInvocations(mMachine);
|
||||
|
||||
mHost.callback.onNotificationAlerted(null /* pulseSuppressedListener */);
|
||||
mSensors.getMockProximitySensor().sendProximityResult(false); /* Near */
|
||||
mSensors.getFakeProximitySensor().sendProximityResult(false); /* Near */
|
||||
|
||||
verify(mMachine, never()).requestState(any());
|
||||
verify(mMachine, never()).requestPulse(anyInt());
|
||||
|
||||
mHost.callback.onNotificationAlerted(null /* pulseSuppressedListener */);
|
||||
mSensors.getMockProximitySensor().sendProximityResult(true); /* Far */
|
||||
waitForSensorManager();
|
||||
mSensors.getFakeProximitySensor().sendProximityResult(true); /* Far */
|
||||
|
||||
verify(mMachine).requestPulse(anyInt());
|
||||
}
|
||||
@@ -111,6 +113,7 @@ public class DozeTriggersTest extends SysuiTestCase {
|
||||
when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
|
||||
|
||||
mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
|
||||
waitForSensorManager();
|
||||
verify(mSensors).requestTriggerSensor(any(), eq(mTapSensor));
|
||||
|
||||
clearInvocations(mSensors);
|
||||
@@ -118,10 +121,12 @@ public class DozeTriggersTest extends SysuiTestCase {
|
||||
DozeMachine.State.DOZE_REQUEST_PULSE);
|
||||
mTriggers.transitionTo(DozeMachine.State.DOZE_REQUEST_PULSE,
|
||||
DozeMachine.State.DOZE_PULSING);
|
||||
waitForSensorManager();
|
||||
verify(mSensors).cancelTriggerSensor(any(), eq(mTapSensor));
|
||||
|
||||
clearInvocations(mSensors);
|
||||
mTriggers.transitionTo(DozeMachine.State.DOZE_PULSING, DozeMachine.State.DOZE_PULSE_DONE);
|
||||
waitForSensorManager();
|
||||
verify(mSensors).requestTriggerSensor(any(), eq(mTapSensor));
|
||||
}
|
||||
|
||||
@@ -133,4 +138,8 @@ public class DozeTriggersTest extends SysuiTestCase {
|
||||
mTriggers.transitionTo(DozeMachine.State.DOZE, DozeMachine.State.FINISH);
|
||||
verify(mDockManagerFake).removeListener(any());
|
||||
}
|
||||
|
||||
private void waitForSensorManager() {
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
* 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.
|
||||
@@ -14,9 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.util;
|
||||
package com.android.systemui.util.sensors;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -24,15 +23,15 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Handler;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.plugins.SensorManagerPlugin;
|
||||
import com.android.systemui.shared.plugins.PluginManager;
|
||||
import com.android.systemui.utils.hardware.FakeSensorManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -40,20 +39,21 @@ import org.junit.runner.RunWith;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class AsyncSensorManagerTest extends SysuiTestCase {
|
||||
|
||||
private TestableAsyncSensorManager mAsyncSensorManager;
|
||||
private FakeSensorManager mFakeSensorManager;
|
||||
private AsyncSensorManager mAsyncSensorManager;
|
||||
private SensorEventListener mListener;
|
||||
private FakeSensorManager.MockProximitySensor mSensor;
|
||||
private FakeSensorManager.FakeProximitySensor mSensor;
|
||||
private PluginManager mPluginManager;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mPluginManager = mock(PluginManager.class);
|
||||
mFakeSensorManager = new FakeSensorManager(mContext);
|
||||
mAsyncSensorManager = new TestableAsyncSensorManager(mFakeSensorManager);
|
||||
mSensor = mFakeSensorManager.getMockProximitySensor();
|
||||
FakeSensorManager fakeSensorManager = new FakeSensorManager(mContext);
|
||||
mAsyncSensorManager = new AsyncSensorManager(
|
||||
fakeSensorManager, mPluginManager, new Handler());
|
||||
mSensor = fakeSensorManager.getFakeProximitySensor();
|
||||
mListener = mock(SensorEventListener.class);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public class AsyncSensorManagerTest extends SysuiTestCase {
|
||||
public void registerListenerImpl() throws Exception {
|
||||
mAsyncSensorManager.registerListener(mListener, mSensor.getSensor(), 100);
|
||||
|
||||
mAsyncSensorManager.waitUntilRequestsCompleted();
|
||||
waitUntilRequestsCompleted();
|
||||
|
||||
// Verify listener was registered.
|
||||
mSensor.sendProximityResult(true);
|
||||
@@ -73,7 +73,7 @@ public class AsyncSensorManagerTest extends SysuiTestCase {
|
||||
mAsyncSensorManager.registerListener(mListener, mSensor.getSensor(), 100);
|
||||
mAsyncSensorManager.unregisterListener(mListener);
|
||||
|
||||
mAsyncSensorManager.waitUntilRequestsCompleted();
|
||||
waitUntilRequestsCompleted();
|
||||
|
||||
// Verify listener was unregistered.
|
||||
mSensor.sendProximityResult(true);
|
||||
@@ -85,7 +85,7 @@ public class AsyncSensorManagerTest extends SysuiTestCase {
|
||||
mAsyncSensorManager.registerListener(mListener, mSensor.getSensor(), 100);
|
||||
mAsyncSensorManager.unregisterListener(mListener, mSensor.getSensor());
|
||||
|
||||
mAsyncSensorManager.waitUntilRequestsCompleted();
|
||||
waitUntilRequestsCompleted();
|
||||
|
||||
// Verify listener was unregistered.
|
||||
mSensor.sendProximityResult(true);
|
||||
@@ -98,13 +98,7 @@ public class AsyncSensorManagerTest extends SysuiTestCase {
|
||||
eq(SensorManagerPlugin.class), eq(true) /* allowMultiple */);
|
||||
}
|
||||
|
||||
private class TestableAsyncSensorManager extends AsyncSensorManager {
|
||||
public TestableAsyncSensorManager(SensorManager sensorManager) {
|
||||
super(sensorManager, mPluginManager);
|
||||
}
|
||||
|
||||
public void waitUntilRequestsCompleted() {
|
||||
assertTrue(mHandler.runWithScissors(() -> {}, 0));
|
||||
}
|
||||
public void waitUntilRequestsCompleted() {
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,10 @@
|
||||
* 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
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.utils.hardware;
|
||||
package com.android.systemui.util.sensors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.HardwareBuffer;
|
||||
@@ -54,7 +54,7 @@ public class FakeSensorManager extends SensorManager {
|
||||
|
||||
public static final String TAP_SENSOR_TYPE = "tapSensorType";
|
||||
|
||||
private final MockProximitySensor mMockProximitySensor;
|
||||
private final FakeProximitySensor mFakeProximitySensor;
|
||||
private final FakeGenericSensor mFakeLightSensor;
|
||||
private final FakeGenericSensor mFakeTapSensor;
|
||||
private final FakeGenericSensor[] mSensors;
|
||||
@@ -68,14 +68,14 @@ public class FakeSensorManager extends SensorManager {
|
||||
}
|
||||
|
||||
mSensors = new FakeGenericSensor[]{
|
||||
mMockProximitySensor = new MockProximitySensor(proxSensor),
|
||||
mFakeProximitySensor = new FakeProximitySensor(proxSensor),
|
||||
mFakeLightSensor = new FakeGenericSensor(createSensor(Sensor.TYPE_LIGHT, null)),
|
||||
mFakeTapSensor = new FakeGenericSensor(createSensor(99, TAP_SENSOR_TYPE))
|
||||
};
|
||||
}
|
||||
|
||||
public MockProximitySensor getMockProximitySensor() {
|
||||
return mMockProximitySensor;
|
||||
public FakeProximitySensor getFakeProximitySensor() {
|
||||
return mFakeProximitySensor;
|
||||
}
|
||||
|
||||
public FakeGenericSensor getFakeLightSensor() {
|
||||
@@ -231,9 +231,9 @@ public class FakeSensorManager extends SensorManager {
|
||||
setter.invoke(sensor, type);
|
||||
}
|
||||
|
||||
public class MockProximitySensor extends FakeGenericSensor {
|
||||
public class FakeProximitySensor extends FakeGenericSensor {
|
||||
|
||||
private MockProximitySensor(Sensor sensor) {
|
||||
private FakeProximitySensor(Sensor sensor) {
|
||||
super(sensor);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* 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 static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class ProximitySensorTest extends SysuiTestCase {
|
||||
|
||||
private ProximitySensor mProximitySensor;
|
||||
private FakeSensorManager.FakeProximitySensor mFakeProximitySensor;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
FakeSensorManager sensorManager = new FakeSensorManager(getContext());
|
||||
AsyncSensorManager asyncSensorManager = new AsyncSensorManager(
|
||||
sensorManager, null, new Handler());
|
||||
mFakeProximitySensor = sensorManager.getFakeProximitySensor();
|
||||
mProximitySensor = new ProximitySensor(getContext(), asyncSensorManager, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleListener() {
|
||||
TestableListener listener = new TestableListener();
|
||||
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
mProximitySensor.register(listener);
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertNull(listener.mLastEvent);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 1);
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertTrue(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 2);
|
||||
|
||||
mProximitySensor.unregister(listener);
|
||||
waitForSensorManager();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiListener() {
|
||||
TestableListener listenerA = new TestableListener();
|
||||
TestableListener listenerB = new TestableListener();
|
||||
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
|
||||
mProximitySensor.register(listenerA);
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
mProximitySensor.register(listenerB);
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertNull(listenerA.mLastEvent);
|
||||
assertNull(listenerB.mLastEvent);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listenerA.mLastEvent.getNear());
|
||||
assertFalse(listenerB.mLastEvent.getNear());
|
||||
assertEquals(listenerA.mCallCount, 1);
|
||||
assertEquals(listenerB.mCallCount, 1);
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertTrue(listenerA.mLastEvent.getNear());
|
||||
assertTrue(listenerB.mLastEvent.getNear());
|
||||
assertEquals(listenerA.mCallCount, 2);
|
||||
assertEquals(listenerB.mCallCount, 2);
|
||||
|
||||
mProximitySensor.unregister(listenerA);
|
||||
mProximitySensor.unregister(listenerB);
|
||||
waitForSensorManager();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnregister() {
|
||||
TestableListener listener = new TestableListener();
|
||||
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
mProximitySensor.register(listener);
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertNull(listener.mLastEvent);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 1);
|
||||
|
||||
mProximitySensor.unregister(listener);
|
||||
waitForSensorManager();
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPauseAndResume() {
|
||||
TestableListener listener = new TestableListener();
|
||||
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
mProximitySensor.register(listener);
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertNull(listener.mLastEvent);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 1);
|
||||
|
||||
mProximitySensor.pause();
|
||||
waitForSensorManager();
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
|
||||
// More events do nothing when paused.
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 1);
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertFalse(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 1);
|
||||
|
||||
mProximitySensor.resume();
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
// Still matches our previous call
|
||||
assertFalse(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 1);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(true);
|
||||
assertFalse(listener.mLastEvent.getNear());
|
||||
assertEquals(listener.mCallCount, 2);
|
||||
|
||||
mProximitySensor.unregister(listener);
|
||||
waitForSensorManager();
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlertListeners() {
|
||||
TestableListener listenerA = new TestableListener();
|
||||
TestableListener listenerB = new TestableListener();
|
||||
|
||||
assertFalse(mProximitySensor.isRegistered());
|
||||
|
||||
mProximitySensor.register(listenerA);
|
||||
mProximitySensor.register(listenerB);
|
||||
waitForSensorManager();
|
||||
assertTrue(mProximitySensor.isRegistered());
|
||||
assertNull(listenerA.mLastEvent);
|
||||
assertNull(listenerB.mLastEvent);
|
||||
|
||||
mProximitySensor.alertListeners();
|
||||
assertNull(listenerA.mLastEvent);
|
||||
assertEquals(listenerA.mCallCount, 1);
|
||||
assertNull(listenerB.mLastEvent);
|
||||
assertEquals(listenerB.mCallCount, 1);
|
||||
|
||||
mFakeProximitySensor.sendProximityResult(false);
|
||||
assertTrue(listenerA.mLastEvent.getNear());
|
||||
assertEquals(listenerA.mCallCount, 2);
|
||||
assertTrue(listenerB.mLastEvent.getNear());
|
||||
assertEquals(listenerB.mCallCount, 2);
|
||||
|
||||
mProximitySensor.unregister(listenerA);
|
||||
mProximitySensor.unregister(listenerB);
|
||||
waitForSensorManager();
|
||||
}
|
||||
|
||||
class TestableListener implements ProximitySensor.ProximitySensorListener {
|
||||
ProximitySensor.ProximityEvent mLastEvent;
|
||||
int mCallCount = 0;
|
||||
|
||||
@Override
|
||||
public void onSensorEvent(ProximitySensor.ProximityEvent proximityEvent) {
|
||||
mLastEvent = proximityEvent;
|
||||
mCallCount++;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
mLastEvent = null;
|
||||
mCallCount = 0;
|
||||
}
|
||||
};
|
||||
|
||||
private void waitForSensorManager() {
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user