• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.system.virtualmachine;
18 
19 import android.annotation.Nullable;
20 import android.os.PersistableBundle;
21 
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.Optional;
25 
26 /** @hide */
27 public class VirtualMachineCustomImageConfig {
28     private static final String KEY_NAME = "name";
29     private static final String KEY_KERNEL = "kernel";
30     private static final String KEY_INITRD = "initrd";
31     private static final String KEY_BOOTLOADER = "bootloader";
32     private static final String KEY_PARAMS = "params";
33     private static final String KEY_DISK_WRITABLES = "disk_writables";
34     private static final String KEY_DISK_IMAGES = "disk_images";
35     private static final String KEY_PARTITION_LABELS = "partition_labels_";
36     private static final String KEY_PARTITION_IMAGES = "partition_images_";
37     private static final String KEY_PARTITION_WRITABLES = "partition_writables_";
38     private static final String KEY_PARTITION_GUIDS = "partition_guids_";
39     private static final String KEY_DISPLAY_CONFIG = "display_config";
40     private static final String KEY_TOUCH = "touch";
41     private static final String KEY_KEYBOARD = "keyboard";
42     private static final String KEY_MOUSE = "mouse";
43     private static final String KEY_SWITCHES = "switches";
44     private static final String KEY_NETWORK = "network";
45     private static final String KEY_GPU = "gpu";
46     private static final String KEY_AUDIO_CONFIG = "audio_config";
47     private static final String KEY_TRACKPAD = "trackpad";
48     private static final String KEY_AUTO_MEMORY_BALLOON = "auto_memory_balloon";
49     private static final String KEY_USB_CONFIG = "usb_config";
50 
51     @Nullable private final String name;
52     @Nullable private final String kernelPath;
53     @Nullable private final String initrdPath;
54     @Nullable private final String bootloaderPath;
55     @Nullable private final String[] params;
56     @Nullable private final Disk[] disks;
57     @Nullable private final SharedPath[] sharedPaths;
58     @Nullable private final DisplayConfig displayConfig;
59     @Nullable private final AudioConfig audioConfig;
60     private final boolean touch;
61     private final boolean keyboard;
62     private final boolean mouse;
63     private final boolean switches;
64     private final boolean network;
65     @Nullable private final GpuConfig gpuConfig;
66     private final boolean trackpad;
67     private final boolean autoMemoryBalloon;
68     @Nullable private final UsbConfig usbConfig;
69 
70     @Nullable
getDisks()71     public Disk[] getDisks() {
72         return disks;
73     }
74 
75     @Nullable
getBootloaderPath()76     public String getBootloaderPath() {
77         return bootloaderPath;
78     }
79 
80     @Nullable
getInitrdPath()81     public String getInitrdPath() {
82         return initrdPath;
83     }
84 
85     @Nullable
getKernelPath()86     public String getKernelPath() {
87         return kernelPath;
88     }
89 
90     @Nullable
getName()91     public String getName() {
92         return name;
93     }
94 
95     @Nullable
getParams()96     public String[] getParams() {
97         return params;
98     }
99 
100     @Nullable
getSharedPaths()101     public SharedPath[] getSharedPaths() {
102         return sharedPaths;
103     }
104 
useTouch()105     public boolean useTouch() {
106         return touch;
107     }
108 
useKeyboard()109     public boolean useKeyboard() {
110         return keyboard;
111     }
112 
useMouse()113     public boolean useMouse() {
114         return mouse;
115     }
116 
useSwitches()117     public boolean useSwitches() {
118         return switches;
119     }
120 
useTrackpad()121     public boolean useTrackpad() {
122         return mouse;
123     }
124 
useAutoMemoryBalloon()125     public boolean useAutoMemoryBalloon() {
126         return autoMemoryBalloon;
127     }
128 
useNetwork()129     public boolean useNetwork() {
130         return network;
131     }
132 
133     /** @hide */
VirtualMachineCustomImageConfig( String name, String kernelPath, String initrdPath, String bootloaderPath, String[] params, Disk[] disks, SharedPath[] sharedPaths, DisplayConfig displayConfig, boolean touch, boolean keyboard, boolean mouse, boolean switches, boolean network, GpuConfig gpuConfig, AudioConfig audioConfig, boolean trackpad, boolean autoMemoryBalloon, UsbConfig usbConfig)134     public VirtualMachineCustomImageConfig(
135             String name,
136             String kernelPath,
137             String initrdPath,
138             String bootloaderPath,
139             String[] params,
140             Disk[] disks,
141             SharedPath[] sharedPaths,
142             DisplayConfig displayConfig,
143             boolean touch,
144             boolean keyboard,
145             boolean mouse,
146             boolean switches,
147             boolean network,
148             GpuConfig gpuConfig,
149             AudioConfig audioConfig,
150             boolean trackpad,
151             boolean autoMemoryBalloon,
152             UsbConfig usbConfig) {
153         this.name = name;
154         this.kernelPath = kernelPath;
155         this.initrdPath = initrdPath;
156         this.bootloaderPath = bootloaderPath;
157         this.params = params;
158         this.disks = disks;
159         this.sharedPaths = sharedPaths;
160         this.displayConfig = displayConfig;
161         this.touch = touch;
162         this.keyboard = keyboard;
163         this.mouse = mouse;
164         this.switches = switches;
165         this.network = network;
166         this.gpuConfig = gpuConfig;
167         this.audioConfig = audioConfig;
168         this.trackpad = trackpad;
169         this.autoMemoryBalloon = autoMemoryBalloon;
170         this.usbConfig = usbConfig;
171     }
172 
from(PersistableBundle customImageConfigBundle)173     static VirtualMachineCustomImageConfig from(PersistableBundle customImageConfigBundle) {
174         Builder builder = new Builder();
175         builder.setName(customImageConfigBundle.getString(KEY_NAME));
176         builder.setKernelPath(customImageConfigBundle.getString(KEY_KERNEL));
177         builder.setInitrdPath(customImageConfigBundle.getString(KEY_INITRD));
178         builder.setBootloaderPath(customImageConfigBundle.getString(KEY_BOOTLOADER));
179         String[] params = customImageConfigBundle.getStringArray(KEY_PARAMS);
180         if (params != null) {
181             for (String param : params) {
182                 builder.addParam(param);
183             }
184         }
185         boolean[] writables = customImageConfigBundle.getBooleanArray(KEY_DISK_WRITABLES);
186         String[] diskImages = customImageConfigBundle.getStringArray(KEY_DISK_IMAGES);
187         if (writables != null && diskImages != null) {
188             if (writables.length == diskImages.length) {
189                 for (int i = 0; i < writables.length; i++) {
190                     String diskImage = diskImages[i];
191                     diskImage = diskImage.equals("") ? null : diskImage;
192                     Disk disk = writables[i] ? Disk.RWDisk(diskImage) : Disk.RODisk(diskImage);
193                     String[] labels =
194                             customImageConfigBundle.getStringArray(KEY_PARTITION_LABELS + i);
195                     String[] images =
196                             customImageConfigBundle.getStringArray(KEY_PARTITION_IMAGES + i);
197                     boolean[] partitionWritables =
198                             customImageConfigBundle.getBooleanArray(KEY_PARTITION_WRITABLES + i);
199                     String[] guids =
200                             customImageConfigBundle.getStringArray(KEY_PARTITION_GUIDS + i);
201                     for (int j = 0; j < labels.length; j++) {
202                         disk.addPartition(
203                                 new Partition(
204                                         labels[j], images[j], partitionWritables[j], guids[j]));
205                     }
206                     builder.addDisk(disk);
207                 }
208             }
209         }
210         PersistableBundle displayConfigPb =
211                 customImageConfigBundle.getPersistableBundle(KEY_DISPLAY_CONFIG);
212         builder.setDisplayConfig(DisplayConfig.from(displayConfigPb));
213         builder.useTouch(customImageConfigBundle.getBoolean(KEY_TOUCH));
214         builder.useKeyboard(customImageConfigBundle.getBoolean(KEY_KEYBOARD));
215         builder.useMouse(customImageConfigBundle.getBoolean(KEY_MOUSE));
216         builder.useNetwork(customImageConfigBundle.getBoolean(KEY_NETWORK));
217         builder.setGpuConfig(GpuConfig.from(customImageConfigBundle.getPersistableBundle(KEY_GPU)));
218         PersistableBundle audioConfigPb =
219                 customImageConfigBundle.getPersistableBundle(KEY_AUDIO_CONFIG);
220         builder.setAudioConfig(AudioConfig.from(audioConfigPb));
221         builder.useTrackpad(customImageConfigBundle.getBoolean(KEY_TRACKPAD));
222         builder.useAutoMemoryBalloon(customImageConfigBundle.getBoolean(KEY_AUTO_MEMORY_BALLOON));
223         PersistableBundle usbConfigPb =
224                 customImageConfigBundle.getPersistableBundle(KEY_USB_CONFIG);
225         builder.setUsbConfig(UsbConfig.from(usbConfigPb));
226         return builder.build();
227     }
228 
toPersistableBundle()229     PersistableBundle toPersistableBundle() {
230         PersistableBundle pb = new PersistableBundle();
231         pb.putString(KEY_NAME, this.name);
232         pb.putString(KEY_KERNEL, this.kernelPath);
233         pb.putString(KEY_BOOTLOADER, this.bootloaderPath);
234         pb.putString(KEY_INITRD, this.initrdPath);
235         pb.putStringArray(KEY_PARAMS, this.params);
236 
237         if (disks != null) {
238             boolean[] writables = new boolean[disks.length];
239             String[] images = new String[disks.length];
240             for (int i = 0; i < disks.length; i++) {
241                 writables[i] = disks[i].writable;
242                 String imagePath = disks[i].imagePath;
243                 images[i] = imagePath == null ? "" : imagePath;
244 
245                 int numPartitions = disks[i].getPartitions().size();
246                 String[] partitionLabels = new String[numPartitions];
247                 String[] partitionImages = new String[numPartitions];
248                 boolean[] partitionWritables = new boolean[numPartitions];
249                 String[] partitionGuids = new String[numPartitions];
250 
251                 for (int j = 0; j < numPartitions; j++) {
252                     Partition p = disks[i].getPartitions().get(j);
253                     partitionLabels[j] = p.name;
254                     partitionImages[j] = p.imagePath;
255                     partitionWritables[j] = p.writable;
256                     partitionGuids[j] = p.guid == null ? "" : p.guid;
257                 }
258                 pb.putStringArray(KEY_PARTITION_LABELS + i, partitionLabels);
259                 pb.putStringArray(KEY_PARTITION_IMAGES + i, partitionImages);
260                 pb.putBooleanArray(KEY_PARTITION_WRITABLES + i, partitionWritables);
261                 pb.putStringArray(KEY_PARTITION_GUIDS + i, partitionGuids);
262             }
263             pb.putBooleanArray(KEY_DISK_WRITABLES, writables);
264             pb.putStringArray(KEY_DISK_IMAGES, images);
265         }
266         pb.putPersistableBundle(
267                 KEY_DISPLAY_CONFIG,
268                 Optional.ofNullable(displayConfig)
269                         .map(dc -> dc.toPersistableBundle())
270                         .orElse(null));
271         pb.putBoolean(KEY_TOUCH, touch);
272         pb.putBoolean(KEY_KEYBOARD, keyboard);
273         pb.putBoolean(KEY_MOUSE, mouse);
274         pb.putBoolean(KEY_SWITCHES, switches);
275         pb.putBoolean(KEY_NETWORK, network);
276         pb.putPersistableBundle(
277                 KEY_GPU,
278                 Optional.ofNullable(gpuConfig).map(gc -> gc.toPersistableBundle()).orElse(null));
279         pb.putPersistableBundle(
280                 KEY_AUDIO_CONFIG,
281                 Optional.ofNullable(audioConfig).map(ac -> ac.toPersistableBundle()).orElse(null));
282         pb.putBoolean(KEY_TRACKPAD, trackpad);
283         pb.putBoolean(KEY_AUTO_MEMORY_BALLOON, autoMemoryBalloon);
284         pb.putPersistableBundle(
285                 KEY_USB_CONFIG,
286                 Optional.ofNullable(usbConfig).map(uc -> uc.toPersistableBundle()).orElse(null));
287         return pb;
288     }
289 
290     @Nullable
getAudioConfig()291     public AudioConfig getAudioConfig() {
292         return audioConfig;
293     }
294 
295     @Nullable
getDisplayConfig()296     public DisplayConfig getDisplayConfig() {
297         return displayConfig;
298     }
299 
300     @Nullable
getGpuConfig()301     public GpuConfig getGpuConfig() {
302         return gpuConfig;
303     }
304 
305     @Nullable
getUsbConfig()306     public UsbConfig getUsbConfig() {
307         return usbConfig;
308     }
309 
310     /** @hide */
311     public static final class SharedPath {
312         private final String path;
313         private final int hostUid;
314         private final int hostGid;
315         private final int guestUid;
316         private final int guestGid;
317         private final int mask;
318         private final String tag;
319         private final String socket;
320         private final boolean appDomain;
321         private final String socketPath;
322 
SharedPath( String path, int hostUid, int hostGid, int guestUid, int guestGid, int mask, String tag, String socket, boolean appDomain, String socketPath)323         public SharedPath(
324                 String path,
325                 int hostUid,
326                 int hostGid,
327                 int guestUid,
328                 int guestGid,
329                 int mask,
330                 String tag,
331                 String socket,
332                 boolean appDomain,
333                 String socketPath) {
334             this.path = path;
335             this.hostUid = hostUid;
336             this.hostGid = hostGid;
337             this.guestUid = guestUid;
338             this.guestGid = guestGid;
339             this.mask = mask;
340             this.tag = tag;
341             this.socket = socket;
342             this.appDomain = appDomain;
343             this.socketPath = socketPath;
344         }
345 
toParcelable()346         android.system.virtualizationservice.SharedPath toParcelable() {
347             android.system.virtualizationservice.SharedPath parcelable =
348                     new android.system.virtualizationservice.SharedPath();
349             parcelable.sharedPath = this.path;
350             parcelable.hostUid = this.hostUid;
351             parcelable.hostGid = this.hostGid;
352             parcelable.guestUid = this.guestUid;
353             parcelable.guestGid = this.guestGid;
354             parcelable.mask = this.mask;
355             parcelable.tag = this.tag;
356             parcelable.socketPath = this.socket;
357             parcelable.appDomain = this.appDomain;
358             return parcelable;
359         }
360 
361         /** @hide */
getSharedPath()362         public String getSharedPath() {
363             return path;
364         }
365 
366         /** @hide */
getHostUid()367         public int getHostUid() {
368             return hostUid;
369         }
370 
371         /** @hide */
getHostGid()372         public int getHostGid() {
373             return hostGid;
374         }
375 
376         /** @hide */
getGuestUid()377         public int getGuestUid() {
378             return guestUid;
379         }
380 
381         /** @hide */
getGuestGid()382         public int getGuestGid() {
383             return guestGid;
384         }
385 
386         /** @hide */
getMask()387         public int getMask() {
388             return mask;
389         }
390 
391         /** @hide */
getTag()392         public String getTag() {
393             return tag;
394         }
395 
396         /** @hide */
getSocket()397         public String getSocket() {
398             return socket;
399         }
400 
401         /** @hide */
getAppDomain()402         public boolean getAppDomain() {
403             return appDomain;
404         }
405 
406         /** @hide */
getSocketPath()407         public String getSocketPath() {
408             return socketPath;
409         }
410     }
411 
412     /** @hide */
413     public static final class Disk {
414         private final boolean writable;
415         private final String imagePath;
416         private final List<Partition> partitions;
417 
Disk(boolean writable, String imagePath)418         private Disk(boolean writable, String imagePath) {
419             this.writable = writable;
420             this.imagePath = imagePath;
421             this.partitions = new ArrayList<>();
422         }
423 
424         /** @hide */
RWDisk(String imagePath)425         public static Disk RWDisk(String imagePath) {
426             return new Disk(true, imagePath);
427         }
428 
429         /** @hide */
RODisk(String imagePath)430         public static Disk RODisk(String imagePath) {
431             return new Disk(false, imagePath);
432         }
433 
434         /** @hide */
isWritable()435         public boolean isWritable() {
436             return writable;
437         }
438 
439         /** @hide */
getImagePath()440         public String getImagePath() {
441             return imagePath;
442         }
443 
444         /** @hide */
addPartition(Partition p)445         public Disk addPartition(Partition p) {
446             this.partitions.add(p);
447             return this;
448         }
449 
450         /** @hide */
getPartitions()451         public List<Partition> getPartitions() {
452             return partitions;
453         }
454     }
455 
456     /** @hide */
457     public static final class Partition {
458         public final String name;
459         public final String imagePath;
460         public final boolean writable;
461         public final String guid;
462 
Partition(String name, String imagePath, boolean writable, String guid)463         public Partition(String name, String imagePath, boolean writable, String guid) {
464             this.name = name;
465             this.imagePath = imagePath;
466             this.writable = writable;
467             this.guid = guid;
468         }
469     }
470 
471     /** @hide */
472     public static final class Builder {
473         private String name;
474         private String kernelPath;
475         private String initrdPath;
476         private String bootloaderPath;
477         private List<String> params = new ArrayList<>();
478         private List<Disk> disks = new ArrayList<>();
479         private List<SharedPath> sharedPaths = new ArrayList<>();
480         private AudioConfig audioConfig;
481         private DisplayConfig displayConfig;
482         private boolean touch;
483         private boolean keyboard;
484         private boolean mouse;
485         private boolean switches;
486         private boolean network;
487         private GpuConfig gpuConfig;
488         private boolean trackpad;
489         private boolean autoMemoryBalloon = false;
490         private UsbConfig usbConfig;
491 
492         /** @hide */
Builder()493         public Builder() {}
494 
495         /** @hide */
setName(String name)496         public Builder setName(String name) {
497             this.name = name;
498             return this;
499         }
500 
501         /** @hide */
setKernelPath(String kernelPath)502         public Builder setKernelPath(String kernelPath) {
503             this.kernelPath = kernelPath;
504             return this;
505         }
506 
507         /** @hide */
setBootloaderPath(String bootloaderPath)508         public Builder setBootloaderPath(String bootloaderPath) {
509             this.bootloaderPath = bootloaderPath;
510             return this;
511         }
512 
513         /** @hide */
setInitrdPath(String initrdPath)514         public Builder setInitrdPath(String initrdPath) {
515             this.initrdPath = initrdPath;
516             return this;
517         }
518 
519         /** @hide */
addDisk(Disk disk)520         public Builder addDisk(Disk disk) {
521             this.disks.add(disk);
522             return this;
523         }
524 
525         /** @hide */
addSharedPath(SharedPath path)526         public Builder addSharedPath(SharedPath path) {
527             this.sharedPaths.add(path);
528             return this;
529         }
530 
531         /** @hide */
addParam(String param)532         public Builder addParam(String param) {
533             this.params.add(param);
534             return this;
535         }
536 
537         /** @hide */
setDisplayConfig(DisplayConfig displayConfig)538         public Builder setDisplayConfig(DisplayConfig displayConfig) {
539             this.displayConfig = displayConfig;
540             return this;
541         }
542 
543         /** @hide */
setGpuConfig(GpuConfig gpuConfig)544         public Builder setGpuConfig(GpuConfig gpuConfig) {
545             this.gpuConfig = gpuConfig;
546             return this;
547         }
548 
549         /** @hide */
useTouch(boolean touch)550         public Builder useTouch(boolean touch) {
551             this.touch = touch;
552             return this;
553         }
554 
555         /** @hide */
useKeyboard(boolean keyboard)556         public Builder useKeyboard(boolean keyboard) {
557             this.keyboard = keyboard;
558             return this;
559         }
560 
561         /** @hide */
useMouse(boolean mouse)562         public Builder useMouse(boolean mouse) {
563             this.mouse = mouse;
564             return this;
565         }
566 
567         /** @hide */
useSwitches(boolean switches)568         public Builder useSwitches(boolean switches) {
569             this.switches = switches;
570             return this;
571         }
572 
573         /** @hide */
useTrackpad(boolean trackpad)574         public Builder useTrackpad(boolean trackpad) {
575             this.trackpad = trackpad;
576             return this;
577         }
578 
579         /** @hide */
useAutoMemoryBalloon(boolean autoMemoryBalloon)580         public Builder useAutoMemoryBalloon(boolean autoMemoryBalloon) {
581             this.autoMemoryBalloon = autoMemoryBalloon;
582             return this;
583         }
584 
585         /** @hide */
useNetwork(boolean network)586         public Builder useNetwork(boolean network) {
587             this.network = network;
588             return this;
589         }
590 
591         /** @hide */
setAudioConfig(AudioConfig audioConfig)592         public Builder setAudioConfig(AudioConfig audioConfig) {
593             this.audioConfig = audioConfig;
594             return this;
595         }
596 
597         /** @hide */
setUsbConfig(UsbConfig usbConfig)598         public Builder setUsbConfig(UsbConfig usbConfig) {
599             this.usbConfig = usbConfig;
600             return this;
601         }
602 
603         /** @hide */
build()604         public VirtualMachineCustomImageConfig build() {
605             return new VirtualMachineCustomImageConfig(
606                     this.name,
607                     this.kernelPath,
608                     this.initrdPath,
609                     this.bootloaderPath,
610                     this.params.toArray(new String[0]),
611                     this.disks.toArray(new Disk[0]),
612                     this.sharedPaths.toArray(new SharedPath[0]),
613                     displayConfig,
614                     touch,
615                     keyboard,
616                     mouse,
617                     switches,
618                     network,
619                     gpuConfig,
620                     audioConfig,
621                     trackpad,
622                     autoMemoryBalloon,
623                     usbConfig);
624         }
625     }
626 
627     /** @hide */
628     public static final class UsbConfig {
629         private static final String KEY_USE_CONTROLLER = "use_controller";
630         public final boolean controller;
631 
UsbConfig(boolean controller)632         public UsbConfig(boolean controller) {
633             this.controller = controller;
634         }
635 
getUsbController()636         public boolean getUsbController() {
637             return this.controller;
638         }
639 
toParceclable()640         android.system.virtualizationservice.UsbConfig toParceclable() {
641             android.system.virtualizationservice.UsbConfig parcelable =
642                     new android.system.virtualizationservice.UsbConfig();
643             parcelable.controller = this.controller;
644             return parcelable;
645         }
646 
from(PersistableBundle pb)647         private static UsbConfig from(PersistableBundle pb) {
648             if (pb == null) {
649                 return null;
650             }
651             Builder builder = new Builder();
652             builder.setController(pb.getBoolean(KEY_USE_CONTROLLER));
653             return builder.build();
654         }
655 
toPersistableBundle()656         private PersistableBundle toPersistableBundle() {
657             PersistableBundle pb = new PersistableBundle();
658             pb.putBoolean(KEY_USE_CONTROLLER, this.controller);
659             return pb;
660         }
661 
662         /** @hide */
663         public static class Builder {
664             private boolean useController = false;
665 
666             /** @hide */
Builder()667             public Builder() {}
668 
669             /** @hide */
setController(boolean useController)670             public Builder setController(boolean useController) {
671                 this.useController = useController;
672                 return this;
673             }
674 
675             /** @hide */
build()676             public UsbConfig build() {
677                 return new UsbConfig(useController);
678             }
679         }
680     }
681 
682     /** @hide */
683     public static final class AudioConfig {
684         private static final String KEY_USE_MICROPHONE = "use_microphone";
685         private static final String KEY_USE_SPEAKER = "use_speaker";
686         private final boolean useMicrophone;
687         private final boolean useSpeaker;
688 
AudioConfig(boolean useMicrophone, boolean useSpeaker)689         private AudioConfig(boolean useMicrophone, boolean useSpeaker) {
690             this.useMicrophone = useMicrophone;
691             this.useSpeaker = useSpeaker;
692         }
693 
694         /** @hide */
useMicrophone()695         public boolean useMicrophone() {
696             return useMicrophone;
697         }
698 
699         /** @hide */
useSpeaker()700         public boolean useSpeaker() {
701             return useSpeaker;
702         }
703 
toParcelable()704         android.system.virtualizationservice.AudioConfig toParcelable() {
705             android.system.virtualizationservice.AudioConfig parcelable =
706                     new android.system.virtualizationservice.AudioConfig();
707             parcelable.useSpeaker = this.useSpeaker;
708             parcelable.useMicrophone = this.useMicrophone;
709 
710             return parcelable;
711         }
712 
from(PersistableBundle pb)713         private static AudioConfig from(PersistableBundle pb) {
714             if (pb == null) {
715                 return null;
716             }
717             Builder builder = new Builder();
718             builder.setUseMicrophone(pb.getBoolean(KEY_USE_MICROPHONE));
719             builder.setUseSpeaker(pb.getBoolean(KEY_USE_SPEAKER));
720             return builder.build();
721         }
722 
toPersistableBundle()723         private PersistableBundle toPersistableBundle() {
724             PersistableBundle pb = new PersistableBundle();
725             pb.putBoolean(KEY_USE_MICROPHONE, this.useMicrophone);
726             pb.putBoolean(KEY_USE_SPEAKER, this.useSpeaker);
727             return pb;
728         }
729 
730         /** @hide */
731         public static class Builder {
732             private boolean useMicrophone = false;
733             private boolean useSpeaker = false;
734 
735             /** @hide */
Builder()736             public Builder() {}
737 
738             /** @hide */
setUseMicrophone(boolean useMicrophone)739             public Builder setUseMicrophone(boolean useMicrophone) {
740                 this.useMicrophone = useMicrophone;
741                 return this;
742             }
743 
744             /** @hide */
setUseSpeaker(boolean useSpeaker)745             public Builder setUseSpeaker(boolean useSpeaker) {
746                 this.useSpeaker = useSpeaker;
747                 return this;
748             }
749 
750             /** @hide */
build()751             public AudioConfig build() {
752                 return new AudioConfig(useMicrophone, useSpeaker);
753             }
754         }
755     }
756 
757     /** @hide */
758     public static final class DisplayConfig {
759         private static final String KEY_WIDTH = "width";
760         private static final String KEY_HEIGHT = "height";
761         private static final String KEY_HORIZONTAL_DPI = "horizontal_dpi";
762         private static final String KEY_VERTICAL_DPI = "vertical_dpi";
763         private static final String KEY_REFRESH_RATE = "refresh_rate";
764         private final int width;
765         private final int height;
766         private final int horizontalDpi;
767         private final int verticalDpi;
768         private final int refreshRate;
769 
DisplayConfig( int width, int height, int horizontalDpi, int verticalDpi, int refreshRate)770         private DisplayConfig(
771                 int width, int height, int horizontalDpi, int verticalDpi, int refreshRate) {
772             this.width = width;
773             this.height = height;
774             this.horizontalDpi = horizontalDpi;
775             this.verticalDpi = verticalDpi;
776             this.refreshRate = refreshRate;
777         }
778 
779         /** @hide */
getWidth()780         public int getWidth() {
781             return width;
782         }
783 
784         /** @hide */
getHeight()785         public int getHeight() {
786             return height;
787         }
788 
789         /** @hide */
getHorizontalDpi()790         public int getHorizontalDpi() {
791             return horizontalDpi;
792         }
793 
794         /** @hide */
getVerticalDpi()795         public int getVerticalDpi() {
796             return verticalDpi;
797         }
798 
799         /** @hide */
getRefreshRate()800         public int getRefreshRate() {
801             return refreshRate;
802         }
803 
toParcelable()804         android.system.virtualizationservice.DisplayConfig toParcelable() {
805             android.system.virtualizationservice.DisplayConfig parcelable =
806                     new android.system.virtualizationservice.DisplayConfig();
807             parcelable.width = this.width;
808             parcelable.height = this.height;
809             parcelable.horizontalDpi = this.horizontalDpi;
810             parcelable.verticalDpi = this.verticalDpi;
811             parcelable.refreshRate = this.refreshRate;
812 
813             return parcelable;
814         }
815 
from(PersistableBundle pb)816         private static DisplayConfig from(PersistableBundle pb) {
817             if (pb == null) {
818                 return null;
819             }
820             Builder builder = new Builder();
821             builder.setWidth(pb.getInt(KEY_WIDTH));
822             builder.setHeight(pb.getInt(KEY_HEIGHT));
823             builder.setHorizontalDpi(pb.getInt(KEY_HORIZONTAL_DPI));
824             builder.setVerticalDpi(pb.getInt(KEY_VERTICAL_DPI));
825             builder.setRefreshRate(pb.getInt(KEY_REFRESH_RATE));
826             return builder.build();
827         }
828 
toPersistableBundle()829         private PersistableBundle toPersistableBundle() {
830             PersistableBundle pb = new PersistableBundle();
831             pb.putInt(KEY_WIDTH, this.width);
832             pb.putInt(KEY_HEIGHT, this.height);
833             pb.putInt(KEY_HORIZONTAL_DPI, this.horizontalDpi);
834             pb.putInt(KEY_VERTICAL_DPI, this.verticalDpi);
835             pb.putInt(KEY_REFRESH_RATE, this.refreshRate);
836             return pb;
837         }
838 
839         /** @hide */
840         public static class Builder {
841             // Default values come from external/crosvm/vm_control/src/gpu.rs
842             private int width;
843             private int height;
844             private int horizontalDpi = 320;
845             private int verticalDpi = 320;
846             private int refreshRate = 60;
847 
848             /** @hide */
Builder()849             public Builder() {}
850 
851             /** @hide */
setWidth(int width)852             public Builder setWidth(int width) {
853                 this.width = width;
854                 return this;
855             }
856 
857             /** @hide */
setHeight(int height)858             public Builder setHeight(int height) {
859                 this.height = height;
860                 return this;
861             }
862 
863             /** @hide */
setHorizontalDpi(int horizontalDpi)864             public Builder setHorizontalDpi(int horizontalDpi) {
865                 this.horizontalDpi = horizontalDpi;
866                 return this;
867             }
868 
869             /** @hide */
setVerticalDpi(int verticalDpi)870             public Builder setVerticalDpi(int verticalDpi) {
871                 this.verticalDpi = verticalDpi;
872                 return this;
873             }
874 
875             /** @hide */
setRefreshRate(int refreshRate)876             public Builder setRefreshRate(int refreshRate) {
877                 this.refreshRate = refreshRate;
878                 return this;
879             }
880 
881             /** @hide */
build()882             public DisplayConfig build() {
883                 if (this.width == 0 || this.height == 0) {
884                     throw new IllegalStateException("width and height must be specified");
885                 }
886                 return new DisplayConfig(width, height, horizontalDpi, verticalDpi, refreshRate);
887             }
888         }
889     }
890 
891     /** @hide */
892     public static final class GpuConfig {
893         private static final String KEY_BACKEND = "backend";
894         private static final String KEY_CONTEXT_TYPES = "context_types";
895         private static final String KEY_PCI_ADDRESS = "pci_address";
896         private static final String KEY_RENDERER_FEATURES = "renderer_features";
897         private static final String KEY_RENDERER_USE_EGL = "renderer_use_egl";
898         private static final String KEY_RENDERER_USE_GLES = "renderer_use_gles";
899         private static final String KEY_RENDERER_USE_GLX = "renderer_use_glx";
900         private static final String KEY_RENDERER_USE_SURFACELESS = "renderer_use_surfaceless";
901         private static final String KEY_RENDERER_USE_VULKAN = "renderer_use_vulkan";
902 
903         private final String backend;
904         private final String[] contextTypes;
905         private final String pciAddress;
906         private final String rendererFeatures;
907         private final boolean rendererUseEgl;
908         private final boolean rendererUseGles;
909         private final boolean rendererUseGlx;
910         private final boolean rendererUseSurfaceless;
911         private final boolean rendererUseVulkan;
912 
GpuConfig( String backend, String[] contextTypes, String pciAddress, String rendererFeatures, boolean rendererUseEgl, boolean rendererUseGles, boolean rendererUseGlx, boolean rendererUseSurfaceless, boolean rendererUseVulkan)913         private GpuConfig(
914                 String backend,
915                 String[] contextTypes,
916                 String pciAddress,
917                 String rendererFeatures,
918                 boolean rendererUseEgl,
919                 boolean rendererUseGles,
920                 boolean rendererUseGlx,
921                 boolean rendererUseSurfaceless,
922                 boolean rendererUseVulkan) {
923             this.backend = backend;
924             this.contextTypes = contextTypes;
925             this.pciAddress = pciAddress;
926             this.rendererFeatures = rendererFeatures;
927             this.rendererUseEgl = rendererUseEgl;
928             this.rendererUseGles = rendererUseGles;
929             this.rendererUseGlx = rendererUseGlx;
930             this.rendererUseSurfaceless = rendererUseSurfaceless;
931             this.rendererUseVulkan = rendererUseVulkan;
932         }
933 
934         /** @hide */
getBackend()935         public String getBackend() {
936             return backend;
937         }
938 
939         /** @hide */
getContextTypes()940         public String[] getContextTypes() {
941             return contextTypes;
942         }
943 
944         /** @hide */
getPciAddress()945         public String getPciAddress() {
946             return pciAddress;
947         }
948 
949         /** @hide */
getRendererFeatures()950         public String getRendererFeatures() {
951             return rendererFeatures;
952         }
953 
954         /** @hide */
getRendererUseEgl()955         public boolean getRendererUseEgl() {
956             return rendererUseEgl;
957         }
958 
959         /** @hide */
getRendererUseGles()960         public boolean getRendererUseGles() {
961             return rendererUseGles;
962         }
963 
964         /** @hide */
getRendererUseGlx()965         public boolean getRendererUseGlx() {
966             return rendererUseGlx;
967         }
968 
969         /** @hide */
getRendererUseSurfaceless()970         public boolean getRendererUseSurfaceless() {
971             return rendererUseSurfaceless;
972         }
973 
974         /** @hide */
getRendererUseVulkan()975         public boolean getRendererUseVulkan() {
976             return rendererUseVulkan;
977         }
978 
toParcelable()979         android.system.virtualizationservice.GpuConfig toParcelable() {
980             android.system.virtualizationservice.GpuConfig parcelable =
981                     new android.system.virtualizationservice.GpuConfig();
982             parcelable.backend = this.backend;
983             parcelable.contextTypes = this.contextTypes;
984             parcelable.pciAddress = this.pciAddress;
985             parcelable.rendererFeatures = this.rendererFeatures;
986             parcelable.rendererUseEgl = this.rendererUseEgl;
987             parcelable.rendererUseGles = this.rendererUseGles;
988             parcelable.rendererUseGlx = this.rendererUseGlx;
989             parcelable.rendererUseSurfaceless = this.rendererUseSurfaceless;
990             parcelable.rendererUseVulkan = this.rendererUseVulkan;
991             return parcelable;
992         }
993 
from(PersistableBundle pb)994         private static GpuConfig from(PersistableBundle pb) {
995             if (pb == null) {
996                 return null;
997             }
998             Builder builder = new Builder();
999             builder.setBackend(pb.getString(KEY_BACKEND));
1000             builder.setContextTypes(pb.getStringArray(KEY_CONTEXT_TYPES));
1001             builder.setPciAddress(pb.getString(KEY_PCI_ADDRESS));
1002             builder.setRendererFeatures(pb.getString(KEY_RENDERER_FEATURES));
1003             builder.setRendererUseEgl(pb.getBoolean(KEY_RENDERER_USE_EGL));
1004             builder.setRendererUseGles(pb.getBoolean(KEY_RENDERER_USE_GLES));
1005             builder.setRendererUseGlx(pb.getBoolean(KEY_RENDERER_USE_GLX));
1006             builder.setRendererUseSurfaceless(pb.getBoolean(KEY_RENDERER_USE_SURFACELESS));
1007             builder.setRendererUseVulkan(pb.getBoolean(KEY_RENDERER_USE_VULKAN));
1008             return builder.build();
1009         }
1010 
toPersistableBundle()1011         private PersistableBundle toPersistableBundle() {
1012             PersistableBundle pb = new PersistableBundle();
1013             pb.putString(KEY_BACKEND, this.backend);
1014             pb.putStringArray(KEY_CONTEXT_TYPES, this.contextTypes);
1015             pb.putString(KEY_PCI_ADDRESS, this.pciAddress);
1016             pb.putString(KEY_RENDERER_FEATURES, this.rendererFeatures);
1017             pb.putBoolean(KEY_RENDERER_USE_EGL, this.rendererUseEgl);
1018             pb.putBoolean(KEY_RENDERER_USE_GLES, this.rendererUseGles);
1019             pb.putBoolean(KEY_RENDERER_USE_GLX, this.rendererUseGlx);
1020             pb.putBoolean(KEY_RENDERER_USE_SURFACELESS, this.rendererUseSurfaceless);
1021             pb.putBoolean(KEY_RENDERER_USE_VULKAN, this.rendererUseVulkan);
1022             return pb;
1023         }
1024 
1025         /** @hide */
1026         public static class Builder {
1027             private String backend;
1028             private String[] contextTypes;
1029             private String pciAddress;
1030             private String rendererFeatures;
1031             private boolean rendererUseEgl = true;
1032             private boolean rendererUseGles = true;
1033             private boolean rendererUseGlx = false;
1034             private boolean rendererUseSurfaceless = true;
1035             private boolean rendererUseVulkan = false;
1036 
1037             /** @hide */
Builder()1038             public Builder() {}
1039 
1040             /** @hide */
setBackend(String backend)1041             public Builder setBackend(String backend) {
1042                 this.backend = backend;
1043                 return this;
1044             }
1045 
1046             /** @hide */
setContextTypes(String[] contextTypes)1047             public Builder setContextTypes(String[] contextTypes) {
1048                 this.contextTypes = contextTypes;
1049                 return this;
1050             }
1051 
1052             /** @hide */
setPciAddress(String pciAddress)1053             public Builder setPciAddress(String pciAddress) {
1054                 this.pciAddress = pciAddress;
1055                 return this;
1056             }
1057 
1058             /** @hide */
setRendererFeatures(String rendererFeatures)1059             public Builder setRendererFeatures(String rendererFeatures) {
1060                 this.rendererFeatures = rendererFeatures;
1061                 return this;
1062             }
1063 
1064             /** @hide */
setRendererUseEgl(Boolean rendererUseEgl)1065             public Builder setRendererUseEgl(Boolean rendererUseEgl) {
1066                 this.rendererUseEgl = rendererUseEgl;
1067                 return this;
1068             }
1069 
1070             /** @hide */
setRendererUseGles(Boolean rendererUseGles)1071             public Builder setRendererUseGles(Boolean rendererUseGles) {
1072                 this.rendererUseGles = rendererUseGles;
1073                 return this;
1074             }
1075 
1076             /** @hide */
setRendererUseGlx(Boolean rendererUseGlx)1077             public Builder setRendererUseGlx(Boolean rendererUseGlx) {
1078                 this.rendererUseGlx = rendererUseGlx;
1079                 return this;
1080             }
1081 
1082             /** @hide */
setRendererUseSurfaceless(Boolean rendererUseSurfaceless)1083             public Builder setRendererUseSurfaceless(Boolean rendererUseSurfaceless) {
1084                 this.rendererUseSurfaceless = rendererUseSurfaceless;
1085                 return this;
1086             }
1087 
1088             /** @hide */
setRendererUseVulkan(Boolean rendererUseVulkan)1089             public Builder setRendererUseVulkan(Boolean rendererUseVulkan) {
1090                 this.rendererUseVulkan = rendererUseVulkan;
1091                 return this;
1092             }
1093 
1094             /** @hide */
build()1095             public GpuConfig build() {
1096                 return new GpuConfig(
1097                         backend,
1098                         contextTypes,
1099                         pciAddress,
1100                         rendererFeatures,
1101                         rendererUseEgl,
1102                         rendererUseGles,
1103                         rendererUseGlx,
1104                         rendererUseSurfaceless,
1105                         rendererUseVulkan);
1106             }
1107         }
1108     }
1109 }
1110