Skeleton for IVmTethering service with flag guarding

This reverts commit f9676878292a49caa03e5270c3be2769b029db60.

Bug: 340376953
Test: adb shell /apex/com.android.virt/bin/vm run-microdroid --network-supported

Change-Id: I9c859dd43e7ba7c852a71afce8f36ca10477ad24
diff --git a/Android.bp b/Android.bp
index 3b6b8b5..b2af69e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -77,6 +77,7 @@
     config_namespace: "ANDROID",
     bool_variables: [
         "release_avf_enable_dice_changes",
+        "release_avf_enable_network",
         "release_avf_enable_vendor_modules",
         "release_avf_enable_virt_cpufreq",
     ],
@@ -91,6 +92,9 @@
         release_avf_enable_dice_changes: {
             cflags: ["-DAVF_OPEN_DICE_CHANGES=1"],
         },
+        release_avf_enable_network: {
+            cflags: ["-DAVF_ENABLE_NETWORK=1"],
+        },
         release_avf_enable_vendor_modules: {
             cflags: ["-DAVF_ENABLE_VENDOR_MODULES=1"],
         },
diff --git a/apex/Android.bp b/apex/Android.bp
index 17b1f9e..8a53a3d 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -89,6 +89,7 @@
     ],
     jni_libs: [
         "libvirtualizationservice_jni",
+        "libvirtualizationsystemservice_jni",
         "libvirtualmachine_jni",
     ],
     // TODO(b/295593640) Unfortunately these are added to the apex even though they are unused.
diff --git a/apex/product_packages.mk b/apex/product_packages.mk
index a318817..486334c 100644
--- a/apex/product_packages.mk
+++ b/apex/product_packages.mk
@@ -56,3 +56,9 @@
     $(error RELEASE_AVF_ENABLE_DICE_CHANGES must also be enabled)
   endif
 endif
+
+ifdef RELEASE_AVF_ENABLE_NETWORK
+  ifndef RELEASE_AVF_ENABLE_LLPVM_CHANGES
+    $(error RELEASE_AVF_ENABLE_LLPVM_CHANGES must also be enabled)
+  endif
+endif
diff --git a/flags/cpp/include/android/avf_cc_flags.h b/flags/cpp/include/android/avf_cc_flags.h
index c922266..70be925 100644
--- a/flags/cpp/include/android/avf_cc_flags.h
+++ b/flags/cpp/include/android/avf_cc_flags.h
@@ -27,6 +27,14 @@
 #endif
 }
 
+inline bool IsNetworkFlagEnabled() {
+#ifdef AVF_ENABLE_NETWORK
+    return AVF_ENABLE_NETWORK;
+#else
+    return false;
+#endif
+}
+
 inline bool IsVendorModulesFlagEnabled() {
 #ifdef AVF_ENABLE_VENDOR_MODULES
     return AVF_ENABLE_VENDOR_MODULES;
diff --git a/java/jni/Android.bp b/java/jni/Android.bp
index 4a569d4..d9b1880 100644
--- a/java/jni/Android.bp
+++ b/java/jni/Android.bp
@@ -20,6 +20,20 @@
 }
 
 cc_library_shared {
+    name: "libvirtualizationsystemservice_jni",
+    defaults: ["avf_build_flags_cc"],
+    srcs: [
+        "com_android_system_virtualmachine_VirtualizationSystemService.cpp",
+    ],
+    apex_available: ["com.android.virt"],
+    shared_libs: [
+        "liblog",
+        "libnativehelper",
+    ],
+    static_libs: ["libavf_cc_flags"],
+}
+
+cc_library_shared {
     name: "libvirtualmachine_jni",
     defaults: ["avf_build_flags_cc"],
     srcs: [
diff --git a/java/jni/com_android_system_virtualmachine_VirtualizationSystemService.cpp b/java/jni/com_android_system_virtualmachine_VirtualizationSystemService.cpp
new file mode 100644
index 0000000..a15e7a7
--- /dev/null
+++ b/java/jni/com_android_system_virtualmachine_VirtualizationSystemService.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "VirtualizationSystemService"
+
+#include <android/avf_cc_flags.h>
+#include <jni.h>
+#include <log/log.h>
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_android_system_virtualmachine_VirtualizationSystemService_nativeIsNetworkFlagEnabled(
+        [[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
+    return android::virtualization::IsNetworkFlagEnabled();
+}
diff --git a/java/service/Android.bp b/java/service/Android.bp
index 8bac7be..814445c 100644
--- a/java/service/Android.bp
+++ b/java/service/Android.bp
@@ -31,6 +31,7 @@
     ],
     static_libs: [
         "android.system.virtualizationmaintenance-java",
+        "android.system.vmtethering-java",
     ],
     sdk_version: "core_platform",
     apex_available: ["com.android.virt"],
diff --git a/java/service/src/com/android/system/virtualmachine/VirtualizationSystemService.java b/java/service/src/com/android/system/virtualmachine/VirtualizationSystemService.java
index 2461755..970f780 100644
--- a/java/service/src/com/android/system/virtualmachine/VirtualizationSystemService.java
+++ b/java/service/src/com/android/system/virtualmachine/VirtualizationSystemService.java
@@ -26,6 +26,7 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.system.virtualizationmaintenance.IVirtualizationMaintenance;
+import android.system.vmtethering.IVmTethering;
 import android.util.Log;
 
 import com.android.internal.os.BackgroundThread;
@@ -39,18 +40,35 @@
  * storing secrets for apps or users that no longer exist.
  */
 public class VirtualizationSystemService extends SystemService {
+    static {
+        System.loadLibrary("virtualizationsystemservice_jni");
+    }
+
     private static final String TAG = VirtualizationSystemService.class.getName();
-    private static final String SERVICE_NAME = "android.system.virtualizationmaintenance";
+    private static final String MAINTENANCE_SERVICE_NAME =
+            "android.system.virtualizationmaintenance";
     private Handler mHandler;
+    private final TetheringService mTetheringService;
+
+    /*
+     * Retrieve boolean value whether RELEASE_AVF_ENABLE_NETWORK build flag is enabled or not.
+     */
+    static native boolean nativeIsNetworkFlagEnabled();
 
     public VirtualizationSystemService(Context context) {
         super(context);
+        if (nativeIsNetworkFlagEnabled()) {
+            mTetheringService = new TetheringService();
+        } else {
+            mTetheringService = null;
+        }
     }
 
     @Override
     public void onStart() {
-        // Nothing needed here - we don't expose any binder service. The binder service we use is
-        // exposed as a lazy service by the virtualizationservice native binary.
+        if (mTetheringService != null) {
+            publishBinderService(IVmTethering.DESCRIPTOR, mTetheringService);
+        }
     }
 
     @Override
@@ -82,11 +100,11 @@
     }
 
     static IVirtualizationMaintenance connectToMaintenanceService() {
-        IBinder binder = ServiceManager.waitForService(SERVICE_NAME);
+        IBinder binder = ServiceManager.waitForService(MAINTENANCE_SERVICE_NAME);
         IVirtualizationMaintenance maintenance =
                 IVirtualizationMaintenance.Stub.asInterface(binder);
         if (maintenance == null) {
-            throw new IllegalStateException("Failed to connect to " + SERVICE_NAME);
+            throw new IllegalStateException("Failed to connect to " + MAINTENANCE_SERVICE_NAME);
         }
         return maintenance;
     }
@@ -136,4 +154,11 @@
             }
         }
     }
+
+    private static final class TetheringService extends IVmTethering.Stub {
+        @Override
+        public void enableVmTethering() throws UnsupportedOperationException {
+            throw new UnsupportedOperationException("VM tethering is not supported yet");
+        }
+    }
 }
diff --git a/virtualizationservice/Android.bp b/virtualizationservice/Android.bp
index 0c39501..f9034af 100644
--- a/virtualizationservice/Android.bp
+++ b/virtualizationservice/Android.bp
@@ -30,6 +30,7 @@
         "android.system.virtualizationservice-rust",
         "android.system.virtualizationservice_internal-rust",
         "android.system.virtualmachineservice-rust",
+        "android.system.vmtethering-rust",
         "android.os.permissions_aidl-rust",
         "libandroid_logger",
         "libanyhow",
diff --git a/virtualizationservice/aidl/Android.bp b/virtualizationservice/aidl/Android.bp
index fb89772..bca4512 100644
--- a/virtualizationservice/aidl/Android.bp
+++ b/virtualizationservice/aidl/Android.bp
@@ -86,6 +86,26 @@
 }
 
 aidl_interface {
+    name: "android.system.vmtethering",
+    srcs: ["android/system/vmtethering/**/*.aidl"],
+    unstable: true,
+    backend: {
+        java: {
+            sdk_version: "module_current",
+            apex_available: [
+                "com.android.virt",
+            ],
+        },
+        rust: {
+            enabled: true,
+            apex_available: [
+                "com.android.virt",
+            ],
+        },
+    },
+}
+
+aidl_interface {
     name: "android.system.virtualmachineservice",
     srcs: ["android/system/virtualmachineservice/**/*.aidl"],
     imports: [
diff --git a/virtualizationservice/aidl/android/system/vmtethering/IVmTethering.aidl b/virtualizationservice/aidl/android/system/vmtethering/IVmTethering.aidl
new file mode 100644
index 0000000..732a515
--- /dev/null
+++ b/virtualizationservice/aidl/android/system/vmtethering/IVmTethering.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright 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 android.system.vmtethering;
+
+interface IVmTethering {
+    /**
+     * Start VM tethering to provide external network to VM.
+     */
+    void enableVmTethering();
+}
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index 70da37b..c0e1cc7 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -25,6 +25,7 @@
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice;
 use android_system_virtualizationservice_internal as android_vs_internal;
 use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice;
+use android_system_vmtethering::aidl::android::system::vmtethering;
 use android_vs_internal::aidl::android::system::virtualizationservice_internal;
 use anyhow::{anyhow, ensure, Context, Result};
 use avflog::LogResult;
@@ -73,6 +74,7 @@
     IVmnic::{BpVmnic, IVmnic},
 };
 use virtualmachineservice::IVirtualMachineService::VM_TOMBSTONES_SERVICE_PORT;
+use vmtethering::IVmTethering::{BpVmTethering, IVmTethering};
 use vsock::{VsockListener, VsockStream};
 
 /// The unique ID of a VM used (together with a port number) for vsock communication.
@@ -163,6 +165,9 @@
     static ref NETWORK_SERVICE: Strong<dyn IVmnic> =
         wait_for_interface(<BpVmnic as IVmnic>::get_descriptor())
             .expect("Could not connect to Vmnic");
+    static ref TETHERING_SERVICE: Strong<dyn IVmTethering> =
+        wait_for_interface(<BpVmTethering as IVmTethering>::get_descriptor())
+            .expect("Could not connect to VmTethering");
 }
 
 fn is_valid_guest_cid(cid: Cid) -> bool {
@@ -523,7 +528,20 @@
             ))
             .with_log();
         }
-        NETWORK_SERVICE.createTapInterface(iface_name_suffix)
+        let tap_fd = NETWORK_SERVICE.createTapInterface(iface_name_suffix)?;
+
+        // TODO(340377643): Due to lack of implementation of creating bridge interface, tethering is
+        // enabled for TAP interface instead of bridge interface. After introducing creation of
+        // bridge interface in AVF, we should modify it.
+        if let Err(e) = TETHERING_SERVICE.enableVmTethering() {
+            if e.exception_code() == ExceptionCode::UNSUPPORTED_OPERATION {
+                warn!("{}", e.get_description());
+            } else {
+                return Err(e);
+            }
+        }
+
+        Ok(tap_fd)
     }
 
     fn deleteTapInterface(&self, tap_fd: &ParcelFileDescriptor) -> binder::Result<()> {