Skip to content

Commit e74baad

Browse files
committed
Enhance AVD system image repair logic with validation checks and macOS uninstall/install retry mechanism
1 parent 0877267 commit e74baad

1 file changed

Lines changed: 66 additions & 6 deletions

File tree

Framework/install_handler/android/emulator.py

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,16 +215,31 @@ async def _repair_avd_system_image_if_needed(avd_name: str, sdk_root: Path) -> b
215215
if not package:
216216
return False
217217

218+
def _is_system_image_dir_valid(path: Path) -> bool:
219+
"""
220+
Emulator needs a fully formed system-image package, not just a folder.
221+
package.xml is the key marker; *.img files indicate extracted payload.
222+
"""
223+
if not path.exists() or not path.is_dir():
224+
return False
225+
package_xml = path / "package.xml"
226+
if not package_xml.exists():
227+
return False
228+
if any(path.glob("*.img")):
229+
return True
230+
# Some packages include nested image files; accept if known metadata exists.
231+
source_properties = path / "source.properties"
232+
return source_properties.exists()
233+
218234
expected_dir = sdk_root / package.replace(";", "/")
219-
if expected_dir.exists() and expected_dir.is_dir():
235+
if _is_system_image_dir_valid(expected_dir):
220236
return False
221237

222238
sdkmanager = _find_sdkmanager(sdk_root)
223239
if not sdkmanager:
224240
return False
225241

226-
if debug:
227-
print(f"[installer][emulator] Repairing missing system image for '{avd_name}': {package}")
242+
print(f"[installer][emulator] Repairing invalid/missing system image for '{avd_name}': {package}")
228243

229244
loop = asyncio.get_event_loop()
230245
if _is_windows():
@@ -259,9 +274,46 @@ async def _repair_avd_system_image_if_needed(avd_name: str, sdk_root: Path) -> b
259274
)
260275

261276
if not success:
277+
print(f"[installer][emulator] System image repair install command failed for package: {package}")
262278
return False
263279

264-
return expected_dir.exists() and expected_dir.is_dir()
280+
# If package still looks invalid, force reinstall by uninstalling first on macOS.
281+
if _is_darwin() and not _is_system_image_dir_valid(expected_dir):
282+
env = _build_android_process_env(sdk_root)
283+
uninstall_cmd = [str(sdkmanager), f"--sdk_root={sdk_root}", "--uninstall", package]
284+
install_cmd = [str(sdkmanager), f"--sdk_root={sdk_root}", package]
285+
try:
286+
print(f"[installer][emulator] Retrying repair via uninstall+install for package: {package}")
287+
await loop.run_in_executor(
288+
None,
289+
lambda: subprocess.run(
290+
uninstall_cmd,
291+
capture_output=True,
292+
text=True,
293+
timeout=600,
294+
env=env
295+
)
296+
)
297+
await loop.run_in_executor(
298+
None,
299+
lambda: subprocess.run(
300+
install_cmd,
301+
capture_output=True,
302+
text=True,
303+
timeout=1800,
304+
env=env
305+
)
306+
)
307+
except Exception as e:
308+
print(f"[installer][emulator] uninstall+install repair failed: {e}")
309+
return False
310+
311+
repaired = _is_system_image_dir_valid(expected_dir)
312+
if repaired:
313+
print(f"[installer][emulator] System image repair succeeded for package: {package}")
314+
else:
315+
print(f"[installer][emulator] System image directory is still invalid after repair: {expected_dir}")
316+
return repaired
265317

266318

267319
def _get_host_arch() -> str:
@@ -491,8 +543,16 @@ async def _attempt_launch(cmd: list[str], wait_seconds: int, attempt_label: str)
491543
if returncode is not None and _is_darwin():
492544
launch_hint = _read_file_tail(log_path).lower()
493545
if "not a valid directory" in launch_hint and "system-images" in launch_hint:
494-
if debug:
495-
print("[installer][emulator] Launch failed due missing system-image directory. Attempting auto-repair.")
546+
print("[installer][emulator] Launch failed due invalid system-image directory. Attempting auto-repair.")
547+
await send_response({
548+
"action": "status",
549+
"data": {
550+
"category": "AndroidEmulator",
551+
"name": avd_name,
552+
"status": "installing",
553+
"comment": "Repairing Android system image for this emulator...",
554+
}
555+
})
496556
repaired = await _repair_avd_system_image_if_needed(avd_name, sdk_root)
497557
if repaired:
498558
await _wait_for_avd_disk_ready(avd_name, timeout_seconds=12)

0 commit comments

Comments
 (0)