Hi all,
RealVNC and Sony Mobile Communications would jointly like to contribute APIs to allow remote control of Android devices. In this sense, "Remote Control" means the ability for applications to 'see' the screen image and to inject key/touch events into the platform.
Remote controlling Android devices is useful for:
- Helpdesk applications
- Testing tools
- TVs & Automotive applications
- Applications which wish to take screenshots for any other reason
It's also incredibly security-critical. To quote Dianne Hackborn[1],
The inject events permission effectively grants an application EVERY possible permission, because it can drive the UI and do anything the user can do.
The screen shot permission allows the application, any time the user is operating the device, to monitor them and do very dangerous things like collect every password they type in web pages and elsewhere.
In fact, the APIs we need are already exposed by the Window Manager and Surface Flinger, to other internal Android components. To make them available to applications, all that's really missing is a solid security model, and that's where we need help.
Security:
We propose to follow the example of Android's new VPN service. Specifically:
- Remote control will be a new 'dangerous' permission
- But because few people read the permissions prompts, there will in addition be a new runtime prompt with suitably alarmist wording:
- "This application is attempting to take control of your device. This application may access any of your data, impersonate you, or do anything else that you can do when using your phone. Are you sure that you want to allow remote control?"
- There will be a notification whenever remote control is active
- Selecting the notification will bring up a second dialog with information about the remote control and the ability to cancel it
- Only one application will be allowed to remotely control the device at once
In diagrammatic form, the arrangement is shown at the end of this mail.
Is this approach acceptable?
We would like to propose one concession to usability - the addition of an 'Always trust this application' checkbox. If checked, further prompting would not occur on subsequent remote control attempts, unless (a) something else is doing remote control, (b) the user closed remote control using the notification.
Details of the APIs:
android.os.RemoteControl will be a new Java API class. Unlike the VPN service, there is no requirement that remote control applications are a Service. This is because it can sometimes be beneficial to capture a screenshot or to inject an event in a one-off fashion from an Activity, Broadcast Receiver or other component. Of course, full remote control solutions would likely be services but we don't want to mandate that.
Broadly, the APIs provided on android.os.RemoteControl will be:
- getFrameBuffer - returns a ParcelFileDescriptor and size of some ashmem shared memory containing the framebuffer
- grabScreen - updates the frame buffer.
- setFramebufferScaledSize - requests scaling of the framebuffer
- injectKeyEvent(android.view.KeyEvent) - types a key
- injectMotionEvent(android.view.MotionEvent) - touches the screen
- getDeviceInfo - returns the real screen size of the device (this may differ from the area to which applications are allowed to draw)
These exactly correspond to internal APIs already available in the surface flinger and window manager.
There will be callbacks when:
- remote control is revoked;
- the device information changes.
Compatibility:
We have been using a remote control arrangement based on the existing APIs within the Window Manager and Surface Flinger since Android 2.3 was released. We can confirm that these APIs have worked on every Android device we have tested, from six manufacturers.
However, since android.os.RemoteControl would be a new public API, we would expect to add tests to the CTS to confirm its operation. This would require that each device supported the OpenGL framebuffer object extension. Is that acceptable? We believe many features of ICS already rely on that extension, because this screenshot code is already used to implement various transitions.
DRM:
The Surface Flinger is already aware of what surfaces contain DRM ('secure') content, and will refuse to capture screenshots if such layers are visible.
Performance:
An end-to-end remote control solution based on these APIs is able to attain high frame rates (14fps+) with low CPU impact, given sufficient bandwidth to the viewing device. This is because the approach uses shared memory and because the existing screen capture code within the Surface Flinger uses framebuffer objects.
However, in future, we would like to add follow-up submissions which:
- Enable downsampling to RGB565 on the GPU
- Allow for incremental captures (grabScreen doesn't return until there's a change)
These allow for 25+fps.
Nevertheless, these are optional enhancements and we would prefer to submit these separately because they involve changes to the Surface Flinger.
Further into the future, we'd like to explore ways to pass the screen image into hardware video encoders or alternatively run OpenGL/RenderScript transforms on the screen image before it leaves the GPU. This should enable full frame-rate HD video. We'd aim to contribute these facilities within the same security architecture.
RealVNC and Sony would be delighted to see these changes in the J release and we're expecting to work hard to achieve that. We'd really be grateful for feedback and suggested improvements, especially with regards to the security model.
Many thanks,
Adrian
PS some very preliminary code can be found at:
but it requires major changes yet. We wanted to discuss the design on this mailing list before submitting code to AOSP, so in that spirit, the code's not ready yet! Notable omissions: (a) new permission, (b) management dialog, (c) removal of old obsolete APIs, (d) simplification to support only a single client, (e) revocation API, (f) actually completing the authorisation process, (g) translations, (h) CTS.
Security design:
+-----------------+ +------------+
| Surface flinger |--------------------| | +---------------+ +-----+
+-----------------+ | New system | | New APIs: | | App |
Existing Binder APIs | service: |-----------| android.os. |-| |
to grab screen and inject | Remote | Binder | RemoteControl | | |
events, protected by | Control | +---------------+ +-----+
signature permissions | Service | /
+-----------------+ | | App /
| Window manager |--------------------| | launches /
+-----------------+ +------------+ intent /
^ Authorises app /
| /
+--------------------+ /
| New system dialogs:|<-----------------
| Remote control |
| dialogs |
+--------------------+