#!/usr/bin/env python3 """Одновременный запуск Binder/GATT probe на двух телефонах, с полными раздельными логами.""" import argparse from pathlib import Path import subprocess import sys import time def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--receiver", required=True, help="ADB serial принимающей стороны") parser.add_argument("--initiator", required=True, help="ADB serial инициатора") parser.add_argument("--receiver-id", required=True, help="64-bit ID принимающей стороны, hex") parser.add_argument("--initiator-id", required=True, help="64-bit ID инициатора, hex") parser.add_argument("--reject", action="store_true", help="Проверить отказ callback вместо duplex") parser.add_argument("--install", action="store_true", help="Установить готовые app и androidTest APK перед тестом") parser.add_argument("--output", type=Path, required=True) args = parser.parse_args() if args.receiver == args.initiator: parser.error("Нужны два разных устройства") for value in (args.receiver_id, args.initiator_id): if not 0 < int(value, 16) <= 0xffffffffffffffff: parser.error("ID должен быть ненулевым unsigned 64-bit числом") args.output.mkdir(parents=True, exist_ok=True) project = Path(__file__).resolve().parents[1] roles = [("receiver", args.receiver, args.initiator_id, "false"), ("initiator", args.initiator, args.receiver_id, "true")] if args.install: for _, serial, _, _ in roles: for apk in ("app/build/outputs/apk/debug/app-debug.apk", "app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk"): subprocess.run(["adb", "-s", serial, "install", "-r", str(project / apk)], check=True) processes = [] files = [] try: # Оба процесса создаются до ожидания: согласование запуска не зависит от задержек отдельных tool approvals. for role, serial, peer, initiate in roles: logfile = args.output / f"{role}.log" output = logfile.open("w") files.append(output) command = ["adb", "-s", serial, "shell", "am", "instrument", "-w", "-e", "peer", peer, "-e", "initiator", initiate, "-e", "reject", str(args.reject).lower(), "com.utun.bletest.test/com.utun.bletest.BleApiProbe"] processes.append((role, subprocess.Popen(command, stdout=output, stderr=subprocess.STDOUT), logfile)) print(f"Started {role}: {serial}, peer={peer}", flush=True) deadline = time.monotonic() + 210 while any(process.poll() is None for _, process, _ in processes): if time.monotonic() >= deadline: raise TimeoutError("Timed out waiting for two-device probe") time.sleep(0.25) success = True for role, process, logfile in processes: content = logfile.read_text() print(f"{role}:\n{content}", flush=True) success &= process.returncode == 0 and "result=PASS " in content and "INSTRUMENTATION_CODE: -1" in content return 0 if success else 1 finally: for _, process, _ in processes: if process.poll() is None: process.terminate() process.wait(timeout=10) for output in files: output.close() if __name__ == "__main__": sys.exit(main())