Solves #381
Solves #169
More or less fixes #156
Fixes #120
This pull request aims to replace existing Intent-based interface for launching commands with AIDL-based API. The API uses Android/Linux ability to pass file descriptors between processes to grant ATE access to /dev/ptmx handle, created by someone else. In effect this means, that another program launches an executable (with it's own permissions), but leaves ATE in charge of showing it's console output.
The AIDL interface is more or less a draft. There is, probably, no way to do it right except by letting people use it a bit and gathering suggestions. Feel free to ask, if you want to know, why it looks this way.
I am personally interested in this for my aria2 port. I will do my best to help with supporting the new code, as long as I am able to use it myself. You can look how an integration is done in ate-support branch or get this build to get a peek at preliminary implementation on device.
This PR introduces new library in addition to emulatorview. It is called libtermexec and contains AIDL files, native code and Java wrapper for launching binaries with inbuilt console support. It can be very useful on it's own to replace java.lang.System and ProcessBuilder for launching executable files (and gives access to the PID unlike those). The library in Android AAR format, with AIDL and native binaries included, can be published on Maven to let people use it readily without using NDK themselves.
This PR may have an impact on various parts of ATE. I tried to keep it minimal without refactoring unnecessary parts, other important changes may have to be done later, see below for details. Biggest changes done here are:
- Splittig ShellSession in few subclasses
- Changes to open /dev/ptmx in Java code and using ParcelFileDescriptor instead of digging integer fd out of FileDescriptor with Reflection. Some reflection still remains, but only on older versions.
Perfomance considerations:
- Foreground mode probably should not be used unless necessary (e.g. don't go foreground when someone is still binding to the TermService). See also this question;
- There should probably be some form of window recycling to prevent single client from opening loads of windows in the "keep window open after session end" mode. Also valid for exesting RUN_SCRIPT-based API.
Security considerations:
- No need for permissions, because no work is done on ATE side besides displaying text from file.
- Someone can pass weird file descriptor (such as /dev/full or just some binary file) instead of /dev/ptmx handle to screw with emulator. Not exactly dangerous and can be mitigated by properly handling failures of native tty-related methods.
- May be abused to impersonate important windows, same as RUN_SCRIPT-based API. I didn't notice any defense there either. Can be mitigated by prepending name of originating app in title. This is already done in AIDL binder, but something seems to be wrong with whole "displaying window title thing", it just does not work for me.
Documentation considerations:
- Must tell people to use Context.BIND_AUTO_CREATE to prevent restart of TermService upon unbind. Maybe there is a way to disallow binding without the flag. Alternatively TermService can keep itself alive with startService and do stopSelf only when necessary.
Hopefully, size and complexity of these changes won't stop you from reviewing them. If you'd rather look at iterative lineage of commits instead of single squashed one, see this branch.
PS I have changed the language level to Java 7, because Java 6 is dead, and multi-catch and string-switch are too good to miss out on. This won't introduce any compatibility changes, unless you try to use try-block resource management (aka try-with-resources), in which case the IDE will loudly warn you. I can roll that one back, if you don't want it.