Merge "Add UObserver on creation of keyboard backlight sysfs nodes" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
bcc2d04dd7
@@ -29,6 +29,8 @@ import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UEventObserver;
|
||||
import android.text.TextUtils;
|
||||
import android.util.IndentingPrintWriter;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
@@ -69,6 +71,8 @@ final class KeyboardBacklightController implements
|
||||
private static final int MAX_BRIGHTNESS = 255;
|
||||
private static final int NUM_BRIGHTNESS_CHANGE_STEPS = 10;
|
||||
|
||||
private static final String UEVENT_KEYBOARD_BACKLIGHT_TAG = "kbd_backlight";
|
||||
|
||||
@VisibleForTesting
|
||||
static final long USER_INACTIVITY_THRESHOLD_MILLIS = Duration.ofSeconds(30).toMillis();
|
||||
|
||||
@@ -120,6 +124,18 @@ final class KeyboardBacklightController implements
|
||||
Message msg = Message.obtain(mHandler, MSG_UPDATE_EXISTING_DEVICES,
|
||||
inputManager.getInputDeviceIds());
|
||||
mHandler.sendMessage(msg);
|
||||
|
||||
// Observe UEvents for "kbd_backlight" sysfs nodes.
|
||||
// We want to observe creation of such LED nodes since they might be created after device
|
||||
// FD created and InputDevice creation logic doesn't initialize LED nodes which leads to
|
||||
// backlight not working.
|
||||
UEventObserver observer = new UEventObserver() {
|
||||
@Override
|
||||
public void onUEvent(UEvent event) {
|
||||
onKeyboardBacklightUEvent(event);
|
||||
}
|
||||
};
|
||||
observer.startObserving(UEVENT_KEYBOARD_BACKLIGHT_TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -386,6 +402,34 @@ final class KeyboardBacklightController implements
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void onKeyboardBacklightUEvent(UEventObserver.UEvent event) {
|
||||
if ("ADD".equalsIgnoreCase(event.get("ACTION")) && "LEDS".equalsIgnoreCase(
|
||||
event.get("SUBSYSTEM"))) {
|
||||
final String devPath = event.get("DEVPATH");
|
||||
if (isValidBacklightNodePath(devPath)) {
|
||||
mNative.sysfsNodeChanged("/sys" + devPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isValidBacklightNodePath(String devPath) {
|
||||
if (TextUtils.isEmpty(devPath)) {
|
||||
return false;
|
||||
}
|
||||
int index = devPath.lastIndexOf('/');
|
||||
if (index < 0) {
|
||||
return false;
|
||||
}
|
||||
String backlightNode = devPath.substring(index + 1);
|
||||
devPath = devPath.substring(0, index);
|
||||
if (!devPath.endsWith("leds") || !backlightNode.contains("kbd_backlight")) {
|
||||
return false;
|
||||
}
|
||||
index = devPath.lastIndexOf('/');
|
||||
return index >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(PrintWriter pw) {
|
||||
IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
|
||||
|
||||
@@ -237,6 +237,12 @@ interface NativeInputManagerService {
|
||||
/** Set whether showing a pointer icon for styluses is enabled. */
|
||||
void setStylusPointerIconEnabled(boolean enabled);
|
||||
|
||||
/**
|
||||
* Report sysfs node changes. This may result in recreation of the corresponding InputDevice.
|
||||
* The recreated device may contain new associated peripheral devices like Light, Battery, etc.
|
||||
*/
|
||||
void sysfsNodeChanged(String sysfsNodePath);
|
||||
|
||||
/** The native implementation of InputManagerService methods. */
|
||||
class NativeImpl implements NativeInputManagerService {
|
||||
/** Pointer to native input manager service object, used by native code. */
|
||||
@@ -484,5 +490,8 @@ interface NativeInputManagerService {
|
||||
|
||||
@Override
|
||||
public native void setStylusPointerIconEnabled(boolean enabled);
|
||||
|
||||
@Override
|
||||
public native void sysfsNodeChanged(String sysfsNodePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2336,6 +2336,14 @@ static void nativeReloadDeviceAliases(JNIEnv* env, jobject nativeImplObj) {
|
||||
InputReaderConfiguration::CHANGE_DEVICE_ALIAS);
|
||||
}
|
||||
|
||||
static void nativeSysfsNodeChanged(JNIEnv* env, jobject nativeImplObj, jstring path) {
|
||||
ScopedUtfChars sysfsNodePathChars(env, path);
|
||||
const std::string sysfsNodePath = sysfsNodePathChars.c_str();
|
||||
|
||||
NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
|
||||
im->getInputManager()->getReader().sysfsNodeChanged(sysfsNodePath);
|
||||
}
|
||||
|
||||
static std::string dumpInputProperties() {
|
||||
std::string out = "Input properties:\n";
|
||||
const std::string strategy =
|
||||
@@ -2651,6 +2659,7 @@ static const JNINativeMethod gInputManagerMethods[] = {
|
||||
{"getBatteryDevicePath", "(I)Ljava/lang/String;", (void*)nativeGetBatteryDevicePath},
|
||||
{"reloadKeyboardLayouts", "()V", (void*)nativeReloadKeyboardLayouts},
|
||||
{"reloadDeviceAliases", "()V", (void*)nativeReloadDeviceAliases},
|
||||
{"sysfsNodeChanged", "(Ljava/lang/String;)V", (void*)nativeSysfsNodeChanged},
|
||||
{"dump", "()Ljava/lang/String;", (void*)nativeDump},
|
||||
{"monitor", "()V", (void*)nativeMonitor},
|
||||
{"isInputDeviceEnabled", "(I)Z", (void*)nativeIsInputDeviceEnabled},
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.hardware.input.IKeyboardBacklightListener
|
||||
import android.hardware.input.IKeyboardBacklightState
|
||||
import android.hardware.input.InputManager
|
||||
import android.hardware.lights.Light
|
||||
import android.os.UEventObserver
|
||||
import android.os.test.TestLooper
|
||||
import android.platform.test.annotations.Presubmit
|
||||
import android.view.InputDevice
|
||||
@@ -39,6 +40,7 @@ import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.any
|
||||
import org.mockito.Mockito.anyInt
|
||||
import org.mockito.Mockito.eq
|
||||
import org.mockito.Mockito.spy
|
||||
@@ -95,6 +97,7 @@ class KeyboardBacklightControllerTests {
|
||||
private lateinit var testLooper: TestLooper
|
||||
private var lightColorMap: HashMap<Int, Int> = HashMap()
|
||||
private var lastBacklightState: KeyboardBacklightState? = null
|
||||
private var sysfsNodeChanges = 0
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
@@ -121,6 +124,9 @@ class KeyboardBacklightControllerTests {
|
||||
lightColorMap.put(args[1] as Int, args[2] as Int)
|
||||
}
|
||||
lightColorMap.clear()
|
||||
`when`(native.sysfsNodeChanged(any())).then {
|
||||
sysfsNodeChanges++
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -393,6 +399,64 @@ class KeyboardBacklightControllerTests {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testKeyboardBacklightSysfsNodeAdded_AfterInputDeviceAdded() {
|
||||
var counter = sysfsNodeChanges
|
||||
keyboardBacklightController.onKeyboardBacklightUEvent(UEventObserver.UEvent(
|
||||
"ACTION=add\u0000SUBSYSTEM=leds\u0000DEVPATH=/xyz/leds/abc::no_backlight\u0000"
|
||||
))
|
||||
assertEquals(
|
||||
"Should not reload sysfs node if UEvent path doesn't contain kbd_backlight",
|
||||
counter,
|
||||
sysfsNodeChanges
|
||||
)
|
||||
|
||||
keyboardBacklightController.onKeyboardBacklightUEvent(UEventObserver.UEvent(
|
||||
"ACTION=add\u0000SUBSYSTEM=power\u0000DEVPATH=/xyz/leds/abc::kbd_backlight\u0000"
|
||||
))
|
||||
assertEquals(
|
||||
"Should not reload sysfs node if UEvent doesn't belong to subsystem LED",
|
||||
counter,
|
||||
sysfsNodeChanges
|
||||
)
|
||||
|
||||
keyboardBacklightController.onKeyboardBacklightUEvent(UEventObserver.UEvent(
|
||||
"ACTION=remove\u0000SUBSYSTEM=leds\u0000DEVPATH=/xyz/leds/abc::kbd_backlight\u0000"
|
||||
))
|
||||
assertEquals(
|
||||
"Should not reload sysfs node if UEvent doesn't have ACTION(add)",
|
||||
counter,
|
||||
sysfsNodeChanges
|
||||
)
|
||||
|
||||
keyboardBacklightController.onKeyboardBacklightUEvent(UEventObserver.UEvent(
|
||||
"ACTION=add\u0000SUBSYSTEM=leds\u0000DEVPATH=/xyz/pqr/abc::kbd_backlight\u0000"
|
||||
))
|
||||
assertEquals(
|
||||
"Should not reload sysfs node if UEvent path doesn't belong to leds/ directory",
|
||||
counter,
|
||||
sysfsNodeChanges
|
||||
)
|
||||
|
||||
keyboardBacklightController.onKeyboardBacklightUEvent(UEventObserver.UEvent(
|
||||
"ACTION=add\u0000SUBSYSTEM=leds\u0000DEVPATH=/xyz/leds/abc::kbd_backlight\u0000"
|
||||
))
|
||||
assertEquals(
|
||||
"Should reload sysfs node if a valid Keyboard backlight LED UEvent occurs",
|
||||
++counter,
|
||||
sysfsNodeChanges
|
||||
)
|
||||
|
||||
keyboardBacklightController.onKeyboardBacklightUEvent(UEventObserver.UEvent(
|
||||
"ACTION=add\u0000SUBSYSTEM=leds\u0000DEVPATH=/xyz/leds/abc:kbd_backlight:red\u0000"
|
||||
))
|
||||
assertEquals(
|
||||
"Should reload sysfs node if a valid Keyboard backlight LED UEvent occurs",
|
||||
++counter,
|
||||
sysfsNodeChanges
|
||||
)
|
||||
}
|
||||
|
||||
inner class KeyboardBacklightListener : IKeyboardBacklightListener.Stub() {
|
||||
override fun onBrightnessChanged(
|
||||
deviceId: Int,
|
||||
|
||||
Reference in New Issue
Block a user