Skip to content

Commit 679f09f

Browse files
committed
Android testbed: ensure managed emulator has 4GB RAM
1 parent bb917d8 commit 679f09f

File tree

3 files changed

+336
-126
lines changed

3 files changed

+336
-126
lines changed

Android/README.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,7 @@ require adding your user to a group, or changing your udev rules. On GitHub
103103
Actions, the test script will do this automatically using the commands shown
104104
[here](https://github.blog/changelog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/).
105105

106-
The test suite can usually be run on a device with 2 GB of RAM, but this is
107-
borderline, so you may need to increase it to 4 GB. As of Android
108-
Studio Koala, 2 GB is the default for all emulators, although the user interface
109-
may indicate otherwise. Locate the emulator's directory under `~/.android/avd`,
110-
and find `hw.ramSize` in both config.ini and hardware-qemu.ini. Either set these
111-
manually to the same value, or use the Android Studio Device Manager, which will
112-
update both files.
106+
The Android testbed's Gradle-managed emulator is configured to use 4 GB of RAM.
113107

114108
You can run the test suite either:
115109

Android/android.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,19 @@
3838
APP_ID = "org.python.testbed"
3939
DECODE_ARGS = ("UTF-8", "backslashreplace")
4040

41+
def get_android_home() -> Path:
42+
try:
43+
return Path(os.environ["ANDROID_HOME"])
44+
except KeyError:
45+
raise SystemExit("The ANDROID_HOME environment variable is required.")
4146

42-
try:
43-
android_home = Path(os.environ['ANDROID_HOME'])
44-
except KeyError:
45-
sys.exit("The ANDROID_HOME environment variable is required.")
4647

47-
adb = Path(
48-
f"{android_home}/platform-tools/adb"
49-
+ (".exe" if os.name == "nt" else "")
50-
)
48+
def get_adb() -> Path:
49+
android_home = get_android_home()
50+
return Path(
51+
f"{android_home}/platform-tools/adb"
52+
+ (".exe" if os.name == "nt" else "")
53+
)
5154

5255
gradlew = Path(
5356
f"{TESTBED_DIR}/gradlew"
@@ -316,17 +319,20 @@ def setup_ci():
316319
else:
317320
raise ValueError(f"Failed to find NDK version in {ENV_SCRIPT.name}")
318321

319-
for item in (android_home / "ndk").iterdir():
322+
for item in (get_android_home() / "ndk").iterdir():
320323
if item.name[0].isdigit() and item.name != ndk_version:
321324
delete_glob(item)
322325

323326

324327
def setup_sdk():
328+
android_home = get_android_home()
325329
sdkmanager = android_home / (
326330
"cmdline-tools/latest/bin/sdkmanager"
327331
+ (".bat" if os.name == "nt" else "")
328332
)
329333

334+
adb = get_adb()
335+
330336
# Gradle will fail if it needs to install an SDK package whose license
331337
# hasn't been accepted, so pre-accept all licenses.
332338
if not all((android_home / "licenses" / path).exists() for path in [
@@ -437,7 +443,7 @@ async def list_devices():
437443
serials = []
438444
header_found = False
439445

440-
lines = (await async_check_output(adb, "devices")).splitlines()
446+
lines = (await async_check_output(get_adb(), "devices")).splitlines()
441447
for line in lines:
442448
# Ignore blank lines, and all lines before the header.
443449
line = line.strip()
@@ -487,9 +493,9 @@ async def find_pid(serial):
487493
try:
488494
# `pidof` requires API level 24 or higher. The level 23 emulator
489495
# includes it, but it doesn't work (it returns all processes).
490-
pid = (await async_check_output(
491-
adb, "-s", serial, "shell", "pidof", "-s", APP_ID
492-
)).strip()
496+
pid = (await async_check_output(
497+
get_adb(), "-s", serial, "shell", "pidof", "-s", APP_ID
498+
)).strip()
493499
except CalledProcessError as e:
494500
# If the app isn't running yet, pidof gives no output. So if there
495501
# is output, there must have been some other error. However, this
@@ -525,7 +531,7 @@ async def logcat_task(context, initial_devices):
525531
# long`). For example, every time pytest runs a test, it prints a "." and
526532
# flushes the stream. Each "." becomes a separate log message, but we should
527533
# show them all on the same line.
528-
args = [adb, "-s", serial, "logcat", "--pid", pid, "--binary"]
534+
args = [get_adb(), "-s", serial, "logcat", "--pid", pid, "--binary"]
529535
logcat_started = False
530536
async with async_process(
531537
*args, stdout=subprocess.PIPE, stderr=None
@@ -599,7 +605,7 @@ async def read_int(size):
599605
payload_fields = (await read_bytes(payload_len - 1)).split(b"\0")
600606
if len(payload_fields) < 2:
601607
raise ValueError(
602-
f"payload {payload!r} does not contain at least 2 "
608+
f"payload {payload_fields!r} does not contain at least 2 "
603609
f"null-separated fields"
604610
)
605611
tag, message, *_ = [
@@ -609,7 +615,7 @@ async def read_int(size):
609615

610616

611617
def stop_app(serial):
612-
run([adb, "-s", serial, "shell", "am", "force-stop", APP_ID], log=False)
618+
run([get_adb(), "-s", serial, "shell", "am", "force-stop", APP_ID], log=False)
613619

614620

615621
async def gradle_task(context):

0 commit comments

Comments
 (0)