Skip to content

fix(appium): skip data connectivity on devices without telephony (#5677) - #5678

Open
mirao wants to merge 1 commit into
codeceptjs:4.xfrom
mirao:fix/5677-appium-network-connection-telephony
Open

fix(appium): skip data connectivity on devices without telephony (#5677)#5678
mirao wants to merge 1 commit into
codeceptjs:4.xfrom
mirao:fix/5677-appium-network-connection-telephony

Conversation

@mirao

@mirao mirao commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Fixes #5677

Problem

mobile: setConnectivity runs adb shell svc <type> <state> for every field it is passed, so always sending data makes setNetworkConnection() fail on system images without telephony (e.g. tablet emulators, ro.build.characteristics=tablet):

WebDriverError: Error executing adbExec. Original error: 'Command
'... shell svc data disable' exited with code 20'; Command output: cmd: Can't find service: phone

This is a regression in 4.1.0 — #5662 replaced the legacy setNetworkConnection command, which tolerated the missing phone service. It takes down whole suites when the call sits in a _beforeSuite hook.

Fix

Probe mobile: deviceInfo for a carrier and only send data when the device actually has telephony.

Dropping data unconditionally is not an option: on a telephony-capable device it leaves cellular up, so setNetworkConnection(1) keeps the device online and "go offline" silently does nothing.

# Android 13 emulator (has telephony), after mobile: setConnectivity
{airplaneMode:true, wifi:false}             -> Active default network: 106 (MOBILE still CONNECTED)
{airplaneMode:true, wifi:false, data:false} -> Active default network: none

Only a positive probe result is cached. The first setNetworkConnection of a run typically happens in a suite-setup hook, seconds after the emulator boots — a real phone whose modem has not registered a carrier yet would report an empty carrierName there, and caching that negative would strip data for the rest of the session. Guarding with !this._hasTelephony re-asks until a carrier appears, then stops probing.

_hasTelephony behaviour
undefined — never probed probe
false — probed, no carrier seen re-probe
true — probed, carrier seen skip

The cost is one extra mobile: deviceInfo per call on a genuinely telephony-less device. That is a plain info read, so unlike the send-and-catch alternative it provokes no exception and adds no red ERROR webdriver: line to tablet runs.

carrierName is still reported while airplane mode is on, so the probe is not perturbed by the connectivity state being changed. grabNetworkConnection() is unaffected — mobile: getConnectivity works on these images.

Verified

Unit tests added for the telephony-less payload, the re-probe while no carrier has been seen, and probe-once-then-cache after a carrier appears. Full file passes (11 passing).

Verified as a patch against 4.1.0 on two live emulators — sdk_gtablet_x86_64 (Android 15, no telephony) and sdk_gphone64_x86_64 (Android 13, carrier T-Mobile):

suite / test image result
NetworkConnectionIndicator Android 15 tablet 6 passed
NetworkConnectionIndicator Android 13 phone 6 passed
StudentAttendance Android 13 phone 54 passed
DndGameWithoutLessonPath Android 15 tablet 8 passed

No ERROR webdriver: line and no Can't find service: phone in any run. StudentAttendance is the test that originally caught the dropped-data failure, so its 54 passing scenarios confirm going offline still genuinely disconnects on a telephony-capable device.

🤖 Generated with Claude Code

…eceptjs#5677)

`mobile: setConnectivity` runs `adb shell svc <type> <state>` for every
field it is passed, so always sending `data` made setNetworkConnection()
fail with "Can't find service: phone" (adb exit 20) on system images
without telephony, such as tablet emulators. This regressed in 4.1.0,
when codeceptjs#5662 replaced the legacy setNetworkConnection command, which
tolerated the missing phone service.

Probe `mobile: deviceInfo` for a carrier and only send `data` when the
device actually has telephony. Dropping `data` unconditionally is not an
option: on a telephony-capable device it leaves cellular up, so going
offline silently does nothing and tests keep passing against a device
that is still online.

Only a positive probe result is cached. A freshly booted device may not
have registered a carrier yet, and since the first call typically comes
from a suite-setup hook seconds after boot, caching that negative would
strip `data` for the rest of the session on a real phone. Guarding with
`!this._hasTelephony` re-asks until a carrier appears, then stops.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Appium: setNetworkConnection() fails on devices without telephony ("Can't find service: phone") — regression in 4.1.0

1 participant