Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bcc2d04d authored by Vaibhav Devmurari's avatar Vaibhav Devmurari Committed by Android (Google) Code Review
Browse files

Merge "Add UObserver on creation of keyboard backlight sysfs nodes" into udc-dev

parents b534a8d4 11c9a2b8
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -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);
+9 −0
Original line number Diff line number Diff line
@@ -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);
    }
}
+9 −0
Original line number Diff line number Diff line
@@ -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},
+64 −0
Original line number Diff line number Diff line
@@ -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,