Merge "Add inactivity timer to turn off keyboard backlight"
This commit is contained in:
committed by
Android (Google) Code Review
commit
686cd7cdd4
@@ -213,4 +213,10 @@ public abstract class InputManagerInternal {
|
||||
* @param enabled When true, stylus buttons will not be reported through motion events.
|
||||
*/
|
||||
public abstract void setStylusButtonMotionEventsEnabled(boolean enabled);
|
||||
|
||||
/**
|
||||
* Notify whether any user activity occurred. This includes any input activity on any
|
||||
* display, external peripherals, fingerprint sensor, etc.
|
||||
*/
|
||||
public abstract void notifyUserActivity();
|
||||
}
|
||||
|
||||
@@ -3271,6 +3271,7 @@ public class InputManagerService extends IInputManager.Stub
|
||||
public void setInteractive(boolean interactive) {
|
||||
mNative.setInteractive(interactive);
|
||||
mBatteryController.onInteractiveChanged(interactive);
|
||||
mKeyboardBacklightController.onInteractiveChanged(interactive);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3357,6 +3358,11 @@ public class InputManagerService extends IInputManager.Stub
|
||||
mKeyboardLayoutManager.onInputMethodSubtypeChanged(userId, subtypeHandle, subtype);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyUserActivity() {
|
||||
mKeyboardBacklightController.notifyUserActivity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementKeyboardBacklight(int deviceId) {
|
||||
mKeyboardBacklightController.incrementKeyboardBacklight(deviceId);
|
||||
@@ -3489,6 +3495,8 @@ public class InputManagerService extends IInputManager.Stub
|
||||
default void decrementKeyboardBacklight(int deviceId) {}
|
||||
default void registerKeyboardBacklightListener(IKeyboardBacklightListener l, int pid) {}
|
||||
default void unregisterKeyboardBacklightListener(IKeyboardBacklightListener l, int pid) {}
|
||||
default void onInteractiveChanged(boolean isInteractive) {}
|
||||
default void notifyUserActivity() {}
|
||||
default void systemRunning() {}
|
||||
default void dump(PrintWriter pw) {}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.server.input;
|
||||
|
||||
import android.annotation.BinderThread;
|
||||
import android.annotation.ColorInt;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.hardware.input.IKeyboardBacklightListener;
|
||||
@@ -29,6 +28,7 @@ import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.util.IndentingPrintWriter;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
@@ -39,9 +39,10 @@ import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* A thread-safe component of {@link InputManagerService} responsible for managing the keyboard
|
||||
@@ -59,12 +60,20 @@ final class KeyboardBacklightController implements
|
||||
private enum Direction {
|
||||
DIRECTION_UP, DIRECTION_DOWN
|
||||
}
|
||||
private static final int MSG_INCREMENT_KEYBOARD_BACKLIGHT = 1;
|
||||
private static final int MSG_DECREMENT_KEYBOARD_BACKLIGHT = 2;
|
||||
private static final int MSG_UPDATE_EXISTING_DEVICES = 1;
|
||||
private static final int MSG_INCREMENT_KEYBOARD_BACKLIGHT = 2;
|
||||
private static final int MSG_DECREMENT_KEYBOARD_BACKLIGHT = 3;
|
||||
private static final int MSG_NOTIFY_USER_ACTIVITY = 4;
|
||||
private static final int MSG_NOTIFY_USER_INACTIVITY = 5;
|
||||
private static final int MSG_INTERACTIVE_STATE_CHANGED = 6;
|
||||
private static final int MAX_BRIGHTNESS = 255;
|
||||
private static final int NUM_BRIGHTNESS_CHANGE_STEPS = 10;
|
||||
|
||||
@VisibleForTesting
|
||||
static final TreeSet<Integer> BRIGHTNESS_LEVELS = new TreeSet<>();
|
||||
static final long USER_INACTIVITY_THRESHOLD_MILLIS = Duration.ofSeconds(30).toMillis();
|
||||
|
||||
@VisibleForTesting
|
||||
static final int[] BRIGHTNESS_VALUE_FOR_LEVEL = new int[NUM_BRIGHTNESS_CHANGE_STEPS + 1];
|
||||
|
||||
private final Context mContext;
|
||||
private final NativeInputManagerService mNative;
|
||||
@@ -72,7 +81,12 @@ final class KeyboardBacklightController implements
|
||||
@GuardedBy("mDataStore")
|
||||
private final PersistentDataStore mDataStore;
|
||||
private final Handler mHandler;
|
||||
private final SparseArray<Light> mKeyboardBacklights = new SparseArray<>();
|
||||
// Always access on handler thread or need to lock this for synchronization.
|
||||
private final SparseArray<KeyboardBacklightState> mKeyboardBacklights = new SparseArray<>(1);
|
||||
// Maintains state if all backlights should be on or turned off
|
||||
private boolean mIsBacklightOn = false;
|
||||
// Maintains state if currently the device is interactive or not
|
||||
private boolean mIsInteractive = true;
|
||||
|
||||
// List of currently registered keyboard backlight listeners
|
||||
@GuardedBy("mKeyboardBacklightListenerRecords")
|
||||
@@ -84,8 +98,8 @@ final class KeyboardBacklightController implements
|
||||
// device brightness range to [0-255]
|
||||
// Levels are: 0, 25, 51, ..., 255
|
||||
for (int i = 0; i <= NUM_BRIGHTNESS_CHANGE_STEPS; i++) {
|
||||
BRIGHTNESS_LEVELS.add(
|
||||
(int) Math.floor(((float) i * MAX_BRIGHTNESS) / NUM_BRIGHTNESS_CHANGE_STEPS));
|
||||
BRIGHTNESS_VALUE_FOR_LEVEL[i] = (int) Math.floor(
|
||||
((float) i * MAX_BRIGHTNESS) / NUM_BRIGHTNESS_CHANGE_STEPS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,10 +116,10 @@ final class KeyboardBacklightController implements
|
||||
InputManager inputManager = Objects.requireNonNull(
|
||||
mContext.getSystemService(InputManager.class));
|
||||
inputManager.registerInputDeviceListener(this, mHandler);
|
||||
// Circle through all the already added input devices
|
||||
for (int deviceId : inputManager.getInputDeviceIds()) {
|
||||
onInputDeviceAdded(deviceId);
|
||||
}
|
||||
|
||||
Message msg = Message.obtain(mHandler, MSG_UPDATE_EXISTING_DEVICES,
|
||||
inputManager.getInputDeviceIds());
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -120,37 +134,41 @@ final class KeyboardBacklightController implements
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyUserActivity() {
|
||||
Message msg = Message.obtain(mHandler, MSG_NOTIFY_USER_ACTIVITY);
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInteractiveChanged(boolean isInteractive) {
|
||||
Message msg = Message.obtain(mHandler, MSG_INTERACTIVE_STATE_CHANGED, isInteractive);
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void updateKeyboardBacklight(int deviceId, Direction direction) {
|
||||
InputDevice inputDevice = getInputDevice(deviceId);
|
||||
Light keyboardBacklight = mKeyboardBacklights.get(deviceId);
|
||||
if (inputDevice == null || keyboardBacklight == null) {
|
||||
KeyboardBacklightState state = mKeyboardBacklights.get(deviceId);
|
||||
if (inputDevice == null || state == null) {
|
||||
return;
|
||||
}
|
||||
Light keyboardBacklight = state.mLight;
|
||||
// Follow preset levels of brightness defined in BRIGHTNESS_LEVELS
|
||||
int currBrightness = BRIGHTNESS_LEVELS.floor(Color.alpha(
|
||||
mNative.getLightColor(deviceId, keyboardBacklight.getId())));
|
||||
int newBrightness;
|
||||
final int currBrightnessLevel = state.mBrightnessLevel;
|
||||
final int newBrightnessLevel;
|
||||
if (direction == Direction.DIRECTION_UP) {
|
||||
newBrightness = currBrightness != MAX_BRIGHTNESS ? BRIGHTNESS_LEVELS.higher(
|
||||
currBrightness) : currBrightness;
|
||||
newBrightnessLevel = Math.min(currBrightnessLevel + 1, NUM_BRIGHTNESS_CHANGE_STEPS);
|
||||
} else {
|
||||
newBrightness = currBrightness != 0 ? BRIGHTNESS_LEVELS.lower(currBrightness)
|
||||
: currBrightness;
|
||||
newBrightnessLevel = Math.max(currBrightnessLevel - 1, 0);
|
||||
}
|
||||
@ColorInt int newColor = Color.argb(newBrightness, 0, 0, 0);
|
||||
mNative.setLightColor(deviceId, keyboardBacklight.getId(), newColor);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Changing brightness from " + currBrightness + " to " + newBrightness);
|
||||
}
|
||||
|
||||
notifyKeyboardBacklightChanged(deviceId, BRIGHTNESS_LEVELS.headSet(newBrightness).size(),
|
||||
true/* isTriggeredByKeyPress */);
|
||||
updateBacklightState(deviceId, keyboardBacklight, newBrightnessLevel,
|
||||
true /* isTriggeredByKeyPress */);
|
||||
|
||||
synchronized (mDataStore) {
|
||||
try {
|
||||
mDataStore.setKeyboardBacklightBrightness(inputDevice.getDescriptor(),
|
||||
keyboardBacklight.getId(),
|
||||
newBrightness);
|
||||
BRIGHTNESS_VALUE_FOR_LEVEL[newBrightnessLevel]);
|
||||
} finally {
|
||||
mDataStore.saveIfNeeded();
|
||||
}
|
||||
@@ -163,23 +181,83 @@ final class KeyboardBacklightController implements
|
||||
brightness = mDataStore.getKeyboardBacklightBrightness(
|
||||
inputDevice.getDescriptor(), keyboardBacklight.getId());
|
||||
}
|
||||
if (!brightness.isEmpty()) {
|
||||
mNative.setLightColor(inputDevice.getId(), keyboardBacklight.getId(),
|
||||
Color.argb(brightness.getAsInt(), 0, 0, 0));
|
||||
if (brightness.isPresent()) {
|
||||
int brightnessValue = Math.max(0, Math.min(MAX_BRIGHTNESS, brightness.getAsInt()));
|
||||
int brightnessLevel = Arrays.binarySearch(BRIGHTNESS_VALUE_FOR_LEVEL, brightnessValue);
|
||||
updateBacklightState(inputDevice.getId(), keyboardBacklight, brightnessLevel,
|
||||
false /* isTriggeredByKeyPress */);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Restoring brightness level " + brightness.getAsInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleUserActivity() {
|
||||
// Ignore user activity if device is not interactive. When device becomes interactive, we
|
||||
// will send another user activity to turn backlight on.
|
||||
if (!mIsInteractive) {
|
||||
return;
|
||||
}
|
||||
if (!mIsBacklightOn) {
|
||||
mIsBacklightOn = true;
|
||||
for (int i = 0; i < mKeyboardBacklights.size(); i++) {
|
||||
int deviceId = mKeyboardBacklights.keyAt(i);
|
||||
KeyboardBacklightState state = mKeyboardBacklights.valueAt(i);
|
||||
updateBacklightState(deviceId, state.mLight, state.mBrightnessLevel,
|
||||
false /* isTriggeredByKeyPress */);
|
||||
}
|
||||
}
|
||||
mHandler.removeMessages(MSG_NOTIFY_USER_INACTIVITY);
|
||||
mHandler.sendEmptyMessageAtTime(MSG_NOTIFY_USER_INACTIVITY,
|
||||
SystemClock.uptimeMillis() + USER_INACTIVITY_THRESHOLD_MILLIS);
|
||||
}
|
||||
|
||||
private void handleUserInactivity() {
|
||||
if (mIsBacklightOn) {
|
||||
mIsBacklightOn = false;
|
||||
for (int i = 0; i < mKeyboardBacklights.size(); i++) {
|
||||
int deviceId = mKeyboardBacklights.keyAt(i);
|
||||
KeyboardBacklightState state = mKeyboardBacklights.valueAt(i);
|
||||
updateBacklightState(deviceId, state.mLight, state.mBrightnessLevel,
|
||||
false /* isTriggeredByKeyPress */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void handleInteractiveStateChange(boolean isInteractive) {
|
||||
// Interactive state changes should force the keyboard to turn on/off irrespective of
|
||||
// whether time out occurred or not.
|
||||
mIsInteractive = isInteractive;
|
||||
if (isInteractive) {
|
||||
handleUserActivity();
|
||||
} else {
|
||||
handleUserInactivity();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_UPDATE_EXISTING_DEVICES:
|
||||
for (int deviceId : (int[]) msg.obj) {
|
||||
onInputDeviceAdded(deviceId);
|
||||
}
|
||||
return true;
|
||||
case MSG_INCREMENT_KEYBOARD_BACKLIGHT:
|
||||
updateKeyboardBacklight((int) msg.obj, Direction.DIRECTION_UP);
|
||||
return true;
|
||||
case MSG_DECREMENT_KEYBOARD_BACKLIGHT:
|
||||
updateKeyboardBacklight((int) msg.obj, Direction.DIRECTION_DOWN);
|
||||
return true;
|
||||
case MSG_NOTIFY_USER_ACTIVITY:
|
||||
handleUserActivity();
|
||||
return true;
|
||||
case MSG_NOTIFY_USER_INACTIVITY:
|
||||
handleUserInactivity();
|
||||
return true;
|
||||
case MSG_INTERACTIVE_STATE_CHANGED:
|
||||
handleInteractiveStateChange((boolean) msg.obj);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -208,12 +286,12 @@ final class KeyboardBacklightController implements
|
||||
mKeyboardBacklights.remove(deviceId);
|
||||
return;
|
||||
}
|
||||
final Light oldBacklight = mKeyboardBacklights.get(deviceId);
|
||||
if (oldBacklight != null && oldBacklight.getId() == keyboardBacklight.getId()) {
|
||||
KeyboardBacklightState state = mKeyboardBacklights.get(deviceId);
|
||||
if (state != null && state.mLight.getId() == keyboardBacklight.getId()) {
|
||||
return;
|
||||
}
|
||||
// The keyboard backlight was added or changed.
|
||||
mKeyboardBacklights.put(deviceId, keyboardBacklight);
|
||||
mKeyboardBacklights.put(deviceId, new KeyboardBacklightState(keyboardBacklight));
|
||||
restoreBacklightBrightness(inputDevice, keyboardBacklight);
|
||||
}
|
||||
|
||||
@@ -275,13 +353,29 @@ final class KeyboardBacklightController implements
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyKeyboardBacklightChanged(int deviceId, int currentBacklightLevel,
|
||||
private void updateBacklightState(int deviceId, Light light, int brightnessLevel,
|
||||
boolean isTriggeredByKeyPress) {
|
||||
KeyboardBacklightState state = mKeyboardBacklights.get(deviceId);
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mNative.setLightColor(deviceId, light.getId(),
|
||||
mIsBacklightOn ? Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[brightnessLevel], 0, 0, 0)
|
||||
: 0);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Changing state from " + state.mBrightnessLevel + " to " + brightnessLevel
|
||||
+ "(isBacklightOn = " + mIsBacklightOn + ")");
|
||||
}
|
||||
state.mBrightnessLevel = brightnessLevel;
|
||||
|
||||
synchronized (mKeyboardBacklightListenerRecords) {
|
||||
for (int i = 0; i < mKeyboardBacklightListenerRecords.size(); i++) {
|
||||
IKeyboardBacklightState callbackState = new IKeyboardBacklightState();
|
||||
callbackState.brightnessLevel = brightnessLevel;
|
||||
callbackState.maxBrightnessLevel = NUM_BRIGHTNESS_CHANGE_STEPS;
|
||||
mKeyboardBacklightListenerRecords.valueAt(i).notifyKeyboardBacklightChanged(
|
||||
deviceId, new KeyboardBacklightState(currentBacklightLevel),
|
||||
isTriggeredByKeyPress);
|
||||
deviceId, callbackState, isTriggeredByKeyPress);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -295,11 +389,14 @@ final class KeyboardBacklightController implements
|
||||
@Override
|
||||
public void dump(PrintWriter pw) {
|
||||
IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
|
||||
ipw.println(TAG + ": " + mKeyboardBacklights.size() + " keyboard backlights");
|
||||
ipw.println(
|
||||
TAG + ": " + mKeyboardBacklights.size() + " keyboard backlights, isBacklightOn = "
|
||||
+ mIsBacklightOn);
|
||||
|
||||
ipw.increaseIndent();
|
||||
for (int i = 0; i < mKeyboardBacklights.size(); i++) {
|
||||
Light light = mKeyboardBacklights.get(i);
|
||||
ipw.println(i + ": { id: " + light.getId() + ", name: " + light.getName() + " }");
|
||||
KeyboardBacklightState state = mKeyboardBacklights.valueAt(i);
|
||||
ipw.println(i + ": " + state.toString());
|
||||
}
|
||||
ipw.decreaseIndent();
|
||||
}
|
||||
@@ -334,17 +431,18 @@ final class KeyboardBacklightController implements
|
||||
}
|
||||
}
|
||||
|
||||
private static class KeyboardBacklightState extends IKeyboardBacklightState {
|
||||
private static class KeyboardBacklightState {
|
||||
private final Light mLight;
|
||||
private int mBrightnessLevel;
|
||||
|
||||
KeyboardBacklightState(int brightnessLevel) {
|
||||
this.brightnessLevel = brightnessLevel;
|
||||
this.maxBrightnessLevel = NUM_BRIGHTNESS_CHANGE_STEPS;
|
||||
KeyboardBacklightState(Light light) {
|
||||
mLight = light;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KeyboardBacklightState{brightnessLevel=" + brightnessLevel
|
||||
+ ", maxBrightnessLevel=" + maxBrightnessLevel
|
||||
return "KeyboardBacklightState{Light=" + mLight.getId()
|
||||
+ ", BrightnessLevel=" + mBrightnessLevel
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,6 +737,7 @@ public class Notifier {
|
||||
}
|
||||
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
|
||||
tm.notifyUserActivity();
|
||||
mInputManagerInternal.notifyUserActivity();
|
||||
mPolicy.userActivity(displayGroupId, event);
|
||||
mFaceDownDetector.userActivity(event);
|
||||
mScreenUndimDetector.userActivity(displayGroupId);
|
||||
|
||||
@@ -28,7 +28,8 @@ import android.os.test.TestLooper
|
||||
import android.platform.test.annotations.Presubmit
|
||||
import android.view.InputDevice
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import com.android.server.input.KeyboardBacklightController.BRIGHTNESS_LEVELS
|
||||
import com.android.server.input.KeyboardBacklightController.BRIGHTNESS_VALUE_FOR_LEVEL
|
||||
import com.android.server.input.KeyboardBacklightController.USER_INACTIVITY_THRESHOLD_MILLIS
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotNull
|
||||
@@ -78,6 +79,7 @@ class KeyboardBacklightControllerTests {
|
||||
const val DEVICE_ID = 1
|
||||
const val LIGHT_ID = 2
|
||||
const val SECOND_LIGHT_ID = 3
|
||||
const val MAX_BRIGHTNESS = 255
|
||||
}
|
||||
|
||||
@get:Rule
|
||||
@@ -118,10 +120,6 @@ class KeyboardBacklightControllerTests {
|
||||
val args = it.arguments
|
||||
lightColorMap.put(args[1] as Int, args[2] as Int)
|
||||
}
|
||||
`when`(native.getLightColor(anyInt(), anyInt())).then {
|
||||
val args = it.arguments
|
||||
lightColorMap.getOrDefault(args[1] as Int, -1)
|
||||
}
|
||||
lightColorMap.clear()
|
||||
}
|
||||
|
||||
@@ -137,21 +135,17 @@ class KeyboardBacklightControllerTests {
|
||||
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
|
||||
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
|
||||
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
|
||||
// Initially backlight is at min
|
||||
lightColorMap[LIGHT_ID] = Color.argb(BRIGHTNESS_LEVELS.first(), 0, 0, 0)
|
||||
|
||||
val brightnessLevelsArray = BRIGHTNESS_LEVELS.toTypedArray()
|
||||
for (level in 1 until brightnessLevelsArray.size) {
|
||||
keyboardBacklightController.incrementKeyboardBacklight(DEVICE_ID)
|
||||
testLooper.dispatchNext()
|
||||
for (level in 1 until BRIGHTNESS_VALUE_FOR_LEVEL.size) {
|
||||
incrementKeyboardBacklight(DEVICE_ID)
|
||||
assertEquals(
|
||||
"Light value for level $level mismatched",
|
||||
Color.argb(brightnessLevelsArray[level], 0, 0, 0),
|
||||
Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[level], 0, 0, 0),
|
||||
lightColorMap[LIGHT_ID]
|
||||
)
|
||||
assertEquals(
|
||||
"Light value for level $level must be correctly stored in the datastore",
|
||||
brightnessLevelsArray[level],
|
||||
BRIGHTNESS_VALUE_FOR_LEVEL[level],
|
||||
dataStore.getKeyboardBacklightBrightness(
|
||||
keyboardWithBacklight.descriptor,
|
||||
LIGHT_ID
|
||||
@@ -159,72 +153,49 @@ class KeyboardBacklightControllerTests {
|
||||
)
|
||||
}
|
||||
|
||||
for (level in brightnessLevelsArray.size - 2 downTo 0) {
|
||||
keyboardBacklightController.decrementKeyboardBacklight(DEVICE_ID)
|
||||
testLooper.dispatchNext()
|
||||
assertEquals(
|
||||
"Light value for level $level mismatched",
|
||||
Color.argb(brightnessLevelsArray[level], 0, 0, 0),
|
||||
lightColorMap[LIGHT_ID]
|
||||
)
|
||||
assertEquals(
|
||||
"Light value for level $level must be correctly stored in the datastore",
|
||||
brightnessLevelsArray[level],
|
||||
dataStore.getKeyboardBacklightBrightness(
|
||||
keyboardWithBacklight.descriptor,
|
||||
LIGHT_ID
|
||||
).asInt
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testKeyboardBacklightIncrementAboveMaxLevel() {
|
||||
val keyboardWithBacklight = createKeyboard(DEVICE_ID)
|
||||
val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
|
||||
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
|
||||
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
|
||||
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
|
||||
// Initially backlight is at max
|
||||
lightColorMap[LIGHT_ID] = Color.argb(BRIGHTNESS_LEVELS.last(), 0, 0, 0)
|
||||
|
||||
keyboardBacklightController.incrementKeyboardBacklight(DEVICE_ID)
|
||||
testLooper.dispatchNext()
|
||||
// Increment above max level
|
||||
incrementKeyboardBacklight(DEVICE_ID)
|
||||
assertEquals(
|
||||
"Light value for max level mismatched",
|
||||
Color.argb(BRIGHTNESS_LEVELS.last(), 0, 0, 0),
|
||||
Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
|
||||
lightColorMap[LIGHT_ID]
|
||||
)
|
||||
assertEquals(
|
||||
"Light value for max level must be correctly stored in the datastore",
|
||||
BRIGHTNESS_LEVELS.last(),
|
||||
MAX_BRIGHTNESS,
|
||||
dataStore.getKeyboardBacklightBrightness(
|
||||
keyboardWithBacklight.descriptor,
|
||||
LIGHT_ID
|
||||
).asInt
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testKeyboardBacklightDecrementBelowMin() {
|
||||
val keyboardWithBacklight = createKeyboard(DEVICE_ID)
|
||||
val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
|
||||
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
|
||||
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
|
||||
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
|
||||
// Initially backlight is at min
|
||||
lightColorMap[LIGHT_ID] = Color.argb(BRIGHTNESS_LEVELS.first(), 0, 0, 0)
|
||||
for (level in BRIGHTNESS_VALUE_FOR_LEVEL.size - 2 downTo 0) {
|
||||
decrementKeyboardBacklight(DEVICE_ID)
|
||||
assertEquals(
|
||||
"Light value for level $level mismatched",
|
||||
Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[level], 0, 0, 0),
|
||||
lightColorMap[LIGHT_ID]
|
||||
)
|
||||
assertEquals(
|
||||
"Light value for level $level must be correctly stored in the datastore",
|
||||
BRIGHTNESS_VALUE_FOR_LEVEL[level],
|
||||
dataStore.getKeyboardBacklightBrightness(
|
||||
keyboardWithBacklight.descriptor,
|
||||
LIGHT_ID
|
||||
).asInt
|
||||
)
|
||||
}
|
||||
|
||||
keyboardBacklightController.decrementKeyboardBacklight(DEVICE_ID)
|
||||
testLooper.dispatchNext()
|
||||
// Decrement below min level
|
||||
decrementKeyboardBacklight(DEVICE_ID)
|
||||
assertEquals(
|
||||
"Light value for min level mismatched",
|
||||
Color.argb(BRIGHTNESS_LEVELS.first(), 0, 0, 0),
|
||||
Color.argb(0, 0, 0, 0),
|
||||
lightColorMap[LIGHT_ID]
|
||||
)
|
||||
assertEquals(
|
||||
"Light value for min level must be correctly stored in the datastore",
|
||||
BRIGHTNESS_LEVELS.first(),
|
||||
0,
|
||||
dataStore.getKeyboardBacklightBrightness(
|
||||
keyboardWithBacklight.descriptor,
|
||||
LIGHT_ID
|
||||
@@ -240,7 +211,7 @@ class KeyboardBacklightControllerTests {
|
||||
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardInputLight))
|
||||
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
|
||||
|
||||
keyboardBacklightController.incrementKeyboardBacklight(DEVICE_ID)
|
||||
incrementKeyboardBacklight(DEVICE_ID)
|
||||
assertTrue("Non Keyboard backlights should not change", lightColorMap.isEmpty())
|
||||
}
|
||||
|
||||
@@ -258,8 +229,7 @@ class KeyboardBacklightControllerTests {
|
||||
)
|
||||
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
|
||||
|
||||
keyboardBacklightController.incrementKeyboardBacklight(DEVICE_ID)
|
||||
testLooper.dispatchNext()
|
||||
incrementKeyboardBacklight(DEVICE_ID)
|
||||
assertEquals("Only keyboard backlights should change", 1, lightColorMap.size)
|
||||
assertNotNull("Keyboard backlight should change", lightColorMap[LIGHT_ID])
|
||||
assertNull("Input lights should not change", lightColorMap[SECOND_LIGHT_ID])
|
||||
@@ -275,14 +245,15 @@ class KeyboardBacklightControllerTests {
|
||||
dataStore.setKeyboardBacklightBrightness(
|
||||
keyboardWithBacklight.descriptor,
|
||||
LIGHT_ID,
|
||||
BRIGHTNESS_LEVELS.last()
|
||||
MAX_BRIGHTNESS
|
||||
)
|
||||
lightColorMap.clear()
|
||||
|
||||
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
|
||||
keyboardBacklightController.notifyUserActivity()
|
||||
testLooper.dispatchNext()
|
||||
assertEquals(
|
||||
"Keyboard backlight level should be restored to the level saved in the data store",
|
||||
Color.argb(BRIGHTNESS_LEVELS.last(), 0, 0, 0),
|
||||
Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
|
||||
lightColorMap[LIGHT_ID]
|
||||
)
|
||||
}
|
||||
@@ -295,11 +266,12 @@ class KeyboardBacklightControllerTests {
|
||||
dataStore.setKeyboardBacklightBrightness(
|
||||
keyboardWithBacklight.descriptor,
|
||||
LIGHT_ID,
|
||||
BRIGHTNESS_LEVELS.last()
|
||||
MAX_BRIGHTNESS
|
||||
)
|
||||
lightColorMap.clear()
|
||||
|
||||
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
|
||||
keyboardBacklightController.notifyUserActivity()
|
||||
testLooper.dispatchNext()
|
||||
assertTrue(
|
||||
"Keyboard backlight should not be changed until its added",
|
||||
lightColorMap.isEmpty()
|
||||
@@ -307,22 +279,22 @@ class KeyboardBacklightControllerTests {
|
||||
|
||||
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
|
||||
keyboardBacklightController.onInputDeviceChanged(DEVICE_ID)
|
||||
keyboardBacklightController.notifyUserActivity()
|
||||
testLooper.dispatchNext()
|
||||
assertEquals(
|
||||
"Keyboard backlight level should be restored to the level saved in the data store",
|
||||
Color.argb(BRIGHTNESS_LEVELS.last(), 0, 0, 0),
|
||||
Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
|
||||
lightColorMap[LIGHT_ID]
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testKeyboardBacklightT_registerUnregisterListener() {
|
||||
fun testKeyboardBacklight_registerUnregisterListener() {
|
||||
val keyboardWithBacklight = createKeyboard(DEVICE_ID)
|
||||
val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
|
||||
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
|
||||
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
|
||||
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
|
||||
// Initially backlight is at min
|
||||
lightColorMap[LIGHT_ID] = Color.argb(BRIGHTNESS_LEVELS.first(), 0, 0, 0)
|
||||
|
||||
// Register backlight listener
|
||||
val listener = KeyboardBacklightListener()
|
||||
@@ -343,8 +315,8 @@ class KeyboardBacklightControllerTests {
|
||||
lastBacklightState!!.brightnessLevel
|
||||
)
|
||||
assertEquals(
|
||||
"Backlight state maxBrightnessLevel should be " + (BRIGHTNESS_LEVELS.size - 1),
|
||||
(BRIGHTNESS_LEVELS.size - 1),
|
||||
"Backlight state maxBrightnessLevel should be " + (BRIGHTNESS_VALUE_FOR_LEVEL.size - 1),
|
||||
(BRIGHTNESS_VALUE_FOR_LEVEL.size - 1),
|
||||
lastBacklightState!!.maxBrightnessLevel
|
||||
)
|
||||
assertEquals(
|
||||
@@ -357,12 +329,70 @@ class KeyboardBacklightControllerTests {
|
||||
keyboardBacklightController.unregisterKeyboardBacklightListener(listener, 0)
|
||||
|
||||
lastBacklightState = null
|
||||
keyboardBacklightController.incrementKeyboardBacklight(DEVICE_ID)
|
||||
testLooper.dispatchNext()
|
||||
incrementKeyboardBacklight(DEVICE_ID)
|
||||
|
||||
assertNull("Listener should not receive any updates", lastBacklightState)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testKeyboardBacklight_userActivity() {
|
||||
val keyboardWithBacklight = createKeyboard(DEVICE_ID)
|
||||
val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
|
||||
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
|
||||
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
|
||||
dataStore.setKeyboardBacklightBrightness(
|
||||
keyboardWithBacklight.descriptor,
|
||||
LIGHT_ID,
|
||||
MAX_BRIGHTNESS
|
||||
)
|
||||
|
||||
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
|
||||
keyboardBacklightController.notifyUserActivity()
|
||||
testLooper.dispatchNext()
|
||||
assertEquals(
|
||||
"Keyboard backlight level should be restored to the level saved in the data store",
|
||||
Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
|
||||
lightColorMap[LIGHT_ID]
|
||||
)
|
||||
|
||||
testLooper.moveTimeForward(USER_INACTIVITY_THRESHOLD_MILLIS + 1000)
|
||||
testLooper.dispatchNext()
|
||||
assertEquals(
|
||||
"Keyboard backlight level should be turned off after inactivity",
|
||||
0,
|
||||
lightColorMap[LIGHT_ID]
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testKeyboardBacklight_displayOnOff() {
|
||||
val keyboardWithBacklight = createKeyboard(DEVICE_ID)
|
||||
val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
|
||||
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
|
||||
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
|
||||
dataStore.setKeyboardBacklightBrightness(
|
||||
keyboardWithBacklight.descriptor,
|
||||
LIGHT_ID,
|
||||
MAX_BRIGHTNESS
|
||||
)
|
||||
|
||||
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
|
||||
keyboardBacklightController.handleInteractiveStateChange(true /* isDisplayOn */)
|
||||
assertEquals(
|
||||
"Keyboard backlight level should be restored to the level saved in the data " +
|
||||
"store when display turned on",
|
||||
Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
|
||||
lightColorMap[LIGHT_ID]
|
||||
)
|
||||
|
||||
keyboardBacklightController.handleInteractiveStateChange(false /* isDisplayOn */)
|
||||
assertEquals(
|
||||
"Keyboard backlight level should be turned off after display is turned off",
|
||||
0,
|
||||
lightColorMap[LIGHT_ID]
|
||||
)
|
||||
}
|
||||
|
||||
inner class KeyboardBacklightListener : IKeyboardBacklightListener.Stub() {
|
||||
override fun onBrightnessChanged(
|
||||
deviceId: Int,
|
||||
@@ -378,6 +408,18 @@ class KeyboardBacklightControllerTests {
|
||||
}
|
||||
}
|
||||
|
||||
private fun incrementKeyboardBacklight(deviceId: Int) {
|
||||
keyboardBacklightController.incrementKeyboardBacklight(deviceId)
|
||||
keyboardBacklightController.notifyUserActivity()
|
||||
testLooper.dispatchAll()
|
||||
}
|
||||
|
||||
private fun decrementKeyboardBacklight(deviceId: Int) {
|
||||
keyboardBacklightController.decrementKeyboardBacklight(deviceId)
|
||||
keyboardBacklightController.notifyUserActivity()
|
||||
testLooper.dispatchAll()
|
||||
}
|
||||
|
||||
class KeyboardBacklightState(
|
||||
val deviceId: Int,
|
||||
val brightnessLevel: Int,
|
||||
|
||||
Reference in New Issue
Block a user