Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions play-services-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ dependencies {
implementation project(':play-services-droidguard-core')
implementation project(':play-services-fido-core')
implementation project(':play-services-fitness-core')
implementation project(':play-services-rcs')
implementation project(':play-services-gmscompliance-core')
implementation project(':play-services-location-core')
implementation project(':play-services-location-core-base')
Expand Down
27 changes: 27 additions & 0 deletions play-services-core/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,33 @@
tools:ignore="WearableBindListener" />
</intent-filter>
</service>

<!-- RCS Engine Lifecycle Service V2 -->
<service
android:name="org.microg.gms.rcs.RcsEngineLifecycleServiceV2"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.rcs.START" />
<action android:name="com.google.android.gms.rcs.engine.BIND" />
<action android:name="com.google.android.gms.rcs.engine.START" />
<action android:name="com.google.android.ims.rcs.engine.IRcsEngineController" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="RcsEngineLifecycleServiceVersions"
android:value="2" />
</service>

<!-- RCS Status Broadcaster -->
<receiver android:name="org.microg.gms.rcs.RcsStatusBroadcaster"
android:exported="true">
<intent-filter android:priority="999">
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* SPDX-FileCopyrightText: 2024 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/

package org.microg.gms.rcs;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Binder;
import android.os.IBinder;

import com.google.android.ims.rcs.engine.IRcsEngineController;
import com.google.android.ims.rcs.engine.RcsEngineLifecycleServiceResult;
import com.google.android.ims.rcsservice.lifecycle.InitializeAndStartRcsTransportRequest;
import com.google.android.ims.rcsservice.lifecycle.StopAllRcsTransportsExceptRequest;

public class RcsEngineLifecycleServiceV2 extends Service {

private StateChangeReceiver stateChangeReceiver;

@Override
public void onCreate() {
super.onCreate();
stateChangeReceiver = new StateChangeReceiver();
IntentFilter filter = new IntentFilter("com.google.android.gms.rcs.engine.STATE_CHANGED");
registerReceiver(stateChangeReceiver, filter);
broadcastRcsAvailable();
}

@Override
public IBinder onBind(Intent intent) {
broadcastRcsAvailable();
return new RcsEngineControllerImpl();
}

private class StateChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if ("com.google.android.gms.rcs.engine.STATE_CHANGED".equals(intent.getAction())) {
broadcastRcsAvailable();
}
}
}

private class RcsEngineControllerImpl extends IRcsEngineController.Stub {

@Override
public RcsEngineLifecycleServiceResult initialize(int subId, int flags) {
broadcastRcsAvailable();
return new RcsEngineLifecycleServiceResult(RcsEngineLifecycleServiceResult.SUCCESS);
}

@Override
public RcsEngineLifecycleServiceResult destroy(int subId) {
return new RcsEngineLifecycleServiceResult(RcsEngineLifecycleServiceResult.SUCCESS);
}

@Override
public RcsEngineLifecycleServiceResult triggerStartRcsStack(int subId) {
return new RcsEngineLifecycleServiceResult(RcsEngineLifecycleServiceResult.SUCCESS);
}

@Override
public RcsEngineLifecycleServiceResult triggerStopRcsStack(int subId) {
return new RcsEngineLifecycleServiceResult(RcsEngineLifecycleServiceResult.SUCCESS);
}

@Override
public RcsEngineLifecycleServiceResult initializeAndStartRcsTransport(
InitializeAndStartRcsTransportRequest request) {
return new RcsEngineLifecycleServiceResult(RcsEngineLifecycleServiceResult.SUCCESS);
}

@Override
public RcsEngineLifecycleServiceResult stopAllRcsTransportsExcept(
StopAllRcsTransportsExceptRequest request) {
return new RcsEngineLifecycleServiceResult(RcsEngineLifecycleServiceResult.SUCCESS);
}
}

@Override
public void onDestroy() {
super.onDestroy();
if (stateChangeReceiver != null) {
unregisterReceiver(stateChangeReceiver);
stateChangeReceiver = null;
}
}

private void broadcastRcsAvailable() {
sendRcsIntent("com.google.android.gms.rcs.action.REGISTRATION_STATE_CHANGED");
sendRcsIntent("com.google.android.gms.rcs.action.CAPABILITY_UPDATE");
sendRcsIntent("com.google.android.gms.rcs.action.PROVISIONING_COMPLETE");
}

private void sendRcsIntent(String action) {
Intent intent = new Intent(action);
intent.putExtra("timestamp", System.currentTimeMillis());
intent.putExtra("hasToken", true);
intent.putExtra("isValidAndUpdated", true);
if ("com.google.android.gms.rcs.action.REGISTRATION_STATE_CHANGED".equals(action)) {
intent.putExtra("state", 7);
}
sendBroadcast(intent);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* SPDX-FileCopyrightText: 2024 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/

package org.microg.gms.rcs;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class RcsStatusBroadcaster extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
sendRcsIntent(context, "com.google.android.gms.rcs.action.REGISTRATION_STATE_CHANGED");
sendRcsIntent(context, "com.google.android.gms.rcs.action.CAPABILITY_UPDATE");
sendRcsIntent(context, "com.google.android.gms.rcs.action.PROVISIONING_COMPLETE");
}

private void sendRcsIntent(Context context, String action) {
Intent rcsIntent = new Intent(action);
rcsIntent.putExtra("timestamp", System.currentTimeMillis());
rcsIntent.putExtra("hasToken", true);
rcsIntent.putExtra("isValidAndUpdated", true);
if ("com.google.android.gms.rcs.action.REGISTRATION_STATE_CHANGED".equals(action)) {
rcsIntent.putExtra("state", 7);
}
context.sendBroadcast(rcsIntent);
}
}
41 changes: 41 additions & 0 deletions play-services-rcs/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2024 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/

apply plugin: 'com.android.application'

android {
namespace "org.microg.gms.rcs.standalone"

compileSdkVersion androidCompileSdk
buildToolsVersion "$androidBuildVersionTools"

defaultConfig {
applicationId "com.google.android.gms.rcs"
versionName "1.0"
versionCode 1
minSdkVersion androidMinSdk
targetSdkVersion androidTargetSdk
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java']
aidl.srcDirs = ['src/main/aidl']
res.srcDirs = ['src/main/res']
}
}
}

dependencies {
implementation project(':play-services-base')
implementation project(':play-services-basement')
implementation project(':play-services-auth-base')
}
53 changes: 53 additions & 0 deletions play-services-rcs/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application>

<!-- RCS Engine Lifecycle Service V2 - Main Service -->
<service
android:name=".RcsEngineLifecycleServiceV2"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.rcs.START" />
<action android:name="com.google.android.gms.rcs.engine.BIND" />
<action android:name="com.google.android.gms.rcs.engine.START" />
<action android:name="com.google.android.ims.rcs.engine.IRcsEngineController" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="RcsEngineLifecycleServiceVersions"
android:value="2" />
</service>

<!-- RCS Capability Provider -->
<provider
android:name=".provider.RcsCapabilityProvider"
android:authorities="com.google.android.gms.rcs.provider"
android:exported="true"
android:permission="com.google.android.gms.permission.INTERNAL_BROADCAST" />

<!-- RCS Contacts Service -->
<service
android:name=".contacts.RcsContactsService"
android:exported="true"
android:permission="com.google.android.gms.permission.INTERNAL_BROADCAST">
<intent-filter>
<action android:name="com.google.android.gms.rcs.contacts.BIND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>

<!-- RCS Status Broadcaster -->
<receiver android:name=".RcsStatusBroadcaster"
android:exported="true">
<intent-filter android:priority="999">
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" />
</intent-filter>
</receiver>

</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* SPDX-FileCopyrightText: 2024 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/

package com.google.android.ims.rcs.engine;

import com.google.android.ims.rcs.engine.RcsEngineLifecycleServiceResult;
import com.google.android.ims.rcsservice.lifecycle.InitializeAndStartRcsTransportRequest;
import com.google.android.ims.rcsservice.lifecycle.StopAllRcsTransportsExceptRequest;

interface IRcsEngineController {
RcsEngineLifecycleServiceResult initialize(int subId, int flags);
RcsEngineLifecycleServiceResult destroy(int subId);
RcsEngineLifecycleServiceResult triggerStartRcsStack(int subId);
RcsEngineLifecycleServiceResult triggerStopRcsStack(int subId);
RcsEngineLifecycleServiceResult initializeAndStartRcsTransport(in InitializeAndStartRcsTransportRequest request);
RcsEngineLifecycleServiceResult stopAllRcsTransportsExcept(in StopAllRcsTransportsExceptRequest request);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2024 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/

package com.google.android.ims.rcs.engine;

parcelable RcsEngineLifecycleServiceResult;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: 2024 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/

package com.google.android.ims.rcsservice.contacts;

parcelable ContactsServiceResult {
int code;
String description;

// Success/error codes
const int SUCCESS = 0;
const int ERROR_UNKNOWN = 1;
const int ERROR_INVALID_DESTINATION = 11;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* SPDX-FileCopyrightText: 2024 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/

package com.google.android.ims.rcsservice.contacts;

import com.google.android.ims.rcsservice.contacts.ContactsServiceResult;
import com.google.android.ims.rcsservice.contacts.ImsCapabilities;

interface IContactsManagement {
ContactsServiceResult forceRefreshCapabilities(String phoneNumber);
ImsCapabilities getCachedCapabilities(String phoneNumber);
ContactsServiceResult refreshCapabilities(String phoneNumber);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2024 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/

package com.google.android.ims.rcsservice.contacts;

parcelable ImsCapabilities {
// Base dutk fields - following Google's exact pattern from reverse-engineered code
boolean isOnline;
boolean isKnownInNetwork;
long lastActivityTimestamp;
int responseCode;
long validityPeriodMillis;
Map<String, String> capabilityMetadata;
List<String> capabilityList;
String rbmBotStatus;

// ImsCapabilities specific fields
long timestamp;
List<String> supportedServiceIdList;
boolean rcsCapable;

// Service IDs for different RCS features
const int SERVICE_ID_CHAT = 1;
const int SERVICE_ID_FILE_TRANSFER = 2;
const int SERVICE_ID_GROUP_CHAT = 3;
const int SERVICE_ID_LOCATION_SHARING = 4;
const int SERVICE_ID_VIDEO_SHARING = 5;
const int SERVICE_ID_VOICE_MESSAGING = 6;
const int SERVICE_ID_SMS_FALLBACK = 7;
const int SERVICE_ID_MMS_FALLBACK = 8;
const int SERVICE_ID_TYPING_INDICATORS = 9;
const int SERVICE_ID_MESSAGE_REVOCATION = 10;
const int SERVICE_ID_MESSAGE_EDITING = 11;
const int SERVICE_ID_REACTIONS = 12;
const int SERVICE_ID_E2EE = 13;
const int SERVICE_ID_GROUP_E2EE = 14;
const int SERVICE_ID_TACHYGRAM = 15;
const int SERVICE_ID_VIDEO_CODEC = 16;
const int SERVICE_ID_IMAGE_CAPTIONS = 17;
const int SERVICE_ID_PROFILE_SHARING = 18;
const int SERVICE_ID_BOT_SUPPORT = 19;
const int SERVICE_ID_GEOPUSH = 20;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2024 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/

package com.google.android.ims.rcsservice.lifecycle;

parcelable InitializeAndStartRcsTransportRequest;
Loading