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