README.md
1# VirtualDeviceManager Demo Apps
2
3#### Page contents
4
5[Overview](#overview) \
6[Prerequisites](#prerequisites) \
7[Build & Install](#build-and-install) \
8[Run](#run) \
9[Host Options](#host-options) \
10[Client Options](#client-options) \
11[Demos](#demos)
12
13## Overview
14
15The VDM Demo Apps allow for showcasing VDM features, rapid prototyping and
16testing of new features.
17
18The VDM Demo contains 3 apps:
19
20* **Host**: installed on the host device, creates and manages a virtual
21 device, which represents the client device and communicates with the
22 physical client device by sending audio and frames of the virtual displays,
23 receiving input and sensor data that is injected into the framework. It can
24 launch apps on the virtual device, which are streamed to the client.
25
26* **Client**: installed on the client device. It receives the audio and frames
27 from the host device, which it renders, and sends back input and sensor
28 data. For best experience with app streaming on multiple displays at the
29 same time, it's best to use a large screen device as a client, like a Pixel
30 Tablet.
31
32* **Demos**: installed on the host, meant to showcase specific VDM features.
33 The demos can be also run natively on the host to illustrate better the
34 difference in the behavior when they are streamed to a virtual device.
35
36## Prerequisites
37
38* An Android device running Android 13 or newer to act as a client device.
39
40* A *rooted* Android device running Android 14 or newer (e.g. a `userdebug` or
41 `eng` build) to act as a host device. Even though VDM is available starting
42 Android 13, the support there is minimal and the Host app is not compatible
43 with Android 13.
44
45* Both devices need to support
46 [Wi-Fi Aware](https://developer.android.com/develop/connectivity/wifi/wifi-aware)
47
48Note: This example app uses an Android device as a client, but there's no such
49general requirement. The client device, its capabilities, the connectivity layer
50and the communication protocol are entirely up to the virtual device owner.
51
52## Build and Install
53
54### Using the script
55
56Simply connect your devices, navigate to the root of your Android checkout and
57run
58
59```
60./development/samples/VirtualDeviceManager/setup.sh
61```
62
63The interactive script will prompt you which apps to install to which of the
64available devices, build the APKs and install them.
65
66### Using adevice on the host device
67
681. Track the required modules.
69
70 ```shell
71 adevice track VdmHost
72 adevice track VdmDemos
73 ```
74
751. Update the device
76
77 ```shell
78 adevice update
79 ```
80
81### Manually
82
831. Source `build/envsetup.sh` and run `lunch` or set
84 `UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true` if there's no local build because
85 the APKs need to be built against a locally built SDK.
86
871. Build the Host app.
88
89 ```shell
90 m -j VdmHost
91 ```
92
931. Install the application as a system app on the host device.
94
95 ```shell
96 adb root && adb disable-verity && adb reboot # one time
97 adb root && adb remount
98 adb push $ANDROID_BUILD_TOP/development/samples/VirtualDeviceManager/host/com.example.android.vdmdemo.host.xml /system/etc/permissions/com.example.android.vdmdemo.host.xml
99 adb shell mkdir /system/priv-app/VdmDemoHost
100 adb push $OUT/system/priv-app/VdmHost/VdmHost.apk /system/priv-app/VdmDemoHost/
101 adb reboot
102 ```
103
104 **Tip:** Subsequent installs without changes to permissions, etc. do not
105 need all the commands above - you can just run \
106 \
107 `adb install -r -d -g $OUT/system/priv-app/VdmHost/VdmHost.apk`
108
1091. Build and install the Demo app on the host device.
110
111 ```shell
112 m -j VdmDemos && adb install -r -d -g $OUT/system/app/VdmDemos/VdmDemos.apk
113 ```
114
1151. Build and install the Client app on the client device.
116
117 ```shell
118 m -j VdmClient && adb install -r -d -g $OUT/system/app/VdmClient/VdmClient.apk
119 ```
120
121## Run
122
1231. Start both the Client and the Host apps on each respective device.
124
1251. They should find each other and connect automatically. On the first launch
126 the Host app will ask to create a CDM association: allow it.
127
128 WARNING: If there are other devices in the vicinity with one of these apps
129 running, they might interfere.
130
1311. Check out the different [Host Options](#host-options) and
132 [Client Options](#client-options) that allow for changing the behavior of
133 the streamed apps and the virtual device in general.
134
1351. Check out the [Demo apps](#demos) that are specifically meant to showcase
136 the VDM features.
137
138<!-- LINT.IfChange(host_options) -->
139
140## Host Options
141
142NOTE: Any flag changes require device reboot or "Force stop" of the host app
143because the flag values are cached and evaluated only when the host app is
144starting. Alternatively, run: \
145\
146`adb shell am force-stop com.example.android.vdmdemo.host`
147
148### Launcher
149
150Once the connection with the client device is established, the Host app will
151show a launcher-like list of installed apps on the host device.
152
153- Clicking an app icon will create a new virtual display, launch the app there
154 and start streaming the display contents to the client. The client will show
155 the surface of that display and render its contents.
156
157- Long pressing on an app icon will open a dialog to select an existing
158 display to launch the app on instead of creating a new one.
159
160- The Host app has a **CREATE HOME DISPLAY** button, clicking it will create a
161 new virtual display, launch the secondary home activity there and start
162 streaming the display contents to the client. The display on the Client app
163 will have a home button, clicking it will navigate the streaming experience
164 back to the home activity. Run the commands below to enable this
165 functionality.
166
167 ```shell
168 adb shell device_config put virtual_devices android.companion.virtual.flags.vdm_custom_home true
169 adb shell am force-stop com.example.android.vdmdemo.host
170 ```
171
172- The Host app has a **CREATE MIRROR DISPLAY** button, clicking it will create
173 a new virtual display, mirror the default host display there and start
174 streaming the display contents to the client.
175
176### Settings
177
178#### Input
179
180The input menu button enables several different mechanisms for injecting input
181from the host device into the focused display on the client device. The focused
182display is indicated by the frame around its header whenever there are more than
183one displays. The display focus is based on user interaction.
184
185Each input screen has a "Back", "Home" and "Forward" buttons.
186
187- **Touchpad** shows an on-screen touchpad for injecting mouse events into the
188 focused display.
189
190- **Remote** allows the host device to act as a pointer that controls the
191 mouse movement on the focused display.
192
193- **Navigation** shows an on-screen D-Pad, rotary and touchpad for navigating
194 the activity on the focused display.
195
196- **Keyboard** shows the host device's on-screen keyboard and sends any key
197 events to the activity on the focused display.
198
199- **Stylus** allows for injecting simulated stylus events into the focused
200 display. Use together with the stylus demo. Run the commands below to enable
201 this functionality.
202
203 ```shell
204 adb shell device_config put virtual_devices android.companion.virtual.flags.virtual_stylus true
205 adb shell am force-stop com.example.android.vdmdemo.host
206 ```
207
208#### General
209
210- **Device profile**: Enables device streaming CDM role as opposed to app
211 streaming role, with all differences in policies that this entails. \
212 *Changing this will recreate the virtual device.*
213
214- **Hide streamed app from recents**: Whether streamed apps should show up in
215 the host device's recent apps. Run the commands below to make this
216 functionality dynamic. \
217 *This can be changed dynamically starting with Android V.*
218
219 ```shell
220 adb shell device_config put virtual_devices android.companion.virtual.flags.dynamic_policy true
221 adb shell am force-stop com.example.android.vdmdemo.host
222 ```
223
224- **Enable cross-device clipboard**: Whether to share the clipboard between
225 the host and the virtual device. If disabled, both devices will have their
226 own isolated clipboards. Run the commands below to enable this
227 functionality. \
228 *This can be changed dynamically.*
229
230 ```shell
231 adb shell device_config put virtual_devices android.companion.virtual.flags.dynamic_policy true
232 adb shell device_config put virtual_devices android.companion.virtual.flags.cross_device_clipboard true
233 adb shell am force-stop com.example.android.vdmdemo.host
234 ```
235
236- **Enable custom activity policy**: Whether to use custom user notification
237 for activities that are unable to launch on the virtual display and send
238 such activities to the default display, whenever possible. Use together with
239 the activity policy demo. The behavior of the display fallback launch is
240 different depending on whether an activity result is expected by the caller,
241 and on whether the default display keyguard is currently locked. \
242 *This can be changed dynamically.*
243
244 ```shell
245 adb shell device_config put virtual_devices android.companion.virtual.flags.dynamic_policy true
246 adb shell device_config put virtual_devices android.companion.virtualdevice.flags.activity_control_api true
247 adb shell am force-stop com.example.android.vdmdemo.host
248 ```
249
250#### Client capabilities
251
252- **Enable client Sensors**: Enables sensor injection from the client device
253 into the host device. Any context that is associated with the virtual device
254 will access the virtual sensors by default. \
255 *Changing this will recreate the virtual device.*
256
257- **Enable client Camera**: Enables front & back camera injection from the
258 client device into the host device. (WIP: Any context that is associated
259 with the virtual device will the virtual cameras by default). Run the
260 commands below on host device to enable this functionality. \
261 *Changing this will recreate the virtual device.*
262
263 ```shell
264 adb shell device_config put virtual_devices android.companion.virtual.flags.virtual_camera true
265 adb shell device_config put virtual_devices android.companion.virtualdevice.flags.virtual_camera_service_discovery true
266 adb shell am force-stop com.example.android.vdmdemo.host
267 ```
268
269- **Enable client Audio**: Enables audio output on the client device. Any
270 context that is associated with the virtual device will play audio on the
271 client by default. \
272 *This can be changed dynamically.*
273
274#### Displays
275
276- **Display rotation**: Whether orientation change requests from streamed apps
277 should trigger orientation change of the relevant display. The client will
278 automatically rotate the relevant display upon such request. Disabling this
279 simulates a fixed orientation display that cannot physically rotate. Then
280 any streamed apps on that display will be letterboxed/pillarboxed if they
281 request orientation change. \
282 *This can be changed dynamically but only applies to newly created
283 displays.*
284
285- **Display category**: Whether to specify a custom display category for the
286 virtual displays. This means that only activities that have explicitly set
287 a matching `android:requiredDisplayCategory` activity attribute can be
288 launched on that display. \
289 *Changing this will recreate the virtual device.*
290
291- **Always unlocked**: Whether the virtual displays should remain unlocked and
292 interactive when the host device is locked. Disabling this will result in a
293 simple lock screen shown on these displays when the host device is locked. \
294 *Changing this will recreate the virtual device.*
295
296- **Show pointer icon**: Whether pointer icon should be shown for virtual
297 input pointer devices. \
298 *This can be changed dynamically.*
299
300- **Custom home**: Whether to use a custom activity as home on home displays,
301 or use the device-default secondary home activity. Run the commands below to
302 enable this functionality. \
303 *Changing this will recreate the virtual device.*
304
305 ```shell
306 adb shell device_config put virtual_devices android.companion.virtual.flags.vdm_custom_home true
307 adb shell am force-stop com.example.android.vdmdemo.host
308 ```
309
310- **Custom status bar**: Whether to add a custom status bar view on the
311 non-mirror virtual displays. Run the commands below to enable this
312 functionality. \
313 *This can be changed dynamically but only applies to newly created
314 displays.*
315
316 ```shell
317 adb shell device_config put virtual_devices android.companion.virtualdevice.flags.status_bar_and_insets true
318 adb shell am force-stop com.example.android.vdmdemo.host
319 ```
320
321- **Display timeout**: Whether to keep the displays always awake or to put
322 them to sleep after a timeout. Run the commands below to enable this
323 functionality. \
324 *Changing this will recreate the virtual device.*
325
326 ```shell
327 adb shell device_config put virtual_devices android.companion.virtualdevice.flags.device_aware_display_power true
328 adb shell am force-stop com.example.android.vdmdemo.host
329 ```
330
331- **Enable client brightness**: Whether to propagate any brightness changes
332 from the virtual display to the client's display. Run the commands below to
333 enable this functionality. \
334 *This can be changed dynamically but only applies to newly created
335 displays.*
336
337 ```shell
338 adb shell device_config put virtual_devices android.companion.virtualdevice.flags.device_aware_display_power true
339 adb shell am force-stop com.example.android.vdmdemo.host
340 ```
341
342#### Audio
343
344- **Use AudioPolicy.updateMixingRules**: Updates the dynamic AudiPolicy mixing rules
345 instead of unregistering and re-registering the AudioPolicy.
346
347#### Input method
348
349Note: The virtual keyboard acts like a physically connected keyboard to the host
350device. If you want the software keyboard to be shown on the virtual displays,
351you likely need to enable this in the host Settings. On a Pixel device: System
352-> Language and input -> Physical keyboard.
353
354- **Display IME policy**: Choose the IME behavior on remote displays. Run the
355 commands below to enable this functionality. \
356 *This can be changed dynamically.*
357
358 ```shell
359 adb shell device_config put virtual_devices android.companion.virtual.flags.vdm_custom_ime true
360 adb shell am force-stop com.example.android.vdmdemo.host
361 ```
362
363- **Use the native client IME**: Enables the native client IME instead of
364 streaming the host's IME on the virtual displays. Requires the *Display IME
365 Policy* to be set to *Show IME on the remote display*. Run the commands
366 below to enable this functionality. \
367 *Changing this will recreate the virtual device.*
368
369 ```shell
370 adb shell device_config put virtual_devices android.companion.virtual.flags.vdm_custom_ime true
371 adb shell am force-stop com.example.android.vdmdemo.host
372 ```
373
374#### Debug
375
376- **Record encoder output**: Enables recording the output of the encoder on
377 the host device to a local file on the device. This can be helpful with
378 debugging Encoding related issues. To download and play the file locally:
379
380 ```shell
381 adb pull /sdcard/Download/vdmdemo_encoder_output_<displayId>.h264
382 ffplay -f h264 vdmdemo_encoder_output_<displayId>.h264
383 ```
384
385<!-- LINT.ThenChange(README.md) -->
386<!-- LINT.IfChange(client_options) -->
387
388## Client Options
389
390### Streamed displays
391
392- Each display on the Client app has a "Back" and "Close" buttons. When a
393 display becomes empty, it's automatically removed.
394
395- Each display on the Client app has a "Rotate" button to switch between
396 portrait and landscape orientation. This simulates the physical rotation of
397 the display of the streamed activity. The "Resize" button can be used to
398 change the display dimensions.
399
400- Each display on the Client app has a "Fullscreen" button which will move the
401 contents of that display to an immersive fullscreen activity. The client's
402 back button/gestures are sent back to the streamed app. Use Volume Down on
403 the client device to exit fullscreen. Volume Up acts as a home key, if the
404 streamed display is a home display.
405
406### Input
407
408The input menu button enables **on-screen D-Pad, rotary and touchpad** for
409navigating the activity on the focused display. The focused display is indicated
410by the frame around its header whenever there are more than one displays. The
411display focus is based on user interaction.
412
413In addition, any input events generated from an **externally connected
414keyboard** are forwarded to the activity streamed on the focused display.
415
416**Externally connected mouse** events are also forwarded to the relevant
417display, if the mouse pointer is currently positioned on a streamed display.
418
419### Power
420
421The power menu button acts as a "virtual power button". It will toggle the state
422of the virtual device and all its displays between ON and OFF.
423Run the commands below on the host device to enable this functionality.
424
425```shell
426adb shell device_config put virtual_devices android.companion.virtual.flags.device_aware_display_power true
427adb shell am force-stop com.example.android.vdmdemo.host
428```
429
430<!-- LINT.ThenChange(README.md) -->
431<!-- LINT.IfChange(demos) -->
432
433## Demos
434
435- **Activity policy**: An activity showcasing blocking of activity launches on
436 the virtual device - either because the activity has opted out via
437 `android:canDisplayOnRemoteDevices` attribute, or because of the custom
438 activity policy of that device.
439
440- **Sensors**: A simple activity balancing a beam on the screen based on the
441 accelerometer events, which allows for selecting which device's sensor to
442 use. By default, will use the sensors of the device it's shown on.
443
444- **Display Power**: A simple activity showcasing the behavior of proximity
445 locks, screen brightness override and requesting the screen to be kept on
446 or turned on.
447
448- **Rotation**: A simple activity that is in landscape by default and can send
449 orientation change requests on demand. Showcases the display rotation on the
450 client, which will rotate the user-visible surface.
451
452- **Home**: A simple activity with utilities around launching HOME and
453 SECONDARY_HOME Intents, as well as other implicit intents.
454
455- **Secure Window**: A simple activity that declares the Window as secure.
456 This showcases the FLAG_SECURE streaming policies in VDM.
457
458- **Permissions**: A simple activity with buttons to request and revoke
459 runtime permissions. This can help test the permission streaming and
460 device-aware permission features.
461
462- **Latency**: Renders a simple counter view that renders a new frame with an
463 incremented counter every second. Can be useful for debugging latency,
464 encoder, decoder issues in the demo application.
465
466- **Vibration**: A simple activity making vibration requests via different
467 APIs and allows for selecting which device's vibrator to use. By default,
468 will use the vibrator of the device it's shown on. Note that currently there
469 is no vibration support on virtual devices, so vibration requests from
470 streamed activities are ignored.
471
472- **Stylus**: A simple drawing activity that reacts on stylus input events.
473 Use together with the simulated stylus input feature of the host app.
474
475- **Recorder**: A simple activity that can start multiple audio recorders.
476 This helps test audio recording permissions and concurrent recordings.
477
478The demo activity depends on whether the **Display Category** Host preference is
479enabled or not. If enabled, it becomes equivalent to the **Home** demo activity,
480which showcases implicit intent handling.
481
482<!-- LINT.ThenChange(README.md) -->
483
484## SDK Version
485
486### Android 16 / Baklava
487
488- Added support for custom power management.
489
490- Added support for custom system windows (like status bar) and insets.
491
492- Added support for per-display activity policies.
493
494- Added support for custom redirection of blocked activities.
495
496- Added support for hiding the blocked activity dialog.
497
498- Added support for virtual display cutout.
499
500- Added support for virtual display rotation.
501
502- Added support for virtual rotary input.
503
504### Android 15 / Vanilla Ice Cream / SDK level 35
505
506- Added support for virtual camera.
507
508- Added support for virtual stylus input.
509
510- Added support for cross-device clipboard.
511
512- Added support for custom home activities.
513
514- Added support for custom IME component.
515
516- Added support for per-display IME policy.
517
518- Added support for fixed orientation displays (disable display rotation).
519
520- Added support for mirroring the default display on the virtual device.
521
522- Added support for dynamic policy changes, so the device does not need to be
523 recreated.
524
525- Improved support for displays that support home activities. Removed
526 navigation bar and added support for normal home intents.
527
528- Improved handling of vibrating requests originating from virtual devices.
529
530- Improved multi-display mouse support.
531
532- Fixed bugs with hiding streamed apps from the host's recent apps.
533
534### Android 14 / Upside Down Cake / SDK level 34
535
536- Added support for display categories and restricted activities.
537
538- Added support for virtual sensors.
539
540- Added device awareness to contexts.
541
542- Added support for clipboard on the virtual device.
543
544- Added support for hiding streamed apps from the host's recent apps.
545
546- Added `COMPANION_DEVICE_NEARBY_DEVICE_STREAMING` device profile.
547
548- Added support for virtual navigation input: D-Pad and navigation touchpad.
549
550- Added support for display categories and restricted activities.
551
552- Improved support for audio, allowing routing to be based on the origin
553 context.
554
555- Improved support for creation of virtual displays and input devices.
556
557- Improved handling of virtual touch events.
558
559### Android 13 / Tiramisu / SDK level 33
560
561- Added support for virtual audio device.
562
563- Added support for hiding the mouse pointer icon.
564
565- Added support for virtual mouse, keyboard, touchscreen.
566
567- Added support for always unlocked displays.
568
569- Added `COMPANION_DEVICE_APP_STREAMING` device profile.
570
571- Added support for virtual device creation.
572