Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
5991207
Implement `play-services-constellation`
opstic Mar 24, 2026
330e932
Merge branch 'microg:master' into constellation
opstic Mar 24, 2026
977afd1
Refactor and small cleanups
opstic Mar 26, 2026
08b36eb
Refactor `org.microg.gms.constellation.core.verification`
opstic Mar 26, 2026
01400ff
More refactoring
opstic Mar 26, 2026
3f15e8b
Add `android.permission.USE_CREDENTIALS` into `AndroidManifest.xml`
opstic Mar 27, 2026
65961f8
Fix `NewApi` lints
opstic Mar 27, 2026
52a58d4
Fix the rest of the lints
opstic Mar 27, 2026
3917eeb
Convert parcelables into Java
opstic Mar 27, 2026
aec46b8
Small fixes
opstic Mar 27, 2026
23e80ba
Formatting
opstic Mar 27, 2026
59e1895
why did i write it like this
opstic Mar 27, 2026
b20cc3c
Remove full name and use import instead
opstic Mar 27, 2026
2552a9e
Use GMS package name instead of our own
opstic Mar 29, 2026
d08e4d8
Remove unnecessary dependencies
opstic Mar 29, 2026
05cd22d
Refactor package name from `builders` to `builder`
opstic Mar 29, 2026
117312d
Clean up `constellation.proto`
opstic Mar 29, 2026
db60565
More consistent formatting
opstic Mar 29, 2026
0621ee7
Use actual Gaia ID
opstic Apr 1, 2026
b82676c
Align more with official behavior
opstic Apr 3, 2026
58732b5
Add more infos to `TelephonyInfo`
opstic Apr 3, 2026
edb6de4
Improve DroidGuard generation
opstic Apr 3, 2026
94c442a
Improve `MtSmsVerifier`
opstic Apr 3, 2026
eddc24d
Reorder `RequestHeader` arguments
opstic Apr 3, 2026
85567ba
Improve RPC error handling
opstic Apr 4, 2026
f3449a7
Improve `MoSmsVerifier`
opstic Apr 4, 2026
6920424
Improve MT SMS timeout behavior
opstic Apr 4, 2026
fbcf53c
Add consent check before verification
opstic Apr 4, 2026
9904b50
Improve `CarrierIdVerifier`
opstic Apr 4, 2026
ec02375
Update `constellation.proto`
opstic Apr 5, 2026
ce85aeb
Small cleanups
opstic Apr 6, 2026
bafa5f4
Add permissions to Self-Check
opstic Apr 6, 2026
a1372b2
Adjust RPC timeout
opstic Apr 7, 2026
564ad08
`RpcClient` formatting
opstic Apr 7, 2026
2ec6d36
Wrap callbacks in `try catch`
opstic Apr 7, 2026
2b8cf43
Refactoring
opstic Apr 8, 2026
44ffa11
Replicate GMS behavior better
opstic May 15, 2026
ac8f7a6
Missed null check
opstic May 16, 2026
23bf307
Set priority of SMS receiver to 1000
opstic May 16, 2026
327b5b0
Add Phenotype flag to prevent ACS fallback
opstic May 16, 2026
309566d
Set timeout on the right place
opstic May 16, 2026
4510ced
Add MLS Phenotype flags
opstic May 17, 2026
ae6ae71
Implement `play-services-asterism`
opstic Mar 24, 2026
ad3b537
Refactoring
opstic Mar 29, 2026
8e7c4de
Remove unnecessary dependencies
opstic Mar 29, 2026
99c9222
Update `RequestHeader` building
opstic Apr 3, 2026
a457d82
Fix `SetAsterismConsent` handling
opstic Apr 5, 2026
46bab0c
Add `toString()` for `SetAsterismConsentRequest`
opstic Apr 6, 2026
d2d0b6e
Remove unnecessary dependency
opstic Apr 7, 2026
d6562c8
Merge branch 'pr-3359' into rcs-support
yasin-ads Jul 5, 2026
c64f627
Merge branch 'pr-3360' into rcs-support
yasin-ads Jul 5, 2026
1a3d63b
docs: add RCS implementation and testing documentation
yasin-ads Jul 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions PR_DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

# Partial RCS Support: Constellation, Asterism, and Testing Documentation

## Summary

This PR provides partial RCS support groundwork for microG by integrating the existing Constellation and Asterism work and adding structured documentation for build/testing status.

## Included

- Integrated Constellation Service work from PR #3359
- Integrated Asterism Service work from PR #3360
- Added RCS implementation status documentation
- Added RCS testing notes and diagnostic workflow

## Current Status

This PR does not fully solve RCS support yet.

The current branch provides partial implementation groundwork. Full RCS message transmission is not yet confirmed.

## Remaining Work

- Tachyon registration support
- DroidGuard challenge compatibility analysis
- Real-device RCS testing
- Message sending and receiving verification
- Locked bootloader verification

## Relation to Issue

Related to #2994.

This PR should not be treated as a complete fix yet. It is intended to help move RCS implementation forward with a clearer implementation and testing baseline.
33 changes: 33 additions & 0 deletions RCS_IMPLEMENTATION_STATUS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# RCS Implementation Status for microG

## Status
Partial RCS implementation support.

## Integrated Work
- Constellation Service integrated from PR #3359
- Asterism Service integrated from PR #3360
- Basic RCS-related implementation groundwork is now available in this branch

## Current Build Status
Build attempt was performed using:

./gradlew assembleDebug

Current result:
FAILED due to Java compiler toolchain configuration issue.

This is an environment/build configuration issue, not a confirmed RCS runtime failure.

## Remaining Work
- Tachyon registration support
- DroidGuard challenge compatibility analysis
- Actual RCS message sending and receiving
- End-to-end testing on a real Android device with active SIM
- Locked bootloader verification as required by the bounty

## Important Note
This branch does not fully solve Issue #2994 yet.

It provides partial implementation groundwork by integrating existing Constellation and Asterism work, and adds structured documentation for testing and future completion.

Related to #2994.
39 changes: 39 additions & 0 deletions RCS_TESTING_NOTES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# RCS Testing Notes

## Environment
- Repository: microg/GmsCore fork
- Branch: rcs-support
- Integrated PRs:
- PR #3359 Constellation Service
- PR #3360 Asterism Service

## Build Attempt

Command:

./gradlew assembleDebug

Result:

FAILED

Known issue:

Java compiler toolchain configuration issue.

## Required Testing Device
Full RCS testing requires:

- Physical Android device
- Active SIM card
- Google Messages installed
- Locked bootloader
- microG GmsCore built and installed
- Required phone, SMS, contacts, and network permissions granted

## Suggested Logcat Commands

```bash
adb logcat | grep -iE "rcs|tachyon|constellation|asterism|provisioning"
adb logcat | grep -i "google.android.apps.messaging"
adb logcat | grep -iE "auth|verification|droidguard"
40 changes: 40 additions & 0 deletions play-services-asterism/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: 2026, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/

apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
apply plugin: 'signing'

android {
namespace "org.microg.gms.asterism"

compileSdkVersion androidCompileSdk
buildToolsVersion "$androidBuildVersionTools"

buildFeatures {
aidl = true
}

defaultConfig {
versionName version
minSdkVersion androidMinSdk
targetSdkVersion androidTargetSdk
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

apply from: '../gradle/publish-android.gradle'

description = 'microG implementation of play-services-asterism'

dependencies {
implementation project(':play-services-basement')

annotationProcessor project(":safe-parcel-processor")
}
46 changes: 46 additions & 0 deletions play-services-asterism/core/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* SPDX-FileCopyrightText: 2026, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/

apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
apply plugin: 'kotlin-android'
apply plugin: 'signing'

android {
namespace "org.microg.gms.asterism.core"

compileSdkVersion androidCompileSdk
buildToolsVersion "$androidBuildVersionTools"

defaultConfig {
versionName version
minSdkVersion androidMinSdk
targetSdkVersion androidTargetSdk
}

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
jvmTarget = 1.8
}
}

apply from: '../../gradle/publish-android.gradle'

description = 'microG service implementation for play-services-asterism'

dependencies {
api project(':play-services-asterism')

implementation project(':play-services-base-core')
implementation project(':play-services-constellation-core')
}
15 changes: 15 additions & 0 deletions play-services-asterism/core/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ SPDX-FileCopyrightText: 2026, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application>
<service android:name=".AsterismApiService">
<intent-filter>
<action android:name="com.google.android.gms.asterism.service.START" />
</intent-filter>
</service>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.google.android.gms.asterism

import org.microg.gms.constellation.core.proto.AsterismClient
import org.microg.gms.constellation.core.proto.Consent
import org.microg.gms.constellation.core.proto.ConsentVersion

val GetAsterismConsentRequest.asterismClient: AsterismClient
get() = AsterismClient.fromValue(asterismClientValue) ?: AsterismClient.UNKNOWN_CLIENT

fun getAsterismConsentResponse(
requestCode: Int,
consentState: Consent,
gmscoreIidToken: String?,
fid: String?,
consentVersion: ConsentVersion
): GetAsterismConsentResponse {
val consentStateValue =
if (consentState == Consent.CONSENTED || consentState == Consent.CONSENT_UNKNOWN) {
consentState.value
} else {
Consent.NO_CONSENT.value
}

return GetAsterismConsentResponse(
requestCode,
consentStateValue,
gmscoreIidToken,
fid,
consentVersion.value
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.google.android.gms.asterism

import org.microg.gms.constellation.core.proto.AsterismClient
import org.microg.gms.constellation.core.proto.AsterismConsent.DeviceConsentVersion
import org.microg.gms.constellation.core.proto.Consent
import org.microg.gms.constellation.core.proto.ConsentSource
import org.microg.gms.constellation.core.proto.ConsentVersion

enum class SetAsterismConsentRequestStatus(val value: Int) {
RESOURCE_TOS(0),
STATIC_STRING(1),
RCS(2),
ON_DEMAND(3),
RESOURCE_TOS_FALLBACK(4);

companion object {
fun fromValue(value: Int): SetAsterismConsentRequestStatus =
entries.find { it.value == value } ?: RESOURCE_TOS_FALLBACK
}
}

val SetAsterismConsentRequest.asterismClient: AsterismClient
get() = AsterismClient.fromValue(asterismClientValue) ?: AsterismClient.UNKNOWN_CLIENT

val SetAsterismConsentRequest.consent: Consent
get() = Consent.fromValue(consentValue) ?: Consent.CONSENT_UNKNOWN

val SetAsterismConsentRequest.consentVersion: ConsentVersion?
get() = ConsentVersion.fromValue(consentVersionValue)

val SetAsterismConsentRequest.deviceConsentSource: ConsentSource
get() = ConsentSource.fromValue(deviceConsentSourceValue) ?: ConsentSource.SOURCE_UNSPECIFIED

val SetAsterismConsentRequest.deviceConsentVersion: DeviceConsentVersion
get() = DeviceConsentVersion.fromValue(deviceConsentVersionValue).let {
if (it == null || it == DeviceConsentVersion.UNKNOWN) {
DeviceConsentVersion.PHONE_VERIFICATION_DEFAULT
} else {
it
}
}

val SetAsterismConsentRequest.status: SetAsterismConsentRequestStatus
get() = SetAsterismConsentRequestStatus.fromValue(statusValue)

fun SetAsterismConsentRequest.isDevicePnvrFlow(): Boolean {
return asterismClient == AsterismClient.CONSTELLATION &&
deviceConsentSourceValue > 0 &&
deviceConsentVersionValue > 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.microg.gms.asterism.core

import android.content.Context
import android.os.Build
import android.util.Log
import com.google.android.gms.asterism.GetAsterismConsentRequest
import com.google.android.gms.asterism.SetAsterismConsentRequest
import com.google.android.gms.asterism.internal.IAsterismApiService
import com.google.android.gms.asterism.internal.IAsterismCallbacks
import com.google.android.gms.common.Feature
import com.google.android.gms.common.internal.ConnectionInfo
import com.google.android.gms.common.internal.GetServiceRequest
import com.google.android.gms.common.internal.IGmsCallbacks
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import org.microg.gms.BaseService
import org.microg.gms.common.GmsService
import org.microg.gms.common.PackageUtils

private const val TAG = "AsterismApiService"

class AsterismApiService : BaseService(TAG, GmsService.ASTERISM) {
private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)

override fun handleServiceRequest(
callback: IGmsCallbacks?,
request: GetServiceRequest?,
service: GmsService?
) {
val packageName = PackageUtils.getAndCheckCallingPackage(this, request?.packageName)
if (!PackageUtils.isGooglePackage(this, packageName)) {
throw SecurityException("$packageName is not a Google package")
}
callback!!.onPostInitCompleteWithConnectionInfo(
0,
AsterismApiServiceImpl(this, serviceScope).asBinder(),
ConnectionInfo().apply {
features = arrayOf(
Feature("asterism_consent", 3),
Feature("one_time_verification", 1),
Feature("carrier_auth", 1),
Feature("verify_phone_number", 2),
Feature("get_iid_token", 1),
Feature("get_pnv_capabilities", 1),
Feature("ts43", 1),
Feature("verify_phone_number_local_read", 1)
)
}
)
}

override fun onDestroy() {
super.onDestroy()
serviceScope.cancel("AsterismApiService destroyed")
}
}

class AsterismApiServiceImpl(
private val context: Context,
private val serviceScope: CoroutineScope
) : IAsterismApiService.Stub() {
override fun getAsterismConsent(
cb: IAsterismCallbacks?,
request: GetAsterismConsentRequest?,
) {
Log.i(TAG, "getAsterismConsent(): $request")
if (cb == null || request == null) return
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
serviceScope.launch { handleGetAsterismConsent(context, cb, request) }
}

override fun setAsterismConsent(cb: IAsterismCallbacks?, request: SetAsterismConsentRequest?) {
Log.i(TAG, "setAsterismConsent(): $request")
if (cb == null || request == null) return
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
serviceScope.launch { handleSetAsterismConsent(context, cb, request) }
}

override fun getIsPnvrConstellationDevice(cb: IAsterismCallbacks?) {
Log.i(TAG, "getIsPnvrConstellationDevice()")
if (cb == null) return
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
serviceScope.launch { handleGetIsPnvrConstellationDevice(context, cb) }
}
}
Loading