Update DozeSensors and DozeBrightnessSensor on posture changes

If the posture changes while AOD is running, make sure
sensors are unregistered + registered properly.

Test: manual, enable AOD and then close/open and check that
correct sensors are registered (dumpsys sensorservice)
Test: atest DozeScreenBrightnessTest DozeSensorsTest
Fixes: 192805135
Fixes: 199344667

Change-Id: I5093dc43e062144adca757c94fa708f51be57a44
This commit is contained in:
Beverly
2021-10-05 14:02:42 -04:00
parent d43e521e9b
commit 1905cf9110
17 changed files with 700 additions and 191 deletions

View File

@@ -22,11 +22,9 @@ import android.os.Build;
import android.os.SystemProperties;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import java.util.Arrays;
import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
/**
* AmbientDisplayConfiguration encapsulates reading access to the configuration of ambient display.
@@ -90,7 +88,12 @@ public class AmbientDisplayConfiguration {
/** {@hide} */
public boolean tapSensorAvailable() {
return !TextUtils.isEmpty(tapSensorType());
for (String tapType : tapSensorTypeMapping()) {
if (!TextUtils.isEmpty(tapType)) {
return true;
}
}
return false;
}
/** {@hide} */
@@ -143,18 +146,18 @@ public class AmbientDisplayConfiguration {
return mContext.getResources().getString(R.string.config_dozeDoubleTapSensorType);
}
/** {@hide} */
private String tapSensorType() {
return mContext.getResources().getString(R.string.config_dozeTapSensorType);
}
/** {@hide} */
public String tapSensorType(int posture) {
return getSensorFromPostureMapping(
mContext.getResources().getStringArray(R.array.config_dozeTapSensorPostureMapping),
tapSensorType(),
posture
);
/** {@hide}
* May support multiple postures.
*/
public String[] tapSensorTypeMapping() {
String[] postureMapping =
mContext.getResources().getStringArray(R.array.config_dozeTapSensorPostureMapping);
if (ArrayUtils.isEmpty(postureMapping)) {
return new String[] {
mContext.getResources().getString(R.string.config_dozeTapSensorType)
};
}
return postureMapping;
}
/** {@hide} */
@@ -253,20 +256,4 @@ public class AmbientDisplayConfiguration {
private boolean boolSetting(String name, int user, int def) {
return Settings.Secure.getIntForUser(mContext.getContentResolver(), name, def, user) != 0;
}
/** {@hide} */
public static String getSensorFromPostureMapping(
String[] postureMapping,
String defaultValue,
int posture) {
String sensorType = defaultValue;
if (postureMapping != null && posture < postureMapping.length) {
sensorType = postureMapping[posture];
} else {
Log.e(TAG, "Unsupported doze posture " + posture
+ " postureMapping=" + Arrays.toString(postureMapping));
}
return TextUtils.isEmpty(sensorType) ? defaultValue : sensorType;
}
}

View File

@@ -26,6 +26,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.policy.DevicePostureController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -267,6 +268,16 @@ public class DozeLog implements Dumpable {
}
}
/**
* Appends doze updates due to a posture change.
*/
public void tracePostureChanged(
@DevicePostureController.DevicePostureInt int posture,
String partUpdated
) {
mLogger.logPostureChanged(posture, partUpdated);
}
/**
* Appends pulse dropped event to logs
*/
@@ -391,8 +402,8 @@ public class DozeLog implements Dumpable {
case REASON_SENSOR_DOUBLE_TAP: return "doubletap";
case PULSE_REASON_SENSOR_LONG_PRESS: return "longpress";
case PULSE_REASON_DOCKING: return "docking";
case PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN: return "reach-wakelockscreen";
case REASON_SENSOR_WAKE_UP: return "presence-wakeup";
case PULSE_REASON_SENSOR_WAKE_REACH: return "reach-wakelockscreen";
case REASON_SENSOR_WAKE_UP_PRESENCE: return "presence-wakeup";
case REASON_SENSOR_TAP: return "tap";
case REASON_SENSOR_UDFPS_LONG_PRESS: return "udfps";
case REASON_SENSOR_QUICK_PICKUP: return "quickPickup";
@@ -403,8 +414,8 @@ public class DozeLog implements Dumpable {
@Retention(RetentionPolicy.SOURCE)
@IntDef({PULSE_REASON_NONE, PULSE_REASON_INTENT, PULSE_REASON_NOTIFICATION,
PULSE_REASON_SENSOR_SIGMOTION, REASON_SENSOR_PICKUP, REASON_SENSOR_DOUBLE_TAP,
PULSE_REASON_SENSOR_LONG_PRESS, PULSE_REASON_DOCKING, REASON_SENSOR_WAKE_UP,
PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN, REASON_SENSOR_TAP,
PULSE_REASON_SENSOR_LONG_PRESS, PULSE_REASON_DOCKING, REASON_SENSOR_WAKE_UP_PRESENCE,
PULSE_REASON_SENSOR_WAKE_REACH, REASON_SENSOR_TAP,
REASON_SENSOR_UDFPS_LONG_PRESS, REASON_SENSOR_QUICK_PICKUP})
public @interface Reason {}
public static final int PULSE_REASON_NONE = -1;
@@ -415,8 +426,8 @@ public class DozeLog implements Dumpable {
public static final int REASON_SENSOR_DOUBLE_TAP = 4;
public static final int PULSE_REASON_SENSOR_LONG_PRESS = 5;
public static final int PULSE_REASON_DOCKING = 6;
public static final int REASON_SENSOR_WAKE_UP = 7;
public static final int PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN = 8;
public static final int REASON_SENSOR_WAKE_UP_PRESENCE = 7;
public static final int PULSE_REASON_SENSOR_WAKE_REACH = 8;
public static final int REASON_SENSOR_TAP = 9;
public static final int REASON_SENSOR_UDFPS_LONG_PRESS = 10;
public static final int REASON_SENSOR_QUICK_PICKUP = 11;

View File

@@ -24,6 +24,7 @@ import com.android.systemui.log.LogLevel.DEBUG
import com.android.systemui.log.LogLevel.ERROR
import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.log.dagger.DozeLog
import com.android.systemui.statusbar.policy.DevicePostureController
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@@ -195,6 +196,16 @@ class DozeLogger @Inject constructor(
})
}
fun logPostureChanged(posture: Int, partUpdated: String) {
buffer.log(TAG, INFO, {
int1 = posture
str1 = partUpdated
}, {
"Posture changed, posture=${DevicePostureController.devicePostureToString(int1)}" +
" partUpdated=$str1"
})
}
fun logPulseDropped(pulsePending: Boolean, state: DozeMachine.State, blocked: Boolean) {
buffer.log(TAG, INFO, {
bool1 = pulsePending

View File

@@ -29,16 +29,18 @@ import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.IndentingPrintWriter;
import com.android.systemui.dock.DockManager;
import com.android.systemui.doze.dagger.BrightnessSensor;
import com.android.systemui.doze.dagger.DozeScope;
import com.android.systemui.doze.dagger.WrappedService;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.util.sensors.AsyncSensorManager;
import java.io.PrintWriter;
import java.util.Objects;
import java.util.Optional;
import javax.inject.Inject;
@@ -60,14 +62,17 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
private final DozeHost mDozeHost;
private final Handler mHandler;
private final SensorManager mSensorManager;
private final Optional<Sensor> mLightSensorOptional;
private final Optional<Sensor>[] mLightSensorOptional; // light sensors to use per posture
private final WakefulnessLifecycle mWakefulnessLifecycle;
private final DozeParameters mDozeParameters;
private final DockManager mDockManager;
private final DevicePostureController mDevicePostureController;
private final DozeLog mDozeLog;
private final int[] mSensorToBrightness;
private final int[] mSensorToScrimOpacity;
private final int mScreenBrightnessDim;
@DevicePostureController.DevicePostureInt
private int mDevicePosture;
private boolean mRegistered;
private int mDefaultDozeBrightness;
private boolean mPaused = false;
@@ -83,27 +88,36 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
private int mDebugBrightnessBucket = -1;
@Inject
public DozeScreenBrightness(Context context, @WrappedService DozeMachine.Service service,
public DozeScreenBrightness(
Context context,
@WrappedService DozeMachine.Service service,
AsyncSensorManager sensorManager,
@BrightnessSensor Optional<Sensor> lightSensorOptional, DozeHost host, Handler handler,
@BrightnessSensor Optional<Sensor>[] lightSensorOptional,
DozeHost host, Handler handler,
AlwaysOnDisplayPolicy alwaysOnDisplayPolicy,
WakefulnessLifecycle wakefulnessLifecycle,
DozeParameters dozeParameters,
DockManager dockManager) {
DevicePostureController devicePostureController,
DozeLog dozeLog
) {
mContext = context;
mDozeService = service;
mSensorManager = sensorManager;
mLightSensorOptional = lightSensorOptional;
mDevicePostureController = devicePostureController;
mDevicePosture = mDevicePostureController.getDevicePosture();
mWakefulnessLifecycle = wakefulnessLifecycle;
mDozeParameters = dozeParameters;
mDozeHost = host;
mHandler = handler;
mDockManager = dockManager;
mDozeLog = dozeLog;
mDefaultDozeBrightness = alwaysOnDisplayPolicy.defaultDozeBrightness;
mScreenBrightnessDim = alwaysOnDisplayPolicy.dimBrightness;
mSensorToBrightness = alwaysOnDisplayPolicy.screenBrightnessArray;
mSensorToScrimOpacity = alwaysOnDisplayPolicy.dimmingScrimArray;
mDevicePostureController.addCallback(mDevicePostureCallback);
}
@Override
@@ -133,6 +147,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
private void onDestroy() {
setLightSensorEnabled(false);
mDevicePostureController.removeCallback(mDevicePostureCallback);
}
@Override
@@ -159,7 +174,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
}
int scrimOpacity = -1;
if (!mLightSensorOptional.isPresent()) {
if (!isLightSensorPresent()) {
// No light sensor, scrims are always transparent.
scrimOpacity = 0;
} else if (brightnessReady) {
@@ -172,6 +187,27 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
}
}
private boolean lightSensorSupportsCurrentPosture() {
return mLightSensorOptional != null
&& mDevicePosture < mLightSensorOptional.length;
}
private boolean isLightSensorPresent() {
if (!lightSensorSupportsCurrentPosture()) {
return mLightSensorOptional != null && mLightSensorOptional[0].isPresent();
}
return mLightSensorOptional[mDevicePosture].isPresent();
}
private Sensor getLightSensor() {
if (!lightSensorSupportsCurrentPosture()) {
return null;
}
return mLightSensorOptional[mDevicePosture].get();
}
private int computeScrimOpacity(int sensorValue) {
if (sensorValue < 0 || sensorValue >= mSensorToScrimOpacity.length) {
return -1;
@@ -220,9 +256,9 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
}
private void setLightSensorEnabled(boolean enabled) {
if (enabled && !mRegistered && mLightSensorOptional.isPresent()) {
if (enabled && !mRegistered && isLightSensorPresent()) {
// Wait until we get an event from the sensor until indicating ready.
mRegistered = mSensorManager.registerListener(this, mLightSensorOptional.get(),
mRegistered = mSensorManager.registerListener(this, getLightSensor(),
SensorManager.SENSOR_DELAY_NORMAL, mHandler);
mLastSensorValue = -1;
} else if (!enabled && mRegistered) {
@@ -255,6 +291,41 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
/** Dump current state */
public void dump(PrintWriter pw) {
pw.println("DozeScreenBrightnessSensorRegistered=" + mRegistered);
pw.println("DozeScreenBrightness:");
IndentingPrintWriter idpw = new IndentingPrintWriter(pw);
idpw.increaseIndent();
idpw.println("registered=" + mRegistered);
idpw.println("posture=" + DevicePostureController.devicePostureToString(mDevicePosture));
}
private final DevicePostureController.Callback mDevicePostureCallback =
new DevicePostureController.Callback() {
@Override
public void onPostureChanged(int posture) {
if (mDevicePosture == posture
|| mLightSensorOptional.length < 2
|| posture >= mLightSensorOptional.length) {
return;
}
final Sensor oldSensor = mLightSensorOptional[mDevicePosture].get();
final Sensor newSensor = mLightSensorOptional[posture].get();
if (Objects.equals(oldSensor, newSensor)) {
mDevicePosture = posture;
// uses the same sensor for the new posture
return;
}
// cancel the previous sensor:
if (mRegistered) {
setLightSensorEnabled(false);
mDevicePosture = posture;
setLightSensorEnabled(true);
} else {
mDevicePosture = posture;
}
mDozeLog.tracePostureChanged(mDevicePosture, "DozeScreenBrightness swap "
+ "{" + oldSensor + "} => {" + newSensor + "}, mRegistered=" + mRegistered);
}
};
}

View File

@@ -38,6 +38,7 @@ import android.util.IndentingPrintWriter;
import android.util.Log;
import android.view.Display;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.UiEvent;
@@ -54,10 +55,36 @@ import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.wakelock.WakeLock;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
/**
* Tracks and registers/unregisters sensors while the device is dozing based on the config
* provided by {@link AmbientDisplayConfiguration} and parameters provided by {@link DozeParameters}
*
* Sensors registration depends on:
* - sensor existence/availability
* - user configuration (some can be toggled on/off via settings)
* - use of the proximity sensor (sometimes prox cannot be registered in certain display states)
* - touch state
* - device posture
*
* Sensors will trigger the provided Callback's {@link Callback#onSensorPulse} method.
* These sensors include:
* - pickup gesture
* - single and double tap gestures
* - udfps long-press gesture
* - reach and presence gestures
* - quick pickup gesture (low-threshold pickup gesture)
*
* This class also registers a ProximitySensor that reports near/far events and will
* trigger callbacks on the provided {@link mProxCallback}.
*/
public class DozeSensors {
private static final boolean DEBUG = DozeService.DEBUG;
@@ -68,15 +95,21 @@ public class DozeSensors {
private final AsyncSensorManager mSensorManager;
private final AmbientDisplayConfiguration mConfig;
private final WakeLock mWakeLock;
private final Consumer<Boolean> mProxCallback;
private final DozeLog mDozeLog;
private final SecureSettings mSecureSettings;
private final Callback mCallback;
private final DevicePostureController mDevicePostureController;
private final boolean mScreenOffUdfpsEnabled;
// Sensors
@VisibleForTesting
protected TriggerSensor[] mSensors;
protected TriggerSensor[] mTriggerSensors;
private final ProximitySensor mProximitySensor;
// Sensor callbacks
private final Callback mSensorCallback; // receives callbacks on registered sensor events
private final Consumer<Boolean> mProxCallback; // receives callbacks on near/far updates
private final Handler mHandler = new Handler();
private final ProximitySensor mProximitySensor;
private long mDebounceFrom;
private boolean mSettingRegistered;
private boolean mListening;
@@ -106,37 +139,47 @@ public class DozeSensors {
}
}
DozeSensors(Context context, AsyncSensorManager sensorManager,
DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
Callback callback, Consumer<Boolean> proxCallback, DozeLog dozeLog,
ProximitySensor proximitySensor, SecureSettings secureSettings,
DozeSensors(
Context context,
AsyncSensorManager sensorManager,
DozeParameters dozeParameters,
AmbientDisplayConfiguration config,
WakeLock wakeLock,
Callback sensorCallback,
Consumer<Boolean> proxCallback,
DozeLog dozeLog,
ProximitySensor proximitySensor,
SecureSettings secureSettings,
AuthController authController,
int devicePosture) {
DevicePostureController devicePostureController
) {
mContext = context;
mSensorManager = sensorManager;
mConfig = config;
mWakeLock = wakeLock;
mProxCallback = proxCallback;
mSecureSettings = secureSettings;
mCallback = callback;
mSensorCallback = sensorCallback;
mDozeLog = dozeLog;
mProximitySensor = proximitySensor;
mProximitySensor.setTag(TAG);
mSelectivelyRegisterProxSensors = dozeParameters.getSelectivelyRegisterSensorsUsingProx();
mListeningProxSensors = !mSelectivelyRegisterProxSensors;
mScreenOffUdfpsEnabled =
config.screenOffUdfpsEnabled(KeyguardUpdateMonitor.getCurrentUser());
mDevicePosture = devicePosture;
mDevicePostureController = devicePostureController;
mDevicePosture = mDevicePostureController.getDevicePosture();
boolean udfpsEnrolled =
authController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser());
boolean alwaysOn = mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT);
mSensors = new TriggerSensor[] {
mTriggerSensors = new TriggerSensor[] {
new TriggerSensor(
mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION),
null /* setting */,
dozeParameters.getPulseOnSigMotion(),
DozeLog.PULSE_REASON_SENSOR_SIGMOTION, false /* touchCoords */,
false /* touchscreen */, dozeLog),
false /* touchscreen */),
new TriggerSensor(
mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE),
Settings.Secure.DOZE_PICK_UP_GESTURE,
@@ -145,18 +188,16 @@ public class DozeSensors {
DozeLog.REASON_SENSOR_PICKUP, false /* touchCoords */,
false /* touchscreen */,
false /* ignoresSetting */,
false /* requires prox */,
dozeLog),
false /* requires prox */),
new TriggerSensor(
findSensor(config.doubleTapSensorType()),
Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
true /* configured */,
DozeLog.REASON_SENSOR_DOUBLE_TAP,
dozeParameters.doubleTapReportsTouchCoordinates(),
true /* touchscreen */,
dozeLog),
true /* touchscreen */),
new TriggerSensor(
findSensor(config.tapSensorType(mDevicePosture)),
findSensors(config.tapSensorTypeMapping()),
Settings.Secure.DOZE_TAP_SCREEN_GESTURE,
true /* settingDef */,
true /* configured */,
@@ -165,7 +206,7 @@ public class DozeSensors {
true /* touchscreen */,
false /* ignoresSetting */,
dozeParameters.singleTapUsesProx(mDevicePosture) /* requiresProx */,
dozeLog),
mDevicePosture),
new TriggerSensor(
findSensor(config.longPressSensorType()),
Settings.Secure.DOZE_PULSE_ON_LONG_PRESS,
@@ -175,8 +216,7 @@ public class DozeSensors {
true /* reports touch coordinates */,
true /* touchscreen */,
false /* ignoresSetting */,
dozeParameters.longPressUsesProx() /* requiresProx */,
dozeLog),
dozeParameters.longPressUsesProx() /* requiresProx */),
new TriggerSensor(
findSensor(config.udfpsLongPressSensorType()),
"doze_pulse_on_auth",
@@ -186,25 +226,22 @@ public class DozeSensors {
true /* reports touch coordinates */,
true /* touchscreen */,
false /* ignoresSetting */,
dozeParameters.longPressUsesProx(),
dozeLog),
dozeParameters.longPressUsesProx()),
new PluginSensor(
new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY),
Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
mConfig.wakeScreenGestureAvailable() && alwaysOn,
DozeLog.REASON_SENSOR_WAKE_UP,
DozeLog.REASON_SENSOR_WAKE_UP_PRESENCE,
false /* reports touch coordinates */,
false /* touchscreen */,
dozeLog),
false /* touchscreen */),
new PluginSensor(
new SensorManagerPlugin.Sensor(TYPE_WAKE_LOCK_SCREEN),
Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
mConfig.wakeScreenGestureAvailable(),
DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN,
DozeLog.PULSE_REASON_SENSOR_WAKE_REACH,
false /* reports touch coordinates */,
false /* touchscreen */,
mConfig.getWakeLockScreenDebounce(),
dozeLog),
mConfig.getWakeLockScreenDebounce()),
new TriggerSensor(
findSensor(config.quickPickupSensorType()),
Settings.Secure.DOZE_QUICK_PICKUP_GESTURE,
@@ -212,10 +249,11 @@ public class DozeSensors {
config.quickPickupSensorEnabled(KeyguardUpdateMonitor.getCurrentUser())
&& udfpsEnrolled,
DozeLog.REASON_SENSOR_QUICK_PICKUP,
false /* touchCoords */,
false /* touchscreen */, dozeLog),
false /* requiresTouchCoordinates */,
false /* requiresTouchscreen */,
false /* ignoresSetting */,
false /* requiresProx */),
};
setProxListening(false); // Don't immediately start listening when we register.
mProximitySensor.register(
proximityEvent -> {
@@ -223,17 +261,21 @@ public class DozeSensors {
mProxCallback.accept(!proximityEvent.getBelow());
}
});
mDevicePostureController.addCallback(mDevicePostureCallback);
}
/**
* Unregister any sensors.
* Unregister all sensors and callbacks.
*/
public void destroy() {
// Unregisters everything, which is enough to allow gc.
for (TriggerSensor triggerSensor : mSensors) {
for (TriggerSensor triggerSensor : mTriggerSensors) {
triggerSensor.setListening(false);
}
mProximitySensor.pause();
mDevicePostureController.removeCallback(mDevicePostureCallback);
}
/**
@@ -248,6 +290,24 @@ public class DozeSensors {
return findSensor(mSensorManager, type, null);
}
@NonNull
private Sensor[] findSensors(@NonNull String[] types) {
Sensor[] sensorMap = new Sensor[DevicePostureController.SUPPORTED_POSTURES_SIZE];
// Map of sensorType => Sensor, so we reuse the same sensor if it's the same between
// postures
Map<String, Sensor> typeToSensorMap = new HashMap<>();
for (int i = 0; i < types.length; i++) {
String sensorType = types[i];
if (!typeToSensorMap.containsKey(sensorType)) {
typeToSensorMap.put(sensorType, findSensor(sensorType));
}
sensorMap[i] = typeToSensorMap.get(sensorType);
}
return sensorMap;
}
/**
* Utility method to find a {@link Sensor} for the supplied string type and string name.
*
@@ -306,7 +366,7 @@ public class DozeSensors {
*/
private void updateListening() {
boolean anyListening = false;
for (TriggerSensor s : mSensors) {
for (TriggerSensor s : mTriggerSensors) {
boolean listen = mListening
&& (!s.mRequiresTouchscreen || mListeningTouchScreenSensors)
&& (!s.mRequiresProx || mListeningProxSensors);
@@ -319,7 +379,7 @@ public class DozeSensors {
if (!anyListening) {
mSecureSettings.unregisterContentObserver(mSettingsObserver);
} else if (!mSettingRegistered) {
for (TriggerSensor s : mSensors) {
for (TriggerSensor s : mTriggerSensors) {
s.registerSettingsObserver(mSettingsObserver);
}
}
@@ -328,7 +388,7 @@ public class DozeSensors {
/** Set the listening state of only the sensors that require the touchscreen. */
public void setTouchscreenSensorsListening(boolean listening) {
for (TriggerSensor sensor : mSensors) {
for (TriggerSensor sensor : mTriggerSensors) {
if (sensor.mRequiresTouchscreen) {
sensor.setListening(listening);
}
@@ -336,7 +396,7 @@ public class DozeSensors {
}
public void onUserSwitched() {
for (TriggerSensor s : mSensors) {
for (TriggerSensor s : mTriggerSensors) {
s.updateListening();
}
}
@@ -366,7 +426,7 @@ public class DozeSensors {
if (userId != ActivityManager.getCurrentUser()) {
return;
}
for (TriggerSensor s : mSensors) {
for (TriggerSensor s : mTriggerSensors) {
s.updateListening();
}
}
@@ -374,7 +434,7 @@ public class DozeSensors {
/** Ignore the setting value of only the sensors that require the touchscreen. */
public void ignoreTouchScreenSensorsSettingInterferingWithDocking(boolean ignore) {
for (TriggerSensor sensor : mSensors) {
for (TriggerSensor sensor : mTriggerSensors) {
if (sensor.mRequiresTouchscreen) {
sensor.ignoreSetting(ignore);
}
@@ -392,7 +452,7 @@ public class DozeSensors {
pw.println("mScreenOffUdfpsEnabled=" + mScreenOffUdfpsEnabled);
IndentingPrintWriter idpw = new IndentingPrintWriter(pw);
idpw.increaseIndent();
for (TriggerSensor s : mSensors) {
for (TriggerSensor s : mTriggerSensors) {
idpw.println("Sensor: " + s.toString());
}
idpw.println("ProxSensor: " + mProximitySensor.toString());
@@ -407,7 +467,7 @@ public class DozeSensors {
@VisibleForTesting
class TriggerSensor extends TriggerEventListener {
final Sensor mSensor;
@NonNull final Sensor[] mSensors; // index = posture, value = sensor
final boolean mConfigured;
final int mPulseReason;
private final String mSetting;
@@ -420,27 +480,67 @@ public class DozeSensors {
protected boolean mRegistered;
protected boolean mDisabled;
protected boolean mIgnoresSetting;
protected final DozeLog mDozeLog;
private @DevicePostureController.DevicePostureInt int mPosture;
public TriggerSensor(Sensor sensor, String setting, boolean configured, int pulseReason,
boolean reportsTouchCoordinates, boolean requiresTouchscreen, DozeLog dozeLog) {
this(sensor, setting, true /* settingDef */, configured, pulseReason,
reportsTouchCoordinates, requiresTouchscreen, dozeLog);
TriggerSensor(
Sensor sensor,
String setting,
boolean configured,
int pulseReason,
boolean reportsTouchCoordinates,
boolean requiresTouchscreen
) {
this(
sensor,
setting,
true /* settingDef */,
configured,
pulseReason,
false /* ignoresSetting */,
false /* requiresProx */,
reportsTouchCoordinates,
requiresTouchscreen
);
}
public TriggerSensor(Sensor sensor, String setting, boolean settingDef,
boolean configured, int pulseReason, boolean reportsTouchCoordinates,
boolean requiresTouchscreen, DozeLog dozeLog) {
this(sensor, setting, settingDef, configured, pulseReason, reportsTouchCoordinates,
requiresTouchscreen, false /* ignoresSetting */,
false /* requiresProx */, dozeLog);
TriggerSensor(
Sensor sensor,
String setting,
boolean settingDef,
boolean configured,
int pulseReason,
boolean reportsTouchCoordinates,
boolean requiresTouchscreen,
boolean ignoresSetting,
boolean requiresProx
) {
this(
new Sensor[]{ sensor },
setting,
settingDef,
configured,
pulseReason,
reportsTouchCoordinates,
requiresTouchscreen,
ignoresSetting,
requiresProx,
DevicePostureController.DEVICE_POSTURE_UNKNOWN
);
}
private TriggerSensor(Sensor sensor, String setting, boolean settingDef,
boolean configured, int pulseReason, boolean reportsTouchCoordinates,
boolean requiresTouchscreen, boolean ignoresSetting, boolean requiresProx,
DozeLog dozeLog) {
mSensor = sensor;
TriggerSensor(
@NonNull Sensor[] sensors,
String setting,
boolean settingDef,
boolean configured,
int pulseReason,
boolean reportsTouchCoordinates,
boolean requiresTouchscreen,
boolean ignoresSetting,
boolean requiresProx,
@DevicePostureController.DevicePostureInt int posture
) {
mSensors = sensors;
mSetting = setting;
mSettingDefault = settingDef;
mConfigured = configured;
@@ -449,7 +549,43 @@ public class DozeSensors {
mRequiresTouchscreen = requiresTouchscreen;
mIgnoresSetting = ignoresSetting;
mRequiresProx = requiresProx;
mDozeLog = dozeLog;
mPosture = posture;
}
/**
* @return true if the sensor changed based for the new posture
*/
public boolean setPosture(@DevicePostureController.DevicePostureInt int posture) {
if (mPosture == posture
|| mSensors.length < 2
|| posture >= mSensors.length) {
return false;
}
Sensor oldSensor = mSensors[mPosture];
Sensor newSensor = mSensors[posture];
if (Objects.equals(oldSensor, newSensor)) {
mPosture = posture;
// uses the same sensor for the new posture
return false;
}
// cancel the previous sensor:
if (mRegistered) {
final boolean rt = mSensorManager.cancelTriggerSensor(this, oldSensor);
if (DEBUG) {
Log.d(TAG, "posture changed, cancelTriggerSensor[" + oldSensor + "] "
+ rt);
}
mRegistered = false;
}
// update the new sensor:
mPosture = posture;
updateListening();
mDozeLog.tracePostureChanged(mPosture, "DozeSensors swap "
+ "{" + oldSensor + "} => {" + newSensor + "}, mRegistered=" + mRegistered);
return true;
}
public void setListening(boolean listen) {
@@ -471,24 +607,23 @@ public class DozeSensors {
}
public void updateListening() {
if (!mConfigured || mSensor == null) return;
final Sensor sensor = mSensors[mPosture];
if (!mConfigured || sensor == null) return;
if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting)) {
if (!mRegistered) {
mRegistered = mSensorManager.requestTriggerSensor(this, mSensor);
mRegistered = mSensorManager.requestTriggerSensor(this, sensor);
if (DEBUG) {
Log.d(TAG, "requestTriggerSensor[" + mSensor
+ "] " + mRegistered);
Log.d(TAG, "requestTriggerSensor[" + sensor + "] " + mRegistered);
}
} else {
if (DEBUG) {
Log.d(TAG, "requestTriggerSensor[" + mSensor
+ "] already registered");
Log.d(TAG, "requestTriggerSensor[" + sensor + "] already registered");
}
}
} else if (mRegistered) {
final boolean rt = mSensorManager.cancelTriggerSensor(this, mSensor);
final boolean rt = mSensorManager.cancelTriggerSensor(this, sensor);
if (DEBUG) {
Log.d(TAG, "cancelTriggerSensor[" + mSensor + "] " + rt);
Log.d(TAG, "cancelTriggerSensor[" + sensor + "] " + rt);
}
mRegistered = false;
}
@@ -506,21 +641,29 @@ public class DozeSensors {
@Override
public String toString() {
return new StringBuilder("{mRegistered=").append(mRegistered)
StringBuilder sb = new StringBuilder();
sb.append("{")
.append("mRegistered=").append(mRegistered)
.append(", mRequested=").append(mRequested)
.append(", mDisabled=").append(mDisabled)
.append(", mConfigured=").append(mConfigured)
.append(", mIgnoresSetting=").append(mIgnoresSetting)
.append(", mSensor=").append(mSensor).append("}").toString();
.append(", mSensors=").append(Arrays.toString(mSensors));
if (mSensors.length > 2) {
sb.append(", mPosture=")
.append(DevicePostureController.devicePostureToString(mDevicePosture));
}
return sb.append("}").toString();
}
@Override
@AnyThread
public void onTrigger(TriggerEvent event) {
final Sensor sensor = mSensors[mDevicePosture];
mDozeLog.traceSensor(mPulseReason);
mHandler.post(mWakeLock.wrap(() -> {
if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
if (mSensor != null && mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
if (sensor != null && sensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
UI_EVENT_LOGGER.log(DozeSensorsUiEvent.ACTION_AMBIENT_GESTURE_PICKUP);
}
@@ -531,7 +674,7 @@ public class DozeSensors {
screenX = event.values[0];
screenY = event.values[1];
}
mCallback.onSensorPulse(mPulseReason, screenX, screenY, event.values);
mSensorCallback.onSensorPulse(mPulseReason, screenX, screenY, event.values);
if (!mRegistered) {
updateListening(); // reregister, this sensor only fires once
}
@@ -569,17 +712,16 @@ public class DozeSensors {
private long mDebounce;
PluginSensor(SensorManagerPlugin.Sensor sensor, String setting, boolean configured,
int pulseReason, boolean reportsTouchCoordinates, boolean requiresTouchscreen,
DozeLog dozeLog) {
int pulseReason, boolean reportsTouchCoordinates, boolean requiresTouchscreen) {
this(sensor, setting, configured, pulseReason, reportsTouchCoordinates,
requiresTouchscreen, 0L /* debounce */, dozeLog);
requiresTouchscreen, 0L /* debounce */);
}
PluginSensor(SensorManagerPlugin.Sensor sensor, String setting, boolean configured,
int pulseReason, boolean reportsTouchCoordinates, boolean requiresTouchscreen,
long debounce, DozeLog dozeLog) {
long debounce) {
super(null, setting, configured, pulseReason, reportsTouchCoordinates,
requiresTouchscreen, dozeLog);
requiresTouchscreen);
mPluginSensor = sensor;
mDebounce = debounce;
}
@@ -633,11 +775,22 @@ public class DozeSensors {
return;
}
if (DEBUG) Log.d(TAG, "onSensorEvent: " + triggerEventToString(event));
mCallback.onSensorPulse(mPulseReason, -1, -1, event.getValues());
mSensorCallback.onSensorPulse(mPulseReason, -1, -1, event.getValues());
}));
}
}
private final DevicePostureController.Callback mDevicePostureCallback = posture -> {
if (mDevicePosture == posture) {
return;
}
mDevicePosture = posture;
for (TriggerSensor triggerSensor : mTriggerSensors) {
triggerSensor.setPosture(mDevicePosture);
}
};
public interface Callback {
/**

View File

@@ -99,8 +99,6 @@ public class DozeTriggers implements DozeMachine.Part {
private final UiEventLogger mUiEventLogger;
private final DevicePostureController mDevicePostureController;
private @DevicePostureController.DevicePostureInt int mDevicePosture;
private long mNotificationPulseTime;
private boolean mPulsePending;
private Runnable mAodInterruptRunnable;
@@ -197,11 +195,12 @@ public class DozeTriggers implements DozeMachine.Part {
mSensorManager = sensorManager;
mWakeLock = wakeLock;
mAllowPulseTriggers = true;
mDevicePostureController = devicePostureController;
mDevicePosture = devicePostureController.getDevicePosture();
mDozeSensors = new DozeSensors(context, mSensorManager, dozeParameters,
config, wakeLock, this::onSensor, this::onProximityFar, dozeLog, proximitySensor,
secureSettings, authController, mDevicePosture);
secureSettings, authController, devicePostureController);
mUiModeManager = mContext.getSystemService(UiModeManager.class);
mDockManager = dockManager;
mProxCheck = proxCheck;
@@ -212,6 +211,10 @@ public class DozeTriggers implements DozeMachine.Part {
mUiEventLogger = uiEventLogger;
mKeyguardStateController = keyguardStateController;
}
private final DevicePostureController.Callback mDevicePostureCallback =
posture -> {
};
@Override
public void setDozeMachine(DozeMachine dozeMachine) {
@@ -284,8 +287,8 @@ public class DozeTriggers implements DozeMachine.Part {
boolean isTap = pulseReason == DozeLog.REASON_SENSOR_TAP;
boolean isPickup = pulseReason == DozeLog.REASON_SENSOR_PICKUP;
boolean isLongPress = pulseReason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS;
boolean isWakeOnPresence = pulseReason == DozeLog.REASON_SENSOR_WAKE_UP;
boolean isWakeOnReach = pulseReason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN;
boolean isWakeOnPresence = pulseReason == DozeLog.REASON_SENSOR_WAKE_UP_PRESENCE;
boolean isWakeOnReach = pulseReason == DozeLog.PULSE_REASON_SENSOR_WAKE_REACH;
boolean isUdfpsLongPress = pulseReason == DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
boolean isQuickPickup = pulseReason == DozeLog.REASON_SENSOR_QUICK_PICKUP;
boolean isWakeDisplayEvent = isQuickPickup || ((isWakeOnPresence || isWakeOnReach)
@@ -455,7 +458,7 @@ public class DozeTriggers implements DozeMachine.Part {
mWantSensors = true;
mWantTouchScreenSensors = true;
if (newState == DozeMachine.State.DOZE_AOD && !sWakeDisplaySensorState) {
onWakeScreen(false, newState, DozeLog.REASON_SENSOR_WAKE_UP);
onWakeScreen(false, newState, DozeLog.REASON_SENSOR_WAKE_UP_PRESENCE);
}
break;
case DOZE_AOD_PAUSED:
@@ -524,7 +527,7 @@ public class DozeTriggers implements DozeMachine.Part {
// When already pulsing we're allowed to show the wallpaper directly without
// requesting a new pulse.
if (dozeState == DozeMachine.State.DOZE_PULSING
&& reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
&& reason == DozeLog.PULSE_REASON_SENSOR_WAKE_REACH) {
mMachine.requestState(DozeMachine.State.DOZE_PULSING_BRIGHT);
return;
}

View File

@@ -155,7 +155,7 @@ public class DozeUi implements DozeMachine.Part, TunerService.Tunable,
public void onPulseStarted() {
try {
mMachine.requestState(
reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN
reason == DozeLog.PULSE_REASON_SENSOR_WAKE_REACH
? DozeMachine.State.DOZE_PULSING_BRIGHT
: DozeMachine.State.DOZE_PULSING);
} catch (IllegalStateException e) {

View File

@@ -43,6 +43,9 @@ import com.android.systemui.util.sensors.AsyncSensorManager;
import com.android.systemui.util.wakelock.DelayedWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import dagger.Module;
@@ -94,16 +97,43 @@ public abstract class DozeModule {
@Provides
@BrightnessSensor
static Optional<Sensor> providesBrightnessSensor(
static Optional<Sensor>[] providesBrightnessSensors(
AsyncSensorManager sensorManager,
Context context,
DozeParameters dozeParameters,
DevicePostureController devicePostureController) {
return Optional.ofNullable(
DozeSensors.findSensor(
sensorManager,
context.getString(R.string.doze_brightness_sensor_type),
dozeParameters.brightnessName(devicePostureController.getDevicePosture())
));
DozeParameters dozeParameters) {
String[] sensorNames = dozeParameters.brightnessNames();
if (sensorNames.length == 0 || sensorNames == null) {
// if no brightness names are specified, just use the brightness sensor type
return new Optional[]{
Optional.ofNullable(DozeSensors.findSensor(
sensorManager,
context.getString(R.string.doze_brightness_sensor_type),
null
))
};
}
// length and index of brightnessMap correspond to DevicePostureController.DevicePostureInt:
final Optional<Sensor>[] brightnessSensorMap =
new Optional[DevicePostureController.SUPPORTED_POSTURES_SIZE];
Arrays.fill(brightnessSensorMap, Optional.empty());
// Map of sensorName => Sensor, so we reuse the same sensor if it's the same between
// postures
Map<String, Optional<Sensor>> nameToSensorMap = new HashMap<>();
for (int i = 0; i < sensorNames.length; i++) {
final String sensorName = sensorNames[i];
if (!nameToSensorMap.containsKey(sensorName)) {
nameToSensorMap.put(sensorName,
Optional.ofNullable(
DozeSensors.findSensor(
sensorManager,
context.getString(R.string.doze_brightness_sensor_type),
sensorNames[i]
)));
}
brightnessSensorMap[i] = nameToSensorMap.get(sensorName);
}
return brightnessSensorMap;
}
}

View File

@@ -283,14 +283,12 @@ public class DozeParameters implements
}
/**
* Sensor to use for brightness changes.
* Gets the brightness string array per posture. Brightness names along with
* doze_brightness_sensor_type is used to determine the brightness sensor to use for
* the current posture.
*/
public String brightnessName(@DevicePostureController.DevicePostureInt int posture) {
return AmbientDisplayConfiguration.getSensorFromPostureMapping(
mResources.getStringArray(R.array.doze_brightness_sensor_name_posture_mapping),
null /* defaultValue */,
posture
);
public String[] brightnessNames() {
return mResources.getStringArray(R.array.doze_brightness_sensor_name_posture_mapping);
}
/**

View File

@@ -226,11 +226,11 @@ public final class DozeServiceHost implements DozeHost {
return;
}
if (reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
if (reason == DozeLog.PULSE_REASON_SENSOR_WAKE_REACH) {
mScrimController.setWakeLockScreenSensorActive(true);
}
boolean passiveAuthInterrupt = reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN
boolean passiveAuthInterrupt = reason == DozeLog.PULSE_REASON_SENSOR_WAKE_REACH
&& mWakeLockScreenPerformsAuth;
// Set the state to pulsing, so ScrimController will know what to do once we ask it to
// execute the transition. The pulse callback will then be invoked when the scrims
@@ -329,7 +329,7 @@ public final class DozeServiceHost implements DozeHost {
@Override
public void extendPulse(int reason) {
if (reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
if (reason == DozeLog.PULSE_REASON_SENSOR_WAKE_REACH) {
mScrimController.setWakeLockScreenSensorActive(true);
}
if (mDozeScrimController.isPulsing() && mHeadsUpManagerPhone.hasNotifications()) {

View File

@@ -29,6 +29,7 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -177,9 +178,7 @@ public class SensorModule {
// 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;
}
Arrays.fill(sensorMap, noProxSensor);
if (!hasPostureSupport(sensorTypes)) {
Log.e("SensorModule", "config doesn't support postures,"

View File

@@ -67,7 +67,8 @@ public class DozeConfigurationUtil {
when(config.tapGestureEnabled(anyInt())).thenReturn(true);
when(config.tapSensorAvailable()).thenReturn(true);
when(config.tapSensorType(anyInt())).thenReturn(FakeSensorManager.TAP_SENSOR_TYPE);
when(config.tapSensorTypeMapping()).thenReturn(
new String[]{FakeSensorManager.TAP_SENSOR_TYPE});
when(config.dozePickupSensorAvailable()).thenReturn(false);
when(config.wakeScreenGestureAvailable()).thenReturn(false);

View File

@@ -51,6 +51,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.concurrency.FakeThreadFactory;
import com.android.systemui.util.sensors.AsyncSensorManager;
@@ -60,6 +61,7 @@ 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.Mock;
import org.mockito.MockitoAnnotations;
@@ -76,6 +78,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
private DozeServiceFake mServiceFake;
private FakeSensorManager.FakeGenericSensor mSensor;
private FakeSensorManager.FakeGenericSensor mSensorInner;
private AsyncSensorManager mSensorManager;
private AlwaysOnDisplayPolicy mAlwaysOnDisplayPolicy;
@Mock
@@ -86,6 +89,10 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
DozeParameters mDozeParameters;
@Mock
DockManager mDockManager;
@Mock
DevicePostureController mDevicePostureController;
@Mock
DozeLog mDozeLog;
private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
private FakeThreadFactory mFakeThreadFactory = new FakeThreadFactory(mFakeExecutor);
@@ -111,9 +118,19 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
mAlwaysOnDisplayPolicy.dimBrightness = DIM_BRIGHTNESS;
mAlwaysOnDisplayPolicy.dimmingScrimArray = SENSOR_TO_OPACITY;
mSensor = fakeSensorManager.getFakeLightSensor();
mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager,
Optional.of(mSensor.getSensor()), mDozeHost, null /* handler */,
mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, mDockManager);
mSensorInner = fakeSensorManager.getFakeLightSensor2();
mScreen = new DozeScreenBrightness(
mContext,
mServiceFake,
mSensorManager,
new Optional[]{Optional.of(mSensor.getSensor())},
mDozeHost,
null /* handler */,
mAlwaysOnDisplayPolicy,
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
mDozeLog);
}
@Test
@@ -151,7 +168,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
@Test
public void doze_doesNotUseLightSensor() {
// GIVEN the device is docked and the display state changes to ON
// GIVEN the device is DOZE and the display state changes to ON
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
waitForSensorManager();
@@ -166,7 +183,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
@Test
public void aod_usesLightSensor() {
// GIVEN the device is docked and the display state changes to ON
// GIVEN the device is DOZE_AOD and the display state changes to ON
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
waitForSensorManager();
@@ -209,9 +226,17 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
@Test
public void testPulsing_withoutLightSensor_setsAoDDimmingScrimTransparent() throws Exception {
mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager,
Optional.empty() /* sensor */, mDozeHost, null /* handler */,
mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, mDockManager);
mScreen = new DozeScreenBrightness(
mContext,
mServiceFake,
mSensorManager,
new Optional[] {Optional.empty()} /* sensor */,
mDozeHost, null /* handler */,
mAlwaysOnDisplayPolicy,
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
mDozeLog);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
reset(mDozeHost);
@@ -238,9 +263,17 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
@Test
public void testNullSensor() throws Exception {
mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager,
Optional.empty() /* sensor */, mDozeHost, null /* handler */,
mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, mDockManager);
mScreen = new DozeScreenBrightness(
mContext,
mServiceFake,
mSensorManager,
new Optional[]{Optional.empty()} /* sensor */,
mDozeHost, null /* handler */,
mAlwaysOnDisplayPolicy,
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
mDozeLog);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
@@ -248,6 +281,130 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);
}
@Test
public void testSensorsSupportPostures_closed() throws Exception {
// GIVEN the device is CLOSED
when(mDevicePostureController.getDevicePosture()).thenReturn(
DevicePostureController.DEVICE_POSTURE_CLOSED);
// GIVEN closed and opened postures use different light sensors
mScreen = new DozeScreenBrightness(
mContext,
mServiceFake,
mSensorManager,
new Optional[]{
Optional.empty() /* unknown */,
Optional.of(mSensor.getSensor()) /* closed */,
Optional.of(mSensorInner.getSensor()) /* half-opened */,
Optional.of(mSensorInner.getSensor()) /* opened */,
Optional.empty() /* flipped */
},
mDozeHost, null /* handler */,
mAlwaysOnDisplayPolicy,
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
mDozeLog);
// GIVEN the device is in AOD
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
waitForSensorManager();
// WHEN new different events are sent from the inner and outer sensors
mSensor.sendSensorEvent(3); // CLOSED sensor
mSensorInner.sendSensorEvent(4); // OPENED sensor
// THEN brightness is updated according to the sensor for CLOSED
assertEquals(3, mServiceFake.screenBrightness);
}
@Test
public void testSensorsSupportPostures_open() throws Exception {
// GIVEN the device is OPENED
when(mDevicePostureController.getDevicePosture()).thenReturn(
DevicePostureController.DEVICE_POSTURE_OPENED);
// GIVEN closed and opened postures use different light sensors
mScreen = new DozeScreenBrightness(
mContext,
mServiceFake,
mSensorManager,
new Optional[]{
Optional.empty() /* unknown */,
Optional.of(mSensor.getSensor()) /* closed */,
Optional.of(mSensorInner.getSensor()) /* half-opened */,
Optional.of(mSensorInner.getSensor()) /* opened */,
Optional.empty() /* flipped */
},
mDozeHost, null /* handler */,
mAlwaysOnDisplayPolicy,
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
mDozeLog);
// GIVEN device is in AOD
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
waitForSensorManager();
// WHEN new different events are sent from the inner and outer sensors
mSensorInner.sendSensorEvent(4); // OPENED sensor
mSensor.sendSensorEvent(3); // CLOSED sensor
// THEN brightness is updated according to the sensor for OPENED
assertEquals(4, mServiceFake.screenBrightness);
}
@Test
public void testSensorsSupportPostures_swapPostures() throws Exception {
ArgumentCaptor<DevicePostureController.Callback> postureCallbackCaptor =
ArgumentCaptor.forClass(DevicePostureController.Callback.class);
reset(mDevicePostureController);
// GIVEN the device starts up AOD OPENED
when(mDevicePostureController.getDevicePosture()).thenReturn(
DevicePostureController.DEVICE_POSTURE_OPENED);
// GIVEN closed and opened postures use different light sensors
mScreen = new DozeScreenBrightness(
mContext,
mServiceFake,
mSensorManager,
new Optional[]{
Optional.empty() /* unknown */,
Optional.of(mSensor.getSensor()) /* closed */,
Optional.of(mSensorInner.getSensor()) /* half-opened */,
Optional.of(mSensorInner.getSensor()) /* opened */,
Optional.empty() /* flipped */
},
mDozeHost, null /* handler */,
mAlwaysOnDisplayPolicy,
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
mDozeLog);
verify(mDevicePostureController).addCallback(postureCallbackCaptor.capture());
// GIVEN device is in AOD
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
waitForSensorManager();
// WHEN the posture changes to CLOSED
postureCallbackCaptor.getValue().onPostureChanged(
DevicePostureController.DEVICE_POSTURE_CLOSED);
waitForSensorManager();
// WHEN new different events are sent from the inner and outer sensors
mSensor.sendSensorEvent(3); // CLOSED sensor
mSensorInner.sendSensorEvent(4); // OPENED sensor
// THEN brightness is updated according to the sensor for CLOSED
assertEquals(3, mServiceFake.screenBrightness);
}
@Test
public void testNoBrightnessDeliveredAfterFinish() throws Exception {
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);

View File

@@ -91,9 +91,9 @@ public class DozeSensorsTest extends SysuiTestCase {
@Mock
private AuthController mAuthController;
@Mock
private DevicePostureController mDevicePostureController;
@Mock
private ProximitySensor mProximitySensor;
private @DevicePostureController.DevicePostureInt int mDevicePosture =
DevicePostureController.DEVICE_POSTURE_UNKNOWN;
private FakeSettings mFakeSettings = new FakeSettings();
private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener;
private TestableLooper mTestableLooper;
@@ -104,13 +104,14 @@ public class DozeSensorsTest extends SysuiTestCase {
public void setUp() {
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
when(mAmbientDisplayConfiguration.tapSensorTypeMapping())
.thenReturn(new String[]{"tapSEnsor"});
when(mAmbientDisplayConfiguration.getWakeLockScreenDebounce()).thenReturn(5000L);
when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
doAnswer(invocation -> {
((Runnable) invocation.getArgument(0)).run();
return null;
}).when(mWakeLock).wrap(any(Runnable.class));
mDevicePosture = DevicePostureController.DEVICE_POSTURE_UNKNOWN;
mDozeSensors = new TestableDozeSensors();
}
@@ -127,14 +128,14 @@ public class DozeSensorsTest extends SysuiTestCase {
mWakeLockScreenListener.onSensorChanged(mock(SensorManagerPlugin.SensorEvent.class));
mTestableLooper.processAllMessages();
verify(mCallback).onSensorPulse(eq(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN),
verify(mCallback).onSensorPulse(eq(DozeLog.PULSE_REASON_SENSOR_WAKE_REACH),
anyFloat(), anyFloat(), eq(null));
mDozeSensors.requestTemporaryDisable();
reset(mCallback);
mWakeLockScreenListener.onSensorChanged(mock(SensorManagerPlugin.SensorEvent.class));
mTestableLooper.processAllMessages();
verify(mCallback, never()).onSensorPulse(eq(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN),
verify(mCallback, never()).onSensorPulse(eq(DozeLog.PULSE_REASON_SENSOR_WAKE_REACH),
anyFloat(), anyFloat(), eq(null));
}
@@ -269,15 +270,80 @@ public class DozeSensorsTest extends SysuiTestCase {
}
@Test
public void testPostureOpen_registersCorrectTapGesture() {
// GIVEN device posture open
mDevicePosture = DevicePostureController.DEVICE_POSTURE_OPENED;
public void testPostureStartStateClosed_registersCorrectSensor() throws Exception {
// GIVEN doze sensor that supports postures
Sensor closedSensor = createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
Sensor openedSensor = createSensor(Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_LIGHT);
TriggerSensor triggerSensor = mDozeSensors.createDozeSensor(
new Sensor[] {
null /* unknown */,
closedSensor,
null /* half-opened */,
openedSensor},
DevicePostureController.DEVICE_POSTURE_CLOSED);
// WHEN DozeSensors are initialized
new TestableDozeSensors();
// WHEN trigger sensor requests listening
triggerSensor.setListening(true);
// THEN we use the posture to determine which tap sensor to use
verify(mAmbientDisplayConfiguration).tapSensorType(eq(mDevicePosture));
// THEN the correct sensor is registered
verify(mSensorManager).requestTriggerSensor(eq(triggerSensor), eq(closedSensor));
verify(mSensorManager, never()).requestTriggerSensor(eq(triggerSensor), eq(openedSensor));
}
@Test
public void testPostureChange_registersCorrectSensor() throws Exception {
// GIVEN doze sensor that supports postures
Sensor closedSensor = createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
Sensor openedSensor = createSensor(Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_LIGHT);
TriggerSensor triggerSensor = mDozeSensors.createDozeSensor(
new Sensor[] {
null /* unknown */,
closedSensor,
null /* half-opened */,
openedSensor},
DevicePostureController.DEVICE_POSTURE_CLOSED);
// GIVEN sensor is listening
when(mSensorManager.requestTriggerSensor(any(), any())).thenReturn(true);
triggerSensor.setListening(true);
reset(mSensorManager);
assertTrue(triggerSensor.mRegistered);
// WHEN posture changes
boolean sensorChanged =
triggerSensor.setPosture(DevicePostureController.DEVICE_POSTURE_OPENED);
// THEN the correct sensor is registered
assertTrue(sensorChanged);
verify(mSensorManager).requestTriggerSensor(eq(triggerSensor), eq(openedSensor));
verify(mSensorManager, never()).requestTriggerSensor(eq(triggerSensor), eq(closedSensor));
}
@Test
public void testPostureChange_noSensorChange() throws Exception {
// GIVEN doze sensor that supports postures
Sensor closedSensor = createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
Sensor openedSensor = createSensor(Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_LIGHT);
TriggerSensor triggerSensor = mDozeSensors.createDozeSensor(
new Sensor[] {
null /* unknown */,
closedSensor,
openedSensor /* half-opened uses the same sensor as opened*/,
openedSensor},
DevicePostureController.DEVICE_POSTURE_HALF_OPENED);
// GIVEN sensor is listening
when(mSensorManager.requestTriggerSensor(any(), any())).thenReturn(true);
triggerSensor.setListening(true);
reset(mSensorManager);
// WHEN posture changes
boolean sensorChanged =
triggerSensor.setPosture(DevicePostureController.DEVICE_POSTURE_OPENED);
// THEN no change in sensor
assertFalse(sensorChanged);
verify(mSensorManager, never()).requestTriggerSensor(eq(triggerSensor), any());
}
@Test
@@ -311,13 +377,12 @@ public class DozeSensorsTest extends SysuiTestCase {
private class TestableDozeSensors extends DozeSensors {
TestableDozeSensors() {
super(getContext(), mSensorManager, mDozeParameters,
mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog,
mProximitySensor, mFakeSettings, mAuthController,
mDevicePosture);
for (TriggerSensor sensor : mSensors) {
mDevicePostureController);
for (TriggerSensor sensor : mTriggerSensors) {
if (sensor instanceof PluginSensor
&& ((PluginSensor) sensor).mPluginSensor.getType()
== TYPE_WAKE_LOCK_SCREEN) {
@@ -326,7 +391,7 @@ public class DozeSensorsTest extends SysuiTestCase {
mSensorTap = sensor;
}
}
mSensors = new TriggerSensor[] {mTriggerSensor, mSensorTap};
mTriggerSensors = new TriggerSensor[] {mTriggerSensor, mSensorTap};
}
public TriggerSensor createDozeSensor(Sensor sensor, boolean settingEnabled,
@@ -337,8 +402,25 @@ public class DozeSensorsTest extends SysuiTestCase {
/* configured */ true,
/* pulseReason*/ 0,
/* reportsTouchCoordinate*/ false,
requiresTouchScreen,
mDozeLog);
/* requiresTouchscreen */ false,
/* ignoresSetting */ false,
requiresTouchScreen);
}
/**
* create a doze sensor that supports postures and is enabled
*/
public TriggerSensor createDozeSensor(Sensor[] sensors, int posture) {
return new TriggerSensor(/* sensor */ sensors,
/* setting name */ "test_setting",
/* settingDefault */ true,
/* configured */ true,
/* pulseReason*/ 0,
/* reportsTouchCoordinate*/ false,
/* requiresTouchscreen */ false,
/* ignoresSetting */ true,
/* requiresProx */false,
posture);
}
}

View File

@@ -204,7 +204,7 @@ public class DozeTriggersTest extends SysuiTestCase {
public void testProximitySensorNotAvailablel() {
mProximitySensor.setSensorAvailable(false);
mTriggers.onSensor(DozeLog.PULSE_REASON_SENSOR_LONG_PRESS, 100, 100, null);
mTriggers.onSensor(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN, 100, 100,
mTriggers.onSensor(DozeLog.PULSE_REASON_SENSOR_WAKE_REACH, 100, 100,
new float[]{1});
mTriggers.onSensor(DozeLog.REASON_SENSOR_TAP, 100, 100, null);
}

View File

@@ -164,7 +164,7 @@ public class DozeServiceHostTest extends SysuiTestCase {
@Test
public void testPulseWhileDozing_notifyAuthInterrupt() {
HashSet<Integer> reasonsWantingAuth = new HashSet<>(
Collections.singletonList(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN));
Collections.singletonList(DozeLog.PULSE_REASON_SENSOR_WAKE_REACH));
HashSet<Integer> reasonsSkippingAuth = new HashSet<>(
Arrays.asList(DozeLog.PULSE_REASON_INTENT,
DozeLog.PULSE_REASON_NOTIFICATION,
@@ -173,7 +173,7 @@ public class DozeServiceHostTest extends SysuiTestCase {
DozeLog.REASON_SENSOR_DOUBLE_TAP,
DozeLog.PULSE_REASON_SENSOR_LONG_PRESS,
DozeLog.PULSE_REASON_DOCKING,
DozeLog.REASON_SENSOR_WAKE_UP,
DozeLog.REASON_SENSOR_WAKE_UP_PRESENCE,
DozeLog.REASON_SENSOR_QUICK_PICKUP,
DozeLog.REASON_SENSOR_TAP));
HashSet<Integer> reasonsThatDontPulse = new HashSet<>(

View File

@@ -55,6 +55,7 @@ public class FakeSensorManager extends SensorManager {
private final FakeProximitySensor mFakeProximitySensor;
private final FakeGenericSensor mFakeLightSensor;
private final FakeGenericSensor mFakeLightSensor2;
private final FakeGenericSensor mFakeTapSensor;
private final FakeGenericSensor[] mSensors;
@@ -70,7 +71,8 @@ public class FakeSensorManager extends SensorManager {
mSensors = new FakeGenericSensor[]{
mFakeProximitySensor = new FakeProximitySensor(proxSensor),
mFakeLightSensor = new FakeGenericSensor(createSensor(Sensor.TYPE_LIGHT, null)),
mFakeTapSensor = new FakeGenericSensor(createSensor(99, TAP_SENSOR_TYPE))
mFakeTapSensor = new FakeGenericSensor(createSensor(99, TAP_SENSOR_TYPE)),
mFakeLightSensor2 = new FakeGenericSensor(createSensor(Sensor.TYPE_LIGHT, null))
};
}
@@ -82,6 +84,10 @@ public class FakeSensorManager extends SensorManager {
return mFakeLightSensor;
}
public FakeGenericSensor getFakeLightSensor2() {
return mFakeLightSensor2;
}
public FakeGenericSensor getFakeTapSensor() {
return mFakeTapSensor;
}