Skip to content

Implement Constellation and Asterism + DroidGuard fixes for RCS support - #3784

Open
naormeit wants to merge 68 commits into
microg:masterfrom
naormeit:rcs-bounty-2994
Open

naormeit wants to merge 68 commits into
microg:masterfrom
naormeit:rcs-bounty-2994

Conversation

@naormeit

@naormeit naormeit commented Sep 5, 2026

Copy link
Copy Markdown

This PR implements the GMS services required for RCS provisioning, addressing issue #2994 where Google Messages displays "RCS chats aren't available for this device" or hangs on "Setting up...". Previously, Constellation (GmsService 155, phone number verification) and Asterism (GmsService 199, RCS ToS/consent) were bound to DummyService. This also resolves DroidGuard tachyon_registration token rejections caused by cache path discrepancies visible to DG via /proc/self/maps.

Fixes #2994.

Contributors & Changes:

  • @opstic: Implemented Constellation and Asterism from scratch (Implement play-services-constellation #3359, Implement play-services-asterism #3360), including AIDL interfaces, proto definitions, gRPC clients, all verification paths (UPI/OTP, MO-SMS, MT-SMS, TS.43 EAP-AKA), and Phenotype flags for Messages/IMS.

  • @br413: Provided DroidGuard tachyon parity fixes (RCS: DroidGuard tachyon fixes, phone-number fallback, and unit tests (#2994) #3644): Changed getDir("cache_dg") to app_dg_cache/, uppercased VM cache key hex, fixed DroidGuardInitReply.createFromParcel() null handling, and added phone number hint fallback when E.164 is null.

  • @camilo-12ch: Fixed the IID empty token issue. getIidToken() no longer returns "" on failure, preventing empty credentials from reaching Google's GPNV endpoint.

  • @paulcakeface: Fixed the public-key ack ordering bug. The EC key is now validated/regenerated before isPublicKeyAcked() is read. Includes regression test.

  • @nwinkelman2: Integrated and repaired the branches. Fixed all 11 Android lint errors, fixed the instrumentation manifest, removed the unsubstantiated custom DG classloader experiment, and fixed a false JVM Parcel round-trip assertion in tests, achieving a CI-green branch for Debug and Release.

  • @keeltrace: Fixed the automatic RCS consent fallback in VerifyPhoneNumber.kt. The auto-consent path now uses RCS_CONSENT for rcs_consent.consent_version and CONSENT_API_TRIGGER in RequestHeader, matching the known-accepted semantics from [BOUNTY] RCS Support [14999$] #2994 testing. Includes regression tests.

  • @HumbleDrummer: Fixed multipart MT-SMS assembly in MtSmsInbox. Assembles ordered PDU parts from a single SMS_RECEIVED broadcast into one logical message before matching, preventing split challenges from failing verification. Includes unit tests.

  • @Anusha0501: Added X-Goog-Spatula header injection via AppCertService binding in constellation-core, with 30-minute cache (avoids circular dependency on play-services-core). Fixed AppCertManager's Android-ID fallback which was building the proto then returning null. Added Asterism consent fallback to rcs_consent when no Gaia entry exists for the RCS client. Corrected TS.43 EAP-AKA to use a consistent identity throughout; entitlement requests now populate terminal vendor/model/SW from Build.* when omitted.

  • Author (This PR): Implemented hasAccount correctness fix in NetworkHandleProxyFactory.createRequest(). Replaced hardcoded hasAccount = false with dynamic reading from AccountManager for com.google accounts (with SecurityException fallback to false).

Out of Scope / Not Claimed:

  • TS.43 carrier testing (no SIM available).

  • Locked-bootloader E2E hardware test — tester recruitment in progress.

Testing:

opstic and others added 12 commits August 2, 2026 18:37
InstanceID failures could be suppressed into an empty string. The empty credential was then exposed as a successful getIidToken response, signed, and included in a GetVerifiedPhoneNumbers request.

Propagate InstanceID failures to the existing error handlers and reject empty credentials before reading the FID, signing, building IIDTokenAuth, or executing GPNV. Regression tests cover exceptions, empty credentials, and the valid request path.

PR microg#3388 handles IID failures in a different Constellation implementation. This change applies equivalent error semantics plus explicit empty-token and GPNV guards to the microg#3359 architecture.
A regenerated EC key was allowed to inherit the previous key's server acknowledgement. Validate stored key material before reading that state, and reset it atomically whenever key material is generated.

Add instrumentation coverage for corrupt and valid stored key pairs.
Align DG cache naming and VM keys with stock GMS, preserve partial init replies, and fall back to phone number hints during Constellation provisioning.
Introduce shared phone-number and VM cache utilities, wire them into Constellation and DroidGuard, and add offline JUnit coverage for provisioning and tachyon-related logic.
…ctory

hasAccount in NetworkHandleProxyFactory.createRequest() was hardcoded to false. This reads the value dynamically from AccountManager for 'com.google' accounts, incorporating a SecurityException fallback to false.
@juliushill42

Copy link
Copy Markdown

@naormeit @opstic

This addresses the X-Goog-Spatula gap that #3784 explicitly lists as out of scope because play-services-constellation-core cannot depend directly on play-services-core without creating a circular dependency.

My branch is built directly on #3784's head:

naormeit/GmsCore@rcs-bounty-2994...juliushill42:GmsCore:rcs-2994-spatula-fix

What the delta does:

  • Reuses the existing IAppCertService AIDL from play-services-api and binds com.google.android.gms.auth.be.appcert.AppCertService, avoiding a direct play-services-core dependency.
  • Adds X-Goog-Spatula to Constellation requests when a header is available.
  • Fixes AppCertManager.getSpatulaHeader()'s Android-ID fallback, which constructed a SpatulaHeaderProto and then returned null.
  • Adds focused tests for header insertion/omission and Android-ID fallback proto construction.

Focused tests, lint, and :play-services-core:assembleVtmDefaultDebug pass locally.

No hardware install has been performed yet; Binder permission/lifecycle and end-to-end RCS provisioning still need device validation.

This is intentionally scoped as a narrow contribution on top of #3784, not a new Constellation/Asterism implementation.

@keeltrace

Copy link
Copy Markdown

There is now a direct empirical link for the small consent-semantics follow-up in naormeit#3.

Earlier in #2994, @unpluggederan tested the real SetConsent endpoint and reported that a request with asterism_client=RCS, nested rcs_consent.consent_version=RCS_CONSENT, and trigger_type=CONSENT_API_TRIGGER was accepted; the following verifyPhoneNumber Sync moved from FAILED_PRECONDITION to a response containing one verification: #2994 (comment)

#3784's existing Asterism SetConsent path already uses those version/trigger semantics, but the separate automatic-consent fallback in VerifyPhoneNumber.kt does not: at head 063ccbea it reuses the parsed request consent version inside nested RcsConsent and leaves the header at the default API-call trigger.

The two KeelTrace commits in naormeit#3 only align that fallback with the known-working/request-accepted semantics and add regression coverage:

  • 516c1eb5af060c4330c9b6a25318f20c58fddd0c — production correction
  • d8dfdffa88e72269a5a73a657c3bf711af8143cf — focused regression tests

Verification is green for focused JUnit, changed-module lint, and an independent assembleRelease: https://github.com/keeltrace/GmsCore/actions/runs/34537649271

This is a narrow correctness contribution on top of #3784, not a separate #2994 implementation or full-bounty claim.

…nsent request semantics

Incorporates two commits from keeltrace that fix the automatic-consent
fallback in VerifyPhoneNumber.kt:
- fix(constellation): align automatic RCS consent request
- test(constellation): cover automatic RCS consent semantics

Co-Authored-By: keeltrace <keeltrace@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
HumbleDrummer and others added 2 commits September 14, 2026 12:50
Assemble the ordered PDU parts from a single SMS_RECEIVED broadcast before matching and buffering the logical message. Reject missing parts and keep the first available sender.

Co-authored-by: Codex <codex@openai.com>
Cover multipart ordering, invalid or missing parts, and single-part/null-sender behavior.

Co-authored-by: Codex <codex@openai.com>
Assemble ordered PDU parts from a single SMS_RECEIVED broadcast into
one logical message before buffering and matching. Previously each PDU
was treated as a separate ReceivedSms, so a challenge split across
segments could never satisfy a pending match as one body.

Also rejects empty broadcasts and broadcasts with any missing body part.
Single-part behavior is unchanged.

Co-authored-by: HumbleDrummer <HumbleDrummer@users.noreply.github.com>
Chess-Debug added a commit to Chess-Debug/GmsCore that referenced this pull request Sep 16, 2026
Restore the complete timeout configuration reported from decompiled stock GMS:
connect/read/write/call are all 60 seconds.

The consolidated microg#3784 baseline retained only readTimeout(60s), leaving
OkHttp defaults for connect/write and an unbounded call timeout. This can
reproduce the earlier Sync/Proceed timeout failures during SMS verification
flows whose server responses exceed OkHttp's 10-second defaults.

Provenance:
- Original bug discovery and real-device observation: @unpluggederan in microg#3360
- Prior implementation: @chenlinxi890-spec in microg#3596
- Foundragon delta: behavior-neutral client factory plus deterministic timeout regression in parent 687a236

Regression:
- BEFORE at 276523b: [connect, read, write, call] = [10s, 60s, 10s, 0]
- AFTER: [60s, 60s, 60s, 60s]

Physical RCS E2E remains NOT YET PHYSICALLY VERIFIED.
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.

[BOUNTY] RCS Support [14999$]

9 participants