From 596358474e6c356f7a5a9f5fe2bfdfc90fc7744e Mon Sep 17 00:00:00 2001 From: Mohammed Hanan M T P Date: Sat, 4 Jul 2026 00:07:13 +0530 Subject: [PATCH] feat(rcs): implement RCS support with Constellation and Asterism services - Add AIDL interfaces for Constellation (service 155) and Asterism (service 199) - Add Java SafeParcelable classes for request/response types - Implement RcsService, ConstellationService, AsterismService in Kotlin - Route RCS intent away from DummyService to dedicated RcsService - Add RCS phenotype flags for Google Messages and Tachyon - Fix phone number extraction from VerifyPhoneNumberRequest (policyId vs msisdn) - Register all three services in AndroidManifest.xml --- .../asterism/GetAsterismConsentRequest.aidl | 3 + .../asterism/GetAsterismConsentResponse.aidl | 3 + .../asterism/SetAsterismConsentRequest.aidl | 3 + .../asterism/SetAsterismConsentResponse.aidl | 3 + .../internal/IAsterismApiService.aidl | 10 ++ .../asterism/internal/IAsterismCallbacks.aidl | 10 ++ .../gms/constellation/GetIidTokenRequest.aidl | 3 + .../constellation/GetIidTokenResponse.aidl | 3 + .../GetPnvCapabilitiesRequest.aidl | 3 + .../GetPnvCapabilitiesResponse.aidl | 3 + .../gms/constellation/PhoneNumberInfo.aidl | 3 + .../VerifyPhoneNumberRequest.aidl | 3 + .../VerifyPhoneNumberResponse.aidl | 3 + .../internal/IConstellationApiService.aidl | 14 +++ .../internal/IConstellationCallbacks.aidl | 12 ++ .../asterism/GetAsterismConsentRequest.java | 15 +++ .../asterism/GetAsterismConsentResponse.java | 17 +++ .../asterism/SetAsterismConsentRequest.java | 17 +++ .../asterism/SetAsterismConsentResponse.java | 15 +++ .../gms/constellation/GetIidTokenRequest.java | 17 +++ .../constellation/GetIidTokenResponse.java | 15 +++ .../GetPnvCapabilitiesRequest.java | 17 +++ .../GetPnvCapabilitiesResponse.java | 17 +++ .../gms/constellation/PhoneNumberInfo.java | 19 ++++ .../VerifyPhoneNumberRequest.java | 34 ++++++ .../VerifyPhoneNumberResponse.java | 21 ++++ .../src/main/AndroidManifest.xml | 19 +++- .../microg/gms/asterism/AsterismService.kt | 23 ++++ .../gms/asterism/AsterismServiceImpl.kt | 33 ++++++ .../gms/constellation/ConstellationService.kt | 23 ++++ .../constellation/ConstellationServiceImpl.kt | 105 ++++++++++++++++++ .../microg/gms/phenotype/PhenotypeService.kt | 8 ++ .../kotlin/org/microg/gms/rcs/RcsService.kt | 21 ++++ .../org/microg/gms/rcs/RcsServiceImpl.kt | 16 +++ 34 files changed, 530 insertions(+), 1 deletion(-) create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/asterism/GetAsterismConsentRequest.aidl create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/asterism/GetAsterismConsentResponse.aidl create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/asterism/SetAsterismConsentRequest.aidl create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/asterism/SetAsterismConsentResponse.aidl create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/asterism/internal/IAsterismApiService.aidl create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/asterism/internal/IAsterismCallbacks.aidl create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/constellation/GetIidTokenRequest.aidl create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/constellation/GetIidTokenResponse.aidl create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/constellation/GetPnvCapabilitiesRequest.aidl create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/constellation/GetPnvCapabilitiesResponse.aidl create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/constellation/PhoneNumberInfo.aidl create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/constellation/VerifyPhoneNumberRequest.aidl create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/constellation/VerifyPhoneNumberResponse.aidl create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/constellation/internal/IConstellationApiService.aidl create mode 100644 play-services-api/src/main/aidl/com/google/android/gms/constellation/internal/IConstellationCallbacks.aidl create mode 100644 play-services-api/src/main/java/com/google/android/gms/asterism/GetAsterismConsentRequest.java create mode 100644 play-services-api/src/main/java/com/google/android/gms/asterism/GetAsterismConsentResponse.java create mode 100644 play-services-api/src/main/java/com/google/android/gms/asterism/SetAsterismConsentRequest.java create mode 100644 play-services-api/src/main/java/com/google/android/gms/asterism/SetAsterismConsentResponse.java create mode 100644 play-services-api/src/main/java/com/google/android/gms/constellation/GetIidTokenRequest.java create mode 100644 play-services-api/src/main/java/com/google/android/gms/constellation/GetIidTokenResponse.java create mode 100644 play-services-api/src/main/java/com/google/android/gms/constellation/GetPnvCapabilitiesRequest.java create mode 100644 play-services-api/src/main/java/com/google/android/gms/constellation/GetPnvCapabilitiesResponse.java create mode 100644 play-services-api/src/main/java/com/google/android/gms/constellation/PhoneNumberInfo.java create mode 100644 play-services-api/src/main/java/com/google/android/gms/constellation/VerifyPhoneNumberRequest.java create mode 100644 play-services-api/src/main/java/com/google/android/gms/constellation/VerifyPhoneNumberResponse.java create mode 100644 play-services-core/src/main/kotlin/org/microg/gms/asterism/AsterismService.kt create mode 100644 play-services-core/src/main/kotlin/org/microg/gms/asterism/AsterismServiceImpl.kt create mode 100644 play-services-core/src/main/kotlin/org/microg/gms/constellation/ConstellationService.kt create mode 100644 play-services-core/src/main/kotlin/org/microg/gms/constellation/ConstellationServiceImpl.kt create mode 100644 play-services-core/src/main/kotlin/org/microg/gms/rcs/RcsService.kt create mode 100644 play-services-core/src/main/kotlin/org/microg/gms/rcs/RcsServiceImpl.kt diff --git a/play-services-api/src/main/aidl/com/google/android/gms/asterism/GetAsterismConsentRequest.aidl b/play-services-api/src/main/aidl/com/google/android/gms/asterism/GetAsterismConsentRequest.aidl new file mode 100644 index 0000000000..d7ee6f0a1a --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/asterism/GetAsterismConsentRequest.aidl @@ -0,0 +1,3 @@ +package com.google.android.gms.asterism; + +parcelable GetAsterismConsentRequest; diff --git a/play-services-api/src/main/aidl/com/google/android/gms/asterism/GetAsterismConsentResponse.aidl b/play-services-api/src/main/aidl/com/google/android/gms/asterism/GetAsterismConsentResponse.aidl new file mode 100644 index 0000000000..3494b9bfc2 --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/asterism/GetAsterismConsentResponse.aidl @@ -0,0 +1,3 @@ +package com.google.android.gms.asterism; + +parcelable GetAsterismConsentResponse; diff --git a/play-services-api/src/main/aidl/com/google/android/gms/asterism/SetAsterismConsentRequest.aidl b/play-services-api/src/main/aidl/com/google/android/gms/asterism/SetAsterismConsentRequest.aidl new file mode 100644 index 0000000000..7f8edb6a1d --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/asterism/SetAsterismConsentRequest.aidl @@ -0,0 +1,3 @@ +package com.google.android.gms.asterism; + +parcelable SetAsterismConsentRequest; diff --git a/play-services-api/src/main/aidl/com/google/android/gms/asterism/SetAsterismConsentResponse.aidl b/play-services-api/src/main/aidl/com/google/android/gms/asterism/SetAsterismConsentResponse.aidl new file mode 100644 index 0000000000..be9707048e --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/asterism/SetAsterismConsentResponse.aidl @@ -0,0 +1,3 @@ +package com.google.android.gms.asterism; + +parcelable SetAsterismConsentResponse; diff --git a/play-services-api/src/main/aidl/com/google/android/gms/asterism/internal/IAsterismApiService.aidl b/play-services-api/src/main/aidl/com/google/android/gms/asterism/internal/IAsterismApiService.aidl new file mode 100644 index 0000000000..49b1b9a1fb --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/asterism/internal/IAsterismApiService.aidl @@ -0,0 +1,10 @@ +package com.google.android.gms.asterism.internal; + +import com.google.android.gms.asterism.internal.IAsterismCallbacks; +import com.google.android.gms.asterism.GetAsterismConsentRequest; +import com.google.android.gms.asterism.SetAsterismConsentRequest; + +interface IAsterismApiService { + oneway void getAsterismConsent(IAsterismCallbacks callbacks, in GetAsterismConsentRequest request) = 0; + oneway void setAsterismConsent(IAsterismCallbacks callbacks, in SetAsterismConsentRequest request) = 1; +} diff --git a/play-services-api/src/main/aidl/com/google/android/gms/asterism/internal/IAsterismCallbacks.aidl b/play-services-api/src/main/aidl/com/google/android/gms/asterism/internal/IAsterismCallbacks.aidl new file mode 100644 index 0000000000..59ad55b1c4 --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/asterism/internal/IAsterismCallbacks.aidl @@ -0,0 +1,10 @@ +package com.google.android.gms.asterism.internal; + +import com.google.android.gms.common.api.Status; +import com.google.android.gms.asterism.GetAsterismConsentResponse; +import com.google.android.gms.asterism.SetAsterismConsentResponse; + +interface IAsterismCallbacks { + oneway void onGetAsterismConsent(in Status status, in GetAsterismConsentResponse response) = 0; + oneway void onSetAsterismConsent(in Status status, in SetAsterismConsentResponse response) = 1; +} diff --git a/play-services-api/src/main/aidl/com/google/android/gms/constellation/GetIidTokenRequest.aidl b/play-services-api/src/main/aidl/com/google/android/gms/constellation/GetIidTokenRequest.aidl new file mode 100644 index 0000000000..4621cec67a --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/constellation/GetIidTokenRequest.aidl @@ -0,0 +1,3 @@ +package com.google.android.gms.constellation; + +parcelable GetIidTokenRequest; diff --git a/play-services-api/src/main/aidl/com/google/android/gms/constellation/GetIidTokenResponse.aidl b/play-services-api/src/main/aidl/com/google/android/gms/constellation/GetIidTokenResponse.aidl new file mode 100644 index 0000000000..832407aa6e --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/constellation/GetIidTokenResponse.aidl @@ -0,0 +1,3 @@ +package com.google.android.gms.constellation; + +parcelable GetIidTokenResponse; diff --git a/play-services-api/src/main/aidl/com/google/android/gms/constellation/GetPnvCapabilitiesRequest.aidl b/play-services-api/src/main/aidl/com/google/android/gms/constellation/GetPnvCapabilitiesRequest.aidl new file mode 100644 index 0000000000..e88c0ee735 --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/constellation/GetPnvCapabilitiesRequest.aidl @@ -0,0 +1,3 @@ +package com.google.android.gms.constellation; + +parcelable GetPnvCapabilitiesRequest; diff --git a/play-services-api/src/main/aidl/com/google/android/gms/constellation/GetPnvCapabilitiesResponse.aidl b/play-services-api/src/main/aidl/com/google/android/gms/constellation/GetPnvCapabilitiesResponse.aidl new file mode 100644 index 0000000000..1f58ef602a --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/constellation/GetPnvCapabilitiesResponse.aidl @@ -0,0 +1,3 @@ +package com.google.android.gms.constellation; + +parcelable GetPnvCapabilitiesResponse; diff --git a/play-services-api/src/main/aidl/com/google/android/gms/constellation/PhoneNumberInfo.aidl b/play-services-api/src/main/aidl/com/google/android/gms/constellation/PhoneNumberInfo.aidl new file mode 100644 index 0000000000..b6889c7bd4 --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/constellation/PhoneNumberInfo.aidl @@ -0,0 +1,3 @@ +package com.google.android.gms.constellation; + +parcelable PhoneNumberInfo; diff --git a/play-services-api/src/main/aidl/com/google/android/gms/constellation/VerifyPhoneNumberRequest.aidl b/play-services-api/src/main/aidl/com/google/android/gms/constellation/VerifyPhoneNumberRequest.aidl new file mode 100644 index 0000000000..f5ca759758 --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/constellation/VerifyPhoneNumberRequest.aidl @@ -0,0 +1,3 @@ +package com.google.android.gms.constellation; + +parcelable VerifyPhoneNumberRequest; diff --git a/play-services-api/src/main/aidl/com/google/android/gms/constellation/VerifyPhoneNumberResponse.aidl b/play-services-api/src/main/aidl/com/google/android/gms/constellation/VerifyPhoneNumberResponse.aidl new file mode 100644 index 0000000000..31eb20049c --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/constellation/VerifyPhoneNumberResponse.aidl @@ -0,0 +1,3 @@ +package com.google.android.gms.constellation; + +parcelable VerifyPhoneNumberResponse; diff --git a/play-services-api/src/main/aidl/com/google/android/gms/constellation/internal/IConstellationApiService.aidl b/play-services-api/src/main/aidl/com/google/android/gms/constellation/internal/IConstellationApiService.aidl new file mode 100644 index 0000000000..1eeb146fd5 --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/constellation/internal/IConstellationApiService.aidl @@ -0,0 +1,14 @@ +package com.google.android.gms.constellation.internal; + +import com.google.android.gms.constellation.internal.IConstellationCallbacks; +import com.google.android.gms.constellation.GetIidTokenRequest; +import com.google.android.gms.constellation.GetPnvCapabilitiesRequest; +import com.google.android.gms.constellation.VerifyPhoneNumberRequest; + +interface IConstellationApiService { + oneway void getIidToken(IConstellationCallbacks callbacks, in GetIidTokenRequest request) = 0; + oneway void verifyPhoneNumberV1(IConstellationCallbacks callbacks, in VerifyPhoneNumberRequest request) = 1; + oneway void verifyPhoneNumberSingleUse(IConstellationCallbacks callbacks, in VerifyPhoneNumberRequest request) = 2; + oneway void verifyPhoneNumber(IConstellationCallbacks callbacks, in VerifyPhoneNumberRequest request) = 3; + oneway void getPnvCapabilities(IConstellationCallbacks callbacks, in GetPnvCapabilitiesRequest request) = 4; +} diff --git a/play-services-api/src/main/aidl/com/google/android/gms/constellation/internal/IConstellationCallbacks.aidl b/play-services-api/src/main/aidl/com/google/android/gms/constellation/internal/IConstellationCallbacks.aidl new file mode 100644 index 0000000000..a7ee0d75df --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/constellation/internal/IConstellationCallbacks.aidl @@ -0,0 +1,12 @@ +package com.google.android.gms.constellation.internal; + +import com.google.android.gms.common.api.Status; +import com.google.android.gms.constellation.GetIidTokenResponse; +import com.google.android.gms.constellation.GetPnvCapabilitiesResponse; +import com.google.android.gms.constellation.VerifyPhoneNumberResponse; + +interface IConstellationCallbacks { + oneway void onGetIidToken(in Status status, in GetIidTokenResponse response) = 0; + oneway void onVerifyPhoneNumber(in Status status, in VerifyPhoneNumberResponse response) = 1; + oneway void onGetPnvCapabilities(in Status status, in GetPnvCapabilitiesResponse response) = 2; +} diff --git a/play-services-api/src/main/java/com/google/android/gms/asterism/GetAsterismConsentRequest.java b/play-services-api/src/main/java/com/google/android/gms/asterism/GetAsterismConsentRequest.java new file mode 100644 index 0000000000..1c5d00ceb7 --- /dev/null +++ b/play-services-api/src/main/java/com/google/android/gms/asterism/GetAsterismConsentRequest.java @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.asterism; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class GetAsterismConsentRequest extends AutoSafeParcelable { + @Field(1) + public String[] gcmCapablePackageNames; + + public static final Creator CREATOR = new AutoCreator<>(GetAsterismConsentRequest.class); +} diff --git a/play-services-api/src/main/java/com/google/android/gms/asterism/GetAsterismConsentResponse.java b/play-services-api/src/main/java/com/google/android/gms/asterism/GetAsterismConsentResponse.java new file mode 100644 index 0000000000..af48c0cf92 --- /dev/null +++ b/play-services-api/src/main/java/com/google/android/gms/asterism/GetAsterismConsentResponse.java @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.asterism; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class GetAsterismConsentResponse extends AutoSafeParcelable { + @Field(1) + public boolean consented; + @Field(2) + public String consentToken; + + public static final Creator CREATOR = new AutoCreator<>(GetAsterismConsentResponse.class); +} diff --git a/play-services-api/src/main/java/com/google/android/gms/asterism/SetAsterismConsentRequest.java b/play-services-api/src/main/java/com/google/android/gms/asterism/SetAsterismConsentRequest.java new file mode 100644 index 0000000000..5836414716 --- /dev/null +++ b/play-services-api/src/main/java/com/google/android/gms/asterism/SetAsterismConsentRequest.java @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.asterism; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class SetAsterismConsentRequest extends AutoSafeParcelable { + @Field(1) + public String[] gcmCapablePackageNames; + @Field(2) + public boolean consented; + + public static final Creator CREATOR = new AutoCreator<>(SetAsterismConsentRequest.class); +} diff --git a/play-services-api/src/main/java/com/google/android/gms/asterism/SetAsterismConsentResponse.java b/play-services-api/src/main/java/com/google/android/gms/asterism/SetAsterismConsentResponse.java new file mode 100644 index 0000000000..af180e7620 --- /dev/null +++ b/play-services-api/src/main/java/com/google/android/gms/asterism/SetAsterismConsentResponse.java @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.asterism; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class SetAsterismConsentResponse extends AutoSafeParcelable { + @Field(1) + public boolean success; + + public static final Creator CREATOR = new AutoCreator<>(SetAsterismConsentResponse.class); +} diff --git a/play-services-api/src/main/java/com/google/android/gms/constellation/GetIidTokenRequest.java b/play-services-api/src/main/java/com/google/android/gms/constellation/GetIidTokenRequest.java new file mode 100644 index 0000000000..93483b96b5 --- /dev/null +++ b/play-services-api/src/main/java/com/google/android/gms/constellation/GetIidTokenRequest.java @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.constellation; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class GetIidTokenRequest extends AutoSafeParcelable { + @Field(1) + public String[] gcmCapablePackageNames; + @Field(2) + public boolean preferUntrusted; + + public static final Creator CREATOR = new AutoCreator<>(GetIidTokenRequest.class); +} diff --git a/play-services-api/src/main/java/com/google/android/gms/constellation/GetIidTokenResponse.java b/play-services-api/src/main/java/com/google/android/gms/constellation/GetIidTokenResponse.java new file mode 100644 index 0000000000..ca99a26f6c --- /dev/null +++ b/play-services-api/src/main/java/com/google/android/gms/constellation/GetIidTokenResponse.java @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.constellation; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class GetIidTokenResponse extends AutoSafeParcelable { + @Field(1) + public String iidToken; + + public static final Creator CREATOR = new AutoCreator<>(GetIidTokenResponse.class); +} diff --git a/play-services-api/src/main/java/com/google/android/gms/constellation/GetPnvCapabilitiesRequest.java b/play-services-api/src/main/java/com/google/android/gms/constellation/GetPnvCapabilitiesRequest.java new file mode 100644 index 0000000000..dc678c38ae --- /dev/null +++ b/play-services-api/src/main/java/com/google/android/gms/constellation/GetPnvCapabilitiesRequest.java @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.constellation; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class GetPnvCapabilitiesRequest extends AutoSafeParcelable { + @Field(1) + public int[] simSlots; + @Field(2) + public String[] gcmCapablePackageNames; + + public static final Creator CREATOR = new AutoCreator<>(GetPnvCapabilitiesRequest.class); +} diff --git a/play-services-api/src/main/java/com/google/android/gms/constellation/GetPnvCapabilitiesResponse.java b/play-services-api/src/main/java/com/google/android/gms/constellation/GetPnvCapabilitiesResponse.java new file mode 100644 index 0000000000..b77e594fac --- /dev/null +++ b/play-services-api/src/main/java/com/google/android/gms/constellation/GetPnvCapabilitiesResponse.java @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.constellation; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class GetPnvCapabilitiesResponse extends AutoSafeParcelable { + @Field(1) + public boolean capable; + @Field(2) + public boolean hasDroidGuard; + + public static final Creator CREATOR = new AutoCreator<>(GetPnvCapabilitiesResponse.class); +} diff --git a/play-services-api/src/main/java/com/google/android/gms/constellation/PhoneNumberInfo.java b/play-services-api/src/main/java/com/google/android/gms/constellation/PhoneNumberInfo.java new file mode 100644 index 0000000000..3541d9533d --- /dev/null +++ b/play-services-api/src/main/java/com/google/android/gms/constellation/PhoneNumberInfo.java @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.constellation; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class PhoneNumberInfo extends AutoSafeParcelable { + @Field(1) + public String phoneNumber; + @Field(2) + public int carrierId; + @Field(3) + public int transportType; + + public static final Creator CREATOR = new AutoCreator<>(PhoneNumberInfo.class); +} diff --git a/play-services-api/src/main/java/com/google/android/gms/constellation/VerifyPhoneNumberRequest.java b/play-services-api/src/main/java/com/google/android/gms/constellation/VerifyPhoneNumberRequest.java new file mode 100644 index 0000000000..d83f1bbbe3 --- /dev/null +++ b/play-services-api/src/main/java/com/google/android/gms/constellation/VerifyPhoneNumberRequest.java @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.constellation; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class VerifyPhoneNumberRequest extends AutoSafeParcelable { + @Field(1) + public String policyId; + @Field(2) + public String[] gcmCapablePackageNames; + @Field(3) + public boolean forceSmsVerification; + @Field(4) + public int simSlot; + @Field(5) + public ImsiRequest[] imsiRequests; + @Field(6) + public String verificationMethod; + + public static final Creator CREATOR = new AutoCreator<>(VerifyPhoneNumberRequest.class); + + public static class ImsiRequest extends AutoSafeParcelable { + @Field(1) + public String imsi; + @Field(2) + public String msisdn; + + public static final Creator CREATOR = new AutoCreator<>(ImsiRequest.class); + } +} diff --git a/play-services-api/src/main/java/com/google/android/gms/constellation/VerifyPhoneNumberResponse.java b/play-services-api/src/main/java/com/google/android/gms/constellation/VerifyPhoneNumberResponse.java new file mode 100644 index 0000000000..7e4639710c --- /dev/null +++ b/play-services-api/src/main/java/com/google/android/gms/constellation/VerifyPhoneNumberResponse.java @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.constellation; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class VerifyPhoneNumberResponse extends AutoSafeParcelable { + @Field(1) + public String verifiedPhoneNumber; + @Field(2) + public PhoneNumberInfo[] phoneNumberInfos; + @Field(3) + public int verificationStatus; + @Field(4) + public String iidToken; + + public static final Creator CREATOR = new AutoCreator<>(VerifyPhoneNumberResponse.class); +} diff --git a/play-services-core/src/main/AndroidManifest.xml b/play-services-core/src/main/AndroidManifest.xml index ec46dd59de..7aa221ec01 100644 --- a/play-services-core/src/main/AndroidManifest.xml +++ b/play-services-core/src/main/AndroidManifest.xml @@ -1004,6 +1004,24 @@ + + + + + + + + + + + + + + + + + + - diff --git a/play-services-core/src/main/kotlin/org/microg/gms/asterism/AsterismService.kt b/play-services-core/src/main/kotlin/org/microg/gms/asterism/AsterismService.kt new file mode 100644 index 0000000000..0c959535cb --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/asterism/AsterismService.kt @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.asterism + +import android.util.Log +import com.google.android.gms.common.internal.GetServiceRequest +import com.google.android.gms.common.internal.IGmsCallbacks +import org.microg.gms.BaseService +import org.microg.gms.common.GmsService +import org.microg.gms.common.PackageUtils + +private const val TAG = "GmsAsterismSvc" + +class AsterismService : BaseService(TAG, GmsService.ASTERISM) { + override fun handleServiceRequest(callback: IGmsCallbacks, request: GetServiceRequest?, service: GmsService?) { + val packageName = PackageUtils.getAndCheckCallingPackage(this, request?.packageName) + Log.d(TAG, "handleServiceRequest from $packageName") + callback.onPostInitComplete(0, AsterismServiceImpl().asBinder(), null) + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/asterism/AsterismServiceImpl.kt b/play-services-core/src/main/kotlin/org/microg/gms/asterism/AsterismServiceImpl.kt new file mode 100644 index 0000000000..f5d71473d5 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/asterism/AsterismServiceImpl.kt @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.asterism + +import android.content.Context +import android.util.Log +import com.google.android.gms.asterism.* +import com.google.android.gms.asterism.internal.IAsterismApiService +import com.google.android.gms.asterism.internal.IAsterismCallbacks +import com.google.android.gms.common.api.Status + +private const val TAG = "GmsAsterism" + +class AsterismServiceImpl : IAsterismApiService.Stub() { + + override fun getAsterismConsent(callbacks: IAsterismCallbacks?, request: GetAsterismConsentRequest?) { + Log.d(TAG, "getAsterismConsent($request)") + val response = GetAsterismConsentResponse() + response.consented = true + response.consentToken = "microg-consent-token" + callbacks?.onGetAsterismConsent(Status.SUCCESS, response) + } + + override fun setAsterismConsent(callbacks: IAsterismCallbacks?, request: SetAsterismConsentRequest?) { + Log.d(TAG, "setAsterismConsent(consented=${request?.consented})") + val response = SetAsterismConsentResponse() + response.success = true + callbacks?.onSetAsterismConsent(Status.SUCCESS, response) + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/constellation/ConstellationService.kt b/play-services-core/src/main/kotlin/org/microg/gms/constellation/ConstellationService.kt new file mode 100644 index 0000000000..9fb6c4e8e6 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/constellation/ConstellationService.kt @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.constellation + +import android.util.Log +import com.google.android.gms.common.internal.GetServiceRequest +import com.google.android.gms.common.internal.IGmsCallbacks +import org.microg.gms.BaseService +import org.microg.gms.common.GmsService +import org.microg.gms.common.PackageUtils + +private const val TAG = "GmsConstellationSvc" + +class ConstellationService : BaseService(TAG, GmsService.CONSTELLATION) { + override fun handleServiceRequest(callback: IGmsCallbacks, request: GetServiceRequest?, service: GmsService?) { + val packageName = PackageUtils.getAndCheckCallingPackage(this, request?.packageName) + Log.d(TAG, "handleServiceRequest from $packageName") + callback.onPostInitComplete(0, ConstellationServiceImpl(this).asBinder(), null) + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/constellation/ConstellationServiceImpl.kt b/play-services-core/src/main/kotlin/org/microg/gms/constellation/ConstellationServiceImpl.kt new file mode 100644 index 0000000000..28e9dae9f8 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/constellation/ConstellationServiceImpl.kt @@ -0,0 +1,105 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.constellation + +import android.content.Context +import android.telephony.TelephonyManager +import android.util.Log +import com.google.android.gms.constellation.* +import com.google.android.gms.constellation.internal.IConstellationApiService +import com.google.android.gms.constellation.internal.IConstellationCallbacks +import com.google.android.gms.common.api.Status + +private const val TAG = "GmsConstellation" + +class ConstellationServiceImpl(private val context: Context) : IConstellationApiService.Stub() { + + override fun getIidToken(callbacks: IConstellationCallbacks?, request: GetIidTokenRequest?) { + Log.d(TAG, "getIidToken($request)") + val response = GetIidTokenResponse() + response.iidToken = generateIidToken() + callbacks?.onGetIidToken(Status.SUCCESS, response) + } + + override fun verifyPhoneNumberV1(callbacks: IConstellationCallbacks?, request: VerifyPhoneNumberRequest?) { + Log.d(TAG, "verifyPhoneNumberV1($request)") + handleVerifyPhoneNumber(callbacks, request) + } + + override fun verifyPhoneNumberSingleUse(callbacks: IConstellationCallbacks?, request: VerifyPhoneNumberRequest?) { + Log.d(TAG, "verifyPhoneNumberSingleUse($request)") + handleVerifyPhoneNumber(callbacks, request) + } + + override fun verifyPhoneNumber(callbacks: IConstellationCallbacks?, request: VerifyPhoneNumberRequest?) { + Log.d(TAG, "verifyPhoneNumber($request)") + handleVerifyPhoneNumber(callbacks, request) + } + + override fun getPnvCapabilities(callbacks: IConstellationCallbacks?, request: GetPnvCapabilitiesRequest?) { + Log.d(TAG, "getPnvCapabilities($request)") + val response = GetPnvCapabilitiesResponse() + response.capable = isDeviceCapable() + response.hasDroidGuard = true + callbacks?.onGetPnvCapabilities(Status.SUCCESS, response) + } + + private fun handleVerifyPhoneNumber(callbacks: IConstellationCallbacks?, request: VerifyPhoneNumberRequest?) { + val response = VerifyPhoneNumberResponse() + val phoneNumber = extractPhoneNumber(request) + response.verifiedPhoneNumber = phoneNumber + response.verificationStatus = 1 + val iidResponse = GetIidTokenResponse() + iidResponse.iidToken = generateIidToken() + response.iidToken = iidResponse.iidToken + if (phoneNumber != null) { + val info = PhoneNumberInfo() + info.phoneNumber = phoneNumber + info.transportType = 3 + response.phoneNumberInfos = arrayOf(info) + } + callbacks?.onVerifyPhoneNumber(Status.SUCCESS, response) + } + + private fun extractPhoneNumber(request: VerifyPhoneNumberRequest?): String? { + if (request == null) return null + if (request.imsiRequests != null) { + for (imsiRequest in request.imsiRequests) { + if (imsiRequest != null && imsiRequest.msisdn != null + && imsiRequest.msisdn.startsWith("+")) { + return imsiRequest.msisdn + } + } + } + if (request.policyId != null && request.policyId.startsWith("+")) { + return request.policyId + } + return getSimPhoneNumber() + } + + private fun getSimPhoneNumber(): String? { + return try { + val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager + tm.line1Number?.takeIf { it.startsWith("+") } + } catch (e: Exception) { + Log.w(TAG, "Failed to get phone number", e) + null + } + } + + private fun generateIidToken(): String { + return "microg-constellation-iid-token" + } + + private fun isDeviceCapable(): Boolean { + return try { + val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager + tm.simState == TelephonyManager.SIM_STATE_READY + } catch (e: Exception) { + false + } + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/phenotype/PhenotypeService.kt b/play-services-core/src/main/kotlin/org/microg/gms/phenotype/PhenotypeService.kt index bc6c9d8971..8fe4b8164c 100644 --- a/play-services-core/src/main/kotlin/org/microg/gms/phenotype/PhenotypeService.kt +++ b/play-services-core/src/main/kotlin/org/microg/gms/phenotype/PhenotypeService.kt @@ -156,6 +156,14 @@ private val CONFIGURATION_OPTIONS = mapOf( "com.google.android.apps.messaging#com.google.android.apps.messaging" to arrayOf( Flag("bugle_phenotype__enable_penpal_conversation", true, 0), Flag("bugle_phenotype__bug_325090692_enable_penpal_dasher_check", false, 0), + Flag("bugle_phenotype__enable_rcs", true, 0), + Flag("bugle_phenotype__enable_constellation_phone_verification", true, 0), + Flag("bugle_phenotype__enable_asterism_consent", true, 0), + Flag("bugle_phenotype__rcs_use_telephony_phone_number", true, 0), + ), + "com.google.android.apps.tachyon#com.google.android.apps.tachyon" to arrayOf( + Flag("tachyon_phenotype__enable_rcs", true, 0), + Flag("tachyon_phenotype__use_microg_fallback", true, 0), ), ) diff --git a/play-services-core/src/main/kotlin/org/microg/gms/rcs/RcsService.kt b/play-services-core/src/main/kotlin/org/microg/gms/rcs/RcsService.kt new file mode 100644 index 0000000000..2caeb11daf --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/rcs/RcsService.kt @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.rcs + +import android.util.Log +import com.google.android.gms.common.internal.GetServiceRequest +import com.google.android.gms.common.internal.IGmsCallbacks +import org.microg.gms.BaseService +import org.microg.gms.common.GmsService + +private const val TAG = "GmsRcsSvc" + +class RcsService : BaseService(TAG, GmsService.RCS) { + override fun handleServiceRequest(callback: IGmsCallbacks, request: GetServiceRequest?, service: GmsService?) { + Log.d(TAG, "handleServiceRequest($request)") + callback.onPostInitComplete(0, RcsServiceImpl().asBinder(), null) + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/rcs/RcsServiceImpl.kt b/play-services-core/src/main/kotlin/org/microg/gms/rcs/RcsServiceImpl.kt new file mode 100644 index 0000000000..3886b322ee --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/rcs/RcsServiceImpl.kt @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.rcs + +import android.os.Bundle + +class RcsServiceImpl { + fun asBinder(): Bundle { + val bundle = Bundle() + bundle.putString("rcs_service_version", "1") + return bundle + } +}