android_tools/emulator/
emulator_tools.rs

1use crate::emulator::*;
2use crate::error::*;
3use std::path::{Path, PathBuf};
4
5#[derive(Clone, Default)]
6pub struct EmulatorTools {
7    list_avds: bool,
8    sysdir: Option<PathBuf>,
9    system: Option<PathBuf>,
10    vendor: Option<PathBuf>,
11    writable_system: bool,
12    delay_adb: bool,
13    datadir: Option<PathBuf>,
14    kernel: Option<PathBuf>,
15    ramdisk: Option<PathBuf>,
16    image: Option<PathBuf>,
17    initdata: Option<PathBuf>,
18    data: Option<PathBuf>,
19    encryption_key: Option<PathBuf>,
20    logcat_output: Option<PathBuf>,
21    partition_size: Option<u32>,
22    cache: Option<PathBuf>,
23    cache_size: Option<u32>,
24    no_cache: bool,
25    nocache: bool,
26    sdcard: Option<PathBuf>,
27    quit_after_boot: Option<u32>,
28    qemu_top_dir: Option<PathBuf>,
29    monitor_adb: bool,
30    snapstorage: Option<PathBuf>,
31    no_snapstorage: bool,
32    snapshot: Option<String>,
33    no_snapshot: bool,
34    no_snapshot_save: bool,
35    no_snapshot_load: bool,
36    snapshot_list: bool,
37    no_snapshot_update_time: bool,
38    wipe_data: bool,
39    avd: Option<String>,
40    avd_arch: Option<String>, // check
41    skindir: Option<PathBuf>,
42    skin: Option<String>,
43    no_skin: bool,
44    noskin: bool,
45    memory: Option<u32>,
46    ui_only: Option<String>,
47    id: Option<String>,
48    cores: Option<u32>,
49    accel: Option<AccelMode>,
50    no_accel: bool,
51    ranchu: bool,
52    engine: Option<Engine>,
53    netspeed: Option<Netspeed>,
54    netdelay: Option<String>,
55    netfast: bool,
56    code_profile: Option<String>,
57    show_kernel: bool,
58    shell: bool,
59    no_jni: bool,
60    nojni: bool,
61    dalvik_vm_checkjni: bool,
62    logcat: Option<String>,
63    no_audio: bool,
64    noaudio: bool,
65    audio: Option<String>,
66    radio: Option<String>,
67    port: Option<String>,
68    ports: Option<Vec<String>>,
69    onion: Option<PathBuf>,
70    onion_alph: Option<String>,
71    onion_rotation: Option<String>,
72    dpi_device: Option<String>,
73    scale: Option<String>,
74    wifi_client_port: Option<String>,
75    wifi_server_port: Option<String>,
76    http_proxy: Option<String>,
77    timezone: Option<String>,
78    change_language: Option<String>,
79    change_country: Option<String>,
80    change_locale: Option<String>,
81    dns_server: Option<String>,
82    net_tap: Option<String>,
83    net_tap_script_up: Option<String>,
84    net_tap_script_down: Option<String>,
85    cpu_delay: Option<String>,
86    no_boot_anim: bool,
87    no_window: bool,
88    qt_hide_window: bool,
89    no_sim: bool,
90    lowram: bool,
91    version: bool,
92    no_passive_gps: bool,
93    gnss_file_path: Option<PathBuf>,
94    gnss_grpc_port: Option<String>,
95    virtio_console: bool,
96    read_only: bool,
97    is_restart: Option<String>,
98    report_console: Option<String>,
99    gps: Option<String>,
100    shell_serial: Option<String>,
101    tcpdump: Option<PathBuf>,
102    bootchart: Option<String>,
103    charmap: Option<PathBuf>,
104    studio_params: Option<PathBuf>,
105    prop: Option<String>,
106    shared_net_id: Option<String>,
107    gpu: Option<String>,
108    use_host_vulkan: bool,
109    camera_back: Option<CameraMode>,
110    camera_front: Option<CameraMode>,
111    webcam_list: bool,
112    virtualscene_poster: Option<String>,
113    screen: Option<ScreenMode>,
114    force_32bit: bool,
115    selinux: Option<SELinux>,
116    unix_pipe: Option<PathBuf>,
117    fixed_scale: bool,
118    wait_for_debugger: bool,
119    skip_adb_auth: bool,
120    metrics_to_console: bool,
121    metrics_collection: bool,
122    metrics_to_file: Option<PathBuf>,
123    detect_image_hang: bool,
124    feature: Option<String>,
125    icc_profile: Option<PathBuf>,
126    sim_access_rules_file: Option<PathBuf>,
127    phone_number: Option<String>,
128    acpi_config: Option<PathBuf>,
129    fuchsia: bool,
130    window_size: Option<String>,
131    allow_host_audio: bool,
132    restart_when_stalled: bool,
133    perf_stat: Option<PathBuf>,
134    share_vid: bool,
135    grpc: Option<String>,
136    grpc_tls_key: Option<PathBuf>,
137    grpc_tls_cer: Option<PathBuf>,
138    grpc_tls_ca: Option<PathBuf>,
139    grpc_use_token: bool,
140    idle_grpc_timeout: Option<u32>,
141    waterfall: Option<String>,
142    multidisplay: Option<String>,
143    google_maps_key: Option<String>,
144    no_location_ui: bool,
145    use_keycode_forwarding: bool,
146    record_session: Option<PathBuf>,
147    legacy_fake_camera: bool,
148    no_camera_hq_edge: bool,
149    no_direct_adb: bool,
150    check_snapshot_loadable: Option<String>,
151    no_hidpi_scaling: bool,
152    no_mouse_reposition: bool,
153    guest_angle: bool,
154    qemu: bool,
155    verbose: bool,
156    debug: Option<DebugTags>,
157    debug_no: Option<DebugTags>,
158    help: bool,
159    help_disk_images: bool,
160    help_debug_tags: bool,
161    help_char_devices: bool,
162    help_environment: bool,
163    help_virtual_device: bool,
164    help_sdk_images: bool,
165    help_build_images: bool,
166    help_all: bool,
167}
168
169impl EmulatorTools {
170    pub fn new() -> Self {
171        Self {
172            ..Default::default()
173        }
174    }
175
176    /// List available AVDs
177    pub fn list_avds(&mut self, list_avds: bool) -> &mut Self {
178        self.list_avds = list_avds;
179        self
180    }
181
182    /// Search for system disk images in <dir>
183    pub fn sysdir(&mut self, sysdir: &Path) -> &mut Self {
184        self.sysdir = Some(sysdir.to_owned());
185        self
186    }
187
188    /// Read initial system image from <file>
189    pub fn system(&mut self, system: &Path) -> &mut Self {
190        self.system = Some(system.to_owned());
191        self
192    }
193
194    /// Read initial vendor image from <file>
195    pub fn vendor(&mut self, vendor: &Path) -> &mut Self {
196        self.vendor = Some(vendor.to_owned());
197        self
198    }
199
200    /// Make system & vendor image writable after `adb remount`
201    pub fn writable_system(&mut self, writable_system: bool) -> &mut Self {
202        self.writable_system = writable_system;
203        self
204    }
205
206    /// Delay adb communication till boot completes
207    pub fn delay_adb(&mut self, delay_adb: bool) -> &mut Self {
208        self.delay_adb = delay_adb;
209        self
210    }
211
212    /// Write user data into <dir>
213    pub fn datadir(&mut self, datadir: &Path) -> &mut Self {
214        self.datadir = Some(datadir.to_owned());
215        self
216    }
217
218    /// Use specific emulated kernel
219    pub fn kernel(&mut self, kernel: &Path) -> &mut Self {
220        self.kernel = Some(kernel.to_owned());
221        self
222    }
223
224    /// Ramdisk image (default <system>/ramdisk.img)
225    pub fn ramdisk(&mut self, ramdisk: &Path) -> &mut Self {
226        self.ramdisk = Some(ramdisk.to_owned());
227        self
228    }
229
230    /// Obsolete, use -system <file> instead
231    pub fn image(&mut self, image: &Path) -> &mut Self {
232        self.image = Some(image.to_owned());
233        self
234    }
235
236    /// Same as `-init-data <file>`
237    pub fn initdata(&mut self, initdata: &Path) -> &mut Self {
238        self.initdata = Some(initdata.to_owned());
239        self
240    }
241
242    /// Data image (default <datadir>/userdata-qemu.img)
243    pub fn data(&mut self, data: &Path) -> &mut Self {
244        self.data = Some(data.to_owned());
245        self
246    }
247
248    /// Read initial encryption key image from <file>
249    pub fn encryption_key(&mut self, encryption_key: &Path) -> &mut Self {
250        self.encryption_key = Some(encryption_key.to_owned());
251        self
252    }
253
254    /// Output file of logcat(default none)
255    pub fn logcat_output(&mut self, logcat_output: &Path) -> &mut Self {
256        self.logcat_output = Some(logcat_output.to_owned());
257        self
258    }
259
260    /// System/data partition size in MBs
261    pub fn partition_size(&mut self, partition_size: u32) -> &mut Self {
262        self.partition_size = Some(partition_size);
263        self
264    }
265
266    /// Cache partition image (default is temporary file)
267    pub fn cache(&mut self, cache: &Path) -> &mut Self {
268        self.cache = Some(cache.to_owned());
269        self
270    }
271
272    /// Cache partition size in MBs
273    pub fn cache_size(&mut self, cache_size: u32) -> &mut Self {
274        self.cache_size = Some(cache_size);
275        self
276    }
277
278    /// Disable the cache partition
279    pub fn no_cache(&mut self, no_cache: bool) -> &mut Self {
280        self.no_cache = no_cache;
281        self
282    }
283
284    /// Same as -no-cache
285    pub fn nocache(&mut self, nocache: bool) -> &mut Self {
286        self.nocache = nocache;
287        self
288    }
289
290    /// SD card image (default <datadir>/sdcard.img)
291    pub fn sdcard(&mut self, sdcard: &Path) -> &mut Self {
292        self.sdcard = Some(sdcard.to_owned());
293        self
294    }
295
296    /// Qeuit emulator after guest boots completely, or after timeout in seconds
297    pub fn quit_after_boot(&mut self, quit_after_boot: u32) -> &mut Self {
298        self.quit_after_boot = Some(quit_after_boot);
299        self
300    }
301
302    /// Use the emulator in the specified dir (relative or absolute path)v
303    pub fn qemu_top_dir(&mut self, qemu_top_dir: &Path) -> &mut Self {
304        self.qemu_top_dir = Some(qemu_top_dir.to_owned());
305        self
306    }
307
308    /// Monitor the adb messages between guest and host, default not
309    pub fn monitor_adb(&mut self, monitor_adb: bool) -> &mut Self {
310        self.monitor_adb = monitor_adb;
311        self
312    }
313
314    /// File that contains all state snapshots (default <datadir>/snapshots.img)
315    pub fn snapstorage(&mut self, snapstorage: &Path) -> &mut Self {
316        self.snapstorage = Some(snapstorage.to_owned());
317        self
318    }
319
320    /// Do not mount a snapshot storage file (this disables all snapshot functionality)
321    pub fn no_snapstorage(&mut self, no_snapstorage: bool) -> &mut Self {
322        self.no_snapstorage = no_snapstorage;
323        self
324    }
325
326    /// Name of snapshot within storage file for auto-start and auto-save (default 'default-boot')
327    pub fn snapshot(&mut self, snapshot: String) -> &mut Self {
328        self.snapshot = Some(snapshot);
329        self
330    }
331
332    /// Perform a full boot and do not auto-save, but qemu vmload and vmsave operate on snapstorage
333    pub fn no_snapshot(&mut self, no_snapshot: bool) -> &mut Self {
334        self.no_snapshot = no_snapshot;
335        self
336    }
337
338    /// Do not auto-save to snapshot on exit: abandon changed state
339    pub fn no_snapshot_save(&mut self, no_snapshot_save: bool) -> &mut Self {
340        self.no_snapshot_save = no_snapshot_save;
341        self
342    }
343
344    /// Do not auto-start from snapshot: perform a full boot
345    pub fn no_snapshot_load(&mut self, no_snapshot_load: bool) -> &mut Self {
346        self.no_snapshot_load = no_snapshot_load;
347        self
348    }
349
350    /// Show a list of available snapshots
351    pub fn snapshot_list(&mut self, snapshot_list: bool) -> &mut Self {
352        self.snapshot_list = snapshot_list;
353        self
354    }
355
356    /// Do not try to correct snapshot time on restore
357    pub fn no_snapshot_update_time(&mut self, no_snapshot_update_time: bool) -> &mut Self {
358        self.no_snapshot_update_time = no_snapshot_update_time;
359        self
360    }
361
362    /// Reset the user data image (copy it from initdata)
363    pub fn wipe_data(&mut self, wipe_data: bool) -> &mut Self {
364        self.wipe_data = wipe_data;
365        self
366    }
367
368    /// Use a specific android virtual device
369    pub fn avd(&mut self, avd: String) -> &mut Self {
370        self.avd = Some(avd);
371        self
372    }
373
374    /// Use a specific target architecture
375    pub fn avd_arch(&mut self, avd_arch: String) -> &mut Self {
376        self.avd_arch = Some(avd_arch);
377        self
378    }
379
380    /// Search skins in <dir> (default <system>/skins)
381    pub fn skindir(&mut self, skindir: &Path) -> &mut Self {
382        self.skindir = Some(skindir.to_owned());
383        self
384    }
385
386    /// Select a given skin
387    pub fn skin(&mut self, skin: String) -> &mut Self {
388        self.skin = Some(skin);
389        self
390    }
391
392    /// Deprecated: create an AVD with no skin instead
393    pub fn no_skin(&mut self, no_skin: bool) -> &mut Self {
394        self.no_skin = no_skin;
395        self
396    }
397
398    /// Same as -no-skin
399    pub fn noskin(&mut self, noskin: bool) -> &mut Self {
400        self.noskin = noskin;
401        self
402    }
403
404    /// Physical RAM size in MBs
405    pub fn memory(&mut self, memory: u32) -> &mut Self {
406        self.memory = Some(memory);
407        self
408    }
409
410    /// Run only the UI feature requested
411    pub fn ui_only(&mut self, ui_only: String) -> &mut Self {
412        self.ui_only = Some(ui_only);
413        self
414    }
415
416    /// Assign an id to this virtual device (separate from the avd name)
417    pub fn id(&mut self, id: String) -> &mut Self {
418        self.id = Some(id);
419        self
420    }
421
422    /// Set number of CPU cores to emulator
423    pub fn cores(&mut self, cores: u32) -> &mut Self {
424        self.cores = Some(cores);
425        self
426    }
427
428    /// Configure emulation acceleration
429    pub fn accel(&mut self, accel: AccelMode) -> &mut Self {
430        self.accel = Some(accel);
431        self
432    }
433
434    /// Same as '-accel off'
435    pub fn no_accel(&mut self, no_accel: bool) -> &mut Self {
436        self.no_accel = no_accel;
437        self
438    }
439
440    /// Use new emulator backend instead of the classic one
441    pub fn ranchu(&mut self, ranchu: bool) -> &mut Self {
442        self.ranchu = ranchu;
443        self
444    }
445
446    /// Select engine. auto|classic|qemu2
447    pub fn engine(&mut self, engine: Engine) -> &mut Self {
448        self.engine = Some(engine);
449        self
450    }
451
452    /// Maximum network download/upload speeds
453    pub fn netspeed(&mut self, netspeed: Netspeed) -> &mut Self {
454        self.netspeed = Some(netspeed);
455        self
456    }
457
458    /// Network latency emulation
459    pub fn netdelay(&mut self, netdelay: String) -> &mut Self {
460        self.netdelay = Some(netdelay);
461        self
462    }
463
464    /// Disable network shaping
465    pub fn netfast(&mut self, netfast: bool) -> &mut Self {
466        self.netfast = netfast;
467        self
468    }
469
470    /// Enable code profiling
471    pub fn code_profile(&mut self, code_profile: String) -> &mut Self {
472        self.code_profile = Some(code_profile);
473        self
474    }
475
476    /// Display kernel messages
477    pub fn show_kernel(&mut self, show_kernel: bool) -> &mut Self {
478        self.show_kernel = show_kernel;
479        self
480    }
481
482    /// Enable root shell on current terminal
483    pub fn shell(&mut self, shell: bool) -> &mut Self {
484        self.shell = shell;
485        self
486    }
487
488    /// Deprecated, see dalvik_vm_checkjni
489    pub fn no_jni(&mut self, no_jni: bool) -> &mut Self {
490        self.no_jni = no_jni;
491        self
492    }
493
494    /// Deprecated, see dalvik_vm_checkjni
495    pub fn nojni(&mut self, nojni: bool) -> &mut Self {
496        self.nojni = nojni;
497        self
498    }
499
500    /// Enable dalvik.vm.checkjni
501    pub fn dalvik_vm_checkjni(&mut self, dalvik_vm_checkjni: bool) -> &mut Self {
502        self.dalvik_vm_checkjni = dalvik_vm_checkjni;
503        self
504    }
505
506    /// Enable logcat output with given tags
507    pub fn logcat(&mut self, logcat: String) -> &mut Self {
508        self.logcat = Some(logcat);
509        self
510    }
511
512    /// Disable audio support
513    pub fn no_audio(&mut self, no_audio: bool) -> &mut Self {
514        self.no_audio = no_audio;
515        self
516    }
517
518    /// Same as -no-audio
519    pub fn noaudio(&mut self, noaudio: bool) -> &mut Self {
520        self.noaudio = noaudio;
521        self
522    }
523
524    /// Use specific audio backend
525    pub fn audio(&mut self, audio: String) -> &mut Self {
526        self.audio = Some(audio);
527        self
528    }
529
530    /// Redirect radio modem interface to character device
531    pub fn radio(&mut self, radio: String) -> &mut Self {
532        self.radio = Some(radio);
533        self
534    }
535
536    /// TCP port that will be used for the console
537    pub fn port(&mut self, port: String) -> &mut Self {
538        self.port = Some(port);
539        self
540    }
541
542    /// TCP ports used for the console and adb bridge
543    pub fn ports(&mut self, ports: Vec<String>) -> &mut Self {
544        self.ports = Some(ports);
545        self
546    }
547
548    /// Use overlay PNG image over screen
549    pub fn onion(&mut self, onion: &Path) -> &mut Self {
550        self.onion = Some(onion.to_owned());
551        self
552    }
553
554    /// Specify onion-skin translucency
555    pub fn onion_alph(&mut self, onion_alph: String) -> &mut Self {
556        self.onion_alph = Some(onion_alph);
557        self
558    }
559
560    /// specify onion-skin rotation
561    pub fn onion_rotation(&mut self, onion_rotation: String) -> &mut Self {
562        self.onion_rotation = Some(onion_rotation);
563        self
564    }
565
566    /// Specify device's resolution in dpi (default DEFAULT_DEVICE_DPI)
567    pub fn dpi_device(&mut self, dpi_device: String) -> &mut Self {
568        self.dpi_device = Some(dpi_device);
569        self
570    }
571
572    /// Scale emulator window (deprecated)
573    pub fn scale(&mut self, scale: String) -> &mut Self {
574        self.scale = Some(scale);
575        self
576    }
577
578    /// Connect to other emulator for WiFi forwarding
579    pub fn wifi_client_port(&mut self, wifi_client_port: String) -> &mut Self {
580        self.wifi_client_port = Some(wifi_client_port);
581        self
582    }
583
584    /// Listen to other emulator for WiFi forwarding
585    pub fn wifi_server_port(&mut self, wifi_server_port: String) -> &mut Self {
586        self.wifi_server_port = Some(wifi_server_port);
587        self
588    }
589
590    /// Make TCP connections through a HTTP/HTTPS proxy
591    pub fn http_proxy(&mut self, http_proxy: String) -> &mut Self {
592        self.http_proxy = Some(http_proxy);
593        self
594    }
595
596    /// Use this timezone instead of the host's default
597    pub fn timezone(&mut self, timezone: String) -> &mut Self {
598        self.timezone = Some(timezone);
599        self
600    }
601
602    /// Use this language instead of the current one. Restarts the framework
603    pub fn change_language(&mut self, change_language: String) -> &mut Self {
604        self.change_language = Some(change_language);
605        self
606    }
607
608    /// Use this country instead of the current one. Restarts the framework
609    pub fn change_country(&mut self, change_country: String) -> &mut Self {
610        self.change_country = Some(change_country);
611        self
612    }
613
614    /// Use this locale instead of the current one. Restarts the framework
615    pub fn change_locale(&mut self, change_locale: String) -> &mut Self {
616        self.change_locale = Some(change_locale);
617        self
618    }
619
620    /// Use this DNS server(s) in the emulated system
621    pub fn dns_server(&mut self, dns_server: String) -> &mut Self {
622        self.dns_server = Some(dns_server);
623        self
624    }
625
626    /// Use this TAP interface for networking
627    pub fn net_tap(&mut self, net_tap: String) -> &mut Self {
628        self.net_tap = Some(net_tap);
629        self
630    }
631
632    /// Script to run when the TAP interface goes up
633    pub fn net_tap_script_up(&mut self, net_tap_script_up: String) -> &mut Self {
634        self.net_tap_script_up = Some(net_tap_script_up);
635        self
636    }
637
638    /// Script to run when the TAP interface goes down
639    pub fn net_tap_script_down(&mut self, net_tap_script_down: String) -> &mut Self {
640        self.net_tap_script_down = Some(net_tap_script_down);
641        self
642    }
643
644    /// Throttle CPU emulation
645    pub fn cpu_delay(&mut self, cpu_delay: String) -> &mut Self {
646        self.cpu_delay = Some(cpu_delay);
647        self
648    }
649
650    /// Disable animation for faster boot
651    pub fn no_boot_anim(&mut self, no_boot_anim: bool) -> &mut Self {
652        self.no_boot_anim = no_boot_anim;
653        self
654    }
655
656    /// Disable graphical window display
657    pub fn no_window(&mut self, no_window: bool) -> &mut Self {
658        self.no_window = no_window;
659        self
660    }
661
662    /// Start QT window but hide window display
663    pub fn qt_hide_window(&mut self, qt_hide_window: bool) -> &mut Self {
664        self.qt_hide_window = qt_hide_window;
665        self
666    }
667
668    /// Device has no SIM card
669    pub fn no_sim(&mut self, no_sim: bool) -> &mut Self {
670        self.no_sim = no_sim;
671        self
672    }
673
674    /// Device is a low ram device
675    pub fn lowram(&mut self, lowram: bool) -> &mut Self {
676        self.lowram = lowram;
677        self
678    }
679
680    /// Display emulator version number
681    pub fn version(&mut self, version: bool) -> &mut Self {
682        self.version = version;
683        self
684    }
685
686    /// Disable passive gps updates
687    pub fn no_passive_gps(&mut self, no_passive_gps: bool) -> &mut Self {
688        self.no_passive_gps = no_passive_gps;
689        self
690    }
691
692    /// Use the specified filepath to read gnss data
693    pub fn gnss_file_path(&mut self, gnss_file_path: &Path) -> &mut Self {
694        self.gnss_file_path = Some(gnss_file_path.to_owned());
695        self
696    }
697
698    /// Use the specified port number to start grpc service to receive gnss data
699    pub fn gnss_grpc_port(&mut self, gnss_grpc_port: String) -> &mut Self {
700        self.gnss_grpc_port = Some(gnss_grpc_port);
701        self
702    }
703
704    /// Using virtio console as console
705    pub fn virtio_console(&mut self, virtio_console: bool) -> &mut Self {
706        self.virtio_console = virtio_console;
707        self
708    }
709
710    /// Allow running multiple instances of emulators on the same AVD, but cannot
711    /// save snapshot
712    pub fn read_only(&mut self, read_only: bool) -> &mut Self {
713        self.read_only = read_only;
714        self
715    }
716
717    /// Specifies that this emulator was a restart, and to wait out <restart-pid>
718    /// before proceeding
719    pub fn is_restart(&mut self, is_restart: String) -> &mut Self {
720        self.is_restart = Some(is_restart);
721        self
722    }
723
724    /// Report console port to remote socket
725    pub fn report_console(&mut self, report_console: String) -> &mut Self {
726        self.report_console = Some(report_console);
727        self
728    }
729
730    /// Redirect NMEA GPS to character device
731    pub fn gps(&mut self, gps: String) -> &mut Self {
732        self.gps = Some(gps);
733        self
734    }
735
736    /// Specific character device for root shell
737    pub fn shell_serial(&mut self, shell_serial: String) -> &mut Self {
738        self.shell_serial = Some(shell_serial);
739        self
740    }
741
742    /// Capture network packets to file
743    pub fn tcpdump(&mut self, tcpdump: &Path) -> &mut Self {
744        self.tcpdump = Some(tcpdump.to_owned());
745        self
746    }
747
748    /// Enable bootcharting
749    pub fn bootchart(&mut self, bootchart: String) -> &mut Self {
750        self.bootchart = Some(bootchart);
751        self
752    }
753
754    /// Use specific key character map
755    pub fn charmap(&mut self, charmap: &Path) -> &mut Self {
756        self.charmap = Some(charmap.to_owned());
757        self
758    }
759
760    /// Used by Android Studio to provide parameters
761    pub fn studio_params(&mut self, studio_params: &Path) -> &mut Self {
762        self.studio_params = Some(studio_params.to_owned());
763        self
764    }
765
766    /// Set system property on boot
767    pub fn prop(&mut self, prop: String) -> &mut Self {
768        self.prop = Some(prop);
769        self
770    }
771
772    /// Join the shared network, using IP address 10.1.2.<number>
773    pub fn shared_net_id(&mut self, shared_net_id: String) -> &mut Self {
774        self.shared_net_id = Some(shared_net_id);
775        self
776    }
777
778    /// Set hardware OpenGLES emulation mode
779    pub fn gpu(&mut self, gpu: String) -> &mut Self {
780        self.gpu = Some(gpu);
781        self
782    }
783
784    /// Use host for vulkan emulation regardless of 'gpu' mode
785    pub fn use_host_vulkan(&mut self, use_host_vulkan: bool) -> &mut Self {
786        self.use_host_vulkan = use_host_vulkan;
787        self
788    }
789
790    /// Set emulation mode for a camera facing back
791    pub fn camera_back(&mut self, camera_back: CameraMode) -> &mut Self {
792        self.camera_back = Some(camera_back);
793        self
794    }
795
796    /// Set emulation mode for a camera facing front
797    pub fn camera_front(&mut self, camera_front: CameraMode) -> &mut Self {
798        self.camera_front = Some(camera_front);
799        self
800    }
801
802    /// Lists web cameras available for emulation
803    pub fn webcam_list(&mut self, webcam_list: bool) -> &mut Self {
804        self.webcam_list = webcam_list;
805        self
806    }
807
808    /// Load a png or jpeg image as a poster in the virtual scene
809    pub fn virtualscene_poster(&mut self, virtualscene_poster: String) -> &mut Self {
810        self.virtualscene_poster = Some(virtualscene_poster);
811        self
812    }
813
814    /// Set emulated screen mode
815    pub fn screen(&mut self, screen: ScreenMode) -> &mut Self {
816        self.screen = Some(screen);
817        self
818    }
819
820    /// Always use 32-bit emulator
821    pub fn force_32bit(&mut self, force_32bit: bool) -> &mut Self {
822        self.force_32bit = force_32bit;
823        self
824    }
825
826    /// Set SELinux to either disabled or permissive mode
827    pub fn selinux(&mut self, selinux: SELinux) -> &mut Self {
828        self.selinux = Some(selinux);
829        self
830    }
831
832    /// Add <path> to the list of allowed Unix pipes
833    pub fn unix_pipe(&mut self, unix_pipe: &Path) -> &mut Self {
834        self.unix_pipe = Some(unix_pipe.to_owned());
835        self
836    }
837
838    /// Use fixed 1:1 scale for the initial emulator window
839    pub fn fixed_scale(&mut self, fixed_scale: bool) -> &mut Self {
840        self.fixed_scale = fixed_scale;
841        self
842    }
843
844    /// Pause on launch and wait for a debugger process to attach before resuming
845    pub fn wait_for_debugger(&mut self, wait_for_debugger: bool) -> &mut Self {
846        self.wait_for_debugger = wait_for_debugger;
847        self
848    }
849
850    /// Skip adb authentication dialogue
851    pub fn skip_adb_auth(&mut self, skip_adb_auth: bool) -> &mut Self {
852        self.skip_adb_auth = skip_adb_auth;
853        self
854    }
855
856    /// Enable usage metrics and print the messages to stdout
857    pub fn metrics_to_console(&mut self, metrics_to_console: bool) -> &mut Self {
858        self.metrics_to_console = metrics_to_console;
859        self
860    }
861
862    /// Enable usage metrics and send them to google play
863    pub fn metrics_collection(&mut self, metrics_collection: bool) -> &mut Self {
864        self.metrics_collection = metrics_collection;
865        self
866    }
867
868    /// Enable usage metrics and write the messages into specified file
869    pub fn metrics_to_file(&mut self, metrics_to_file: &Path) -> &mut Self {
870        self.metrics_to_file = Some(metrics_to_file.to_owned());
871        self
872    }
873
874    /// Enable the detection of system image hangs
875    pub fn detect_image_hang(&mut self, detect_image_hang: bool) -> &mut Self {
876        self.detect_image_hang = detect_image_hang;
877        self
878    }
879
880    /// Force-enable or disable (-name) the features
881    pub fn feature(&mut self, feature: String) -> &mut Self {
882        self.feature = Some(feature);
883        self
884    }
885
886    /// Use icc profile from specified file
887    pub fn icc_profile(&mut self, icc_profile: &Path) -> &mut Self {
888        self.icc_profile = Some(icc_profile.to_owned());
889        self
890    }
891
892    /// Use SIM access rules from specified file
893    pub fn sim_access_rules_file(&mut self, sim_access_rules_file: &Path) -> &mut Self {
894        self.sim_access_rules_file = Some(sim_access_rules_file.to_owned());
895        self
896    }
897
898    /// Sets the phone number of the emulated device
899    pub fn phone_number(&mut self, phone_number: String) -> &mut Self {
900        self.phone_number = Some(phone_number);
901        self
902    }
903
904    /// Specify acpi device proprerties (hierarchical key=value pair)
905    pub fn acpi_config(&mut self, acpi_config: &Path) -> &mut Self {
906        self.acpi_config = Some(acpi_config.to_owned());
907        self
908    }
909
910    /// Run Fuchsia image. Bypasses android-specific setup; args after are treated
911    /// as standard QEMU args
912    pub fn fuchsia(&mut self, fuchsia: bool) -> &mut Self {
913        self.fuchsia = fuchsia;
914        self
915    }
916
917    /// Set window size for when bypassing android-specific setup
918    pub fn window_size(&mut self, window_size: String) -> &mut Self {
919        self.window_size = Some(window_size);
920        self
921    }
922
923    /// Allows sending of audio from audio input devices. Otherwise, zeroes
924    /// out audio
925    pub fn allow_host_audio(&mut self, allow_host_audio: bool) -> &mut Self {
926        self.allow_host_audio = allow_host_audio;
927        self
928    }
929
930    /// Allows restarting guest when it is stalled
931    pub fn restart_when_stalled(&mut self, restart_when_stalled: bool) -> &mut Self {
932        self.restart_when_stalled = restart_when_stalled;
933        self
934    }
935
936    /// Run periodic perf stat reporter in the background and write output to
937    /// specified file
938    pub fn perf_stat(&mut self, perf_stat: &Path) -> &mut Self {
939        self.perf_stat = Some(perf_stat.to_owned());
940        self
941    }
942
943    /// Share current video state in shared memory region
944    pub fn share_vid(&mut self, share_vid: bool) -> &mut Self {
945        self.share_vid = share_vid;
946        self
947    }
948
949    /// TCP ports used for the gRPC bridge
950    pub fn grpc(&mut self, grpc: String) -> &mut Self {
951        self.grpc = Some(grpc);
952        self
953    }
954
955    /// File with the private key used to enable gRPC TLS
956    pub fn grpc_tls_key(&mut self, grpc_tls_key: &Path) -> &mut Self {
957        self.grpc_tls_key = Some(grpc_tls_key.to_owned());
958        self
959    }
960
961    /// File with the public X509 certificate used to enable gRPC TLS
962    pub fn grpc_tls_cer(&mut self, grpc_tls_cer: &Path) -> &mut Self {
963        self.grpc_tls_cer = Some(grpc_tls_cer.to_owned());
964        self
965    }
966
967    /// File with the Certificate Authorities used to validate client certificates
968    pub fn grpc_tls_ca(&mut self, grpc_tls_ca: &Path) -> &mut Self {
969        self.grpc_tls_ca = Some(grpc_tls_ca.to_owned());
970        self
971    }
972
973    /// Use the emulator console token for gRPC authentication
974    pub fn grpc_use_token(&mut self, grpc_use_token: bool) -> &mut Self {
975        self.grpc_use_token = grpc_use_token;
976        self
977    }
978
979    /// Terminate the emulator if there is no gRPC activity within <timeout> seconds
980    pub fn idle_grpc_timeout(&mut self, idle_grpc_timeout: u32) -> &mut Self {
981        self.idle_grpc_timeout = Some(idle_grpc_timeout);
982        self
983    }
984
985    /// Mode in which to run waterfall
986    pub fn waterfall(&mut self, waterfall: String) -> &mut Self {
987        self.waterfall = Some(waterfall);
988        self
989    }
990
991    /// Config multiple displays
992    pub fn multidisplay(&mut self, multidisplay: String) -> &mut Self {
993        self.multidisplay = Some(multidisplay);
994        self
995    }
996
997    /// API key to use with the Google Maps GUI
998    pub fn google_maps_key(&mut self, google_maps_key: String) -> &mut Self {
999        self.google_maps_key = Some(google_maps_key);
1000        self
1001    }
1002
1003    /// Disable the location UI in the extended window
1004    pub fn no_location_ui(&mut self, no_location_ui: bool) -> &mut Self {
1005        self.no_location_ui = no_location_ui;
1006        self
1007    }
1008
1009    /// Use keycode forwarding instead of host charmap translation
1010    pub fn use_keycode_forwarding(&mut self, use_keycode_forwarding: bool) -> &mut Self {
1011        self.use_keycode_forwarding = use_keycode_forwarding;
1012        self
1013    }
1014
1015    /// Screen record the emulator session
1016    pub fn record_session(&mut self, record_session: &Path) -> &mut Self {
1017        self.record_session = Some(record_session.to_owned());
1018        self
1019    }
1020
1021    /// Use legacy camera HAL for the emulated fake camera
1022    pub fn legacy_fake_camera(&mut self, legacy_fake_camera: bool) -> &mut Self {
1023        self.legacy_fake_camera = legacy_fake_camera;
1024        self
1025    }
1026
1027    /// Disable high qualify edge processing for emulated camera
1028    pub fn no_camera_hq_edge(&mut self, no_camera_hq_edge: bool) -> &mut Self {
1029        self.no_camera_hq_edge = no_camera_hq_edge;
1030        self
1031    }
1032
1033    /// Use external adb executable for internal communication
1034    pub fn no_direct_adb(&mut self, no_direct_adb: bool) -> &mut Self {
1035        self.no_direct_adb = no_direct_adb;
1036        self
1037    }
1038
1039    /// Check if a snasphot is loadable
1040    pub fn check_snapshot_loadable(&mut self, check_snapshot_loadable: String) -> &mut Self {
1041        self.check_snapshot_loadable = Some(check_snapshot_loadable);
1042        self
1043    }
1044
1045    /// Disable HiDPI scaling of guest display on macOS devices
1046    pub fn no_hidpi_scaling(&mut self, no_hidpi_scaling: bool) -> &mut Self {
1047        self.no_hidpi_scaling = no_hidpi_scaling;
1048        self
1049    }
1050
1051    /// Do not reposition the mouse to emulator window center if mouse pointer gets
1052    /// out of the window
1053    pub fn no_mouse_reposition(&mut self, no_mouse_reposition: bool) -> &mut Self {
1054        self.no_mouse_reposition = no_mouse_reposition;
1055        self
1056    }
1057
1058    /// Enable guest ANGLE as system driver
1059    pub fn guest_angle(&mut self, guest_angle: bool) -> &mut Self {
1060        self.guest_angle = guest_angle;
1061        self
1062    }
1063
1064    /// Pass arguments to qemu
1065    pub fn qemu(&mut self, qemu: bool) -> &mut Self {
1066        self.qemu = qemu;
1067        self
1068    }
1069
1070    /// Same as '-debug-init'
1071    pub fn verbose(&mut self, verbose: bool) -> &mut Self {
1072        self.verbose = verbose;
1073        self
1074    }
1075
1076    /// Enable/disable debug messages
1077    pub fn debug(&mut self, debug: DebugTags) -> &mut Self {
1078        self.debug = Some(debug);
1079        self
1080    }
1081
1082    pub fn debug_no(&mut self, debug_no: DebugTags) -> &mut Self {
1083        self.debug_no = Some(debug_no);
1084        self
1085    }
1086
1087    /// Print this help
1088    pub fn help(&mut self, help: bool) -> &mut Self {
1089        self.help = help;
1090        self
1091    }
1092
1093    /// About disk images
1094    pub fn help_disk_images(&mut self, help_disk_images: bool) -> &mut Self {
1095        self.help_disk_images = help_disk_images;
1096        self
1097    }
1098
1099    /// Debug tags for -debug <tags>
1100    pub fn help_debug_tags(&mut self, help_debug_tags: bool) -> &mut Self {
1101        self.help_debug_tags = help_debug_tags;
1102        self
1103    }
1104
1105    /// Character <device> specification
1106    pub fn help_char_devices(&mut self, help_char_devices: bool) -> &mut Self {
1107        self.help_char_devices = help_char_devices;
1108        self
1109    }
1110
1111    /// Environment variables
1112    pub fn help_environment(&mut self, help_environment: bool) -> &mut Self {
1113        self.help_environment = help_environment;
1114        self
1115    }
1116
1117    /// Virtual device management
1118    pub fn help_virtual_device(&mut self, help_virtual_device: bool) -> &mut Self {
1119        self.help_virtual_device = help_virtual_device;
1120        self
1121    }
1122
1123    /// About disk images when using the SDK
1124    pub fn help_sdk_images(&mut self, help_sdk_images: bool) -> &mut Self {
1125        self.help_sdk_images = help_sdk_images;
1126        self
1127    }
1128
1129    /// About disk images when building Android
1130    pub fn help_build_images(&mut self, help_build_images: bool) -> &mut Self {
1131        self.help_build_images = help_build_images;
1132        self
1133    }
1134
1135    /// Prints all help content
1136    pub fn help_all(&mut self, help_all: bool) -> &mut Self {
1137        self.help_all = help_all;
1138        self
1139    }
1140
1141    /// Runs `emulator` commands and initialize emulator
1142    pub fn run(&self) -> Result<()> {
1143        let mut emulator = emulator_tool()?;
1144        if self.list_avds {
1145            emulator.arg("-list-avds");
1146        }
1147        if let Some(sysdir) = &self.sysdir {
1148            emulator.arg("-sysdir").arg(sysdir);
1149        }
1150        if let Some(system) = &self.system {
1151            emulator.arg("-system").arg(system);
1152        }
1153        if let Some(vendor) = &self.vendor {
1154            emulator.arg("-vendor").arg(vendor);
1155        }
1156        if self.writable_system {
1157            emulator.arg("-writable-system");
1158        }
1159        if self.delay_adb {
1160            emulator.arg("-delay-adb");
1161        }
1162        if let Some(datadir) = &self.datadir {
1163            emulator.arg("-datadir").arg(datadir);
1164        }
1165        if let Some(kernel) = &self.kernel {
1166            emulator.arg("-kernel").arg(kernel);
1167        }
1168        if let Some(ramdisk) = &self.ramdisk {
1169            emulator.arg("-ramdisk").arg(ramdisk);
1170        }
1171        if let Some(image) = &self.image {
1172            emulator.arg("-image").arg(image);
1173        }
1174        if let Some(initdata) = &self.initdata {
1175            emulator.arg("-initdata").arg(initdata);
1176        }
1177        if let Some(data) = &self.data {
1178            emulator.arg("-data").arg(data);
1179        }
1180        if let Some(encryption_key) = &self.encryption_key {
1181            emulator.arg("-encryption-key").arg(encryption_key);
1182        }
1183        if let Some(logcat_output) = &self.logcat_output {
1184            emulator.arg("-logcat-output").arg(logcat_output);
1185        }
1186        if let Some(partition_size) = &self.partition_size {
1187            emulator
1188                .arg("-partition-size")
1189                .arg(partition_size.to_string());
1190        }
1191        if let Some(cache) = &self.cache {
1192            emulator.arg("-cache").arg(cache);
1193        }
1194        if let Some(cache_size) = &self.cache_size {
1195            emulator.arg("-cache-size").arg(cache_size.to_string());
1196        }
1197        if self.no_cache {
1198            emulator.arg("-no-cache");
1199        }
1200        if self.nocache {
1201            emulator.arg("-nocache");
1202        }
1203        if let Some(sdcard) = &self.sdcard {
1204            emulator.arg("-sdcard").arg(sdcard);
1205        }
1206        if let Some(quit_after_boot) = &self.quit_after_boot {
1207            emulator
1208                .arg("-quit-after-boot")
1209                .arg(quit_after_boot.to_string());
1210        }
1211        if let Some(qemu_top_dir) = &self.qemu_top_dir {
1212            emulator.arg("-qemu-top-dir").arg(qemu_top_dir);
1213        }
1214        if self.monitor_adb {
1215            emulator.arg("-monitor-adb");
1216        }
1217        if let Some(snapstorage) = &self.snapstorage {
1218            emulator.arg("-snapstorage").arg(snapstorage);
1219        }
1220        if self.no_snapstorage {
1221            emulator.arg("-no-snapstorage");
1222        }
1223        if let Some(snapshot) = &self.snapshot {
1224            emulator.arg("-snapshot").arg(snapshot);
1225        }
1226        if self.no_snapshot {
1227            emulator.arg("-no-snapshot");
1228        }
1229        if self.no_snapshot_save {
1230            emulator.arg("-no-snapshot-save");
1231        }
1232        if self.no_snapshot_load {
1233            emulator.arg("-no-snapshot-load");
1234        }
1235        if self.snapshot_list {
1236            emulator.arg("-snapshot-list");
1237        }
1238        if self.no_snapshot_update_time {
1239            emulator.arg("-no-snapshot-update-time");
1240        }
1241        if self.wipe_data {
1242            emulator.arg("-wipe-data");
1243        }
1244        if let Some(avd) = &self.avd {
1245            emulator.arg("-avd").arg(avd);
1246        }
1247        if let Some(avd_arch) = &self.avd_arch {
1248            emulator.arg("-avd-arch").arg(avd_arch);
1249        }
1250        if let Some(skindir) = &self.skindir {
1251            emulator.arg("-skindir").arg(skindir);
1252        }
1253        if let Some(skin) = &self.skin {
1254            emulator.arg("-skin").arg(skin);
1255        }
1256        if self.no_skin {
1257            emulator.arg("-no-skin");
1258        }
1259        if self.noskin {
1260            emulator.arg("-noskin");
1261        }
1262        if let Some(memory) = &self.memory {
1263            emulator.arg("-memory").arg(memory.to_string());
1264        }
1265        if let Some(ui_only) = &self.ui_only {
1266            emulator.arg("-ui-only").arg(ui_only);
1267        }
1268        if let Some(id) = &self.id {
1269            emulator.arg("-id").arg(id);
1270        }
1271        if let Some(cores) = &self.cores {
1272            emulator.arg("-id").arg(cores.to_string());
1273        }
1274        if let Some(accel) = &self.accel {
1275            emulator.arg("-id").arg(accel.to_string());
1276        }
1277        if self.no_accel {
1278            emulator.arg("-no-accel");
1279        }
1280        if self.ranchu {
1281            emulator.arg("-ranchu");
1282        }
1283        if let Some(engine) = &self.engine {
1284            emulator.arg("-engine").arg(engine.to_string());
1285        }
1286        if let Some(netspeed) = &self.netspeed {
1287            emulator.arg("-netspeed").arg(netspeed.to_string());
1288        }
1289        if let Some(netdelay) = &self.netdelay {
1290            emulator.arg("-netdelay").arg(netdelay);
1291        }
1292        if self.netfast {
1293            emulator.arg("-netfast");
1294        }
1295        if let Some(code_profile) = &self.code_profile {
1296            emulator.arg("-code-profile").arg(code_profile);
1297        }
1298        if self.show_kernel {
1299            emulator.arg("-show-kernel");
1300        }
1301        if self.shell {
1302            emulator.arg("-shell");
1303        }
1304        if self.no_jni {
1305            emulator.arg("-no-jni");
1306        }
1307        if self.nojni {
1308            emulator.arg("-nojni");
1309        }
1310        if self.dalvik_vm_checkjni {
1311            emulator.arg("-dalvik-vm-checkjni");
1312        }
1313        if let Some(logcat) = &self.logcat {
1314            emulator.arg("-logcat").arg(logcat);
1315        }
1316        if self.no_audio {
1317            emulator.arg("-no-audio");
1318        }
1319        if self.noaudio {
1320            emulator.arg("-noaudio");
1321        }
1322        if let Some(audio) = &self.audio {
1323            emulator.arg("-audio").arg(audio);
1324        }
1325        if let Some(radio) = &self.radio {
1326            emulator.arg("-radio").arg(radio);
1327        }
1328        if let Some(port) = &self.port {
1329            emulator.arg("-port").arg(port);
1330        }
1331        if let Some(ports) = &self.ports {
1332            emulator.arg("-ports").arg(
1333                ports
1334                    .iter()
1335                    .map(|v| v.to_string())
1336                    .collect::<Vec<String>>()
1337                    .join(","),
1338            );
1339        }
1340        if let Some(onion) = &self.onion {
1341            emulator.arg("-onion").arg(onion);
1342        }
1343        if let Some(onion_alph) = &self.onion_alph {
1344            emulator.arg("-onion-alpha").arg(onion_alph);
1345        }
1346        if let Some(onion_rotation) = &self.onion_rotation {
1347            emulator.arg("-onion-rotation").arg(onion_rotation);
1348        }
1349        if let Some(dpi_device) = &self.dpi_device {
1350            emulator.arg("-dpi-device").arg(dpi_device);
1351        }
1352        if let Some(scale) = &self.scale {
1353            emulator.arg("-scale").arg(scale);
1354        }
1355        if let Some(wifi_client_port) = &self.wifi_client_port {
1356            emulator.arg("-wifi-client-port").arg(wifi_client_port);
1357        }
1358        if let Some(wifi_server_port) = &self.wifi_server_port {
1359            emulator.arg("-wifi-server-port").arg(wifi_server_port);
1360        }
1361        if let Some(http_proxy) = &self.http_proxy {
1362            emulator.arg("-http-proxy").arg(http_proxy);
1363        }
1364        if let Some(timezone) = &self.timezone {
1365            emulator.arg("-timezone").arg(timezone);
1366        }
1367        if let Some(change_language) = &self.change_language {
1368            emulator.arg("-change-language").arg(change_language);
1369        }
1370        if let Some(change_country) = &self.change_country {
1371            emulator.arg("-change-country").arg(change_country);
1372        }
1373        if let Some(change_locale) = &self.change_locale {
1374            emulator.arg("-change-locale").arg(change_locale);
1375        }
1376        if let Some(dns_server) = &self.dns_server {
1377            emulator.arg("-dns-server").arg(dns_server);
1378        }
1379        if let Some(net_tap) = &self.net_tap {
1380            emulator.arg("-net-tap").arg(net_tap);
1381        }
1382        if let Some(net_tap_script_up) = &self.net_tap_script_up {
1383            emulator.arg("-net-tap-script-up").arg(net_tap_script_up);
1384        }
1385        if let Some(net_tap_script_down) = &self.net_tap_script_down {
1386            emulator
1387                .arg("-net-tap-script-down")
1388                .arg(net_tap_script_down);
1389        }
1390        if let Some(cpu_delay) = &self.cpu_delay {
1391            emulator.arg("-cpu-delay").arg(cpu_delay);
1392        }
1393        if self.no_boot_anim {
1394            emulator.arg("-no-boot-anim");
1395        }
1396        if self.no_window {
1397            emulator.arg("-no-window");
1398        }
1399        if self.qt_hide_window {
1400            emulator.arg("-qt-hide-window");
1401        }
1402        if self.no_sim {
1403            emulator.arg("-no-sim");
1404        }
1405        if self.lowram {
1406            emulator.arg("-lowram");
1407        }
1408        if self.version {
1409            emulator.arg("-version");
1410        }
1411        if self.no_passive_gps {
1412            emulator.arg("-no-passive-gps");
1413        }
1414        if let Some(gnss_file_path) = &self.gnss_file_path {
1415            emulator.arg("-gnss-file-path").arg(gnss_file_path);
1416        }
1417        if let Some(gnss_grpc_port) = &self.gnss_grpc_port {
1418            emulator.arg("-gnss-grpc-port").arg(gnss_grpc_port);
1419        }
1420        if self.virtio_console {
1421            emulator.arg("-virtio-console");
1422        }
1423        if self.read_only {
1424            emulator.arg("-read-only");
1425        }
1426        if let Some(is_restart) = &self.is_restart {
1427            emulator.arg("-is-restart").arg(is_restart);
1428        }
1429        if let Some(report_console) = &self.report_console {
1430            emulator.arg("-report-console").arg(report_console);
1431        }
1432        if let Some(gps) = &self.gps {
1433            emulator.arg("-gps").arg(gps);
1434        }
1435        if let Some(shell_serial) = &self.shell_serial {
1436            emulator.arg("-shell-serial").arg(shell_serial);
1437        }
1438        if let Some(tcpdump) = &self.tcpdump {
1439            emulator.arg("-tcpdump").arg(tcpdump);
1440        }
1441        if let Some(bootchart) = &self.bootchart {
1442            emulator.arg("-bootchart").arg(bootchart);
1443        }
1444        if let Some(charmap) = &self.charmap {
1445            emulator.arg("-charmap").arg(charmap);
1446        }
1447        if let Some(studio_params) = &self.studio_params {
1448            emulator.arg("-studio-params").arg(studio_params);
1449        }
1450        if let Some(prop) = &self.prop {
1451            emulator.arg("-prop").arg(prop);
1452        }
1453        if let Some(shared_net_id) = &self.shared_net_id {
1454            emulator.arg("-shared-net-id").arg(shared_net_id);
1455        }
1456        if let Some(gpu) = &self.gpu {
1457            emulator.arg("-gpu").arg(gpu);
1458        }
1459        if self.use_host_vulkan {
1460            emulator.arg("-use-host-vulkan");
1461        }
1462        if let Some(camera_back) = &self.camera_back {
1463            emulator.arg("-camera-back").arg(camera_back.to_string());
1464        }
1465        if let Some(camera_front) = &self.camera_front {
1466            emulator.arg("-camera-front").arg(camera_front.to_string());
1467        }
1468        if self.webcam_list {
1469            emulator.arg("-webcam-list");
1470        }
1471        if let Some(virtualscene_poster) = &self.virtualscene_poster {
1472            emulator
1473                .arg("-virtualscene-poster")
1474                .arg(virtualscene_poster);
1475        }
1476        if let Some(screen) = &self.screen {
1477            emulator.arg("-screen").arg(screen.to_string());
1478        }
1479        if self.force_32bit {
1480            emulator.arg("-force-32bit");
1481        }
1482        if let Some(selinux) = &self.selinux {
1483            emulator.arg("-selinux").arg(selinux.to_string());
1484        }
1485        if let Some(unix_pipe) = &self.unix_pipe {
1486            emulator.arg("-unix-pipe").arg(unix_pipe);
1487        }
1488        if self.fixed_scale {
1489            emulator.arg("-fixed-scale");
1490        }
1491        if self.wait_for_debugger {
1492            emulator.arg("-wait-for-debugger");
1493        }
1494        if self.skip_adb_auth {
1495            emulator.arg("-skip-adb-auth");
1496        }
1497        if self.metrics_to_console {
1498            emulator.arg("-metrics-to-console");
1499        }
1500        if self.metrics_collection {
1501            emulator.arg("-metrics-collection");
1502        }
1503        if let Some(metrics_to_file) = &self.metrics_to_file {
1504            emulator.arg("-metrics-to-file").arg(metrics_to_file);
1505        }
1506        if self.detect_image_hang {
1507            emulator.arg("-detect-image-hang");
1508        }
1509        if let Some(feature) = &self.feature {
1510            emulator.arg("-feature").arg(feature);
1511        }
1512        if let Some(icc_profile) = &self.icc_profile {
1513            emulator.arg("-icc-profile").arg(icc_profile);
1514        }
1515        if let Some(sim_access_rules_file) = &self.sim_access_rules_file {
1516            emulator
1517                .arg("-sim-access-rules-file")
1518                .arg(sim_access_rules_file);
1519        }
1520        if let Some(phone_number) = &self.phone_number {
1521            emulator.arg("-phone-number").arg(phone_number);
1522        }
1523        if let Some(acpi_config) = &self.acpi_config {
1524            emulator.arg("-acpi-config").arg(acpi_config);
1525        }
1526        if self.fuchsia {
1527            emulator.arg("-fuchsia");
1528        }
1529        if let Some(window_size) = &self.window_size {
1530            emulator.arg("-window-size").arg(window_size);
1531        }
1532        if self.allow_host_audio {
1533            emulator.arg("-allow-host-audio");
1534        }
1535        if self.restart_when_stalled {
1536            emulator.arg("-restart-when-stalled");
1537        }
1538        if let Some(perf_stat) = &self.perf_stat {
1539            emulator.arg("-perf-stat").arg(perf_stat);
1540        }
1541        if self.share_vid {
1542            emulator.arg("-share-vid");
1543        }
1544        if let Some(grpc) = &self.grpc {
1545            emulator.arg("-grpc").arg(grpc);
1546        }
1547        if let Some(grpc_tls_key) = &self.grpc_tls_key {
1548            emulator.arg("-grpc-tls-key").arg(grpc_tls_key);
1549        }
1550        if let Some(grpc_tls_cer) = &self.grpc_tls_cer {
1551            emulator.arg("-grpc-tls-cer").arg(grpc_tls_cer);
1552        }
1553        if let Some(grpc_tls_ca) = &self.grpc_tls_ca {
1554            emulator.arg("-grpc-tls-ca").arg(grpc_tls_ca);
1555        }
1556        if self.grpc_use_token {
1557            emulator.arg("-grpc-use-token");
1558        }
1559        if let Some(idle_grpc_timeout) = &self.idle_grpc_timeout {
1560            emulator
1561                .arg("-idle-grpc-timeout")
1562                .arg(idle_grpc_timeout.to_string());
1563        }
1564        if let Some(waterfall) = &self.waterfall {
1565            emulator.arg("-waterfall").arg(waterfall);
1566        }
1567        if let Some(multidisplay) = &self.multidisplay {
1568            emulator.arg("-multidisplay").arg(multidisplay);
1569        }
1570        if let Some(google_maps_key) = &self.google_maps_key {
1571            emulator.arg("-google-maps-key").arg(google_maps_key);
1572        }
1573        if self.no_location_ui {
1574            emulator.arg("-no-location-ui");
1575        }
1576        if self.use_keycode_forwarding {
1577            emulator.arg("-use-keycode-forwarding");
1578        }
1579        if let Some(record_session) = &self.record_session {
1580            emulator.arg("-record-session").arg(record_session);
1581        }
1582        if self.legacy_fake_camera {
1583            emulator.arg("-legacy-fake-camera");
1584        }
1585        if self.no_camera_hq_edge {
1586            emulator.arg("-no-camera-hq-edge");
1587        }
1588        if self.no_direct_adb {
1589            emulator.arg("-no-direct-adb");
1590        }
1591        if let Some(check_snapshot_loadable) = &self.check_snapshot_loadable {
1592            emulator
1593                .arg("-check-snapshot-loadable")
1594                .arg(check_snapshot_loadable);
1595        }
1596        if self.no_hidpi_scaling {
1597            emulator.arg("-no-hidpi-scaling");
1598        }
1599        if self.no_mouse_reposition {
1600            emulator.arg("-no-mouse-reposition");
1601        }
1602        if self.guest_angle {
1603            emulator.arg("-guest-angle");
1604        }
1605        if self.qemu {
1606            emulator.arg("-qemu");
1607        }
1608        if self.verbose {
1609            emulator.arg("-verbose");
1610        }
1611        if let Some(debug) = &self.debug {
1612            emulator.arg("-debug").arg(debug.to_string());
1613        }
1614        if let Some(debug_no) = &self.debug_no {
1615            emulator.arg(format!("-debug-no-{}", debug_no));
1616        }
1617        if self.help {
1618            emulator.arg("-help");
1619        }
1620        if self.help_disk_images {
1621            emulator.arg("-help-disk-images");
1622        }
1623        if self.help_debug_tags {
1624            emulator.arg("-help-debug-tags");
1625        }
1626        if self.help_debug_tags {
1627            emulator.arg("-help-debug-tags");
1628        }
1629        if self.help_char_devices {
1630            emulator.arg("-help-char-devices");
1631        }
1632        if self.help_environment {
1633            emulator.arg("-help-environment");
1634        }
1635        if self.help_virtual_device {
1636            emulator.arg("-help-virtual-device");
1637        }
1638        if self.help_sdk_images {
1639            emulator.arg("-help-sdk-images");
1640        }
1641        if self.help_build_images {
1642            emulator.arg("-help-build-images");
1643        }
1644        if self.help_all {
1645            emulator.arg("-help-all");
1646        }
1647        emulator.output_err(true)?;
1648        Ok(())
1649    }
1650}