Skip to content

Implement play-services-asterism - #3360

Open
opstic wants to merge 52 commits into
microg:masterfrom
opstic:asterism
Open

opstic wants to merge 52 commits into
microg:masterfrom
opstic:asterism

Conversation

@opstic

@opstic opstic commented Mar 24, 2026 •

Copy link
Copy Markdown

This is PR 2 of 2 towards RCS support.
Related PR: #3359
Related issue: #2994

Depends on #3359 (Note: Until it's merged, this PR will include its commits in the diff)

Description

This PR implements the Asterism service, including:

  • getAsterismConsent
  • setAsterismConsent
  • getIsPnvrConstellationDevice

This PR uses gRPC proto definitions and client implementation introduced in play-services-constellation (PR #3359)

@mar-v-in mar-v-in linked an issue Jun 7, 2026 that may be closed by this pull request
@chenlinxi890-spec

Copy link
Copy Markdown

Complementary PR submitted: #3596 (#3596)

This PR adds two critical bug fixes on top of the Constellation/Asterism implementation:

  1. gRPC timeout fix: Added connectTimeout/writeTimeout/callTimeout (60s) — only readTimeout was set
  2. DeadObjectException fix: Wrapped callbacks.onPhoneNumber* in try-catch

These address the bugs identified by unpluggederan in issue #2994 comments.

@chenlinxi890-spec

Copy link
Copy Markdown

Quick update: I submitted a complementary fix PR (#3596) but @mar-v-in correctly pointed out it duplicates #3360 since the timeout and callback fixes are already in this PR. Closing #3596.

The two critical bugs mentioned by @unpluggederan are already addressed:

  1. ✅ gRPC timeout fix — commit 309566d (Set timeout on the right place)
  2. ✅ DeadObjectException fix — commit 2ec6d36 (Wrap callbacks in try catch)

Remaining issue from @unpluggederan's last comment:

  • Tachygram/DroidGuard attestation failures causing RCS to show 'Connected' but not actually work

I'm investigating this DroidGuard attestation path next.

@charlieijk

Copy link
Copy Markdown

Heads-up on a NewApi issue in the phone-number-verification settings path. It applies to #3359 as well, since 395864f0 is on both branches.

ConstellationStateStore is @file:RequiresApi(Build.VERSION_CODES.O), but two callers reach it unguarded from minSdkVersion 19 code:

  • play-services-core/src/main/kotlin/org/microg/gms/ui/SettingsFragment.kt:125 — ConstellationStateStore.isPhoneNumberVerificationEnabled(...) in the summary block
  • play-services-constellation/core/src/main/kotlin/org/microg/gms/constellation/core/ui/PhoneNumberVerificationPreferencesFragment.kt — the file carries no @RequiresApi and calls setPhoneNumberVerificationEnabled / isPhoneNumberVerificationEnabled / loadLastPhoneNumberVerification

There's no lint baseline and no coreLibraryDesugaring in the tree, so NewApi stays at error severity.

To be precise about the severity: the two methods reachable from the settings screen are SettingsContract reads, so I don't believe this actually crashes at runtime — the java.time.Instant usage that motivates the annotation lives in loadVerificationTokens / storeSyncResponse, which the settings UI never calls. So this reads as a build/lint break rather than a user-visible one.

What built cleanly for me locally:

// PhoneNumberVerificationPreferencesFragment.kt — after the licence header, before the package line
@file:RequiresApi(Build.VERSION_CODES.O)
// SettingsFragment.kt — hide the entry instead of calling into it
findPreference<Preference>(PREF_PHONE_NUMBER_VERIFICATION)!!.apply {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        onPreferenceClickListener = Preference.OnPreferenceClickListener {
            findNavController().navigate(requireContext(), R.id.openPhoneNumberVerificationSettings)
            true
        }
    } else {
        isVisible = false
    }
}

...plus the same SDK_INT guard around the setSummary call at line 125.

Happy to open a PR against asterism if that's useful, otherwise feel free to fold it in directly.

@charlieijk

Copy link
Copy Markdown

Follow-up to the above, in case it saves time on the rest of that lint run. CI on 2a680646 fails at :play-services-constellation-core:lintDebug with 11 errors, and the console only prints the first (the NewApi one), so I went looking for others statically. Two more that look like errors rather than warnings:

1. RestrictedApi — overriding onBindPreferences()

PhoneNumberVerificationPreferencesFragment.kt:24 overrides PreferenceFragmentCompat.onBindPreferences(). The method is genuinely invoked — bindPreferences() calls it from onViewCreated — so the runtime behaviour is fine. But in androidx.preference:1.2.0 it is declared:

/**
 * Used by Settings.
 * @hide
 */
@RestrictTo(LIBRARY_GROUP_PREFIX)
protected void onBindPreferences() {}

RestrictToDetector.isApplicableAnnotationUsage exempts only ASSIGNMENT_LHS/ASSIGNMENT_RHS; the METHOD_OVERRIDE exemption applies to its VisibleForTesting branch, not the @RestrictTo one. RestrictedApi is Severity.ERROR.

Doing the lookups in onCreatePreferences, straight after addPreferencesFromResource, avoids the override entirely:

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
    addPreferencesFromResource(R.xml.preferences_phone_number_verification)
    enabled = requireNotNull(findPreference<SwitchBarPreference>(PREF_ENABLED))
    lastUseCategory = requireNotNull(findPreference<PreferenceCategory>(PREF_LAST_USE_CATEGORY))
    app = requireNotNull(findPreference<PhoneNumberVerificationAppPreference>(PREF_LAST_USE))
    // ...existing listener wiring
}

2. NewApi — ?android:attr/textAppearanceListItemSecondary

preference_phone_number_verification_last_use.xml:58 and :69.

android:textAppearanceListItemSecondary was added in API 21 — it is absent from api/current.txt on android-4.4.4_r1 and present on android-5.0.0_r1 — and the module is minSdkVersion 19. Lint's ApiDetector resolves ?android: theme references and checks them against minSdk.

Dropping the android: namespace fixes it: AppCompat declares <attr format="reference" name="textAppearanceListItemSecondary"/> and supplies it in its themes, and this UI already runs under Theme.Material3.DayNight / Theme.AppCompat.*.

android:textAppearance="?attr/textAppearanceListItemSecondary"

One caveat: unlike the API-26 item, these two come from reading the lint detector sources and the AOSP API files rather than from a lint run of my own, so treat them as leads rather than confirmed. That still leaves roughly 8 of the 11 unaccounted for.

@nwinkelman2

Copy link
Copy Markdown

I reproduced this PR's Android lint failure locally and prepared a focused repair on top of the current asterism head: nwinkelman2@c00ccb5

The patch preserves this PR's commit history and authorship. It fixes the 11 hard lint errors without introducing a baseline:

  • narrows the API 26 requirement to only the six state-store methods that use Instant, keeping settings-only calls available on API 19+
  • moves preference initialization to public onCreatePreferences instead of restricted onBindPreferences
  • explicitly exports the two intent-filter services while retaining their runtime Google-caller authentication
  • fixes the AppCompat text appearance, start padding, and decorative icon accessibility findings

Verification on the exact patched branch:

  • :play-services-constellation-core:lintDebug — successful
  • :play-services-asterism-core:lintDebug — successful
  • both modules' assembleDebug tasks — successful
  • git diff --check — clean

GitHub does not allow my account to open a PR against this fork (CreatePullRequest permission error). If useful, the author can cherry-pick c00ccb516e7530273351335742516ecde642aaf2 onto asterism; I can also revise the patch promptly if the preferred service-export contract differs.

@nwinkelman2

Copy link
Copy Markdown

Follow-up integration result: I merged current microg/GmsCore master into the patched RCS stack without conflicts and reran the two feature modules against the current build system.

Reproducible integration branch: https://github.com/nwinkelman2/GmsCore/tree/integration/rcs-current-upstream

Current-master verification:

  • :play-services-constellation-core:lintDebug — successful
  • :play-services-asterism-core:lintDebug — successful
  • :play-services-constellation-core:assembleDebug — successful
  • :play-services-asterism-core:assembleDebug — successful

This does not claim locked-bootloader RCS send/receive validation; it specifically removes the stale-base/build-integration uncertainty while that device-level acceptance edge remains open.

@nwinkelman2

Copy link
Copy Markdown

I also assembled the existing focused follow-ups into one reviewable branch on top of the current asterism head, preserving each original author and commit:

https://github.com/nwinkelman2/GmsCore/tree/integration/rcs-consolidated

Commit stack:

  1. c00ccb51 — current Android lint/build repair described above
  2. 8169ea80 — Camilo Cabezas's invalid-IID propagation and regression coverage (fb9a853c)
  3. 1551c7b7 — Paulcake's stale public-key acknowledgement repair and regression coverage (325f1477)

Fresh verification of the combined stack:

  • Constellation lint — successful
  • Asterism lint — successful
  • both modules' debug assembly — successful
  • Constellation instrumentation APK assembly — successful
  • working tree and diff integrity — clean

No Android device is attached to this build host, so I have not rerun the instrumentation suite or claimed locked-bootloader send/receive proof. The point of this branch is to give the existing human implementation a consolidated, authorship-preserving path through its known CI and identity-state defects, not to create another competing RCS implementation.

@nwinkelman2

Copy link
Copy Markdown

Final integration update for review: the current-upstream assistance branch is now finalized at 0266edd:

https://github.com/nwinkelman2/GmsCore/tree/integration/rcs-current-upstream

This supersedes my interim branch notes above. It preserves Opstic's RCS implementation and the external authorship of each follow-up; it is an integration/reliability aid, not a competing authorship or bounty claim.

Included repairs:

  • c00ccb5: fixes the 11 Android lint errors without a baseline.
  • e89740d: Camilo Cabezas's invalid-IID propagation and regressions.
  • 719a221: Paulcake's stale public-key acknowledgement reset and regressions.
  • fd27912: instrumentation manifest compatibility by keeping the test APK change minSdk-only.
  • 3e0509c and 150714a: br413 SIM phone hint, cache, and reply handling with regressions.
  • 56749ac: replaces the false JVM Parcel round-trip assertion with a deterministic field-contract regression.
  • 0266edd: removes the unsubstantiated custom DroidGuard classloader experiment and keeps the platform dalvik.system.DexClassLoader behavior.

Exact-head local gate passed:

  • play-services-droidguard:testDebugUnitTest
  • play-services-constellation-core:testDebugUnitTest
  • play-services-constellation-core:lintDebug
  • play-services-asterism-core:lintDebug
  • play-services-constellation-core:assembleDebug
  • play-services-asterism-core:assembleDebug
  • play-services-constellation-core:assembleDebugAndroidTest

Result: BUILD SUCCESSFUL, 571 actionable tasks.

Hosted Debug and Release jobs are both green on the same exact head:
https://github.com/nwinkelman2/GmsCore/actions/runs/33644048116

I do not have an attached Android device here, so the instrumentation APK was built but the device suite was not executed. I am also not claiming locked-bootloader Google Messages send/receive proof; that remains a physical-device acceptance step for the primary implementation.

Chess-Debug added a commit to Chess-Debug/GmsCore that referenced this pull request Sep 16, 2026
Refactor RpcClient construction behind an internal factory without changing
runtime timeout behavior, then add a regression that requires the stock-GMS
60-second timeout contract for connect/read/write/call.

Baseline expectation at 276523b:
- connect: OkHttp default 10s -> FAIL
- read: 60s -> PASS
- write: OkHttp default 10s -> FAIL
- call: OkHttp default 0/unbounded -> FAIL

Provenance:
- Bug report / decompiled-GMS comparison: @unpluggederan, microg#3360 discussion
- Prior implementation attempt: @chenlinxi890-spec, microg#3596
- Foundragon delta: adds a focused deterministic regression before restoring the fix

This commit is intentionally the BEFORE_FAIL checkpoint; the next commit
restores the previously proposed timeout parity fix.
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.
Chess-Debug added a commit to Chess-Debug/GmsCore that referenced this pull request Sep 16, 2026
Extract the existing Gaia-only consent mapping into a behavior-neutral helper,
wire the Asterism JVM test source set, and add the focused resolver matrix.

The baseline keeps matching-Gaia behavior, but fails the two cases where the
server returns a valid RCS-specific consent without a matching Gaia entry.

Provenance:
- Original Constellation/Asterism implementation: @opstic (microg#3359/microg#3360)
- Focused fallback tests/fix proposal: @keeltrace, naormeit#1 and #6
- Parallel follow-up: @Anusha0501, naormeit#4
- Foundragon delta: freeze only the minimal missing-field fallback; do not
  invent a new Gaia-vs-RCS precedence rule

Expected BEFORE failures:
- rcsConsentIsUsedWhenMatchingGaiaConsentIsAbsent
- unrelatedGaiaConsentDoesNotMaskRcsConsent

Physical RCS E2E remains NOT YET PHYSICALLY VERIFIED.
ayush8620 added a commit to ayush8620/GmsCore that referenced this pull request Sep 21, 2026
Implement play-services-asterism with AIDL surface and AsterismApiService for
get/setAsterismConsent and getIsPnvrConstellationDevice, including fail-closed
RCS consent semantics and Samsung composite-token helpers.

Adapted from @opstic microg#3360 with hardening from microg#3808/microg#3784. Depends on the
Constellation module for shared RPC/client pieces.
ayush8620 added a commit to ayush8620/GmsCore that referenced this pull request Sep 21, 2026
Document implemented RCS stack, gap vs microg#3360/microg#3808, build/test commands,
logcat filters, and evidence Ayush must capture for BountyHub. Honest:
still needs on-device E2E; no PR ready from this commit.
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$]

5 participants