diff --git a/matrix-sdk-android-flow/.gitignore b/matrix-sdk-android-flow/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/matrix-sdk-android-flow/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/matrix-sdk-android-flow/build.gradle b/matrix-sdk-android-flow/build.gradle
new file mode 100644
index 0000000000..4aecec169b
--- /dev/null
+++ b/matrix-sdk-android-flow/build.gradle
@@ -0,0 +1,49 @@
+
+plugins {
+ id 'com.android.library'
+ id 'org.jetbrains.kotlin.android'
+}
+
+android {
+ compileSdk 31
+
+ defaultConfig {
+ minSdk 21
+ targetSdk 31
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+
+ implementation project(":matrix-sdk-android")
+ implementation libs.androidx.appCompat
+
+ implementation libs.jetbrains.kotlinStdlibJdk7
+ implementation libs.jetbrains.coroutinesCore
+ implementation libs.jetbrains.coroutinesAndroid
+ implementation libs.androidx.lifecycleLivedata
+
+ // Paging
+ implementation libs.androidx.pagingRuntimeKtx
+
+ // Logging
+ implementation libs.jakewharton.timber
+
+}
\ No newline at end of file
diff --git a/matrix-sdk-android-flow/consumer-rules.pro b/matrix-sdk-android-flow/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/matrix-sdk-android-flow/proguard-rules.pro b/matrix-sdk-android-flow/proguard-rules.pro
new file mode 100644
index 0000000000..481bb43481
--- /dev/null
+++ b/matrix-sdk-android-flow/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/matrix-sdk-android-flow/src/androidTest/java/org/matrix/android/sdk/flow/ExampleInstrumentedTest.kt b/matrix-sdk-android-flow/src/androidTest/java/org/matrix/android/sdk/flow/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000000..41799955a4
--- /dev/null
+++ b/matrix-sdk-android-flow/src/androidTest/java/org/matrix/android/sdk/flow/ExampleInstrumentedTest.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.flow
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("org.matrix.android.sdk.flow.test", appContext.packageName)
+ }
+}
diff --git a/matrix-sdk-android-flow/src/main/AndroidManifest.xml b/matrix-sdk-android-flow/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..2392c0bfcb
--- /dev/null
+++ b/matrix-sdk-android-flow/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowRoom.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowRoom.kt
new file mode 100644
index 0000000000..a3e476ce08
--- /dev/null
+++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowRoom.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.flow
+
+import androidx.lifecycle.asFlow
+import kotlinx.coroutines.flow.Flow
+import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.session.events.model.Event
+import org.matrix.android.sdk.api.session.room.Room
+import org.matrix.android.sdk.api.session.room.members.RoomMemberQueryParams
+import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary
+import org.matrix.android.sdk.api.session.room.model.ReadReceipt
+import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
+import org.matrix.android.sdk.api.session.room.send.UserDraft
+import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
+import org.matrix.android.sdk.api.util.Optional
+
+class FlowRoom(private val room: Room) {
+
+ fun liveRoomSummary(): Flow> {
+ return room.getRoomSummaryLive().asFlow()
+ }
+
+ fun liveRoomMembers(queryParams: RoomMemberQueryParams): Flow> {
+ return room.getRoomMembersLive(queryParams).asFlow()
+ }
+
+ fun liveAnnotationSummary(eventId: String): Flow> {
+ return room.getEventAnnotationsSummaryLive(eventId).asFlow()
+ }
+
+ fun liveTimelineEvent(eventId: String): Flow> {
+ return room.getTimeLineEventLive(eventId).asFlow()
+ }
+
+ fun liveStateEvent(eventType: String, stateKey: QueryStringValue): Flow> {
+ return room.getStateEventLive(eventType, stateKey).asFlow()
+ }
+
+ fun liveStateEvents(eventTypes: Set): Flow> {
+ return room.getStateEventsLive(eventTypes).asFlow()
+ }
+
+ fun liveReadMarker(): Flow> {
+ return room.getReadMarkerLive().asFlow()
+ }
+
+ fun liveReadReceipt(): Flow> {
+ return room.getMyReadReceiptLive().asFlow()
+ }
+
+ fun liveEventReadReceipts(eventId: String): Flow> {
+ return room.getEventReadReceiptsLive(eventId).asFlow()
+ }
+
+ fun liveDraft(): Flow> {
+ return room.getDraftLive().asFlow()
+ }
+
+ fun liveNotificationState(): Flow {
+ return room.getLiveRoomNotificationState().asFlow()
+ }
+}
+
+fun Room.flow(): FlowRoom {
+ return FlowRoom(this)
+}
diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt
new file mode 100644
index 0000000000..affcd4a65d
--- /dev/null
+++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.flow
+
+import androidx.lifecycle.asFlow
+import androidx.paging.PagedList
+import kotlinx.coroutines.flow.Flow
+import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
+import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
+import org.matrix.android.sdk.api.session.group.GroupSummaryQueryParams
+import org.matrix.android.sdk.api.session.group.model.GroupSummary
+import org.matrix.android.sdk.api.session.identity.ThreePid
+import org.matrix.android.sdk.api.session.pushers.Pusher
+import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
+import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
+import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
+import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
+import org.matrix.android.sdk.api.session.sync.SyncState
+import org.matrix.android.sdk.api.session.user.model.User
+import org.matrix.android.sdk.api.session.widgets.model.Widget
+import org.matrix.android.sdk.api.util.Optional
+import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
+import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
+import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo
+
+class RxFlow(private val session: Session) {
+
+ fun liveRoomSummaries(queryParams: RoomSummaryQueryParams): Flow> {
+ return session.getRoomSummariesLive(queryParams).asFlow()
+ }
+
+ fun liveGroupSummaries(queryParams: GroupSummaryQueryParams): Flow> {
+ return session.getGroupSummariesLive(queryParams).asFlow()
+ }
+
+ fun liveSpaceSummaries(queryParams: SpaceSummaryQueryParams): Flow> {
+ return session.spaceService().getSpaceSummariesLive(queryParams).asFlow()
+ }
+
+ fun liveBreadcrumbs(queryParams: RoomSummaryQueryParams): Flow> {
+ return session.getBreadcrumbsLive(queryParams).asFlow()
+ }
+
+ fun liveMyDevicesInfo(): Flow> {
+ return session.cryptoService().getLiveMyDevicesInfo().asFlow()
+ }
+
+ fun liveSyncState(): Flow {
+ return session.getSyncStateLive().asFlow()
+ }
+
+ fun livePushers(): Flow> {
+ return session.getPushersLive().asFlow()
+ }
+
+ fun liveUser(userId: String): Flow> {
+ return session.getUserLive(userId).asFlow()
+ }
+
+ fun liveRoomMember(userId: String, roomId: String): Flow> {
+ return session.getRoomMemberLive(userId, roomId).asFlow()
+ }
+
+ fun liveUsers(): Flow> {
+ return session.getUsersLive().asFlow()
+ }
+
+ fun liveIgnoredUsers(): Flow> {
+ return session.getIgnoredUsersLive().asFlow()
+ }
+
+ fun livePagedUsers(filter: String? = null, excludedUserIds: Set? = null): Flow> {
+ return session.getPagedUsersLive(filter, excludedUserIds).asFlow()
+ }
+
+ fun liveThreePIds(refreshData: Boolean): Flow> {
+ return session.getThreePidsLive(refreshData).asFlow()
+ }
+
+ fun livePendingThreePIds(): Flow> {
+ return session.getPendingThreePidsLive().asFlow()
+ }
+
+ fun liveUserCryptoDevices(userId: String): Flow> {
+ return session.cryptoService().getLiveCryptoDeviceInfo(userId).asFlow()
+ }
+
+ fun liveCrossSigningInfo(userId: String): Flow> {
+ return session.cryptoService().crossSigningService().getLiveCrossSigningKeys(userId).asFlow()
+ }
+
+ fun liveCrossSigningPrivateKeys(): Flow> {
+ return session.cryptoService().crossSigningService().getLiveCrossSigningPrivateKeys().asFlow()
+ }
+
+ fun liveUserAccountData(types: Set): Flow> {
+ return session.accountDataService().getLiveUserAccountDataEvents(types).asFlow()
+ }
+
+ fun liveRoomAccountData(types: Set): Flow> {
+ return session.accountDataService().getLiveRoomAccountDataEvents(types).asFlow()
+ }
+
+ fun liveRoomWidgets(
+ roomId: String,
+ widgetId: QueryStringValue,
+ widgetTypes: Set? = null,
+ excludedTypes: Set? = null
+ ): Flow> {
+ return session.widgetService().getRoomWidgetsLive(roomId, widgetId, widgetTypes, excludedTypes).asFlow()
+ }
+
+ fun liveRoomChangeMembershipState(): Flow