oNaiPs / droidVncServer

VNC server for Android devices.
GNU General Public License v3.0
906 stars 480 forks source link

VNC keyboard not removed when server stopped (with solution) #36

Open m-ric opened 12 years ago

m-ric commented 12 years ago

I met an issue on my pandaboard running AOSP-4.0.4. After I started and stopped VNC server, Android virtual keyboard did not prompt anymore, although I had no USB keyboard connected. Before that virtual / physical keyboards toggled dynamically smoothly when USB keyboard was plugged in and out. After some tests, I figured out that droid-VNC-server creates a standard keyboard, and it is recognized as a built-in keyboard by Android. See http://pastebin.com/7NurfTwj.

On this log, I commented USB keyboard plug-in with:

*** plugging keyboard ***

When VNC server is stopped, later in the log, three lines are of interest:

I/EventHub(  153): Removed device: path=/dev/input/event3 name=qwerty id=6 fd=203 classes=0x27
W/EventHub(  153): built-in keyboard device /dev/input/event3 (id=6) is closing! the apps will not like this
W/InputReader(  153): Ignoring spurious device removed event for deviceId 6.

The keyboard created by droid-VNC-server is not removed completely because it is defined as built-in! Android cannot "remove" a so-called built-in device. Then when I enter a keyboard-demanding application, Android virtual keyboard does not pop up because Android believes that a built-in keyboard is already present... Can be annoying on a device without physical keyboard.

So I patched droidvncdaemon/vnc/input.c:

         1, /* Vendor id. */
         1, /* Product id. */
         1 /* Version id. */
     }; 

-    if((inputfd = suinput_open("qwerty", &id)) == -1)
+    if((inputfd = suinput_open("qwerty_vnc", &id)) == -1)
     {
         L("cannot create virtual kbd device.\n");
    sendMsgToGui("~SHOW|Cannot create virtual input device!\n");
         //  exit(EXIT_FAILURE); do not exit, so we still can see the framebuffer
     }

And I created a new .idc file in /system/usr/idc similar to qwerty.idc, only difference is:

keyboard.builtIn = 0
oNaiPs commented 12 years ago

Thanks for you interest and contribution to the project! I'm not sure if it is safe to put a file on /system, wouldnt work if we simply close the virtual device before closing the daemon? I'm not sure if i'm doing it!

Best

m-ric commented 12 years ago

Q: "wouldnt work if we simply close the virtual device before closing the daemon?" A: you are already closing the device: close_app() calls cleanupInput(), which calls suinput_close(inputfd). This part is ok. Problem is that the device is set as built-in, and Android refuses to close built-in devices! sample of frameworks/base/services/input/InputReader.cpp:

void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
    InputDevice* device = NULL;
    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
    if (deviceIndex >= 0) {
        device = mDevices.valueAt(deviceIndex);
        mDevices.removeItemsAt(deviceIndex, 1);
    } else {
        ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
        return;
    }

    if (device->isIgnored()) {
        ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
                device->getId(), device->getName().string());
    } else {
        ALOGI("Device removed: id=%d, name='%s', sources=0x%08x",
                device->getId(), device->getName().string(), device->getSources());
    }

    device->reset(when);
    delete device;
}

Maybe only ICS does that, I don't know. But I don't think there is a safe way to force ICS to close a built-in device. Do you see my point?

A safe solution would be to use a non built-in device for keyboard, thus not using the default qwerty.idc but some other file. Or to force qwerty.idc not to be built-in for the purpose of vnc-server. I don't know how to do this latter...

oNaiPs commented 12 years ago

Thanks for your suggestions... I am as well considering adding support for a second input method, which i think should work in even more devices than uinput brings us (i've heard some comments of not working on some devices)....

That would be to startup the "monkey --port PORT" android cmd that listens on a determined PORT, and injects touch/key events directly on the Java framework... have you acknowledge this already?

best

m-ric commented 12 years ago

I have used the monkey for stress test only, not as a uinput wrapper. Probably worth trying if the execution overhead is acceptable.

oNaiPs commented 12 years ago

I've made some research on this lately. Monkey uses the IWindowManager.aidl Binder interface to inject keys/touch through the WindowManagerService.java. Ideally we should have a AIDL->CPP translator so we could put the daemon injecting keys directly to the service, but we do not have that.

Any thoughs on this? My question would be, is it easier to implement the stubs by hand or adapting the AIDL translator to generate cpp files?

m-ric commented 12 years ago

Sorry for the delay, but to answer your question : I have no idea.

ADTC commented 9 years ago

Facing this problem still on Android 4.4.4 Samsung Galaxy S3 GT-I9305 (a European stock ROM). Is this solution already added in the app? Android still thinks a physical keyboard is present, hence doesn't show virtual keyboard no matter what I try (except restart).

Duplicate issues: #61 #103