Merge "Import translations. DO NOT MERGE ANYWHERE" into main
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/DebianServiceImpl.java b/android/TerminalApp/java/com/android/virtualization/terminal/DebianServiceImpl.java
index 9cf6093..9a97a52 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/DebianServiceImpl.java
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/DebianServiceImpl.java
@@ -25,11 +25,9 @@
 
 import com.android.virtualization.terminal.proto.DebianServiceGrpc;
 import com.android.virtualization.terminal.proto.ForwardingRequestItem;
-import com.android.virtualization.terminal.proto.IpAddr;
 import com.android.virtualization.terminal.proto.QueueOpeningRequest;
 import com.android.virtualization.terminal.proto.ReportVmActivePortsRequest;
 import com.android.virtualization.terminal.proto.ReportVmActivePortsResponse;
-import com.android.virtualization.terminal.proto.ReportVmIpAddrResponse;
 import com.android.virtualization.terminal.proto.ShutdownQueueOpeningRequest;
 import com.android.virtualization.terminal.proto.ShutdownRequestItem;
 
@@ -42,16 +40,14 @@
     private final Context mContext;
     private final PortsStateManager mPortsStateManager;
     private PortsStateManager.Listener mPortsStateListener;
-    private final DebianServiceCallback mCallback;
     private Runnable mShutdownRunnable;
 
     static {
         System.loadLibrary("forwarder_host_jni");
     }
 
-    DebianServiceImpl(Context context, DebianServiceCallback callback) {
+    DebianServiceImpl(Context context) {
         super();
-        mCallback = callback;
         mContext = context;
         mPortsStateManager = PortsStateManager.getInstance(mContext);
     }
@@ -69,16 +65,6 @@
     }
 
     @Override
-    public void reportVmIpAddr(
-            IpAddr request, StreamObserver<ReportVmIpAddrResponse> responseObserver) {
-        Log.d(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(TAG, "OpenForwardingRequestQueue");
@@ -160,8 +146,4 @@
                         .mapToInt(Integer::intValue)
                         .toArray());
     }
-
-    protected interface DebianServiceCallback {
-        void onIpAddressAvailable(String ipAddr);
-    }
 }
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
index 016af83..4fddd14 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
@@ -28,11 +28,12 @@
 import android.graphics.fonts.FontStyle;
 import android.net.Uri;
 import android.net.http.SslError;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.ConditionVariable;
 import android.os.Environment;
-import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.util.Log;
@@ -62,10 +63,8 @@
 import com.google.android.material.appbar.MaterialToolbar;
 
 import java.io.IOException;
-import java.net.InetAddress;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.net.UnknownHostException;
 import java.security.KeyStore;
 import java.security.PrivateKey;
 import java.security.cert.X509Certificate;
@@ -77,8 +76,6 @@
         implements VmLauncherService.VmLauncherServiceCallback, AccessibilityStateChangeListener {
     static final String TAG = "VmTerminalApp";
     static final String KEY_DISK_SIZE = "disk_size";
-    private static final String VM_ADDR = "192.168.0.2";
-    private static final int TTYD_PORT = 7681;
     private static final int TERMINAL_CONNECTION_TIMEOUT_MS;
     private static final int REQUEST_CODE_INSTALLER = 0x33;
     private static final int FONT_SIZE_DEFAULT = 13;
@@ -234,7 +231,7 @@
         activityResultLauncher.launch(intent);
     }
 
-    private URL getTerminalServiceUrl() {
+    private URL getTerminalServiceUrl(String ipAddress, int port) {
         Configuration config = getResources().getConfiguration();
 
         String query =
@@ -249,8 +246,9 @@
                         + "&titleFixed="
                         + getString(R.string.app_name);
 
+
         try {
-            return new URL("https", VM_ADDR, TTYD_PORT, "/" + query);
+            return new URL("https", ipAddress, port, "/" + query);
         } catch (MalformedURLException e) {
             // this cannot happen
             return null;
@@ -266,7 +264,6 @@
     }
 
     private void connectToTerminalService() {
-        Log.i(TAG, "URL=" + getTerminalServiceUrl().toString());
         mTerminalView.setWebViewClient(
                 new WebViewClient() {
                     private boolean mLoadFailed = false;
@@ -344,46 +341,38 @@
                         handler.proceed();
                     }
                 });
-        mExecutorService.execute(
-                () -> {
-                    // TODO(b/376793781): Remove polling
-                    waitUntilVmStarts();
-                    runOnUiThread(() -> mTerminalView.loadUrl(getTerminalServiceUrl().toString()));
+
+        // TODO: refactor this block as a method
+        NsdManager nsdManager = getSystemService(NsdManager.class);
+        NsdServiceInfo info = new NsdServiceInfo();
+        info.setServiceType("_http._tcp");
+        info.setServiceName("ttyd");
+        nsdManager.registerServiceInfoCallback(
+                info,
+                mExecutorService,
+                new NsdManager.ServiceInfoCallback() {
+                    @Override
+                    public void onServiceInfoCallbackRegistrationFailed(int errorCode) {}
+
+                    @Override
+                    public void onServiceInfoCallbackUnregistered() {}
+
+                    @Override
+                    public void onServiceLost() {}
+
+                    @Override
+                    public void onServiceUpdated(NsdServiceInfo info) {
+                        nsdManager.unregisterServiceInfoCallback(this);
+
+                        Log.i(TAG, "Service found: " + info.toString());
+                        String ipAddress = info.getHostAddresses().get(0).getHostAddress();
+                        int port = info.getPort();
+                        URL url = getTerminalServiceUrl(ipAddress, port);
+                        runOnUiThread(() -> mTerminalView.loadUrl(url.toString()));
+                    }
                 });
     }
 
-    private static void waitUntilVmStarts() {
-        InetAddress addr = null;
-        try {
-            addr = InetAddress.getByName(VM_ADDR);
-        } catch (UnknownHostException e) {
-            // this can never happen.
-        }
-        long startTime = SystemClock.elapsedRealtime();
-        while (true) {
-            int remainingTime =
-                    TERMINAL_CONNECTION_TIMEOUT_MS
-                            - (int) (SystemClock.elapsedRealtime() - startTime);
-
-            if (Thread.interrupted()) {
-                Log.d(TAG, "the waiting thread is interrupted");
-                return;
-            }
-            if (remainingTime <= 0) {
-                throw new RuntimeException("Connection to terminal timeout");
-            }
-            try {
-                // Note: this quits immediately if VM is unreachable.
-                if (addr.isReachable(remainingTime)) {
-                    return;
-                }
-            } catch (IOException e) {
-                // give up on network error
-                throw new RuntimeException(e);
-            }
-        }
-    }
-
     @Override
     protected void onDestroy() {
         if (mExecutorService != null) {
@@ -414,11 +403,6 @@
     }
 
     @Override
-    public void onIpAddrAvailable(String ipAddr) {
-        // TODO: remove this
-    }
-
-    @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         getMenuInflater().inflate(R.menu.main_menu, menu);
         return true;
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.java b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.java
index f262f1f..09b58d3 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.java
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.java
@@ -25,6 +25,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Icon;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -59,7 +61,7 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
-public class VmLauncherService extends Service implements DebianServiceImpl.DebianServiceCallback {
+public class VmLauncherService extends Service {
     private static final String EXTRA_NOTIFICATION = "EXTRA_NOTIFICATION";
     private static final String ACTION_START_VM_LAUNCHER_SERVICE =
             "android.virtualization.START_VM_LAUNCHER_SERVICE";
@@ -70,8 +72,6 @@
     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;
@@ -90,8 +90,6 @@
         void onVmStop();
 
         void onVmError();
-
-        void onIpAddrAvailable(String ipAddr);
     }
 
     public static void run(
@@ -117,9 +115,6 @@
                             case RESULT_ERROR:
                                 callback.onVmError();
                                 return;
-                            case RESULT_IPADDR:
-                                callback.onIpAddrAvailable(resultData.getString(KEY_VM_IP_ADDR));
-                                return;
                         }
                     }
                 };
@@ -205,7 +200,33 @@
         mResultReceiver.send(RESULT_START, null);
 
         mPortNotifier = new PortNotifier(this);
-        startDebianServer();
+
+        // TODO: dedup this part
+        NsdManager nsdManager = getSystemService(NsdManager.class);
+        NsdServiceInfo info = new NsdServiceInfo();
+        info.setServiceType("_http._tcp");
+        info.setServiceName("ttyd");
+        nsdManager.registerServiceInfoCallback(
+                info,
+                mExecutorService,
+                new NsdManager.ServiceInfoCallback() {
+                    @Override
+                    public void onServiceInfoCallbackRegistrationFailed(int errorCode) {}
+
+                    @Override
+                    public void onServiceInfoCallbackUnregistered() {}
+
+                    @Override
+                    public void onServiceLost() {}
+
+                    @Override
+                    public void onServiceUpdated(NsdServiceInfo info) {
+                        nsdManager.unregisterServiceInfoCallback(this);
+                        Log.i(TAG, "Service found: " + info.toString());
+                        String ipAddress = info.getHostAddresses().get(0).getHostAddress();
+                        startDebianServer(ipAddress);
+                    }
+                });
 
         return START_NOT_STICKY;
     }
@@ -263,7 +284,7 @@
         return changed;
     }
 
-    private void startDebianServer() {
+    private void startDebianServer(String ipAddress) {
         ServerInterceptor interceptor =
                 new ServerInterceptor() {
                     @Override
@@ -271,16 +292,13 @@
                             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)) {
+                                        remoteAddr.getAddress().getHostAddress(), ipAddress)) {
                             // Allow the request only if it is from VM
                             return next.startCall(call, headers);
                         }
@@ -292,7 +310,7 @@
         try {
             // TODO(b/372666638): gRPC for java doesn't support vsock for now.
             int port = 0;
-            mDebianService = new DebianServiceImpl(this, this);
+            mDebianService = new DebianServiceImpl(this);
             mServer =
                     OkHttpServerBuilder.forPort(port, InsecureServerCredentials.create())
                             .intercept(interceptor)
@@ -317,14 +335,6 @@
                 });
     }
 
-    @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);
-    }
-
     public static void stop(Context context) {
         Intent i = getMyIntent(context);
         i.setAction(VmLauncherService.ACTION_STOP_VM_LAUNCHER_SERVICE);
diff --git a/build/debian/build.sh b/build/debian/build.sh
index 9bb1481..3db6a40 100755
--- a/build/debian/build.sh
+++ b/build/debian/build.sh
@@ -222,7 +222,6 @@
 	build_ttyd
 	build_rust_binary_and_copy forwarder_guest
 	build_rust_binary_and_copy forwarder_guest_launcher
-	build_rust_binary_and_copy ip_addr_reporter
 	build_rust_binary_and_copy shutdown_runner
 }
 
diff --git a/build/debian/fai_config/files/etc/systemd/system/forwarder_guest_launcher.service/AVF b/build/debian/fai_config/files/etc/systemd/system/forwarder_guest_launcher.service/AVF
index f4c2a24..129fdad 100644
--- a/build/debian/fai_config/files/etc/systemd/system/forwarder_guest_launcher.service/AVF
+++ b/build/debian/fai_config/files/etc/systemd/system/forwarder_guest_launcher.service/AVF
@@ -4,7 +4,7 @@
 After=network.target
 After=virtiofs_internal.service
 [Service]
-ExecStart=/usr/bin/bash -c '/usr/local/bin/forwarder_guest_launcher --host 192.168.0.1 --grpc_port $(cat /mnt/internal/debian_service_port)'
+ExecStart=/usr/bin/bash -c '/usr/local/bin/forwarder_guest_launcher --grpc_port $(cat /mnt/internal/debian_service_port)'
 Type=simple
 Restart=on-failure
 RestartSec=1
diff --git a/build/debian/fai_config/files/etc/systemd/system/ip_addr_reporter.service/AVF b/build/debian/fai_config/files/etc/systemd/system/ip_addr_reporter.service/AVF
deleted file mode 100644
index b9f3193..0000000
--- a/build/debian/fai_config/files/etc/systemd/system/ip_addr_reporter.service/AVF
+++ /dev/null
@@ -1,14 +0,0 @@
-[Unit]
-Description=ip report service
-After=syslog.target
-After=network.target
-Requires=ttyd.service
-After=virtiofs_internal.service
-[Service]
-ExecStart=/usr/bin/bash -c '/usr/local/bin/ip_addr_reporter --grpc_port $(cat /mnt/internal/debian_service_port)'
-Type=simple
-Restart=on-failure
-User=root
-Group=root
-[Install]
-WantedBy=multi-user.target
diff --git a/build/debian/fai_config/scripts/AVF/10-systemd b/build/debian/fai_config/scripts/AVF/10-systemd
index 119bec7..998cbfd 100755
--- a/build/debian/fai_config/scripts/AVF/10-systemd
+++ b/build/debian/fai_config/scripts/AVF/10-systemd
@@ -2,11 +2,9 @@
 
 chmod +x $target/usr/local/bin/forwarder_guest
 chmod +x $target/usr/local/bin/forwarder_guest_launcher
-chmod +x $target/usr/local/bin/ip_addr_reporter
 chmod +x $target/usr/local/bin/shutdown_runner
 chmod +x $target/usr/local/bin/ttyd
 ln -s /etc/systemd/system/ttyd.service $target/etc/systemd/system/multi-user.target.wants/ttyd.service
-ln -s /etc/systemd/system/ip_addr_reporter.service $target/etc/systemd/system/multi-user.target.wants/ip_addr_reporter.service
 ln -s /etc/systemd/system/virtiofs.service $target/etc/systemd/system/multi-user.target.wants/virtiofs.service
 ln -s /etc/systemd/system/forwarder_guest_launcher.service $target/etc/systemd/system/multi-user.target.wants/forwarder_guest_launcher.service
 ln -s /etc/systemd/system/virtiofs_internal.service $target/etc/systemd/system/multi-user.target.wants/virtiofs_internal.service
diff --git a/guest/forwarder_guest_launcher/Cargo.toml b/guest/forwarder_guest_launcher/Cargo.toml
index c875484..aef27f9 100644
--- a/guest/forwarder_guest_launcher/Cargo.toml
+++ b/guest/forwarder_guest_launcher/Cargo.toml
@@ -12,6 +12,7 @@
 futures = "0.3.31"
 listeners = "0.2.1"
 log = "0.4.22"
+netdev = "0.31.0"
 prost = "0.13.3"
 serde = { version = "1.0.215", features = ["derive"] }
 tokio = { version = "1.40.0", features = ["process", "rt-multi-thread"] }
diff --git a/guest/forwarder_guest_launcher/src/main.rs b/guest/forwarder_guest_launcher/src/main.rs
index f6944d6..6a2a692 100644
--- a/guest/forwarder_guest_launcher/src/main.rs
+++ b/guest/forwarder_guest_launcher/src/main.rs
@@ -52,10 +52,6 @@
 #[derive(Parser)]
 /// Flags for running command
 pub struct Args {
-    /// Host IP address
-    #[arg(long)]
-    #[arg(alias = "host")]
-    host_addr: String,
     /// grpc port number
     #[arg(long)]
     #[arg(alias = "grpc_port")]
@@ -171,7 +167,8 @@
     env_logger::init();
     debug!("Starting forwarder_guest_launcher");
     let args = Args::parse();
-    let addr = format!("https://{}:{}", args.host_addr, args.grpc_port);
+    let gateway_ip_addr = netdev::get_default_gateway()?.ipv4[0];
+    let addr = format!("https://{}:{}", gateway_ip_addr.to_string(), args.grpc_port);
     let channel = Endpoint::from_shared(addr)?.connect().await?;
     let client = DebianServiceClient::new(channel);
 
diff --git a/guest/ip_addr_reporter/.gitignore b/guest/ip_addr_reporter/.gitignore
deleted file mode 100644
index ea8c4bf..0000000
--- a/guest/ip_addr_reporter/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target
diff --git a/guest/ip_addr_reporter/Cargo.toml b/guest/ip_addr_reporter/Cargo.toml
deleted file mode 100644
index 7592e3f..0000000
--- a/guest/ip_addr_reporter/Cargo.toml
+++ /dev/null
@@ -1,15 +0,0 @@
-[package]
-name = "ip_addr_reporter"
-version = "0.1.0"
-edition = "2021"
-license = "Apache-2.0"
-
-[dependencies]
-clap = { version = "4.5.20", features = ["derive"] }
-netdev = "0.31.0"
-prost = "0.13.3"
-tokio = { version = "1.40.0", features = ["rt-multi-thread"] }
-tonic = "0.12.3"
-
-[build-dependencies]
-tonic-build = "0.12.3"
diff --git a/guest/ip_addr_reporter/build.rs b/guest/ip_addr_reporter/build.rs
deleted file mode 100644
index e3939d4..0000000
--- a/guest/ip_addr_reporter/build.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() -> Result<(), Box<dyn std::error::Error>> {
-    let proto_file = "../../libs/debian_service/proto/DebianService.proto";
-
-    tonic_build::compile_protos(proto_file).unwrap();
-
-    Ok(())
-}
diff --git a/guest/ip_addr_reporter/src/main.rs b/guest/ip_addr_reporter/src/main.rs
deleted file mode 100644
index 62a7aef..0000000
--- a/guest/ip_addr_reporter/src/main.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-use api::debian_service_client::DebianServiceClient;
-use api::IpAddr;
-
-use clap::Parser;
-pub mod api {
-    tonic::include_proto!("com.android.virtualization.terminal.proto");
-}
-
-#[derive(Parser)]
-/// Flags for running command
-pub struct Args {
-    /// grpc port number
-    #[arg(long)]
-    #[arg(alias = "grpc_port")]
-    grpc_port: String,
-}
-
-#[tokio::main]
-async fn main() -> Result<(), String> {
-    let args = Args::parse();
-    let gateway_ip_addr = netdev::get_default_gateway()?.ipv4[0];
-    let ip_addr = netdev::get_default_interface()?.ipv4[0].addr();
-
-    let server_addr = format!("http://{}:{}", gateway_ip_addr.to_string(), args.grpc_port);
-
-    println!("local ip addr: {}", ip_addr.to_string());
-    println!("coonect to grpc server {}", server_addr);
-
-    let mut client = DebianServiceClient::connect(server_addr).await.map_err(|e| e.to_string())?;
-
-    let request = tonic::Request::new(IpAddr { addr: ip_addr.to_string() });
-
-    let response = client.report_vm_ip_addr(request).await.map_err(|e| e.to_string())?;
-    println!("response from server: {:?}", response);
-    Ok(())
-}
diff --git a/libs/debian_service/proto/DebianService.proto b/libs/debian_service/proto/DebianService.proto
index 739f0ac..60f20d4 100644
--- a/libs/debian_service/proto/DebianService.proto
+++ b/libs/debian_service/proto/DebianService.proto
@@ -23,7 +23,6 @@
 
 service DebianService {
   rpc ReportVmActivePorts (ReportVmActivePortsRequest) returns (ReportVmActivePortsResponse) {}
-  rpc ReportVmIpAddr (IpAddr) returns (ReportVmIpAddrResponse) {}
   rpc OpenForwardingRequestQueue (QueueOpeningRequest) returns (stream ForwardingRequestItem) {}
   rpc OpenShutdownRequestQueue (ShutdownQueueOpeningRequest) returns (stream ShutdownRequestItem) {}
 }
@@ -32,14 +31,6 @@
   int32 cid = 1;
 }
 
-message IpAddr {
-  string addr = 1;
-}
-
-message ReportVmIpAddrResponse {
-  bool success = 1;
-}
-
 message ReportVmActivePortsRequest {
   repeated int32 ports = 1;
 }
@@ -55,4 +46,4 @@
 
 message ShutdownQueueOpeningRequest {}
 
-message ShutdownRequestItem {}
\ No newline at end of file
+message ShutdownRequestItem {}
diff --git a/libs/service-virtualization/src/com/android/system/virtualmachine/VirtualizationSystemService.java b/libs/service-virtualization/src/com/android/system/virtualmachine/VirtualizationSystemService.java
index afa286c..febf343 100644
--- a/libs/service-virtualization/src/com/android/system/virtualmachine/VirtualizationSystemService.java
+++ b/libs/service-virtualization/src/com/android/system/virtualmachine/VirtualizationSystemService.java
@@ -163,11 +163,8 @@
 
         @Override
         public void enableVmTethering() {
-            LinkAddress local = new LinkAddress("192.168.0.1/24");
-            LinkAddress client = new LinkAddress("192.168.0.2/24");
             final TetheringRequest tr =
                     new TetheringRequest.Builder(TetheringManager.TETHERING_VIRTUAL)
-                            .setStaticIpv4Addresses(local, client)
                             .setConnectivityScope(TetheringManager.CONNECTIVITY_SCOPE_GLOBAL)
                             .build();