Merge changes Id33c0af3,I66d97987,Idbd4bf2f into main

* changes:
  virtmgr: Wait for socket file before connecting
  virtiofs: Add systemd unit to mount virtiofs inside guest
  virtiofs: Request permission to access storage
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
index af41c85..e278165 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
@@ -26,8 +26,11 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Icon;
 import android.graphics.fonts.FontStyle;
+import android.net.Uri;
 import android.net.http.SslError;
 import android.os.Bundle;
+import android.os.Environment;
+import android.provider.Settings;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.util.Log;
@@ -44,6 +47,10 @@
 import android.webkit.WebViewClient;
 import android.widget.Toast;
 
+import androidx.activity.result.ActivityResult;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
+
 import com.android.virtualization.vmlauncher.InstallUtils;
 import com.android.virtualization.vmlauncher.VmLauncherService;
 import com.android.virtualization.vmlauncher.VmLauncherServices;
@@ -81,6 +88,7 @@
     private WebView mWebView;
     private AccessibilityManager mAccessibilityManager;
     private static final int POST_NOTIFICATIONS_PERMISSION_REQUEST_CODE = 101;
+    private ActivityResultLauncher<Intent> manageExternalStorageActivityResultLauncher;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -111,12 +119,41 @@
         connectToTerminalService();
         readClientCertificate();
 
+        manageExternalStorageActivityResultLauncher =
+                registerForActivityResult(
+                        new ActivityResultContracts.StartActivityForResult(),
+                        (ActivityResult result) -> {
+                            if (Environment.isExternalStorageManager()) {
+                                Toast.makeText(this, "Storage permission set!", Toast.LENGTH_SHORT)
+                                        .show();
+                            } else {
+                                Toast.makeText(
+                                                this,
+                                                "Storage permission not set",
+                                                Toast.LENGTH_SHORT)
+                                        .show();
+                            }
+                            startVm();
+                        });
+
         // if installer is launched, it will be handled in onActivityResult
         if (!launchInstaller) {
-            startVm();
+            if (!Environment.isExternalStorageManager()) {
+                requestStoragePermissions(this, manageExternalStorageActivityResultLauncher);
+            } else {
+                startVm();
+            }
         }
     }
 
+    private void requestStoragePermissions(
+            Context context, ActivityResultLauncher<Intent> activityResultLauncher) {
+        Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
+        Uri uri = Uri.fromParts("package", context.getPackageName(), null);
+        intent.setData(uri);
+        activityResultLauncher.launch(intent);
+    }
+
     private URL getTerminalServiceUrl() {
         Configuration config = getResources().getConfiguration();
 
@@ -406,7 +443,11 @@
                 Log.e(TAG, "Failed to start VM. Installer returned error.");
                 finish();
             }
-            startVm();
+            if (!Environment.isExternalStorageManager()) {
+                requestStoragePermissions(this, manageExternalStorageActivityResultLauncher);
+            } else {
+                startVm();
+            }
         }
     }
 
diff --git a/android/virtmgr/src/crosvm.rs b/android/virtmgr/src/crosvm.rs
index b2283d0..b28834a 100644
--- a/android/virtmgr/src/crosvm.rs
+++ b/android/virtmgr/src/crosvm.rs
@@ -1244,6 +1244,9 @@
     }
 
     for shared_path in &config.shared_paths {
+        if let Err(e) = wait_for_file(&shared_path.socket_path, 5) {
+            bail!("Error waiting for file: {}", e);
+        }
         command
             .arg("--vhost-user-fs")
             .arg(format!("{},tag={}", &shared_path.socket_path, &shared_path.tag));
@@ -1269,6 +1272,23 @@
     Ok(result)
 }
 
+fn wait_for_file(path: &str, timeout_secs: u64) -> Result<(), std::io::Error> {
+    let start_time = std::time::Instant::now();
+    let timeout = Duration::from_secs(timeout_secs);
+
+    while start_time.elapsed() < timeout {
+        if std::fs::metadata(path).is_ok() {
+            return Ok(()); // File exists
+        }
+        thread::sleep(Duration::from_millis(100));
+    }
+
+    Err(std::io::Error::new(
+        std::io::ErrorKind::NotFound,
+        format!("File not found within {} seconds: {}", timeout_secs, path),
+    ))
+}
+
 /// Ensure that the configuration has a valid combination of fields set, or return an error if not.
 fn validate_config(config: &CrosvmConfig) -> Result<(), Error> {
     if config.bootloader.is_none() && config.kernel.is_none() {
diff --git a/build/debian/fai_config/files/etc/systemd/system/virtiofs.service/AVF b/build/debian/fai_config/files/etc/systemd/system/virtiofs.service/AVF
new file mode 100644
index 0000000..31ed059
--- /dev/null
+++ b/build/debian/fai_config/files/etc/systemd/system/virtiofs.service/AVF
@@ -0,0 +1,13 @@
+[Unit]
+Description=Mount virtiofs emulated file path
+After=network.target
+
+[Service]
+Type=oneshot
+User=root
+Group=root
+ExecStart=/bin/bash -c 'mkdir -p /mnt/shared; chown 1000:100 /mnt/shared; mount -t virtiofs android /mnt/shared'
+RemainAfterExit=yes
+
+[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 6a106c6..0886f72 100755
--- a/build/debian/fai_config/scripts/AVF/10-systemd
+++ b/build/debian/fai_config/scripts/AVF/10-systemd
@@ -6,3 +6,4 @@
 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
diff --git a/build/debian/vm_config.json.aarch64 b/build/debian/vm_config.json.aarch64
index 9f9295c..5b7489e 100644
--- a/build/debian/vm_config.json.aarch64
+++ b/build/debian/vm_config.json.aarch64
@@ -7,6 +7,14 @@
             "writable": true
         }
     ],
+    "sharedPath": [
+        {
+            "sharedPath": "/storage/emulated"
+        },
+        {
+            "sharedPath": "/data/data/com.google.android.virtualization.terminal/files"
+        }
+    ],
     "protected": false,
     "cpu_topology": "match_host",
     "platform_version": "~1.0",
diff --git a/build/debian/vm_config.json.x86_64 b/build/debian/vm_config.json.x86_64
index 2fb9faa..8a491e4 100644
--- a/build/debian/vm_config.json.x86_64
+++ b/build/debian/vm_config.json.x86_64
@@ -7,6 +7,14 @@
             "writable": true
         }
     ],
+    "sharedPath": [
+        {
+            "sharedPath": "/storage/emulated"
+        },
+        {
+            "sharedPath": "/data/data/com.google.android.virtualization.terminal/files"
+        }
+    ],
     "kernel": "$PAYLOAD_DIR/vmlinuz",
     "initrd": "$PAYLOAD_DIR/initrd.img",
     "params": "root=/dev/vda1",
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
index 5d6b13f..a259fe2 100644
--- a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/ConfigJson.java
+++ b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/ConfigJson.java
@@ -19,6 +19,7 @@
 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;
@@ -157,22 +158,40 @@
     private static class SharedPathJson {
         private SharedPathJson() {}
 
-        // Package ID of Terminal app.
-        private static final String TERMINAL_PACKAGE_ID =
-                "com.google.android.virtualization.terminal";
         private String sharedPath;
+        private static final int GUEST_UID = 1000;
+        private static final int GUEST_GID = 100;
 
         private SharedPath toConfig(Context context) {
             try {
-                int uid =
-                        context.getPackageManager()
-                                .getPackageUidAsUser(TERMINAL_PACKAGE_ID, context.getUserId());
-
-                return new SharedPath(sharedPath, uid, uid, 0, 0, 0007, "android", "android");
+                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 {