When running unity8 on top of mir, the input events generated by autopilot have no effect on the application under test. I've spent the best part of a day debugging this, so what follows is a brain dump of everything we've tried, so others can continue the effort while I sleep.
Basic Notes:
===========
To run the autopilot tests, there are a few things you need to do:
1) Get the test cases. From the host, run 'phablet-click-test-setup'.
2) Switch to running mir: "touch ~phablet/.display-mir && sudo reboot"
3) Install the test dependencies. In this example I'll use the ubuntu ui toolkit test suite:
sudo apt-get install ubuntu-ui-toolkit-autopilot
4) Unlike surface flinger, you *must* have the unity8 shell running when trying to run a test suite. This is becasue without unity8, there's no display server, so you can't launch any applications. This caught me out for a while, because the error message you get isn't particularly intuitive.
5) Now you can run the test. I recommend just running a single test:
cd ~/autopilot
autopilot run -v ubuntuuitoolkit.tests.gallery.test_gallery.GenericTests.test_navigation
The test will fail because the input events never make it through to the application.
and then restart unity8 (so those environment variables are picked up), then re-run the autopilot test, you'll get additional log output from mir in ~/.cache/upstart/unity8.log
If you run those tests again, you'll see two messages like this:
[EE, android-input] [EventHub]could not open /dev/input/event6, Permission denied
[EE, android-input] [EventHub]could not open /dev/input/event7, Permission denied
This is mir finding the new device nodes that autopilot creates, but failing to open them.
I ran unity8 under strace, and the resulting log file is here:
Note that, at this point, you probably want an easier way to reproduce this than running the entire autopilot test. You can simply run this in a shell:
python -c "from time import sleep; from autopilot.input import Touch; t = Touch.create(); sleep(60)"
Debugging Permissions:
=====================
So it looks like a file permissions problem. We've looked at the following:
i) The file permissions in the ubuntu-side:
$ ls -l /dev/input/event*
crw-rw---- 1 root android_input 13, 64 Oct 1 23:37 /dev/input/event0
crw-rw---- 1 root android_input 13, 65 Oct 1 23:37 /dev/input/event1
crw-rw---- 1 root android_input 13, 66 Oct 1 23:37 /dev/input/event2
crw-rw---- 1 root android_input 13, 67 Oct 1 23:37 /dev/input/event3
crw-rw---- 1 root android_input 13, 68 Oct 1 23:37 /dev/input/event4
crw-rw---- 1 root android_input 13, 69 Oct 1 23:37 /dev/input/event5
crw-rw---- 1 root android_input 13, 70 Oct 2 02:36 /dev/input/event6
crw-rw---- 1 root android_input 13, 71 Oct 2 02:36 /dev/input/event7
iii) We've verified that this is not apparmor doing something to us:
$ grep DENIED /var/log/syslog
Other Interesting Things:
=====================
If we create the autopilot touch device before unity8 starts, then mir is able to open the device nodes just fine. This suggests to me that:
- it's not something to do with these devices being uinput, rather than "real" devices.
The code that opens this device is (in lp:mir HEAD)
3rd_party/android-input/android/frameworks/base/services/input/EventHub.cpp line 959 and looks like this:
~~~
int fd = open(devicePath, O_RDWR | O_CLOEXEC);
if(fd < 0) {
ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
return -1;
}
~~~
I wondered if the open mode flags were causing a problem, but a simple program that opens the same device in the same way works perfectly.
Current Suspicions:
=================
The big clue here seems to be that mir can open all devices when it starts, but fails to open devices that are created later. Perhaps:
- mir has fewer priviledges / permissions later, than it does when it starts up?
- perhaps there's a race condition, and both mir *and* something else are trying to access the same device node at the same time, and this is somehow causing problems.
When running unity8 on top of mir, the input events generated by autopilot have no effect on the application under test. I've spent the best part of a day debugging this, so what follows is a brain dump of everything we've tried, so others can continue the effort while I sleep.
Basic Notes:
===========
To run the autopilot tests, there are a few things you need to do:
1) Get the test cases. From the host, run 'phablet- click-test- setup'.
2) Switch to running mir: "touch ~phablet/ .display- mir && sudo reboot"
3) Install the test dependencies. In this example I'll use the ubuntu ui toolkit test suite:
sudo apt-get install ubuntu- ui-toolkit- autopilot
4) Unlike surface flinger, you *must* have the unity8 shell running when trying to run a test suite. This is becasue without unity8, there's no display server, so you can't launch any applications. This caught me out for a while, because the error message you get isn't particularly intuitive.
5) Now you can run the test. I recommend just running a single test:
cd ~/autopilot .tests. gallery. test_gallery. GenericTests. test_navigation
autopilot run -v ubuntuuitoolkit
The test will fail because the input events never make it through to the application.
Debugging mir:
=============
If you export some environment variables...
initctl set-env MIR_SERVER_ INPUT_REPORT= log LEGACY_ INPUT_REPORT= log
initctl set-env MIR_SERVER_
and then restart unity8 (so those environment variables are picked up), then re-run the autopilot test, you'll get additional log output from mir in ~/.cache/ upstart/ unity8. log
If you run those tests again, you'll see two messages like this:
[EE, android-input] [EventHub]could not open /dev/input/event6, Permission denied
[EE, android-input] [EventHub]could not open /dev/input/event7, Permission denied
This is mir finding the new device nodes that autopilot creates, but failing to open them.
I ran unity8 under strace, and the resulting log file is here:
http:// people. canonical. com/~thomir/ strace_ out.gz
It's a large log file, but the relevant sections are:
6214 open("/ dev/input/ event7" , O_RDWR| O_LARGEFILE| O_CLOEXEC <unfinished ...>
6214 <... open resumed> ) = -1 EACCES (Permission denied)
Note that, at this point, you probably want an easier way to reproduce this than running the entire autopilot test. You can simply run this in a shell:
python -c "from time import sleep; from autopilot.input import Touch; t = Touch.create(); sleep(60)"
Debugging Permissions: ======= =======
=======
So it looks like a file permissions problem. We've looked at the following:
i) The file permissions in the ubuntu-side:
$ ls -l /dev/input/event*
crw-rw---- 1 root android_input 13, 64 Oct 1 23:37 /dev/input/event0
crw-rw---- 1 root android_input 13, 65 Oct 1 23:37 /dev/input/event1
crw-rw---- 1 root android_input 13, 66 Oct 1 23:37 /dev/input/event2
crw-rw---- 1 root android_input 13, 67 Oct 1 23:37 /dev/input/event3
crw-rw---- 1 root android_input 13, 68 Oct 1 23:37 /dev/input/event4
crw-rw---- 1 root android_input 13, 69 Oct 1 23:37 /dev/input/event5
crw-rw---- 1 root android_input 13, 70 Oct 2 02:36 /dev/input/event6
crw-rw---- 1 root android_input 13, 71 Oct 2 02:36 /dev/input/event7
ii) The permissions android-side:
$ sudo android-chroot
root@android:/ # ls -l /dev/input/event*
crw-rw---- root input 13, 64 2013-10-01 23:37 event0
crw-rw---- root input 13, 65 2013-10-01 23:37 event1
crw-rw---- root input 13, 66 2013-10-01 23:37 event2
crw-rw---- root input 13, 67 2013-10-01 23:37 event3
crw-rw---- root input 13, 68 2013-10-01 23:37 event4
crw-rw---- root input 13, 69 2013-10-01 23:37 event5
crw-rw---- root input 13, 70 2013-10-02 02:36 event6
crw-rw---- root input 13, 71 2013-10-02 02:36 event7
iii) We've verified that this is not apparmor doing something to us:
$ grep DENIED /var/log/syslog
Other Interesting Things: ======= =======
=======
If we create the autopilot touch device before unity8 starts, then mir is able to open the device nodes just fine. This suggests to me that:
- it's not something to do with these devices being uinput, rather than "real" devices.
The code that opens this device is (in lp:mir HEAD)
3rd_party/ android- input/android/ frameworks/ base/services/ input/EventHub. cpp line 959 and looks like this:
~~~
int fd = open(devicePath, O_RDWR | O_CLOEXEC);
if(fd < 0) {
ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
return -1;
}
~~~
I wondered if the open mode flags were causing a problem, but a simple program that opens the same device in the same way works perfectly.
Current Suspicions:
=================
The big clue here seems to be that mir can open all devices when it starts, but fails to open devices that are created later. Perhaps:
- mir has fewer priviledges / permissions later, than it does when it starts up?
- perhaps there's a race condition, and both mir *and* something else are trying to access the same device node at the same time, and this is somehow causing problems.