Skip to content

feat(android): Add cellular network technology to connection type - #6146

Open
alwx wants to merge 9 commits into
mainfrom
alwx/feature/3886
Open

alwx wants to merge 9 commits into
mainfrom
alwx/feature/3886

Conversation

@alwx

@alwx alwx commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

📜 Description

Following the network attribute conventions, where device.connection_type is deprecated in favour of network.connection.type and backfilled from it, the connection type keeps its documented values and the cellular generation gets its own attribute:

Device context key Convention attribute Values
connection_type network.connection.type wifi, ethernet, cellular (unchanged)
connection_effective_type network.connection.effective_type 2g, 3g, 4g, 5g

Device gains connection_effective_type, which is a public API addition (see the regenerated sentry.api). Relay has no typed network context yet, so the value rides in the device context under the analogous leaf name - worth confirming that placement.

The technology comes from two sources, in CellularNetworkTechnologyProvider:

  • Android 12 (API 31) and above — TelephonyCallback.DisplayInfoListener, which requires no
    permission
    . The listener is registered and unregistered alongside the existing network callback
    in AndroidConnectionStatusProvider, so nothing extra stays alive in the background, and reading
    the value never blocks on telephony. TelephonyDisplayInfo.getOverrideNetworkType() takes
    precedence over getNetworkType(), so a device showing 5G to the user is also reported as 5G.
  • Below Android 12 — TelephonyManager.getDataNetworkType() (API 24+), called only when the
    hosting app already holds READ_PHONE_STATE or READ_BASIC_PHONE_STATE. Per
    this comment the
    SDK does not declare those permissions itself; apps without them simply get no technology.

Two things worth a second opinion:

  1. Value format. Resolved: the generation goes into network.connection.effective_type with bare 4g / 5g, not folded into the connection type.
  2. Breadcrumbs stay coarse. NetworkBreadcrumbsIntegration uses the static
    getConnectionType(NetworkCapabilities), which is unchanged. It has no access to the telephony
    state, and its isSimilar de-duplication compares the type, so a technology flapping between 4G
    and 5G would produce breadcrumb noise. Happy to extend it in a follow-up if wanted.

On exception handling: the new code catches SecurityException, IllegalStateException and
UnsupportedOperationException explicitly rather than Throwable. Those are the documented
failures for telephony registration on devices without telephony hardware or for processes that are
not allowed to listen.

💡 Motivation and Context

Original request: getsentry/team-mobile#150,
Linear project SDK-2033.

💚 How did you test it?

New CellularNetworkTechnologyProviderTest covers the NETWORK_TYPE_* to generation mapping, the
override-type precedence, the permission gate below API 31, the API 24 floor for
getDataNetworkType(), registering and unregistering the display info listener, and the
no-telephony and SecurityException paths. AndroidConnectionStatusProviderTest gained cases for
the refined cellular_5g value, for falling back to plain cellular without permission, and for
leaving wifi untouched.

Verified with the full :sentry-android-core:testReleaseUnitTest suite, :sentry-android-core:lintRelease
(which caught the missing API 24 guard on getDataNetworkType()), and ./gradlew spotlessApply apiDump
— the latter produced no .api changes, since the new class is @ApiStatus.Internal.

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.

🔮 Next steps

device.connection_type is not documented in the
device context docs, so the
granular values should be added there. Hybrid SDKs pick the value up from the Android device context
without changes.

Refine device.connection_type from cellular to cellular_4g or
cellular_5g when the network technology is known.

From Android 12 the generation comes from the display info
listener, which needs no permission. On older versions it is read
from TelephonyManager only when the hosting app already holds
READ_PHONE_STATE or READ_BASIC_PHONE_STATE, which the SDK does not
declare itself.

Fixes #3886
@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 5a32881

@alwx

alwx commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

@cursor review

@sentry

sentry Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.58.0 (1) release

⚙️ sentry-android Build Distribution Settings

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

The display info listener was started before the network callback
was registered. Unregistering is skipped while there is no network
callback, so a failed registration left the listener running for
the rest of the process, including in the background.

Start it only after the network callback registered, and guard the
check-then-act in register and unregister with a lock so concurrent
callers cannot register a second listener that is never stored.
@alwx

alwx commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

@cursor review

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

@alwx
alwx marked this pull request as ready for review September 23, 2026 10:51
device.connection_type is deprecated in favour of
network.connection.type, and the conventions already have
network.connection.effective_type for the generation, so the
technology is no longer folded into the connection type.

Device gains connection_effective_type with 2g, 3g, 4g or 5g,
mirroring how connection_type aliases network.connection.type.
@alwx

alwx commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

@cursor review

Reading the connection type and the network technology separately
let a connectivity change land between them, so an event could
report a wifi connection with a cellular technology.

Both now come from one accessor that derives them from a single
cache read.
@alwx

alwx commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

@cursor review

The NSA mmWave override network type fell through to the network
type, which is LTE for NSA, so a 5G mmWave connection reported 4g.

Unregistering also dropped the callback reference before it was
unregistered, orphaning a still-registered callback when the
telephony manager was gone.
@alwx

alwx commented Sep 24, 2026

Copy link
Copy Markdown
Contributor Author

@cursor review

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Monitoring stops when the app goes to the background, and from API
31 on the display info listener is the only source, so clearing
the cached generation left every background event without a
technology while the connection type still resolved.
@alwx

alwx commented Sep 24, 2026

Copy link
Copy Markdown
Contributor Author

@cursor review

The SDK executor rejects work once it is shut down, and its queue
check doesn't cover that, so a display info change arriving after
Sentry.close threw RejectedExecutionException on a thread owned by
the telephony framework.
@alwx

alwx commented Sep 24, 2026

Copy link
Copy Markdown
Contributor Author

@cursor review

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

The rejecting executor is shared through the options, and teardown
closes the provider through it, so leaving it rejecting skipped
clearing the static connectivity manager for later tests.
@alwx

alwx commented Sep 24, 2026

Copy link
Copy Markdown
Contributor Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 5a32881. Configure here.

This branch has not been deployed

No deployments
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.

Connection Type to include Cellular Network Technology (e.g. 3G, 4G LTE, 5G)

1 participant