Unite vm_launcher_lib into VmTerminalApp

Bug: 379800648
Test: build and run terminal app
Change-Id: I9ad7d68ec8adc0cb787a70169ea70f32e4bdd3b2
diff --git a/libs/debian_service/proto/DebianService.proto b/libs/debian_service/proto/DebianService.proto
index bf05ebe..61bcece 100644
--- a/libs/debian_service/proto/DebianService.proto
+++ b/libs/debian_service/proto/DebianService.proto
@@ -16,9 +16,9 @@
 
 syntax = "proto3";
 
-package com.android.virtualization.vmlauncher.proto;
+package com.android.virtualization.terminal.proto;
 
-option java_package = "com.android.virtualization.vmlauncher.proto";
+option java_package = "com.android.virtualization.terminal.proto";
 option java_multiple_files = true;
 
 service DebianService {
diff --git a/libs/vm_launcher_lib/Android.bp b/libs/vm_launcher_lib/Android.bp
deleted file mode 100644
index 7dced4e..0000000
--- a/libs/vm_launcher_lib/Android.bp
+++ /dev/null
@@ -1,23 +0,0 @@
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-java_library {
-    name: "vm_launcher_lib",
-    srcs: ["java/**/*.java"],
-    apex_available: [
-        "//apex_available:platform",
-        "com.android.virt",
-    ],
-    platform_apis: true,
-    static_libs: [
-        "gson",
-        "debian-service-grpclib-lite",
-        "apache-commons-compress",
-    ],
-    libs: [
-        "androidx.annotation_annotation",
-        "framework-virtualization.impl",
-        "framework-annotations-lib",
-    ],
-}
diff --git a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/ConfigJson.java b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/ConfigJson.java
deleted file mode 100644
index f229964..0000000
--- a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/ConfigJson.java
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.virtualization.vmlauncher;
-
-import android.content.Context;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.Rect;
-import android.os.Environment;
-import android.system.virtualmachine.VirtualMachineConfig;
-import android.system.virtualmachine.VirtualMachineCustomImageConfig;
-import android.system.virtualmachine.VirtualMachineCustomImageConfig.AudioConfig;
-import android.system.virtualmachine.VirtualMachineCustomImageConfig.Disk;
-import android.system.virtualmachine.VirtualMachineCustomImageConfig.DisplayConfig;
-import android.system.virtualmachine.VirtualMachineCustomImageConfig.GpuConfig;
-import android.system.virtualmachine.VirtualMachineCustomImageConfig.Partition;
-import android.system.virtualmachine.VirtualMachineCustomImageConfig.SharedPath;
-import android.util.DisplayMetrics;
-import android.view.WindowManager;
-import android.view.WindowMetrics;
-
-import com.google.gson.Gson;
-import com.google.gson.annotations.SerializedName;
-
-import java.io.FileReader;
-import java.util.Arrays;
-import java.util.Objects;
-
-/** This class and its inner classes model vm_config.json. */
-class ConfigJson {
-    private static final boolean DEBUG = true;
-
-    private ConfigJson() {}
-
-    @SerializedName("protected")
-    private boolean isProtected;
-
-    private String name;
-    private String cpu_topology;
-    private String platform_version;
-    private int memory_mib = 1024;
-    private String console_input_device;
-    private String bootloader;
-    private String kernel;
-    private String initrd;
-    private String params;
-    private boolean debuggable;
-    private boolean console_out;
-    private boolean connect_console;
-    private boolean network;
-    private InputJson input;
-    private AudioJson audio;
-    private DiskJson[] disks;
-    private SharedPathJson[] sharedPath;
-    private DisplayJson display;
-    private GpuJson gpu;
-
-    /** Parses JSON file at jsonPath */
-    static ConfigJson from(String jsonPath) {
-        try (FileReader r = new FileReader(jsonPath)) {
-            return new Gson().fromJson(r, ConfigJson.class);
-        } catch (Exception e) {
-            throw new RuntimeException("Failed to parse " + jsonPath, e);
-        }
-    }
-
-    private int getCpuTopology() {
-        switch (cpu_topology) {
-            case "one_cpu":
-                return VirtualMachineConfig.CPU_TOPOLOGY_ONE_CPU;
-            case "match_host":
-                return VirtualMachineConfig.CPU_TOPOLOGY_MATCH_HOST;
-            default:
-                throw new RuntimeException("invalid cpu topology: " + cpu_topology);
-        }
-    }
-
-    private int getDebugLevel() {
-        return debuggable
-                ? VirtualMachineConfig.DEBUG_LEVEL_FULL
-                : VirtualMachineConfig.DEBUG_LEVEL_NONE;
-    }
-
-    /** Converts this parsed JSON into VirtualMachieConfig Builder */
-    VirtualMachineConfig.Builder toConfigBuilder(Context context) {
-        return new VirtualMachineConfig.Builder(context)
-                .setProtectedVm(isProtected)
-                .setMemoryBytes((long) memory_mib * 1024 * 1024)
-                .setConsoleInputDevice(console_input_device)
-                .setCpuTopology(getCpuTopology())
-                .setCustomImageConfig(toCustomImageConfigBuilder(context).build())
-                .setDebugLevel(getDebugLevel())
-                .setVmOutputCaptured(console_out)
-                .setConnectVmConsole(connect_console);
-    }
-
-    VirtualMachineCustomImageConfig.Builder toCustomImageConfigBuilder(Context context) {
-        VirtualMachineCustomImageConfig.Builder builder =
-                new VirtualMachineCustomImageConfig.Builder();
-
-        builder.setName(name)
-                .setBootloaderPath(bootloader)
-                .setKernelPath(kernel)
-                .setInitrdPath(initrd)
-                .useNetwork(network);
-
-        if (input != null) {
-            builder.useTouch(input.touchscreen)
-                    .useKeyboard(input.keyboard)
-                    .useMouse(input.mouse)
-                    .useTrackpad(input.trackpad)
-                    .useSwitches(input.switches);
-        }
-
-        if (audio != null) {
-            builder.setAudioConfig(audio.toConfig());
-        }
-
-        if (display != null) {
-            builder.setDisplayConfig(display.toConfig(context));
-        }
-
-        if (gpu != null) {
-            builder.setGpuConfig(gpu.toConfig());
-        }
-
-        if (params != null) {
-            Arrays.stream(params.split(" ")).forEach(builder::addParam);
-        }
-
-        if (disks != null) {
-            Arrays.stream(disks).map(d -> d.toConfig()).forEach(builder::addDisk);
-        }
-
-        if (sharedPath != null) {
-            Arrays.stream(sharedPath)
-                    .map(d -> d.toConfig(context))
-                    .filter(Objects::nonNull)
-                    .forEach(builder::addSharedPath);
-        }
-        return builder;
-    }
-
-    private static class SharedPathJson {
-        private SharedPathJson() {}
-
-        private String sharedPath;
-        private static final int GUEST_UID = 1000;
-        private static final int GUEST_GID = 100;
-
-        private SharedPath toConfig(Context context) {
-            try {
-                int terminalUid = getTerminalUid(context);
-                if (sharedPath.contains("emulated")) {
-                    if (Environment.isExternalStorageManager()) {
-                        int currentUserId = context.getUserId();
-                        String path = sharedPath + "/" + currentUserId + "/Download";
-                        return new SharedPath(
-                                path,
-                                terminalUid,
-                                terminalUid,
-                                GUEST_UID,
-                                GUEST_GID,
-                                0007,
-                                "android",
-                                "android");
-                    }
-                    return null;
-                }
-                return new SharedPath(
-                        sharedPath, terminalUid, terminalUid, 0, 0, 0007, "internal", "internal");
-            } catch (NameNotFoundException e) {
-                return null;
-            }
-        }
-
-        private int getTerminalUid(Context context) throws NameNotFoundException {
-            return context.getPackageManager()
-                    .getPackageUidAsUser(context.getPackageName(), context.getUserId());
-        }
-    }
-
-    private static class InputJson {
-        private InputJson() {}
-
-        private boolean touchscreen;
-        private boolean keyboard;
-        private boolean mouse;
-        private boolean switches;
-        private boolean trackpad;
-    }
-
-    private static class AudioJson {
-        private AudioJson() {}
-
-        private boolean microphone;
-        private boolean speaker;
-
-        private AudioConfig toConfig() {
-            return new AudioConfig.Builder()
-                    .setUseMicrophone(microphone)
-                    .setUseSpeaker(speaker)
-                    .build();
-        }
-    }
-
-    private static class DiskJson {
-        private DiskJson() {}
-
-        private boolean writable;
-        private String image;
-        private PartitionJson[] partitions;
-
-        private Disk toConfig() {
-            Disk d = writable ? Disk.RWDisk(image) : Disk.RODisk(image);
-            for (PartitionJson pj : partitions) {
-                boolean writable = this.writable && pj.writable;
-                d.addPartition(new Partition(pj.label, pj.path, writable, pj.guid));
-            }
-            return d;
-        }
-    }
-
-    private static class PartitionJson {
-        private PartitionJson() {}
-
-        private boolean writable;
-        private String label;
-        private String path;
-        private String guid;
-    }
-
-    private static class DisplayJson {
-        private DisplayJson() {}
-
-        private float scale;
-        private int refresh_rate;
-        private int width_pixels;
-        private int height_pixels;
-
-        private DisplayConfig toConfig(Context context) {
-            WindowManager wm = context.getSystemService(WindowManager.class);
-            WindowMetrics metrics = wm.getCurrentWindowMetrics();
-            Rect dispBounds = metrics.getBounds();
-
-            int width = width_pixels > 0 ? width_pixels : dispBounds.right;
-            int height = height_pixels > 0 ? height_pixels : dispBounds.bottom;
-
-            int dpi = (int) (DisplayMetrics.DENSITY_DEFAULT * metrics.getDensity());
-            if (scale > 0.0f) {
-                dpi = (int) (dpi * scale);
-            }
-
-            int refreshRate = (int) context.getDisplay().getRefreshRate();
-            if (this.refresh_rate != 0) {
-                refreshRate = this.refresh_rate;
-            }
-
-            return new DisplayConfig.Builder()
-                    .setWidth(width)
-                    .setHeight(height)
-                    .setHorizontalDpi(dpi)
-                    .setVerticalDpi(dpi)
-                    .setRefreshRate(refreshRate)
-                    .build();
-        }
-    }
-
-    private static class GpuJson {
-        private GpuJson() {}
-
-        private String backend;
-        private String pci_address;
-        private String renderer_features;
-        private boolean renderer_use_egl = true;
-        private boolean renderer_use_gles = true;
-        private boolean renderer_use_glx = false;
-        private boolean renderer_use_surfaceless = true;
-        private boolean renderer_use_vulkan = false;
-        private String[] context_types;
-
-        private GpuConfig toConfig() {
-            return new GpuConfig.Builder()
-                    .setBackend(backend)
-                    .setPciAddress(pci_address)
-                    .setRendererFeatures(renderer_features)
-                    .setRendererUseEgl(renderer_use_egl)
-                    .setRendererUseGles(renderer_use_gles)
-                    .setRendererUseGlx(renderer_use_glx)
-                    .setRendererUseSurfaceless(renderer_use_surfaceless)
-                    .setRendererUseVulkan(renderer_use_vulkan)
-                    .setContextTypes(context_types)
-                    .build();
-        }
-    }
-}
diff --git a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/DebianServiceImpl.java b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/DebianServiceImpl.java
deleted file mode 100644
index 68ff2ec..0000000
--- a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/DebianServiceImpl.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.virtualization.vmlauncher;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.util.Log;
-
-import androidx.annotation.Keep;
-
-import com.android.virtualization.vmlauncher.proto.DebianServiceGrpc;
-import com.android.virtualization.vmlauncher.proto.ForwardingRequestItem;
-import com.android.virtualization.vmlauncher.proto.IpAddr;
-import com.android.virtualization.vmlauncher.proto.QueueOpeningRequest;
-import com.android.virtualization.vmlauncher.proto.ReportVmActivePortsRequest;
-import com.android.virtualization.vmlauncher.proto.ReportVmActivePortsResponse;
-import com.android.virtualization.vmlauncher.proto.ReportVmIpAddrResponse;
-
-import io.grpc.stub.StreamObserver;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-final class DebianServiceImpl extends DebianServiceGrpc.DebianServiceImplBase {
-    public static final String TAG = "DebianService";
-    private static final String PREFERENCE_FILE_KEY =
-            "com.android.virtualization.terminal.PREFERENCE_FILE_KEY";
-    private static final String PREFERENCE_FORWARDING_PORTS = "PREFERENCE_FORWARDING_PORTS";
-    private static final String PREFERENCE_FORWARDING_PORT_IS_ENABLED_PREFIX =
-            "PREFERENCE_FORWARDING_PORT_IS_ENABLED_";
-
-    private final Context mContext;
-    private final SharedPreferences mSharedPref;
-    private SharedPreferences.OnSharedPreferenceChangeListener mPortForwardingListener;
-    private final DebianServiceCallback mCallback;
-
-
-    static {
-        System.loadLibrary("forwarder_host_jni");
-    }
-
-    DebianServiceImpl(Context context, DebianServiceCallback callback) {
-        super();
-        mCallback = callback;
-        mContext = context;
-        mSharedPref = mContext.getSharedPreferences(PREFERENCE_FILE_KEY, Context.MODE_PRIVATE);
-    }
-
-    @Override
-    public void reportVmActivePorts(
-            ReportVmActivePortsRequest request,
-            StreamObserver<ReportVmActivePortsResponse> responseObserver) {
-        Log.d(DebianServiceImpl.TAG, "reportVmActivePorts: " + request.toString());
-
-        SharedPreferences.Editor editor = mSharedPref.edit();
-        Set<String> ports = new HashSet<>();
-        for (int port : request.getPortsList()) {
-            ports.add(Integer.toString(port));
-            if (!mSharedPref.contains(
-                    PREFERENCE_FORWARDING_PORT_IS_ENABLED_PREFIX + Integer.toString(port))) {
-                editor.putBoolean(
-                        PREFERENCE_FORWARDING_PORT_IS_ENABLED_PREFIX + Integer.toString(port),
-                        false);
-            }
-        }
-        editor.putStringSet(PREFERENCE_FORWARDING_PORTS, ports);
-        editor.apply();
-
-        ReportVmActivePortsResponse reply =
-                ReportVmActivePortsResponse.newBuilder().setSuccess(true).build();
-        responseObserver.onNext(reply);
-        responseObserver.onCompleted();
-    }
-
-    @Override
-    public void reportVmIpAddr(
-            IpAddr request, StreamObserver<ReportVmIpAddrResponse> responseObserver) {
-        Log.d(DebianServiceImpl.TAG, "reportVmIpAddr: " + request.toString());
-        mCallback.onIpAddressAvailable(request.getAddr());
-        ReportVmIpAddrResponse reply = ReportVmIpAddrResponse.newBuilder().setSuccess(true).build();
-        responseObserver.onNext(reply);
-        responseObserver.onCompleted();
-    }
-
-    @Override
-    public void openForwardingRequestQueue(
-            QueueOpeningRequest request, StreamObserver<ForwardingRequestItem> responseObserver) {
-        Log.d(DebianServiceImpl.TAG, "OpenForwardingRequestQueue");
-        mPortForwardingListener =
-                new SharedPreferences.OnSharedPreferenceChangeListener() {
-                    @Override
-                    public void onSharedPreferenceChanged(
-                            SharedPreferences sharedPreferences, String key) {
-                        if (key.startsWith(PREFERENCE_FORWARDING_PORT_IS_ENABLED_PREFIX)
-                                || key.equals(PREFERENCE_FORWARDING_PORTS)) {
-                            updateListeningPorts();
-                        }
-                    }
-                };
-        mSharedPref.registerOnSharedPreferenceChangeListener(mPortForwardingListener);
-        updateListeningPorts();
-        runForwarderHost(request.getCid(), new ForwarderHostCallback(responseObserver));
-        responseObserver.onCompleted();
-    }
-
-    @Keep
-    private static class ForwarderHostCallback {
-        private StreamObserver<ForwardingRequestItem> mResponseObserver;
-
-        ForwarderHostCallback(StreamObserver<ForwardingRequestItem> responseObserver) {
-            mResponseObserver = responseObserver;
-        }
-
-        private void onForwardingRequestReceived(int guestTcpPort, int vsockPort) {
-            ForwardingRequestItem item =
-                    ForwardingRequestItem.newBuilder()
-                            .setGuestTcpPort(guestTcpPort)
-                            .setVsockPort(vsockPort)
-                            .build();
-            mResponseObserver.onNext(item);
-        }
-    }
-
-    private static native void runForwarderHost(int cid, ForwarderHostCallback callback);
-
-    private static native void terminateForwarderHost();
-
-    void killForwarderHost() {
-        Log.d(DebianServiceImpl.TAG, "Stopping port forwarding");
-        if (mPortForwardingListener != null) {
-            mSharedPref.unregisterOnSharedPreferenceChangeListener(mPortForwardingListener);
-            terminateForwarderHost();
-        }
-    }
-
-    private static native void updateListeningPorts(int[] ports);
-
-    private void updateListeningPorts() {
-        updateListeningPorts(
-                mSharedPref
-                        .getStringSet(PREFERENCE_FORWARDING_PORTS, Collections.emptySet())
-                        .stream()
-                        .filter(
-                                port ->
-                                        mSharedPref.getBoolean(
-                                                PREFERENCE_FORWARDING_PORT_IS_ENABLED_PREFIX + port,
-                                                false))
-                        .map(Integer::valueOf)
-                        .mapToInt(Integer::intValue)
-                        .toArray());
-    }
-
-    protected interface DebianServiceCallback {
-        void onIpAddressAvailable(String ipAddr);
-    }
-}
diff --git a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/InstallUtils.java b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/InstallUtils.java
deleted file mode 100644
index 4044fff..0000000
--- a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/InstallUtils.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.virtualization.vmlauncher;
-
-import android.content.Context;
-import android.os.Environment;
-import android.os.FileUtils;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import org.apache.commons.compress.archivers.ArchiveEntry;
-import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
-import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.function.Function;
-
-public class InstallUtils {
-    private static final String TAG = InstallUtils.class.getSimpleName();
-
-    private static final String VM_CONFIG_FILENAME = "vm_config.json";
-    private static final String COMPRESSED_PAYLOAD_FILENAME = "images.tar.gz";
-    private static final String ROOTFS_FILENAME = "root_part";
-    private static final String BACKUP_FILENAME = "root_part_backup";
-    private static final String INSTALLATION_COMPLETED_FILENAME = "completed";
-    private static final String PAYLOAD_DIR = "linux";
-
-    public static String getVmConfigPath(Context context) {
-        return getInternalStorageDir(context).toPath().resolve(VM_CONFIG_FILENAME).toString();
-    }
-
-    public static boolean isImageInstalled(Context context) {
-        return Files.exists(getInstallationCompletedPath(context));
-    }
-
-    public static void backupRootFs(Context context) throws IOException {
-        Files.move(
-                getRootfsFile(context).toPath(),
-                getBackupFile(context).toPath(),
-                StandardCopyOption.REPLACE_EXISTING);
-    }
-
-    public static boolean createInstalledMarker(Context context) {
-        try {
-            File file = new File(getInstallationCompletedPath(context).toString());
-            return file.createNewFile();
-        } catch (IOException e) {
-            Log.e(TAG, "Failed to mark install completed", e);
-            return false;
-        }
-    }
-
-    @VisibleForTesting
-    public static void deleteInstallation(Context context) {
-        FileUtils.deleteContentsAndDir(getInternalStorageDir(context));
-    }
-
-    private static Path getPayloadPath() {
-        File payloadDir = Environment.getExternalStoragePublicDirectory(PAYLOAD_DIR);
-        if (payloadDir == null) {
-            Log.d(TAG, "no payload dir: " + payloadDir);
-            return null;
-        }
-        Path payloadPath = payloadDir.toPath().resolve(COMPRESSED_PAYLOAD_FILENAME);
-        return payloadPath;
-    }
-
-    public static boolean payloadFromExternalStorageExists() {
-        return Files.exists(getPayloadPath());
-    }
-
-    public static File getInternalStorageDir(Context context) {
-        return new File(context.getFilesDir(), PAYLOAD_DIR);
-    }
-
-    public static File getBackupFile(Context context) {
-        return new File(context.getFilesDir(), BACKUP_FILENAME);
-    }
-
-    private static Path getInstallationCompletedPath(Context context) {
-        return getInternalStorageDir(context).toPath().resolve(INSTALLATION_COMPLETED_FILENAME);
-    }
-
-    public static boolean installImageFromExternalStorage(Context context) {
-        if (!payloadFromExternalStorageExists()) {
-            Log.d(TAG, "no artifact file from external storage");
-            return false;
-        }
-        Path payloadPath = getPayloadPath();
-        try (BufferedInputStream inputStream =
-                        new BufferedInputStream(Files.newInputStream(payloadPath));
-                TarArchiveInputStream tar =
-                        new TarArchiveInputStream(new GzipCompressorInputStream(inputStream))) {
-            ArchiveEntry entry;
-            Path baseDir = new File(context.getFilesDir(), PAYLOAD_DIR).toPath();
-            Files.createDirectories(baseDir);
-            while ((entry = tar.getNextEntry()) != null) {
-                Path extractTo = baseDir.resolve(entry.getName());
-                if (entry.isDirectory()) {
-                    Files.createDirectories(extractTo);
-                } else {
-                    Files.copy(tar, extractTo, StandardCopyOption.REPLACE_EXISTING);
-                }
-            }
-        } catch (IOException e) {
-            Log.e(TAG, "installation failed", e);
-            return false;
-        }
-        if (!resolvePathInVmConfig(context)) {
-            Log.d(TAG, "resolving path failed");
-            try {
-                Files.deleteIfExists(Path.of(getVmConfigPath(context)));
-            } catch (IOException e) {
-                return false;
-            }
-            return false;
-        }
-
-        // remove payload if installation is done.
-        try {
-            Files.deleteIfExists(payloadPath);
-        } catch (IOException e) {
-            Log.d(TAG, "failed to remove installed payload", e);
-        }
-
-        // Create marker for installation done.
-        return createInstalledMarker(context);
-    }
-
-    private static Function<String, String> getReplacer(Context context) {
-        Map<String, String> rules = new HashMap<>();
-        rules.put("\\$PAYLOAD_DIR", new File(context.getFilesDir(), PAYLOAD_DIR).toString());
-        rules.put("\\$USER_ID", String.valueOf(context.getUserId()));
-        rules.put("\\$PACKAGE_NAME", context.getPackageName());
-        String appDataDir = context.getDataDir().toString();
-        // TODO: remove this hack
-        if (context.getUserId() == 0) {
-            appDataDir = "/data/data/" + context.getPackageName();
-        }
-        rules.put("\\$APP_DATA_DIR", appDataDir);
-        return (s) -> {
-            for (Map.Entry<String, String> rule : rules.entrySet()) {
-                s = s.replaceAll(rule.getKey(), rule.getValue());
-            }
-            return s;
-        };
-    }
-
-    public static boolean resolvePathInVmConfig(Context context) {
-        try {
-            String replacedVmConfig =
-                    String.join(
-                            "\n",
-                            Files.readAllLines(Path.of(getVmConfigPath(context))).stream()
-                                    .map(getReplacer(context))
-                                    .toList());
-            Files.write(Path.of(getVmConfigPath(context)), replacedVmConfig.getBytes());
-            return true;
-        } catch (IOException e) {
-            return false;
-        }
-    }
-
-    public static File getRootfsFile(Context context) throws FileNotFoundException {
-        File file = new File(getInternalStorageDir(context), ROOTFS_FILENAME);
-        if (!file.exists()) {
-            Log.d(TAG, file.getAbsolutePath() + " - file not found");
-            throw new FileNotFoundException("File not found: " + ROOTFS_FILENAME);
-        }
-        return file;
-    }
-}
diff --git a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/Logger.java b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/Logger.java
deleted file mode 100644
index e1cb285..0000000
--- a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/Logger.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.virtualization.vmlauncher;
-
-import android.system.virtualmachine.VirtualMachine;
-import android.system.virtualmachine.VirtualMachineConfig;
-import android.system.virtualmachine.VirtualMachineException;
-import android.util.Log;
-
-import libcore.io.Streams;
-
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
-import java.util.concurrent.ExecutorService;
-
-/**
- * Forwards VM's console output to a file on the Android side, and VM's log output to Android logd.
- */
-class Logger {
-    private Logger() {}
-
-    static void setup(VirtualMachine vm, Path path, ExecutorService executor) {
-        if (vm.getConfig().getDebugLevel() != VirtualMachineConfig.DEBUG_LEVEL_FULL) {
-            return;
-        }
-
-        try {
-            InputStream console = vm.getConsoleOutput();
-            OutputStream file = Files.newOutputStream(path, StandardOpenOption.CREATE);
-            executor.submit(() -> Streams.copy(console, new LineBufferedOutputStream(file)));
-
-            InputStream log = vm.getLogOutput();
-            executor.submit(() -> writeToLogd(log, vm.getName()));
-        } catch (VirtualMachineException | IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private static boolean writeToLogd(InputStream input, String vmName) throws IOException {
-        BufferedReader reader = new BufferedReader(new InputStreamReader(input));
-        String line;
-        while ((line = reader.readLine()) != null && !Thread.interrupted()) {
-            Log.d(vmName, line);
-        }
-        // TODO: find out why javac complains when the return type of this method is void. It
-        // (incorrectly?) thinks that IOException should be caught inside the lambda.
-        return true;
-    }
-
-    private static class LineBufferedOutputStream extends BufferedOutputStream {
-        LineBufferedOutputStream(OutputStream out) {
-            super(out);
-        }
-
-        @Override
-        public void write(byte[] buf, int off, int len) throws IOException {
-            super.write(buf, off, len);
-            for (int i = 0; i < len; ++i) {
-                if (buf[off + i] == '\n') {
-                    flush();
-                    break;
-                }
-            }
-        }
-    }
-}
diff --git a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/Runner.java b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/Runner.java
deleted file mode 100644
index 9b97fee..0000000
--- a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/Runner.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.virtualization.vmlauncher;
-
-import android.content.Context;
-import android.system.virtualmachine.VirtualMachine;
-import android.system.virtualmachine.VirtualMachineCallback;
-import android.system.virtualmachine.VirtualMachineConfig;
-import android.system.virtualmachine.VirtualMachineCustomImageConfig;
-import android.system.virtualmachine.VirtualMachineException;
-import android.system.virtualmachine.VirtualMachineManager;
-import android.util.Log;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ForkJoinPool;
-
-/** Utility class for creating a VM and waiting for it to finish. */
-class Runner {
-    private static final String TAG = Runner.class.getSimpleName();
-    private final VirtualMachine mVirtualMachine;
-    private final Callback mCallback;
-
-    private Runner(VirtualMachine vm, Callback cb) {
-        mVirtualMachine = vm;
-        mCallback = cb;
-    }
-
-    /** Create a virtual machine of the given config, under the given context. */
-    static Runner create(Context context, VirtualMachineConfig config)
-            throws VirtualMachineException {
-        // context may already be the app context, but calling this again is not harmful.
-        // See b/359439878 on why vmm should be obtained from the app context.
-        Context appContext = context.getApplicationContext();
-        VirtualMachineManager vmm = appContext.getSystemService(VirtualMachineManager.class);
-        VirtualMachineCustomImageConfig customConfig = config.getCustomImageConfig();
-        if (customConfig == null) {
-            throw new RuntimeException("CustomImageConfig is missing");
-        }
-
-        String name = customConfig.getName();
-        if (name == null || name.isEmpty()) {
-            throw new RuntimeException("Virtual machine's name is missing in the config");
-        }
-
-        VirtualMachine vm = vmm.getOrCreate(name, config);
-        try {
-            vm.setConfig(config);
-        } catch (VirtualMachineException e) {
-            vmm.delete(name);
-            vm = vmm.create(name, config);
-            Log.w(TAG, "Re-creating virtual machine (" + name + ")", e);
-        }
-
-        Callback cb = new Callback();
-        vm.setCallback(ForkJoinPool.commonPool(), cb);
-        vm.run();
-        return new Runner(vm, cb);
-    }
-
-    /** Give access to the underlying VirtualMachine object. */
-    VirtualMachine getVm() {
-        return mVirtualMachine;
-    }
-
-    /** Get future about VM's exit status. */
-    CompletableFuture<Boolean> getExitStatus() {
-        return mCallback.mFinishedSuccessfully;
-    }
-
-    private static class Callback implements VirtualMachineCallback {
-        final CompletableFuture<Boolean> mFinishedSuccessfully = new CompletableFuture<>();
-
-        @Override
-        public void onPayloadStarted(VirtualMachine vm) {
-            // This event is only from Microdroid-based VM. Custom VM shouldn't emit this.
-        }
-
-        @Override
-        public void onPayloadReady(VirtualMachine vm) {
-            // This event is only from Microdroid-based VM. Custom VM shouldn't emit this.
-        }
-
-        @Override
-        public void onPayloadFinished(VirtualMachine vm, int exitCode) {
-            // This event is only from Microdroid-based VM. Custom VM shouldn't emit this.
-        }
-
-        @Override
-        public void onError(VirtualMachine vm, int errorCode, String message) {
-            Log.e(TAG, "Error from VM. code: " + errorCode + " (" + message + ")");
-            mFinishedSuccessfully.complete(false);
-        }
-
-        @Override
-        public void onStopped(VirtualMachine vm, int reason) {
-            Log.d(TAG, "VM stopped. Reason: " + reason);
-            mFinishedSuccessfully.complete(true);
-        }
-    }
-}
diff --git a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/VmLauncherService.java b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/VmLauncherService.java
deleted file mode 100644
index 1eb558e..0000000
--- a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/VmLauncherService.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.virtualization.vmlauncher;
-
-import android.app.Notification;
-import android.app.Service;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.ResultReceiver;
-import android.system.virtualmachine.VirtualMachine;
-import android.system.virtualmachine.VirtualMachineConfig;
-import android.system.virtualmachine.VirtualMachineCustomImageConfig;
-import android.system.virtualmachine.VirtualMachineCustomImageConfig.Disk;
-import android.system.virtualmachine.VirtualMachineException;
-import android.util.Log;
-
-import io.grpc.Grpc;
-import io.grpc.InsecureServerCredentials;
-import io.grpc.Metadata;
-import io.grpc.Server;
-import io.grpc.ServerCall;
-import io.grpc.ServerCallHandler;
-import io.grpc.ServerInterceptor;
-import io.grpc.Status;
-import io.grpc.okhttp.OkHttpServerBuilder;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.nio.file.Path;
-import java.util.Objects;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-public class VmLauncherService extends Service implements DebianServiceImpl.DebianServiceCallback {
-    public static final String EXTRA_NOTIFICATION = "EXTRA_NOTIFICATION";
-    private static final String TAG = "VmLauncherService";
-
-    private static final int RESULT_START = 0;
-    private static final int RESULT_STOP = 1;
-    private static final int RESULT_ERROR = 2;
-    private static final int RESULT_IPADDR = 3;
-    private static final String KEY_VM_IP_ADDR = "ip_addr";
-
-    private ExecutorService mExecutorService;
-    private VirtualMachine mVirtualMachine;
-    private ResultReceiver mResultReceiver;
-    private Server mServer;
-    private DebianServiceImpl mDebianService;
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return null;
-    }
-
-    private void startForeground(Notification notification) {
-        startForeground(this.hashCode(), notification);
-    }
-
-    @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
-        if (Objects.equals(
-                intent.getAction(), VmLauncherServices.ACTION_STOP_VM_LAUNCHER_SERVICE)) {
-            stopSelf();
-            return START_NOT_STICKY;
-        }
-        if (mVirtualMachine != null) {
-            Log.d(TAG, "VM instance is already started");
-            return START_NOT_STICKY;
-        }
-        mExecutorService = Executors.newCachedThreadPool();
-
-        ConfigJson json = ConfigJson.from(InstallUtils.getVmConfigPath(this));
-        VirtualMachineConfig.Builder configBuilder = json.toConfigBuilder(this);
-        VirtualMachineCustomImageConfig.Builder customImageConfigBuilder =
-                json.toCustomImageConfigBuilder(this);
-        File backupFile = InstallUtils.getBackupFile(this);
-        if (backupFile.exists()) {
-            customImageConfigBuilder.addDisk(Disk.RWDisk(backupFile.getPath()));
-            configBuilder.setCustomImageConfig(customImageConfigBuilder.build());
-        }
-        VirtualMachineConfig config = configBuilder.build();
-
-        Runner runner;
-        try {
-            android.os.Trace.beginSection("vmCreate");
-            runner = Runner.create(this, config);
-            android.os.Trace.endSection();
-            android.os.Trace.beginAsyncSection("debianBoot", 0);
-        } catch (VirtualMachineException e) {
-            Log.e(TAG, "cannot create runner", e);
-            stopSelf();
-            return START_NOT_STICKY;
-        }
-        mVirtualMachine = runner.getVm();
-        mResultReceiver =
-                intent.getParcelableExtra(Intent.EXTRA_RESULT_RECEIVER, ResultReceiver.class);
-
-        runner.getExitStatus()
-                .thenAcceptAsync(
-                        success -> {
-                            if (mResultReceiver != null) {
-                                mResultReceiver.send(success ? RESULT_STOP : RESULT_ERROR, null);
-                            }
-                            stopSelf();
-                        });
-        Path logPath = getFileStreamPath(mVirtualMachine.getName() + ".log").toPath();
-        Logger.setup(mVirtualMachine, logPath, mExecutorService);
-
-        Notification notification = intent.getParcelableExtra(EXTRA_NOTIFICATION,
-                Notification.class);
-
-        startForeground(notification);
-
-        mResultReceiver.send(RESULT_START, null);
-
-        startDebianServer();
-
-        return START_NOT_STICKY;
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        stopDebianServer();
-        if (mVirtualMachine != null) {
-            if (mVirtualMachine.getStatus() == VirtualMachine.STATUS_RUNNING) {
-                try {
-                    mVirtualMachine.stop();
-                    stopForeground(STOP_FOREGROUND_REMOVE);
-                } catch (VirtualMachineException e) {
-                    Log.e(TAG, "failed to stop a VM instance", e);
-                }
-            }
-            mExecutorService.shutdownNow();
-            mExecutorService = null;
-            mVirtualMachine = null;
-        }
-    }
-
-    private void startDebianServer() {
-        ServerInterceptor interceptor =
-                new ServerInterceptor() {
-                    @Override
-                    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
-                            ServerCall<ReqT, RespT> call,
-                            Metadata headers,
-                            ServerCallHandler<ReqT, RespT> next) {
-                        // Refer to VirtualizationSystemService.TetheringService
-                        final String VM_STATIC_IP_ADDR = "192.168.0.2";
-                        InetSocketAddress remoteAddr =
-                                (InetSocketAddress)
-                                        call.getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR);
-
-                        if (remoteAddr != null
-                                && Objects.equals(
-                                        remoteAddr.getAddress().getHostAddress(),
-                                        VM_STATIC_IP_ADDR)) {
-                            // Allow the request only if it is from VM
-                            return next.startCall(call, headers);
-                        }
-                        Log.d(TAG, "blocked grpc request from " + remoteAddr);
-                        call.close(Status.Code.PERMISSION_DENIED.toStatus(), new Metadata());
-                        return new ServerCall.Listener<ReqT>() {};
-                    }
-                };
-        try {
-            // TODO(b/372666638): gRPC for java doesn't support vsock for now.
-            int port = 0;
-            mDebianService = new DebianServiceImpl(this, this);
-            mServer =
-                    OkHttpServerBuilder.forPort(port, InsecureServerCredentials.create())
-                            .intercept(interceptor)
-                            .addService(mDebianService)
-                            .build()
-                            .start();
-        } catch (IOException e) {
-            Log.d(TAG, "grpc server error", e);
-            return;
-        }
-
-        mExecutorService.execute(
-                () -> {
-                    // TODO(b/373533555): we can use mDNS for that.
-                    String debianServicePortFileName = "debian_service_port";
-                    File debianServicePortFile = new File(getFilesDir(), debianServicePortFileName);
-                    try (FileOutputStream writer = new FileOutputStream(debianServicePortFile)) {
-                        writer.write(String.valueOf(mServer.getPort()).getBytes());
-                    } catch (IOException e) {
-                        Log.d(TAG, "cannot write grpc port number", e);
-                    }
-                });
-    }
-
-    private void stopDebianServer() {
-        if (mDebianService != null) {
-            mDebianService.killForwarderHost();
-        }
-        if (mServer != null) {
-            mServer.shutdown();
-        }
-    }
-
-    @Override
-    public void onIpAddressAvailable(String ipAddr) {
-        android.os.Trace.endAsyncSection("debianBoot", 0);
-        Bundle b = new Bundle();
-        b.putString(VmLauncherService.KEY_VM_IP_ADDR, ipAddr);
-        mResultReceiver.send(VmLauncherService.RESULT_IPADDR, b);
-    }
-}
diff --git a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/VmLauncherServices.java b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/VmLauncherServices.java
deleted file mode 100644
index 6eca2b3..0000000
--- a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/VmLauncherServices.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.virtualization.vmlauncher;
-
-import android.app.Notification;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Parcel;
-import android.os.ResultReceiver;
-import android.util.Log;
-
-import java.util.List;
-
-public class VmLauncherServices {
-    private static final String TAG = "VmLauncherServices";
-
-    private static final String ACTION_START_VM_LAUNCHER_SERVICE =
-            "android.virtualization.START_VM_LAUNCHER_SERVICE";
-
-    public static final String ACTION_STOP_VM_LAUNCHER_SERVICE =
-            "android.virtualization.STOP_VM_LAUNCHER_SERVICE";
-    private static final int RESULT_START = 0;
-    private static final int RESULT_STOP = 1;
-    private static final int RESULT_ERROR = 2;
-    private static final int RESULT_IPADDR = 3;
-    private static final String KEY_VM_IP_ADDR = "ip_addr";
-
-    private static Intent buildVmLauncherServiceIntent(Context context) {
-        Intent i = new Intent();
-        i.setAction(ACTION_START_VM_LAUNCHER_SERVICE);
-
-        Intent intent = new Intent(ACTION_START_VM_LAUNCHER_SERVICE);
-        PackageManager pm = context.getPackageManager();
-        List<ResolveInfo> resolveInfos =
-                pm.queryIntentServices(intent, PackageManager.MATCH_DEFAULT_ONLY);
-        if (resolveInfos == null || resolveInfos.size() != 1) {
-            Log.e(TAG, "cannot find a service to handle ACTION_START_VM_LAUNCHER_SERVICE");
-            return null;
-        }
-        String packageName = resolveInfos.get(0).serviceInfo.packageName;
-
-        i.setPackage(packageName);
-        return i;
-    }
-
-    public static void stopVmLauncherService(Context context) {
-        Intent i = buildVmLauncherServiceIntent(context);
-        context.stopService(i);
-    }
-
-    public static void startVmLauncherService(Context context, VmLauncherServiceCallback callback,
-            Notification notification) {
-        Intent i = buildVmLauncherServiceIntent(context);
-        if (i == null) {
-            return;
-        }
-        ResultReceiver resultReceiver =
-                new ResultReceiver(new Handler(Looper.myLooper())) {
-                    @Override
-                    protected void onReceiveResult(int resultCode, Bundle resultData) {
-                        if (callback == null) {
-                            return;
-                        }
-                        switch (resultCode) {
-                            case RESULT_START:
-                                callback.onVmStart();
-                                return;
-                            case RESULT_STOP:
-                                callback.onVmStop();
-                                return;
-                            case RESULT_ERROR:
-                                callback.onVmError();
-                                return;
-                            case RESULT_IPADDR:
-                                callback.onIpAddrAvailable(resultData.getString(KEY_VM_IP_ADDR));
-                                return;
-                        }
-                    }
-                };
-        i.putExtra(Intent.EXTRA_RESULT_RECEIVER, getResultReceiverForIntent(resultReceiver));
-        i.putExtra(VmLauncherService.EXTRA_NOTIFICATION, notification);
-        context.startForegroundService(i);
-    }
-
-    public interface VmLauncherServiceCallback {
-        void onVmStart();
-
-        void onVmStop();
-
-        void onVmError();
-
-        void onIpAddrAvailable(String ipAddr);
-    }
-
-    private static ResultReceiver getResultReceiverForIntent(ResultReceiver r) {
-        Parcel parcel = Parcel.obtain();
-        r.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        r = ResultReceiver.CREATOR.createFromParcel(parcel);
-        parcel.recycle();
-        return r;
-    }
-}